Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
c8f9292bab | ||
|
0ec933a615 | ||
|
2135b6a51a | ||
|
00e35d9bf6 | ||
|
6dfb6ccf8c | ||
|
e87e8b012c | ||
|
e8f1ca8427 | ||
|
ad47bd2d4e | ||
|
a5ff0024fb |
@@ -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]
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -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,
|
||||||
|
@@ -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();
|
||||||
|
@@ -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;
|
||||||
|
@@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -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);
|
||||||
|
@@ -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;
|
||||||
|
@@ -94,7 +94,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 +180,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,
|
||||||
|
@@ -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}\".");
|
||||||
}
|
}
|
||||||
|
@@ -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
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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)
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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)
|
||||||
|
@@ -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>
|
||||||
|
@@ -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;
|
||||||
|
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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();
|
||||||
}
|
}
|
||||||
|
@@ -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()
|
||||||
|
@@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -48,6 +48,10 @@ 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 List<string> _gpuIds = new List<string>();
|
||||||
|
private KeyboardHotkeys _keyboardHotkeys;
|
||||||
|
private int _graphicsBackendIndex;
|
||||||
|
|
||||||
public int ResolutionScale
|
public int ResolutionScale
|
||||||
{
|
{
|
||||||
@@ -97,6 +101,17 @@ namespace Ryujinx.Ava.Ui.ViewModels
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsVulkanAvailable
|
||||||
|
{
|
||||||
|
get => _isVulkanAvailable;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_isVulkanAvailable = 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 +158,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 +185,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 +243,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)" : "")}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -656,7 +656,12 @@ namespace Ryujinx.Ava.Ui.Windows
|
|||||||
{
|
{
|
||||||
AppHost = null;
|
AppHost = null;
|
||||||
|
|
||||||
Dispatcher.UIThread.Post(Close);
|
Dispatcher.UIThread.Post(() =>
|
||||||
|
{
|
||||||
|
MainContent = null;
|
||||||
|
|
||||||
|
Close();
|
||||||
|
});
|
||||||
};
|
};
|
||||||
AppHost?.Stop();
|
AppHost?.Stop();
|
||||||
|
|
||||||
|
@@ -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>
|
||||||
|
@@ -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.
|
||||||
|
@@ -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);
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -30,5 +30,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
|||||||
{
|
{
|
||||||
_impl.Window.SetSize(width, height);
|
_impl.Window.SetSize(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ChangeVSyncMode(bool vsyncEnabled) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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)
|
||||||
|
@@ -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)
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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(
|
||||||
@@ -1286,6 +1341,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];
|
||||||
|
@@ -124,11 +124,42 @@ namespace Ryujinx.Graphics.Gpu.Engine.Types
|
|||||||
ColorFormat.R8Snorm => new FormatInfo(Format.R8Snorm, 1, 1, 1, 1),
|
ColorFormat.R8Snorm => new FormatInfo(Format.R8Snorm, 1, 1, 1, 1),
|
||||||
ColorFormat.R8Sint => new FormatInfo(Format.R8Sint, 1, 1, 1, 1),
|
ColorFormat.R8Sint => new FormatInfo(Format.R8Sint, 1, 1, 1, 1),
|
||||||
ColorFormat.R8Uint => new FormatInfo(Format.R8Uint, 1, 1, 1, 1),
|
ColorFormat.R8Uint => new FormatInfo(Format.R8Uint, 1, 1, 1, 1),
|
||||||
ColorFormat.B5G5R5X1Unorm => new FormatInfo(Format.B5G5R5X1Unorm, 1, 1, 2, 4),
|
ColorFormat.B5G5R5X1Unorm => new FormatInfo(Format.B5G5R5A1Unorm, 1, 1, 2, 4),
|
||||||
ColorFormat.R8G8B8X8Unorm => new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4, 4),
|
ColorFormat.R8G8B8X8Unorm => new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4, 4),
|
||||||
ColorFormat.R8G8B8X8Srgb => new FormatInfo(Format.R8G8B8A8Srgb, 1, 1, 4, 4),
|
ColorFormat.R8G8B8X8Srgb => new FormatInfo(Format.R8G8B8A8Srgb, 1, 1, 4, 4),
|
||||||
_ => FormatInfo.Default
|
_ => FormatInfo.Default
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if a format has an alpha component.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="format">Format to be checked</param>
|
||||||
|
/// <returns>True if the format has no alpha component (RGBX), false if it does (RGBA)</returns>
|
||||||
|
public static bool NoAlpha(this ColorFormat format)
|
||||||
|
{
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case ColorFormat.R32G32B32X32Float:
|
||||||
|
case ColorFormat.R32G32B32X32Sint:
|
||||||
|
case ColorFormat.R32G32B32X32Uint:
|
||||||
|
case ColorFormat.R16G16B16X16Unorm:
|
||||||
|
case ColorFormat.R16G16B16X16Snorm:
|
||||||
|
case ColorFormat.R16G16B16X16Sint:
|
||||||
|
case ColorFormat.R16G16B16X16Uint:
|
||||||
|
case ColorFormat.R16G16B16X16Float:
|
||||||
|
case ColorFormat.R8G8B8X8Snorm:
|
||||||
|
case ColorFormat.R8G8B8X8Sint:
|
||||||
|
case ColorFormat.R8G8B8X8Uint:
|
||||||
|
case ColorFormat.B8G8R8X8Unorm:
|
||||||
|
case ColorFormat.B8G8R8X8Srgb:
|
||||||
|
case ColorFormat.B5G5R5X1Unorm:
|
||||||
|
case ColorFormat.R8G8B8X8Unorm:
|
||||||
|
case ColorFormat.R8G8B8X8Srgb:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -553,7 +553,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
|
|
||||||
specStateMatches &= specState.MatchesTexture(stage, index, descriptor);
|
specStateMatches &= specState.MatchesTexture(stage, index, descriptor);
|
||||||
|
|
||||||
Sampler sampler = _samplerPool?.Get(samplerId);
|
Sampler sampler = samplerPool?.Get(samplerId);
|
||||||
|
|
||||||
ITexture hostTexture = texture?.GetTargetTexture(bindingInfo.Target);
|
ITexture hostTexture = texture?.GetTargetTexture(bindingInfo.Target);
|
||||||
ISampler hostSampler = sampler?.GetHostSampler(texture);
|
ISampler hostSampler = sampler?.GetHostSampler(texture);
|
||||||
|
@@ -515,7 +515,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!graphicsState.AttributeTypes.ToSpan().SequenceEqual(GraphicsState.AttributeTypes.ToSpan()))
|
if (!graphicsState.AttributeTypes.AsSpan().SequenceEqual(GraphicsState.AttributeTypes.AsSpan()))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@@ -52,7 +52,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
/// <returns>Span of varying locations</returns>
|
/// <returns>Span of varying locations</returns>
|
||||||
public ReadOnlySpan<byte> AsSpan()
|
public ReadOnlySpan<byte> AsSpan()
|
||||||
{
|
{
|
||||||
return MemoryMarshal.Cast<uint, byte>(VaryingLocations.ToSpan()).Slice(0, Math.Min(128, VaryingCount));
|
return MemoryMarshal.Cast<uint, byte>(VaryingLocations.AsSpan()).Slice(0, Math.Min(128, VaryingCount));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -30,23 +30,23 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
Span<ushort> dst16 = MemoryMarshal.Cast<byte, ushort>(dst);
|
Span<ushort> dst16 = MemoryMarshal.Cast<byte, ushort>(dst);
|
||||||
if (xd.Lossless)
|
if (xd.Lossless)
|
||||||
{
|
{
|
||||||
Idct.HighbdIwht4x4Add(dqcoeff.ToSpan(), dst16, stride, eob, xd.Bd);
|
Idct.HighbdIwht4x4Add(dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch (txSize)
|
switch (txSize)
|
||||||
{
|
{
|
||||||
case TxSize.Tx4x4:
|
case TxSize.Tx4x4:
|
||||||
Idct.HighbdIdct4x4Add(dqcoeff.ToSpan(), dst16, stride, eob, xd.Bd);
|
Idct.HighbdIdct4x4Add(dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd);
|
||||||
break;
|
break;
|
||||||
case TxSize.Tx8x8:
|
case TxSize.Tx8x8:
|
||||||
Idct.HighbdIdct8x8Add(dqcoeff.ToSpan(), dst16, stride, eob, xd.Bd);
|
Idct.HighbdIdct8x8Add(dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd);
|
||||||
break;
|
break;
|
||||||
case TxSize.Tx16x16:
|
case TxSize.Tx16x16:
|
||||||
Idct.HighbdIdct16x16Add(dqcoeff.ToSpan(), dst16, stride, eob, xd.Bd);
|
Idct.HighbdIdct16x16Add(dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd);
|
||||||
break;
|
break;
|
||||||
case TxSize.Tx32x32:
|
case TxSize.Tx32x32:
|
||||||
Idct.HighbdIdct32x32Add(dqcoeff.ToSpan(), dst16, stride, eob, xd.Bd);
|
Idct.HighbdIdct32x32Add(dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd);
|
||||||
break;
|
break;
|
||||||
default: Debug.Assert(false, "Invalid transform size"); break;
|
default: Debug.Assert(false, "Invalid transform size"); break;
|
||||||
}
|
}
|
||||||
@@ -56,16 +56,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
if (xd.Lossless)
|
if (xd.Lossless)
|
||||||
{
|
{
|
||||||
Idct.Iwht4x4Add(dqcoeff.ToSpan(), dst, stride, eob);
|
Idct.Iwht4x4Add(dqcoeff.AsSpan(), dst, stride, eob);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch (txSize)
|
switch (txSize)
|
||||||
{
|
{
|
||||||
case TxSize.Tx4x4: Idct.Idct4x4Add(dqcoeff.ToSpan(), dst, stride, eob); break;
|
case TxSize.Tx4x4: Idct.Idct4x4Add(dqcoeff.AsSpan(), dst, stride, eob); break;
|
||||||
case TxSize.Tx8x8: Idct.Idct8x8Add(dqcoeff.ToSpan(), dst, stride, eob); break;
|
case TxSize.Tx8x8: Idct.Idct8x8Add(dqcoeff.AsSpan(), dst, stride, eob); break;
|
||||||
case TxSize.Tx16x16: Idct.Idct16x16Add(dqcoeff.ToSpan(), dst, stride, eob); break;
|
case TxSize.Tx16x16: Idct.Idct16x16Add(dqcoeff.AsSpan(), dst, stride, eob); break;
|
||||||
case TxSize.Tx32x32: Idct.Idct32x32Add(dqcoeff.ToSpan(), dst, stride, eob); break;
|
case TxSize.Tx32x32: Idct.Idct32x32Add(dqcoeff.AsSpan(), dst, stride, eob); break;
|
||||||
default: Debug.Assert(false, "Invalid transform size"); return;
|
default: Debug.Assert(false, "Invalid transform size"); return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,21 +73,21 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
|
|
||||||
if (eob == 1)
|
if (eob == 1)
|
||||||
{
|
{
|
||||||
dqcoeff.ToSpan()[0] = 0;
|
dqcoeff.AsSpan()[0] = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (txSize <= TxSize.Tx16x16 && eob <= 10)
|
if (txSize <= TxSize.Tx16x16 && eob <= 10)
|
||||||
{
|
{
|
||||||
dqcoeff.ToSpan().Slice(0, 4 * (4 << (int)txSize)).Fill(0);
|
dqcoeff.AsSpan().Slice(0, 4 * (4 << (int)txSize)).Fill(0);
|
||||||
}
|
}
|
||||||
else if (txSize == TxSize.Tx32x32 && eob <= 34)
|
else if (txSize == TxSize.Tx32x32 && eob <= 34)
|
||||||
{
|
{
|
||||||
dqcoeff.ToSpan().Slice(0, 256).Fill(0);
|
dqcoeff.AsSpan().Slice(0, 256).Fill(0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dqcoeff.ToSpan().Slice(0, 16 << ((int)txSize << 1)).Fill(0);
|
dqcoeff.AsSpan().Slice(0, 16 << ((int)txSize << 1)).Fill(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -109,23 +109,23 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
Span<ushort> dst16 = MemoryMarshal.Cast<byte, ushort>(dst);
|
Span<ushort> dst16 = MemoryMarshal.Cast<byte, ushort>(dst);
|
||||||
if (xd.Lossless)
|
if (xd.Lossless)
|
||||||
{
|
{
|
||||||
Idct.HighbdIwht4x4Add(dqcoeff.ToSpan(), dst16, stride, eob, xd.Bd);
|
Idct.HighbdIwht4x4Add(dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch (txSize)
|
switch (txSize)
|
||||||
{
|
{
|
||||||
case TxSize.Tx4x4:
|
case TxSize.Tx4x4:
|
||||||
Idct.HighbdIht4x4Add(txType, dqcoeff.ToSpan(), dst16, stride, eob, xd.Bd);
|
Idct.HighbdIht4x4Add(txType, dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd);
|
||||||
break;
|
break;
|
||||||
case TxSize.Tx8x8:
|
case TxSize.Tx8x8:
|
||||||
Idct.HighbdIht8x8Add(txType, dqcoeff.ToSpan(), dst16, stride, eob, xd.Bd);
|
Idct.HighbdIht8x8Add(txType, dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd);
|
||||||
break;
|
break;
|
||||||
case TxSize.Tx16x16:
|
case TxSize.Tx16x16:
|
||||||
Idct.HighbdIht16x16Add(txType, dqcoeff.ToSpan(), dst16, stride, eob, xd.Bd);
|
Idct.HighbdIht16x16Add(txType, dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd);
|
||||||
break;
|
break;
|
||||||
case TxSize.Tx32x32:
|
case TxSize.Tx32x32:
|
||||||
Idct.HighbdIdct32x32Add(dqcoeff.ToSpan(), dst16, stride, eob, xd.Bd);
|
Idct.HighbdIdct32x32Add(dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd);
|
||||||
break;
|
break;
|
||||||
default: Debug.Assert(false, "Invalid transform size"); break;
|
default: Debug.Assert(false, "Invalid transform size"); break;
|
||||||
}
|
}
|
||||||
@@ -135,16 +135,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
if (xd.Lossless)
|
if (xd.Lossless)
|
||||||
{
|
{
|
||||||
Idct.Iwht4x4Add(dqcoeff.ToSpan(), dst, stride, eob);
|
Idct.Iwht4x4Add(dqcoeff.AsSpan(), dst, stride, eob);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch (txSize)
|
switch (txSize)
|
||||||
{
|
{
|
||||||
case TxSize.Tx4x4: Idct.Iht4x4Add(txType, dqcoeff.ToSpan(), dst, stride, eob); break;
|
case TxSize.Tx4x4: Idct.Iht4x4Add(txType, dqcoeff.AsSpan(), dst, stride, eob); break;
|
||||||
case TxSize.Tx8x8: Idct.Iht8x8Add(txType, dqcoeff.ToSpan(), dst, stride, eob); break;
|
case TxSize.Tx8x8: Idct.Iht8x8Add(txType, dqcoeff.AsSpan(), dst, stride, eob); break;
|
||||||
case TxSize.Tx16x16: Idct.Iht16x16Add(txType, dqcoeff.ToSpan(), dst, stride, eob); break;
|
case TxSize.Tx16x16: Idct.Iht16x16Add(txType, dqcoeff.AsSpan(), dst, stride, eob); break;
|
||||||
case TxSize.Tx32x32: Idct.Idct32x32Add(dqcoeff.ToSpan(), dst, stride, eob); break;
|
case TxSize.Tx32x32: Idct.Idct32x32Add(dqcoeff.AsSpan(), dst, stride, eob); break;
|
||||||
default: Debug.Assert(false, "Invalid transform size"); return;
|
default: Debug.Assert(false, "Invalid transform size"); return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -152,21 +152,21 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
|
|
||||||
if (eob == 1)
|
if (eob == 1)
|
||||||
{
|
{
|
||||||
dqcoeff.ToSpan()[0] = 0;
|
dqcoeff.AsSpan()[0] = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (txType == TxType.DctDct && txSize <= TxSize.Tx16x16 && eob <= 10)
|
if (txType == TxType.DctDct && txSize <= TxSize.Tx16x16 && eob <= 10)
|
||||||
{
|
{
|
||||||
dqcoeff.ToSpan().Slice(0, 4 * (4 << (int)txSize)).Fill(0);
|
dqcoeff.AsSpan().Slice(0, 4 * (4 << (int)txSize)).Fill(0);
|
||||||
}
|
}
|
||||||
else if (txSize == TxSize.Tx32x32 && eob <= 34)
|
else if (txSize == TxSize.Tx32x32 && eob <= 34)
|
||||||
{
|
{
|
||||||
dqcoeff.ToSpan().Slice(0, 256).Fill(0);
|
dqcoeff.AsSpan().Slice(0, 256).Fill(0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dqcoeff.ToSpan().Slice(0, 16 << ((int)txSize << 1)).Fill(0);
|
dqcoeff.AsSpan().Slice(0, 16 << ((int)txSize << 1)).Fill(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -184,7 +184,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
PredictionMode mode = (plane == 0) ? mi.Mode : mi.UvMode;
|
PredictionMode mode = (plane == 0) ? mi.Mode : mi.UvMode;
|
||||||
int dstOffset = 4 * row * pd.Dst.Stride + 4 * col;
|
int dstOffset = 4 * row * pd.Dst.Stride + 4 * col;
|
||||||
byte* dst = &pd.Dst.Buf.ToPointer()[dstOffset];
|
byte* dst = &pd.Dst.Buf.ToPointer()[dstOffset];
|
||||||
Span<byte> dstSpan = pd.Dst.Buf.ToSpan().Slice(dstOffset);
|
Span<byte> dstSpan = pd.Dst.Buf.AsSpan().Slice(dstOffset);
|
||||||
|
|
||||||
if (mi.SbType < BlockSize.Block8x8)
|
if (mi.SbType < BlockSize.Block8x8)
|
||||||
{
|
{
|
||||||
@@ -223,7 +223,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
ref MacroBlockDPlane pd = ref xd.Plane[plane];
|
ref MacroBlockDPlane pd = ref xd.Plane[plane];
|
||||||
var sc = Luts.Vp9DefaultScanOrders[(int)txSize];
|
var sc = Luts.Vp9DefaultScanOrders[(int)txSize];
|
||||||
int eob = Detokenize.DecodeBlockTokens(ref twd, plane, sc, col, row, txSize, mi.SegmentId);
|
int eob = Detokenize.DecodeBlockTokens(ref twd, plane, sc, col, row, txSize, mi.SegmentId);
|
||||||
Span<byte> dst = pd.Dst.Buf.ToSpan().Slice(4 * row * pd.Dst.Stride + 4 * col);
|
Span<byte> dst = pd.Dst.Buf.AsSpan().Slice(4 * row * pd.Dst.Stride + 4 * col);
|
||||||
|
|
||||||
if (eob > 0)
|
if (eob > 0)
|
||||||
{
|
{
|
||||||
@@ -922,7 +922,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
BlockSize subsize,
|
BlockSize subsize,
|
||||||
int bw)
|
int bw)
|
||||||
{
|
{
|
||||||
Span<sbyte> aboveCtx = twd.Xd.AboveSegContext.Slice(miCol).ToSpan();
|
Span<sbyte> aboveCtx = twd.Xd.AboveSegContext.Slice(miCol).AsSpan();
|
||||||
Span<sbyte> leftCtx = MemoryMarshal.CreateSpan(ref twd.Xd.LeftSegContext[miRow & Constants.MiMask], 8 - (miRow & Constants.MiMask));
|
Span<sbyte> leftCtx = MemoryMarshal.CreateSpan(ref twd.Xd.LeftSegContext[miRow & Constants.MiMask], 8 - (miRow & Constants.MiMask));
|
||||||
|
|
||||||
// Update the partition context at the end notes. Set partition bits
|
// Update the partition context at the end notes. Set partition bits
|
||||||
@@ -1077,7 +1077,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
errorInfo.InternalError(CodecErr.CodecCorruptFrame, "Truncated packet or corrupt tile length");
|
errorInfo.InternalError(CodecErr.CodecCorruptFrame, "Truncated packet or corrupt tile length");
|
||||||
}
|
}
|
||||||
|
|
||||||
size = BinaryPrimitives.ReadInt32BigEndian(data.ToSpan());
|
size = BinaryPrimitives.ReadInt32BigEndian(data.AsSpan());
|
||||||
data = data.Slice(4);
|
data = data.Slice(4);
|
||||||
|
|
||||||
if (size > data.Length)
|
if (size > data.Length)
|
||||||
@@ -1250,8 +1250,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
Debug.Assert(tileCols <= (1 << 6));
|
Debug.Assert(tileCols <= (1 << 6));
|
||||||
Debug.Assert(tileRows == 1);
|
Debug.Assert(tileRows == 1);
|
||||||
|
|
||||||
cm.AboveContext.ToSpan().Fill(0);
|
cm.AboveContext.AsSpan().Fill(0);
|
||||||
cm.AboveSegContext.ToSpan().Fill(0);
|
cm.AboveSegContext.AsSpan().Fill(0);
|
||||||
|
|
||||||
for (n = 0; n < numWorkers; ++n)
|
for (n = 0; n < numWorkers; ++n)
|
||||||
{
|
{
|
||||||
@@ -1266,12 +1266,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
|
|
||||||
GetTileBuffers(ref cm, data, tileCols, ref tileBuffers);
|
GetTileBuffers(ref cm, data, tileCols, ref tileBuffers);
|
||||||
|
|
||||||
tileBuffers.ToSpan().Slice(0, tileCols).Sort(CompareTileBuffers);
|
tileBuffers.AsSpan().Slice(0, tileCols).Sort(CompareTileBuffers);
|
||||||
|
|
||||||
if (numWorkers == tileCols)
|
if (numWorkers == tileCols)
|
||||||
{
|
{
|
||||||
TileBuffer largest = tileBuffers[0];
|
TileBuffer largest = tileBuffers[0];
|
||||||
Span<TileBuffer> buffers = tileBuffers.ToSpan();
|
Span<TileBuffer> buffers = tileBuffers.AsSpan();
|
||||||
buffers.Slice(1).CopyTo(buffers.Slice(0, tileBuffers.Length - 1));
|
buffers.Slice(1).CopyTo(buffers.Slice(0, tileBuffers.Length - 1));
|
||||||
tileBuffers[tileCols - 1] = largest;
|
tileBuffers[tileCols - 1] = largest;
|
||||||
}
|
}
|
||||||
|
@@ -21,7 +21,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
|
|
||||||
private static PredictionMode ReadIntraModeY(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, int sizeGroup)
|
private static PredictionMode ReadIntraModeY(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, int sizeGroup)
|
||||||
{
|
{
|
||||||
PredictionMode yMode = ReadIntraMode(ref r, cm.Fc.Value.YModeProb[sizeGroup].ToSpan());
|
PredictionMode yMode = ReadIntraMode(ref r, cm.Fc.Value.YModeProb[sizeGroup].AsSpan());
|
||||||
if (!xd.Counts.IsNull)
|
if (!xd.Counts.IsNull)
|
||||||
{
|
{
|
||||||
++xd.Counts.Value.YMode[sizeGroup][(int)yMode];
|
++xd.Counts.Value.YMode[sizeGroup][(int)yMode];
|
||||||
@@ -32,7 +32,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
|
|
||||||
private static PredictionMode ReadIntraModeUv(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, byte yMode)
|
private static PredictionMode ReadIntraModeUv(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, byte yMode)
|
||||||
{
|
{
|
||||||
PredictionMode uvMode = ReadIntraMode(ref r, cm.Fc.Value.UvModeProb[yMode].ToSpan());
|
PredictionMode uvMode = ReadIntraMode(ref r, cm.Fc.Value.UvModeProb[yMode].AsSpan());
|
||||||
if (!xd.Counts.IsNull)
|
if (!xd.Counts.IsNull)
|
||||||
{
|
{
|
||||||
++xd.Counts.Value.UvMode[yMode][(int)uvMode];
|
++xd.Counts.Value.UvMode[yMode][(int)uvMode];
|
||||||
@@ -43,7 +43,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
|
|
||||||
private static PredictionMode ReadInterMode(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, int ctx)
|
private static PredictionMode ReadInterMode(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, int ctx)
|
||||||
{
|
{
|
||||||
int mode = r.ReadTree(Luts.Vp9InterModeTree, cm.Fc.Value.InterModeProb[ctx].ToSpan());
|
int mode = r.ReadTree(Luts.Vp9InterModeTree, cm.Fc.Value.InterModeProb[ctx].AsSpan());
|
||||||
if (!xd.Counts.IsNull)
|
if (!xd.Counts.IsNull)
|
||||||
{
|
{
|
||||||
++xd.Counts.Value.InterMode[ctx][mode];
|
++xd.Counts.Value.InterMode[ctx][mode];
|
||||||
@@ -54,16 +54,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
|
|
||||||
private static int ReadSegmentId(ref Reader r, ref Array7<byte> segTreeProbs)
|
private static int ReadSegmentId(ref Reader r, ref Array7<byte> segTreeProbs)
|
||||||
{
|
{
|
||||||
return r.ReadTree(Luts.Vp9SegmentTree, segTreeProbs.ToSpan());
|
return r.ReadTree(Luts.Vp9SegmentTree, segTreeProbs.AsSpan());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ReadOnlySpan<byte> GetTxProbs(ref Vp9EntropyProbs fc, TxSize maxTxSize, int ctx)
|
private static ReadOnlySpan<byte> GetTxProbs(ref Vp9EntropyProbs fc, TxSize maxTxSize, int ctx)
|
||||||
{
|
{
|
||||||
switch (maxTxSize)
|
switch (maxTxSize)
|
||||||
{
|
{
|
||||||
case TxSize.Tx8x8: return fc.Tx8x8Prob[ctx].ToSpan();
|
case TxSize.Tx8x8: return fc.Tx8x8Prob[ctx].AsSpan();
|
||||||
case TxSize.Tx16x16: return fc.Tx16x16Prob[ctx].ToSpan();
|
case TxSize.Tx16x16: return fc.Tx16x16Prob[ctx].AsSpan();
|
||||||
case TxSize.Tx32x32: return fc.Tx32x32Prob[ctx].ToSpan();
|
case TxSize.Tx32x32: return fc.Tx32x32Prob[ctx].AsSpan();
|
||||||
default: Debug.Assert(false, "Invalid maxTxSize."); return ReadOnlySpan<byte>.Empty;
|
default: Debug.Assert(false, "Invalid maxTxSize."); return ReadOnlySpan<byte>.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,9 +72,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
switch (maxTxSize)
|
switch (maxTxSize)
|
||||||
{
|
{
|
||||||
case TxSize.Tx8x8: return counts.Tx8x8[ctx].ToSpan();
|
case TxSize.Tx8x8: return counts.Tx8x8[ctx].AsSpan();
|
||||||
case TxSize.Tx16x16: return counts.Tx16x16[ctx].ToSpan();
|
case TxSize.Tx16x16: return counts.Tx16x16[ctx].AsSpan();
|
||||||
case TxSize.Tx32x32: return counts.Tx32x32[ctx].ToSpan();
|
case TxSize.Tx32x32: return counts.Tx32x32[ctx].AsSpan();
|
||||||
default: Debug.Assert(false, "Invalid maxTxSize."); return Span<uint>.Empty;
|
default: Debug.Assert(false, "Invalid maxTxSize."); return Span<uint>.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -253,7 +253,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
int mag, d, fr, hp;
|
int mag, d, fr, hp;
|
||||||
bool sign = r.Read(fc.Sign[mvcomp]) != 0;
|
bool sign = r.Read(fc.Sign[mvcomp]) != 0;
|
||||||
MvClassType mvClass = (MvClassType)r.ReadTree(Luts.Vp9MvClassTree, fc.Classes[mvcomp].ToSpan());
|
MvClassType mvClass = (MvClassType)r.ReadTree(Luts.Vp9MvClassTree, fc.Classes[mvcomp].AsSpan());
|
||||||
bool class0 = mvClass == MvClassType.MvClass0;
|
bool class0 = mvClass == MvClassType.MvClass0;
|
||||||
|
|
||||||
// Integer part
|
// Integer part
|
||||||
@@ -277,7 +277,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fractional part
|
// Fractional part
|
||||||
fr = r.ReadTree(Luts.Vp9MvFPTree, class0 ? fc.Class0Fp[mvcomp][d].ToSpan() : fc.Fp[mvcomp].ToSpan());
|
fr = r.ReadTree(Luts.Vp9MvFPTree, class0 ? fc.Class0Fp[mvcomp][d].AsSpan() : fc.Fp[mvcomp].AsSpan());
|
||||||
|
|
||||||
// High precision part (if hp is not used, the default value of the hp is 1)
|
// High precision part (if hp is not used, the default value of the hp is 1)
|
||||||
hp = usehp ? r.Read(class0 ? fc.Class0Hp[mvcomp] : fc.Hp[mvcomp]) : 1;
|
hp = usehp ? r.Read(class0 ? fc.Class0Hp[mvcomp] : fc.Hp[mvcomp]) : 1;
|
||||||
@@ -295,7 +295,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
Ptr<Vp9BackwardUpdates> counts,
|
Ptr<Vp9BackwardUpdates> counts,
|
||||||
bool allowHP)
|
bool allowHP)
|
||||||
{
|
{
|
||||||
MvJointType jointType = (MvJointType)r.ReadTree(Luts.Vp9MvJointTree, fc.Joints.ToSpan());
|
MvJointType jointType = (MvJointType)r.ReadTree(Luts.Vp9MvJointTree, fc.Joints.AsSpan());
|
||||||
bool useHP = allowHP && refr.UseMvHp();
|
bool useHP = allowHP && refr.UseMvHp();
|
||||||
Mv diff = new Mv();
|
Mv diff = new Mv();
|
||||||
|
|
||||||
@@ -402,7 +402,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
private static byte ReadSwitchableInterpFilter(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r)
|
private static byte ReadSwitchableInterpFilter(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r)
|
||||||
{
|
{
|
||||||
int ctx = xd.GetPredContextSwitchableInterp();
|
int ctx = xd.GetPredContextSwitchableInterp();
|
||||||
byte type = (byte)r.ReadTree(Luts.Vp9SwitchableInterpTree, cm.Fc.Value.SwitchableInterpProb[ctx].ToSpan());
|
byte type = (byte)r.ReadTree(Luts.Vp9SwitchableInterpTree, cm.Fc.Value.SwitchableInterpProb[ctx].AsSpan());
|
||||||
if (!xd.Counts.IsNull)
|
if (!xd.Counts.IsNull)
|
||||||
{
|
{
|
||||||
++xd.Counts.Value.SwitchableInterp[ctx][type];
|
++xd.Counts.Value.SwitchableInterp[ctx][type];
|
||||||
@@ -1060,7 +1060,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
PredictionMode above = AboveBlockMode(mi, aboveMi, block);
|
PredictionMode above = AboveBlockMode(mi, aboveMi, block);
|
||||||
PredictionMode left = LeftBlockMode(mi, leftMi, block);
|
PredictionMode left = LeftBlockMode(mi, leftMi, block);
|
||||||
return fc.KfYModeProb[(int)above][(int)left].ToSpan();
|
return fc.KfYModeProb[(int)above][(int)left].AsSpan();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ReadIntraFrameModeInfo(
|
private static void ReadIntraFrameModeInfo(
|
||||||
@@ -1113,7 +1113,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
mi.Value.UvMode = ReadIntraMode(ref r, cm.Fc.Value.KfUvModeProb[(int)mi.Value.Mode].ToSpan());
|
mi.Value.UvMode = ReadIntraMode(ref r, cm.Fc.Value.KfUvModeProb[(int)mi.Value.Mode].AsSpan());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CopyRefFramePair(ref Array2<sbyte> dst, ref Array2<sbyte> src)
|
private static void CopyRefFramePair(ref Array2<sbyte> dst, ref Array2<sbyte> src)
|
||||||
|
@@ -236,8 +236,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
ref MacroBlockDPlane pd = ref xd.Plane[plane];
|
ref MacroBlockDPlane pd = ref xd.Plane[plane];
|
||||||
ref Array2<short> dequant = ref pd.SegDequant[segId];
|
ref Array2<short> dequant = ref pd.SegDequant[segId];
|
||||||
int eob;
|
int eob;
|
||||||
Span<sbyte> a = pd.AboveContext.ToSpan().Slice(x);
|
Span<sbyte> a = pd.AboveContext.AsSpan().Slice(x);
|
||||||
Span<sbyte> l = pd.LeftContext.ToSpan().Slice(y);
|
Span<sbyte> l = pd.LeftContext.AsSpan().Slice(y);
|
||||||
int ctx;
|
int ctx;
|
||||||
int ctxShiftA = 0;
|
int ctxShiftA = 0;
|
||||||
int ctxShiftL = 0;
|
int ctxShiftL = 0;
|
||||||
@@ -250,7 +250,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
eob = DecodeCoefs(
|
eob = DecodeCoefs(
|
||||||
ref xd,
|
ref xd,
|
||||||
GetPlaneType(plane),
|
GetPlaneType(plane),
|
||||||
pd.DqCoeff.ToSpan(),
|
pd.DqCoeff.AsSpan(),
|
||||||
txSize,
|
txSize,
|
||||||
ref dequant,
|
ref dequant,
|
||||||
ctx,
|
ctx,
|
||||||
@@ -266,7 +266,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
eob = DecodeCoefs(
|
eob = DecodeCoefs(
|
||||||
ref xd,
|
ref xd,
|
||||||
GetPlaneType(plane),
|
GetPlaneType(plane),
|
||||||
pd.DqCoeff.ToSpan(),
|
pd.DqCoeff.AsSpan(),
|
||||||
txSize,
|
txSize,
|
||||||
ref dequant,
|
ref dequant,
|
||||||
ctx,
|
ctx,
|
||||||
@@ -283,7 +283,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
eob = DecodeCoefs(
|
eob = DecodeCoefs(
|
||||||
ref xd,
|
ref xd,
|
||||||
GetPlaneType(plane),
|
GetPlaneType(plane),
|
||||||
pd.DqCoeff.ToSpan(),
|
pd.DqCoeff.AsSpan(),
|
||||||
txSize,
|
txSize,
|
||||||
ref dequant,
|
ref dequant,
|
||||||
ctx,
|
ctx,
|
||||||
@@ -303,7 +303,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
eob = DecodeCoefs(
|
eob = DecodeCoefs(
|
||||||
ref xd,
|
ref xd,
|
||||||
GetPlaneType(plane),
|
GetPlaneType(plane),
|
||||||
pd.DqCoeff.ToSpan(),
|
pd.DqCoeff.AsSpan(),
|
||||||
txSize,
|
txSize,
|
||||||
ref dequant,
|
ref dequant,
|
||||||
ctx,
|
ctx,
|
||||||
|
@@ -50,7 +50,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
|
|
||||||
private void Fill()
|
private void Fill()
|
||||||
{
|
{
|
||||||
ReadOnlySpan<byte> buffer = _buffer.ToSpan();
|
ReadOnlySpan<byte> buffer = _buffer.AsSpan();
|
||||||
ReadOnlySpan<byte> bufferStart = buffer;
|
ReadOnlySpan<byte> bufferStart = buffer;
|
||||||
ulong value = Value;
|
ulong value = Value;
|
||||||
int count = Count;
|
int count = Count;
|
||||||
|
@@ -359,8 +359,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
blockInsideLimit = 1;
|
blockInsideLimit = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
lfi.Lfthr[lvl].Lim.ToSpan().Fill((byte)blockInsideLimit);
|
lfi.Lfthr[lvl].Lim.AsSpan().Fill((byte)blockInsideLimit);
|
||||||
lfi.Lfthr[lvl].Mblim.ToSpan().Fill((byte)(2 * (lvl + 2) + blockInsideLimit));
|
lfi.Lfthr[lvl].Mblim.AsSpan().Fill((byte)(2 * (lvl + 2) + blockInsideLimit));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -395,7 +395,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
// We could get rid of this if we assume that deltas are set to
|
// We could get rid of this if we assume that deltas are set to
|
||||||
// zero when not in use; encoder always uses deltas
|
// zero when not in use; encoder always uses deltas
|
||||||
MemoryMarshal.Cast<Array2<byte>, byte>(lfi.Lvl[segId].ToSpan()).Fill((byte)lvlSeg);
|
MemoryMarshal.Cast<Array2<byte>, byte>(lfi.Lvl[segId].AsSpan()).Fill((byte)lvlSeg);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@@ -70,7 +70,6 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
Add(Format.D32Float, new FormatInfo(1, false, false, All.DepthComponent32f, PixelFormat.DepthComponent, PixelType.Float));
|
Add(Format.D32Float, new FormatInfo(1, false, false, All.DepthComponent32f, PixelFormat.DepthComponent, PixelType.Float));
|
||||||
Add(Format.D24UnormS8Uint, new FormatInfo(1, false, false, All.Depth24Stencil8, PixelFormat.DepthStencil, PixelType.UnsignedInt248));
|
Add(Format.D24UnormS8Uint, new FormatInfo(1, false, false, All.Depth24Stencil8, PixelFormat.DepthStencil, PixelType.UnsignedInt248));
|
||||||
Add(Format.D32FloatS8Uint, new FormatInfo(1, false, false, All.Depth32fStencil8, PixelFormat.DepthStencil, PixelType.Float32UnsignedInt248Rev));
|
Add(Format.D32FloatS8Uint, new FormatInfo(1, false, false, All.Depth32fStencil8, PixelFormat.DepthStencil, PixelType.Float32UnsignedInt248Rev));
|
||||||
Add(Format.R8G8B8X8Srgb, new FormatInfo(4, false, false, All.Srgb8, PixelFormat.Rgba, PixelType.UnsignedByte));
|
|
||||||
Add(Format.R8G8B8A8Srgb, new FormatInfo(4, false, false, All.Srgb8Alpha8, PixelFormat.Rgba, PixelType.UnsignedByte));
|
Add(Format.R8G8B8A8Srgb, new FormatInfo(4, false, false, All.Srgb8Alpha8, PixelFormat.Rgba, PixelType.UnsignedByte));
|
||||||
Add(Format.R4G4B4A4Unorm, new FormatInfo(4, true, false, All.Rgba4, PixelFormat.Rgba, PixelType.UnsignedShort4444Reversed));
|
Add(Format.R4G4B4A4Unorm, new FormatInfo(4, true, false, All.Rgba4, PixelFormat.Rgba, PixelType.UnsignedShort4444Reversed));
|
||||||
Add(Format.R5G5B5X1Unorm, new FormatInfo(4, true, false, All.Rgb5, PixelFormat.Rgb, PixelType.UnsignedShort1555Reversed));
|
Add(Format.R5G5B5X1Unorm, new FormatInfo(4, true, false, All.Rgb5, PixelFormat.Rgb, PixelType.UnsignedShort1555Reversed));
|
||||||
@@ -94,8 +93,12 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
Add(Format.Bc7Srgb, new FormatInfo(4, false, false, All.CompressedSrgbAlphaBptcUnorm));
|
Add(Format.Bc7Srgb, new FormatInfo(4, false, false, All.CompressedSrgbAlphaBptcUnorm));
|
||||||
Add(Format.Bc6HSfloat, new FormatInfo(4, false, false, All.CompressedRgbBptcSignedFloat));
|
Add(Format.Bc6HSfloat, new FormatInfo(4, false, false, All.CompressedRgbBptcSignedFloat));
|
||||||
Add(Format.Bc6HUfloat, new FormatInfo(4, false, false, All.CompressedRgbBptcUnsignedFloat));
|
Add(Format.Bc6HUfloat, new FormatInfo(4, false, false, All.CompressedRgbBptcUnsignedFloat));
|
||||||
|
Add(Format.Etc2RgbUnorm, new FormatInfo(4, false, false, All.CompressedRgb8Etc2));
|
||||||
Add(Format.Etc2RgbaUnorm, new FormatInfo(4, false, false, All.CompressedRgba8Etc2Eac));
|
Add(Format.Etc2RgbaUnorm, new FormatInfo(4, false, false, All.CompressedRgba8Etc2Eac));
|
||||||
|
Add(Format.Etc2RgbPtaUnorm, new FormatInfo(4, false, false, All.CompressedRgb8PunchthroughAlpha1Etc2));
|
||||||
|
Add(Format.Etc2RgbSrgb, new FormatInfo(4, false, false, All.CompressedSrgb8Etc2));
|
||||||
Add(Format.Etc2RgbaSrgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Etc2Eac));
|
Add(Format.Etc2RgbaSrgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Etc2Eac));
|
||||||
|
Add(Format.Etc2RgbPtaSrgb, new FormatInfo(4, false, false, All.CompressedSrgb8PunchthroughAlpha1Etc2));
|
||||||
Add(Format.R8Uscaled, new FormatInfo(1, false, true, All.R8ui, PixelFormat.RedInteger, PixelType.UnsignedByte));
|
Add(Format.R8Uscaled, new FormatInfo(1, false, true, All.R8ui, PixelFormat.RedInteger, PixelType.UnsignedByte));
|
||||||
Add(Format.R8Sscaled, new FormatInfo(1, false, true, All.R8i, PixelFormat.RedInteger, PixelType.Byte));
|
Add(Format.R8Sscaled, new FormatInfo(1, false, true, All.R8i, PixelFormat.RedInteger, PixelType.Byte));
|
||||||
Add(Format.R16Uscaled, new FormatInfo(1, false, true, All.R16ui, PixelFormat.RedInteger, PixelType.UnsignedShort));
|
Add(Format.R16Uscaled, new FormatInfo(1, false, true, All.R16ui, PixelFormat.RedInteger, PixelType.UnsignedShort));
|
||||||
@@ -124,18 +127,6 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
Add(Format.R10G10B10A2Sint, new FormatInfo(4, false, false, All.Rgb10A2, PixelFormat.RgbaInteger, (PixelType)All.Int2101010Rev));
|
Add(Format.R10G10B10A2Sint, new FormatInfo(4, false, false, All.Rgb10A2, PixelFormat.RgbaInteger, (PixelType)All.Int2101010Rev));
|
||||||
Add(Format.R10G10B10A2Uscaled, new FormatInfo(4, false, true, All.Rgb10A2ui, PixelFormat.RgbaInteger, PixelType.UnsignedInt2101010Reversed));
|
Add(Format.R10G10B10A2Uscaled, new FormatInfo(4, false, true, All.Rgb10A2ui, PixelFormat.RgbaInteger, PixelType.UnsignedInt2101010Reversed));
|
||||||
Add(Format.R10G10B10A2Sscaled, new FormatInfo(4, false, true, All.Rgb10A2, PixelFormat.RgbaInteger, PixelType.UnsignedInt2101010Reversed));
|
Add(Format.R10G10B10A2Sscaled, new FormatInfo(4, false, true, All.Rgb10A2, PixelFormat.RgbaInteger, PixelType.UnsignedInt2101010Reversed));
|
||||||
Add(Format.R8G8B8X8Unorm, new FormatInfo(4, true, false, All.Rgb8, PixelFormat.Rgba, PixelType.UnsignedByte));
|
|
||||||
Add(Format.R8G8B8X8Snorm, new FormatInfo(4, true, false, All.Rgb8Snorm, PixelFormat.Rgba, PixelType.Byte));
|
|
||||||
Add(Format.R8G8B8X8Uint, new FormatInfo(4, false, false, All.Rgb8ui, PixelFormat.RgbaInteger, PixelType.UnsignedByte));
|
|
||||||
Add(Format.R8G8B8X8Sint, new FormatInfo(4, false, false, All.Rgb8i, PixelFormat.RgbaInteger, PixelType.Byte));
|
|
||||||
Add(Format.R16G16B16X16Float, new FormatInfo(4, false, false, All.Rgb16f, PixelFormat.Rgba, PixelType.HalfFloat));
|
|
||||||
Add(Format.R16G16B16X16Unorm, new FormatInfo(4, true, false, All.Rgb16, PixelFormat.Rgba, PixelType.UnsignedShort));
|
|
||||||
Add(Format.R16G16B16X16Snorm, new FormatInfo(4, true, false, All.Rgb16Snorm, PixelFormat.Rgba, PixelType.Short));
|
|
||||||
Add(Format.R16G16B16X16Uint, new FormatInfo(4, false, false, All.Rgb16ui, PixelFormat.RgbaInteger, PixelType.UnsignedShort));
|
|
||||||
Add(Format.R16G16B16X16Sint, new FormatInfo(4, false, false, All.Rgb16i, PixelFormat.RgbaInteger, PixelType.Short));
|
|
||||||
Add(Format.R32G32B32X32Float, new FormatInfo(4, false, false, All.Rgb32f, PixelFormat.Rgba, PixelType.Float));
|
|
||||||
Add(Format.R32G32B32X32Uint, new FormatInfo(4, false, false, All.Rgb32ui, PixelFormat.RgbaInteger, PixelType.UnsignedInt));
|
|
||||||
Add(Format.R32G32B32X32Sint, new FormatInfo(4, false, false, All.Rgb32i, PixelFormat.RgbaInteger, PixelType.Int));
|
|
||||||
Add(Format.Astc4x4Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc4X4Khr));
|
Add(Format.Astc4x4Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc4X4Khr));
|
||||||
Add(Format.Astc5x4Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc5X4Khr));
|
Add(Format.Astc5x4Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc5X4Khr));
|
||||||
Add(Format.Astc5x5Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc5X5Khr));
|
Add(Format.Astc5x5Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc5X5Khr));
|
||||||
@@ -165,12 +156,9 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
Add(Format.Astc12x10Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc12X10Khr));
|
Add(Format.Astc12x10Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc12X10Khr));
|
||||||
Add(Format.Astc12x12Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc12X12Khr));
|
Add(Format.Astc12x12Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc12X12Khr));
|
||||||
Add(Format.B5G6R5Unorm, new FormatInfo(3, true, false, All.Rgb565, PixelFormat.Rgb, PixelType.UnsignedShort565Reversed));
|
Add(Format.B5G6R5Unorm, new FormatInfo(3, true, false, All.Rgb565, PixelFormat.Rgb, PixelType.UnsignedShort565Reversed));
|
||||||
Add(Format.B5G5R5X1Unorm, new FormatInfo(4, true, false, All.Rgb5, PixelFormat.Rgba, PixelType.UnsignedShort1555Reversed));
|
|
||||||
Add(Format.B5G5R5A1Unorm, new FormatInfo(4, true, false, All.Rgb5A1, PixelFormat.Rgba, PixelType.UnsignedShort1555Reversed));
|
Add(Format.B5G5R5A1Unorm, new FormatInfo(4, true, false, All.Rgb5A1, PixelFormat.Rgba, PixelType.UnsignedShort1555Reversed));
|
||||||
Add(Format.A1B5G5R5Unorm, new FormatInfo(4, true, false, All.Rgb5A1, PixelFormat.Rgba, PixelType.UnsignedShort5551));
|
Add(Format.A1B5G5R5Unorm, new FormatInfo(4, true, false, All.Rgb5A1, PixelFormat.Rgba, PixelType.UnsignedShort5551));
|
||||||
Add(Format.B8G8R8X8Unorm, new FormatInfo(4, true, false, All.Rgba8, PixelFormat.Rgba, PixelType.UnsignedByte));
|
|
||||||
Add(Format.B8G8R8A8Unorm, new FormatInfo(4, true, false, All.Rgba8, PixelFormat.Rgba, PixelType.UnsignedByte));
|
Add(Format.B8G8R8A8Unorm, new FormatInfo(4, true, false, All.Rgba8, PixelFormat.Rgba, PixelType.UnsignedByte));
|
||||||
Add(Format.B8G8R8X8Srgb, new FormatInfo(4, false, false, All.Srgb8, PixelFormat.Rgba, PixelType.UnsignedByte));
|
|
||||||
Add(Format.B8G8R8A8Srgb, new FormatInfo(4, false, false, All.Srgb8Alpha8, PixelFormat.Rgba, PixelType.UnsignedByte));
|
Add(Format.B8G8R8A8Srgb, new FormatInfo(4, false, false, All.Srgb8Alpha8, PixelFormat.Rgba, PixelType.UnsignedByte));
|
||||||
|
|
||||||
Add(Format.R8Unorm, SizedInternalFormat.R8);
|
Add(Format.R8Unorm, SizedInternalFormat.R8);
|
||||||
|
@@ -236,7 +236,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PreDraw();
|
PreDraw(vertexCount);
|
||||||
|
|
||||||
if (_primitiveType == PrimitiveType.Quads && !HwCapabilities.SupportsQuads)
|
if (_primitiveType == PrimitiveType.Quads && !HwCapabilities.SupportsQuads)
|
||||||
{
|
{
|
||||||
@@ -354,7 +354,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PreDraw();
|
PreDrawVbUnbounded();
|
||||||
|
|
||||||
int indexElemSize = 1;
|
int indexElemSize = 1;
|
||||||
|
|
||||||
@@ -686,7 +686,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PreDraw();
|
PreDrawVbUnbounded();
|
||||||
|
|
||||||
GL.BindBuffer((BufferTarget)All.DrawIndirectBuffer, indirectBuffer.Handle.ToInt32());
|
GL.BindBuffer((BufferTarget)All.DrawIndirectBuffer, indirectBuffer.Handle.ToInt32());
|
||||||
GL.BindBuffer((BufferTarget)All.ParameterBuffer, parameterBuffer.Handle.ToInt32());
|
GL.BindBuffer((BufferTarget)All.ParameterBuffer, parameterBuffer.Handle.ToInt32());
|
||||||
@@ -709,7 +709,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PreDraw();
|
PreDrawVbUnbounded();
|
||||||
|
|
||||||
_vertexArray.SetRangeOfIndexBuffer();
|
_vertexArray.SetRangeOfIndexBuffer();
|
||||||
|
|
||||||
@@ -1515,11 +1515,22 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
_supportBuffer.Commit();
|
_supportBuffer.Commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void PreDraw(int vertexCount)
|
||||||
|
{
|
||||||
|
_vertexArray.PreDraw(vertexCount);
|
||||||
|
PreDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PreDrawVbUnbounded()
|
||||||
|
{
|
||||||
|
_vertexArray.PreDrawVbUnbounded();
|
||||||
|
PreDraw();
|
||||||
|
}
|
||||||
|
|
||||||
private void PreDraw()
|
private void PreDraw()
|
||||||
{
|
{
|
||||||
DrawCount++;
|
DrawCount++;
|
||||||
|
|
||||||
_vertexArray.Validate();
|
|
||||||
_unit0Texture?.Bind(0);
|
_unit0Texture?.Bind(0);
|
||||||
_supportBuffer.Commit();
|
_supportBuffer.Commit();
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
using OpenTK.Graphics.OpenGL;
|
using OpenTK.Graphics.OpenGL;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Numerics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.OpenGL
|
namespace Ryujinx.Graphics.OpenGL
|
||||||
@@ -16,12 +17,16 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
|
|
||||||
private int _vertexAttribsCount;
|
private int _vertexAttribsCount;
|
||||||
private int _vertexBuffersCount;
|
private int _vertexBuffersCount;
|
||||||
|
private int _minVertexCount;
|
||||||
|
|
||||||
private uint _vertexAttribsInUse;
|
private uint _vertexAttribsInUse;
|
||||||
private uint _vertexBuffersInUse;
|
private uint _vertexBuffersInUse;
|
||||||
|
private uint _vertexBuffersLimited;
|
||||||
|
|
||||||
private BufferRange _indexBuffer;
|
private BufferRange _indexBuffer;
|
||||||
private BufferHandle _tempIndexBuffer;
|
private BufferHandle _tempIndexBuffer;
|
||||||
|
private BufferHandle _tempVertexBuffer;
|
||||||
|
private int _tempVertexBufferSize;
|
||||||
|
|
||||||
public VertexArray()
|
public VertexArray()
|
||||||
{
|
{
|
||||||
@@ -40,6 +45,8 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
|
|
||||||
public void SetVertexBuffers(ReadOnlySpan<VertexBufferDescriptor> vertexBuffers)
|
public void SetVertexBuffers(ReadOnlySpan<VertexBufferDescriptor> vertexBuffers)
|
||||||
{
|
{
|
||||||
|
int minVertexCount = int.MaxValue;
|
||||||
|
|
||||||
int bindingIndex;
|
int bindingIndex;
|
||||||
for (bindingIndex = 0; bindingIndex < vertexBuffers.Length; bindingIndex++)
|
for (bindingIndex = 0; bindingIndex < vertexBuffers.Length; bindingIndex++)
|
||||||
{
|
{
|
||||||
@@ -47,6 +54,12 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
|
|
||||||
if (vb.Buffer.Handle != BufferHandle.Null)
|
if (vb.Buffer.Handle != BufferHandle.Null)
|
||||||
{
|
{
|
||||||
|
int vertexCount = vb.Stride <= 0 ? 0 : vb.Buffer.Size / vb.Stride;
|
||||||
|
if (minVertexCount > vertexCount)
|
||||||
|
{
|
||||||
|
minVertexCount = vertexCount;
|
||||||
|
}
|
||||||
|
|
||||||
GL.BindVertexBuffer(bindingIndex, vb.Buffer.Handle.ToInt32(), (IntPtr)vb.Buffer.Offset, vb.Stride);
|
GL.BindVertexBuffer(bindingIndex, vb.Buffer.Handle.ToInt32(), (IntPtr)vb.Buffer.Offset, vb.Stride);
|
||||||
GL.VertexBindingDivisor(bindingIndex, vb.Divisor);
|
GL.VertexBindingDivisor(bindingIndex, vb.Divisor);
|
||||||
_vertexBuffersInUse |= 1u << bindingIndex;
|
_vertexBuffersInUse |= 1u << bindingIndex;
|
||||||
@@ -64,6 +77,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
}
|
}
|
||||||
|
|
||||||
_vertexBuffersCount = bindingIndex;
|
_vertexBuffersCount = bindingIndex;
|
||||||
|
_minVertexCount = minVertexCount;
|
||||||
_needsAttribsUpdate = true;
|
_needsAttribsUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,6 +157,101 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
GL.BindBuffer(BufferTarget.ElementArrayBuffer, _indexBuffer.Handle.ToInt32());
|
GL.BindBuffer(BufferTarget.ElementArrayBuffer, _indexBuffer.Handle.ToInt32());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void PreDraw(int vertexCount)
|
||||||
|
{
|
||||||
|
LimitVertexBuffers(vertexCount);
|
||||||
|
Validate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PreDrawVbUnbounded()
|
||||||
|
{
|
||||||
|
UnlimitVertexBuffers();
|
||||||
|
Validate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LimitVertexBuffers(int vertexCount)
|
||||||
|
{
|
||||||
|
// Is it possible for the draw to fetch outside the bounds of any vertex buffer currently bound?
|
||||||
|
|
||||||
|
if (vertexCount <= _minVertexCount)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the draw can fetch out of bounds, let's ensure that it will only fetch zeros rather than memory garbage.
|
||||||
|
|
||||||
|
int currentTempVbOffset = 0;
|
||||||
|
uint buffersInUse = _vertexBuffersInUse;
|
||||||
|
|
||||||
|
while (buffersInUse != 0)
|
||||||
|
{
|
||||||
|
int vbIndex = BitOperations.TrailingZeroCount(buffersInUse);
|
||||||
|
|
||||||
|
ref var vb = ref _vertexBuffers[vbIndex];
|
||||||
|
|
||||||
|
int requiredSize = vertexCount * vb.Stride;
|
||||||
|
|
||||||
|
if (vb.Buffer.Size < requiredSize)
|
||||||
|
{
|
||||||
|
BufferHandle tempVertexBuffer = EnsureTempVertexBufferSize(currentTempVbOffset + requiredSize);
|
||||||
|
|
||||||
|
Buffer.Copy(vb.Buffer.Handle, tempVertexBuffer, vb.Buffer.Offset, currentTempVbOffset, vb.Buffer.Size);
|
||||||
|
Buffer.Clear(tempVertexBuffer, currentTempVbOffset + vb.Buffer.Size, requiredSize - vb.Buffer.Size, 0);
|
||||||
|
|
||||||
|
GL.BindVertexBuffer(vbIndex, tempVertexBuffer.ToInt32(), (IntPtr)currentTempVbOffset, vb.Stride);
|
||||||
|
|
||||||
|
currentTempVbOffset += requiredSize;
|
||||||
|
_vertexBuffersLimited |= 1u << vbIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffersInUse &= ~(1u << vbIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private BufferHandle EnsureTempVertexBufferSize(int size)
|
||||||
|
{
|
||||||
|
BufferHandle tempVertexBuffer = _tempVertexBuffer;
|
||||||
|
|
||||||
|
if (_tempVertexBufferSize < size)
|
||||||
|
{
|
||||||
|
_tempVertexBufferSize = size;
|
||||||
|
|
||||||
|
if (tempVertexBuffer == BufferHandle.Null)
|
||||||
|
{
|
||||||
|
tempVertexBuffer = Buffer.Create(size);
|
||||||
|
_tempVertexBuffer = tempVertexBuffer;
|
||||||
|
return tempVertexBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer.Resize(_tempVertexBuffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tempVertexBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnlimitVertexBuffers()
|
||||||
|
{
|
||||||
|
uint buffersLimited = _vertexBuffersLimited;
|
||||||
|
|
||||||
|
if (buffersLimited == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (buffersLimited != 0)
|
||||||
|
{
|
||||||
|
int vbIndex = BitOperations.TrailingZeroCount(buffersLimited);
|
||||||
|
|
||||||
|
ref var vb = ref _vertexBuffers[vbIndex];
|
||||||
|
|
||||||
|
GL.BindVertexBuffer(vbIndex, vb.Buffer.Handle.ToInt32(), (IntPtr)vb.Buffer.Offset, vb.Stride);
|
||||||
|
|
||||||
|
buffersLimited &= ~(1u << vbIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
_vertexBuffersLimited = 0;
|
||||||
|
}
|
||||||
|
|
||||||
public void Validate()
|
public void Validate()
|
||||||
{
|
{
|
||||||
for (int attribIndex = 0; attribIndex < _vertexAttribsCount; attribIndex++)
|
for (int attribIndex = 0; attribIndex < _vertexAttribsCount; attribIndex++)
|
||||||
|
@@ -1,19 +0,0 @@
|
|||||||
using Ryujinx.Graphics.GAL;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.OpenGL
|
|
||||||
{
|
|
||||||
struct VertexBuffer
|
|
||||||
{
|
|
||||||
public BufferRange Range { get; }
|
|
||||||
|
|
||||||
public int Divisor { get; }
|
|
||||||
public int Stride { get; }
|
|
||||||
|
|
||||||
public VertexBuffer(BufferRange range, int divisor, int stride)
|
|
||||||
{
|
|
||||||
Range = range;
|
|
||||||
Divisor = divisor;
|
|
||||||
Stride = stride;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -58,6 +58,8 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
GL.PixelStore(PixelStoreParameter.UnpackAlignment, 4);
|
GL.PixelStore(PixelStoreParameter.UnpackAlignment, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ChangeVSyncMode(bool vsyncEnabled) { }
|
||||||
|
|
||||||
private void CreateStagingFramebuffer()
|
private void CreateStagingFramebuffer()
|
||||||
{
|
{
|
||||||
_stagingFrameBuffer = GL.GenFramebuffer();
|
_stagingFrameBuffer = GL.GenFramebuffer();
|
||||||
|
@@ -66,7 +66,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
Add(Format.D32Float, VkFormat.D32Sfloat);
|
Add(Format.D32Float, VkFormat.D32Sfloat);
|
||||||
Add(Format.D24UnormS8Uint, VkFormat.D24UnormS8Uint);
|
Add(Format.D24UnormS8Uint, VkFormat.D24UnormS8Uint);
|
||||||
Add(Format.D32FloatS8Uint, VkFormat.D32SfloatS8Uint);
|
Add(Format.D32FloatS8Uint, VkFormat.D32SfloatS8Uint);
|
||||||
Add(Format.R8G8B8X8Srgb, VkFormat.R8G8B8Srgb);
|
|
||||||
Add(Format.R8G8B8A8Srgb, VkFormat.R8G8B8A8Srgb);
|
Add(Format.R8G8B8A8Srgb, VkFormat.R8G8B8A8Srgb);
|
||||||
Add(Format.R4G4Unorm, VkFormat.R4G4UnormPack8);
|
Add(Format.R4G4Unorm, VkFormat.R4G4UnormPack8);
|
||||||
Add(Format.R4G4B4A4Unorm, VkFormat.R4G4B4A4UnormPack16);
|
Add(Format.R4G4B4A4Unorm, VkFormat.R4G4B4A4UnormPack16);
|
||||||
@@ -91,6 +90,12 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
Add(Format.Bc7Srgb, VkFormat.BC7SrgbBlock);
|
Add(Format.Bc7Srgb, VkFormat.BC7SrgbBlock);
|
||||||
Add(Format.Bc6HSfloat, VkFormat.BC6HSfloatBlock);
|
Add(Format.Bc6HSfloat, VkFormat.BC6HSfloatBlock);
|
||||||
Add(Format.Bc6HUfloat, VkFormat.BC6HUfloatBlock);
|
Add(Format.Bc6HUfloat, VkFormat.BC6HUfloatBlock);
|
||||||
|
Add(Format.Etc2RgbUnorm, VkFormat.Etc2R8G8B8UnormBlock);
|
||||||
|
Add(Format.Etc2RgbaUnorm, VkFormat.Etc2R8G8B8A8UnormBlock);
|
||||||
|
Add(Format.Etc2RgbPtaUnorm, VkFormat.Etc2R8G8B8A1UnormBlock);
|
||||||
|
Add(Format.Etc2RgbSrgb, VkFormat.Etc2R8G8B8SrgbBlock);
|
||||||
|
Add(Format.Etc2RgbaSrgb, VkFormat.Etc2R8G8B8A8SrgbBlock);
|
||||||
|
Add(Format.Etc2RgbPtaSrgb, VkFormat.Etc2R8G8B8A1SrgbBlock);
|
||||||
Add(Format.R8Uscaled, VkFormat.R8Uscaled);
|
Add(Format.R8Uscaled, VkFormat.R8Uscaled);
|
||||||
Add(Format.R8Sscaled, VkFormat.R8Sscaled);
|
Add(Format.R8Sscaled, VkFormat.R8Sscaled);
|
||||||
Add(Format.R16Uscaled, VkFormat.R16Uscaled);
|
Add(Format.R16Uscaled, VkFormat.R16Uscaled);
|
||||||
@@ -119,18 +124,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
Add(Format.R10G10B10A2Sint, VkFormat.A2B10G10R10SintPack32);
|
Add(Format.R10G10B10A2Sint, VkFormat.A2B10G10R10SintPack32);
|
||||||
Add(Format.R10G10B10A2Uscaled, VkFormat.A2B10G10R10UscaledPack32);
|
Add(Format.R10G10B10A2Uscaled, VkFormat.A2B10G10R10UscaledPack32);
|
||||||
Add(Format.R10G10B10A2Sscaled, VkFormat.A2B10G10R10SscaledPack32);
|
Add(Format.R10G10B10A2Sscaled, VkFormat.A2B10G10R10SscaledPack32);
|
||||||
Add(Format.R8G8B8X8Unorm, VkFormat.R8G8B8Unorm);
|
|
||||||
Add(Format.R8G8B8X8Snorm, VkFormat.R8G8B8SNorm);
|
|
||||||
Add(Format.R8G8B8X8Uint, VkFormat.R8G8B8Uint);
|
|
||||||
Add(Format.R8G8B8X8Sint, VkFormat.R8G8B8Sint);
|
|
||||||
Add(Format.R16G16B16X16Float, VkFormat.R16G16B16Sfloat);
|
|
||||||
Add(Format.R16G16B16X16Unorm, VkFormat.R16G16B16Unorm);
|
|
||||||
Add(Format.R16G16B16X16Snorm, VkFormat.R16G16B16SNorm);
|
|
||||||
Add(Format.R16G16B16X16Uint, VkFormat.R16G16B16Uint);
|
|
||||||
Add(Format.R16G16B16X16Sint, VkFormat.R16G16B16Sint);
|
|
||||||
Add(Format.R32G32B32X32Float, VkFormat.R32G32B32Sfloat);
|
|
||||||
Add(Format.R32G32B32X32Uint, VkFormat.R32G32B32Uint);
|
|
||||||
Add(Format.R32G32B32X32Sint, VkFormat.R32G32B32Sint);
|
|
||||||
Add(Format.Astc4x4Unorm, VkFormat.Astc4x4UnormBlock);
|
Add(Format.Astc4x4Unorm, VkFormat.Astc4x4UnormBlock);
|
||||||
Add(Format.Astc5x4Unorm, VkFormat.Astc5x4UnormBlock);
|
Add(Format.Astc5x4Unorm, VkFormat.Astc5x4UnormBlock);
|
||||||
Add(Format.Astc5x5Unorm, VkFormat.Astc5x5UnormBlock);
|
Add(Format.Astc5x5Unorm, VkFormat.Astc5x5UnormBlock);
|
||||||
@@ -160,12 +153,9 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
Add(Format.Astc12x10Srgb, VkFormat.Astc12x10SrgbBlock);
|
Add(Format.Astc12x10Srgb, VkFormat.Astc12x10SrgbBlock);
|
||||||
Add(Format.Astc12x12Srgb, VkFormat.Astc12x12SrgbBlock);
|
Add(Format.Astc12x12Srgb, VkFormat.Astc12x12SrgbBlock);
|
||||||
Add(Format.B5G6R5Unorm, VkFormat.R5G6B5UnormPack16);
|
Add(Format.B5G6R5Unorm, VkFormat.R5G6B5UnormPack16);
|
||||||
Add(Format.B5G5R5X1Unorm, VkFormat.A1R5G5B5UnormPack16);
|
|
||||||
Add(Format.B5G5R5A1Unorm, VkFormat.A1R5G5B5UnormPack16);
|
Add(Format.B5G5R5A1Unorm, VkFormat.A1R5G5B5UnormPack16);
|
||||||
Add(Format.A1B5G5R5Unorm, VkFormat.R5G5B5A1UnormPack16);
|
Add(Format.A1B5G5R5Unorm, VkFormat.R5G5B5A1UnormPack16);
|
||||||
Add(Format.B8G8R8X8Unorm, VkFormat.B8G8R8Unorm);
|
|
||||||
Add(Format.B8G8R8A8Unorm, VkFormat.B8G8R8A8Unorm);
|
Add(Format.B8G8R8A8Unorm, VkFormat.B8G8R8A8Unorm);
|
||||||
Add(Format.B8G8R8X8Srgb, VkFormat.B8G8R8Srgb);
|
|
||||||
Add(Format.B8G8R8A8Srgb, VkFormat.B8G8R8A8Srgb);
|
Add(Format.B8G8R8A8Srgb, VkFormat.B8G8R8A8Srgb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -7,7 +7,9 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
class ImageWindow : WindowBase, IWindow, IDisposable
|
class ImageWindow : WindowBase, IWindow, IDisposable
|
||||||
{
|
{
|
||||||
private const int ImageCount = 5;
|
internal const VkFormat Format = VkFormat.R8G8B8A8Unorm;
|
||||||
|
|
||||||
|
private const int ImageCount = 3;
|
||||||
private const int SurfaceWidth = 1280;
|
private const int SurfaceWidth = 1280;
|
||||||
private const int SurfaceHeight = 720;
|
private const int SurfaceHeight = 720;
|
||||||
|
|
||||||
@@ -18,52 +20,49 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
private Auto<DisposableImage>[] _images;
|
private Auto<DisposableImage>[] _images;
|
||||||
private Auto<DisposableImageView>[] _imageViews;
|
private Auto<DisposableImageView>[] _imageViews;
|
||||||
private Auto<MemoryAllocation>[] _imageAllocationAuto;
|
private Auto<MemoryAllocation>[] _imageAllocationAuto;
|
||||||
|
private ImageState[] _states;
|
||||||
|
private PresentImageInfo[] _presentedImages;
|
||||||
|
private FenceHolder[] _fences;
|
||||||
|
|
||||||
private ulong[] _imageSizes;
|
private ulong[] _imageSizes;
|
||||||
private ulong[] _imageOffsets;
|
private ulong[] _imageOffsets;
|
||||||
|
|
||||||
private Semaphore _imageAvailableSemaphore;
|
|
||||||
private Semaphore _renderFinishedSemaphore;
|
|
||||||
|
|
||||||
private int _width = SurfaceWidth;
|
private int _width = SurfaceWidth;
|
||||||
private int _height = SurfaceHeight;
|
private int _height = SurfaceHeight;
|
||||||
private VkFormat _format;
|
|
||||||
private bool _recreateImages;
|
private bool _recreateImages;
|
||||||
private int _nextImage;
|
private int _nextImage;
|
||||||
|
|
||||||
internal new bool ScreenCaptureRequested { get; set; }
|
|
||||||
|
|
||||||
public unsafe ImageWindow(VulkanRenderer gd, PhysicalDevice physicalDevice, Device device)
|
public unsafe ImageWindow(VulkanRenderer gd, PhysicalDevice physicalDevice, Device device)
|
||||||
{
|
{
|
||||||
_gd = gd;
|
_gd = gd;
|
||||||
_physicalDevice = physicalDevice;
|
_physicalDevice = physicalDevice;
|
||||||
_device = device;
|
_device = device;
|
||||||
|
|
||||||
_format = VkFormat.R8G8B8A8Unorm;
|
|
||||||
|
|
||||||
_images = new Auto<DisposableImage>[ImageCount];
|
_images = new Auto<DisposableImage>[ImageCount];
|
||||||
_imageAllocationAuto = new Auto<MemoryAllocation>[ImageCount];
|
_imageAllocationAuto = new Auto<MemoryAllocation>[ImageCount];
|
||||||
_imageSizes = new ulong[ImageCount];
|
_imageSizes = new ulong[ImageCount];
|
||||||
_imageOffsets = new ulong[ImageCount];
|
_imageOffsets = new ulong[ImageCount];
|
||||||
|
_states = new ImageState[ImageCount];
|
||||||
|
_presentedImages = new PresentImageInfo[ImageCount];
|
||||||
|
|
||||||
CreateImages();
|
CreateImages();
|
||||||
|
|
||||||
var semaphoreCreateInfo = new SemaphoreCreateInfo()
|
|
||||||
{
|
|
||||||
SType = StructureType.SemaphoreCreateInfo
|
|
||||||
};
|
|
||||||
|
|
||||||
gd.Api.CreateSemaphore(device, semaphoreCreateInfo, null, out _imageAvailableSemaphore).ThrowOnError();
|
|
||||||
gd.Api.CreateSemaphore(device, semaphoreCreateInfo, null, out _renderFinishedSemaphore).ThrowOnError();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RecreateImages()
|
private void RecreateImages()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < ImageCount; i++)
|
for (int i = 0; i < ImageCount; i++)
|
||||||
{
|
{
|
||||||
_imageViews[i]?.Dispose();
|
lock (_states[i])
|
||||||
_imageAllocationAuto[i]?.Dispose();
|
{
|
||||||
_images[i]?.Dispose();
|
_states[i].IsValid = false;
|
||||||
|
_fences[i]?.Wait();
|
||||||
|
_fences[i]?.Put();
|
||||||
|
_imageViews[i]?.Dispose();
|
||||||
|
_imageAllocationAuto[i]?.Dispose();
|
||||||
|
_images[i]?.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
_presentedImages = null;
|
||||||
|
|
||||||
CreateImages();
|
CreateImages();
|
||||||
}
|
}
|
||||||
@@ -71,34 +70,35 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
private unsafe void CreateImages()
|
private unsafe void CreateImages()
|
||||||
{
|
{
|
||||||
_imageViews = new Auto<DisposableImageView>[ImageCount];
|
_imageViews = new Auto<DisposableImageView>[ImageCount];
|
||||||
|
_fences = new FenceHolder[ImageCount];
|
||||||
|
_presentedImages = new PresentImageInfo[ImageCount];
|
||||||
|
|
||||||
|
_nextImage = 0;
|
||||||
var cbs = _gd.CommandBufferPool.Rent();
|
var cbs = _gd.CommandBufferPool.Rent();
|
||||||
|
|
||||||
|
var imageCreateInfo = new ImageCreateInfo
|
||||||
|
{
|
||||||
|
SType = StructureType.ImageCreateInfo,
|
||||||
|
ImageType = ImageType.ImageType2D,
|
||||||
|
Format = Format,
|
||||||
|
Extent = new Extent3D((uint?)_width, (uint?)_height, 1),
|
||||||
|
MipLevels = 1,
|
||||||
|
ArrayLayers = 1,
|
||||||
|
Samples = SampleCountFlags.SampleCount1Bit,
|
||||||
|
Tiling = ImageTiling.Optimal,
|
||||||
|
Usage = ImageUsageFlags.ImageUsageColorAttachmentBit | ImageUsageFlags.ImageUsageTransferSrcBit | ImageUsageFlags.ImageUsageTransferDstBit,
|
||||||
|
SharingMode = SharingMode.Exclusive,
|
||||||
|
InitialLayout = ImageLayout.Undefined,
|
||||||
|
Flags = ImageCreateFlags.ImageCreateMutableFormatBit
|
||||||
|
};
|
||||||
|
|
||||||
for (int i = 0; i < _images.Length; i++)
|
for (int i = 0; i < _images.Length; i++)
|
||||||
{
|
{
|
||||||
var imageCreateInfo = new ImageCreateInfo
|
|
||||||
{
|
|
||||||
SType = StructureType.ImageCreateInfo,
|
|
||||||
ImageType = ImageType.ImageType2D,
|
|
||||||
Format = _format,
|
|
||||||
Extent =
|
|
||||||
new Extent3D((uint?)_width,
|
|
||||||
(uint?)_height, 1),
|
|
||||||
MipLevels = 1,
|
|
||||||
ArrayLayers = 1,
|
|
||||||
Samples = SampleCountFlags.SampleCount1Bit,
|
|
||||||
Tiling = ImageTiling.Optimal,
|
|
||||||
Usage = ImageUsageFlags.ImageUsageColorAttachmentBit | ImageUsageFlags.ImageUsageTransferSrcBit | ImageUsageFlags.ImageUsageTransferDstBit,
|
|
||||||
SharingMode = SharingMode.Exclusive,
|
|
||||||
InitialLayout = ImageLayout.Undefined,
|
|
||||||
Flags = ImageCreateFlags.ImageCreateMutableFormatBit
|
|
||||||
};
|
|
||||||
|
|
||||||
_gd.Api.CreateImage(_device, imageCreateInfo, null, out var image).ThrowOnError();
|
_gd.Api.CreateImage(_device, imageCreateInfo, null, out var image).ThrowOnError();
|
||||||
_images[i] = new Auto<DisposableImage>(new DisposableImage(_gd.Api, _device, image));
|
_images[i] = new Auto<DisposableImage>(new DisposableImage(_gd.Api, _device, image));
|
||||||
|
|
||||||
_gd.Api.GetImageMemoryRequirements(_device, image,
|
_gd.Api.GetImageMemoryRequirements(_device, image,
|
||||||
out var memoryRequirements);
|
out var memoryRequirements);
|
||||||
|
|
||||||
var allocation = _gd.MemoryAllocator.AllocateDeviceMemory(_physicalDevice, memoryRequirements, MemoryPropertyFlags.MemoryPropertyDeviceLocalBit);
|
var allocation = _gd.MemoryAllocator.AllocateDeviceMemory(_physicalDevice, memoryRequirements, MemoryPropertyFlags.MemoryPropertyDeviceLocalBit);
|
||||||
|
|
||||||
_imageSizes[i] = allocation.Size;
|
_imageSizes[i] = allocation.Size;
|
||||||
@@ -108,7 +108,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
_gd.Api.BindImageMemory(_device, image, allocation.Memory, allocation.Offset);
|
_gd.Api.BindImageMemory(_device, image, allocation.Memory, allocation.Offset);
|
||||||
|
|
||||||
_imageViews[i] = CreateImageView(image, _format);
|
_imageViews[i] = CreateImageView(image, Format);
|
||||||
|
|
||||||
Transition(
|
Transition(
|
||||||
cbs.CommandBuffer,
|
cbs.CommandBuffer,
|
||||||
@@ -116,7 +116,9 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
ImageLayout.Undefined,
|
ImageLayout.Undefined,
|
||||||
ImageLayout.ColorAttachmentOptimal);
|
ImageLayout.TransferSrcOptimal);
|
||||||
|
|
||||||
|
_states[i] = new ImageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
_gd.CommandBufferPool.Return(cbs);
|
_gd.CommandBufferPool.Return(cbs);
|
||||||
@@ -165,7 +167,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
image.GetUnsafe().Value,
|
image.GetUnsafe().Value,
|
||||||
0,
|
0,
|
||||||
AccessFlags.AccessTransferWriteBit,
|
AccessFlags.AccessTransferWriteBit,
|
||||||
ImageLayout.ColorAttachmentOptimal,
|
ImageLayout.TransferSrcOptimal,
|
||||||
ImageLayout.General);
|
ImageLayout.General);
|
||||||
|
|
||||||
var view = (TextureView)texture;
|
var view = (TextureView)texture;
|
||||||
@@ -232,7 +234,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_imageViews[_nextImage],
|
_imageViews[_nextImage],
|
||||||
_width,
|
_width,
|
||||||
_height,
|
_height,
|
||||||
_format,
|
Format,
|
||||||
new Extents2D(srcX0, srcY0, srcX1, srcY1),
|
new Extents2D(srcX0, srcY0, srcX1, srcY1),
|
||||||
new Extents2D(dstX0, dstY1, dstX1, dstY0),
|
new Extents2D(dstX0, dstY1, dstX1, dstY0),
|
||||||
true,
|
true,
|
||||||
@@ -244,7 +246,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
ImageLayout.General,
|
ImageLayout.General,
|
||||||
ImageLayout.ColorAttachmentOptimal);
|
ImageLayout.TransferSrcOptimal);
|
||||||
|
|
||||||
_gd.CommandBufferPool.Return(
|
_gd.CommandBufferPool.Return(
|
||||||
cbs,
|
cbs,
|
||||||
@@ -252,12 +254,30 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
stackalloc[] { PipelineStageFlags.PipelineStageColorAttachmentOutputBit },
|
stackalloc[] { PipelineStageFlags.PipelineStageColorAttachmentOutputBit },
|
||||||
null);
|
null);
|
||||||
|
|
||||||
var memory = _imageAllocationAuto[_nextImage].GetUnsafe().Memory;
|
_fences[_nextImage]?.Put();
|
||||||
var presentInfo = new PresentImageInfo(image.GetUnsafe().Value, memory, _imageSizes[_nextImage], _imageOffsets[_nextImage], _renderFinishedSemaphore, _imageAvailableSemaphore);
|
_fences[_nextImage] = cbs.GetFence();
|
||||||
|
cbs.GetFence().Get();
|
||||||
|
|
||||||
swapBuffersCallback(presentInfo);
|
PresentImageInfo info = _presentedImages[_nextImage];
|
||||||
|
|
||||||
_nextImage %= ImageCount;
|
if (info == null)
|
||||||
|
{
|
||||||
|
info = new PresentImageInfo(
|
||||||
|
image,
|
||||||
|
_imageAllocationAuto[_nextImage],
|
||||||
|
_device,
|
||||||
|
_physicalDevice,
|
||||||
|
_imageSizes[_nextImage],
|
||||||
|
_imageOffsets[_nextImage],
|
||||||
|
new Extent2D((uint)_width, (uint)_height),
|
||||||
|
_states[_nextImage]);
|
||||||
|
|
||||||
|
_presentedImages[_nextImage] = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
swapBuffersCallback(info);
|
||||||
|
|
||||||
|
_nextImage = (_nextImage + 1) % ImageCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe void Transition(
|
private unsafe void Transition(
|
||||||
@@ -320,11 +340,11 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
_gd.Api.DestroySemaphore(_device, _renderFinishedSemaphore, null);
|
|
||||||
_gd.Api.DestroySemaphore(_device, _imageAvailableSemaphore, null);
|
|
||||||
|
|
||||||
for (int i = 0; i < ImageCount; i++)
|
for (int i = 0; i < ImageCount; i++)
|
||||||
{
|
{
|
||||||
|
_states[i].IsValid = false;
|
||||||
|
_fences[i]?.Wait();
|
||||||
|
_fences[i]?.Put();
|
||||||
_imageViews[i]?.Dispose();
|
_imageViews[i]?.Dispose();
|
||||||
_imageAllocationAuto[i]?.Dispose();
|
_imageAllocationAuto[i]?.Dispose();
|
||||||
_images[i]?.Dispose();
|
_images[i]?.Dispose();
|
||||||
@@ -337,25 +357,73 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
Dispose(true);
|
Dispose(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void ChangeVSyncMode(bool vsyncEnabled) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ImageState
|
||||||
|
{
|
||||||
|
private bool _isValid = true;
|
||||||
|
|
||||||
|
public bool IsValid
|
||||||
|
{
|
||||||
|
get => _isValid;
|
||||||
|
internal set
|
||||||
|
{
|
||||||
|
_isValid = value;
|
||||||
|
|
||||||
|
StateChanged?.Invoke(this, _isValid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler<bool> StateChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PresentImageInfo
|
public class PresentImageInfo
|
||||||
{
|
{
|
||||||
public Image Image { get; }
|
private readonly Auto<DisposableImage> _image;
|
||||||
public DeviceMemory Memory { get; }
|
private readonly Auto<MemoryAllocation> _memory;
|
||||||
public ulong MemorySize { get; set; }
|
|
||||||
public ulong MemoryOffset { get; set; }
|
|
||||||
public Semaphore ReadySemaphore { get; }
|
|
||||||
public Semaphore AvailableSemaphore { get; }
|
|
||||||
|
|
||||||
public PresentImageInfo(Image image, DeviceMemory memory, ulong memorySize, ulong memoryOffset, Semaphore readySemaphore, Semaphore availableSemaphore)
|
public Image Image => _image.GetUnsafe().Value;
|
||||||
|
|
||||||
|
public DeviceMemory Memory => _memory.GetUnsafe().Memory;
|
||||||
|
|
||||||
|
public Device Device { get; }
|
||||||
|
public PhysicalDevice PhysicalDevice { get; }
|
||||||
|
public ulong MemorySize { get; }
|
||||||
|
public ulong MemoryOffset { get; }
|
||||||
|
public Extent2D Extent { get; }
|
||||||
|
public ImageState State { get; internal set; }
|
||||||
|
internal PresentImageInfo(
|
||||||
|
Auto<DisposableImage> image,
|
||||||
|
Auto<MemoryAllocation> memory,
|
||||||
|
Device device,
|
||||||
|
PhysicalDevice physicalDevice,
|
||||||
|
ulong memorySize,
|
||||||
|
ulong memoryOffset,
|
||||||
|
Extent2D extent2D,
|
||||||
|
ImageState state)
|
||||||
{
|
{
|
||||||
this.Image = image;
|
_image = image;
|
||||||
this.Memory = memory;
|
_memory = memory;
|
||||||
this.MemorySize = memorySize;
|
Device = device;
|
||||||
this.MemoryOffset = memoryOffset;
|
PhysicalDevice = physicalDevice;
|
||||||
this.ReadySemaphore = readySemaphore;
|
MemorySize = memorySize;
|
||||||
this.AvailableSemaphore = availableSemaphore;
|
MemoryOffset = memoryOffset;
|
||||||
|
Extent = extent2D;
|
||||||
|
State = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Get()
|
||||||
|
{
|
||||||
|
_memory.IncrementReferenceCount();
|
||||||
|
_image.IncrementReferenceCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Put()
|
||||||
|
{
|
||||||
|
_memory.DecrementReferenceCount();
|
||||||
|
_image.DecrementReferenceCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -31,7 +31,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
Length = length;
|
Length = length;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Span<T> ToSpan()
|
public Span<T> AsSpan()
|
||||||
{
|
{
|
||||||
return new Span<T>(Pointer, Length);
|
return new Span<T>(Pointer, Length);
|
||||||
}
|
}
|
||||||
|
@@ -582,7 +582,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_newState.PipelineLayout = internalProgram.PipelineLayout;
|
_newState.PipelineLayout = internalProgram.PipelineLayout;
|
||||||
_newState.StagesCount = (uint)stages.Length;
|
_newState.StagesCount = (uint)stages.Length;
|
||||||
|
|
||||||
stages.CopyTo(_newState.Stages.ToSpan().Slice(0, stages.Length));
|
stages.CopyTo(_newState.Stages.AsSpan().Slice(0, stages.Length));
|
||||||
|
|
||||||
SignalStateChange();
|
SignalStateChange();
|
||||||
}
|
}
|
||||||
@@ -921,7 +921,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
protected void UpdatePipelineAttachmentFormats()
|
protected void UpdatePipelineAttachmentFormats()
|
||||||
{
|
{
|
||||||
var dstAttachmentFormats = _newState.Internal.AttachmentFormats.ToSpan();
|
var dstAttachmentFormats = _newState.Internal.AttachmentFormats.AsSpan();
|
||||||
FramebufferParams.AttachmentFormats.CopyTo(dstAttachmentFormats);
|
FramebufferParams.AttachmentFormats.CopyTo(dstAttachmentFormats);
|
||||||
|
|
||||||
int maxAttachmentIndex = FramebufferParams.MaxColorAttachmentIndex + (FramebufferParams.HasDepthStencil ? 1 : 0);
|
int maxAttachmentIndex = FramebufferParams.MaxColorAttachmentIndex + (FramebufferParams.HasDepthStencil ? 1 : 0);
|
||||||
|
@@ -117,7 +117,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
private void RecordScissor(Vk api, CommandBuffer commandBuffer)
|
private void RecordScissor(Vk api, CommandBuffer commandBuffer)
|
||||||
{
|
{
|
||||||
api.CmdSetScissor(commandBuffer, 0, (uint)ScissorsCount, _scissors.ToSpan());
|
api.CmdSetScissor(commandBuffer, 0, (uint)ScissorsCount, _scissors.AsSpan());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RecordStencilMasks(Vk api, CommandBuffer commandBuffer)
|
private void RecordStencilMasks(Vk api, CommandBuffer commandBuffer)
|
||||||
@@ -132,7 +132,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
private void RecordViewport(Vk api, CommandBuffer commandBuffer)
|
private void RecordViewport(Vk api, CommandBuffer commandBuffer)
|
||||||
{
|
{
|
||||||
api.CmdSetViewport(commandBuffer, 0, (uint)ViewportsCount, Viewports.ToSpan());
|
api.CmdSetViewport(commandBuffer, 0, (uint)ViewportsCount, Viewports.AsSpan());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -52,22 +52,22 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SequenceEqual<VertexInputAttributeDescription>(VertexAttributeDescriptions.ToSpan(), other.VertexAttributeDescriptions.ToSpan(), VertexAttributeDescriptionsCount))
|
if (!SequenceEqual<VertexInputAttributeDescription>(VertexAttributeDescriptions.AsSpan(), other.VertexAttributeDescriptions.AsSpan(), VertexAttributeDescriptionsCount))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SequenceEqual<VertexInputBindingDescription>(VertexBindingDescriptions.ToSpan(), other.VertexBindingDescriptions.ToSpan(), VertexBindingDescriptionsCount))
|
if (!SequenceEqual<VertexInputBindingDescription>(VertexBindingDescriptions.AsSpan(), other.VertexBindingDescriptions.AsSpan(), VertexBindingDescriptionsCount))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SequenceEqual<PipelineColorBlendAttachmentState>(ColorBlendAttachmentState.ToSpan(), other.ColorBlendAttachmentState.ToSpan(), ColorBlendAttachmentStateCount))
|
if (!SequenceEqual<PipelineColorBlendAttachmentState>(ColorBlendAttachmentState.AsSpan(), other.ColorBlendAttachmentState.AsSpan(), ColorBlendAttachmentStateCount))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SequenceEqual<Format>(AttachmentFormats.ToSpan(), other.AttachmentFormats.ToSpan(), ColorBlendAttachmentStateCount + (HasDepthStencil ? 1u : 0u)))
|
if (!SequenceEqual<Format>(AttachmentFormats.AsSpan(), other.AttachmentFormats.AsSpan(), ColorBlendAttachmentStateCount + (HasDepthStencil ? 1u : 0u)))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@@ -245,7 +245,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
PipelineState pipeline = _state.ToVulkanPipelineState(_gd);
|
PipelineState pipeline = _state.ToVulkanPipelineState(_gd);
|
||||||
|
|
||||||
// Copy the shader stage info to the pipeline.
|
// Copy the shader stage info to the pipeline.
|
||||||
var stages = pipeline.Stages.ToSpan();
|
var stages = pipeline.Stages.AsSpan();
|
||||||
|
|
||||||
for (int i = 0; i < _shaders.Length; i++)
|
for (int i = 0; i < _shaders.Length; i++)
|
||||||
{
|
{
|
||||||
|
@@ -25,6 +25,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
private int _width;
|
private int _width;
|
||||||
private int _height;
|
private int _height;
|
||||||
|
private bool _vsyncEnabled;
|
||||||
|
private bool _vsyncModeChanged;
|
||||||
private VkFormat _format;
|
private VkFormat _format;
|
||||||
|
|
||||||
public unsafe Window(VulkanRenderer gd, SurfaceKHR surface, PhysicalDevice physicalDevice, Device device)
|
public unsafe Window(VulkanRenderer gd, SurfaceKHR surface, PhysicalDevice physicalDevice, Device device)
|
||||||
@@ -47,6 +49,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
private void RecreateSwapchain()
|
private void RecreateSwapchain()
|
||||||
{
|
{
|
||||||
|
_vsyncModeChanged = false;
|
||||||
|
|
||||||
for (int i = 0; i < _swapchainImageViews.Length; i++)
|
for (int i = 0; i < _swapchainImageViews.Length; i++)
|
||||||
{
|
{
|
||||||
_swapchainImageViews[i].Dispose();
|
_swapchainImageViews[i].Dispose();
|
||||||
@@ -110,7 +114,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
ImageArrayLayers = 1,
|
ImageArrayLayers = 1,
|
||||||
PreTransform = capabilities.CurrentTransform,
|
PreTransform = capabilities.CurrentTransform,
|
||||||
CompositeAlpha = CompositeAlphaFlagsKHR.CompositeAlphaOpaqueBitKhr,
|
CompositeAlpha = CompositeAlphaFlagsKHR.CompositeAlphaOpaqueBitKhr,
|
||||||
PresentMode = ChooseSwapPresentMode(presentModes),
|
PresentMode = ChooseSwapPresentMode(presentModes, _vsyncEnabled),
|
||||||
Clipped = true,
|
Clipped = true,
|
||||||
OldSwapchain = oldSwapchain
|
OldSwapchain = oldSwapchain
|
||||||
};
|
};
|
||||||
@@ -178,9 +182,9 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
return availableFormats[0];
|
return availableFormats[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PresentModeKHR ChooseSwapPresentMode(PresentModeKHR[] availablePresentModes)
|
private static PresentModeKHR ChooseSwapPresentMode(PresentModeKHR[] availablePresentModes, bool vsyncEnabled)
|
||||||
{
|
{
|
||||||
if (availablePresentModes.Contains(PresentModeKHR.PresentModeImmediateKhr))
|
if (!vsyncEnabled && availablePresentModes.Contains(PresentModeKHR.PresentModeImmediateKhr))
|
||||||
{
|
{
|
||||||
return PresentModeKHR.PresentModeImmediateKhr;
|
return PresentModeKHR.PresentModeImmediateKhr;
|
||||||
}
|
}
|
||||||
@@ -188,6 +192,10 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
return PresentModeKHR.PresentModeMailboxKhr;
|
return PresentModeKHR.PresentModeMailboxKhr;
|
||||||
}
|
}
|
||||||
|
else if (availablePresentModes.Contains(PresentModeKHR.PresentModeFifoKhr))
|
||||||
|
{
|
||||||
|
return PresentModeKHR.PresentModeFifoKhr;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return PresentModeKHR.PresentModeFifoKhr;
|
return PresentModeKHR.PresentModeFifoKhr;
|
||||||
@@ -224,7 +232,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
ref nextImage);
|
ref nextImage);
|
||||||
|
|
||||||
if (acquireResult == Result.ErrorOutOfDateKhr ||
|
if (acquireResult == Result.ErrorOutOfDateKhr ||
|
||||||
acquireResult == Result.SuboptimalKhr)
|
acquireResult == Result.SuboptimalKhr ||
|
||||||
|
_vsyncModeChanged)
|
||||||
{
|
{
|
||||||
RecreateSwapchain();
|
RecreateSwapchain();
|
||||||
}
|
}
|
||||||
@@ -404,6 +413,12 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
// Not needed as we can get the size from the surface.
|
// Not needed as we can get the size from the surface.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void ChangeVSyncMode(bool vsyncEnabled)
|
||||||
|
{
|
||||||
|
_vsyncEnabled = vsyncEnabled;
|
||||||
|
_vsyncModeChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
|
@@ -10,5 +10,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
public abstract void Dispose();
|
public abstract void Dispose();
|
||||||
public abstract void Present(ITexture texture, ImageCrop crop, Action<object> swapBuffersCallback);
|
public abstract void Present(ITexture texture, ImageCrop crop, Action<object> swapBuffersCallback);
|
||||||
public abstract void SetSize(int width, int height);
|
public abstract void SetSize(int width, int height);
|
||||||
|
public abstract void ChangeVSyncMode(bool vsyncEnabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -72,9 +72,16 @@ namespace Ryujinx.HLE.HOS.Applets
|
|||||||
|
|
||||||
int playerMin = argHeader.PlayerCountMin;
|
int playerMin = argHeader.PlayerCountMin;
|
||||||
int playerMax = argHeader.PlayerCountMax;
|
int playerMax = argHeader.PlayerCountMax;
|
||||||
|
bool singleMode = argHeader.EnableSingleMode != 0;
|
||||||
|
|
||||||
Logger.Stub?.PrintStub(LogClass.ServiceHid, $"ControllerApplet Arg {playerMin} {playerMax} {argHeader.EnableTakeOverConnection} {argHeader.EnableSingleMode}");
|
Logger.Stub?.PrintStub(LogClass.ServiceHid, $"ControllerApplet Arg {playerMin} {playerMax} {argHeader.EnableTakeOverConnection} {argHeader.EnableSingleMode}");
|
||||||
|
|
||||||
|
if (singleMode)
|
||||||
|
{
|
||||||
|
// Applications can set an arbitrary player range even with SingleMode, so clamp it
|
||||||
|
playerMin = playerMax = 1;
|
||||||
|
}
|
||||||
|
|
||||||
int configuredCount = 0;
|
int configuredCount = 0;
|
||||||
PlayerIndex primaryIndex = PlayerIndex.Unknown;
|
PlayerIndex primaryIndex = PlayerIndex.Unknown;
|
||||||
while (!_system.Device.Hid.Npads.Validate(playerMin, playerMax, (ControllerType)privateArg.NpadStyleSet, out configuredCount, out primaryIndex))
|
while (!_system.Device.Hid.Npads.Validate(playerMin, playerMax, (ControllerType)privateArg.NpadStyleSet, out configuredCount, out primaryIndex))
|
||||||
|
@@ -19,7 +19,7 @@ namespace Ryujinx.HLE.HOS.Applets
|
|||||||
{
|
{
|
||||||
private byte element;
|
private byte element;
|
||||||
|
|
||||||
public Span<byte> ToSpan() => MemoryMarshal.CreateSpan(ref element, 8 * 0x81);
|
public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref element, 8 * 0x81);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#pragma warning restore CS0649
|
#pragma warning restore CS0649
|
||||||
|
@@ -19,7 +19,7 @@ namespace Ryujinx.HLE.HOS.Applets
|
|||||||
{
|
{
|
||||||
private byte element;
|
private byte element;
|
||||||
|
|
||||||
public Span<byte> ToSpan() => MemoryMarshal.CreateSpan(ref element, 4 * 0x81);
|
public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref element, 4 * 0x81);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#pragma warning restore CS0649
|
#pragma warning restore CS0649
|
||||||
|
@@ -179,8 +179,8 @@ namespace Ryujinx.HLE.HOS.Applets.Error
|
|||||||
byte[] messageTextBuffer = new byte[0x800];
|
byte[] messageTextBuffer = new byte[0x800];
|
||||||
byte[] detailsTextBuffer = new byte[0x800];
|
byte[] detailsTextBuffer = new byte[0x800];
|
||||||
|
|
||||||
applicationErrorArg.MessageText.ToSpan().CopyTo(messageTextBuffer);
|
applicationErrorArg.MessageText.AsSpan().CopyTo(messageTextBuffer);
|
||||||
applicationErrorArg.DetailsText.ToSpan().CopyTo(detailsTextBuffer);
|
applicationErrorArg.DetailsText.AsSpan().CopyTo(detailsTextBuffer);
|
||||||
|
|
||||||
string messageText = Encoding.ASCII.GetString(messageTextBuffer.TakeWhile(b => !b.Equals(0)).ToArray());
|
string messageText = Encoding.ASCII.GetString(messageTextBuffer.TakeWhile(b => !b.Equals(0)).ToArray());
|
||||||
string detailsText = Encoding.ASCII.GetString(detailsTextBuffer.TakeWhile(b => !b.Equals(0)).ToArray());
|
string detailsText = Encoding.ASCII.GetString(detailsTextBuffer.TakeWhile(b => !b.Equals(0)).ToArray());
|
||||||
|
@@ -224,6 +224,17 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
|
|||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[CommandHipc(62)] // 4.0.0+
|
||||||
|
// GetHdcpAuthenticationState() -> s32 state
|
||||||
|
public ResultCode GetHdcpAuthenticationState(ServiceCtx context)
|
||||||
|
{
|
||||||
|
context.ResponseData.Write(0);
|
||||||
|
|
||||||
|
Logger.Stub?.PrintStub(LogClass.ServiceAm);
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
[CommandHipc(66)] // 6.0.0+
|
[CommandHipc(66)] // 6.0.0+
|
||||||
// SetCpuBoostMode(u32 cpu_boost_mode)
|
// SetCpuBoostMode(u32 cpu_boost_mode)
|
||||||
public ResultCode SetCpuBoostMode(ServiceCtx context)
|
public ResultCode SetCpuBoostMode(ServiceCtx context)
|
||||||
|
@@ -2,6 +2,7 @@ using Ryujinx.Common.Logging;
|
|||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
|
using Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy.Types;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
|
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
|
||||||
@@ -316,6 +317,22 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
|
|||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[CommandHipc(80)] // 4.0.0+
|
||||||
|
// SetWirelessPriorityMode(s32 wireless_priority_mode)
|
||||||
|
public ResultCode SetWirelessPriorityMode(ServiceCtx context)
|
||||||
|
{
|
||||||
|
WirelessPriorityMode wirelessPriorityMode = (WirelessPriorityMode)context.RequestData.ReadInt32();
|
||||||
|
|
||||||
|
if (wirelessPriorityMode > WirelessPriorityMode.Unknown2)
|
||||||
|
{
|
||||||
|
return ResultCode.InvalidParameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.Stub?.PrintStub(LogClass.ServiceAm, new { wirelessPriorityMode });
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
[CommandHipc(90)] // 6.0.0+
|
[CommandHipc(90)] // 6.0.0+
|
||||||
// GetAccumulatedSuspendedTickValue() -> u64
|
// GetAccumulatedSuspendedTickValue() -> u64
|
||||||
public ResultCode GetAccumulatedSuspendedTickValue(ServiceCtx context)
|
public ResultCode GetAccumulatedSuspendedTickValue(ServiceCtx context)
|
||||||
@@ -356,5 +373,21 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
|
|||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[CommandHipc(120)] // 11.0.0+
|
||||||
|
// SaveCurrentScreenshot(s32 album_report_option)
|
||||||
|
public ResultCode SaveCurrentScreenshot(ServiceCtx context)
|
||||||
|
{
|
||||||
|
AlbumReportOption albumReportOption = (AlbumReportOption)context.RequestData.ReadInt32();
|
||||||
|
|
||||||
|
if (albumReportOption > AlbumReportOption.Unknown3)
|
||||||
|
{
|
||||||
|
return ResultCode.InvalidParameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.Stub?.PrintStub(LogClass.ServiceAm, new { albumReportOption });
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -0,0 +1,10 @@
|
|||||||
|
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy.Types
|
||||||
|
{
|
||||||
|
enum AlbumReportOption
|
||||||
|
{
|
||||||
|
OverlayNotDisplayed,
|
||||||
|
OverlayDisplayed,
|
||||||
|
Unknown2,
|
||||||
|
Unknown3
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,9 @@
|
|||||||
|
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy.Types
|
||||||
|
{
|
||||||
|
enum WirelessPriorityMode
|
||||||
|
{
|
||||||
|
Default,
|
||||||
|
OptimizedForWlan,
|
||||||
|
Unknown2
|
||||||
|
}
|
||||||
|
}
|
@@ -117,7 +117,7 @@ namespace Ryujinx.HLE.HOS.Services.Audio
|
|||||||
|
|
||||||
OpusMultiStreamParametersEx parameters = context.Memory.Read<OpusMultiStreamParametersEx>(parametersAddress);
|
OpusMultiStreamParametersEx parameters = context.Memory.Read<OpusMultiStreamParametersEx>(parametersAddress);
|
||||||
|
|
||||||
byte[] mappings = MemoryMarshal.Cast<uint, byte>(parameters.ChannelMappings.ToSpan()).ToArray();
|
byte[] mappings = MemoryMarshal.Cast<uint, byte>(parameters.ChannelMappings.AsSpan()).ToArray();
|
||||||
|
|
||||||
// UseLargeFrameSize can be ignored due to not relying on fixed size buffers for storing the decoded result.
|
// UseLargeFrameSize can be ignored due to not relying on fixed size buffers for storing the decoded result.
|
||||||
MakeObject(context, new IHardwareOpusDecoder(
|
MakeObject(context, new IHardwareOpusDecoder(
|
||||||
|
@@ -131,7 +131,7 @@ namespace Ryujinx.HLE.HOS.Services.Friend.ServiceCreator
|
|||||||
return ResultCode.InvalidArgument;
|
return ResultCode.InvalidArgument;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Service mount the friends:/ system savedata and try to load friend.cache file, returns true if exists, false otherwise.
|
// TODO: Service mount the friends:/ system savedata and try to load friend.cache file, returns true if exists, false otherwise.
|
||||||
// NOTE: If no cache is available, guest then calls nn::friends::EnsureFriendListAvailable, we can avoid that by faking the cache check.
|
// NOTE: If no cache is available, guest then calls nn::friends::EnsureFriendListAvailable, we can avoid that by faking the cache check.
|
||||||
context.ResponseData.Write(true);
|
context.ResponseData.Write(true);
|
||||||
|
|
||||||
@@ -190,7 +190,7 @@ namespace Ryujinx.HLE.HOS.Services.Friend.ServiceCreator
|
|||||||
}
|
}
|
||||||
|
|
||||||
context.Device.System.AccountManager.OpenUserOnlinePlay(userId);
|
context.Device.System.AccountManager.OpenUserOnlinePlay(userId);
|
||||||
|
|
||||||
Logger.Stub?.PrintStub(LogClass.ServiceFriend, new { UserId = userId.ToString() });
|
Logger.Stub?.PrintStub(LogClass.ServiceFriend, new { UserId = userId.ToString() });
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
@@ -277,7 +277,7 @@ namespace Ryujinx.HLE.HOS.Services.Friend.ServiceCreator
|
|||||||
|
|
||||||
Array16<byte> randomGuid = new Array16<byte>();
|
Array16<byte> randomGuid = new Array16<byte>();
|
||||||
|
|
||||||
Guid.NewGuid().ToByteArray().AsSpan().CopyTo(randomGuid.ToSpan());
|
Guid.NewGuid().ToByteArray().AsSpan().CopyTo(randomGuid.AsSpan());
|
||||||
|
|
||||||
PlayHistoryRegistrationKey playHistoryRegistrationKey = new PlayHistoryRegistrationKey
|
PlayHistoryRegistrationKey playHistoryRegistrationKey = new PlayHistoryRegistrationKey
|
||||||
{
|
{
|
||||||
|
@@ -26,7 +26,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
|||||||
SamplingNumber = previousEntry.SamplingNumber + 1,
|
SamplingNumber = previousEntry.SamplingNumber + 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
keyState.Keys.AsSpan().CopyTo(newState.Keys.RawData.ToSpan());
|
keyState.Keys.AsSpan().CopyTo(newState.Keys.RawData.AsSpan());
|
||||||
newState.Modifiers = (KeyboardModifier)keyState.Modifier;
|
newState.Modifiers = (KeyboardModifier)keyState.Modifier;
|
||||||
|
|
||||||
lifo.Write(ref newState);
|
lifo.Write(ref newState);
|
||||||
|
@@ -543,7 +543,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
|||||||
Attributes = SixAxisSensorAttribute.IsConnected
|
Attributes = SixAxisSensorAttribute.IsConnected
|
||||||
};
|
};
|
||||||
|
|
||||||
state.Orientation.AsSpan().CopyTo(newState.Direction.ToSpan());
|
state.Orientation.AsSpan().CopyTo(newState.Direction.AsSpan());
|
||||||
|
|
||||||
ref RingLifo<SixAxisSensorState> lifo = ref GetSixAxisSensorLifo(ref currentNpad, isRightPair);
|
ref RingLifo<SixAxisSensorState> lifo = ref GetSixAxisSensorLifo(ref currentNpad, isRightPair);
|
||||||
|
|
||||||
|
@@ -628,7 +628,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
|
|||||||
Reserved2 = new Array6<byte>()
|
Reserved2 = new Array6<byte>()
|
||||||
};
|
};
|
||||||
|
|
||||||
Uuid.CopyTo(tagInfo.Uuid.ToSpan());
|
Uuid.CopyTo(tagInfo.Uuid.AsSpan());
|
||||||
|
|
||||||
context.Memory.Write(outputPosition, tagInfo);
|
context.Memory.Write(outputPosition, tagInfo);
|
||||||
|
|
||||||
|
@@ -85,7 +85,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
|
|||||||
Reserved1 = new Array64<byte>(),
|
Reserved1 = new Array64<byte>(),
|
||||||
Reserved2 = new Array58<byte>()
|
Reserved2 = new Array58<byte>()
|
||||||
};
|
};
|
||||||
Encoding.ASCII.GetBytes("Ryujinx").CopyTo(registerInfo.Nickname.ToSpan());
|
Encoding.ASCII.GetBytes("Ryujinx").CopyTo(registerInfo.Nickname.AsSpan());
|
||||||
|
|
||||||
return registerInfo;
|
return registerInfo;
|
||||||
}
|
}
|
||||||
|
@@ -84,7 +84,7 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
|
|||||||
networkProfile.IpSettingData.IpAddressSetting = new IpAddressSetting(interfaceProperties, unicastAddress);
|
networkProfile.IpSettingData.IpAddressSetting = new IpAddressSetting(interfaceProperties, unicastAddress);
|
||||||
networkProfile.IpSettingData.DnsSetting = new DnsSetting(interfaceProperties);
|
networkProfile.IpSettingData.DnsSetting = new DnsSetting(interfaceProperties);
|
||||||
|
|
||||||
Encoding.ASCII.GetBytes("RyujinxNetwork").CopyTo(networkProfile.Name.ToSpan());
|
Encoding.ASCII.GetBytes("RyujinxNetwork").CopyTo(networkProfile.Name.AsSpan());
|
||||||
|
|
||||||
context.Memory.Write(networkProfileDataPosition, networkProfile);
|
context.Memory.Write(networkProfileDataPosition, networkProfile);
|
||||||
|
|
||||||
|
@@ -16,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
|||||||
|
|
||||||
public IPEndPoint ToIPEndPoint()
|
public IPEndPoint ToIPEndPoint()
|
||||||
{
|
{
|
||||||
IPAddress address = new IPAddress(Address.ToSpan());
|
IPAddress address = new IPAddress(Address.AsSpan());
|
||||||
int port = (ushort)IPAddress.NetworkToHostOrder((short)Port);
|
int port = (ushort)IPAddress.NetworkToHostOrder((short)Port);
|
||||||
|
|
||||||
return new IPEndPoint(address, port);
|
return new IPEndPoint(address, port);
|
||||||
@@ -31,7 +31,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
|||||||
Port = (ushort)IPAddress.HostToNetworkOrder((short)endpoint.Port)
|
Port = (ushort)IPAddress.HostToNetworkOrder((short)endpoint.Port)
|
||||||
};
|
};
|
||||||
|
|
||||||
endpoint.Address.GetAddressBytes().AsSpan().CopyTo(result.Address.ToSpan());
|
endpoint.Address.GetAddressBytes().AsSpan().CopyTo(result.Address.AsSpan());
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@@ -22,7 +22,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres.Types
|
|||||||
Port = port;
|
Port = port;
|
||||||
Address = new Array4<byte>();
|
Address = new Array4<byte>();
|
||||||
|
|
||||||
address.TryWriteBytes(Address.ToSpan(), out _);
|
address.TryWriteBytes(Address.AsSpan(), out _);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ToNetworkOrder()
|
public void ToNetworkOrder()
|
||||||
@@ -43,7 +43,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres.Types
|
|||||||
{
|
{
|
||||||
if (BitConverter.IsLittleEndian)
|
if (BitConverter.IsLittleEndian)
|
||||||
{
|
{
|
||||||
address.ToSpan().Reverse();
|
address.AsSpan().Reverse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1440,7 +1440,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
|||||||
|
|
||||||
int timeZoneSize = Math.Min(StringUtils.LengthCstr(timeZoneAbbreviation), 8);
|
int timeZoneSize = Math.Min(StringUtils.LengthCstr(timeZoneAbbreviation), 8);
|
||||||
|
|
||||||
timeZoneAbbreviation[..timeZoneSize].CopyTo(calendarAdditionalInfo.TimezoneName.ToSpan());
|
timeZoneAbbreviation[..timeZoneSize].CopyTo(calendarAdditionalInfo.TimezoneName.AsSpan());
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@@ -49,7 +49,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
|
|||||||
Height = height
|
Height = height
|
||||||
};
|
};
|
||||||
|
|
||||||
Encoding.ASCII.GetBytes(name).AsSpan().CopyTo(displayInfo.Name.ToSpan());
|
Encoding.ASCII.GetBytes(name).AsSpan().CopyTo(displayInfo.Name.AsSpan());
|
||||||
|
|
||||||
_displayInfo.Add(displayInfo);
|
_displayInfo.Add(displayInfo);
|
||||||
}
|
}
|
||||||
@@ -171,7 +171,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
|
|||||||
return ResultCode.InvalidValue;
|
return ResultCode.InvalidValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int displayId = _displayInfo.FindIndex(display => Encoding.ASCII.GetString(display.Name.ToSpan()).Trim('\0') == name);
|
int displayId = _displayInfo.FindIndex(display => Encoding.ASCII.GetString(display.Name.AsSpan()).Trim('\0') == name);
|
||||||
|
|
||||||
if (displayId == -1)
|
if (displayId == -1)
|
||||||
{
|
{
|
||||||
|
@@ -402,6 +402,8 @@ namespace Ryujinx.Ui
|
|||||||
Device.Gpu.InitializeShaderCache(_gpuCancellationTokenSource.Token);
|
Device.Gpu.InitializeShaderCache(_gpuCancellationTokenSource.Token);
|
||||||
Translator.IsReadyForTranslation.Set();
|
Translator.IsReadyForTranslation.Set();
|
||||||
|
|
||||||
|
Renderer.Window.ChangeVSyncMode(Device.EnableDeviceVsync);
|
||||||
|
|
||||||
(Toplevel as MainWindow)?.ActivatePauseMenu();
|
(Toplevel as MainWindow)?.ActivatePauseMenu();
|
||||||
|
|
||||||
while (_isActive)
|
while (_isActive)
|
||||||
|
@@ -46,7 +46,7 @@ namespace Spv.Generator
|
|||||||
result += _resultType.WordCount;
|
result += _resultType.WordCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
Span<Operand> operands = _operands.ToSpan();
|
Span<Operand> operands = _operands.AsSpan();
|
||||||
for (int i = 0; i < operands.Length; i++)
|
for (int i = 0; i < operands.Length; i++)
|
||||||
{
|
{
|
||||||
result += operands[i].WordCount;
|
result += operands[i].WordCount;
|
||||||
@@ -120,7 +120,7 @@ namespace Spv.Generator
|
|||||||
writer.Write(Id);
|
writer.Write(Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Span<Operand> operands = _operands.ToSpan();
|
Span<Operand> operands = _operands.AsSpan();
|
||||||
for (int i = 0; i < operands.Length; i++)
|
for (int i = 0; i < operands.Length; i++)
|
||||||
{
|
{
|
||||||
operands[i].WriteOperand(writer);
|
operands[i].WriteOperand(writer);
|
||||||
@@ -185,8 +185,8 @@ namespace Spv.Generator
|
|||||||
|
|
||||||
public bool EqualsContent(Instruction cmpObj)
|
public bool EqualsContent(Instruction cmpObj)
|
||||||
{
|
{
|
||||||
Span<Operand> thisOperands = _operands.ToSpan();
|
Span<Operand> thisOperands = _operands.AsSpan();
|
||||||
Span<Operand> cmpOperands = cmpObj._operands.ToSpan();
|
Span<Operand> cmpOperands = cmpObj._operands.AsSpan();
|
||||||
|
|
||||||
if (thisOperands.Length != cmpOperands.Length)
|
if (thisOperands.Length != cmpOperands.Length)
|
||||||
{
|
{
|
||||||
@@ -211,7 +211,7 @@ namespace Spv.Generator
|
|||||||
|
|
||||||
public int GetHashCodeContent()
|
public int GetHashCodeContent()
|
||||||
{
|
{
|
||||||
return DeterministicHashCode.Combine<Operand>(_operands.ToSpan());
|
return DeterministicHashCode.Combine<Operand>(_operands.AsSpan());
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetHashCodeResultType()
|
public int GetHashCodeResultType()
|
||||||
@@ -221,7 +221,7 @@ namespace Spv.Generator
|
|||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
return DeterministicHashCode.Combine(Opcode, Id, _resultType, DeterministicHashCode.Combine<Operand>(_operands.ToSpan()));
|
return DeterministicHashCode.Combine(Opcode, Id, _resultType, DeterministicHashCode.Combine<Operand>(_operands.AsSpan()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Equals(Operand obj)
|
public bool Equals(Operand obj)
|
||||||
|
@@ -15,7 +15,7 @@ namespace Spv.Generator
|
|||||||
public Operand Operand5;
|
public Operand Operand5;
|
||||||
public Operand[] Overflow;
|
public Operand[] Overflow;
|
||||||
|
|
||||||
public Span<Operand> ToSpan()
|
public Span<Operand> AsSpan()
|
||||||
{
|
{
|
||||||
if (Count > InternalCount)
|
if (Count > InternalCount)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user