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="a">First instance</param>
/// <param name="b">Second instance</param> /// <param name="b">Second instance</param>
/// <returns><see langword="true"/> if not equal; otherwise <see langword="false"/></returns> /// <returns><see langword="true"/> if not equal; otherwise <see langword="false"/></returns>
/// <inheritdoc/>
public static bool operator !=(Symbol a, Symbol b) public static bool operator !=(Symbol a, Symbol b)
{ {
return !(a == b); return !(a == b);

View File

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

View File

@@ -4,6 +4,11 @@ namespace ARMeilleure.CodeGen.X86
{ {
partial class Assembler partial class Assembler
{ {
public static bool SupportsVexPrefix(X86Instruction inst)
{
return _instTable[(int)inst].Flags.HasFlag(InstructionFlags.Vex);
}
private const int BadOp = 0; private const int BadOp = 0;
[Flags] [Flags]

View File

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

View File

@@ -1297,11 +1297,15 @@ namespace ARMeilleure.CodeGen.X86
{ {
if (IsIntrinsic(operation.Instruction)) if (IsIntrinsic(operation.Instruction))
{ {
IntrinsicInfo info = IntrinsicTable.GetInfo(operation.Intrinsic);
bool hasVex = HardwareCapabilities.SupportsVexEncoding && Assembler.SupportsVexPrefix(info.Inst);
bool isUnary = operation.SourcesCount < 2; bool isUnary = operation.SourcesCount < 2;
bool hasVecDest = operation.Destination != default && operation.Destination.Type == OperandType.V128; bool hasVecDest = operation.Destination != default && operation.Destination.Type == OperandType.V128;
return !HardwareCapabilities.SupportsVexEncoding && !isUnary && hasVecDest; return !hasVex && !isUnary && hasVecDest;
} }
return false; return false;

View File

@@ -206,7 +206,7 @@ namespace ARMeilleure.Common
/// <typeparam name="T">Type of elements</typeparam> /// <typeparam name="T">Type of elements</typeparam>
/// <param name="length">Number of elements</param> /// <param name="length">Number of elements</param>
/// <param name="fill">Fill value</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> /// <returns>Allocated block</returns>
private IntPtr Allocate<T>(int length, T fill, bool leaf) where T : unmanaged private IntPtr Allocate<T>(int length, T fill, bool leaf) where T : unmanaged
{ {

View File

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

View File

@@ -9,6 +9,9 @@ namespace ARMeilleure.Common
class Counter<T> : IDisposable where T : unmanaged class Counter<T> : IDisposable where T : unmanaged
{ {
private bool _disposed; private bool _disposed;
/// <summary>
/// Index in the <see cref="EntryTable{T}"/>
/// </summary>
private readonly int _index; private readonly int _index;
private readonly EntryTable<T> _countTable; private readonly EntryTable<T> _countTable;
@@ -17,7 +20,6 @@ namespace ARMeilleure.Common
/// <see cref="EntryTable{T}"/> instance and index. /// <see cref="EntryTable{T}"/> instance and index.
/// </summary> /// </summary>
/// <param name="countTable"><see cref="EntryTable{T}"/> instance</param> /// <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="ArgumentNullException"><paramref name="countTable"/> is <see langword="null"/></exception>
/// <exception cref="ArgumentException"><typeparamref name="T"/> is unsupported</exception> /// <exception cref="ArgumentException"><typeparamref name="T"/> is unsupported</exception>
public Counter(EntryTable<T> countTable) public Counter(EntryTable<T> countTable)
@@ -68,7 +70,7 @@ namespace ARMeilleure.Common
/// <summary> /// <summary>
/// Releases all unmanaged and optionally managed resources used by the <see cref="Counter{T}"/> instance. /// Releases all unmanaged and optionally managed resources used by the <see cref="Counter{T}"/> instance.
/// </summary> /// </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) protected virtual void Dispose(bool disposing)
{ {
if (!_disposed) if (!_disposed)

View File

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

View File

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

View File

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

View File

@@ -2,8 +2,6 @@
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System; using System;
using System.Diagnostics;
using static ARMeilleure.Instructions.InstEmitFlowHelper; using static ARMeilleure.Instructions.InstEmitFlowHelper;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper; using static ARMeilleure.Instructions.InstEmitSimdHelper;

View File

@@ -2,8 +2,6 @@ using ARMeilleure.Memory;
using ARMeilleure.State; using ARMeilleure.State;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System; using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions namespace ARMeilleure.Instructions
{ {

View File

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

View File

@@ -344,7 +344,7 @@ namespace ARMeilleure.Translation
} }
/// <summary> /// <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> /// </summary>
/// <param name="key">Key to search for</param> /// <param name="key">Key to search for</param>
/// <returns>Number of deleted values</returns> /// <returns>Number of deleted values</returns>

View File

@@ -4,7 +4,6 @@ using Ryujinx.Memory;
using Ryujinx.SDL2.Common; using Ryujinx.SDL2.Common;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using static Ryujinx.Audio.Integration.IHardwareDeviceDriver; using static Ryujinx.Audio.Integration.IHardwareDeviceDriver;

View File

@@ -4,7 +4,6 @@ using Ryujinx.Common.Logging;
using Ryujinx.Memory; using Ryujinx.Memory;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using static SDL2.SDL; using static SDL2.SDL;

View File

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

View File

@@ -1,7 +1,6 @@
using Ryujinx.Audio.Renderer.Dsp.State; using Ryujinx.Audio.Renderer.Dsp.State;
using Ryujinx.Audio.Renderer.Parameter; using Ryujinx.Audio.Renderer.Parameter;
using System; using System;
using System.Runtime.CompilerServices;
namespace Ryujinx.Audio.Renderer.Dsp.Command namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {

View File

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

View File

@@ -1,6 +1,5 @@
using Ryujinx.Audio.Renderer.Parameter.Sink; using Ryujinx.Audio.Renderer.Parameter.Sink;
using Ryujinx.Audio.Renderer.Server.MemoryPool; using Ryujinx.Audio.Renderer.Server.MemoryPool;
using System;
using System.Diagnostics; using System.Diagnostics;
namespace Ryujinx.Audio.Renderer.Dsp.Command namespace Ryujinx.Audio.Renderer.Dsp.Command

View File

@@ -6,7 +6,6 @@ using Ryujinx.Memory;
using System; using System;
using System.Buffers; using System.Buffers;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
namespace Ryujinx.Audio.Renderer.Dsp.Command namespace Ryujinx.Audio.Renderer.Dsp.Command

View File

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

View File

@@ -1,5 +1,4 @@
using System; using System;
using System.Diagnostics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
namespace Ryujinx.Audio.Renderer.Dsp.Command 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 Ryujinx.Audio.Renderer.Parameter.Effect;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.CompilerServices;
namespace Ryujinx.Audio.Renderer.Dsp.Command namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {

View File

@@ -3,7 +3,6 @@ using Ryujinx.Audio.Renderer.Parameter;
using Ryujinx.Audio.Renderer.Parameter.Effect; using Ryujinx.Audio.Renderer.Parameter.Effect;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Ryujinx.Audio.Renderer.Dsp.Command namespace Ryujinx.Audio.Renderer.Dsp.Command

View File

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

View File

@@ -76,7 +76,7 @@ namespace Ryujinx.Audio.Renderer.Dsp
if (!info.DecodingBehaviour.HasFlag(DecodingBehaviour.SkipPitchAndSampleRateConversion)) if (!info.DecodingBehaviour.HasFlag(DecodingBehaviour.SkipPitchAndSampleRateConversion))
{ {
voiceState.Pitch.ToSpan().Slice(0, pitchMaxLength).CopyTo(tempBuffer); voiceState.Pitch.AsSpan().Slice(0, pitchMaxLength).CopyTo(tempBuffer);
tempBufferIndex += pitchMaxLength; 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); 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; i += sampleCountToProcess;

View File

@@ -24,8 +24,8 @@ namespace Ryujinx.Audio.Renderer.Parameter.Effect
/// </summary> /// </summary>
public void Reset() public void Reset()
{ {
InputMax.ToSpan().Fill(0.0f); InputMax.AsSpan().Fill(0.0f);
CompressionGainMin.ToSpan().Fill(1.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.Sink;
using Ryujinx.Audio.Renderer.Server.Upsampler; using Ryujinx.Audio.Renderer.Server.Upsampler;
using Ryujinx.Audio.Renderer.Server.Voice; using Ryujinx.Audio.Renderer.Server.Voice;
using Ryujinx.Common.Memory;
using System; using System;
using CpuAddress = System.UInt64; 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<byte> biquadStateRawMemory = SpanMemoryManager<byte>.Cast(state).Slice(VoiceUpdateState.BiquadStateOffset, VoiceUpdateState.BiquadStateSize * Constants.VoiceBiquadFilterCount);
Memory<BiquadFilterState> stateMemory = SpanMemoryManager<BiquadFilterState>.Cast(biquadStateRawMemory); 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 else
{ {
@@ -337,8 +337,8 @@ namespace Ryujinx.Audio.Renderer.Server
GeneratePerformance(ref performanceEntry, PerformanceCommand.Type.Start, nodeId); GeneratePerformance(ref performanceEntry, PerformanceCommand.Type.Start, nodeId);
} }
GenerateVoiceMix(channelResource.Mix.ToSpan(), GenerateVoiceMix(channelResource.Mix.AsSpan(),
channelResource.PreviousMix.ToSpan(), channelResource.PreviousMix.AsSpan(),
dspStateMemory, dspStateMemory,
mix.BufferOffset, mix.BufferOffset,
mix.BufferCount, mix.BufferCount,
@@ -505,8 +505,8 @@ namespace Ryujinx.Audio.Renderer.Server
BiquadFilterParameter parameter = new BiquadFilterParameter(); BiquadFilterParameter parameter = new BiquadFilterParameter();
parameter.Enable = true; parameter.Enable = true;
effect.Parameter.Denominator.ToSpan().CopyTo(parameter.Denominator.ToSpan()); effect.Parameter.Denominator.AsSpan().CopyTo(parameter.Denominator.AsSpan());
effect.Parameter.Numerator.ToSpan().CopyTo(parameter.Numerator.ToSpan()); effect.Parameter.Numerator.AsSpan().CopyTo(parameter.Numerator.AsSpan());
for (int i = 0; i < effect.Parameter.ChannelCount; i++) for (int i = 0; i < effect.Parameter.ChannelCount; i++)
{ {
@@ -923,8 +923,8 @@ namespace Ryujinx.Audio.Renderer.Server
if (useCustomDownMixingCommand) if (useCustomDownMixingCommand)
{ {
_commandBuffer.GenerateDownMixSurroundToStereo(finalMix.BufferOffset, _commandBuffer.GenerateDownMixSurroundToStereo(finalMix.BufferOffset,
sink.Parameter.Input.ToSpan(), sink.Parameter.Input.AsSpan(),
sink.Parameter.Input.ToSpan(), sink.Parameter.Input.AsSpan(),
sink.DownMixCoefficients, sink.DownMixCoefficients,
Constants.InvalidNodeId); Constants.InvalidNodeId);
} }
@@ -932,8 +932,8 @@ namespace Ryujinx.Audio.Renderer.Server
else if (_rendererContext.ChannelCount == 2 && sink.Parameter.InputCount == 6) else if (_rendererContext.ChannelCount == 2 && sink.Parameter.InputCount == 6)
{ {
_commandBuffer.GenerateDownMixSurroundToStereo(finalMix.BufferOffset, _commandBuffer.GenerateDownMixSurroundToStereo(finalMix.BufferOffset,
sink.Parameter.Input.ToSpan(), sink.Parameter.Input.AsSpan(),
sink.Parameter.Input.ToSpan(), sink.Parameter.Input.AsSpan(),
Constants.DefaultSurroundToStereoCoefficients, Constants.DefaultSurroundToStereoCoefficients,
Constants.InvalidNodeId); Constants.InvalidNodeId);
} }
@@ -945,7 +945,7 @@ namespace Ryujinx.Audio.Renderer.Server
_commandBuffer.GenerateUpsample(finalMix.BufferOffset, _commandBuffer.GenerateUpsample(finalMix.BufferOffset,
sink.UpsamplerState, sink.UpsamplerState,
sink.Parameter.InputCount, sink.Parameter.InputCount,
sink.Parameter.Input.ToSpan(), sink.Parameter.Input.AsSpan(),
commandList.BufferCount, commandList.BufferCount,
commandList.SampleCount, commandList.SampleCount,
commandList.SampleRate, commandList.SampleRate,

View File

@@ -1,9 +1,5 @@
using Ryujinx.Audio.Common;
using Ryujinx.Audio.Renderer.Dsp.Command; using Ryujinx.Audio.Renderer.Dsp.Command;
using Ryujinx.Audio.Renderer.Parameter.Effect;
using System;
using System.Diagnostics; using System.Diagnostics;
using static Ryujinx.Audio.Renderer.Parameter.VoiceInParameter;
namespace Ryujinx.Audio.Renderer.Server namespace Ryujinx.Audio.Renderer.Server
{ {

View File

@@ -63,10 +63,10 @@ namespace Ryujinx.Audio.Renderer.Server.Sink
else else
{ {
Parameter.DownMixParameterEnabled = inputDeviceParameter.DownMixParameterEnabled; 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(); errorInfo = new BehaviourParameter.ErrorInfo();
outStatus = new SinkOutStatus(); outStatus = new SinkOutStatus();

View File

@@ -119,7 +119,7 @@ namespace Ryujinx.Audio.Renderer.Server
ref VoiceChannelResource resource = ref context.GetChannelResource(i); ref VoiceChannelResource resource = ref context.GetChannelResource(i);
resource.Id = parameter.Id; resource.Id = parameter.Id;
parameter.Mix.ToSpan().CopyTo(resource.Mix.ToSpan()); parameter.Mix.AsSpan().CopyTo(resource.Mix.AsSpan());
resource.IsUsed = parameter.IsUsed; resource.IsUsed = parameter.IsUsed;
} }
@@ -587,7 +587,7 @@ namespace Ryujinx.Audio.Renderer.Server
{ {
ref BehaviourErrorInfoOutStatus outStatus = ref SpanIOHelper.GetWriteRef<BehaviourErrorInfoOutStatus>(ref _output)[0]; 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.BehaviourSize = (uint)Unsafe.SizeOf<BehaviourErrorInfoOutStatus>();
OutputHeader.TotalSize += OutputHeader.BehaviourSize; OutputHeader.TotalSize += OutputHeader.BehaviourSize;

View File

@@ -34,7 +34,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
public void UpdateState() 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; Pitch = 0.0f;
Volume = 0.0f; Volume = 0.0f;
PreviousVolume = 0.0f; PreviousVolume = 0.0f;
BiquadFilters.ToSpan().Fill(new BiquadFilterParameter()); BiquadFilters.AsSpan().Fill(new BiquadFilterParameter());
WaveBuffersCount = 0; WaveBuffersCount = 0;
WaveBuffersIndex = 0; WaveBuffersIndex = 0;
MixId = Constants.UnusedMixId; MixId = Constants.UnusedMixId;
@@ -288,7 +288,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
ChannelsCount = parameter.ChannelCount; ChannelsCount = parameter.ChannelCount;
Pitch = parameter.Pitch; Pitch = parameter.Pitch;
Volume = parameter.Volume; Volume = parameter.Volume;
parameter.BiquadFilters.ToSpan().CopyTo(BiquadFilters.ToSpan()); parameter.BiquadFilters.AsSpan().CopyTo(BiquadFilters.AsSpan());
WaveBuffersCount = parameter.WaveBuffersCount; WaveBuffersCount = parameter.WaveBuffersCount;
WaveBuffersIndex = parameter.WaveBuffersIndex; WaveBuffersIndex = parameter.WaveBuffersIndex;
@@ -308,7 +308,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
SplitterId = Constants.UnusedSplitterId; SplitterId = Constants.UnusedSplitterId;
} }
parameter.ChannelResourceIds.ToSpan().CopyTo(ChannelResourceIds.ToSpan()); parameter.ChannelResourceIds.AsSpan().CopyTo(ChannelResourceIds.AsSpan());
DecodingBehaviour behaviour = DecodingBehaviour.Default; DecodingBehaviour behaviour = DecodingBehaviour.Default;
@@ -638,7 +638,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
voiceUpdateState.Offset = 0; voiceUpdateState.Offset = 0;
voiceUpdateState.PlayedSampleCount = 0; voiceUpdateState.PlayedSampleCount = 0;
voiceUpdateState.Pitch.ToSpan().Fill(0); voiceUpdateState.Pitch.AsSpan().Fill(0);
voiceUpdateState.Fraction = 0; voiceUpdateState.Fraction = 0;
voiceUpdateState.LoopContext = new Dsp.State.AdpcmLoopContext(); voiceUpdateState.LoopContext = new Dsp.State.AdpcmLoopContext();
} }
@@ -650,7 +650,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
case Types.PlayState.Stopped: case Types.PlayState.Stopped:
case Types.PlayState.Paused: case Types.PlayState.Paused:
foreach (ref WaveBuffer wavebuffer in WaveBuffers.ToSpan()) foreach (ref WaveBuffer wavebuffer in WaveBuffers.AsSpan())
{ {
wavebuffer.BufferAddressInfo.GetReference(true); wavebuffer.BufferAddressInfo.GetReference(true);
wavebuffer.ContextAddressInfo.GetReference(true); wavebuffer.ContextAddressInfo.GetReference(true);

View File

@@ -12,6 +12,7 @@ using Ryujinx.Audio.Integration;
using Ryujinx.Ava.Common; using Ryujinx.Ava.Common;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Input; using Ryujinx.Ava.Input;
using Ryujinx.Ava.Ui.Backend.Vulkan;
using Ryujinx.Ava.Ui.Controls; using Ryujinx.Ava.Ui.Controls;
using Ryujinx.Ava.Ui.Models; using Ryujinx.Ava.Ui.Models;
using Ryujinx.Ava.Ui.Vulkan; using Ryujinx.Ava.Ui.Vulkan;
@@ -334,6 +335,8 @@ namespace Ryujinx.Ava
return; return;
} }
AvaloniaLocator.Current.GetService<VulkanPlatformInterface>()?.MainSurface.Display.ChangeVSyncMode(true);
_isStopped = true; _isStopped = true;
_isActive = false; _isActive = false;
} }
@@ -596,12 +599,13 @@ namespace Ryujinx.Ava
if (Program.UseVulkan) if (Program.UseVulkan)
{ {
var vulkan = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>(); var vulkan = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>();
renderer = new VulkanRenderer(vulkan.Instance.InternalHandle, renderer = new VulkanRenderer(vulkan.Instance.InternalHandle,
vulkan.Device.InternalHandle, vulkan.MainSurface.Device.InternalHandle,
vulkan.PhysicalDevice.InternalHandle, vulkan.PhysicalDevice.InternalHandle,
vulkan.Device.Queue.InternalHandle, vulkan.MainSurface.Device.Queue.InternalHandle,
vulkan.PhysicalDevice.QueueFamilyIndex, vulkan.PhysicalDevice.QueueFamilyIndex,
vulkan.Device.Lock); vulkan.MainSurface.Device.Lock);
} }
else else
{ {
@@ -775,7 +779,10 @@ namespace Ryujinx.Ava
Width = (int)e.Width; Width = (int)e.Width;
Height = (int)e.Height; Height = (int)e.Height;
SetRendererWindowSize(e); if (!Program.UseVulkan)
{
SetRendererWindowSize(e);
}
} }
private void MainLoop() private void MainLoop()
@@ -815,12 +822,11 @@ namespace Ryujinx.Ava
_renderer.ScreenCaptured += Renderer_ScreenCaptured; _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); Device.Gpu.Renderer.Initialize(_glLogLevel);
@@ -837,8 +843,6 @@ namespace Ryujinx.Ava
Renderer.Start(); Renderer.Start();
Renderer.QueueRender();
while (_isActive) while (_isActive)
{ {
if (Device.WaitFifo()) if (Device.WaitFifo())
@@ -889,6 +893,16 @@ namespace Ryujinx.Ava
$"FIFO: {Device.Statistics.GetFifoPercent():00.00} %", $"FIFO: {Device.Statistics.GetFifoPercent():00.00} %",
$"GPU: {_renderer.GetHardwareInfo().GpuVendor}")); $"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); Renderer.Present(image);
} }
@@ -970,6 +984,9 @@ namespace Ryujinx.Ava
{ {
case KeyboardHotkeyState.ToggleVSync: case KeyboardHotkeyState.ToggleVSync:
Device.EnableDeviceVsync = !Device.EnableDeviceVsync; Device.EnableDeviceVsync = !Device.EnableDeviceVsync;
AvaloniaLocator.Current.GetService<VulkanPlatformInterface>()?.MainSurface?.Display?.ChangeVSyncMode(Device.EnableDeviceVsync);
break; break;
case KeyboardHotkeyState.Screenshot: case KeyboardHotkeyState.Screenshot:
ScreenshotRequested = true; ScreenshotRequested = true;

View File

@@ -52,8 +52,8 @@
"GameListContextMenuOpenModsDirectory": "Open Mods Directory", "GameListContextMenuOpenModsDirectory": "Open Mods Directory",
"GameListContextMenuOpenModsDirectoryToolTip": "Opens the directory which contains Application's Mods", "GameListContextMenuOpenModsDirectoryToolTip": "Opens the directory which contains Application's Mods",
"GameListContextMenuCacheManagement": "Cache Management", "GameListContextMenuCacheManagement": "Cache Management",
"GameListContextMenuCacheManagementPurgePptc": "Purge PPTC Cache", "GameListContextMenuCacheManagementPurgePptc": "Queue PPTC Rebuild",
"GameListContextMenuCacheManagementPurgePptcToolTip": "Deletes Application's PPTC cache", "GameListContextMenuCacheManagementPurgePptcToolTip": "Trigger PPTC to rebuild at boot time on the next game launch",
"GameListContextMenuCacheManagementPurgeShaderCache": "Purge Shader Cache", "GameListContextMenuCacheManagementPurgeShaderCache": "Purge Shader Cache",
"GameListContextMenuCacheManagementPurgeShaderCacheToolTip": "Deletes Application's shader cache", "GameListContextMenuCacheManagementPurgeShaderCacheToolTip": "Deletes Application's shader cache",
"GameListContextMenuCacheManagementOpenPptcDirectory": "Open PPTC Directory", "GameListContextMenuCacheManagementOpenPptcDirectory": "Open PPTC Directory",
@@ -350,7 +350,7 @@
"DialogProfileDeleteProfileTitle": "Deleting Profile", "DialogProfileDeleteProfileTitle": "Deleting Profile",
"DialogProfileDeleteProfileMessage": "This action is irreversible, are you sure you want to continue?", "DialogProfileDeleteProfileMessage": "This action is irreversible, are you sure you want to continue?",
"DialogWarning": "Warning", "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}", "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?", "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}", "DialogShaderDeletionErrorMessage": "Error purging Shader cache at {0}: {1}",

View File

@@ -24,7 +24,6 @@ using System.Buffers;
using System.IO; using System.IO;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using static LibHac.Fs.ApplicationSaveDataManagement;
using Path = System.IO.Path; using Path = System.IO.Path;
namespace Ryujinx.Ava.Common namespace Ryujinx.Ava.Common

View File

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

View File

@@ -16,8 +16,6 @@ using Ryujinx.Graphics.Vulkan;
using Ryujinx.Modules; using Ryujinx.Modules;
using Ryujinx.Ui.Common; using Ryujinx.Ui.Common;
using Ryujinx.Ui.Common.Configuration; using Ryujinx.Ui.Common.Configuration;
using Silk.NET.Vulkan.Extensions.EXT;
using Silk.NET.Vulkan.Extensions.KHR;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@@ -94,7 +92,6 @@ namespace Ryujinx.Ava
.With(new Ui.Vulkan.VulkanOptions() .With(new Ui.Vulkan.VulkanOptions()
{ {
ApplicationName = "Ryujinx.Graphics.Vulkan", ApplicationName = "Ryujinx.Graphics.Vulkan",
VulkanVersion = new Version(1, 2),
MaxQueueCount = 2, MaxQueueCount = 2,
PreferDiscreteGpu = true, PreferDiscreteGpu = true,
PreferredDevice = !PreviewerDetached ? "" : ConfigurationState.Instance.Graphics.PreferredGpu.Value, PreferredDevice = !PreviewerDetached ? "" : ConfigurationState.Instance.Graphics.PreferredGpu.Value,
@@ -181,6 +178,18 @@ namespace Ryujinx.Ava
UseVulkan = PreviewerDetached ? ConfigurationState.Instance.Graphics.GraphicsBackend.Value == GraphicsBackend.Vulkan : false; 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) 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, // 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 Ryujinx.HLE.Ui;
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
namespace Ryujinx.Ava.Ui.Applet namespace Ryujinx.Ava.Ui.Applet
{ {

View File

@@ -1,7 +1,6 @@
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Threading; using Avalonia.Threading;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Ui.Windows; using Ryujinx.Ava.Ui.Windows;

View File

@@ -1,7 +1,6 @@
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Media; using Avalonia.Media;
using FluentAvalonia.Core; using FluentAvalonia.Core;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;

View File

@@ -7,7 +7,8 @@ namespace Ryujinx.Ava.Ui.Vulkan
{ {
public static void ThrowOnError(this Result result) 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}\"."); throw new Exception($"Unexpected API error \"{result}\".");
} }

View File

@@ -1,26 +1,90 @@
using System; using System;
using Avalonia;
using Avalonia.Skia; using Avalonia.Skia;
using Ryujinx.Ava.Ui.Vulkan; using Ryujinx.Ava.Ui.Vulkan;
using Ryujinx.Ava.Ui.Vulkan.Surfaces; using Ryujinx.Ava.Ui.Vulkan.Surfaces;
using Silk.NET.Vulkan;
using SkiaSharp; using SkiaSharp;
namespace Ryujinx.Ava.Ui.Backend.Vulkan namespace Ryujinx.Ava.Ui.Backend.Vulkan
{ {
internal class VulkanRenderTarget : ISkiaGpuRenderTarget internal class VulkanRenderTarget : ISkiaGpuRenderTarget
{ {
public GRContext GrContext { get; set; } public GRContext GrContext { get; private set; }
private readonly VulkanSurfaceRenderTarget _surface; private readonly VulkanSurfaceRenderTarget _surface;
private readonly VulkanPlatformInterface _vulkanPlatformInterface;
private readonly IVulkanPlatformSurface _vulkanPlatformSurface; private readonly IVulkanPlatformSurface _vulkanPlatformSurface;
private GRVkBackendContext _grVkBackend;
public VulkanRenderTarget(VulkanPlatformInterface vulkanPlatformInterface, IVulkanPlatformSurface vulkanPlatformSurface) public VulkanRenderTarget(VulkanPlatformInterface vulkanPlatformInterface, IVulkanPlatformSurface vulkanPlatformSurface)
{ {
_surface = vulkanPlatformInterface.CreateRenderTarget(vulkanPlatformSurface); _surface = vulkanPlatformInterface.CreateRenderTarget(vulkanPlatformSurface);
_vulkanPlatformInterface = vulkanPlatformInterface;
_vulkanPlatformSurface = vulkanPlatformSurface; _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() public void Dispose()
{ {
_grVkBackend.Dispose();
GrContext.Dispose();
_surface.Dispose(); _surface.Dispose();
} }
@@ -45,20 +109,22 @@ namespace Ryujinx.Ava.Ui.Backend.Vulkan
{ {
GrContext.ResetContext(); GrContext.ResetContext();
var image = _surface.GetImage();
var imageInfo = new GRVkImageInfo() var imageInfo = new GRVkImageInfo()
{ {
CurrentQueueFamily = disp.QueueFamilyIndex, CurrentQueueFamily = disp.QueueFamilyIndex,
Format = _surface.ImageFormat, Format = (uint)image.Format,
Image = _surface.Image.Handle, Image = image.Handle,
ImageLayout = (uint)_surface.Image.CurrentLayout, ImageLayout = (uint)image.CurrentLayout,
ImageTiling = (uint)_surface.Image.Tiling, ImageTiling = (uint)image.Tiling,
ImageUsageFlags = _surface.UsageFlags, ImageUsageFlags = _surface.UsageFlags,
LevelCount = _surface.MipLevels, LevelCount = _surface.MipLevels,
SampleCount = 1, SampleCount = 1,
Protected = false, Protected = false,
Alloc = new GRVkAlloc() Alloc = new GRVkAlloc()
{ {
Memory = _surface.Image.MemoryHandle, Memory = image.MemoryHandle,
Flags = 0, Flags = 0,
Offset = 0, Offset = 0,
Size = _surface.MemorySize Size = _surface.MemorySize

View File

@@ -13,71 +13,12 @@ namespace Ryujinx.Ava.Ui.Backend.Vulkan
public class VulkanSkiaGpu : ISkiaGpu public class VulkanSkiaGpu : ISkiaGpu
{ {
private readonly VulkanPlatformInterface _vulkan; private readonly VulkanPlatformInterface _vulkan;
private readonly long? _maxResourceBytes; public long? MaxResourceBytes { get; }
private GRVkBackendContext _grVkBackend;
private bool _initialized;
public GRContext GrContext { get; private set; }
public VulkanSkiaGpu(long? maxResourceBytes) public VulkanSkiaGpu(long? maxResourceBytes)
{ {
_vulkan = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>(); _vulkan = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>();
_maxResourceBytes = maxResourceBytes; 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);
}
} }
public ISkiaGpuRenderTarget TryCreateRenderTarget(IEnumerable<object> surfaces) public ISkiaGpuRenderTarget TryCreateRenderTarget(IEnumerable<object> surfaces)
@@ -106,10 +47,6 @@ namespace Ryujinx.Ava.Ui.Backend.Vulkan
VulkanRenderTarget vulkanRenderTarget = new VulkanRenderTarget(_vulkan, window); VulkanRenderTarget vulkanRenderTarget = new VulkanRenderTarget(_vulkan, window);
Initialize();
vulkanRenderTarget.GrContext = GrContext;
return vulkanRenderTarget; return vulkanRenderTarget;
} }

View File

@@ -1,5 +1,6 @@
using System; using System;
using Avalonia; using Avalonia;
using Ryujinx.Graphics.Vulkan;
using Silk.NET.Vulkan; using Silk.NET.Vulkan;
namespace Ryujinx.Ava.Ui.Vulkan.Surfaces namespace Ryujinx.Ava.Ui.Vulkan.Surfaces
@@ -7,24 +8,35 @@ namespace Ryujinx.Ava.Ui.Vulkan.Surfaces
internal class VulkanSurfaceRenderTarget : IDisposable internal class VulkanSurfaceRenderTarget : IDisposable
{ {
private readonly VulkanPlatformInterface _platformInterface; private readonly VulkanPlatformInterface _platformInterface;
private readonly Format _format; private readonly Format _format;
public VulkanImage Image { get; private set; } private VulkanCommandBufferPool.VulkanCommandBuffer _commandBuffer;
public bool IsCorrupted { get; private set; } = true; private VulkanImage Image { get; set; }
private object _lock = new object();
public uint MipLevels => Image.MipLevels; public uint MipLevels => Image.MipLevels;
public VulkanDevice Device { get; }
public VulkanSurfaceRenderTarget(VulkanPlatformInterface platformInterface, VulkanSurface surface) public VulkanSurfaceRenderTarget(VulkanPlatformInterface platformInterface, VulkanSurface surface)
{ {
_platformInterface = platformInterface; _platformInterface = platformInterface;
Display = VulkanDisplay.CreateDisplay(platformInterface.Instance, platformInterface.Device, var device = VulkanInitialization.CreateDevice(platformInterface.Api,
platformInterface.PhysicalDevice, surface); 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; Surface = surface;
// Skia seems to only create surfaces from images with unorm format // Skia seems to only create surfaces from images with unorm format
IsRgba = Display.SurfaceFormat.Format >= Format.R8G8B8A8Unorm && IsRgba = Display.SurfaceFormat.Format >= Format.R8G8B8A8Unorm &&
Display.SurfaceFormat.Format <= Format.R8G8B8A8Srgb; Display.SurfaceFormat.Format <= Format.R8G8B8A8Srgb;
@@ -33,13 +45,13 @@ namespace Ryujinx.Ava.Ui.Vulkan.Surfaces
public bool IsRgba { get; } public bool IsRgba { get; }
public uint ImageFormat => (uint) _format; public uint ImageFormat => (uint)_format;
public ulong MemorySize => Image.MemorySize; 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; public uint UsageFlags => Image.UsageFlags;
@@ -47,46 +59,76 @@ namespace Ryujinx.Ava.Ui.Vulkan.Surfaces
public void Dispose() public void Dispose()
{ {
_platformInterface.Device.WaitIdle(); lock (_lock)
DestroyImage(); {
Display?.Dispose(); DestroyImage();
Surface?.Dispose(); Display?.Dispose();
Surface?.Dispose();
Device?.Dispose();
Display = null;
Surface = null;
}
} }
public VulkanSurfaceRenderingSession BeginDraw(float scaling) public VulkanSurfaceRenderingSession BeginDraw(float scaling)
{ {
var session = new VulkanSurfaceRenderingSession(Display, _platformInterface.Device, this, scaling); if (Image == null)
{
RecreateImage();
}
if (IsCorrupted) _commandBuffer?.WaitForFence();
{ _commandBuffer = null;
IsCorrupted = false;
DestroyImage(); var session = new VulkanSurfaceRenderingSession(Display, Device, this, scaling);
CreateImage();
} Image.TransitionLayout(ImageLayout.ColorAttachmentOptimal, AccessFlags.AccessNoneKhr);
else
{
Image.TransitionLayout(ImageLayout.ColorAttachmentOptimal, AccessFlags.AccessNoneKhr);
}
return session; return session;
} }
public void Invalidate() public void RecreateImage()
{ {
IsCorrupted = true; DestroyImage();
CreateImage();
} }
private void CreateImage() private void CreateImage()
{ {
Size = Display.Size; 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() private void DestroyImage()
{ {
_platformInterface.Device.WaitIdle(); _commandBuffer?.WaitForFence();
_commandBuffer = null;
Image?.Dispose(); 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 CommandPool _commandPool;
private readonly List<VulkanCommandBuffer> _usedCommandBuffers = new(); private readonly List<VulkanCommandBuffer> _usedCommandBuffers = new();
private readonly object _lock = new object();
public unsafe VulkanCommandBufferPool(VulkanDevice device, VulkanPhysicalDevice physicalDevice) public unsafe VulkanCommandBufferPool(VulkanDevice device, VulkanPhysicalDevice physicalDevice)
{ {
@@ -36,9 +37,12 @@ namespace Ryujinx.Ava.Ui.Vulkan
Level = CommandBufferLevel.Primary 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() public VulkanCommandBuffer CreateCommandBuffer()
@@ -48,7 +52,7 @@ namespace Ryujinx.Ava.Ui.Vulkan
public void FreeUsedCommandBuffers() public void FreeUsedCommandBuffers()
{ {
lock (_usedCommandBuffers) lock (_lock)
{ {
foreach (var usedCommandBuffer in _usedCommandBuffers) foreach (var usedCommandBuffer in _usedCommandBuffers)
{ {
@@ -61,7 +65,7 @@ namespace Ryujinx.Ava.Ui.Vulkan
private void DisposeCommandBuffer(VulkanCommandBuffer commandBuffer) private void DisposeCommandBuffer(VulkanCommandBuffer commandBuffer)
{ {
lock (_usedCommandBuffers) lock (_lock)
{ {
_usedCommandBuffers.Add(commandBuffer); _usedCommandBuffers.Add(commandBuffer);
} }
@@ -69,8 +73,11 @@ namespace Ryujinx.Ava.Ui.Vulkan
public void Dispose() public void Dispose()
{ {
FreeUsedCommandBuffers(); lock (_lock)
_device.Api.DestroyCommandPool(_device.InternalHandle, _commandPool, Span<AllocationCallbacks>.Empty); {
FreeUsedCommandBuffers();
_device.Api.DestroyCommandPool(_device.InternalHandle, _commandPool, Span<AllocationCallbacks>.Empty);
}
} }
public class VulkanCommandBuffer : IDisposable public class VulkanCommandBuffer : IDisposable
@@ -80,6 +87,8 @@ namespace Ryujinx.Ava.Ui.Vulkan
private readonly Fence _fence; private readonly Fence _fence;
private bool _hasEnded; private bool _hasEnded;
private bool _hasStarted; private bool _hasStarted;
private bool _isDisposed;
private object _lock = new object();
public IntPtr Handle => InternalHandle.Handle; public IntPtr Handle => InternalHandle.Handle;
@@ -101,6 +110,22 @@ namespace Ryujinx.Ava.Ui.Vulkan
device.Api.CreateFence(device.InternalHandle, fenceCreateInfo, null, out _fence); 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() public void BeginRecording()
{ {
if (!_hasStarted) if (!_hasStarted)
@@ -173,9 +198,17 @@ namespace Ryujinx.Ava.Ui.Vulkan
public void Dispose() public void Dispose()
{ {
_device.Api.WaitForFences(_device.InternalHandle, 1, _fence, true, ulong.MaxValue); lock (_lock)
_device.Api.FreeCommandBuffers(_device.InternalHandle, _commandBufferPool._commandPool, 1, InternalHandle); {
_device.Api.DestroyFence(_device.InternalHandle, _fence, Span<AllocationCallbacks>.Empty); 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); api.GetDeviceQueue(apiHandle, physicalDevice.QueueFamilyIndex, 0, out var queue);
var vulkanQueue = new VulkanQueue(this, queue); Queue = new VulkanQueue(this, queue);
Queue = vulkanQueue;
PresentQueue = vulkanQueue; PresentQueue = Queue;
CommandBufferPool = new VulkanCommandBufferPool(this, physicalDevice);
} }
public IntPtr Handle => InternalHandle.Handle; public IntPtr Handle => InternalHandle.Handle;
@@ -29,13 +26,12 @@ namespace Ryujinx.Ava.Ui.Vulkan
public VulkanQueue Queue { get; private set; } public VulkanQueue Queue { get; private set; }
public VulkanQueue PresentQueue { get; } public VulkanQueue PresentQueue { get; }
public VulkanCommandBufferPool CommandBufferPool { get; }
public void Dispose() public void Dispose()
{ {
WaitIdle(); WaitIdle();
CommandBufferPool?.Dispose();
Queue = null; Queue = null;
Api.DestroyDevice(InternalHandle, Span<AllocationCallbacks>.Empty);
} }
internal void Submit(SubmitInfo submitInfo, Fence fence = default) internal void Submit(SubmitInfo submitInfo, Fence fence = default)

View File

@@ -3,7 +3,6 @@ using System.Linq;
using System.Threading; using System.Threading;
using Avalonia; using Avalonia;
using Ryujinx.Ava.Ui.Vulkan.Surfaces; using Ryujinx.Ava.Ui.Vulkan.Surfaces;
using Ryujinx.Ui.Common.Configuration;
using Silk.NET.Vulkan; using Silk.NET.Vulkan;
using Silk.NET.Vulkan.Extensions.KHR; using Silk.NET.Vulkan.Extensions.KHR;
@@ -15,16 +14,19 @@ namespace Ryujinx.Ava.Ui.Vulkan
private readonly VulkanInstance _instance; private readonly VulkanInstance _instance;
private readonly VulkanPhysicalDevice _physicalDevice; private readonly VulkanPhysicalDevice _physicalDevice;
private readonly VulkanSemaphorePair _semaphorePair; private readonly VulkanSemaphorePair _semaphorePair;
private readonly VulkanDevice _device;
private uint _nextImage; private uint _nextImage;
private readonly VulkanSurface _surface; private readonly VulkanSurface _surface;
private SurfaceFormatKHR _surfaceFormat; private SurfaceFormatKHR _surfaceFormat;
private SwapchainKHR _swapchain; private SwapchainKHR _swapchain;
private Extent2D _swapchainExtent; private Extent2D _swapchainExtent;
private Image[] _swapchainImages; private Image[] _swapchainImages;
private VulkanDevice _device { get; } private ImageView[] _swapchainImageViews = Array.Empty<ImageView>();
private ImageView[] _swapchainImageViews = new ImageView[0];
private bool _vsyncStateChanged; private bool _vsyncStateChanged;
private bool _vsyncEnabled; private bool _vsyncEnabled;
private bool _surfaceChanged;
public event EventHandler Presented;
public VulkanCommandBufferPool CommandBufferPool { get; set; } public VulkanCommandBufferPool CommandBufferPool { get; set; }
@@ -73,6 +75,14 @@ namespace Ryujinx.Ava.Ui.Vulkan
CommandBufferPool.Dispose(); CommandBufferPool.Dispose();
} }
public bool IsSurfaceChanged()
{
var changed = _surfaceChanged;
_surfaceChanged = false;
return changed;
}
private static unsafe SwapchainKHR CreateSwapchain(VulkanInstance instance, VulkanDevice device, private static unsafe SwapchainKHR CreateSwapchain(VulkanInstance instance, VulkanDevice device,
VulkanPhysicalDevice physicalDevice, VulkanSurface surface, out Extent2D swapchainExtent, VulkanPhysicalDevice physicalDevice, VulkanSurface surface, out Extent2D swapchainExtent,
SwapchainKHR? oldswapchain = null, bool vsyncEnabled = true) SwapchainKHR? oldswapchain = null, bool vsyncEnabled = true)
@@ -193,22 +203,23 @@ namespace Ryujinx.Ava.Ui.Vulkan
} }
var modes = presentModes.ToList(); var modes = presentModes.ToList();
var presentMode = PresentModeKHR.PresentModeFifoKhr;
if (!vsyncEnabled && modes.Contains(PresentModeKHR.PresentModeImmediateKhr)) if (!vsyncEnabled && modes.Contains(PresentModeKHR.PresentModeImmediateKhr))
{ {
presentMode = PresentModeKHR.PresentModeImmediateKhr; return PresentModeKHR.PresentModeImmediateKhr;
} }
else if (modes.Contains(PresentModeKHR.PresentModeMailboxKhr)) 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, 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); _swapchain = CreateSwapchain(_instance, _device, _physicalDevice, _surface, out _swapchainExtent, _swapchain, _vsyncEnabled);
CreateSwapchainImages(); CreateSwapchainImages();
_surfaceChanged = true;
} }
private unsafe ImageView CreateSwapchainImageView(Image swapchainImage, Format format) private unsafe ImageView CreateSwapchainImageView(Image swapchainImage, Format format)
@@ -306,7 +319,7 @@ namespace Ryujinx.Ava.Ui.Vulkan
return true; return true;
} }
internal VulkanCommandBufferPool.VulkanCommandBuffer StartPresentation(VulkanSurfaceRenderTarget renderTarget) internal VulkanCommandBufferPool.VulkanCommandBuffer StartPresentation()
{ {
_nextImage = 0; _nextImage = 0;
while (true) while (true)
@@ -346,8 +359,10 @@ namespace Ryujinx.Ava.Ui.Vulkan
internal void BlitImageToCurrentImage(VulkanSurfaceRenderTarget renderTarget, CommandBuffer commandBuffer) internal void BlitImageToCurrentImage(VulkanSurfaceRenderTarget renderTarget, CommandBuffer commandBuffer)
{ {
var image = renderTarget.GetImage();
VulkanMemoryHelper.TransitionLayout(_device, commandBuffer, VulkanMemoryHelper.TransitionLayout(_device, commandBuffer,
renderTarget.Image.InternalHandle.Value, (ImageLayout)renderTarget.Image.CurrentLayout, image.InternalHandle.Value, (ImageLayout)image.CurrentLayout,
AccessFlags.AccessNoneKhr, AccessFlags.AccessNoneKhr,
ImageLayout.TransferSrcOptimal, ImageLayout.TransferSrcOptimal,
AccessFlags.AccessTransferReadBit, 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, ImageLayout.TransferSrcOptimal,
_swapchainImages[_nextImage], _swapchainImages[_nextImage],
ImageLayout.TransferDstOptimal, ImageLayout.TransferDstOptimal,
@@ -390,9 +405,9 @@ namespace Ryujinx.Ava.Ui.Vulkan
Filter.Linear); Filter.Linear);
VulkanMemoryHelper.TransitionLayout(_device, commandBuffer, VulkanMemoryHelper.TransitionLayout(_device, commandBuffer,
renderTarget.Image.InternalHandle.Value, ImageLayout.TransferSrcOptimal, image.InternalHandle.Value, ImageLayout.TransferSrcOptimal,
AccessFlags.AccessTransferReadBit, AccessFlags.AccessTransferReadBit,
(ImageLayout)renderTarget.Image.CurrentLayout, (ImageLayout)image.CurrentLayout,
AccessFlags.AccessNoneKhr, AccessFlags.AccessNoneKhr,
renderTarget.MipLevels); renderTarget.MipLevels);
} }
@@ -434,6 +449,8 @@ namespace Ryujinx.Ava.Ui.Vulkan
} }
CommandBufferPool.FreeUsedCommandBuffers(); CommandBufferPool.FreeUsedCommandBuffers();
Presented?.Invoke(this, null);
} }
} }
} }

View File

@@ -148,20 +148,18 @@ namespace Ryujinx.Ava.Ui.Vulkan
_currentAccessFlags = destinationAccessFlags; _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() _imageView = default;
{ InternalHandle = null;
_device.Api.DestroyImageView(_device.InternalHandle, _imageView.Value, null); _imageMemory = default;
_device.Api.DestroyImage(_device.InternalHandle, InternalHandle.Value, null); }
_device.Api.FreeMemory(_device.InternalHandle, _imageMemory, null);
_imageView = default;
InternalHandle = default;
_imageMemory = default;
} }
} }
} }

View File

@@ -57,8 +57,7 @@ namespace Ryujinx.Ava.Ui.Vulkan
var applicationInfo = new ApplicationInfo var applicationInfo = new ApplicationInfo
{ {
PApplicationName = (byte*)applicationName, PApplicationName = (byte*)applicationName,
ApiVersion = new Version32((uint)options.VulkanVersion.Major, (uint)options.VulkanVersion.Minor, ApiVersion = Vk.Version12.Value,
(uint)options.VulkanVersion.Build),
PEngineName = (byte*)engineName, PEngineName = (byte*)engineName,
EngineVersion = new Version32(1, 0, 0), EngineVersion = new Version32(1, 0, 0),
ApplicationVersion = new Version32(1, 0, 0) ApplicationVersion = new Version32(1, 0, 0)

View File

@@ -11,11 +11,6 @@ namespace Ryujinx.Ava.Ui.Vulkan
/// </summary> /// </summary>
public string ApplicationName { get; set; } 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> /// <summary>
/// Specifies additional extensions to enable if available on the instance /// Specifies additional extensions to enable if available on the instance
/// </summary> /// </summary>

View File

@@ -18,13 +18,11 @@ namespace Ryujinx.Ava.Ui.Vulkan
public VulkanPhysicalDevice PhysicalDevice { get; private set; } public VulkanPhysicalDevice PhysicalDevice { get; private set; }
public VulkanInstance Instance { get; } public VulkanInstance Instance { get; }
public VulkanDevice Device { get; set; }
public Vk Api { get; private set; } public Vk Api { get; private set; }
public VulkanSurfaceRenderTarget MainSurface { get; set; } public VulkanSurfaceRenderTarget MainSurface { get; set; }
public void Dispose() public void Dispose()
{ {
Device?.Dispose();
Instance?.Dispose(); Instance?.Dispose();
Api?.Dispose(); Api?.Dispose();
} }
@@ -54,16 +52,9 @@ namespace Ryujinx.Ava.Ui.Vulkan
{ {
var surface = VulkanSurface.CreateSurface(Instance, platformSurface); var surface = VulkanSurface.CreateSurface(Instance, platformSurface);
if (Device == null) if (PhysicalDevice == null)
{ {
PhysicalDevice = VulkanPhysicalDevice.FindSuitablePhysicalDevice(Instance, surface, _options.PreferDiscreteGpu, _options.PreferredDevice); 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); var renderTarget = new VulkanSurfaceRenderTarget(this, surface);
@@ -71,7 +62,6 @@ namespace Ryujinx.Ava.Ui.Vulkan
if (MainSurface == null && surface != null) if (MainSurface == null && surface != null)
{ {
MainSurface = renderTarget; MainSurface = renderTarget;
MainSurface.Display.ChangeVSyncMode(false);
} }
return renderTarget; return renderTarget;

View File

@@ -9,7 +9,6 @@ namespace Ryujinx.Ava.Ui.Vulkan
{ {
private readonly VulkanDevice _device; private readonly VulkanDevice _device;
private readonly VulkanSurfaceRenderTarget _renderTarget; private readonly VulkanSurfaceRenderTarget _renderTarget;
private VulkanCommandBufferPool.VulkanCommandBuffer _commandBuffer;
public VulkanSurfaceRenderingSession(VulkanDisplay display, VulkanDevice device, public VulkanSurfaceRenderingSession(VulkanDisplay display, VulkanDevice device,
VulkanSurfaceRenderTarget renderTarget, float scaling) VulkanSurfaceRenderTarget renderTarget, float scaling)
@@ -32,17 +31,13 @@ namespace Ryujinx.Ava.Ui.Vulkan
{ {
if (!Display.EnsureSwapchainAvailable()) if (!Display.EnsureSwapchainAvailable())
{ {
_renderTarget.Invalidate(); _renderTarget.RecreateImage();
} }
} }
public void Dispose() public void Dispose()
{ {
_commandBuffer = Display.StartPresentation(_renderTarget); _renderTarget.EndDraw();
Display.BlitImageToCurrentImage(_renderTarget, _commandBuffer.InternalHandle);
Display.EndPresentation(_commandBuffer);
} }
} }
} }

View File

@@ -1,9 +1,7 @@
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Ui.Models; using Ryujinx.Ava.Ui.Models;
using Ryujinx.Ava.Ui.Windows;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.Ui.Controls

View File

@@ -37,7 +37,7 @@ namespace Ryujinx.Ava.Ui.Controls
public override void DestroyBackgroundContext() public override void DestroyBackgroundContext()
{ {
_image = null; Image = null;
if (_fence != IntPtr.Zero) if (_fence != IntPtr.Zero)
{ {
@@ -57,6 +57,8 @@ namespace Ryujinx.Ava.Ui.Controls
Dispatcher.UIThread.InvokeAsync(() => Dispatcher.UIThread.InvokeAsync(() =>
{ {
Image = (int)image; Image = (int)image;
InvalidateVisual();
}).Wait(); }).Wait();
if (_fence != IntPtr.Zero) if (_fence != IntPtr.Zero)
@@ -66,7 +68,7 @@ namespace Ryujinx.Ava.Ui.Controls
_fence = GL.FenceSync(SyncCondition.SyncGpuCommandsComplete, WaitSyncFlags.None); _fence = GL.FenceSync(SyncCondition.SyncGpuCommandsComplete, WaitSyncFlags.None);
QueueRender(); InvalidateVisual();
_gameBackgroundWindow.SwapBuffers(); _gameBackgroundWindow.SwapBuffers();
} }

View File

@@ -11,25 +11,7 @@ namespace Ryujinx.Ava.Ui.Controls
{ {
internal abstract class RendererControl : Control internal abstract class RendererControl : Control
{ {
protected object _image; protected object Image { get; set; }
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);
}
public event EventHandler<EventArgs> RendererInitialized; public event EventHandler<EventArgs> RendererInitialized;
public event EventHandler<Size> SizeChanged; public event EventHandler<Size> SizeChanged;
@@ -60,8 +42,6 @@ namespace Ryujinx.Ava.Ui.Controls
if (!rect.IsEmpty) if (!rect.IsEmpty)
{ {
RenderSize = rect.Size * VisualRoot.RenderScaling; RenderSize = rect.Size * VisualRoot.RenderScaling;
DrawOperation?.Dispose();
DrawOperation = CreateDrawOperation(); DrawOperation = CreateDrawOperation();
} }
} }
@@ -97,17 +77,11 @@ namespace Ryujinx.Ava.Ui.Controls
RendererInitialized?.Invoke(this, EventArgs.Empty); RendererInitialized?.Invoke(this, EventArgs.Empty);
} }
public void QueueRender()
{
Program.RenderTimer.TickNow();
}
internal abstract void Present(object image); internal abstract void Present(object image);
internal void Start() internal void Start()
{ {
IsStarted = true; IsStarted = true;
QueueRender();
} }
internal void Stop() internal void Stop()

View File

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

View File

@@ -1,4 +1,5 @@
using Avalonia; using Avalonia;
using Avalonia.Media;
using Avalonia.Platform; using Avalonia.Platform;
using Avalonia.Rendering.SceneGraph; using Avalonia.Rendering.SceneGraph;
using Avalonia.Skia; using Avalonia.Skia;
@@ -11,20 +12,23 @@ using Silk.NET.Vulkan;
using SkiaSharp; using SkiaSharp;
using SPB.Windowing; using SPB.Windowing;
using System; using System;
using System.Collections.Generic; using System.Collections.Concurrent;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.Ui.Controls
{ {
internal class VulkanRendererControl : RendererControl internal class VulkanRendererControl : RendererControl
{ {
private const int MaxImagesInFlight = 3;
private VulkanPlatformInterface _platformInterface; private VulkanPlatformInterface _platformInterface;
private ConcurrentQueue<PresentImageInfo> _imagesInFlight;
private PresentImageInfo _currentImage;
public VulkanRendererControl(GraphicsDebugLevel graphicsDebugLevel) : base(graphicsDebugLevel) public VulkanRendererControl(GraphicsDebugLevel graphicsDebugLevel) : base(graphicsDebugLevel)
{ {
_platformInterface = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>(); _platformInterface = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>();
_imagesInFlight = new ConcurrentQueue<PresentImageInfo>();
} }
public override void DestroyBackgroundContext() public override void DestroyBackgroundContext()
@@ -37,6 +41,40 @@ namespace Ryujinx.Ava.Ui.Controls
return new VulkanDrawOperation(this); 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() protected override void CreateWindow()
{ {
} }
@@ -51,12 +89,29 @@ namespace Ryujinx.Ava.Ui.Controls
internal override void Present(object image) internal override void Present(object image)
{ {
Dispatcher.UIThread.InvokeAsync(() => Image = image;
{
Image = image;
}).Wait();
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 private class VulkanDrawOperation : ICustomDrawOperation
@@ -64,6 +119,7 @@ namespace Ryujinx.Ava.Ui.Controls
public Rect Bounds { get; } public Rect Bounds { get; }
private readonly VulkanRendererControl _control; private readonly VulkanRendererControl _control;
private bool _isDestroyed;
public VulkanDrawOperation(VulkanRendererControl control) public VulkanDrawOperation(VulkanRendererControl control)
{ {
@@ -73,7 +129,12 @@ namespace Ryujinx.Ava.Ui.Controls
public void Dispose() public void Dispose()
{ {
if (_isDestroyed)
{
return;
}
_isDestroyed = true;
} }
public bool Equals(ICustomDrawOperation other) public bool Equals(ICustomDrawOperation other)
@@ -86,30 +147,33 @@ namespace Ryujinx.Ava.Ui.Controls
return Bounds.Contains(p); 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; return;
} }
var image = (PresentImageInfo)_control.Image; var image = _control.GetImage();
if (context is not ISkiaDrawingContextImpl skiaDrawingContextImpl) if (!image.State.IsValid)
{ {
_control._currentImage = null;
return; return;
} }
_control._platformInterface.Device.QueueWaitIdle();
var gpu = AvaloniaLocator.Current.GetService<VulkanSkiaGpu>(); var gpu = AvaloniaLocator.Current.GetService<VulkanSkiaGpu>();
image.Get();
var imageInfo = new GRVkImageInfo() var imageInfo = new GRVkImageInfo()
{ {
CurrentQueueFamily = _control._platformInterface.PhysicalDevice.QueueFamilyIndex, CurrentQueueFamily = _control._platformInterface.PhysicalDevice.QueueFamilyIndex,
Format = (uint)Format.R8G8B8A8Unorm, Format = (uint)Format.R8G8B8A8Unorm,
Image = image.Image.Handle, Image = image.Image.Handle,
ImageLayout = (uint)ImageLayout.ColorAttachmentOptimal, ImageLayout = (uint)ImageLayout.TransferSrcOptimal,
ImageTiling = (uint)ImageTiling.Optimal, ImageTiling = (uint)ImageTiling.Optimal,
ImageUsageFlags = (uint)(ImageUsageFlags.ImageUsageColorAttachmentBit ImageUsageFlags = (uint)(ImageUsageFlags.ImageUsageColorAttachmentBit
| ImageUsageFlags.ImageUsageTransferSrcBit | ImageUsageFlags.ImageUsageTransferSrcBit
@@ -127,13 +191,15 @@ namespace Ryujinx.Ava.Ui.Controls
}; };
using var backendTexture = new GRBackendRenderTarget( using var backendTexture = new GRBackendRenderTarget(
(int)_control.RenderSize.Width, (int)image.Extent.Width,
(int)_control.RenderSize.Height, (int)image.Extent.Height,
1, 1,
imageInfo); imageInfo);
var vulkan = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>();
using var surface = SKSurface.Create( using var surface = SKSurface.Create(
gpu.GrContext, skiaDrawingContextImpl.GrContext,
backendTexture, backendTexture,
GRSurfaceOrigin.TopLeft, GRSurfaceOrigin.TopLeft,
SKColorType.Rgba8888); SKColorType.Rgba8888);
@@ -143,10 +209,11 @@ namespace Ryujinx.Ava.Ui.Controls
return; 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(); 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.Controls.ApplicationLifetimes;
using Avalonia.Svg.Skia; using Avalonia.Svg.Skia;
using Avalonia.Threading; using Avalonia.Threading;
using Avalonia.VisualTree;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Input; using Ryujinx.Ava.Input;
using Ryujinx.Ava.Ui.Controls; using Ryujinx.Ava.Ui.Controls;
@@ -24,7 +23,6 @@ using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Text.Json; using System.Text.Json;
using ConfigGamepadInputId = Ryujinx.Common.Configuration.Hid.Controller.GamepadInputId; using ConfigGamepadInputId = Ryujinx.Common.Configuration.Hid.Controller.GamepadInputId;
using ConfigStickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId; using ConfigStickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;

View File

@@ -38,6 +38,8 @@ namespace Ryujinx.Ava.Ui.ViewModels
{ {
internal class MainWindowViewModel : BaseModel internal class MainWindowViewModel : BaseModel
{ {
private const int HotKeyPressDelayMs = 500;
private readonly MainWindow _owner; private readonly MainWindow _owner;
private ObservableCollection<ApplicationData> _applications; private ObservableCollection<ApplicationData> _applications;
private string _aspectStatusText; private string _aspectStatusText;
@@ -54,6 +56,7 @@ namespace Ryujinx.Ava.Ui.ViewModels
private bool _isLoading; private bool _isLoading;
private int _progressMaximum; private int _progressMaximum;
private int _progressValue; private int _progressValue;
private long _lastFullscreenToggle = Environment.TickCount64;
private bool _showLoadProgress; private bool _showLoadProgress;
private bool _showMenuAndStatusBar = true; private bool _showMenuAndStatusBar = true;
private bool _showStatusSeparator; private bool _showStatusSeparator;
@@ -929,6 +932,13 @@ namespace Ryujinx.Ava.Ui.ViewModels
public void ToggleFullscreen() public void ToggleFullscreen()
{ {
if (Environment.TickCount64 - _lastFullscreenToggle < HotKeyPressDelayMs)
{
return;
}
_lastFullscreenToggle = Environment.TickCount64;
WindowState state = _owner.WindowState; WindowState state = _owner.WindowState;
if (state == WindowState.FullScreen) if (state == WindowState.FullScreen)
@@ -1085,6 +1095,11 @@ namespace Ryujinx.Ava.Ui.ViewModels
{ {
selection.Favorite = !selection.Favorite; selection.Favorite = !selection.Favorite;
_owner.ApplicationLibrary.LoadAndSaveMetaData(selection.TitleId, appMetadata =>
{
appMetadata.Favorite = selection.Favorite;
});
RefreshView(); RefreshView();
} }
} }

View File

@@ -48,6 +48,11 @@ namespace Ryujinx.Ava.Ui.ViewModels
private int _graphicsBackendMultithreadingIndex; private int _graphicsBackendMultithreadingIndex;
private float _previousVolumeLevel; private float _previousVolumeLevel;
private float _volume; 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 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 EnableDiscordIntegration { get; set; }
public bool CheckUpdatesOnStart { get; set; } public bool CheckUpdatesOnStart { get; set; }
public bool ShowConfirmExit { get; set; } public bool ShowConfirmExit { get; set; }
@@ -143,10 +170,10 @@ namespace Ryujinx.Ava.Ui.ViewModels
public int BaseStyleIndex { get; set; } public int BaseStyleIndex { get; set; }
public int GraphicsBackendIndex public int GraphicsBackendIndex
{ {
get => graphicsBackendIndex; get => _graphicsBackendIndex;
set set
{ {
graphicsBackendIndex = value; _graphicsBackendIndex = value;
OnPropertyChanged(); OnPropertyChanged();
OnPropertyChanged(nameof(IsVulkanSelected)); OnPropertyChanged(nameof(IsVulkanSelected));
} }
@@ -170,14 +197,9 @@ namespace Ryujinx.Ava.Ui.ViewModels
public DateTimeOffset DateOffset { get; set; } public DateTimeOffset DateOffset { get; set; }
public TimeSpan TimeOffset { get; set; } public TimeSpan TimeOffset { get; set; }
public AvaloniaList<TimeZone> TimeZones { get; set; } public AvaloniaList<TimeZone> TimeZones { get; set; }
public AvaloniaList<string> GameDirectories { get; set; } public AvaloniaList<string> GameDirectories { get; set; }
public ObservableCollection<ComboBoxItem> AvailableGpus { get; set; } public ObservableCollection<ComboBoxItem> AvailableGpus { get; set; }
private KeyboardHotkeys _keyboardHotkeys;
private int graphicsBackendIndex;
private List<string> _gpuIds = new List<string>();
public KeyboardHotkeys KeyboardHotkeys public KeyboardHotkeys KeyboardHotkeys
{ {
get => _keyboardHotkeys; get => _keyboardHotkeys;
@@ -233,20 +255,31 @@ namespace Ryujinx.Ava.Ui.ViewModels
if (!Program.UseVulkan) if (!Program.UseVulkan)
{ {
var devices = VulkanRenderer.GetPhysicalDevices(); var devices = VulkanRenderer.GetPhysicalDevices();
foreach (var device in devices)
if (devices.Length == 0)
{ {
_gpuIds.Add(device.Id); IsVulkanAvailable = false;
names.Add($"{device.Name} {(device.IsDiscrete ? "(dGpu)" : "")}"); GraphicsBackendIndex = 1;
}
else
{
foreach (var device in devices)
{
_gpuIds.Add(device.Id);
names.Add($"{device.Name} {(device.IsDiscrete ? "(dGPU)" : "")}");
}
} }
} }
else else
{ {
foreach (var device in VulkanPhysicalDevice.SuitableDevices) 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 value = device.Value;
var name = value.DeviceName; 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() public async Task SaveSettings()
{ {
List<string> gameDirs = new List<string>(GameDirectories);
ConfigurationState config = ConfigurationState.Instance; ConfigurationState config = ConfigurationState.Instance;
if (_directoryChanged)
{
List<string> gameDirs = new List<string>(GameDirectories);
config.Ui.GameDirs.Value = gameDirs;
}
if (_validTzRegions.Contains(TimeZone)) if (_validTzRegions.Contains(TimeZone))
{ {
config.System.TimeZone.Value = TimeZone; config.System.TimeZone.Value = TimeZone;
@@ -444,7 +481,6 @@ namespace Ryujinx.Ava.Ui.ViewModels
config.System.SystemTimeOffset.Value = systemTimeOffset.Seconds; config.System.SystemTimeOffset.Value = systemTimeOffset.Seconds;
config.Graphics.ShadersDumpPath.Value = ShaderDumpPath; config.Graphics.ShadersDumpPath.Value = ShaderDumpPath;
config.Ui.GameDirs.Value = gameDirs;
config.System.FsGlobalAccessLogMode.Value = FsGlobalAccessLogMode; config.System.FsGlobalAccessLogMode.Value = FsGlobalAccessLogMode;
config.System.MemoryManagerMode.Value = (MemoryManagerMode)MemoryMode; 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.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Threading; using Avalonia.Threading;

View File

@@ -1,4 +1,3 @@
using Avalonia;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Ui.Models; 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.Common.Locale;
using Ryujinx.Ava.Ui.Models; using Ryujinx.Ava.Ui.Models;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS; using Ryujinx.HLE.HOS;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;

View File

@@ -12,7 +12,6 @@ using Ryujinx.Ava.Ui.Applet;
using Ryujinx.Ava.Ui.Controls; using Ryujinx.Ava.Ui.Controls;
using Ryujinx.Ava.Ui.Models; using Ryujinx.Ava.Ui.Models;
using Ryujinx.Ava.Ui.ViewModels; using Ryujinx.Ava.Ui.ViewModels;
using Ryujinx.Ava.Ui.Vulkan;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Graphics.Gpu; using Ryujinx.Graphics.Gpu;
@@ -27,7 +26,6 @@ using Ryujinx.Ui.Common.Configuration;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -656,7 +654,12 @@ namespace Ryujinx.Ava.Ui.Windows
{ {
AppHost = null; AppHost = null;
Dispatcher.UIThread.Post(Close); Dispatcher.UIThread.Post(() =>
{
MainContent = null;
Close();
});
}; };
AppHost?.Stop(); AppHost?.Stop();

View File

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

View File

@@ -162,6 +162,7 @@ namespace Ryujinx.Ava.Ui.Windows
if (!string.IsNullOrWhiteSpace(path) && Directory.Exists(path) && !ViewModel.GameDirectories.Contains(path)) if (!string.IsNullOrWhiteSpace(path) && Directory.Exists(path) && !ViewModel.GameDirectories.Contains(path))
{ {
ViewModel.GameDirectories.Add(path); ViewModel.GameDirectories.Add(path);
ViewModel.DirectoryChanged = true;
} }
else else
{ {
@@ -170,6 +171,7 @@ namespace Ryujinx.Ava.Ui.Windows
if (!string.IsNullOrWhiteSpace(path)) if (!string.IsNullOrWhiteSpace(path))
{ {
ViewModel.GameDirectories.Add(path); ViewModel.GameDirectories.Add(path);
ViewModel.DirectoryChanged = true;
} }
} }
} }
@@ -181,6 +183,7 @@ namespace Ryujinx.Ava.Ui.Windows
foreach (string path in selected) foreach (string path in selected)
{ {
ViewModel.GameDirectories.Remove(path); ViewModel.GameDirectories.Remove(path);
ViewModel.DirectoryChanged = true;
} }
} }
@@ -232,10 +235,12 @@ namespace Ryujinx.Ava.Ui.Windows
ControllerSettings?.SaveCurrentProfile(); ControllerSettings?.SaveCurrentProfile();
if (Owner is MainWindow window) if (Owner is MainWindow window && ViewModel.DirectoryChanged)
{ {
window.ViewModel.LoadApplications(); window.ViewModel.LoadApplications();
} }
ViewModel.DirectoryChanged = false;
} }
protected override void OnClosed(EventArgs e) protected override void OnClosed(EventArgs e)

View File

@@ -1,4 +1,3 @@
using Avalonia;
using Avalonia.Collections; using Avalonia.Collections;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Threading; using Avalonia.Threading;
@@ -18,7 +17,6 @@ using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS; using Ryujinx.HLE.HOS;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

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

View File

@@ -1,8 +1,6 @@
using Ryujinx.Common.Configuration.Hid.Controller.Motion; using Ryujinx.Common.Configuration.Hid.Controller.Motion;
using System; using System;
using System.ComponentModel;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using NotImplementedException = System.NotImplementedException;
namespace Ryujinx.Common.Configuration.Hid.Controller 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 namespace Ryujinx.Common.GraphicsDriver.NVAPI
{ {

View File

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

View File

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

View File

@@ -87,7 +87,7 @@ namespace Ryujinx.Common.Memory
/// Gets a span from the array. /// Gets a span from the array.
/// </summary> /// </summary>
/// <returns>Span of the array</returns> /// <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> /// <summary>
/// Gets the array base pointer. /// 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 /// 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. /// 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 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 /// This version of the function is not used, but serves as a reference for the native
/// implementation in ARMeilleure. /// implementation in ARMeilleure.
/// </remarks> /// </remarks>
@@ -128,12 +128,12 @@ namespace Ryujinx.Common.Memory.PartialUnmaps
const uint ExitCodeStillActive = 259; const uint ExitCodeStillActive = 259;
const int ThreadQueryInformation = 0x40; const int ThreadQueryInformation = 0x40;
Span<int> ids = LocalCounts.ThreadIds.ToSpan(); Span<int> ids = LocalCounts.ThreadIds.AsSpan();
for (int i = 0; i < ids.Length; i++) for (int i = 0; i < ids.Length; i++)
{ {
int id = ids[i]; int id = ids[i];
if (id != 0) if (id != 0)
{ {
IntPtr handle = OpenThread(ThreadQueryInformation, false, (uint)id); IntPtr handle = OpenThread(ThreadQueryInformation, false, (uint)id);

View File

@@ -7,8 +7,8 @@ namespace Ryujinx.Common.Memory
{ {
T _e0; T _e0;
public int Length => 1; public int Length => 1;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 1); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 1);
} }
public struct Array2<T> : IArray<T> where T : unmanaged public struct Array2<T> : IArray<T> where T : unmanaged
{ {
@@ -17,8 +17,8 @@ namespace Ryujinx.Common.Memory
Array1<T> _other; Array1<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 2; public int Length => 2;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 2); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 2);
} }
public struct Array3<T> : IArray<T> where T : unmanaged public struct Array3<T> : IArray<T> where T : unmanaged
{ {
@@ -27,8 +27,8 @@ namespace Ryujinx.Common.Memory
Array2<T> _other; Array2<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 3; public int Length => 3;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 3); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 3);
} }
public struct Array4<T> : IArray<T> where T : unmanaged public struct Array4<T> : IArray<T> where T : unmanaged
{ {
@@ -37,8 +37,8 @@ namespace Ryujinx.Common.Memory
Array3<T> _other; Array3<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 4; public int Length => 4;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 4); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 4);
} }
public struct Array5<T> : IArray<T> where T : unmanaged public struct Array5<T> : IArray<T> where T : unmanaged
{ {
@@ -47,8 +47,8 @@ namespace Ryujinx.Common.Memory
Array4<T> _other; Array4<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 5; public int Length => 5;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 5); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 5);
} }
public struct Array6<T> : IArray<T> where T : unmanaged public struct Array6<T> : IArray<T> where T : unmanaged
{ {
@@ -57,8 +57,8 @@ namespace Ryujinx.Common.Memory
Array5<T> _other; Array5<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 6; public int Length => 6;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 6); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 6);
} }
public struct Array7<T> : IArray<T> where T : unmanaged public struct Array7<T> : IArray<T> where T : unmanaged
{ {
@@ -67,8 +67,8 @@ namespace Ryujinx.Common.Memory
Array6<T> _other; Array6<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 7; public int Length => 7;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 7); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 7);
} }
public struct Array8<T> : IArray<T> where T : unmanaged public struct Array8<T> : IArray<T> where T : unmanaged
{ {
@@ -77,8 +77,8 @@ namespace Ryujinx.Common.Memory
Array7<T> _other; Array7<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 8; public int Length => 8;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 8); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 8);
} }
public struct Array9<T> : IArray<T> where T : unmanaged public struct Array9<T> : IArray<T> where T : unmanaged
{ {
@@ -87,8 +87,8 @@ namespace Ryujinx.Common.Memory
Array8<T> _other; Array8<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 9; public int Length => 9;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 9); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 9);
} }
public struct Array10<T> : IArray<T> where T : unmanaged public struct Array10<T> : IArray<T> where T : unmanaged
{ {
@@ -97,8 +97,8 @@ namespace Ryujinx.Common.Memory
Array9<T> _other; Array9<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 10; public int Length => 10;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 10); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 10);
} }
public struct Array11<T> : IArray<T> where T : unmanaged public struct Array11<T> : IArray<T> where T : unmanaged
{ {
@@ -107,8 +107,8 @@ namespace Ryujinx.Common.Memory
Array10<T> _other; Array10<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 11; public int Length => 11;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 11); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 11);
} }
public struct Array12<T> : IArray<T> where T : unmanaged public struct Array12<T> : IArray<T> where T : unmanaged
{ {
@@ -117,8 +117,8 @@ namespace Ryujinx.Common.Memory
Array11<T> _other; Array11<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 12; public int Length => 12;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 12); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 12);
} }
public struct Array13<T> : IArray<T> where T : unmanaged public struct Array13<T> : IArray<T> where T : unmanaged
{ {
@@ -127,8 +127,8 @@ namespace Ryujinx.Common.Memory
Array12<T> _other; Array12<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 13; public int Length => 13;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 13); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 13);
} }
public struct Array14<T> : IArray<T> where T : unmanaged public struct Array14<T> : IArray<T> where T : unmanaged
{ {
@@ -137,8 +137,8 @@ namespace Ryujinx.Common.Memory
Array13<T> _other; Array13<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 14; public int Length => 14;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 14); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 14);
} }
public struct Array15<T> : IArray<T> where T : unmanaged public struct Array15<T> : IArray<T> where T : unmanaged
{ {
@@ -147,8 +147,8 @@ namespace Ryujinx.Common.Memory
Array14<T> _other; Array14<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 15; public int Length => 15;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 15); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 15);
} }
public struct Array16<T> : IArray<T> where T : unmanaged public struct Array16<T> : IArray<T> where T : unmanaged
{ {
@@ -157,8 +157,8 @@ namespace Ryujinx.Common.Memory
Array15<T> _other; Array15<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 16; public int Length => 16;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 16); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 16);
} }
public struct Array17<T> : IArray<T> where T : unmanaged public struct Array17<T> : IArray<T> where T : unmanaged
{ {
@@ -167,8 +167,8 @@ namespace Ryujinx.Common.Memory
Array16<T> _other; Array16<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 17; public int Length => 17;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 17); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 17);
} }
public struct Array18<T> : IArray<T> where T : unmanaged public struct Array18<T> : IArray<T> where T : unmanaged
{ {
@@ -177,8 +177,8 @@ namespace Ryujinx.Common.Memory
Array17<T> _other; Array17<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 18; public int Length => 18;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 18); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 18);
} }
public struct Array19<T> : IArray<T> where T : unmanaged public struct Array19<T> : IArray<T> where T : unmanaged
{ {
@@ -187,8 +187,8 @@ namespace Ryujinx.Common.Memory
Array18<T> _other; Array18<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 19; public int Length => 19;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 19); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 19);
} }
public struct Array20<T> : IArray<T> where T : unmanaged public struct Array20<T> : IArray<T> where T : unmanaged
{ {
@@ -197,8 +197,8 @@ namespace Ryujinx.Common.Memory
Array19<T> _other; Array19<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 20; public int Length => 20;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 20); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 20);
} }
public struct Array21<T> : IArray<T> where T : unmanaged public struct Array21<T> : IArray<T> where T : unmanaged
{ {
@@ -207,8 +207,8 @@ namespace Ryujinx.Common.Memory
Array20<T> _other; Array20<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 21; public int Length => 21;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 21); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 21);
} }
public struct Array22<T> : IArray<T> where T : unmanaged public struct Array22<T> : IArray<T> where T : unmanaged
{ {
@@ -217,8 +217,8 @@ namespace Ryujinx.Common.Memory
Array21<T> _other; Array21<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 22; public int Length => 22;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 22); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 22);
} }
public struct Array23<T> : IArray<T> where T : unmanaged public struct Array23<T> : IArray<T> where T : unmanaged
{ {
@@ -227,8 +227,8 @@ namespace Ryujinx.Common.Memory
Array22<T> _other; Array22<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 23; public int Length => 23;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 23); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 23);
} }
public struct Array24<T> : IArray<T> where T : unmanaged public struct Array24<T> : IArray<T> where T : unmanaged
{ {
@@ -237,8 +237,8 @@ namespace Ryujinx.Common.Memory
Array23<T> _other; Array23<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 24; public int Length => 24;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 24); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 24);
} }
public struct Array25<T> : IArray<T> where T : unmanaged public struct Array25<T> : IArray<T> where T : unmanaged
{ {
@@ -247,8 +247,8 @@ namespace Ryujinx.Common.Memory
Array24<T> _other; Array24<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 25; public int Length => 25;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 25); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 25);
} }
public struct Array26<T> : IArray<T> where T : unmanaged public struct Array26<T> : IArray<T> where T : unmanaged
{ {
@@ -257,8 +257,8 @@ namespace Ryujinx.Common.Memory
Array25<T> _other; Array25<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 26; public int Length => 26;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 26); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 26);
} }
public struct Array27<T> : IArray<T> where T : unmanaged public struct Array27<T> : IArray<T> where T : unmanaged
{ {
@@ -267,8 +267,8 @@ namespace Ryujinx.Common.Memory
Array26<T> _other; Array26<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 27; public int Length => 27;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 27); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 27);
} }
public struct Array28<T> : IArray<T> where T : unmanaged public struct Array28<T> : IArray<T> where T : unmanaged
{ {
@@ -277,8 +277,8 @@ namespace Ryujinx.Common.Memory
Array27<T> _other; Array27<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 28; public int Length => 28;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 28); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 28);
} }
public struct Array29<T> : IArray<T> where T : unmanaged public struct Array29<T> : IArray<T> where T : unmanaged
{ {
@@ -287,8 +287,8 @@ namespace Ryujinx.Common.Memory
Array28<T> _other; Array28<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 29; public int Length => 29;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 29); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 29);
} }
public struct Array30<T> : IArray<T> where T : unmanaged public struct Array30<T> : IArray<T> where T : unmanaged
{ {
@@ -297,8 +297,8 @@ namespace Ryujinx.Common.Memory
Array29<T> _other; Array29<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 30; public int Length => 30;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 30); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 30);
} }
public struct Array31<T> : IArray<T> where T : unmanaged public struct Array31<T> : IArray<T> where T : unmanaged
{ {
@@ -307,8 +307,8 @@ namespace Ryujinx.Common.Memory
Array30<T> _other; Array30<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 31; public int Length => 31;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 31); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 31);
} }
public struct Array32<T> : IArray<T> where T : unmanaged public struct Array32<T> : IArray<T> where T : unmanaged
{ {
@@ -317,8 +317,8 @@ namespace Ryujinx.Common.Memory
Array31<T> _other; Array31<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 32; public int Length => 32;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 32); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 32);
} }
public struct Array33<T> : IArray<T> where T : unmanaged public struct Array33<T> : IArray<T> where T : unmanaged
{ {
@@ -327,8 +327,8 @@ namespace Ryujinx.Common.Memory
Array32<T> _other; Array32<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 33; public int Length => 33;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 33); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 33);
} }
public struct Array34<T> : IArray<T> where T : unmanaged public struct Array34<T> : IArray<T> where T : unmanaged
{ {
@@ -337,8 +337,8 @@ namespace Ryujinx.Common.Memory
Array33<T> _other; Array33<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 34; public int Length => 34;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 34); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 34);
} }
public struct Array35<T> : IArray<T> where T : unmanaged public struct Array35<T> : IArray<T> where T : unmanaged
{ {
@@ -347,8 +347,8 @@ namespace Ryujinx.Common.Memory
Array34<T> _other; Array34<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 35; public int Length => 35;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 35); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 35);
} }
public struct Array36<T> : IArray<T> where T : unmanaged public struct Array36<T> : IArray<T> where T : unmanaged
{ {
@@ -357,8 +357,8 @@ namespace Ryujinx.Common.Memory
Array35<T> _other; Array35<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 36; public int Length => 36;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 36); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 36);
} }
public struct Array37<T> : IArray<T> where T : unmanaged public struct Array37<T> : IArray<T> where T : unmanaged
{ {
@@ -367,8 +367,8 @@ namespace Ryujinx.Common.Memory
Array36<T> _other; Array36<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 37; public int Length => 37;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 37); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 37);
} }
public struct Array38<T> : IArray<T> where T : unmanaged public struct Array38<T> : IArray<T> where T : unmanaged
{ {
@@ -377,8 +377,8 @@ namespace Ryujinx.Common.Memory
Array37<T> _other; Array37<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 38; public int Length => 38;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 38); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 38);
} }
public struct Array39<T> : IArray<T> where T : unmanaged public struct Array39<T> : IArray<T> where T : unmanaged
{ {
@@ -387,8 +387,8 @@ namespace Ryujinx.Common.Memory
Array38<T> _other; Array38<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 39; public int Length => 39;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 39); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 39);
} }
public struct Array40<T> : IArray<T> where T : unmanaged public struct Array40<T> : IArray<T> where T : unmanaged
{ {
@@ -397,8 +397,8 @@ namespace Ryujinx.Common.Memory
Array39<T> _other; Array39<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 40; public int Length => 40;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 40); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 40);
} }
public struct Array41<T> : IArray<T> where T : unmanaged public struct Array41<T> : IArray<T> where T : unmanaged
{ {
@@ -407,8 +407,8 @@ namespace Ryujinx.Common.Memory
Array40<T> _other; Array40<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 41; public int Length => 41;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 41); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 41);
} }
public struct Array42<T> : IArray<T> where T : unmanaged public struct Array42<T> : IArray<T> where T : unmanaged
{ {
@@ -417,8 +417,8 @@ namespace Ryujinx.Common.Memory
Array41<T> _other; Array41<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 42; public int Length => 42;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 42); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 42);
} }
public struct Array43<T> : IArray<T> where T : unmanaged public struct Array43<T> : IArray<T> where T : unmanaged
{ {
@@ -427,8 +427,8 @@ namespace Ryujinx.Common.Memory
Array42<T> _other; Array42<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 43; public int Length => 43;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 43); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 43);
} }
public struct Array44<T> : IArray<T> where T : unmanaged public struct Array44<T> : IArray<T> where T : unmanaged
{ {
@@ -437,8 +437,8 @@ namespace Ryujinx.Common.Memory
Array43<T> _other; Array43<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 44; public int Length => 44;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 44); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 44);
} }
public struct Array45<T> : IArray<T> where T : unmanaged public struct Array45<T> : IArray<T> where T : unmanaged
{ {
@@ -447,8 +447,8 @@ namespace Ryujinx.Common.Memory
Array44<T> _other; Array44<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 45; public int Length => 45;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 45); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 45);
} }
public struct Array46<T> : IArray<T> where T : unmanaged public struct Array46<T> : IArray<T> where T : unmanaged
{ {
@@ -457,8 +457,8 @@ namespace Ryujinx.Common.Memory
Array45<T> _other; Array45<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 46; public int Length => 46;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 46); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 46);
} }
public struct Array47<T> : IArray<T> where T : unmanaged public struct Array47<T> : IArray<T> where T : unmanaged
{ {
@@ -467,8 +467,8 @@ namespace Ryujinx.Common.Memory
Array46<T> _other; Array46<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 47; public int Length => 47;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 47); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 47);
} }
public struct Array48<T> : IArray<T> where T : unmanaged public struct Array48<T> : IArray<T> where T : unmanaged
{ {
@@ -477,8 +477,8 @@ namespace Ryujinx.Common.Memory
Array47<T> _other; Array47<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 48; public int Length => 48;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 48); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 48);
} }
public struct Array49<T> : IArray<T> where T : unmanaged public struct Array49<T> : IArray<T> where T : unmanaged
{ {
@@ -487,8 +487,8 @@ namespace Ryujinx.Common.Memory
Array48<T> _other; Array48<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 49; public int Length => 49;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 49); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 49);
} }
public struct Array50<T> : IArray<T> where T : unmanaged public struct Array50<T> : IArray<T> where T : unmanaged
{ {
@@ -497,8 +497,8 @@ namespace Ryujinx.Common.Memory
Array49<T> _other; Array49<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 50; public int Length => 50;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 50); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 50);
} }
public struct Array51<T> : IArray<T> where T : unmanaged public struct Array51<T> : IArray<T> where T : unmanaged
{ {
@@ -507,8 +507,8 @@ namespace Ryujinx.Common.Memory
Array50<T> _other; Array50<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 51; public int Length => 51;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 51); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 51);
} }
public struct Array52<T> : IArray<T> where T : unmanaged public struct Array52<T> : IArray<T> where T : unmanaged
{ {
@@ -517,8 +517,8 @@ namespace Ryujinx.Common.Memory
Array51<T> _other; Array51<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 52; public int Length => 52;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 52); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 52);
} }
public struct Array53<T> : IArray<T> where T : unmanaged public struct Array53<T> : IArray<T> where T : unmanaged
{ {
@@ -527,8 +527,8 @@ namespace Ryujinx.Common.Memory
Array52<T> _other; Array52<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 53; public int Length => 53;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 53); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 53);
} }
public struct Array54<T> : IArray<T> where T : unmanaged public struct Array54<T> : IArray<T> where T : unmanaged
{ {
@@ -537,8 +537,8 @@ namespace Ryujinx.Common.Memory
Array53<T> _other; Array53<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 54; public int Length => 54;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 54); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 54);
} }
public struct Array55<T> : IArray<T> where T : unmanaged public struct Array55<T> : IArray<T> where T : unmanaged
{ {
@@ -547,8 +547,8 @@ namespace Ryujinx.Common.Memory
Array54<T> _other; Array54<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 55; public int Length => 55;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 55); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 55);
} }
public struct Array56<T> : IArray<T> where T : unmanaged public struct Array56<T> : IArray<T> where T : unmanaged
{ {
@@ -557,8 +557,8 @@ namespace Ryujinx.Common.Memory
Array55<T> _other; Array55<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 56; public int Length => 56;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 56); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 56);
} }
public struct Array57<T> : IArray<T> where T : unmanaged public struct Array57<T> : IArray<T> where T : unmanaged
{ {
@@ -567,8 +567,8 @@ namespace Ryujinx.Common.Memory
Array56<T> _other; Array56<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 57; public int Length => 57;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 57); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 57);
} }
public struct Array58<T> : IArray<T> where T : unmanaged public struct Array58<T> : IArray<T> where T : unmanaged
{ {
@@ -577,8 +577,8 @@ namespace Ryujinx.Common.Memory
Array57<T> _other; Array57<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 58; public int Length => 58;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 58); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 58);
} }
public struct Array59<T> : IArray<T> where T : unmanaged public struct Array59<T> : IArray<T> where T : unmanaged
{ {
@@ -587,8 +587,8 @@ namespace Ryujinx.Common.Memory
Array58<T> _other; Array58<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 59; public int Length => 59;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 59); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 59);
} }
public struct Array60<T> : IArray<T> where T : unmanaged public struct Array60<T> : IArray<T> where T : unmanaged
{ {
@@ -597,8 +597,8 @@ namespace Ryujinx.Common.Memory
Array59<T> _other; Array59<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 60; public int Length => 60;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 60); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 60);
} }
public struct Array61<T> : IArray<T> where T : unmanaged public struct Array61<T> : IArray<T> where T : unmanaged
{ {
@@ -607,8 +607,8 @@ namespace Ryujinx.Common.Memory
Array60<T> _other; Array60<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 61; public int Length => 61;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 61); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 61);
} }
public struct Array62<T> : IArray<T> where T : unmanaged public struct Array62<T> : IArray<T> where T : unmanaged
{ {
@@ -617,8 +617,8 @@ namespace Ryujinx.Common.Memory
Array61<T> _other; Array61<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 62; public int Length => 62;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 62); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 62);
} }
public struct Array63<T> : IArray<T> where T : unmanaged public struct Array63<T> : IArray<T> where T : unmanaged
{ {
@@ -627,8 +627,8 @@ namespace Ryujinx.Common.Memory
Array62<T> _other; Array62<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 63; public int Length => 63;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 63); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 63);
} }
public struct Array64<T> : IArray<T> where T : unmanaged public struct Array64<T> : IArray<T> where T : unmanaged
{ {
@@ -637,8 +637,8 @@ namespace Ryujinx.Common.Memory
Array63<T> _other; Array63<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 64; public int Length => 64;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 64); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 64);
} }
public struct Array73<T> : IArray<T> where T : unmanaged public struct Array73<T> : IArray<T> where T : unmanaged
{ {
@@ -648,7 +648,7 @@ namespace Ryujinx.Common.Memory
Array8<T> _other2; Array8<T> _other2;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 73; public int Length => 73;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 73); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 73);
} }
} }

View File

@@ -11,8 +11,8 @@ namespace Ryujinx.Common.Memory
byte _element; byte _element;
public int Length => Size; public int Length => Size;
public ref byte this[int index] => ref ToSpan()[index]; public ref byte this[int index] => ref AsSpan()[index];
public Span<byte> ToSpan() => MemoryMarshal.CreateSpan(ref _element, Size); public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
} }
[StructLayout(LayoutKind.Sequential, Size = Size, Pack = 1)] [StructLayout(LayoutKind.Sequential, Size = Size, Pack = 1)]
@@ -23,8 +23,8 @@ namespace Ryujinx.Common.Memory
byte _element; byte _element;
public int Length => Size; public int Length => Size;
public ref byte this[int index] => ref ToSpan()[index]; public ref byte this[int index] => ref AsSpan()[index];
public Span<byte> ToSpan() => MemoryMarshal.CreateSpan(ref _element, Size); public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
} }
[StructLayout(LayoutKind.Sequential, Size = Size, Pack = 1)] [StructLayout(LayoutKind.Sequential, Size = Size, Pack = 1)]
@@ -35,8 +35,8 @@ namespace Ryujinx.Common.Memory
byte _element; byte _element;
public int Length => Size; public int Length => Size;
public ref byte this[int index] => ref ToSpan()[index]; public ref byte this[int index] => ref AsSpan()[index];
public Span<byte> ToSpan() => MemoryMarshal.CreateSpan(ref _element, Size); public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
} }
[StructLayout(LayoutKind.Sequential, Size = Size, Pack = 1)] [StructLayout(LayoutKind.Sequential, Size = Size, Pack = 1)]
@@ -47,8 +47,8 @@ namespace Ryujinx.Common.Memory
byte _element; byte _element;
public int Length => Size; public int Length => Size;
public ref byte this[int index] => ref ToSpan()[index]; public ref byte this[int index] => ref AsSpan()[index];
public Span<byte> ToSpan() => MemoryMarshal.CreateSpan(ref _element, Size); public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
} }
[StructLayout(LayoutKind.Sequential, Size = Size, Pack = 1)] [StructLayout(LayoutKind.Sequential, Size = Size, Pack = 1)]
@@ -59,8 +59,8 @@ namespace Ryujinx.Common.Memory
byte _element; byte _element;
public int Length => Size; public int Length => Size;
public ref byte this[int index] => ref ToSpan()[index]; public ref byte this[int index] => ref AsSpan()[index];
public Span<byte> ToSpan() => MemoryMarshal.CreateSpan(ref _element, Size); public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
} }
[StructLayout(LayoutKind.Sequential, Size = Size, Pack = 1)] [StructLayout(LayoutKind.Sequential, Size = Size, Pack = 1)]
@@ -71,7 +71,7 @@ namespace Ryujinx.Common.Memory
byte _element; byte _element;
public int Length => Size; public int Length => Size;
public ref byte this[int index] => ref ToSpan()[index]; public ref byte this[int index] => ref AsSpan()[index];
public Span<byte> ToSpan() => MemoryMarshal.CreateSpan(ref _element, Size); public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

@@ -56,7 +56,6 @@ namespace Ryujinx.Graphics.GAL
D32Float, D32Float,
D24UnormS8Uint, D24UnormS8Uint,
D32FloatS8Uint, D32FloatS8Uint,
R8G8B8X8Srgb,
R8G8B8A8Srgb, R8G8B8A8Srgb,
R4G4Unorm, R4G4Unorm,
R4G4B4A4Unorm, R4G4B4A4Unorm,
@@ -83,8 +82,10 @@ namespace Ryujinx.Graphics.GAL
Bc6HUfloat, Bc6HUfloat,
Etc2RgbUnorm, Etc2RgbUnorm,
Etc2RgbaUnorm, Etc2RgbaUnorm,
Etc2RgbPtaUnorm,
Etc2RgbSrgb, Etc2RgbSrgb,
Etc2RgbaSrgb, Etc2RgbaSrgb,
Etc2RgbPtaSrgb,
R8Uscaled, R8Uscaled,
R8Sscaled, R8Sscaled,
R16Uscaled, R16Uscaled,
@@ -113,18 +114,6 @@ namespace Ryujinx.Graphics.GAL
R10G10B10A2Sint, R10G10B10A2Sint,
R10G10B10A2Uscaled, R10G10B10A2Uscaled,
R10G10B10A2Sscaled, R10G10B10A2Sscaled,
R8G8B8X8Unorm,
R8G8B8X8Snorm,
R8G8B8X8Uint,
R8G8B8X8Sint,
R16G16B16X16Float,
R16G16B16X16Unorm,
R16G16B16X16Snorm,
R16G16B16X16Uint,
R16G16B16X16Sint,
R32G32B32X32Float,
R32G32B32X32Uint,
R32G32B32X32Sint,
Astc4x4Unorm, Astc4x4Unorm,
Astc5x4Unorm, Astc5x4Unorm,
Astc5x5Unorm, Astc5x5Unorm,
@@ -154,12 +143,9 @@ namespace Ryujinx.Graphics.GAL
Astc12x10Srgb, Astc12x10Srgb,
Astc12x12Srgb, Astc12x12Srgb,
B5G6R5Unorm, B5G6R5Unorm,
B5G5R5X1Unorm,
B5G5R5A1Unorm, B5G5R5A1Unorm,
A1B5G5R5Unorm, A1B5G5R5Unorm,
B8G8R8X8Unorm,
B8G8R8A8Unorm, B8G8R8A8Unorm,
B8G8R8X8Srgb,
B8G8R8A8Srgb B8G8R8A8Srgb
} }
@@ -272,7 +258,6 @@ namespace Ryujinx.Graphics.GAL
case Format.R8Snorm: case Format.R8Snorm:
case Format.R8Sint: case Format.R8Sint:
case Format.R8Uint: case Format.R8Uint:
case Format.B5G5R5X1Unorm:
return true; return true;
} }
@@ -357,11 +342,8 @@ namespace Ryujinx.Graphics.GAL
switch (format) switch (format)
{ {
case Format.B5G6R5Unorm: case Format.B5G6R5Unorm:
case Format.B5G5R5X1Unorm:
case Format.B5G5R5A1Unorm: case Format.B5G5R5A1Unorm:
case Format.B8G8R8X8Unorm:
case Format.B8G8R8A8Unorm: case Format.B8G8R8A8Unorm:
case Format.B8G8R8X8Srgb:
case Format.B8G8R8A8Srgb: case Format.B8G8R8A8Srgb:
return true; return true;
} }
@@ -412,9 +394,6 @@ namespace Ryujinx.Graphics.GAL
case Format.R16G16B16A16Uint: case Format.R16G16B16A16Uint:
case Format.R32G32B32A32Uint: case Format.R32G32B32A32Uint:
case Format.R10G10B10A2Uint: case Format.R10G10B10A2Uint:
case Format.R8G8B8X8Uint:
case Format.R16G16B16X16Uint:
case Format.R32G32B32X32Uint:
return true; return true;
} }
@@ -443,9 +422,6 @@ namespace Ryujinx.Graphics.GAL
case Format.R16G16B16A16Sint: case Format.R16G16B16A16Sint:
case Format.R32G32B32A32Sint: case Format.R32G32B32A32Sint:
case Format.R10G10B10A2Sint: case Format.R10G10B10A2Sint:
case Format.R8G8B8X8Sint:
case Format.R16G16B16X16Sint:
case Format.R32G32B32X32Sint:
return true; return true;
} }

View File

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

View File

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

View File

@@ -7,5 +7,7 @@ namespace Ryujinx.Graphics.GAL
void Present(ITexture texture, ImageCrop crop, Action<object> swapBuffersCallback); void Present(ITexture texture, ImageCrop crop, Action<object> swapBuffersCallback);
void SetSize(int width, int height); 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) public void Set(int vertices, ReadOnlySpan<float> defaultOuterLevel, ReadOnlySpan<float> defaultInnerLevel)
{ {
_vertices = vertices; _vertices = vertices;
defaultOuterLevel.CopyTo(_defaultOuterLevel.ToSpan()); defaultOuterLevel.CopyTo(_defaultOuterLevel.AsSpan());
defaultInnerLevel.CopyTo(_defaultInnerLevel.ToSpan()); defaultInnerLevel.CopyTo(_defaultInnerLevel.AsSpan());
} }
public static void Run(ref SetPatchParametersCommand command, ThreadedRenderer threaded, IRenderer renderer) 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 Ryujinx.Graphics.GAL.Multithreading.Model;
using System; using System;
using System.Buffers;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{ {

View File

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

View File

@@ -1,5 +1,4 @@
using Ryujinx.Graphics.GAL.Multithreading.Model; using Ryujinx.Graphics.GAL.Multithreading.Model;
using Ryujinx.Graphics.Shader;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands 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 class SourceProgramRequest : IProgramRequest
{ {

View File

@@ -30,5 +30,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
{ {
_impl.Window.SetSize(width, height); _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) public void SetVertexAttribs(ReadOnlySpan<VertexAttribDescriptor> vertexAttribs)
{ {
VertexAttribCount = vertexAttribs.Length; VertexAttribCount = vertexAttribs.Length;
vertexAttribs.CopyTo(VertexAttribs.ToSpan()); vertexAttribs.CopyTo(VertexAttribs.AsSpan());
} }
public void SetLogicOpState(bool enable, LogicalOp op) 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) 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) 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) public void UpdateViewportInverse(Vector4<float> data)

View File

@@ -1,6 +1,5 @@
using Ryujinx.Graphics.Device; using Ryujinx.Graphics.Device;
using Ryujinx.Graphics.Gpu.Engine.GPFifo; using Ryujinx.Graphics.Gpu.Engine.GPFifo;
using Ryujinx.Graphics.Gpu.Memory;
using System; using System;
namespace Ryujinx.Graphics.Gpu.Engine.MME namespace Ryujinx.Graphics.Gpu.Engine.MME

View File

@@ -12,7 +12,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
#pragma warning disable CS0169 #pragma warning disable CS0169
private uint _e0; private uint _e0;
#pragma warning restore CS0169 #pragma warning restore CS0169
public ref uint this[int index] => ref ToSpan()[index]; public ref uint this[int index] => ref AsSpan()[index];
public Span<uint> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 256); public Span<uint> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 256);
} }
} }

View File

@@ -1,7 +1,6 @@
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Gpu.Engine.Types; using Ryujinx.Graphics.Gpu.Engine.Types;
using System; using System;
using System.Text;
namespace Ryujinx.Graphics.Gpu.Engine.Threed namespace Ryujinx.Graphics.Gpu.Engine.Threed
{ {

View File

@@ -42,6 +42,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
private uint _prevFirstVertex; private uint _prevFirstVertex;
private bool _prevTfEnable; private bool _prevTfEnable;
private uint _prevRtNoAlphaMask;
/// <summary> /// <summary>
/// Creates a new instance of the state updater. /// Creates a new instance of the state updater.
/// </summary> /// </summary>
@@ -331,8 +333,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
_context.Renderer.Pipeline.SetPatchParameters( _context.Renderer.Pipeline.SetPatchParameters(
_state.State.PatchVertices, _state.State.PatchVertices,
_state.State.TessOuterLevel.ToSpan(), _state.State.TessOuterLevel.AsSpan(),
_state.State.TessInnerLevel.ToSpan()); _state.State.TessInnerLevel.AsSpan());
} }
/// <summary> /// <summary>
@@ -398,6 +400,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
int clipRegionHeight = int.MaxValue; int clipRegionHeight = int.MaxValue;
bool changedScale = false; bool changedScale = false;
uint rtNoAlphaMask = 0;
for (int index = 0; index < Constants.TotalRenderTargets; index++) for (int index = 0; index < Constants.TotalRenderTargets; index++)
{ {
@@ -412,6 +415,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
continue; continue;
} }
if (colorState.Format.NoAlpha())
{
rtNoAlphaMask |= 1u << index;
}
Image.Texture color = memoryManager.Physical.TextureCache.FindOrCreateTexture( Image.Texture color = memoryManager.Physical.TextureCache.FindOrCreateTexture(
memoryManager, memoryManager,
colorState, colorState,
@@ -485,6 +493,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
} }
_channel.TextureManager.SetClipRegion(clipRegionWidth, clipRegionHeight); _channel.TextureManager.SetClipRegion(clipRegionWidth, clipRegionHeight);
if (useControl && _prevRtNoAlphaMask != rtNoAlphaMask)
{
_prevRtNoAlphaMask = rtNoAlphaMask;
UpdateBlendState();
}
} }
/// <summary> /// <summary>
@@ -1056,44 +1071,80 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
bool blendIndependent = _state.State.BlendIndependent; bool blendIndependent = _state.State.BlendIndependent;
ColorF blendConstant = _state.State.BlendConstant; ColorF blendConstant = _state.State.BlendConstant;
for (int index = 0; index < Constants.TotalRenderTargets; index++) if (blendIndependent)
{ {
BlendDescriptor descriptor; for (int index = 0; index < Constants.TotalRenderTargets; index++)
if (blendIndependent)
{ {
bool enable = _state.State.BlendEnable[index]; bool enable = _state.State.BlendEnable[index];
var blend = _state.State.BlendState[index]; var blend = _state.State.BlendState[index];
descriptor = new BlendDescriptor( var descriptor = new BlendDescriptor(
enable, enable,
blendConstant, blendConstant,
blend.ColorOp, blend.ColorOp,
blend.ColorSrcFactor, FilterBlendFactor(blend.ColorSrcFactor, index),
blend.ColorDstFactor, FilterBlendFactor(blend.ColorDstFactor, index),
blend.AlphaOp, blend.AlphaOp,
blend.AlphaSrcFactor, FilterBlendFactor(blend.AlphaSrcFactor, index),
blend.AlphaDstFactor); FilterBlendFactor(blend.AlphaDstFactor, index));
}
else
{
bool enable = _state.State.BlendEnable[0];
var blend = _state.State.BlendStateCommon;
descriptor = new BlendDescriptor( _pipeline.BlendDescriptors[index] = descriptor;
enable, _context.Renderer.Pipeline.SetBlendState(index, descriptor);
blendConstant,
blend.ColorOp,
blend.ColorSrcFactor,
blend.ColorDstFactor,
blend.AlphaOp,
blend.AlphaSrcFactor,
blend.AlphaDstFactor);
} }
_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> /// <summary>
@@ -1242,6 +1293,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
_channel.BufferManager.SetGraphicsUniformBufferBindings(stage, info.CBuffers); _channel.BufferManager.SetGraphicsUniformBufferBindings(stage, info.CBuffers);
} }
/// <summary>
/// Gets the current texture pool state.
/// </summary>
/// <returns>Texture pool state</returns>
private GpuChannelPoolState GetPoolState() private GpuChannelPoolState GetPoolState()
{ {
return new GpuChannelPoolState( return new GpuChannelPoolState(
@@ -1262,10 +1317,12 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
for (int location = 0; location < attributeTypes.Length; location++) 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, VertexAttribType.Sint => AttributeType.Sint,
4 => AttributeType.Uint, VertexAttribType.Uint => AttributeType.Uint,
_ => AttributeType.Float _ => AttributeType.Float
}; };
} }
@@ -1286,6 +1343,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
ref attributeTypes); 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() private DepthMode GetDepthMode()
{ {
ref var transform = ref _state.State.ViewportTransform[0]; ref var transform = ref _state.State.ViewportTransform[0];

Some files were not shown because too many files have changed in this diff Show More