Compare commits
18 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
b994dafe7a | ||
|
54421760c3 | ||
|
88a0e720cb | ||
|
53cc9e0561 | ||
|
7defc59b9d | ||
|
951700fdd8 | ||
|
eb6430f103 | ||
|
80a879cb44 | ||
|
2197f41506 | ||
|
c8f9292bab | ||
|
0ec933a615 | ||
|
2135b6a51a | ||
|
00e35d9bf6 | ||
|
6dfb6ccf8c | ||
|
e87e8b012c | ||
|
e8f1ca8427 | ||
|
ad47bd2d4e | ||
|
a5ff0024fb |
@@ -58,7 +58,6 @@ namespace ARMeilleure.CodeGen.Linking
|
||||
/// <param name="a">First instance</param>
|
||||
/// <param name="b">Second instance</param>
|
||||
/// <returns><see langword="true"/> if not equal; otherwise <see langword="false"/></returns>
|
||||
/// <inheritdoc/>
|
||||
public static bool operator !=(Symbol a, Symbol b)
|
||||
{
|
||||
return !(a == b);
|
||||
|
@@ -1,6 +1,4 @@
|
||||
using ARMeilleure.Common;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using System;
|
||||
|
||||
namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
{
|
||||
|
@@ -4,6 +4,11 @@ namespace ARMeilleure.CodeGen.X86
|
||||
{
|
||||
partial class Assembler
|
||||
{
|
||||
public static bool SupportsVexPrefix(X86Instruction inst)
|
||||
{
|
||||
return _instTable[(int)inst].Flags.HasFlag(InstructionFlags.Vex);
|
||||
}
|
||||
|
||||
private const int BadOp = 0;
|
||||
|
||||
[Flags]
|
||||
|
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ARMeilleure.CodeGen.X86
|
||||
{
|
||||
|
@@ -1297,11 +1297,15 @@ namespace ARMeilleure.CodeGen.X86
|
||||
{
|
||||
if (IsIntrinsic(operation.Instruction))
|
||||
{
|
||||
IntrinsicInfo info = IntrinsicTable.GetInfo(operation.Intrinsic);
|
||||
|
||||
bool hasVex = HardwareCapabilities.SupportsVexEncoding && Assembler.SupportsVexPrefix(info.Inst);
|
||||
|
||||
bool isUnary = operation.SourcesCount < 2;
|
||||
|
||||
bool hasVecDest = operation.Destination != default && operation.Destination.Type == OperandType.V128;
|
||||
|
||||
return !HardwareCapabilities.SupportsVexEncoding && !isUnary && hasVecDest;
|
||||
return !hasVex && !isUnary && hasVecDest;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@@ -206,7 +206,7 @@ namespace ARMeilleure.Common
|
||||
/// <typeparam name="T">Type of elements</typeparam>
|
||||
/// <param name="length">Number of elements</param>
|
||||
/// <param name="fill">Fill value</param>
|
||||
/// <param name="leaf"><see langword="true"/> if leaf; otherwise <see langword=""="false"/></param>
|
||||
/// <param name="leaf"><see langword="true"/> if leaf; otherwise <see langword="false"/></param>
|
||||
/// <returns>Allocated block</returns>
|
||||
private IntPtr Allocate<T>(int length, T fill, bool leaf) where T : unmanaged
|
||||
{
|
||||
|
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace ARMeilleure.Common
|
||||
{
|
||||
|
@@ -9,6 +9,9 @@ namespace ARMeilleure.Common
|
||||
class Counter<T> : IDisposable where T : unmanaged
|
||||
{
|
||||
private bool _disposed;
|
||||
/// <summary>
|
||||
/// Index in the <see cref="EntryTable{T}"/>
|
||||
/// </summary>
|
||||
private readonly int _index;
|
||||
private readonly EntryTable<T> _countTable;
|
||||
|
||||
@@ -17,7 +20,6 @@ namespace ARMeilleure.Common
|
||||
/// <see cref="EntryTable{T}"/> instance and index.
|
||||
/// </summary>
|
||||
/// <param name="countTable"><see cref="EntryTable{T}"/> instance</param>
|
||||
/// <param name="index">Index in the <see cref="EntryTable{T}"/></param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="countTable"/> is <see langword="null"/></exception>
|
||||
/// <exception cref="ArgumentException"><typeparamref name="T"/> is unsupported</exception>
|
||||
public Counter(EntryTable<T> countTable)
|
||||
@@ -68,7 +70,7 @@ namespace ARMeilleure.Common
|
||||
/// <summary>
|
||||
/// Releases all unmanaged and optionally managed resources used by the <see cref="Counter{T}"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="disposing"><see langword="true"/> to dispose managed resources also; otherwise just unmanaged resouces</param>
|
||||
/// <param name="disposing"><see langword="true"/> to dispose managed resources also; otherwise just unmanaged resources</param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposed)
|
||||
|
@@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
|
@@ -1,6 +1,4 @@
|
||||
using ARMeilleure.Instructions;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCodeT32BImm20 : OpCodeT32, IOpCode32BImm
|
||||
{
|
||||
|
@@ -1,7 +1,5 @@
|
||||
using ARMeilleure.Decoders;
|
||||
using ARMeilleure.Translation;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitFlowHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
|
@@ -2,8 +2,6 @@
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitFlowHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
|
@@ -2,8 +2,6 @@ using ARMeilleure.Memory;
|
||||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
{
|
||||
|
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ARMeilleure.Signal
|
||||
|
@@ -344,7 +344,7 @@ namespace ARMeilleure.Translation
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the value from the dictionary after searching for it with <paramref name="key">.
|
||||
/// Removes the value from the dictionary after searching for it with <paramref name="key"/>.
|
||||
/// </summary>
|
||||
/// <param name="key">Key to search for</param>
|
||||
/// <returns>Number of deleted values</returns>
|
||||
|
@@ -4,7 +4,6 @@ using Ryujinx.Memory;
|
||||
using Ryujinx.SDL2.Common;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
using static Ryujinx.Audio.Integration.IHardwareDeviceDriver;
|
||||
|
@@ -4,7 +4,6 @@ using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Memory;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
using static SDL2.SDL;
|
||||
|
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
namespace SoundIOSharp
|
||||
namespace SoundIOSharp
|
||||
{
|
||||
public struct SoundIOSampleRateRange
|
||||
{
|
||||
|
@@ -1,7 +1,6 @@
|
||||
using Ryujinx.Audio.Renderer.Dsp.State;
|
||||
using Ryujinx.Audio.Renderer.Parameter;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
{
|
||||
|
@@ -1,5 +1,4 @@
|
||||
using Ryujinx.Audio.Renderer.Dsp.State;
|
||||
using Ryujinx.Audio.Renderer.Parameter;
|
||||
using Ryujinx.Memory;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
@@ -1,6 +1,5 @@
|
||||
using Ryujinx.Audio.Renderer.Parameter.Sink;
|
||||
using Ryujinx.Audio.Renderer.Server.MemoryPool;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
@@ -6,7 +6,6 @@ using Ryujinx.Memory;
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
@@ -1,5 +1,3 @@
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
{
|
||||
public class CopyMixBufferCommand : ICommand
|
||||
|
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
@@ -2,7 +2,6 @@ using Ryujinx.Audio.Renderer.Dsp.State;
|
||||
using Ryujinx.Audio.Renderer.Parameter.Effect;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
{
|
||||
|
@@ -3,7 +3,6 @@ using Ryujinx.Audio.Renderer.Parameter;
|
||||
using Ryujinx.Audio.Renderer.Parameter.Effect;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
@@ -1,6 +1,5 @@
|
||||
using Ryujinx.Audio.Renderer.Server.Upsampler;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
{
|
||||
|
@@ -76,7 +76,7 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
||||
|
||||
if (!info.DecodingBehaviour.HasFlag(DecodingBehaviour.SkipPitchAndSampleRateConversion))
|
||||
{
|
||||
voiceState.Pitch.ToSpan().Slice(0, pitchMaxLength).CopyTo(tempBuffer);
|
||||
voiceState.Pitch.AsSpan().Slice(0, pitchMaxLength).CopyTo(tempBuffer);
|
||||
tempBufferIndex += pitchMaxLength;
|
||||
}
|
||||
|
||||
@@ -239,7 +239,7 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
||||
|
||||
ResamplerHelper.Resample(outputBuffer, tempBuffer, sampleRateRatio, ref fraction, sampleCountToProcess, info.SrcQuality, y != sourceSampleCountToProcess || info.Pitch != 1.0f);
|
||||
|
||||
tempBuffer.Slice(sampleCountToDecode, pitchMaxLength).CopyTo(voiceState.Pitch.ToSpan());
|
||||
tempBuffer.Slice(sampleCountToDecode, pitchMaxLength).CopyTo(voiceState.Pitch.AsSpan());
|
||||
}
|
||||
|
||||
i += sampleCountToProcess;
|
||||
|
@@ -24,8 +24,8 @@ namespace Ryujinx.Audio.Renderer.Parameter.Effect
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
InputMax.ToSpan().Fill(0.0f);
|
||||
CompressionGainMin.ToSpan().Fill(1.0f);
|
||||
InputMax.AsSpan().Fill(0.0f);
|
||||
CompressionGainMin.AsSpan().Fill(1.0f);
|
||||
}
|
||||
}
|
||||
}
|
@@ -7,7 +7,6 @@ using Ryujinx.Audio.Renderer.Server.Performance;
|
||||
using Ryujinx.Audio.Renderer.Server.Sink;
|
||||
using Ryujinx.Audio.Renderer.Server.Upsampler;
|
||||
using Ryujinx.Audio.Renderer.Server.Voice;
|
||||
using Ryujinx.Common.Memory;
|
||||
using System;
|
||||
using CpuAddress = System.UInt64;
|
||||
|
||||
|
@@ -141,7 +141,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||
Memory<byte> biquadStateRawMemory = SpanMemoryManager<byte>.Cast(state).Slice(VoiceUpdateState.BiquadStateOffset, VoiceUpdateState.BiquadStateSize * Constants.VoiceBiquadFilterCount);
|
||||
Memory<BiquadFilterState> stateMemory = SpanMemoryManager<BiquadFilterState>.Cast(biquadStateRawMemory);
|
||||
|
||||
_commandBuffer.GenerateGroupedBiquadFilter(baseIndex, voiceState.BiquadFilters.ToSpan(), stateMemory, bufferOffset, bufferOffset, voiceState.BiquadFilterNeedInitialization, nodeId);
|
||||
_commandBuffer.GenerateGroupedBiquadFilter(baseIndex, voiceState.BiquadFilters.AsSpan(), stateMemory, bufferOffset, bufferOffset, voiceState.BiquadFilterNeedInitialization, nodeId);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -337,8 +337,8 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||
GeneratePerformance(ref performanceEntry, PerformanceCommand.Type.Start, nodeId);
|
||||
}
|
||||
|
||||
GenerateVoiceMix(channelResource.Mix.ToSpan(),
|
||||
channelResource.PreviousMix.ToSpan(),
|
||||
GenerateVoiceMix(channelResource.Mix.AsSpan(),
|
||||
channelResource.PreviousMix.AsSpan(),
|
||||
dspStateMemory,
|
||||
mix.BufferOffset,
|
||||
mix.BufferCount,
|
||||
@@ -505,8 +505,8 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||
BiquadFilterParameter parameter = new BiquadFilterParameter();
|
||||
|
||||
parameter.Enable = true;
|
||||
effect.Parameter.Denominator.ToSpan().CopyTo(parameter.Denominator.ToSpan());
|
||||
effect.Parameter.Numerator.ToSpan().CopyTo(parameter.Numerator.ToSpan());
|
||||
effect.Parameter.Denominator.AsSpan().CopyTo(parameter.Denominator.AsSpan());
|
||||
effect.Parameter.Numerator.AsSpan().CopyTo(parameter.Numerator.AsSpan());
|
||||
|
||||
for (int i = 0; i < effect.Parameter.ChannelCount; i++)
|
||||
{
|
||||
@@ -923,8 +923,8 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||
if (useCustomDownMixingCommand)
|
||||
{
|
||||
_commandBuffer.GenerateDownMixSurroundToStereo(finalMix.BufferOffset,
|
||||
sink.Parameter.Input.ToSpan(),
|
||||
sink.Parameter.Input.ToSpan(),
|
||||
sink.Parameter.Input.AsSpan(),
|
||||
sink.Parameter.Input.AsSpan(),
|
||||
sink.DownMixCoefficients,
|
||||
Constants.InvalidNodeId);
|
||||
}
|
||||
@@ -932,8 +932,8 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||
else if (_rendererContext.ChannelCount == 2 && sink.Parameter.InputCount == 6)
|
||||
{
|
||||
_commandBuffer.GenerateDownMixSurroundToStereo(finalMix.BufferOffset,
|
||||
sink.Parameter.Input.ToSpan(),
|
||||
sink.Parameter.Input.ToSpan(),
|
||||
sink.Parameter.Input.AsSpan(),
|
||||
sink.Parameter.Input.AsSpan(),
|
||||
Constants.DefaultSurroundToStereoCoefficients,
|
||||
Constants.InvalidNodeId);
|
||||
}
|
||||
@@ -945,7 +945,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||
_commandBuffer.GenerateUpsample(finalMix.BufferOffset,
|
||||
sink.UpsamplerState,
|
||||
sink.Parameter.InputCount,
|
||||
sink.Parameter.Input.ToSpan(),
|
||||
sink.Parameter.Input.AsSpan(),
|
||||
commandList.BufferCount,
|
||||
commandList.SampleCount,
|
||||
commandList.SampleRate,
|
||||
|
@@ -1,9 +1,5 @@
|
||||
using Ryujinx.Audio.Common;
|
||||
using Ryujinx.Audio.Renderer.Dsp.Command;
|
||||
using Ryujinx.Audio.Renderer.Parameter.Effect;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using static Ryujinx.Audio.Renderer.Parameter.VoiceInParameter;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Server
|
||||
{
|
||||
|
@@ -63,10 +63,10 @@ namespace Ryujinx.Audio.Renderer.Server.Sink
|
||||
else
|
||||
{
|
||||
Parameter.DownMixParameterEnabled = inputDeviceParameter.DownMixParameterEnabled;
|
||||
inputDeviceParameter.DownMixParameter.ToSpan().CopyTo(Parameter.DownMixParameter.ToSpan());
|
||||
inputDeviceParameter.DownMixParameter.AsSpan().CopyTo(Parameter.DownMixParameter.AsSpan());
|
||||
}
|
||||
|
||||
Parameter.DownMixParameter.ToSpan().CopyTo(DownMixCoefficients.AsSpan());
|
||||
Parameter.DownMixParameter.AsSpan().CopyTo(DownMixCoefficients.AsSpan());
|
||||
|
||||
errorInfo = new BehaviourParameter.ErrorInfo();
|
||||
outStatus = new SinkOutStatus();
|
||||
|
@@ -119,7 +119,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||
ref VoiceChannelResource resource = ref context.GetChannelResource(i);
|
||||
|
||||
resource.Id = parameter.Id;
|
||||
parameter.Mix.ToSpan().CopyTo(resource.Mix.ToSpan());
|
||||
parameter.Mix.AsSpan().CopyTo(resource.Mix.AsSpan());
|
||||
resource.IsUsed = parameter.IsUsed;
|
||||
}
|
||||
|
||||
@@ -587,7 +587,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||
{
|
||||
ref BehaviourErrorInfoOutStatus outStatus = ref SpanIOHelper.GetWriteRef<BehaviourErrorInfoOutStatus>(ref _output)[0];
|
||||
|
||||
_behaviourContext.CopyErrorInfo(outStatus.ErrorInfos.ToSpan(), out outStatus.ErrorInfosCount);
|
||||
_behaviourContext.CopyErrorInfo(outStatus.ErrorInfos.AsSpan(), out outStatus.ErrorInfosCount);
|
||||
|
||||
OutputHeader.BehaviourSize = (uint)Unsafe.SizeOf<BehaviourErrorInfoOutStatus>();
|
||||
OutputHeader.TotalSize += OutputHeader.BehaviourSize;
|
||||
|
@@ -34,7 +34,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
|
||||
|
||||
public void UpdateState()
|
||||
{
|
||||
Mix.ToSpan().CopyTo(PreviousMix.ToSpan());
|
||||
Mix.AsSpan().CopyTo(PreviousMix.AsSpan());
|
||||
}
|
||||
}
|
||||
}
|
@@ -202,7 +202,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
|
||||
Pitch = 0.0f;
|
||||
Volume = 0.0f;
|
||||
PreviousVolume = 0.0f;
|
||||
BiquadFilters.ToSpan().Fill(new BiquadFilterParameter());
|
||||
BiquadFilters.AsSpan().Fill(new BiquadFilterParameter());
|
||||
WaveBuffersCount = 0;
|
||||
WaveBuffersIndex = 0;
|
||||
MixId = Constants.UnusedMixId;
|
||||
@@ -288,7 +288,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
|
||||
ChannelsCount = parameter.ChannelCount;
|
||||
Pitch = parameter.Pitch;
|
||||
Volume = parameter.Volume;
|
||||
parameter.BiquadFilters.ToSpan().CopyTo(BiquadFilters.ToSpan());
|
||||
parameter.BiquadFilters.AsSpan().CopyTo(BiquadFilters.AsSpan());
|
||||
WaveBuffersCount = parameter.WaveBuffersCount;
|
||||
WaveBuffersIndex = parameter.WaveBuffersIndex;
|
||||
|
||||
@@ -308,7 +308,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
|
||||
SplitterId = Constants.UnusedSplitterId;
|
||||
}
|
||||
|
||||
parameter.ChannelResourceIds.ToSpan().CopyTo(ChannelResourceIds.ToSpan());
|
||||
parameter.ChannelResourceIds.AsSpan().CopyTo(ChannelResourceIds.AsSpan());
|
||||
|
||||
DecodingBehaviour behaviour = DecodingBehaviour.Default;
|
||||
|
||||
@@ -638,7 +638,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
|
||||
|
||||
voiceUpdateState.Offset = 0;
|
||||
voiceUpdateState.PlayedSampleCount = 0;
|
||||
voiceUpdateState.Pitch.ToSpan().Fill(0);
|
||||
voiceUpdateState.Pitch.AsSpan().Fill(0);
|
||||
voiceUpdateState.Fraction = 0;
|
||||
voiceUpdateState.LoopContext = new Dsp.State.AdpcmLoopContext();
|
||||
}
|
||||
@@ -650,7 +650,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
|
||||
|
||||
case Types.PlayState.Stopped:
|
||||
case Types.PlayState.Paused:
|
||||
foreach (ref WaveBuffer wavebuffer in WaveBuffers.ToSpan())
|
||||
foreach (ref WaveBuffer wavebuffer in WaveBuffers.AsSpan())
|
||||
{
|
||||
wavebuffer.BufferAddressInfo.GetReference(true);
|
||||
wavebuffer.ContextAddressInfo.GetReference(true);
|
||||
|
@@ -12,6 +12,7 @@ using Ryujinx.Audio.Integration;
|
||||
using Ryujinx.Ava.Common;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Input;
|
||||
using Ryujinx.Ava.Ui.Backend.Vulkan;
|
||||
using Ryujinx.Ava.Ui.Controls;
|
||||
using Ryujinx.Ava.Ui.Models;
|
||||
using Ryujinx.Ava.Ui.Vulkan;
|
||||
@@ -334,6 +335,8 @@ namespace Ryujinx.Ava
|
||||
return;
|
||||
}
|
||||
|
||||
AvaloniaLocator.Current.GetService<VulkanPlatformInterface>()?.MainSurface.Display.ChangeVSyncMode(true);
|
||||
|
||||
_isStopped = true;
|
||||
_isActive = false;
|
||||
}
|
||||
@@ -596,12 +599,13 @@ namespace Ryujinx.Ava
|
||||
if (Program.UseVulkan)
|
||||
{
|
||||
var vulkan = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>();
|
||||
|
||||
renderer = new VulkanRenderer(vulkan.Instance.InternalHandle,
|
||||
vulkan.Device.InternalHandle,
|
||||
vulkan.MainSurface.Device.InternalHandle,
|
||||
vulkan.PhysicalDevice.InternalHandle,
|
||||
vulkan.Device.Queue.InternalHandle,
|
||||
vulkan.MainSurface.Device.Queue.InternalHandle,
|
||||
vulkan.PhysicalDevice.QueueFamilyIndex,
|
||||
vulkan.Device.Lock);
|
||||
vulkan.MainSurface.Device.Lock);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -775,7 +779,10 @@ namespace Ryujinx.Ava
|
||||
Width = (int)e.Width;
|
||||
Height = (int)e.Height;
|
||||
|
||||
SetRendererWindowSize(e);
|
||||
if (!Program.UseVulkan)
|
||||
{
|
||||
SetRendererWindowSize(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void MainLoop()
|
||||
@@ -815,12 +822,11 @@ namespace Ryujinx.Ava
|
||||
|
||||
_renderer.ScreenCaptured += Renderer_ScreenCaptured;
|
||||
|
||||
if (!Program.UseVulkan)
|
||||
{
|
||||
(_renderer as OpenGLRenderer).InitializeBackgroundContext(SPBOpenGLContext.CreateBackgroundContext((Renderer as OpenGLRendererControl).GameContext));
|
||||
(_renderer as OpenGLRenderer)?.InitializeBackgroundContext(SPBOpenGLContext.CreateBackgroundContext((Renderer as OpenGLRendererControl).GameContext));
|
||||
|
||||
Renderer.MakeCurrent();
|
||||
}
|
||||
Renderer.MakeCurrent();
|
||||
|
||||
AvaloniaLocator.Current.GetService<VulkanPlatformInterface>()?.MainSurface?.Display?.ChangeVSyncMode(Device.EnableDeviceVsync);
|
||||
|
||||
Device.Gpu.Renderer.Initialize(_glLogLevel);
|
||||
|
||||
@@ -837,8 +843,6 @@ namespace Ryujinx.Ava
|
||||
|
||||
Renderer.Start();
|
||||
|
||||
Renderer.QueueRender();
|
||||
|
||||
while (_isActive)
|
||||
{
|
||||
if (Device.WaitFifo())
|
||||
@@ -889,6 +893,16 @@ namespace Ryujinx.Ava
|
||||
$"FIFO: {Device.Statistics.GetFifoPercent():00.00} %",
|
||||
$"GPU: {_renderer.GetHardwareInfo().GpuVendor}"));
|
||||
|
||||
if (Program.UseVulkan)
|
||||
{
|
||||
var platformInterface = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>();
|
||||
if (platformInterface.MainSurface.Display.IsSurfaceChanged())
|
||||
{
|
||||
SetRendererWindowSize(new Size(Width, Height));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Renderer.Present(image);
|
||||
}
|
||||
|
||||
@@ -970,6 +984,9 @@ namespace Ryujinx.Ava
|
||||
{
|
||||
case KeyboardHotkeyState.ToggleVSync:
|
||||
Device.EnableDeviceVsync = !Device.EnableDeviceVsync;
|
||||
|
||||
AvaloniaLocator.Current.GetService<VulkanPlatformInterface>()?.MainSurface?.Display?.ChangeVSyncMode(Device.EnableDeviceVsync);
|
||||
|
||||
break;
|
||||
case KeyboardHotkeyState.Screenshot:
|
||||
ScreenshotRequested = true;
|
||||
|
@@ -52,8 +52,8 @@
|
||||
"GameListContextMenuOpenModsDirectory": "Open Mods Directory",
|
||||
"GameListContextMenuOpenModsDirectoryToolTip": "Opens the directory which contains Application's Mods",
|
||||
"GameListContextMenuCacheManagement": "Cache Management",
|
||||
"GameListContextMenuCacheManagementPurgePptc": "Purge PPTC Cache",
|
||||
"GameListContextMenuCacheManagementPurgePptcToolTip": "Deletes Application's PPTC cache",
|
||||
"GameListContextMenuCacheManagementPurgePptc": "Queue PPTC Rebuild",
|
||||
"GameListContextMenuCacheManagementPurgePptcToolTip": "Trigger PPTC to rebuild at boot time on the next game launch",
|
||||
"GameListContextMenuCacheManagementPurgeShaderCache": "Purge Shader Cache",
|
||||
"GameListContextMenuCacheManagementPurgeShaderCacheToolTip": "Deletes Application's shader cache",
|
||||
"GameListContextMenuCacheManagementOpenPptcDirectory": "Open PPTC Directory",
|
||||
@@ -350,7 +350,7 @@
|
||||
"DialogProfileDeleteProfileTitle": "Deleting Profile",
|
||||
"DialogProfileDeleteProfileMessage": "This action is irreversible, are you sure you want to continue?",
|
||||
"DialogWarning": "Warning",
|
||||
"DialogPPTCDeletionMessage": "You are about to delete the PPTC cache for :\n\n{0}\n\nAre you sure you want to proceed?",
|
||||
"DialogPPTCDeletionMessage": "You are about to queue a PPTC rebuild on the next boot of:\n\n{0}\n\nAre you sure you want to proceed?",
|
||||
"DialogPPTCDeletionErrorMessage": "Error purging PPTC cache at {0}: {1}",
|
||||
"DialogShaderDeletionMessage": "You are about to delete the Shader cache for :\n\n{0}\n\nAre you sure you want to proceed?",
|
||||
"DialogShaderDeletionErrorMessage": "Error purging Shader cache at {0}: {1}",
|
||||
|
@@ -24,7 +24,6 @@ using System.Buffers;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using static LibHac.Fs.ApplicationSaveDataManagement;
|
||||
using Path = System.IO.Path;
|
||||
|
||||
namespace Ryujinx.Ava.Common
|
||||
|
@@ -1,7 +1,6 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Threading;
|
||||
using Ryujinx.Input;
|
||||
using System;
|
||||
using System.Numerics;
|
||||
|
@@ -16,8 +16,6 @@ using Ryujinx.Graphics.Vulkan;
|
||||
using Ryujinx.Modules;
|
||||
using Ryujinx.Ui.Common;
|
||||
using Ryujinx.Ui.Common.Configuration;
|
||||
using Silk.NET.Vulkan.Extensions.EXT;
|
||||
using Silk.NET.Vulkan.Extensions.KHR;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
@@ -94,7 +92,6 @@ namespace Ryujinx.Ava
|
||||
.With(new Ui.Vulkan.VulkanOptions()
|
||||
{
|
||||
ApplicationName = "Ryujinx.Graphics.Vulkan",
|
||||
VulkanVersion = new Version(1, 2),
|
||||
MaxQueueCount = 2,
|
||||
PreferDiscreteGpu = true,
|
||||
PreferredDevice = !PreviewerDetached ? "" : ConfigurationState.Instance.Graphics.PreferredGpu.Value,
|
||||
@@ -181,6 +178,18 @@ namespace Ryujinx.Ava
|
||||
|
||||
UseVulkan = PreviewerDetached ? ConfigurationState.Instance.Graphics.GraphicsBackend.Value == GraphicsBackend.Vulkan : false;
|
||||
|
||||
if (UseVulkan)
|
||||
{
|
||||
if (VulkanRenderer.GetPhysicalDevices().Length == 0)
|
||||
{
|
||||
UseVulkan = false;
|
||||
|
||||
ConfigurationState.Instance.Graphics.GraphicsBackend.Value = GraphicsBackend.OpenGl;
|
||||
|
||||
Logger.Warning?.PrintMsg(LogClass.Application, "A suitable Vulkan physical device is not available. Falling back to OpenGL");
|
||||
}
|
||||
}
|
||||
|
||||
if (UseVulkan)
|
||||
{
|
||||
// With a custom gpu backend, avalonia doesn't enable dpi awareness, so the backend must handle it. This isn't so for the opengl backed,
|
||||
|
@@ -10,7 +10,6 @@ using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationPr
|
||||
using Ryujinx.HLE.Ui;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ryujinx.Ava.Ui.Applet
|
||||
{
|
||||
|
@@ -1,7 +1,6 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Threading;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Ui.Windows;
|
||||
|
@@ -1,7 +1,6 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Media;
|
||||
using FluentAvalonia.Core;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
|
@@ -7,7 +7,8 @@ namespace Ryujinx.Ava.Ui.Vulkan
|
||||
{
|
||||
public static void ThrowOnError(this Result result)
|
||||
{
|
||||
if (result != Result.Success)
|
||||
// Only negative result codes are errors.
|
||||
if ((int)result < (int)Result.Success)
|
||||
{
|
||||
throw new Exception($"Unexpected API error \"{result}\".");
|
||||
}
|
||||
|
@@ -1,26 +1,90 @@
|
||||
using System;
|
||||
using Avalonia;
|
||||
using Avalonia.Skia;
|
||||
using Ryujinx.Ava.Ui.Vulkan;
|
||||
using Ryujinx.Ava.Ui.Vulkan.Surfaces;
|
||||
using Silk.NET.Vulkan;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Ryujinx.Ava.Ui.Backend.Vulkan
|
||||
{
|
||||
internal class VulkanRenderTarget : ISkiaGpuRenderTarget
|
||||
{
|
||||
public GRContext GrContext { get; set; }
|
||||
public GRContext GrContext { get; private set; }
|
||||
|
||||
private readonly VulkanSurfaceRenderTarget _surface;
|
||||
private readonly VulkanPlatformInterface _vulkanPlatformInterface;
|
||||
private readonly IVulkanPlatformSurface _vulkanPlatformSurface;
|
||||
private GRVkBackendContext _grVkBackend;
|
||||
|
||||
public VulkanRenderTarget(VulkanPlatformInterface vulkanPlatformInterface, IVulkanPlatformSurface vulkanPlatformSurface)
|
||||
{
|
||||
_surface = vulkanPlatformInterface.CreateRenderTarget(vulkanPlatformSurface);
|
||||
_vulkanPlatformInterface = vulkanPlatformInterface;
|
||||
_vulkanPlatformSurface = vulkanPlatformSurface;
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
GRVkGetProcedureAddressDelegate getProc = GetVulkanProcAddress;
|
||||
|
||||
_grVkBackend = new GRVkBackendContext()
|
||||
{
|
||||
VkInstance = _surface.Device.Handle,
|
||||
VkPhysicalDevice = _vulkanPlatformInterface.PhysicalDevice.Handle,
|
||||
VkDevice = _surface.Device.Handle,
|
||||
VkQueue = _surface.Device.Queue.Handle,
|
||||
GraphicsQueueIndex = _vulkanPlatformInterface.PhysicalDevice.QueueFamilyIndex,
|
||||
GetProcedureAddress = getProc
|
||||
};
|
||||
|
||||
GrContext = GRContext.CreateVulkan(_grVkBackend);
|
||||
|
||||
var gpu = AvaloniaLocator.Current.GetService<VulkanSkiaGpu>();
|
||||
|
||||
if (gpu.MaxResourceBytes.HasValue)
|
||||
{
|
||||
GrContext.SetResourceCacheLimit(gpu.MaxResourceBytes.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private IntPtr GetVulkanProcAddress(string name, IntPtr instanceHandle, IntPtr deviceHandle)
|
||||
{
|
||||
IntPtr addr;
|
||||
|
||||
if (deviceHandle != IntPtr.Zero)
|
||||
{
|
||||
addr = _vulkanPlatformInterface.Api.GetDeviceProcAddr(new Device(deviceHandle), name);
|
||||
|
||||
if (addr != IntPtr.Zero)
|
||||
{
|
||||
return addr;
|
||||
}
|
||||
|
||||
addr = _vulkanPlatformInterface.Api.GetDeviceProcAddr(new Device(_surface.Device.Handle), name);
|
||||
|
||||
if (addr != IntPtr.Zero)
|
||||
{
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
||||
addr = _vulkanPlatformInterface.Api.GetInstanceProcAddr(new Instance(_vulkanPlatformInterface.Instance.Handle), name);
|
||||
|
||||
if (addr == IntPtr.Zero)
|
||||
{
|
||||
addr = _vulkanPlatformInterface.Api.GetInstanceProcAddr(new Instance(instanceHandle), name);
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_grVkBackend.Dispose();
|
||||
GrContext.Dispose();
|
||||
_surface.Dispose();
|
||||
}
|
||||
|
||||
@@ -45,20 +109,22 @@ namespace Ryujinx.Ava.Ui.Backend.Vulkan
|
||||
{
|
||||
GrContext.ResetContext();
|
||||
|
||||
var image = _surface.GetImage();
|
||||
|
||||
var imageInfo = new GRVkImageInfo()
|
||||
{
|
||||
CurrentQueueFamily = disp.QueueFamilyIndex,
|
||||
Format = _surface.ImageFormat,
|
||||
Image = _surface.Image.Handle,
|
||||
ImageLayout = (uint)_surface.Image.CurrentLayout,
|
||||
ImageTiling = (uint)_surface.Image.Tiling,
|
||||
Format = (uint)image.Format,
|
||||
Image = image.Handle,
|
||||
ImageLayout = (uint)image.CurrentLayout,
|
||||
ImageTiling = (uint)image.Tiling,
|
||||
ImageUsageFlags = _surface.UsageFlags,
|
||||
LevelCount = _surface.MipLevels,
|
||||
SampleCount = 1,
|
||||
Protected = false,
|
||||
Alloc = new GRVkAlloc()
|
||||
{
|
||||
Memory = _surface.Image.MemoryHandle,
|
||||
Memory = image.MemoryHandle,
|
||||
Flags = 0,
|
||||
Offset = 0,
|
||||
Size = _surface.MemorySize
|
||||
|
@@ -13,71 +13,12 @@ namespace Ryujinx.Ava.Ui.Backend.Vulkan
|
||||
public class VulkanSkiaGpu : ISkiaGpu
|
||||
{
|
||||
private readonly VulkanPlatformInterface _vulkan;
|
||||
private readonly long? _maxResourceBytes;
|
||||
private GRVkBackendContext _grVkBackend;
|
||||
private bool _initialized;
|
||||
|
||||
public GRContext GrContext { get; private set; }
|
||||
public long? MaxResourceBytes { get; }
|
||||
|
||||
public VulkanSkiaGpu(long? maxResourceBytes)
|
||||
{
|
||||
_vulkan = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>();
|
||||
_maxResourceBytes = maxResourceBytes;
|
||||
}
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
if (_initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_initialized = true;
|
||||
GRVkGetProcedureAddressDelegate getProc = (string name, IntPtr instanceHandle, IntPtr deviceHandle) =>
|
||||
{
|
||||
IntPtr addr = IntPtr.Zero;
|
||||
|
||||
if (deviceHandle != IntPtr.Zero)
|
||||
{
|
||||
addr = _vulkan.Device.Api.GetDeviceProcAddr(new Device(deviceHandle), name);
|
||||
|
||||
if (addr != IntPtr.Zero)
|
||||
{
|
||||
return addr;
|
||||
}
|
||||
|
||||
addr = _vulkan.Device.Api.GetDeviceProcAddr(new Device(_vulkan.Device.Handle), name);
|
||||
|
||||
if (addr != IntPtr.Zero)
|
||||
{
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
||||
addr = _vulkan.Device.Api.GetInstanceProcAddr(new Instance(_vulkan.Instance.Handle), name);
|
||||
|
||||
if (addr == IntPtr.Zero)
|
||||
{
|
||||
addr = _vulkan.Device.Api.GetInstanceProcAddr(new Instance(instanceHandle), name);
|
||||
}
|
||||
|
||||
return addr;
|
||||
};
|
||||
|
||||
_grVkBackend = new GRVkBackendContext()
|
||||
{
|
||||
VkInstance = _vulkan.Device.Handle,
|
||||
VkPhysicalDevice = _vulkan.PhysicalDevice.Handle,
|
||||
VkDevice = _vulkan.Device.Handle,
|
||||
VkQueue = _vulkan.Device.Queue.Handle,
|
||||
GraphicsQueueIndex = _vulkan.PhysicalDevice.QueueFamilyIndex,
|
||||
GetProcedureAddress = getProc
|
||||
};
|
||||
GrContext = GRContext.CreateVulkan(_grVkBackend);
|
||||
if (_maxResourceBytes.HasValue)
|
||||
{
|
||||
GrContext.SetResourceCacheLimit(_maxResourceBytes.Value);
|
||||
}
|
||||
MaxResourceBytes = maxResourceBytes;
|
||||
}
|
||||
|
||||
public ISkiaGpuRenderTarget TryCreateRenderTarget(IEnumerable<object> surfaces)
|
||||
@@ -106,10 +47,6 @@ namespace Ryujinx.Ava.Ui.Backend.Vulkan
|
||||
|
||||
VulkanRenderTarget vulkanRenderTarget = new VulkanRenderTarget(_vulkan, window);
|
||||
|
||||
Initialize();
|
||||
|
||||
vulkanRenderTarget.GrContext = GrContext;
|
||||
|
||||
return vulkanRenderTarget;
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using Avalonia;
|
||||
using Ryujinx.Graphics.Vulkan;
|
||||
using Silk.NET.Vulkan;
|
||||
|
||||
namespace Ryujinx.Ava.Ui.Vulkan.Surfaces
|
||||
@@ -7,24 +8,35 @@ namespace Ryujinx.Ava.Ui.Vulkan.Surfaces
|
||||
internal class VulkanSurfaceRenderTarget : IDisposable
|
||||
{
|
||||
private readonly VulkanPlatformInterface _platformInterface;
|
||||
|
||||
private readonly Format _format;
|
||||
|
||||
public VulkanImage Image { get; private set; }
|
||||
public bool IsCorrupted { get; private set; } = true;
|
||||
private VulkanCommandBufferPool.VulkanCommandBuffer _commandBuffer;
|
||||
private VulkanImage Image { get; set; }
|
||||
private object _lock = new object();
|
||||
|
||||
public uint MipLevels => Image.MipLevels;
|
||||
public VulkanDevice Device { get; }
|
||||
|
||||
public VulkanSurfaceRenderTarget(VulkanPlatformInterface platformInterface, VulkanSurface surface)
|
||||
{
|
||||
_platformInterface = platformInterface;
|
||||
|
||||
Display = VulkanDisplay.CreateDisplay(platformInterface.Instance, platformInterface.Device,
|
||||
platformInterface.PhysicalDevice, surface);
|
||||
var device = VulkanInitialization.CreateDevice(platformInterface.Api,
|
||||
platformInterface.PhysicalDevice.InternalHandle,
|
||||
platformInterface.PhysicalDevice.QueueFamilyIndex,
|
||||
VulkanInitialization.GetSupportedExtensions(platformInterface.Api, platformInterface.PhysicalDevice.InternalHandle),
|
||||
platformInterface.PhysicalDevice.QueueCount);
|
||||
|
||||
Device = new VulkanDevice(device, platformInterface.PhysicalDevice, platformInterface.Api);
|
||||
|
||||
Display = VulkanDisplay.CreateDisplay(
|
||||
platformInterface.Instance,
|
||||
Device,
|
||||
platformInterface.PhysicalDevice,
|
||||
surface);
|
||||
Surface = surface;
|
||||
|
||||
// Skia seems to only create surfaces from images with unorm format
|
||||
|
||||
IsRgba = Display.SurfaceFormat.Format >= Format.R8G8B8A8Unorm &&
|
||||
Display.SurfaceFormat.Format <= Format.R8G8B8A8Srgb;
|
||||
|
||||
@@ -33,13 +45,13 @@ namespace Ryujinx.Ava.Ui.Vulkan.Surfaces
|
||||
|
||||
public bool IsRgba { get; }
|
||||
|
||||
public uint ImageFormat => (uint) _format;
|
||||
public uint ImageFormat => (uint)_format;
|
||||
|
||||
public ulong MemorySize => Image.MemorySize;
|
||||
|
||||
public VulkanDisplay Display { get; }
|
||||
public VulkanDisplay Display { get; private set; }
|
||||
|
||||
public VulkanSurface Surface { get; }
|
||||
public VulkanSurface Surface { get; private set; }
|
||||
|
||||
public uint UsageFlags => Image.UsageFlags;
|
||||
|
||||
@@ -47,46 +59,76 @@ namespace Ryujinx.Ava.Ui.Vulkan.Surfaces
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_platformInterface.Device.WaitIdle();
|
||||
DestroyImage();
|
||||
Display?.Dispose();
|
||||
Surface?.Dispose();
|
||||
lock (_lock)
|
||||
{
|
||||
DestroyImage();
|
||||
Display?.Dispose();
|
||||
Surface?.Dispose();
|
||||
Device?.Dispose();
|
||||
|
||||
Display = null;
|
||||
Surface = null;
|
||||
}
|
||||
}
|
||||
|
||||
public VulkanSurfaceRenderingSession BeginDraw(float scaling)
|
||||
{
|
||||
var session = new VulkanSurfaceRenderingSession(Display, _platformInterface.Device, this, scaling);
|
||||
if (Image == null)
|
||||
{
|
||||
RecreateImage();
|
||||
}
|
||||
|
||||
if (IsCorrupted)
|
||||
{
|
||||
IsCorrupted = false;
|
||||
DestroyImage();
|
||||
CreateImage();
|
||||
}
|
||||
else
|
||||
{
|
||||
Image.TransitionLayout(ImageLayout.ColorAttachmentOptimal, AccessFlags.AccessNoneKhr);
|
||||
}
|
||||
_commandBuffer?.WaitForFence();
|
||||
_commandBuffer = null;
|
||||
|
||||
var session = new VulkanSurfaceRenderingSession(Display, Device, this, scaling);
|
||||
|
||||
Image.TransitionLayout(ImageLayout.ColorAttachmentOptimal, AccessFlags.AccessNoneKhr);
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
public void Invalidate()
|
||||
public void RecreateImage()
|
||||
{
|
||||
IsCorrupted = true;
|
||||
DestroyImage();
|
||||
CreateImage();
|
||||
}
|
||||
|
||||
private void CreateImage()
|
||||
{
|
||||
Size = Display.Size;
|
||||
|
||||
Image = new VulkanImage(_platformInterface.Device, _platformInterface.PhysicalDevice, _platformInterface.Device.CommandBufferPool, ImageFormat, Size);
|
||||
Image = new VulkanImage(Device, _platformInterface.PhysicalDevice, Display.CommandBufferPool, ImageFormat, Size);
|
||||
}
|
||||
|
||||
private void DestroyImage()
|
||||
{
|
||||
_platformInterface.Device.WaitIdle();
|
||||
_commandBuffer?.WaitForFence();
|
||||
_commandBuffer = null;
|
||||
Image?.Dispose();
|
||||
Image = null;
|
||||
}
|
||||
|
||||
public VulkanImage GetImage()
|
||||
{
|
||||
return Image;
|
||||
}
|
||||
|
||||
public void EndDraw()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (Display == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_commandBuffer = Display.StartPresentation();
|
||||
|
||||
Display.BlitImageToCurrentImage(this, _commandBuffer.InternalHandle);
|
||||
|
||||
Display.EndPresentation(_commandBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -10,6 +10,7 @@ namespace Ryujinx.Ava.Ui.Vulkan
|
||||
private readonly CommandPool _commandPool;
|
||||
|
||||
private readonly List<VulkanCommandBuffer> _usedCommandBuffers = new();
|
||||
private readonly object _lock = new object();
|
||||
|
||||
public unsafe VulkanCommandBufferPool(VulkanDevice device, VulkanPhysicalDevice physicalDevice)
|
||||
{
|
||||
@@ -36,9 +37,12 @@ namespace Ryujinx.Ava.Ui.Vulkan
|
||||
Level = CommandBufferLevel.Primary
|
||||
};
|
||||
|
||||
_device.Api.AllocateCommandBuffers(_device.InternalHandle, commandBufferAllocateInfo, out var commandBuffer);
|
||||
lock (_lock)
|
||||
{
|
||||
_device.Api.AllocateCommandBuffers(_device.InternalHandle, commandBufferAllocateInfo, out var commandBuffer);
|
||||
|
||||
return commandBuffer;
|
||||
return commandBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
public VulkanCommandBuffer CreateCommandBuffer()
|
||||
@@ -48,7 +52,7 @@ namespace Ryujinx.Ava.Ui.Vulkan
|
||||
|
||||
public void FreeUsedCommandBuffers()
|
||||
{
|
||||
lock (_usedCommandBuffers)
|
||||
lock (_lock)
|
||||
{
|
||||
foreach (var usedCommandBuffer in _usedCommandBuffers)
|
||||
{
|
||||
@@ -61,7 +65,7 @@ namespace Ryujinx.Ava.Ui.Vulkan
|
||||
|
||||
private void DisposeCommandBuffer(VulkanCommandBuffer commandBuffer)
|
||||
{
|
||||
lock (_usedCommandBuffers)
|
||||
lock (_lock)
|
||||
{
|
||||
_usedCommandBuffers.Add(commandBuffer);
|
||||
}
|
||||
@@ -69,8 +73,11 @@ namespace Ryujinx.Ava.Ui.Vulkan
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
FreeUsedCommandBuffers();
|
||||
_device.Api.DestroyCommandPool(_device.InternalHandle, _commandPool, Span<AllocationCallbacks>.Empty);
|
||||
lock (_lock)
|
||||
{
|
||||
FreeUsedCommandBuffers();
|
||||
_device.Api.DestroyCommandPool(_device.InternalHandle, _commandPool, Span<AllocationCallbacks>.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
public class VulkanCommandBuffer : IDisposable
|
||||
@@ -80,6 +87,8 @@ namespace Ryujinx.Ava.Ui.Vulkan
|
||||
private readonly Fence _fence;
|
||||
private bool _hasEnded;
|
||||
private bool _hasStarted;
|
||||
private bool _isDisposed;
|
||||
private object _lock = new object();
|
||||
|
||||
public IntPtr Handle => InternalHandle.Handle;
|
||||
|
||||
@@ -101,6 +110,22 @@ namespace Ryujinx.Ava.Ui.Vulkan
|
||||
device.Api.CreateFence(device.InternalHandle, fenceCreateInfo, null, out _fence);
|
||||
}
|
||||
|
||||
public void WaitForFence()
|
||||
{
|
||||
if (_isDisposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
if (!_isDisposed)
|
||||
{
|
||||
_device.Api.WaitForFences(_device.InternalHandle, 1, _fence, true, ulong.MaxValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void BeginRecording()
|
||||
{
|
||||
if (!_hasStarted)
|
||||
@@ -173,9 +198,17 @@ namespace Ryujinx.Ava.Ui.Vulkan
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_device.Api.WaitForFences(_device.InternalHandle, 1, _fence, true, ulong.MaxValue);
|
||||
_device.Api.FreeCommandBuffers(_device.InternalHandle, _commandBufferPool._commandPool, 1, InternalHandle);
|
||||
_device.Api.DestroyFence(_device.InternalHandle, _fence, Span<AllocationCallbacks>.Empty);
|
||||
lock (_lock)
|
||||
{
|
||||
if (!_isDisposed)
|
||||
{
|
||||
_isDisposed = true;
|
||||
|
||||
_device.Api.WaitForFences(_device.InternalHandle, 1, _fence, true, ulong.MaxValue);
|
||||
_device.Api.FreeCommandBuffers(_device.InternalHandle, _commandBufferPool._commandPool, 1, InternalHandle);
|
||||
_device.Api.DestroyFence(_device.InternalHandle, _fence, Span<AllocationCallbacks>.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -14,12 +14,9 @@ namespace Ryujinx.Ava.Ui.Vulkan
|
||||
|
||||
api.GetDeviceQueue(apiHandle, physicalDevice.QueueFamilyIndex, 0, out var queue);
|
||||
|
||||
var vulkanQueue = new VulkanQueue(this, queue);
|
||||
Queue = vulkanQueue;
|
||||
Queue = new VulkanQueue(this, queue);
|
||||
|
||||
PresentQueue = vulkanQueue;
|
||||
|
||||
CommandBufferPool = new VulkanCommandBufferPool(this, physicalDevice);
|
||||
PresentQueue = Queue;
|
||||
}
|
||||
|
||||
public IntPtr Handle => InternalHandle.Handle;
|
||||
@@ -29,13 +26,12 @@ namespace Ryujinx.Ava.Ui.Vulkan
|
||||
|
||||
public VulkanQueue Queue { get; private set; }
|
||||
public VulkanQueue PresentQueue { get; }
|
||||
public VulkanCommandBufferPool CommandBufferPool { get; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
WaitIdle();
|
||||
CommandBufferPool?.Dispose();
|
||||
Queue = null;
|
||||
Api.DestroyDevice(InternalHandle, Span<AllocationCallbacks>.Empty);
|
||||
}
|
||||
|
||||
internal void Submit(SubmitInfo submitInfo, Fence fence = default)
|
||||
|
@@ -3,7 +3,6 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using Avalonia;
|
||||
using Ryujinx.Ava.Ui.Vulkan.Surfaces;
|
||||
using Ryujinx.Ui.Common.Configuration;
|
||||
using Silk.NET.Vulkan;
|
||||
using Silk.NET.Vulkan.Extensions.KHR;
|
||||
|
||||
@@ -15,16 +14,19 @@ namespace Ryujinx.Ava.Ui.Vulkan
|
||||
private readonly VulkanInstance _instance;
|
||||
private readonly VulkanPhysicalDevice _physicalDevice;
|
||||
private readonly VulkanSemaphorePair _semaphorePair;
|
||||
private readonly VulkanDevice _device;
|
||||
private uint _nextImage;
|
||||
private readonly VulkanSurface _surface;
|
||||
private SurfaceFormatKHR _surfaceFormat;
|
||||
private SwapchainKHR _swapchain;
|
||||
private Extent2D _swapchainExtent;
|
||||
private Image[] _swapchainImages;
|
||||
private VulkanDevice _device { get; }
|
||||
private ImageView[] _swapchainImageViews = new ImageView[0];
|
||||
private ImageView[] _swapchainImageViews = Array.Empty<ImageView>();
|
||||
private bool _vsyncStateChanged;
|
||||
private bool _vsyncEnabled;
|
||||
private bool _surfaceChanged;
|
||||
|
||||
public event EventHandler Presented;
|
||||
|
||||
public VulkanCommandBufferPool CommandBufferPool { get; set; }
|
||||
|
||||
@@ -73,6 +75,14 @@ namespace Ryujinx.Ava.Ui.Vulkan
|
||||
CommandBufferPool.Dispose();
|
||||
}
|
||||
|
||||
public bool IsSurfaceChanged()
|
||||
{
|
||||
var changed = _surfaceChanged;
|
||||
_surfaceChanged = false;
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
private static unsafe SwapchainKHR CreateSwapchain(VulkanInstance instance, VulkanDevice device,
|
||||
VulkanPhysicalDevice physicalDevice, VulkanSurface surface, out Extent2D swapchainExtent,
|
||||
SwapchainKHR? oldswapchain = null, bool vsyncEnabled = true)
|
||||
@@ -193,22 +203,23 @@ namespace Ryujinx.Ava.Ui.Vulkan
|
||||
}
|
||||
|
||||
var modes = presentModes.ToList();
|
||||
var presentMode = PresentModeKHR.PresentModeFifoKhr;
|
||||
|
||||
if (!vsyncEnabled && modes.Contains(PresentModeKHR.PresentModeImmediateKhr))
|
||||
{
|
||||
presentMode = PresentModeKHR.PresentModeImmediateKhr;
|
||||
return PresentModeKHR.PresentModeImmediateKhr;
|
||||
}
|
||||
else if (modes.Contains(PresentModeKHR.PresentModeMailboxKhr))
|
||||
{
|
||||
presentMode = PresentModeKHR.PresentModeMailboxKhr;
|
||||
return PresentModeKHR.PresentModeMailboxKhr;
|
||||
}
|
||||
else if (modes.Contains(PresentModeKHR.PresentModeImmediateKhr))
|
||||
else if (modes.Contains(PresentModeKHR.PresentModeFifoKhr))
|
||||
{
|
||||
presentMode = PresentModeKHR.PresentModeImmediateKhr;
|
||||
return PresentModeKHR.PresentModeFifoKhr;
|
||||
}
|
||||
else
|
||||
{
|
||||
return PresentModeKHR.PresentModeImmediateKhr;
|
||||
}
|
||||
|
||||
return presentMode;
|
||||
}
|
||||
|
||||
internal static VulkanDisplay CreateDisplay(VulkanInstance instance, VulkanDevice device,
|
||||
@@ -266,6 +277,8 @@ namespace Ryujinx.Ava.Ui.Vulkan
|
||||
_swapchain = CreateSwapchain(_instance, _device, _physicalDevice, _surface, out _swapchainExtent, _swapchain, _vsyncEnabled);
|
||||
|
||||
CreateSwapchainImages();
|
||||
|
||||
_surfaceChanged = true;
|
||||
}
|
||||
|
||||
private unsafe ImageView CreateSwapchainImageView(Image swapchainImage, Format format)
|
||||
@@ -306,7 +319,7 @@ namespace Ryujinx.Ava.Ui.Vulkan
|
||||
return true;
|
||||
}
|
||||
|
||||
internal VulkanCommandBufferPool.VulkanCommandBuffer StartPresentation(VulkanSurfaceRenderTarget renderTarget)
|
||||
internal VulkanCommandBufferPool.VulkanCommandBuffer StartPresentation()
|
||||
{
|
||||
_nextImage = 0;
|
||||
while (true)
|
||||
@@ -346,8 +359,10 @@ namespace Ryujinx.Ava.Ui.Vulkan
|
||||
|
||||
internal void BlitImageToCurrentImage(VulkanSurfaceRenderTarget renderTarget, CommandBuffer commandBuffer)
|
||||
{
|
||||
var image = renderTarget.GetImage();
|
||||
|
||||
VulkanMemoryHelper.TransitionLayout(_device, commandBuffer,
|
||||
renderTarget.Image.InternalHandle.Value, (ImageLayout)renderTarget.Image.CurrentLayout,
|
||||
image.InternalHandle.Value, (ImageLayout)image.CurrentLayout,
|
||||
AccessFlags.AccessNoneKhr,
|
||||
ImageLayout.TransferSrcOptimal,
|
||||
AccessFlags.AccessTransferReadBit,
|
||||
@@ -381,7 +396,7 @@ namespace Ryujinx.Ava.Ui.Vulkan
|
||||
}
|
||||
};
|
||||
|
||||
_device.Api.CmdBlitImage(commandBuffer, renderTarget.Image.InternalHandle.Value,
|
||||
_device.Api.CmdBlitImage(commandBuffer, image.InternalHandle.Value,
|
||||
ImageLayout.TransferSrcOptimal,
|
||||
_swapchainImages[_nextImage],
|
||||
ImageLayout.TransferDstOptimal,
|
||||
@@ -390,9 +405,9 @@ namespace Ryujinx.Ava.Ui.Vulkan
|
||||
Filter.Linear);
|
||||
|
||||
VulkanMemoryHelper.TransitionLayout(_device, commandBuffer,
|
||||
renderTarget.Image.InternalHandle.Value, ImageLayout.TransferSrcOptimal,
|
||||
image.InternalHandle.Value, ImageLayout.TransferSrcOptimal,
|
||||
AccessFlags.AccessTransferReadBit,
|
||||
(ImageLayout)renderTarget.Image.CurrentLayout,
|
||||
(ImageLayout)image.CurrentLayout,
|
||||
AccessFlags.AccessNoneKhr,
|
||||
renderTarget.MipLevels);
|
||||
}
|
||||
@@ -434,6 +449,8 @@ namespace Ryujinx.Ava.Ui.Vulkan
|
||||
}
|
||||
|
||||
CommandBufferPool.FreeUsedCommandBuffers();
|
||||
|
||||
Presented?.Invoke(this, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -148,20 +148,18 @@ namespace Ryujinx.Ava.Ui.Vulkan
|
||||
_currentAccessFlags = destinationAccessFlags;
|
||||
}
|
||||
|
||||
public void TransitionLayout(uint destinationLayout, uint destinationAccessFlags)
|
||||
public void Dispose()
|
||||
{
|
||||
TransitionLayout((ImageLayout)destinationLayout, (AccessFlags)destinationAccessFlags);
|
||||
}
|
||||
if (InternalHandle != null)
|
||||
{
|
||||
_device.Api.DestroyImageView(_device.InternalHandle, _imageView.Value, Span<AllocationCallbacks>.Empty);
|
||||
_device.Api.DestroyImage(_device.InternalHandle, InternalHandle.Value, Span<AllocationCallbacks>.Empty);
|
||||
_device.Api.FreeMemory(_device.InternalHandle, _imageMemory, Span<AllocationCallbacks>.Empty);
|
||||
|
||||
public unsafe void Dispose()
|
||||
{
|
||||
_device.Api.DestroyImageView(_device.InternalHandle, _imageView.Value, null);
|
||||
_device.Api.DestroyImage(_device.InternalHandle, InternalHandle.Value, null);
|
||||
_device.Api.FreeMemory(_device.InternalHandle, _imageMemory, null);
|
||||
|
||||
_imageView = default;
|
||||
InternalHandle = default;
|
||||
_imageMemory = default;
|
||||
_imageView = default;
|
||||
InternalHandle = null;
|
||||
_imageMemory = default;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -57,8 +57,7 @@ namespace Ryujinx.Ava.Ui.Vulkan
|
||||
var applicationInfo = new ApplicationInfo
|
||||
{
|
||||
PApplicationName = (byte*)applicationName,
|
||||
ApiVersion = new Version32((uint)options.VulkanVersion.Major, (uint)options.VulkanVersion.Minor,
|
||||
(uint)options.VulkanVersion.Build),
|
||||
ApiVersion = Vk.Version12.Value,
|
||||
PEngineName = (byte*)engineName,
|
||||
EngineVersion = new Version32(1, 0, 0),
|
||||
ApplicationVersion = new Version32(1, 0, 0)
|
||||
|
@@ -11,11 +11,6 @@ namespace Ryujinx.Ava.Ui.Vulkan
|
||||
/// </summary>
|
||||
public string ApplicationName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the Vulkan API version to use
|
||||
/// </summary>
|
||||
public Version VulkanVersion { get; set; } = new Version(1, 1, 0);
|
||||
|
||||
/// <summary>
|
||||
/// Specifies additional extensions to enable if available on the instance
|
||||
/// </summary>
|
||||
|
@@ -18,13 +18,11 @@ namespace Ryujinx.Ava.Ui.Vulkan
|
||||
|
||||
public VulkanPhysicalDevice PhysicalDevice { get; private set; }
|
||||
public VulkanInstance Instance { get; }
|
||||
public VulkanDevice Device { get; set; }
|
||||
public Vk Api { get; private set; }
|
||||
public VulkanSurfaceRenderTarget MainSurface { get; set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Device?.Dispose();
|
||||
Instance?.Dispose();
|
||||
Api?.Dispose();
|
||||
}
|
||||
@@ -54,16 +52,9 @@ namespace Ryujinx.Ava.Ui.Vulkan
|
||||
{
|
||||
var surface = VulkanSurface.CreateSurface(Instance, platformSurface);
|
||||
|
||||
if (Device == null)
|
||||
if (PhysicalDevice == null)
|
||||
{
|
||||
PhysicalDevice = VulkanPhysicalDevice.FindSuitablePhysicalDevice(Instance, surface, _options.PreferDiscreteGpu, _options.PreferredDevice);
|
||||
var device = VulkanInitialization.CreateDevice(Instance.Api,
|
||||
PhysicalDevice.InternalHandle,
|
||||
PhysicalDevice.QueueFamilyIndex,
|
||||
VulkanInitialization.GetSupportedExtensions(Instance.Api, PhysicalDevice.InternalHandle),
|
||||
PhysicalDevice.QueueCount);
|
||||
|
||||
Device = new VulkanDevice(device, PhysicalDevice, Instance.Api);
|
||||
}
|
||||
|
||||
var renderTarget = new VulkanSurfaceRenderTarget(this, surface);
|
||||
@@ -71,7 +62,6 @@ namespace Ryujinx.Ava.Ui.Vulkan
|
||||
if (MainSurface == null && surface != null)
|
||||
{
|
||||
MainSurface = renderTarget;
|
||||
MainSurface.Display.ChangeVSyncMode(false);
|
||||
}
|
||||
|
||||
return renderTarget;
|
||||
|
@@ -9,7 +9,6 @@ namespace Ryujinx.Ava.Ui.Vulkan
|
||||
{
|
||||
private readonly VulkanDevice _device;
|
||||
private readonly VulkanSurfaceRenderTarget _renderTarget;
|
||||
private VulkanCommandBufferPool.VulkanCommandBuffer _commandBuffer;
|
||||
|
||||
public VulkanSurfaceRenderingSession(VulkanDisplay display, VulkanDevice device,
|
||||
VulkanSurfaceRenderTarget renderTarget, float scaling)
|
||||
@@ -32,17 +31,13 @@ namespace Ryujinx.Ava.Ui.Vulkan
|
||||
{
|
||||
if (!Display.EnsureSwapchainAvailable())
|
||||
{
|
||||
_renderTarget.Invalidate();
|
||||
_renderTarget.RecreateImage();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_commandBuffer = Display.StartPresentation(_renderTarget);
|
||||
|
||||
Display.BlitImageToCurrentImage(_renderTarget, _commandBuffer.InternalHandle);
|
||||
|
||||
Display.EndPresentation(_commandBuffer);
|
||||
_renderTarget.EndDraw();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,9 +1,7 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Ui.Models;
|
||||
using Ryujinx.Ava.Ui.Windows;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ryujinx.Ava.Ui.Controls
|
||||
|
@@ -37,7 +37,7 @@ namespace Ryujinx.Ava.Ui.Controls
|
||||
|
||||
public override void DestroyBackgroundContext()
|
||||
{
|
||||
_image = null;
|
||||
Image = null;
|
||||
|
||||
if (_fence != IntPtr.Zero)
|
||||
{
|
||||
@@ -57,6 +57,8 @@ namespace Ryujinx.Ava.Ui.Controls
|
||||
Dispatcher.UIThread.InvokeAsync(() =>
|
||||
{
|
||||
Image = (int)image;
|
||||
|
||||
InvalidateVisual();
|
||||
}).Wait();
|
||||
|
||||
if (_fence != IntPtr.Zero)
|
||||
@@ -66,7 +68,7 @@ namespace Ryujinx.Ava.Ui.Controls
|
||||
|
||||
_fence = GL.FenceSync(SyncCondition.SyncGpuCommandsComplete, WaitSyncFlags.None);
|
||||
|
||||
QueueRender();
|
||||
InvalidateVisual();
|
||||
|
||||
_gameBackgroundWindow.SwapBuffers();
|
||||
}
|
||||
|
@@ -11,25 +11,7 @@ namespace Ryujinx.Ava.Ui.Controls
|
||||
{
|
||||
internal abstract class RendererControl : Control
|
||||
{
|
||||
protected object _image;
|
||||
|
||||
static RendererControl()
|
||||
{
|
||||
AffectsRender<RendererControl>(ImageProperty);
|
||||
}
|
||||
|
||||
public readonly static StyledProperty<object> ImageProperty =
|
||||
AvaloniaProperty.Register<RendererControl, object>(
|
||||
nameof(Image),
|
||||
0,
|
||||
inherits: true,
|
||||
defaultBindingMode: BindingMode.TwoWay);
|
||||
|
||||
protected object Image
|
||||
{
|
||||
get => _image;
|
||||
set => SetAndRaise(ImageProperty, ref _image, value);
|
||||
}
|
||||
protected object Image { get; set; }
|
||||
|
||||
public event EventHandler<EventArgs> RendererInitialized;
|
||||
public event EventHandler<Size> SizeChanged;
|
||||
@@ -60,8 +42,6 @@ namespace Ryujinx.Ava.Ui.Controls
|
||||
if (!rect.IsEmpty)
|
||||
{
|
||||
RenderSize = rect.Size * VisualRoot.RenderScaling;
|
||||
|
||||
DrawOperation?.Dispose();
|
||||
DrawOperation = CreateDrawOperation();
|
||||
}
|
||||
}
|
||||
@@ -97,17 +77,11 @@ namespace Ryujinx.Ava.Ui.Controls
|
||||
RendererInitialized?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public void QueueRender()
|
||||
{
|
||||
Program.RenderTimer.TickNow();
|
||||
}
|
||||
|
||||
internal abstract void Present(object image);
|
||||
|
||||
internal void Start()
|
||||
{
|
||||
IsStarted = true;
|
||||
QueueRender();
|
||||
}
|
||||
|
||||
internal void Stop()
|
||||
|
@@ -1,6 +1,4 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Ryujinx.Ava.Ui.Windows;
|
||||
|
||||
namespace Ryujinx.Ava.Ui.Controls
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.Rendering.SceneGraph;
|
||||
using Avalonia.Skia;
|
||||
@@ -11,20 +12,23 @@ using Silk.NET.Vulkan;
|
||||
using SkiaSharp;
|
||||
using SPB.Windowing;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace Ryujinx.Ava.Ui.Controls
|
||||
{
|
||||
internal class VulkanRendererControl : RendererControl
|
||||
{
|
||||
private const int MaxImagesInFlight = 3;
|
||||
|
||||
private VulkanPlatformInterface _platformInterface;
|
||||
private ConcurrentQueue<PresentImageInfo> _imagesInFlight;
|
||||
private PresentImageInfo _currentImage;
|
||||
|
||||
public VulkanRendererControl(GraphicsDebugLevel graphicsDebugLevel) : base(graphicsDebugLevel)
|
||||
{
|
||||
_platformInterface = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>();
|
||||
|
||||
_imagesInFlight = new ConcurrentQueue<PresentImageInfo>();
|
||||
}
|
||||
|
||||
public override void DestroyBackgroundContext()
|
||||
@@ -37,6 +41,40 @@ namespace Ryujinx.Ava.Ui.Controls
|
||||
return new VulkanDrawOperation(this);
|
||||
}
|
||||
|
||||
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnDetachedFromVisualTree(e);
|
||||
|
||||
_imagesInFlight.Clear();
|
||||
|
||||
if (_platformInterface.MainSurface.Display != null)
|
||||
{
|
||||
_platformInterface.MainSurface.Display.Presented -= Window_Presented;
|
||||
}
|
||||
|
||||
_currentImage?.Put();
|
||||
_currentImage = null;
|
||||
}
|
||||
|
||||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnAttachedToVisualTree(e);
|
||||
|
||||
_platformInterface.MainSurface.Display.Presented += Window_Presented;
|
||||
}
|
||||
|
||||
private void Window_Presented(object sender, EventArgs e)
|
||||
{
|
||||
_platformInterface.MainSurface.Device.QueueWaitIdle();
|
||||
_currentImage?.Put();
|
||||
_currentImage = null;
|
||||
}
|
||||
|
||||
public override void Render(DrawingContext context)
|
||||
{
|
||||
base.Render(context);
|
||||
}
|
||||
|
||||
protected override void CreateWindow()
|
||||
{
|
||||
}
|
||||
@@ -51,12 +89,29 @@ namespace Ryujinx.Ava.Ui.Controls
|
||||
|
||||
internal override void Present(object image)
|
||||
{
|
||||
Dispatcher.UIThread.InvokeAsync(() =>
|
||||
{
|
||||
Image = image;
|
||||
}).Wait();
|
||||
Image = image;
|
||||
|
||||
QueueRender();
|
||||
_imagesInFlight.Enqueue((PresentImageInfo)image);
|
||||
|
||||
if (_imagesInFlight.Count > MaxImagesInFlight)
|
||||
{
|
||||
_imagesInFlight.TryDequeue(out _);
|
||||
}
|
||||
|
||||
Dispatcher.UIThread.Post(InvalidateVisual);
|
||||
}
|
||||
|
||||
private PresentImageInfo GetImage()
|
||||
{
|
||||
lock (_imagesInFlight)
|
||||
{
|
||||
if (!_imagesInFlight.TryDequeue(out _currentImage))
|
||||
{
|
||||
_currentImage = (PresentImageInfo)Image;
|
||||
}
|
||||
|
||||
return _currentImage;
|
||||
}
|
||||
}
|
||||
|
||||
private class VulkanDrawOperation : ICustomDrawOperation
|
||||
@@ -64,6 +119,7 @@ namespace Ryujinx.Ava.Ui.Controls
|
||||
public Rect Bounds { get; }
|
||||
|
||||
private readonly VulkanRendererControl _control;
|
||||
private bool _isDestroyed;
|
||||
|
||||
public VulkanDrawOperation(VulkanRendererControl control)
|
||||
{
|
||||
@@ -73,7 +129,12 @@ namespace Ryujinx.Ava.Ui.Controls
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_isDestroyed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_isDestroyed = true;
|
||||
}
|
||||
|
||||
public bool Equals(ICustomDrawOperation other)
|
||||
@@ -86,30 +147,33 @@ namespace Ryujinx.Ava.Ui.Controls
|
||||
return Bounds.Contains(p);
|
||||
}
|
||||
|
||||
public void Render(IDrawingContextImpl context)
|
||||
public unsafe void Render(IDrawingContextImpl context)
|
||||
{
|
||||
if (_control.Image == null || _control.RenderSize.Width == 0 || _control.RenderSize.Height == 0)
|
||||
if (_isDestroyed || _control.Image == null || _control.RenderSize.Width == 0 || _control.RenderSize.Height == 0 ||
|
||||
context is not ISkiaDrawingContextImpl skiaDrawingContextImpl)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var image = (PresentImageInfo)_control.Image;
|
||||
var image = _control.GetImage();
|
||||
|
||||
if (context is not ISkiaDrawingContextImpl skiaDrawingContextImpl)
|
||||
if (!image.State.IsValid)
|
||||
{
|
||||
_control._currentImage = null;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
_control._platformInterface.Device.QueueWaitIdle();
|
||||
|
||||
var gpu = AvaloniaLocator.Current.GetService<VulkanSkiaGpu>();
|
||||
|
||||
image.Get();
|
||||
|
||||
var imageInfo = new GRVkImageInfo()
|
||||
{
|
||||
CurrentQueueFamily = _control._platformInterface.PhysicalDevice.QueueFamilyIndex,
|
||||
Format = (uint)Format.R8G8B8A8Unorm,
|
||||
Image = image.Image.Handle,
|
||||
ImageLayout = (uint)ImageLayout.ColorAttachmentOptimal,
|
||||
ImageLayout = (uint)ImageLayout.TransferSrcOptimal,
|
||||
ImageTiling = (uint)ImageTiling.Optimal,
|
||||
ImageUsageFlags = (uint)(ImageUsageFlags.ImageUsageColorAttachmentBit
|
||||
| ImageUsageFlags.ImageUsageTransferSrcBit
|
||||
@@ -127,13 +191,15 @@ namespace Ryujinx.Ava.Ui.Controls
|
||||
};
|
||||
|
||||
using var backendTexture = new GRBackendRenderTarget(
|
||||
(int)_control.RenderSize.Width,
|
||||
(int)_control.RenderSize.Height,
|
||||
(int)image.Extent.Width,
|
||||
(int)image.Extent.Height,
|
||||
1,
|
||||
imageInfo);
|
||||
|
||||
var vulkan = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>();
|
||||
|
||||
using var surface = SKSurface.Create(
|
||||
gpu.GrContext,
|
||||
skiaDrawingContextImpl.GrContext,
|
||||
backendTexture,
|
||||
GRSurfaceOrigin.TopLeft,
|
||||
SKColorType.Rgba8888);
|
||||
@@ -143,10 +209,11 @@ namespace Ryujinx.Ava.Ui.Controls
|
||||
return;
|
||||
}
|
||||
|
||||
var rect = new Rect(new Point(), _control.RenderSize);
|
||||
var rect = new Rect(new Point(), new Size(image.Extent.Width, image.Extent.Height));
|
||||
|
||||
using var snapshot = surface.Snapshot();
|
||||
skiaDrawingContextImpl.SkCanvas.DrawImage(snapshot, rect.ToSKRect(), _control.Bounds.ToSKRect(), new SKPaint());
|
||||
skiaDrawingContextImpl.SkCanvas.DrawImage(snapshot, rect.ToSKRect(), _control.Bounds.ToSKRect(),
|
||||
new SKPaint());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@ using Avalonia.Controls;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Svg.Skia;
|
||||
using Avalonia.Threading;
|
||||
using Avalonia.VisualTree;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Input;
|
||||
using Ryujinx.Ava.Ui.Controls;
|
||||
@@ -24,7 +23,6 @@ using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using ConfigGamepadInputId = Ryujinx.Common.Configuration.Hid.Controller.GamepadInputId;
|
||||
using ConfigStickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
|
||||
|
@@ -38,6 +38,8 @@ namespace Ryujinx.Ava.Ui.ViewModels
|
||||
{
|
||||
internal class MainWindowViewModel : BaseModel
|
||||
{
|
||||
private const int HotKeyPressDelayMs = 500;
|
||||
|
||||
private readonly MainWindow _owner;
|
||||
private ObservableCollection<ApplicationData> _applications;
|
||||
private string _aspectStatusText;
|
||||
@@ -54,6 +56,7 @@ namespace Ryujinx.Ava.Ui.ViewModels
|
||||
private bool _isLoading;
|
||||
private int _progressMaximum;
|
||||
private int _progressValue;
|
||||
private long _lastFullscreenToggle = Environment.TickCount64;
|
||||
private bool _showLoadProgress;
|
||||
private bool _showMenuAndStatusBar = true;
|
||||
private bool _showStatusSeparator;
|
||||
@@ -929,6 +932,13 @@ namespace Ryujinx.Ava.Ui.ViewModels
|
||||
|
||||
public void ToggleFullscreen()
|
||||
{
|
||||
if (Environment.TickCount64 - _lastFullscreenToggle < HotKeyPressDelayMs)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_lastFullscreenToggle = Environment.TickCount64;
|
||||
|
||||
WindowState state = _owner.WindowState;
|
||||
|
||||
if (state == WindowState.FullScreen)
|
||||
@@ -1085,6 +1095,11 @@ namespace Ryujinx.Ava.Ui.ViewModels
|
||||
{
|
||||
selection.Favorite = !selection.Favorite;
|
||||
|
||||
_owner.ApplicationLibrary.LoadAndSaveMetaData(selection.TitleId, appMetadata =>
|
||||
{
|
||||
appMetadata.Favorite = selection.Favorite;
|
||||
});
|
||||
|
||||
RefreshView();
|
||||
}
|
||||
}
|
||||
|
@@ -48,6 +48,11 @@ namespace Ryujinx.Ava.Ui.ViewModels
|
||||
private int _graphicsBackendMultithreadingIndex;
|
||||
private float _previousVolumeLevel;
|
||||
private float _volume;
|
||||
private bool _isVulkanAvailable = true;
|
||||
private bool _directoryChanged = false;
|
||||
private List<string> _gpuIds = new List<string>();
|
||||
private KeyboardHotkeys _keyboardHotkeys;
|
||||
private int _graphicsBackendIndex;
|
||||
|
||||
public int ResolutionScale
|
||||
{
|
||||
@@ -97,6 +102,28 @@ namespace Ryujinx.Ava.Ui.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsVulkanAvailable
|
||||
{
|
||||
get => _isVulkanAvailable;
|
||||
set
|
||||
{
|
||||
_isVulkanAvailable = value;
|
||||
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public bool DirectoryChanged
|
||||
{
|
||||
get => _directoryChanged;
|
||||
set
|
||||
{
|
||||
_directoryChanged = value;
|
||||
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public bool EnableDiscordIntegration { get; set; }
|
||||
public bool CheckUpdatesOnStart { get; set; }
|
||||
public bool ShowConfirmExit { get; set; }
|
||||
@@ -143,10 +170,10 @@ namespace Ryujinx.Ava.Ui.ViewModels
|
||||
public int BaseStyleIndex { get; set; }
|
||||
public int GraphicsBackendIndex
|
||||
{
|
||||
get => graphicsBackendIndex;
|
||||
get => _graphicsBackendIndex;
|
||||
set
|
||||
{
|
||||
graphicsBackendIndex = value;
|
||||
_graphicsBackendIndex = value;
|
||||
OnPropertyChanged();
|
||||
OnPropertyChanged(nameof(IsVulkanSelected));
|
||||
}
|
||||
@@ -170,14 +197,9 @@ namespace Ryujinx.Ava.Ui.ViewModels
|
||||
public DateTimeOffset DateOffset { get; set; }
|
||||
public TimeSpan TimeOffset { get; set; }
|
||||
public AvaloniaList<TimeZone> TimeZones { get; set; }
|
||||
|
||||
public AvaloniaList<string> GameDirectories { get; set; }
|
||||
public ObservableCollection<ComboBoxItem> AvailableGpus { get; set; }
|
||||
|
||||
private KeyboardHotkeys _keyboardHotkeys;
|
||||
private int graphicsBackendIndex;
|
||||
private List<string> _gpuIds = new List<string>();
|
||||
|
||||
public KeyboardHotkeys KeyboardHotkeys
|
||||
{
|
||||
get => _keyboardHotkeys;
|
||||
@@ -233,20 +255,31 @@ namespace Ryujinx.Ava.Ui.ViewModels
|
||||
if (!Program.UseVulkan)
|
||||
{
|
||||
var devices = VulkanRenderer.GetPhysicalDevices();
|
||||
foreach (var device in devices)
|
||||
|
||||
if (devices.Length == 0)
|
||||
{
|
||||
_gpuIds.Add(device.Id);
|
||||
names.Add($"{device.Name} {(device.IsDiscrete ? "(dGpu)" : "")}");
|
||||
IsVulkanAvailable = false;
|
||||
GraphicsBackendIndex = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var device in devices)
|
||||
{
|
||||
_gpuIds.Add(device.Id);
|
||||
names.Add($"{device.Name} {(device.IsDiscrete ? "(dGPU)" : "")}");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var device in VulkanPhysicalDevice.SuitableDevices)
|
||||
{
|
||||
_gpuIds.Add(VulkanInitialization.StringFromIdPair(device.Value.VendorID, device.Value.DeviceID));
|
||||
_gpuIds.Add(
|
||||
VulkanInitialization.StringFromIdPair(device.Value.VendorID, device.Value.DeviceID));
|
||||
var value = device.Value;
|
||||
var name = value.DeviceName;
|
||||
names.Add($"{Marshal.PtrToStringAnsi((IntPtr)name)} {(device.Value.DeviceType == PhysicalDeviceType.DiscreteGpu ? "(dGpu)" : "")}");
|
||||
names.Add(
|
||||
$"{Marshal.PtrToStringAnsi((IntPtr)name)} {(device.Value.DeviceType == PhysicalDeviceType.DiscreteGpu ? "(dGPU)" : "")}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -376,10 +409,14 @@ namespace Ryujinx.Ava.Ui.ViewModels
|
||||
|
||||
public async Task SaveSettings()
|
||||
{
|
||||
List<string> gameDirs = new List<string>(GameDirectories);
|
||||
|
||||
ConfigurationState config = ConfigurationState.Instance;
|
||||
|
||||
if (_directoryChanged)
|
||||
{
|
||||
List<string> gameDirs = new List<string>(GameDirectories);
|
||||
config.Ui.GameDirs.Value = gameDirs;
|
||||
}
|
||||
|
||||
if (_validTzRegions.Contains(TimeZone))
|
||||
{
|
||||
config.System.TimeZone.Value = TimeZone;
|
||||
@@ -444,7 +481,6 @@ namespace Ryujinx.Ava.Ui.ViewModels
|
||||
|
||||
config.System.SystemTimeOffset.Value = systemTimeOffset.Seconds;
|
||||
config.Graphics.ShadersDumpPath.Value = ShaderDumpPath;
|
||||
config.Ui.GameDirs.Value = gameDirs;
|
||||
config.System.FsGlobalAccessLogMode.Value = FsGlobalAccessLogMode;
|
||||
config.System.MemoryManagerMode.Value = (MemoryManagerMode)MemoryMode;
|
||||
|
||||
|
@@ -1,5 +1,4 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Threading;
|
||||
|
@@ -1,4 +1,3 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Interactivity;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Ui.Models;
|
||||
|
@@ -1,11 +1,9 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Collections;
|
||||
using Avalonia.Collections;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Ui.Models;
|
||||
using Ryujinx.HLE.FileSystem;
|
||||
using Ryujinx.HLE.HOS;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
|
@@ -12,7 +12,6 @@ using Ryujinx.Ava.Ui.Applet;
|
||||
using Ryujinx.Ava.Ui.Controls;
|
||||
using Ryujinx.Ava.Ui.Models;
|
||||
using Ryujinx.Ava.Ui.ViewModels;
|
||||
using Ryujinx.Ava.Ui.Vulkan;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Graphics.Gpu;
|
||||
@@ -27,7 +26,6 @@ using Ryujinx.Ui.Common.Configuration;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -656,7 +654,12 @@ namespace Ryujinx.Ava.Ui.Windows
|
||||
{
|
||||
AppHost = null;
|
||||
|
||||
Dispatcher.UIThread.Post(Close);
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
MainContent = null;
|
||||
|
||||
Close();
|
||||
});
|
||||
};
|
||||
AppHost?.Stop();
|
||||
|
||||
|
@@ -519,7 +519,7 @@
|
||||
HorizontalContentAlignment="Left"
|
||||
ToolTip.Tip="{locale:Locale SettingsTabGraphicsBackendTooltip}"
|
||||
SelectedIndex="{Binding GraphicsBackendIndex}">
|
||||
<ComboBoxItem>
|
||||
<ComboBoxItem IsVisible="{Binding IsVulkanAvailable}">
|
||||
<TextBlock Text="Vulkan" />
|
||||
</ComboBoxItem>
|
||||
<ComboBoxItem>
|
||||
|
@@ -162,6 +162,7 @@ namespace Ryujinx.Ava.Ui.Windows
|
||||
if (!string.IsNullOrWhiteSpace(path) && Directory.Exists(path) && !ViewModel.GameDirectories.Contains(path))
|
||||
{
|
||||
ViewModel.GameDirectories.Add(path);
|
||||
ViewModel.DirectoryChanged = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -170,6 +171,7 @@ namespace Ryujinx.Ava.Ui.Windows
|
||||
if (!string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
ViewModel.GameDirectories.Add(path);
|
||||
ViewModel.DirectoryChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -181,6 +183,7 @@ namespace Ryujinx.Ava.Ui.Windows
|
||||
foreach (string path in selected)
|
||||
{
|
||||
ViewModel.GameDirectories.Remove(path);
|
||||
ViewModel.DirectoryChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,10 +235,12 @@ namespace Ryujinx.Ava.Ui.Windows
|
||||
|
||||
ControllerSettings?.SaveCurrentProfile();
|
||||
|
||||
if (Owner is MainWindow window)
|
||||
if (Owner is MainWindow window && ViewModel.DirectoryChanged)
|
||||
{
|
||||
window.ViewModel.LoadApplications();
|
||||
}
|
||||
|
||||
ViewModel.DirectoryChanged = false;
|
||||
}
|
||||
|
||||
protected override void OnClosed(EventArgs e)
|
||||
|
@@ -1,4 +1,3 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Collections;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Threading;
|
||||
@@ -18,7 +17,6 @@ using Ryujinx.HLE.FileSystem;
|
||||
using Ryujinx.HLE.HOS;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
@@ -1,5 +1,3 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Modules;
|
||||
using System;
|
||||
|
@@ -1,8 +1,6 @@
|
||||
using Ryujinx.Common.Configuration.Hid.Controller.Motion;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Text.Json.Serialization;
|
||||
using NotImplementedException = System.NotImplementedException;
|
||||
|
||||
namespace Ryujinx.Common.Configuration.Hid.Controller
|
||||
{
|
||||
|
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Common.GraphicsDriver.NVAPI
|
||||
{
|
||||
|
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace Ryujinx.Common.Logging
|
||||
{
|
||||
|
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Ryujinx.Common.Logging
|
||||
{
|
||||
|
@@ -87,7 +87,7 @@ namespace Ryujinx.Common.Memory
|
||||
/// Gets a span from the array.
|
||||
/// </summary>
|
||||
/// <returns>Span of the array</returns>
|
||||
public Span<T> ToSpan() => Length == 0 ? Span<T>.Empty : MemoryMarshal.CreateSpan(ref this[0], Length);
|
||||
public Span<T> AsSpan() => Length == 0 ? Span<T>.Empty : MemoryMarshal.CreateSpan(ref this[0], Length);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the array base pointer.
|
||||
|
@@ -83,7 +83,7 @@ namespace Ryujinx.Common.Memory.PartialUnmaps
|
||||
/// memory might be accessed but is unmapped. Users of the API must compensate for that by catching the
|
||||
/// access violation and retrying if it happened between the unmap and remap operation.
|
||||
/// This method can be used to decide if retrying in such cases is necessary or not.
|
||||
///
|
||||
///
|
||||
/// This version of the function is not used, but serves as a reference for the native
|
||||
/// implementation in ARMeilleure.
|
||||
/// </remarks>
|
||||
@@ -128,12 +128,12 @@ namespace Ryujinx.Common.Memory.PartialUnmaps
|
||||
const uint ExitCodeStillActive = 259;
|
||||
const int ThreadQueryInformation = 0x40;
|
||||
|
||||
Span<int> ids = LocalCounts.ThreadIds.ToSpan();
|
||||
Span<int> ids = LocalCounts.ThreadIds.AsSpan();
|
||||
|
||||
for (int i = 0; i < ids.Length; i++)
|
||||
{
|
||||
int id = ids[i];
|
||||
|
||||
|
||||
if (id != 0)
|
||||
{
|
||||
IntPtr handle = OpenThread(ThreadQueryInformation, false, (uint)id);
|
||||
|
@@ -7,8 +7,8 @@ namespace Ryujinx.Common.Memory
|
||||
{
|
||||
T _e0;
|
||||
public int Length => 1;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 1);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 1);
|
||||
}
|
||||
public struct Array2<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -17,8 +17,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array1<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 2;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 2);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 2);
|
||||
}
|
||||
public struct Array3<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -27,8 +27,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array2<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 3;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 3);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 3);
|
||||
}
|
||||
public struct Array4<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -37,8 +37,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array3<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 4;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 4);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 4);
|
||||
}
|
||||
public struct Array5<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -47,8 +47,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array4<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 5;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 5);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 5);
|
||||
}
|
||||
public struct Array6<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -57,8 +57,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array5<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 6;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 6);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 6);
|
||||
}
|
||||
public struct Array7<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -67,8 +67,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array6<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 7;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 7);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 7);
|
||||
}
|
||||
public struct Array8<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -77,8 +77,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array7<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 8;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 8);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 8);
|
||||
}
|
||||
public struct Array9<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -87,8 +87,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array8<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 9;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 9);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 9);
|
||||
}
|
||||
public struct Array10<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -97,8 +97,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array9<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 10;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 10);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 10);
|
||||
}
|
||||
public struct Array11<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -107,8 +107,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array10<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 11;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 11);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 11);
|
||||
}
|
||||
public struct Array12<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -117,8 +117,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array11<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 12;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 12);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 12);
|
||||
}
|
||||
public struct Array13<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -127,8 +127,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array12<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 13;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 13);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 13);
|
||||
}
|
||||
public struct Array14<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -137,8 +137,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array13<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 14;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 14);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 14);
|
||||
}
|
||||
public struct Array15<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -147,8 +147,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array14<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 15;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 15);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 15);
|
||||
}
|
||||
public struct Array16<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -157,8 +157,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array15<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 16;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 16);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 16);
|
||||
}
|
||||
public struct Array17<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -167,8 +167,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array16<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 17;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 17);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 17);
|
||||
}
|
||||
public struct Array18<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -177,8 +177,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array17<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 18;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 18);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 18);
|
||||
}
|
||||
public struct Array19<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -187,8 +187,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array18<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 19;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 19);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 19);
|
||||
}
|
||||
public struct Array20<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -197,8 +197,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array19<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 20;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 20);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 20);
|
||||
}
|
||||
public struct Array21<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -207,8 +207,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array20<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 21;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 21);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 21);
|
||||
}
|
||||
public struct Array22<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -217,8 +217,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array21<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 22;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 22);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 22);
|
||||
}
|
||||
public struct Array23<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -227,8 +227,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array22<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 23;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 23);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 23);
|
||||
}
|
||||
public struct Array24<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -237,8 +237,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array23<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 24;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 24);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 24);
|
||||
}
|
||||
public struct Array25<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -247,8 +247,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array24<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 25;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 25);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 25);
|
||||
}
|
||||
public struct Array26<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -257,8 +257,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array25<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 26;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 26);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 26);
|
||||
}
|
||||
public struct Array27<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -267,8 +267,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array26<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 27;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 27);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 27);
|
||||
}
|
||||
public struct Array28<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -277,8 +277,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array27<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 28;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 28);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 28);
|
||||
}
|
||||
public struct Array29<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -287,8 +287,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array28<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 29;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 29);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 29);
|
||||
}
|
||||
public struct Array30<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -297,8 +297,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array29<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 30;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 30);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 30);
|
||||
}
|
||||
public struct Array31<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -307,8 +307,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array30<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 31;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 31);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 31);
|
||||
}
|
||||
public struct Array32<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -317,8 +317,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array31<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 32;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 32);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 32);
|
||||
}
|
||||
public struct Array33<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -327,8 +327,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array32<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 33;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 33);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 33);
|
||||
}
|
||||
public struct Array34<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -337,8 +337,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array33<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 34;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 34);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 34);
|
||||
}
|
||||
public struct Array35<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -347,8 +347,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array34<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 35;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 35);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 35);
|
||||
}
|
||||
public struct Array36<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -357,8 +357,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array35<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 36;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 36);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 36);
|
||||
}
|
||||
public struct Array37<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -367,8 +367,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array36<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 37;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 37);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 37);
|
||||
}
|
||||
public struct Array38<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -377,8 +377,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array37<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 38;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 38);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 38);
|
||||
}
|
||||
public struct Array39<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -387,8 +387,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array38<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 39;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 39);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 39);
|
||||
}
|
||||
public struct Array40<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -397,8 +397,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array39<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 40;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 40);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 40);
|
||||
}
|
||||
public struct Array41<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -407,8 +407,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array40<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 41;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 41);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 41);
|
||||
}
|
||||
public struct Array42<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -417,8 +417,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array41<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 42;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 42);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 42);
|
||||
}
|
||||
public struct Array43<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -427,8 +427,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array42<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 43;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 43);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 43);
|
||||
}
|
||||
public struct Array44<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -437,8 +437,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array43<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 44;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 44);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 44);
|
||||
}
|
||||
public struct Array45<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -447,8 +447,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array44<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 45;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 45);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 45);
|
||||
}
|
||||
public struct Array46<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -457,8 +457,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array45<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 46;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 46);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 46);
|
||||
}
|
||||
public struct Array47<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -467,8 +467,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array46<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 47;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 47);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 47);
|
||||
}
|
||||
public struct Array48<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -477,8 +477,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array47<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 48;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 48);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 48);
|
||||
}
|
||||
public struct Array49<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -487,8 +487,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array48<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 49;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 49);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 49);
|
||||
}
|
||||
public struct Array50<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -497,8 +497,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array49<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 50;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 50);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 50);
|
||||
}
|
||||
public struct Array51<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -507,8 +507,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array50<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 51;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 51);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 51);
|
||||
}
|
||||
public struct Array52<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -517,8 +517,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array51<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 52;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 52);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 52);
|
||||
}
|
||||
public struct Array53<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -527,8 +527,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array52<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 53;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 53);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 53);
|
||||
}
|
||||
public struct Array54<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -537,8 +537,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array53<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 54;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 54);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 54);
|
||||
}
|
||||
public struct Array55<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -547,8 +547,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array54<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 55;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 55);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 55);
|
||||
}
|
||||
public struct Array56<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -557,8 +557,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array55<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 56;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 56);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 56);
|
||||
}
|
||||
public struct Array57<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -567,8 +567,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array56<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 57;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 57);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 57);
|
||||
}
|
||||
public struct Array58<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -577,8 +577,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array57<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 58;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 58);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 58);
|
||||
}
|
||||
public struct Array59<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -587,8 +587,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array58<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 59;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 59);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 59);
|
||||
}
|
||||
public struct Array60<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -597,8 +597,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array59<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 60;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 60);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 60);
|
||||
}
|
||||
public struct Array61<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -607,8 +607,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array60<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 61;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 61);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 61);
|
||||
}
|
||||
public struct Array62<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -617,8 +617,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array61<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 62;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 62);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 62);
|
||||
}
|
||||
public struct Array63<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -627,8 +627,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array62<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 63;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 63);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 63);
|
||||
}
|
||||
public struct Array64<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -637,8 +637,8 @@ namespace Ryujinx.Common.Memory
|
||||
Array63<T> _other;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 64;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 64);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 64);
|
||||
}
|
||||
public struct Array73<T> : IArray<T> where T : unmanaged
|
||||
{
|
||||
@@ -648,7 +648,7 @@ namespace Ryujinx.Common.Memory
|
||||
Array8<T> _other2;
|
||||
#pragma warning restore CS0169
|
||||
public int Length => 73;
|
||||
public ref T this[int index] => ref ToSpan()[index];
|
||||
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 73);
|
||||
public ref T this[int index] => ref AsSpan()[index];
|
||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 73);
|
||||
}
|
||||
}
|
||||
|
@@ -11,8 +11,8 @@ namespace Ryujinx.Common.Memory
|
||||
byte _element;
|
||||
|
||||
public int Length => Size;
|
||||
public ref byte this[int index] => ref ToSpan()[index];
|
||||
public Span<byte> ToSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
|
||||
public ref byte this[int index] => ref AsSpan()[index];
|
||||
public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Size = Size, Pack = 1)]
|
||||
@@ -23,8 +23,8 @@ namespace Ryujinx.Common.Memory
|
||||
byte _element;
|
||||
|
||||
public int Length => Size;
|
||||
public ref byte this[int index] => ref ToSpan()[index];
|
||||
public Span<byte> ToSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
|
||||
public ref byte this[int index] => ref AsSpan()[index];
|
||||
public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Size = Size, Pack = 1)]
|
||||
@@ -35,8 +35,8 @@ namespace Ryujinx.Common.Memory
|
||||
byte _element;
|
||||
|
||||
public int Length => Size;
|
||||
public ref byte this[int index] => ref ToSpan()[index];
|
||||
public Span<byte> ToSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
|
||||
public ref byte this[int index] => ref AsSpan()[index];
|
||||
public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Size = Size, Pack = 1)]
|
||||
@@ -47,8 +47,8 @@ namespace Ryujinx.Common.Memory
|
||||
byte _element;
|
||||
|
||||
public int Length => Size;
|
||||
public ref byte this[int index] => ref ToSpan()[index];
|
||||
public Span<byte> ToSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
|
||||
public ref byte this[int index] => ref AsSpan()[index];
|
||||
public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Size = Size, Pack = 1)]
|
||||
@@ -59,8 +59,8 @@ namespace Ryujinx.Common.Memory
|
||||
byte _element;
|
||||
|
||||
public int Length => Size;
|
||||
public ref byte this[int index] => ref ToSpan()[index];
|
||||
public Span<byte> ToSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
|
||||
public ref byte this[int index] => ref AsSpan()[index];
|
||||
public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Size = Size, Pack = 1)]
|
||||
@@ -71,7 +71,7 @@ namespace Ryujinx.Common.Memory
|
||||
byte _element;
|
||||
|
||||
public int Length => Size;
|
||||
public ref byte this[int index] => ref ToSpan()[index];
|
||||
public Span<byte> ToSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
|
||||
public ref byte this[int index] => ref AsSpan()[index];
|
||||
public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@ using System;
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
|
||||
namespace Ryujinx.Common.System
|
||||
{
|
||||
|
@@ -24,7 +24,7 @@ namespace Ryujinx.Common.SystemInfo
|
||||
if (sysctlbyname("hw.memsize", ref totalRAM) != 0) // Bytes
|
||||
{
|
||||
totalRAM = 0;
|
||||
};
|
||||
}
|
||||
|
||||
CpuName = $"{cpuName} ; {LogicalCoreCount} logical";
|
||||
RamTotal = totalRAM;
|
||||
|
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Management;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
|
@@ -1,4 +1,3 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Ryujinx.Common
|
||||
|
@@ -56,7 +56,6 @@ namespace Ryujinx.Graphics.GAL
|
||||
D32Float,
|
||||
D24UnormS8Uint,
|
||||
D32FloatS8Uint,
|
||||
R8G8B8X8Srgb,
|
||||
R8G8B8A8Srgb,
|
||||
R4G4Unorm,
|
||||
R4G4B4A4Unorm,
|
||||
@@ -83,8 +82,10 @@ namespace Ryujinx.Graphics.GAL
|
||||
Bc6HUfloat,
|
||||
Etc2RgbUnorm,
|
||||
Etc2RgbaUnorm,
|
||||
Etc2RgbPtaUnorm,
|
||||
Etc2RgbSrgb,
|
||||
Etc2RgbaSrgb,
|
||||
Etc2RgbPtaSrgb,
|
||||
R8Uscaled,
|
||||
R8Sscaled,
|
||||
R16Uscaled,
|
||||
@@ -113,18 +114,6 @@ namespace Ryujinx.Graphics.GAL
|
||||
R10G10B10A2Sint,
|
||||
R10G10B10A2Uscaled,
|
||||
R10G10B10A2Sscaled,
|
||||
R8G8B8X8Unorm,
|
||||
R8G8B8X8Snorm,
|
||||
R8G8B8X8Uint,
|
||||
R8G8B8X8Sint,
|
||||
R16G16B16X16Float,
|
||||
R16G16B16X16Unorm,
|
||||
R16G16B16X16Snorm,
|
||||
R16G16B16X16Uint,
|
||||
R16G16B16X16Sint,
|
||||
R32G32B32X32Float,
|
||||
R32G32B32X32Uint,
|
||||
R32G32B32X32Sint,
|
||||
Astc4x4Unorm,
|
||||
Astc5x4Unorm,
|
||||
Astc5x5Unorm,
|
||||
@@ -154,12 +143,9 @@ namespace Ryujinx.Graphics.GAL
|
||||
Astc12x10Srgb,
|
||||
Astc12x12Srgb,
|
||||
B5G6R5Unorm,
|
||||
B5G5R5X1Unorm,
|
||||
B5G5R5A1Unorm,
|
||||
A1B5G5R5Unorm,
|
||||
B8G8R8X8Unorm,
|
||||
B8G8R8A8Unorm,
|
||||
B8G8R8X8Srgb,
|
||||
B8G8R8A8Srgb
|
||||
}
|
||||
|
||||
@@ -272,7 +258,6 @@ namespace Ryujinx.Graphics.GAL
|
||||
case Format.R8Snorm:
|
||||
case Format.R8Sint:
|
||||
case Format.R8Uint:
|
||||
case Format.B5G5R5X1Unorm:
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -357,11 +342,8 @@ namespace Ryujinx.Graphics.GAL
|
||||
switch (format)
|
||||
{
|
||||
case Format.B5G6R5Unorm:
|
||||
case Format.B5G5R5X1Unorm:
|
||||
case Format.B5G5R5A1Unorm:
|
||||
case Format.B8G8R8X8Unorm:
|
||||
case Format.B8G8R8A8Unorm:
|
||||
case Format.B8G8R8X8Srgb:
|
||||
case Format.B8G8R8A8Srgb:
|
||||
return true;
|
||||
}
|
||||
@@ -412,9 +394,6 @@ namespace Ryujinx.Graphics.GAL
|
||||
case Format.R16G16B16A16Uint:
|
||||
case Format.R32G32B32A32Uint:
|
||||
case Format.R10G10B10A2Uint:
|
||||
case Format.R8G8B8X8Uint:
|
||||
case Format.R16G16B16X16Uint:
|
||||
case Format.R32G32B32X32Uint:
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -443,9 +422,6 @@ namespace Ryujinx.Graphics.GAL
|
||||
case Format.R16G16B16A16Sint:
|
||||
case Format.R32G32B32A32Sint:
|
||||
case Format.R10G10B10A2Sint:
|
||||
case Format.R8G8B8X8Sint:
|
||||
case Format.R16G16B16X16Sint:
|
||||
case Format.R32G32B32X32Sint:
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Ryujinx.Graphics.GAL
|
||||
namespace Ryujinx.Graphics.GAL
|
||||
{
|
||||
public struct HardwareInfo
|
||||
{
|
||||
|
@@ -1,5 +1,4 @@
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Graphics.Shader;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.GAL
|
||||
|
@@ -7,5 +7,7 @@ namespace Ryujinx.Graphics.GAL
|
||||
void Present(ITexture texture, ImageCrop crop, Action<object> swapBuffersCallback);
|
||||
|
||||
void SetSize(int width, int height);
|
||||
|
||||
void ChangeVSyncMode(bool vsyncEnabled);
|
||||
}
|
||||
}
|
||||
|
@@ -13,13 +13,13 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands
|
||||
public void Set(int vertices, ReadOnlySpan<float> defaultOuterLevel, ReadOnlySpan<float> defaultInnerLevel)
|
||||
{
|
||||
_vertices = vertices;
|
||||
defaultOuterLevel.CopyTo(_defaultOuterLevel.ToSpan());
|
||||
defaultInnerLevel.CopyTo(_defaultInnerLevel.ToSpan());
|
||||
defaultOuterLevel.CopyTo(_defaultOuterLevel.AsSpan());
|
||||
defaultInnerLevel.CopyTo(_defaultInnerLevel.AsSpan());
|
||||
}
|
||||
|
||||
public static void Run(ref SetPatchParametersCommand command, ThreadedRenderer threaded, IRenderer renderer)
|
||||
{
|
||||
renderer.Pipeline.SetPatchParameters(command._vertices, command._defaultOuterLevel.ToSpan(), command._defaultInnerLevel.ToSpan());
|
||||
renderer.Pipeline.SetPatchParameters(command._vertices, command._defaultOuterLevel.AsSpan(), command._defaultInnerLevel.AsSpan());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,5 @@
|
||||
using Ryujinx.Graphics.GAL.Multithreading.Model;
|
||||
using System;
|
||||
using System.Buffers;
|
||||
|
||||
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
|
||||
{
|
||||
|
@@ -1,6 +1,5 @@
|
||||
using Ryujinx.Graphics.GAL.Multithreading.Model;
|
||||
using System;
|
||||
using System.Buffers;
|
||||
|
||||
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
|
||||
{
|
||||
|
@@ -1,5 +1,4 @@
|
||||
using Ryujinx.Graphics.GAL.Multithreading.Model;
|
||||
using Ryujinx.Graphics.Shader;
|
||||
|
||||
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
|
||||
{
|
||||
|
@@ -1,6 +1,4 @@
|
||||
using System.Linq;
|
||||
|
||||
namespace Ryujinx.Graphics.GAL.Multithreading.Resources.Programs
|
||||
namespace Ryujinx.Graphics.GAL.Multithreading.Resources.Programs
|
||||
{
|
||||
class SourceProgramRequest : IProgramRequest
|
||||
{
|
||||
|
@@ -30,5 +30,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
||||
{
|
||||
_impl.Window.SetSize(width, height);
|
||||
}
|
||||
|
||||
public void ChangeVSyncMode(bool vsyncEnabled) { }
|
||||
}
|
||||
}
|
||||
|
@@ -66,7 +66,7 @@ namespace Ryujinx.Graphics.GAL
|
||||
public void SetVertexAttribs(ReadOnlySpan<VertexAttribDescriptor> vertexAttribs)
|
||||
{
|
||||
VertexAttribCount = vertexAttribs.Length;
|
||||
vertexAttribs.CopyTo(VertexAttribs.ToSpan());
|
||||
vertexAttribs.CopyTo(VertexAttribs.AsSpan());
|
||||
}
|
||||
|
||||
public void SetLogicOpState(bool enable, LogicalOp op)
|
||||
|
@@ -65,12 +65,12 @@ namespace Ryujinx.Graphics.GAL
|
||||
|
||||
public void UpdateRenderScale(ReadOnlySpan<Vector4<float>> data, int offset, int count)
|
||||
{
|
||||
UpdateGenericField(SupportBuffer.GraphicsRenderScaleOffset, data, Data.RenderScale.ToSpan(), offset, count);
|
||||
UpdateGenericField(SupportBuffer.GraphicsRenderScaleOffset, data, Data.RenderScale.AsSpan(), offset, count);
|
||||
}
|
||||
|
||||
public void UpdateFragmentIsBgra(ReadOnlySpan<Vector4<int>> data, int offset, int count)
|
||||
{
|
||||
UpdateGenericField(SupportBuffer.FragmentIsBgraOffset, data, Data.FragmentIsBgra.ToSpan(), offset, count);
|
||||
UpdateGenericField(SupportBuffer.FragmentIsBgraOffset, data, Data.FragmentIsBgra.AsSpan(), offset, count);
|
||||
}
|
||||
|
||||
public void UpdateViewportInverse(Vector4<float> data)
|
||||
|
@@ -1,6 +1,5 @@
|
||||
using Ryujinx.Graphics.Device;
|
||||
using Ryujinx.Graphics.Gpu.Engine.GPFifo;
|
||||
using Ryujinx.Graphics.Gpu.Memory;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Gpu.Engine.MME
|
||||
|
@@ -12,7 +12,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||
#pragma warning disable CS0169
|
||||
private uint _e0;
|
||||
#pragma warning restore CS0169
|
||||
public ref uint this[int index] => ref ToSpan()[index];
|
||||
public Span<uint> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 256);
|
||||
public ref uint this[int index] => ref AsSpan()[index];
|
||||
public Span<uint> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 256);
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,6 @@
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Graphics.Gpu.Engine.Types;
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
{
|
||||
|
@@ -42,6 +42,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
private uint _prevFirstVertex;
|
||||
private bool _prevTfEnable;
|
||||
|
||||
private uint _prevRtNoAlphaMask;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the state updater.
|
||||
/// </summary>
|
||||
@@ -331,8 +333,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
|
||||
_context.Renderer.Pipeline.SetPatchParameters(
|
||||
_state.State.PatchVertices,
|
||||
_state.State.TessOuterLevel.ToSpan(),
|
||||
_state.State.TessInnerLevel.ToSpan());
|
||||
_state.State.TessOuterLevel.AsSpan(),
|
||||
_state.State.TessInnerLevel.AsSpan());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -398,6 +400,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
int clipRegionHeight = int.MaxValue;
|
||||
|
||||
bool changedScale = false;
|
||||
uint rtNoAlphaMask = 0;
|
||||
|
||||
for (int index = 0; index < Constants.TotalRenderTargets; index++)
|
||||
{
|
||||
@@ -412,6 +415,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
continue;
|
||||
}
|
||||
|
||||
if (colorState.Format.NoAlpha())
|
||||
{
|
||||
rtNoAlphaMask |= 1u << index;
|
||||
}
|
||||
|
||||
Image.Texture color = memoryManager.Physical.TextureCache.FindOrCreateTexture(
|
||||
memoryManager,
|
||||
colorState,
|
||||
@@ -485,6 +493,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
}
|
||||
|
||||
_channel.TextureManager.SetClipRegion(clipRegionWidth, clipRegionHeight);
|
||||
|
||||
if (useControl && _prevRtNoAlphaMask != rtNoAlphaMask)
|
||||
{
|
||||
_prevRtNoAlphaMask = rtNoAlphaMask;
|
||||
|
||||
UpdateBlendState();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1056,44 +1071,80 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
bool blendIndependent = _state.State.BlendIndependent;
|
||||
ColorF blendConstant = _state.State.BlendConstant;
|
||||
|
||||
for (int index = 0; index < Constants.TotalRenderTargets; index++)
|
||||
if (blendIndependent)
|
||||
{
|
||||
BlendDescriptor descriptor;
|
||||
|
||||
if (blendIndependent)
|
||||
for (int index = 0; index < Constants.TotalRenderTargets; index++)
|
||||
{
|
||||
bool enable = _state.State.BlendEnable[index];
|
||||
var blend = _state.State.BlendState[index];
|
||||
|
||||
descriptor = new BlendDescriptor(
|
||||
var descriptor = new BlendDescriptor(
|
||||
enable,
|
||||
blendConstant,
|
||||
blend.ColorOp,
|
||||
blend.ColorSrcFactor,
|
||||
blend.ColorDstFactor,
|
||||
FilterBlendFactor(blend.ColorSrcFactor, index),
|
||||
FilterBlendFactor(blend.ColorDstFactor, index),
|
||||
blend.AlphaOp,
|
||||
blend.AlphaSrcFactor,
|
||||
blend.AlphaDstFactor);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool enable = _state.State.BlendEnable[0];
|
||||
var blend = _state.State.BlendStateCommon;
|
||||
FilterBlendFactor(blend.AlphaSrcFactor, index),
|
||||
FilterBlendFactor(blend.AlphaDstFactor, index));
|
||||
|
||||
descriptor = new BlendDescriptor(
|
||||
enable,
|
||||
blendConstant,
|
||||
blend.ColorOp,
|
||||
blend.ColorSrcFactor,
|
||||
blend.ColorDstFactor,
|
||||
blend.AlphaOp,
|
||||
blend.AlphaSrcFactor,
|
||||
blend.AlphaDstFactor);
|
||||
_pipeline.BlendDescriptors[index] = descriptor;
|
||||
_context.Renderer.Pipeline.SetBlendState(index, descriptor);
|
||||
}
|
||||
|
||||
_pipeline.BlendDescriptors[index] = descriptor;
|
||||
_context.Renderer.Pipeline.SetBlendState(index, descriptor);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool enable = _state.State.BlendEnable[0];
|
||||
var blend = _state.State.BlendStateCommon;
|
||||
|
||||
var descriptor = new BlendDescriptor(
|
||||
enable,
|
||||
blendConstant,
|
||||
blend.ColorOp,
|
||||
FilterBlendFactor(blend.ColorSrcFactor, 0),
|
||||
FilterBlendFactor(blend.ColorDstFactor, 0),
|
||||
blend.AlphaOp,
|
||||
FilterBlendFactor(blend.AlphaSrcFactor, 0),
|
||||
FilterBlendFactor(blend.AlphaDstFactor, 0));
|
||||
|
||||
for (int index = 0; index < Constants.TotalRenderTargets; index++)
|
||||
{
|
||||
_pipeline.BlendDescriptors[index] = descriptor;
|
||||
_context.Renderer.Pipeline.SetBlendState(index, descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a blend factor for the color target currently.
|
||||
/// This will return <paramref name="factor"/> unless the target format has no alpha component,
|
||||
/// in which case it will replace destination alpha factor with a constant factor of one or zero.
|
||||
/// </summary>
|
||||
/// <param name="factor">Input factor</param>
|
||||
/// <param name="index">Color target index</param>
|
||||
/// <returns>New blend factor</returns>
|
||||
private BlendFactor FilterBlendFactor(BlendFactor factor, int index)
|
||||
{
|
||||
// If any color target format without alpha is being used, we need to make sure that
|
||||
// if blend is active, it will not use destination alpha as a factor.
|
||||
// That is required because RGBX formats are emulated using host RGBA formats.
|
||||
|
||||
if (_state.State.RtColorState[index].Format.NoAlpha())
|
||||
{
|
||||
switch (factor)
|
||||
{
|
||||
case BlendFactor.DstAlpha:
|
||||
case BlendFactor.DstAlphaGl:
|
||||
factor = BlendFactor.One;
|
||||
break;
|
||||
case BlendFactor.OneMinusDstAlpha:
|
||||
case BlendFactor.OneMinusDstAlphaGl:
|
||||
factor = BlendFactor.Zero;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return factor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1242,6 +1293,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
_channel.BufferManager.SetGraphicsUniformBufferBindings(stage, info.CBuffers);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current texture pool state.
|
||||
/// </summary>
|
||||
/// <returns>Texture pool state</returns>
|
||||
private GpuChannelPoolState GetPoolState()
|
||||
{
|
||||
return new GpuChannelPoolState(
|
||||
@@ -1262,10 +1317,12 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
|
||||
for (int location = 0; location < attributeTypes.Length; location++)
|
||||
{
|
||||
attributeTypes[location] = vertexAttribState[location].UnpackType() switch
|
||||
VertexAttribType type = vertexAttribState[location].UnpackType();
|
||||
|
||||
attributeTypes[location] = type switch
|
||||
{
|
||||
3 => AttributeType.Sint,
|
||||
4 => AttributeType.Uint,
|
||||
VertexAttribType.Sint => AttributeType.Sint,
|
||||
VertexAttribType.Uint => AttributeType.Uint,
|
||||
_ => AttributeType.Float
|
||||
};
|
||||
}
|
||||
@@ -1286,6 +1343,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
ref attributeTypes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the depth mode that is currently being used (zero to one or minus one to one).
|
||||
/// </summary>
|
||||
/// <returns>Current depth mode</returns>
|
||||
private DepthMode GetDepthMode()
|
||||
{
|
||||
ref var transform = ref _state.State.ViewportTransform[0];
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user