Compare commits

...

18 Commits

Author SHA1 Message Date
RKennedy9064
b994dafe7a Update PPTC dialog text to match label and tooltip (#3618)
* Update PPTC dialog text to match label and tooltip

* Update to requested text

* Reverting spaces

* Adding newline back in
2022-08-24 08:25:49 +00:00
MutantAura
54421760c3 Check if game directories have been updated before refreshing GUI (#3607)
* Check if game directories have been updated before refreshing list on save.

* Cleanup spacing

* Add Avalonia and reset value after saving

* Fix Avalonia

* Fix multiple directories not being added in GTK
2022-08-21 13:07:28 +00:00
gdkchan
88a0e720cb Use RGBA16 vertex format if RGB16 is not supported on Vulkan (#3552)
* Use RGBA16 vertex format if RGB16 is not supported on Vulkan

* Catch all shader compilation exceptions
2022-08-20 16:20:27 -03:00
EmulationFanatic
53cc9e0561 Change 'Purge PPTC Cache' label & tooltip to reflect function behavior (#3601)
* Change PPTC purge label & tooltip

* Change Avalonia labels
2022-08-19 23:39:59 +00:00
Nicholas Rodine
7defc59b9d A few minor documentation fixes. (#3599)
* A few minor documentation fixes.

* Removed more invalid inheritdoc instances.
2022-08-19 18:21:06 -03:00
Nicholas Rodine
951700fdd8 Removed unused usings. (#3593)
* Removed unused usings.

* Added back using, now that it's used.

* Removed extra whitespace.
2022-08-18 18:04:54 +02:00
Nicholas Rodine
eb6430f103 Skipped over the last "Count" key explicitly, instead of relying on an exception. (#3595) 2022-08-18 02:00:27 +02:00
Nicholas Rodine
80a879cb44 Fix SpirV parse failure (#3597)
* Added .ToString overrides, to help diagnose and debug SpirV generated code.

* Added Spirv to team shared dictionary, so the word will not show up as a warning.

* Fixed bug where we were creating invalid constants (bool 0i and float 0i)

* Update Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Update Spv.Generator/Instruction.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Adjusted spacing to match style of the rest of the code.

* Added handler for FP64(double) as well, for undefined aggregate types.

* Made the operand labels a static dictionary, to avoid re-allocation on each call.
Replaced Contains/Get with a TryGetValue, to reduce the number of dictionary lookups.

* Added newline between AllOperands and ToString().

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2022-08-18 01:49:43 +02:00
Nicholas Rodine
2197f41506 Removed extra semicolons. (#3594) 2022-08-17 09:05:15 +02:00
Emmanuel Hansen
c8f9292bab Avalonia - Couple fixes and improvements to vulkan (#3483)
* drop split devices, rebase

* add fallback to opengl if vulkan is not available

* addressed review

* ensure present image references are incremented and decremented when necessary

* allow changing vsync for vulkan

* fix screenshot on avalonia vulkan

* save favorite when toggled

* improve sync between popups

* use separate devices for each new window

* fix crash when closing window

* addressed review

* don't create the main window with immediate mode

* change skia vk delegate to method

* update vulkan throwonerror

* addressed review
2022-08-16 16:32:37 +00:00
gdkchan
0ec933a615 Vulkan: Add ETC2 texture formats (#3576) 2022-08-16 15:42:42 +02:00
Ac_K
2135b6a51a am: Stub SetWirelessPriorityMode, SetWirelessPriorityMode and GetHdcpAuthenticationState (#3535)
This PR some calls in `am` service:
- ISelfController: SetWirelessPriorityMode, SaveCurrentScreenshot (Partially checked by RE).
- ICommonStateGetter: GetHdcpAuthenticationState

Close #1831 and close #3527
2022-08-15 11:12:08 +00:00
mageven
00e35d9bf6 ControllerApplet: Override player counts when SingleMode is set (#3571) 2022-08-15 09:46:08 +02:00
merry
6dfb6ccf8c PreAllocator: Check if instruction supports a Vex prefix in IsVexSameOperandDestSrc1 (#3587) 2022-08-14 17:35:08 -03:00
gdkchan
e87e8b012c Fix texture bindings using wrong sampler pool in some cases (#3583) 2022-08-14 14:00:30 -03:00
gdkchan
e8f1ca8427 OpenGL: Limit vertex buffer range for non-indexed draws (#3542)
* Limit vertex buffer range for non-indexed draws

* Fix typo
2022-08-11 20:21:56 -03:00
gdkchan
ad47bd2d4e Fix blend with RGBX color formats (#3553) 2022-08-11 18:23:25 -03:00
gdkchan
a5ff0024fb Rename ToSpan to AsSpan (#3556) 2022-08-11 18:07:37 -03:00
238 changed files with 1516 additions and 1036 deletions

View File

@@ -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);

View File

@@ -1,6 +1,4 @@
using ARMeilleure.Common;
using ARMeilleure.IntermediateRepresentation;
using System;
namespace ARMeilleure.CodeGen.RegisterAllocators
{

View File

@@ -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]

View File

@@ -1,5 +1,4 @@
using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.CodeGen.X86
{

View File

@@ -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;

View File

@@ -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
{

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;
namespace ARMeilleure.Common
{

View File

@@ -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)

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Reflection.Emit;
namespace ARMeilleure.Decoders
{

View File

@@ -1,6 +1,4 @@
using ARMeilleure.Instructions;
namespace ARMeilleure.Decoders
namespace ARMeilleure.Decoders
{
class OpCodeT32BImm20 : OpCodeT32, IOpCode32BImm
{

View File

@@ -1,7 +1,5 @@
using ARMeilleure.Decoders;
using ARMeilleure.Translation;
using static ARMeilleure.Instructions.InstEmitFlowHelper;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.Instructions

View File

@@ -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;

View File

@@ -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
{

View File

@@ -1,5 +1,4 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace ARMeilleure.Signal

View File

@@ -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>

View File

@@ -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;

View File

@@ -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;

View File

@@ -1,5 +1,4 @@
using System;
namespace SoundIOSharp
namespace SoundIOSharp
{
public struct SoundIOSampleRateRange
{

View File

@@ -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
{

View File

@@ -1,5 +1,4 @@
using Ryujinx.Audio.Renderer.Dsp.State;
using Ryujinx.Audio.Renderer.Parameter;
using Ryujinx.Memory;
using System;
using System.Runtime.CompilerServices;

View File

@@ -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

View File

@@ -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

View File

@@ -1,5 +1,3 @@
using System;
namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public class CopyMixBufferCommand : ICommand

View File

@@ -1,5 +1,4 @@
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
namespace Ryujinx.Audio.Renderer.Dsp.Command

View File

@@ -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
{

View File

@@ -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

View File

@@ -1,6 +1,5 @@
using Ryujinx.Audio.Renderer.Server.Upsampler;
using System;
using System.Runtime.CompilerServices;
namespace Ryujinx.Audio.Renderer.Dsp.Command
{

View File

@@ -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;

View File

@@ -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);
}
}
}

View File

@@ -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;

View File

@@ -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,

View File

@@ -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
{

View File

@@ -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();

View File

@@ -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;

View File

@@ -34,7 +34,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
public void UpdateState()
{
Mix.ToSpan().CopyTo(PreviousMix.ToSpan());
Mix.AsSpan().CopyTo(PreviousMix.AsSpan());
}
}
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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}",

View File

@@ -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

View File

@@ -1,7 +1,6 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Threading;
using Ryujinx.Input;
using System;
using System.Numerics;

View File

@@ -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,

View File

@@ -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
{

View File

@@ -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;

View File

@@ -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;

View File

@@ -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}\".");
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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);
}
}
}
}

View File

@@ -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);
}
}
}
}
}

View File

@@ -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)

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}
}
}

View File

@@ -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)

View File

@@ -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>

View File

@@ -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;

View File

@@ -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();
}
}
}

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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()

View File

@@ -1,6 +1,4 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Ryujinx.Ava.Ui.Windows;
namespace Ryujinx.Ava.Ui.Controls

View File

@@ -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());
}
}
}

View File

@@ -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;

View File

@@ -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();
}
}

View File

@@ -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;

View File

@@ -1,5 +1,4 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Threading;

View File

@@ -1,4 +1,3 @@
using Avalonia;
using Avalonia.Interactivity;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Ui.Models;

View File

@@ -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;

View File

@@ -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();

View File

@@ -519,7 +519,7 @@
HorizontalContentAlignment="Left"
ToolTip.Tip="{locale:Locale SettingsTabGraphicsBackendTooltip}"
SelectedIndex="{Binding GraphicsBackendIndex}">
<ComboBoxItem>
<ComboBoxItem IsVisible="{Binding IsVulkanAvailable}">
<TextBlock Text="Vulkan" />
</ComboBoxItem>
<ComboBoxItem>

View File

@@ -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)

View File

@@ -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;

View File

@@ -1,5 +1,3 @@
using Avalonia;
using Avalonia.Controls;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Modules;
using System;

View File

@@ -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
{

View File

@@ -1,5 +1,4 @@
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices;
namespace Ryujinx.Common.GraphicsDriver.NVAPI
{

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Concurrent;
namespace Ryujinx.Common.Logging
{

View File

@@ -1,7 +1,6 @@
using System;
using System.IO;
using System.Linq;
using System.Reflection;
namespace Ryujinx.Common.Logging
{

View File

@@ -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.

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -3,7 +3,6 @@ using System;
using System.Drawing;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
namespace Ryujinx.Common.System
{

View File

@@ -24,7 +24,7 @@ namespace Ryujinx.Common.SystemInfo
if (sysctlbyname("hw.memsize", ref totalRAM) != 0) // Bytes
{
totalRAM = 0;
};
}
CpuName = $"{cpuName} ; {LogicalCoreCount} logical";
RamTotal = totalRAM;

View File

@@ -1,5 +1,4 @@
using System;
using System.Globalization;
using System.Management;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;

View File

@@ -1,4 +1,3 @@
using System;
using System.Numerics;
namespace Ryujinx.Common

View File

@@ -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;
}

View File

@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Ryujinx.Graphics.GAL
namespace Ryujinx.Graphics.GAL
{
public struct HardwareInfo
{

View File

@@ -1,5 +1,4 @@
using Ryujinx.Common.Configuration;
using Ryujinx.Graphics.Shader;
using System;
namespace Ryujinx.Graphics.GAL

View File

@@ -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);
}
}

View File

@@ -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());
}
}
}

View File

@@ -1,6 +1,5 @@
using Ryujinx.Graphics.GAL.Multithreading.Model;
using System;
using System.Buffers;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{

View File

@@ -1,6 +1,5 @@
using Ryujinx.Graphics.GAL.Multithreading.Model;
using System;
using System.Buffers;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{

View File

@@ -1,5 +1,4 @@
using Ryujinx.Graphics.GAL.Multithreading.Model;
using Ryujinx.Graphics.Shader;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{

View File

@@ -1,6 +1,4 @@
using System.Linq;
namespace Ryujinx.Graphics.GAL.Multithreading.Resources.Programs
namespace Ryujinx.Graphics.GAL.Multithreading.Resources.Programs
{
class SourceProgramRequest : IProgramRequest
{

View File

@@ -30,5 +30,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
{
_impl.Window.SetSize(width, height);
}
public void ChangeVSyncMode(bool vsyncEnabled) { }
}
}

View File

@@ -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)

View File

@@ -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)

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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
{

View File

@@ -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