Compare commits

..

2 Commits

Author SHA1 Message Date
Keaton
38e58b90f0 Merge d9587ffa28 into 1219f329c1 2025-03-10 18:55:46 +02:00
KeatonTheBot
d9587ffa28 Revert "Vulkan: Feedback loop detection and barriers (#7226)"
This reverts commit ca59c3f499.
2025-02-26 15:38:52 -06:00
48 changed files with 242 additions and 1138 deletions

View File

@@ -19,7 +19,6 @@ jobs:
configuration: [Debug, Release] configuration: [Debug, Release]
platform: platform:
- { name: win-x64, os: windows-latest, zip_os_name: win_x64 } - { name: win-x64, os: windows-latest, zip_os_name: win_x64 }
- { name: win-arm64, os: windows-latest, zip_os_name: win_arm64 }
- { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 } - { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 }
- { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 } - { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 }
- { name: osx-x64, os: macos-13, zip_os_name: osx_x64 } - { name: osx-x64, os: macos-13, zip_os_name: osx_x64 }

View File

@@ -62,7 +62,6 @@ jobs:
| Platform | Artifact | | Platform | Artifact |
|--|--| |--|--|
| Windows 64-bit | [Canary Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip) | | Windows 64-bit | [Canary Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip) |
| Windows ARM 64-bit | [Canary Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_arm64.zip) |
| Linux 64-bit | [Canary Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) | | Linux 64-bit | [Canary Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) |
| Linux ARM 64-bit | [Canary Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) | | Linux ARM 64-bit | [Canary Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) |
| macOS | [Canary macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) | | macOS | [Canary macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) |
@@ -80,7 +79,6 @@ jobs:
matrix: matrix:
platform: platform:
- { name: win-x64, os: windows-latest, zip_os_name: win_x64 } - { name: win-x64, os: windows-latest, zip_os_name: win_x64 }
- { name: win-arm64, os: windows-latest, zip_os_name: win_arm64 }
- { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 } - { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 }
- { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 } - { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 }
steps: steps:

View File

@@ -66,7 +66,6 @@ jobs:
matrix: matrix:
platform: platform:
- { name: win-x64, os: windows-latest, zip_os_name: win_x64 } - { name: win-x64, os: windows-latest, zip_os_name: win_x64 }
- { name: win-arm64, os: windows-latest, zip_os_name: win_arm64 }
- { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 } - { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 }
- { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 } - { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 }
steps: steps:
@@ -118,7 +117,6 @@ jobs:
if: matrix.platform.os == 'ubuntu-latest' if: matrix.platform.os == 'ubuntu-latest'
run: | run: |
pushd publish pushd publish
rm libarmeilleure-jitsupport.dylib
chmod +x Ryujinx.sh Ryujinx chmod +x Ryujinx.sh Ryujinx
tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish
popd popd

View File

@@ -39,7 +39,7 @@
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.8.2" /> <PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.8.2" />
<PackageVersion Include="Open.NAT.Core" Version="2.1.0.5" /> <PackageVersion Include="Open.NAT.Core" Version="2.1.0.5" />
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" /> <PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.AllArch" Version="6.1.2-build3" /> <PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.3-build14" />
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" /> <PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" /> <PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
<PackageVersion Include="Gommon" Version="2.7.1.1" /> <PackageVersion Include="Gommon" Version="2.7.1.1" />
@@ -53,8 +53,8 @@
<PackageVersion Include="SkiaSharp" Version="2.88.9" /> <PackageVersion Include="SkiaSharp" Version="2.88.9" />
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.9" /> <PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.9" />
<PackageVersion Include="SPB" Version="0.0.4-build32" /> <PackageVersion Include="SPB" Version="0.0.4-build32" />
<PackageVersion Include="System.IO.Hashing" Version="9.0.2" /> <PackageVersion Include="System.IO.Hashing" Version="9.0.0" />
<PackageVersion Include="System.Management" Version="9.0.2" /> <PackageVersion Include="System.Management" Version="9.0.0" />
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" /> <PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -1,14 +1,14 @@
<table align="center"> <table align="center">
<tr> <tr>
<td align="center" width="25%"> <td align="center" width="25%">
<img src="https://raw.githubusercontent.com/Ryubing/Assets/refs/heads/main/RyujinxApp_1024.png" alt="Ryujinx" > <img src="https://raw.githubusercontent.com/GreemDev/ryuassets/refs/heads/main/RyujinxApp_1024.png" alt="Ryujinx" >
</td> </td>
<td align="center" width="75%"> <td align="center" width="75%">
# Ryujinx # Ryujinx
[![Release workflow](https://github.com/Ryubing/Ryujinx/actions/workflows/release.yml/badge.svg)](https://github.com/Ryubing/Ryujinx/actions/workflows/release.yml) [![Release workflow](https://github.com/Ryubing/Ryujinx/actions/workflows/release.yml/badge.svg)](https://github.com/Ryubing/Ryujinx/actions/workflows/release.yml)
[![Latest release](https://img.shields.io/github/v/release/Ryubing/Ryujinx)](https://github.com/Ryubing/Ryujinx/releases/latest) [![Latest release](https://img.shields.io/github/v/release/GreemDev/Ryujinx)](https://github.com/Ryubing/Ryujinx/releases/latest)
<br> <br>
[![Canary workflow](https://github.com/Ryubing/Ryujinx/actions/workflows/canary.yml/badge.svg)](https://github.com/Ryubing/Ryujinx/actions/workflows/canary.yml) [![Canary workflow](https://github.com/Ryubing/Ryujinx/actions/workflows/canary.yml/badge.svg)](https://github.com/Ryubing/Ryujinx/actions/workflows/canary.yml)
[![Latest canary release](https://img.shields.io/github/v/release/Ryubing/Canary-Releases?label=canary)](https://github.com/Ryubing/Canary-Releases/releases/latest) [![Latest canary release](https://img.shields.io/github/v/release/Ryubing/Canary-Releases?label=canary)](https://github.com/Ryubing/Canary-Releases/releases/latest)

View File

@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<RuntimeIdentifiers>win-x64;osx-x64;linux-x64;win-arm64;osx-arm64;linux-arm64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;osx-x64;linux-x64</RuntimeIdentifiers>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes> <DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
@@ -11,15 +11,15 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.dll" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'"> <ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.dll" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64'">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>libsoundio.dll</TargetPath> <TargetPath>libsoundio.dll</TargetPath>
</ContentWithTargetPath> </ContentWithTargetPath>
<ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.dylib" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'win-x64' AND '$(RuntimeIdentifier)' != 'win-arm64'"> <ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.dylib" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'win-x64'">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>libsoundio.dylib</TargetPath> <TargetPath>libsoundio.dylib</TargetPath>
</ContentWithTargetPath> </ContentWithTargetPath>
<ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.so" Condition="'$(RuntimeIdentifier)' != 'win-x64' AND '$(RuntimeIdentifier)' != 'win-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64' AND '$(RuntimeIdentifier)' != 'linux-arm64'"> <ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.so" Condition="'$(RuntimeIdentifier)' != 'win-x64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64'">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>libsoundio.so</TargetPath> <TargetPath>libsoundio.so</TargetPath>
</ContentWithTargetPath> </ContentWithTargetPath>

View File

@@ -13,7 +13,5 @@ namespace Ryujinx.Common.Configuration.Hid
public Key VolumeDown { get; set; } public Key VolumeDown { get; set; }
public Key CustomVSyncIntervalIncrement { get; set; } public Key CustomVSyncIntervalIncrement { get; set; }
public Key CustomVSyncIntervalDecrement { get; set; } public Key CustomVSyncIntervalDecrement { get; set; }
public Key TurboMode { get; set; }
public bool TurboModeWhileHeld { get; set; }
} }
} }

View File

@@ -1,4 +1,3 @@
using Ryujinx.Common.Utilities;
using System; using System;
namespace Ryujinx.Common.GraphicsDriver namespace Ryujinx.Common.GraphicsDriver
@@ -11,7 +10,7 @@ namespace Ryujinx.Common.GraphicsDriver
string flags = existingFlags == null ? newFlags : $"{existingFlags},{newFlags}"; string flags = existingFlags == null ? newFlags : $"{existingFlags},{newFlags}";
OsUtils.SetEnvironmentVariableNoCaching(envVar, flags); Environment.SetEnvironmentVariable(envVar, flags);
} }
public static void InitDriverConfig(bool oglThreading) public static void InitDriverConfig(bool oglThreading)
@@ -23,11 +22,10 @@ namespace Ryujinx.Common.GraphicsDriver
ToggleOGLThreading(oglThreading); ToggleOGLThreading(oglThreading);
} }
public static void ToggleOGLThreading(bool enabled) public static void ToggleOGLThreading(bool enabled)
{ {
OsUtils.SetEnvironmentVariableNoCaching("mesa_glthread", enabled.ToString().ToLower()); Environment.SetEnvironmentVariable("mesa_glthread", enabled.ToString().ToLower());
OsUtils.SetEnvironmentVariableNoCaching("__GL_THREADED_OPTIMIZATIONS", enabled ? "1" : "0"); Environment.SetEnvironmentVariable("__GL_THREADED_OPTIMIZATIONS", enabled ? "1" : "0");
try try
{ {

View File

@@ -1,24 +0,0 @@
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Ryujinx.Common.Utilities
{
public partial class OsUtils
{
[LibraryImport("libc", SetLastError = true)]
private static partial int setenv([MarshalAs(UnmanagedType.LPStr)] string name, [MarshalAs(UnmanagedType.LPStr)] string value, int overwrite);
public static void SetEnvironmentVariableNoCaching(string key, string value)
{
// Set the value in the cached environment variables, too.
Environment.SetEnvironmentVariable(key, value);
if (!OperatingSystem.IsWindows())
{
int res = setenv(key, value, 1);
Debug.Assert(res != -1);
}
}
}
}

View File

@@ -8,17 +8,10 @@ namespace Ryujinx.Cpu
/// </summary> /// </summary>
public interface ITickSource : ICounter public interface ITickSource : ICounter
{ {
public const long RealityTickScalar = 100;
/// <summary> /// <summary>
/// Time elapsed since the counter was created. /// Time elapsed since the counter was created.
/// </summary> /// </summary>
TimeSpan ElapsedTime { get; } TimeSpan ElapsedTime { get; }
/// <summary>
/// Clock tick scalar, in percent points (100 = 1.0).
/// </summary>
long TickScalar { get; set; }
/// <summary> /// <summary>
/// Time elapsed since the counter was created, in seconds. /// Time elapsed since the counter was created, in seconds.

View File

@@ -14,37 +14,12 @@ namespace Ryujinx.Cpu
/// <inheritdoc/> /// <inheritdoc/>
public ulong Counter => (ulong)(ElapsedSeconds * Frequency); public ulong Counter => (ulong)(ElapsedSeconds * Frequency);
public long TickScalar { get; set; }
private static long _acumElapsedTicks;
private static long _lastElapsedTicks;
private long ElapsedTicks
{
get
{
long elapsedTicks = _tickCounter.ElapsedTicks;
_acumElapsedTicks += (elapsedTicks - _lastElapsedTicks) * TickScalar / 100;
_lastElapsedTicks = elapsedTicks;
return _acumElapsedTicks;
}
}
/// <inheritdoc/> /// <inheritdoc/>
public TimeSpan ElapsedTime => _tickCounter.Elapsed;
public TimeSpan ElapsedTime => Stopwatch.GetElapsedTime(0, ElapsedTicks);
/// <inheritdoc/> /// <inheritdoc/>
public double ElapsedSeconds => ElapsedTicks * _hostTickFreq; public double ElapsedSeconds => _tickCounter.ElapsedTicks * _hostTickFreq;
public TickSource(ulong frequency) public TickSource(ulong frequency)
{ {

View File

@@ -1065,14 +1065,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
/// </summary> /// </summary>
private void UpdateIndexBufferState() private void UpdateIndexBufferState()
{ {
IndexBufferState? indexBufferNullable = _state?.State.IndexBufferState; IndexBufferState indexBuffer = _state.State.IndexBufferState;
if (!indexBufferNullable.HasValue)
{
return;
}
IndexBufferState indexBuffer = indexBufferNullable.Value;
if (_drawState.IndexCount == 0) if (_drawState.IndexCount == 0)
{ {

View File

@@ -12,8 +12,8 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
private static readonly Dictionary<string, (int, int)> _librariesWhitelist = new() private static readonly Dictionary<string, (int, int)> _librariesWhitelist = new()
{ {
{ AvCodecLibraryName, (58, 61) }, { AvCodecLibraryName, (58, 59) },
{ AvUtilLibraryName, (56, 59) }, { AvUtilLibraryName, (56, 57) },
}; };
private static string FormatLibraryNameForCurrentOs(string libraryName, int version) private static string FormatLibraryNameForCurrentOs(string libraryName, int version)

View File

@@ -32,12 +32,10 @@ namespace Ryujinx.Graphics.Vulkan
CommandBuffer CommandBuffer
} }
private bool _feedbackLoopActive;
private PipelineStageFlags _incoherentBufferWriteStages; private PipelineStageFlags _incoherentBufferWriteStages;
private PipelineStageFlags _incoherentTextureWriteStages; private PipelineStageFlags _incoherentTextureWriteStages;
private PipelineStageFlags _extraStages; private PipelineStageFlags _extraStages;
private IncoherentBarrierType _queuedIncoherentBarrier; private IncoherentBarrierType _queuedIncoherentBarrier;
private bool _queuedFeedbackLoopBarrier;
public BarrierBatch(VulkanRenderer gd) public BarrierBatch(VulkanRenderer gd)
{ {
@@ -55,6 +53,17 @@ namespace Ryujinx.Graphics.Vulkan
stages |= PipelineStageFlags.TransformFeedbackBitExt; stages |= PipelineStageFlags.TransformFeedbackBitExt;
} }
if (!gd.IsTBDR)
{
// Desktop GPUs can transform image barriers into memory barriers.
access |= AccessFlags.DepthStencilAttachmentWriteBit | AccessFlags.ColorAttachmentWriteBit;
access |= AccessFlags.DepthStencilAttachmentReadBit | AccessFlags.ColorAttachmentReadBit;
stages |= PipelineStageFlags.EarlyFragmentTestsBit | PipelineStageFlags.LateFragmentTestsBit;
stages |= PipelineStageFlags.ColorAttachmentOutputBit;
}
return (access, stages); return (access, stages);
} }
@@ -169,34 +178,16 @@ namespace Ryujinx.Graphics.Vulkan
} }
_queuedIncoherentBarrier = IncoherentBarrierType.None; _queuedIncoherentBarrier = IncoherentBarrierType.None;
_queuedFeedbackLoopBarrier = false;
} }
else if (_feedbackLoopActive && _queuedFeedbackLoopBarrier)
{
// Feedback loop barrier.
MemoryBarrier barrier = new()
{
SType = StructureType.MemoryBarrier,
SrcAccessMask = AccessFlags.ShaderWriteBit,
DstAccessMask = AccessFlags.ShaderReadBit
};
QueueBarrier(barrier, PipelineStageFlags.FragmentShaderBit, PipelineStageFlags.AllGraphicsBit);
_queuedFeedbackLoopBarrier = false;
}
_feedbackLoopActive = false;
} }
} }
public unsafe void Flush(CommandBufferScoped cbs, bool inRenderPass, RenderPassHolder rpHolder, Action endRenderPass) public unsafe void Flush(CommandBufferScoped cbs, bool inRenderPass, RenderPassHolder rpHolder, Action endRenderPass)
{ {
Flush(cbs, null, false, inRenderPass, rpHolder, endRenderPass); Flush(cbs, null, inRenderPass, rpHolder, endRenderPass);
} }
public unsafe void Flush(CommandBufferScoped cbs, ShaderCollection program, bool feedbackLoopActive, bool inRenderPass, RenderPassHolder rpHolder, Action endRenderPass) public unsafe void Flush(CommandBufferScoped cbs, ShaderCollection program, bool inRenderPass, RenderPassHolder rpHolder, Action endRenderPass)
{ {
if (program != null) if (program != null)
{ {
@@ -204,8 +195,6 @@ namespace Ryujinx.Graphics.Vulkan
_incoherentTextureWriteStages |= program.IncoherentTextureWriteStages; _incoherentTextureWriteStages |= program.IncoherentTextureWriteStages;
} }
_feedbackLoopActive |= feedbackLoopActive;
FlushMemoryBarrier(program, inRenderPass); FlushMemoryBarrier(program, inRenderPass);
if (!inRenderPass && rpHolder != null) if (!inRenderPass && rpHolder != null)
@@ -417,8 +406,6 @@ namespace Ryujinx.Graphics.Vulkan
{ {
_queuedIncoherentBarrier = type; _queuedIncoherentBarrier = type;
} }
_queuedFeedbackLoopBarrier = true;
} }
public void QueueTextureBarrier() public void QueueTextureBarrier()

View File

@@ -3,7 +3,6 @@ using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Shader; using Ryujinx.Graphics.Shader;
using Silk.NET.Vulkan; using Silk.NET.Vulkan;
using System; using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Buffer = Silk.NET.Vulkan.Buffer; using Buffer = Silk.NET.Vulkan.Buffer;
@@ -43,15 +42,15 @@ namespace Ryujinx.Graphics.Vulkan
private record struct TextureRef private record struct TextureRef
{ {
public ShaderStage Stage; public ShaderStage Stage;
public TextureView View; public TextureStorage Storage;
public Auto<DisposableImageView> ImageView; public Auto<DisposableImageView> View;
public Auto<DisposableSampler> Sampler; public Auto<DisposableSampler> Sampler;
public TextureRef(ShaderStage stage, TextureView view, Auto<DisposableImageView> imageView, Auto<DisposableSampler> sampler) public TextureRef(ShaderStage stage, TextureStorage storage, Auto<DisposableImageView> view, Auto<DisposableSampler> sampler)
{ {
Stage = stage; Stage = stage;
Storage = storage;
View = view; View = view;
ImageView = imageView;
Sampler = sampler; Sampler = sampler;
} }
} }
@@ -59,14 +58,14 @@ namespace Ryujinx.Graphics.Vulkan
private record struct ImageRef private record struct ImageRef
{ {
public ShaderStage Stage; public ShaderStage Stage;
public TextureView View; public TextureStorage Storage;
public Auto<DisposableImageView> ImageView; public Auto<DisposableImageView> View;
public ImageRef(ShaderStage stage, TextureView view, Auto<DisposableImageView> imageView) public ImageRef(ShaderStage stage, TextureStorage storage, Auto<DisposableImageView> view)
{ {
Stage = stage; Stage = stage;
Storage = storage;
View = view; View = view;
ImageView = imageView;
} }
} }
@@ -124,8 +123,6 @@ namespace Ryujinx.Graphics.Vulkan
private readonly TextureView _dummyTexture; private readonly TextureView _dummyTexture;
private readonly SamplerHolder _dummySampler; private readonly SamplerHolder _dummySampler;
public List<TextureView> FeedbackLoopHazards { get; private set; }
public DescriptorSetUpdater(VulkanRenderer gd, Device device) public DescriptorSetUpdater(VulkanRenderer gd, Device device)
{ {
_gd = gd; _gd = gd;
@@ -210,15 +207,10 @@ namespace Ryujinx.Graphics.Vulkan
_templateUpdater = new(); _templateUpdater = new();
} }
public void Initialize(bool isMainPipeline) public void Initialize()
{ {
MemoryOwner<byte> dummyTextureData = MemoryOwner<byte>.RentCleared(4); MemoryOwner<byte> dummyTextureData = MemoryOwner<byte>.RentCleared(4);
_dummyTexture.SetData(dummyTextureData); _dummyTexture.SetData(dummyTextureData);
if (isMainPipeline)
{
FeedbackLoopHazards = [];
}
} }
private static bool BindingOverlaps(ref DescriptorBufferInfo info, int bindingOffset, int offset, int size) private static bool BindingOverlaps(ref DescriptorBufferInfo info, int bindingOffset, int offset, int size)
@@ -281,18 +273,6 @@ namespace Ryujinx.Graphics.Vulkan
public void InsertBindingBarriers(CommandBufferScoped cbs) public void InsertBindingBarriers(CommandBufferScoped cbs)
{ {
if ((FeedbackLoopHazards?.Count ?? 0) > 0)
{
// Clear existing hazards - they will be rebuilt.
foreach (TextureView hazard in FeedbackLoopHazards)
{
hazard.DecrementHazardUses();
}
FeedbackLoopHazards.Clear();
}
foreach (ResourceBindingSegment segment in _program.BindingSegments[PipelineBase.TextureSetIndex]) foreach (ResourceBindingSegment segment in _program.BindingSegments[PipelineBase.TextureSetIndex])
{ {
if (segment.Type == ResourceType.TextureAndSampler) if (segment.Type == ResourceType.TextureAndSampler)
@@ -302,7 +282,7 @@ namespace Ryujinx.Graphics.Vulkan
for (int i = 0; i < segment.Count; i++) for (int i = 0; i < segment.Count; i++)
{ {
ref TextureRef texture = ref _textureRefs[segment.Binding + i]; ref TextureRef texture = ref _textureRefs[segment.Binding + i];
texture.View?.PrepareForUsage(cbs, texture.Stage.ConvertToPipelineStageFlags(), FeedbackLoopHazards); texture.Storage?.QueueWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, texture.Stage.ConvertToPipelineStageFlags());
} }
} }
else else
@@ -323,7 +303,7 @@ namespace Ryujinx.Graphics.Vulkan
for (int i = 0; i < segment.Count; i++) for (int i = 0; i < segment.Count; i++)
{ {
ref ImageRef image = ref _imageRefs[segment.Binding + i]; ref ImageRef image = ref _imageRefs[segment.Binding + i];
image.View?.PrepareForUsage(cbs, image.Stage.ConvertToPipelineStageFlags(), FeedbackLoopHazards); image.Storage?.QueueWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, image.Stage.ConvertToPipelineStageFlags());
} }
} }
else else
@@ -397,12 +377,8 @@ namespace Ryujinx.Graphics.Vulkan
} }
else if (image is TextureView view) else if (image is TextureView view)
{ {
ref ImageRef iRef = ref _imageRefs[binding]; view.Storage.QueueWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, stage.ConvertToPipelineStageFlags());
_imageRefs[binding] = new(stage, view.Storage, view.GetIdentityImageView());
iRef.View?.ClearUsage(FeedbackLoopHazards);
view?.PrepareForUsage(cbs, stage.ConvertToPipelineStageFlags(), FeedbackLoopHazards);
iRef = new(stage, view, view.GetIdentityImageView());
} }
else else
{ {
@@ -500,12 +476,9 @@ namespace Ryujinx.Graphics.Vulkan
} }
else if (texture is TextureView view) else if (texture is TextureView view)
{ {
ref TextureRef iRef = ref _textureRefs[binding]; view.Storage.QueueWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, stage.ConvertToPipelineStageFlags());
iRef.View?.ClearUsage(FeedbackLoopHazards); _textureRefs[binding] = new(stage, view.Storage, view.GetImageView(), ((SamplerHolder)sampler)?.GetSampler());
view?.PrepareForUsage(cbs, stage.ConvertToPipelineStageFlags(), FeedbackLoopHazards);
iRef = new(stage, view, view.GetImageView(), ((SamplerHolder)sampler)?.GetSampler());
} }
else else
{ {
@@ -527,7 +500,7 @@ namespace Ryujinx.Graphics.Vulkan
{ {
view.Storage.QueueWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, stage.ConvertToPipelineStageFlags()); view.Storage.QueueWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, stage.ConvertToPipelineStageFlags());
_textureRefs[binding] = new(stage, view, view.GetIdentityImageView(), ((SamplerHolder)sampler)?.GetSampler()); _textureRefs[binding] = new(stage, view.Storage, view.GetIdentityImageView(), ((SamplerHolder)sampler)?.GetSampler());
SignalDirty(DirtyFlags.Texture); SignalDirty(DirtyFlags.Texture);
} }
@@ -853,7 +826,7 @@ namespace Ryujinx.Graphics.Vulkan
ref DescriptorImageInfo texture = ref textures[i]; ref DescriptorImageInfo texture = ref textures[i];
ref TextureRef refs = ref _textureRefs[binding + i]; ref TextureRef refs = ref _textureRefs[binding + i];
texture.ImageView = refs.ImageView?.Get(cbs).Value ?? default; texture.ImageView = refs.View?.Get(cbs).Value ?? default;
texture.Sampler = refs.Sampler?.Get(cbs).Value ?? default; texture.Sampler = refs.Sampler?.Get(cbs).Value ?? default;
if (texture.ImageView.Handle == 0) if (texture.ImageView.Handle == 0)
@@ -903,7 +876,7 @@ namespace Ryujinx.Graphics.Vulkan
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
images[i].ImageView = _imageRefs[binding + i].ImageView?.Get(cbs).Value ?? default; images[i].ImageView = _imageRefs[binding + i].View?.Get(cbs).Value ?? default;
} }
tu.Push<DescriptorImageInfo>(images[..count]); tu.Push<DescriptorImageInfo>(images[..count]);
@@ -974,7 +947,7 @@ namespace Ryujinx.Graphics.Vulkan
ref DescriptorImageInfo texture = ref textures[i]; ref DescriptorImageInfo texture = ref textures[i];
ref TextureRef refs = ref _textureRefs[binding + i]; ref TextureRef refs = ref _textureRefs[binding + i];
texture.ImageView = refs.ImageView?.Get(cbs).Value ?? default; texture.ImageView = refs.View?.Get(cbs).Value ?? default;
texture.Sampler = refs.Sampler?.Get(cbs).Value ?? default; texture.Sampler = refs.Sampler?.Get(cbs).Value ?? default;
if (texture.ImageView.Handle == 0) if (texture.ImageView.Handle == 0)

View File

@@ -1,12 +0,0 @@
using System;
namespace Ryujinx.Graphics.Vulkan
{
[Flags]
internal enum FeedbackLoopAspects
{
None = 0,
Color = 1 << 0,
Depth = 1 << 1,
}
}

View File

@@ -303,27 +303,6 @@ namespace Ryujinx.Graphics.Vulkan
_depthStencil?.Storage?.AddStoreOpUsage(true); _depthStencil?.Storage?.AddStoreOpUsage(true);
} }
public void ClearBindings()
{
_depthStencil?.Storage.ClearBindings();
for (int i = 0; i < _colorsCanonical.Length; i++)
{
_colorsCanonical[i]?.Storage.ClearBindings();
}
}
public void AddBindings()
{
_depthStencil?.Storage.AddBinding(_depthStencil);
for (int i = 0; i < _colorsCanonical.Length; i++)
{
TextureView color = _colorsCanonical[i];
color?.Storage.AddBinding(color);
}
}
public (RenderPassHolder rpHolder, Auto<DisposableFramebuffer> framebuffer) GetPassAndFramebuffer( public (RenderPassHolder rpHolder, Auto<DisposableFramebuffer> framebuffer) GetPassAndFramebuffer(
VulkanRenderer gd, VulkanRenderer gd,
Device device, Device device,

View File

@@ -46,8 +46,6 @@ namespace Ryujinx.Graphics.Vulkan
public readonly bool SupportsViewportArray2; public readonly bool SupportsViewportArray2;
public readonly bool SupportsHostImportedMemory; public readonly bool SupportsHostImportedMemory;
public readonly bool SupportsDepthClipControl; public readonly bool SupportsDepthClipControl;
public readonly bool SupportsAttachmentFeedbackLoop;
public readonly bool SupportsDynamicAttachmentFeedbackLoop;
public readonly uint SubgroupSize; public readonly uint SubgroupSize;
public readonly SampleCountFlags SupportedSampleCounts; public readonly SampleCountFlags SupportedSampleCounts;
public readonly PortabilitySubsetFlags PortabilitySubset; public readonly PortabilitySubsetFlags PortabilitySubset;
@@ -86,8 +84,6 @@ namespace Ryujinx.Graphics.Vulkan
bool supportsViewportArray2, bool supportsViewportArray2,
bool supportsHostImportedMemory, bool supportsHostImportedMemory,
bool supportsDepthClipControl, bool supportsDepthClipControl,
bool supportsAttachmentFeedbackLoop,
bool supportsDynamicAttachmentFeedbackLoop,
uint subgroupSize, uint subgroupSize,
SampleCountFlags supportedSampleCounts, SampleCountFlags supportedSampleCounts,
PortabilitySubsetFlags portabilitySubset, PortabilitySubsetFlags portabilitySubset,
@@ -125,8 +121,6 @@ namespace Ryujinx.Graphics.Vulkan
SupportsViewportArray2 = supportsViewportArray2; SupportsViewportArray2 = supportsViewportArray2;
SupportsHostImportedMemory = supportsHostImportedMemory; SupportsHostImportedMemory = supportsHostImportedMemory;
SupportsDepthClipControl = supportsDepthClipControl; SupportsDepthClipControl = supportsDepthClipControl;
SupportsAttachmentFeedbackLoop = supportsAttachmentFeedbackLoop;
SupportsDynamicAttachmentFeedbackLoop = supportsDynamicAttachmentFeedbackLoop;
SubgroupSize = subgroupSize; SubgroupSize = subgroupSize;
SupportedSampleCounts = supportedSampleCounts; SupportedSampleCounts = supportedSampleCounts;
PortabilitySubset = portabilitySubset; PortabilitySubset = portabilitySubset;

View File

@@ -3,7 +3,6 @@ using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Shader; using Ryujinx.Graphics.Shader;
using Silk.NET.Vulkan; using Silk.NET.Vulkan;
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
@@ -36,7 +35,6 @@ namespace Ryujinx.Graphics.Vulkan
public readonly Action EndRenderPassDelegate; public readonly Action EndRenderPassDelegate;
protected PipelineDynamicState DynamicState; protected PipelineDynamicState DynamicState;
protected bool IsMainPipeline;
private PipelineState _newState; private PipelineState _newState;
private bool _graphicsStateDirty; private bool _graphicsStateDirty;
private bool _computeStateDirty; private bool _computeStateDirty;
@@ -89,9 +87,6 @@ namespace Ryujinx.Graphics.Vulkan
private bool _tfEnabled; private bool _tfEnabled;
private bool _tfActive; private bool _tfActive;
private FeedbackLoopAspects _feedbackLoop;
private bool _passWritesDepthStencil;
private readonly PipelineColorBlendAttachmentState[] _storedBlend; private readonly PipelineColorBlendAttachmentState[] _storedBlend;
public ulong DrawCount { get; private set; } public ulong DrawCount { get; private set; }
public bool RenderPassActive { get; private set; } public bool RenderPassActive { get; private set; }
@@ -133,7 +128,7 @@ namespace Ryujinx.Graphics.Vulkan
public void Initialize() public void Initialize()
{ {
_descriptorSetUpdater.Initialize(IsMainPipeline); _descriptorSetUpdater.Initialize();
QuadsToTrisPattern = new IndexBufferPattern(Gd, 4, 6, 0, [0, 1, 2, 0, 2, 3], 4, false); QuadsToTrisPattern = new IndexBufferPattern(Gd, 4, 6, 0, [0, 1, 2, 0, 2, 3], 4, false);
TriFanToTrisPattern = new IndexBufferPattern(Gd, 3, 3, 2, [int.MinValue, -1, 0], 1, true); TriFanToTrisPattern = new IndexBufferPattern(Gd, 3, 3, 2, [int.MinValue, -1, 0], 1, true);
@@ -821,8 +816,6 @@ namespace Ryujinx.Graphics.Vulkan
_newState.DepthTestEnable = depthTest.TestEnable; _newState.DepthTestEnable = depthTest.TestEnable;
_newState.DepthWriteEnable = depthTest.WriteEnable; _newState.DepthWriteEnable = depthTest.WriteEnable;
_newState.DepthCompareOp = depthTest.Func.Convert(); _newState.DepthCompareOp = depthTest.Func.Convert();
UpdatePassDepthStencil();
SignalStateChange(); SignalStateChange();
} }
@@ -1088,8 +1081,6 @@ namespace Ryujinx.Graphics.Vulkan
_newState.StencilFrontPassOp = stencilTest.FrontDpPass.Convert(); _newState.StencilFrontPassOp = stencilTest.FrontDpPass.Convert();
_newState.StencilFrontDepthFailOp = stencilTest.FrontDpFail.Convert(); _newState.StencilFrontDepthFailOp = stencilTest.FrontDpFail.Convert();
_newState.StencilFrontCompareOp = stencilTest.FrontFunc.Convert(); _newState.StencilFrontCompareOp = stencilTest.FrontFunc.Convert();
UpdatePassDepthStencil();
SignalStateChange(); SignalStateChange();
} }
@@ -1437,23 +1428,7 @@ namespace Ryujinx.Graphics.Vulkan
} }
} }
if (IsMainPipeline)
{
FramebufferParams?.ClearBindings();
}
FramebufferParams = new FramebufferParams(Device, colors, depthStencil); FramebufferParams = new FramebufferParams(Device, colors, depthStencil);
if (IsMainPipeline)
{
FramebufferParams.AddBindings();
_newState.FeedbackLoopAspects = FeedbackLoopAspects.None;
_bindingBarriersDirty = true;
}
_passWritesDepthStencil = false;
UpdatePassDepthStencil();
UpdatePipelineAttachmentFormats(); UpdatePipelineAttachmentFormats();
} }
@@ -1520,82 +1495,11 @@ namespace Ryujinx.Graphics.Vulkan
} }
} }
Gd.Barriers.Flush(Cbs, _program, _feedbackLoop != 0, RenderPassActive, _rpHolder, EndRenderPassDelegate); Gd.Barriers.Flush(Cbs, _program, RenderPassActive, _rpHolder, EndRenderPassDelegate);
_descriptorSetUpdater.UpdateAndBindDescriptorSets(Cbs, PipelineBindPoint.Compute); _descriptorSetUpdater.UpdateAndBindDescriptorSets(Cbs, PipelineBindPoint.Compute);
} }
private bool ChangeFeedbackLoop(FeedbackLoopAspects aspects)
{
if (_feedbackLoop != aspects)
{
if (Gd.Capabilities.SupportsDynamicAttachmentFeedbackLoop)
{
DynamicState.SetFeedbackLoop(aspects);
}
else
{
_newState.FeedbackLoopAspects = aspects;
}
_feedbackLoop = aspects;
return true;
}
return false;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private bool UpdateFeedbackLoop()
{
List<TextureView> hazards = _descriptorSetUpdater.FeedbackLoopHazards;
if ((hazards?.Count ?? 0) > 0)
{
FeedbackLoopAspects aspects = 0;
foreach (TextureView view in hazards)
{
// May need to enforce feedback loop layout here in the future.
// Though technically, it should always work with the general layout.
if (view.Info.Format.IsDepthOrStencil())
{
if (_passWritesDepthStencil)
{
// If depth/stencil isn't written in the pass, it doesn't count as a feedback loop.
aspects |= FeedbackLoopAspects.Depth;
}
}
else
{
aspects |= FeedbackLoopAspects.Color;
}
}
return ChangeFeedbackLoop(aspects);
}
else if (_feedbackLoop != 0)
{
return ChangeFeedbackLoop(FeedbackLoopAspects.None);
}
return false;
}
private void UpdatePassDepthStencil()
{
if (!RenderPassActive)
{
_passWritesDepthStencil = false;
}
// Stencil test being enabled doesn't necessarily mean a write, but it's not critical to check.
_passWritesDepthStencil |= (_newState.DepthTestEnable && _newState.DepthWriteEnable) || _newState.StencilTestEnable;
}
private bool RecreateGraphicsPipelineIfNeeded() private bool RecreateGraphicsPipelineIfNeeded()
{ {
if (AutoFlush.ShouldFlushDraw(DrawCount)) if (AutoFlush.ShouldFlushDraw(DrawCount))
@@ -1603,7 +1507,7 @@ namespace Ryujinx.Graphics.Vulkan
Gd.FlushAllCommands(); Gd.FlushAllCommands();
} }
DynamicState.ReplayIfDirty(Gd, CommandBuffer); DynamicState.ReplayIfDirty(Gd.Api, CommandBuffer);
if (_needsIndexBufferRebind && _indexBufferPattern == null) if (_needsIndexBufferRebind && _indexBufferPattern == null)
{ {
@@ -1637,15 +1541,7 @@ namespace Ryujinx.Graphics.Vulkan
_vertexBufferUpdater.Commit(Cbs); _vertexBufferUpdater.Commit(Cbs);
} }
if (_bindingBarriersDirty) if (_graphicsStateDirty || Pbp != PipelineBindPoint.Graphics)
{
// Stale barriers may have been activated by switching program. Emit any that are relevant.
_descriptorSetUpdater.InsertBindingBarriers(Cbs);
_bindingBarriersDirty = false;
}
if (UpdateFeedbackLoop() || _graphicsStateDirty || Pbp != PipelineBindPoint.Graphics)
{ {
if (!CreatePipeline(PipelineBindPoint.Graphics)) if (!CreatePipeline(PipelineBindPoint.Graphics))
{ {
@@ -1654,9 +1550,17 @@ namespace Ryujinx.Graphics.Vulkan
_graphicsStateDirty = false; _graphicsStateDirty = false;
Pbp = PipelineBindPoint.Graphics; Pbp = PipelineBindPoint.Graphics;
if (_bindingBarriersDirty)
{
// Stale barriers may have been activated by switching program. Emit any that are relevant.
_descriptorSetUpdater.InsertBindingBarriers(Cbs);
_bindingBarriersDirty = false;
}
} }
Gd.Barriers.Flush(Cbs, _program, _feedbackLoop != 0, RenderPassActive, _rpHolder, EndRenderPassDelegate); Gd.Barriers.Flush(Cbs, _program, RenderPassActive, _rpHolder, EndRenderPassDelegate);
_descriptorSetUpdater.UpdateAndBindDescriptorSets(Cbs, PipelineBindPoint.Graphics); _descriptorSetUpdater.UpdateAndBindDescriptorSets(Cbs, PipelineBindPoint.Graphics);

View File

@@ -1,6 +1,5 @@
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using Silk.NET.Vulkan; using Silk.NET.Vulkan;
using Silk.NET.Vulkan.Extensions.EXT;
namespace Ryujinx.Graphics.Vulkan namespace Ryujinx.Graphics.Vulkan
{ {
@@ -22,8 +21,6 @@ namespace Ryujinx.Graphics.Vulkan
private Array4<float> _blendConstants; private Array4<float> _blendConstants;
private FeedbackLoopAspects _feedbackLoopAspects;
public uint ViewportsCount; public uint ViewportsCount;
public Array16<Viewport> Viewports; public Array16<Viewport> Viewports;
@@ -35,8 +32,7 @@ namespace Ryujinx.Graphics.Vulkan
Scissor = 1 << 2, Scissor = 1 << 2,
Stencil = 1 << 3, Stencil = 1 << 3,
Viewport = 1 << 4, Viewport = 1 << 4,
FeedbackLoop = 1 << 5, All = Blend | DepthBias | Scissor | Stencil | Viewport,
All = Blend | DepthBias | Scissor | Stencil | Viewport | FeedbackLoop,
} }
private DirtyFlags _dirty; private DirtyFlags _dirty;
@@ -103,22 +99,13 @@ namespace Ryujinx.Graphics.Vulkan
} }
} }
public void SetFeedbackLoop(FeedbackLoopAspects aspects)
{
_feedbackLoopAspects = aspects;
_dirty |= DirtyFlags.FeedbackLoop;
}
public void ForceAllDirty() public void ForceAllDirty()
{ {
_dirty = DirtyFlags.All; _dirty = DirtyFlags.All;
} }
public void ReplayIfDirty(VulkanRenderer gd, CommandBuffer commandBuffer) public void ReplayIfDirty(Vk api, CommandBuffer commandBuffer)
{ {
Vk api = gd.Api;
if (_dirty.HasFlag(DirtyFlags.Blend)) if (_dirty.HasFlag(DirtyFlags.Blend))
{ {
RecordBlend(api, commandBuffer); RecordBlend(api, commandBuffer);
@@ -144,11 +131,6 @@ namespace Ryujinx.Graphics.Vulkan
RecordViewport(api, commandBuffer); RecordViewport(api, commandBuffer);
} }
if (_dirty.HasFlag(DirtyFlags.FeedbackLoop) && gd.Capabilities.SupportsDynamicAttachmentFeedbackLoop)
{
RecordFeedbackLoop(gd.DynamicFeedbackLoopApi, commandBuffer);
}
_dirty = DirtyFlags.None; _dirty = DirtyFlags.None;
} }
@@ -187,17 +169,5 @@ namespace Ryujinx.Graphics.Vulkan
api.CmdSetViewport(commandBuffer, 0, ViewportsCount, Viewports.AsSpan()); api.CmdSetViewport(commandBuffer, 0, ViewportsCount, Viewports.AsSpan());
} }
} }
private readonly void RecordFeedbackLoop(ExtAttachmentFeedbackLoopDynamicState api, CommandBuffer commandBuffer)
{
ImageAspectFlags aspects = (_feedbackLoopAspects & FeedbackLoopAspects.Color) != 0 ? ImageAspectFlags.ColorBit : 0;
if ((_feedbackLoopAspects & FeedbackLoopAspects.Depth) != 0)
{
aspects |= ImageAspectFlags.DepthBit | ImageAspectFlags.StencilBit;
}
api.CmdSetAttachmentFeedbackLoopEnable(commandBuffer, aspects);
}
} }
} }

View File

@@ -28,8 +28,6 @@ namespace Ryujinx.Graphics.Vulkan
_activeBufferMirrors = []; _activeBufferMirrors = [];
CommandBuffer = (Cbs = gd.CommandBufferPool.Rent()).CommandBuffer; CommandBuffer = (Cbs = gd.CommandBufferPool.Rent()).CommandBuffer;
IsMainPipeline = true;
} }
private void CopyPendingQuery() private void CopyPendingQuery()
@@ -237,7 +235,7 @@ namespace Ryujinx.Graphics.Vulkan
if (Pipeline != null && Pbp == PipelineBindPoint.Graphics) if (Pipeline != null && Pbp == PipelineBindPoint.Graphics)
{ {
DynamicState.ReplayIfDirty(Gd, CommandBuffer); DynamicState.ReplayIfDirty(Gd.Api, CommandBuffer);
} }
} }

View File

@@ -8,7 +8,6 @@ namespace Ryujinx.Graphics.Vulkan
struct PipelineState : IDisposable struct PipelineState : IDisposable
{ {
private const int RequiredSubgroupSize = 32; private const int RequiredSubgroupSize = 32;
private const int MaxDynamicStatesCount = 9;
public PipelineUid Internal; public PipelineUid Internal;
@@ -300,12 +299,6 @@ namespace Ryujinx.Graphics.Vulkan
set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFFBF) | ((value ? 1UL : 0UL) << 6); set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFFBF) | ((value ? 1UL : 0UL) << 6);
} }
public FeedbackLoopAspects FeedbackLoopAspects
{
readonly get => (FeedbackLoopAspects)((Internal.Id8 >> 7) & 0x3);
set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFE7F) | (((ulong)value) << 7);
}
public bool HasTessellationControlShader; public bool HasTessellationControlShader;
public NativeArray<PipelineShaderStageCreateInfo> Stages; public NativeArray<PipelineShaderStageCreateInfo> Stages;
public PipelineLayout PipelineLayout; public PipelineLayout PipelineLayout;
@@ -571,11 +564,9 @@ namespace Ryujinx.Graphics.Vulkan
} }
bool supportsExtDynamicState = gd.Capabilities.SupportsExtendedDynamicState; bool supportsExtDynamicState = gd.Capabilities.SupportsExtendedDynamicState;
bool supportsFeedbackLoopDynamicState = gd.Capabilities.SupportsDynamicAttachmentFeedbackLoop; int dynamicStatesCount = supportsExtDynamicState ? 8 : 7;
DynamicState* dynamicStates = stackalloc DynamicState[MaxDynamicStatesCount]; DynamicState* dynamicStates = stackalloc DynamicState[dynamicStatesCount];
int dynamicStatesCount = 7;
dynamicStates[0] = DynamicState.Viewport; dynamicStates[0] = DynamicState.Viewport;
dynamicStates[1] = DynamicState.Scissor; dynamicStates[1] = DynamicState.Scissor;
@@ -587,12 +578,7 @@ namespace Ryujinx.Graphics.Vulkan
if (supportsExtDynamicState) if (supportsExtDynamicState)
{ {
dynamicStates[dynamicStatesCount++] = DynamicState.VertexInputBindingStrideExt; dynamicStates[7] = DynamicState.VertexInputBindingStrideExt;
}
if (supportsFeedbackLoopDynamicState)
{
dynamicStates[dynamicStatesCount++] = DynamicState.AttachmentFeedbackLoopEnableExt;
} }
PipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo = new() PipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo = new()
@@ -602,27 +588,9 @@ namespace Ryujinx.Graphics.Vulkan
PDynamicStates = dynamicStates, PDynamicStates = dynamicStates,
}; };
PipelineCreateFlags flags = 0;
if (gd.Capabilities.SupportsAttachmentFeedbackLoop)
{
FeedbackLoopAspects aspects = FeedbackLoopAspects;
if ((aspects & FeedbackLoopAspects.Color) != 0)
{
flags |= PipelineCreateFlags.CreateColorAttachmentFeedbackLoopBitExt;
}
if ((aspects & FeedbackLoopAspects.Depth) != 0)
{
flags |= PipelineCreateFlags.CreateDepthStencilAttachmentFeedbackLoopBitExt;
}
}
GraphicsPipelineCreateInfo pipelineCreateInfo = new() GraphicsPipelineCreateInfo pipelineCreateInfo = new()
{ {
SType = StructureType.GraphicsPipelineCreateInfo, SType = StructureType.GraphicsPipelineCreateInfo,
Flags = flags,
StageCount = StagesCount, StageCount = StagesCount,
PStages = Stages.Pointer, PStages = Stages.Pointer,
PVertexInputState = &vertexInputState, PVertexInputState = &vertexInputState,

View File

@@ -4,7 +4,6 @@ using Silk.NET.Vulkan;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices;
using Format = Ryujinx.Graphics.GAL.Format; using Format = Ryujinx.Graphics.GAL.Format;
using VkBuffer = Silk.NET.Vulkan.Buffer; using VkBuffer = Silk.NET.Vulkan.Buffer;
using VkFormat = Silk.NET.Vulkan.Format; using VkFormat = Silk.NET.Vulkan.Format;
@@ -13,11 +12,6 @@ namespace Ryujinx.Graphics.Vulkan
{ {
class TextureStorage : IDisposable class TextureStorage : IDisposable
{ {
private struct TextureSliceInfo
{
public int BindCount;
}
private const MemoryPropertyFlags DefaultImageMemoryFlags = private const MemoryPropertyFlags DefaultImageMemoryFlags =
MemoryPropertyFlags.DeviceLocalBit; MemoryPropertyFlags.DeviceLocalBit;
@@ -49,7 +43,6 @@ namespace Ryujinx.Graphics.Vulkan
private readonly Image _image; private readonly Image _image;
private readonly Auto<DisposableImage> _imageAuto; private readonly Auto<DisposableImage> _imageAuto;
private readonly Auto<MemoryAllocation> _allocationAuto; private readonly Auto<MemoryAllocation> _allocationAuto;
private readonly int _depthOrLayers;
private Auto<MemoryAllocation> _foreignAllocationAuto; private Auto<MemoryAllocation> _foreignAllocationAuto;
private Dictionary<Format, TextureStorage> _aliasedStorages; private Dictionary<Format, TextureStorage> _aliasedStorages;
@@ -62,9 +55,6 @@ namespace Ryujinx.Graphics.Vulkan
private int _viewsCount; private int _viewsCount;
private readonly ulong _size; private readonly ulong _size;
private int _bindCount;
private readonly TextureSliceInfo[] _slices;
public VkFormat VkFormat { get; } public VkFormat VkFormat { get; }
public unsafe TextureStorage( public unsafe TextureStorage(
@@ -85,7 +75,6 @@ namespace Ryujinx.Graphics.Vulkan
uint depth = (uint)(info.Target == Target.Texture3D ? info.Depth : 1); uint depth = (uint)(info.Target == Target.Texture3D ? info.Depth : 1);
VkFormat = format; VkFormat = format;
_depthOrLayers = info.GetDepthOrLayers();
ImageType type = info.Target.Convert(); ImageType type = info.Target.Convert();
@@ -161,8 +150,6 @@ namespace Ryujinx.Graphics.Vulkan
InitialTransition(ImageLayout.Preinitialized, ImageLayout.General); InitialTransition(ImageLayout.Preinitialized, ImageLayout.General);
} }
_slices = new TextureSliceInfo[levels * _depthOrLayers];
} }
public TextureStorage CreateAliasedColorForDepthStorageUnsafe(Format format) public TextureStorage CreateAliasedColorForDepthStorageUnsafe(Format format)
@@ -325,12 +312,6 @@ namespace Ryujinx.Graphics.Vulkan
usage |= ImageUsageFlags.StorageBit; usage |= ImageUsageFlags.StorageBit;
} }
if (capabilities.SupportsAttachmentFeedbackLoop &&
(usage & (ImageUsageFlags.DepthStencilAttachmentBit | ImageUsageFlags.ColorAttachmentBit)) != 0)
{
usage |= ImageUsageFlags.AttachmentFeedbackLoopBitExt;
}
return usage; return usage;
} }
@@ -531,55 +512,6 @@ namespace Ryujinx.Graphics.Vulkan
} }
} }
public void AddBinding(TextureView view)
{
// Assumes a view only has a first level.
int index = view.FirstLevel * _depthOrLayers + view.FirstLayer;
int layers = view.Layers;
for (int i = 0; i < layers; i++)
{
ref TextureSliceInfo info = ref _slices[index++];
info.BindCount++;
}
_bindCount++;
}
public void ClearBindings()
{
if (_bindCount != 0)
{
Array.Clear(_slices, 0, _slices.Length);
_bindCount = 0;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsBound(TextureView view)
{
if (_bindCount != 0)
{
int index = view.FirstLevel * _depthOrLayers + view.FirstLayer;
int layers = view.Layers;
for (int i = 0; i < layers; i++)
{
ref TextureSliceInfo info = ref _slices[index++];
if (info.BindCount != 0)
{
return true;
}
}
}
return false;
}
public void IncrementViewsCount() public void IncrementViewsCount()
{ {
_viewsCount++; _viewsCount++;

View File

@@ -23,8 +23,6 @@ namespace Ryujinx.Graphics.Vulkan
private readonly Auto<DisposableImageView> _imageView2dArray; private readonly Auto<DisposableImageView> _imageView2dArray;
private Dictionary<Format, TextureView> _selfManagedViews; private Dictionary<Format, TextureView> _selfManagedViews;
private int _hazardUses;
private readonly TextureCreateInfo _info; private readonly TextureCreateInfo _info;
private HashTableSlim<RenderPassCacheKey, RenderPassHolder> _renderPasses; private HashTableSlim<RenderPassCacheKey, RenderPassHolder> _renderPasses;
@@ -1039,34 +1037,6 @@ namespace Ryujinx.Graphics.Vulkan
throw new NotImplementedException(); throw new NotImplementedException();
} }
public void PrepareForUsage(CommandBufferScoped cbs, PipelineStageFlags flags, List<TextureView> feedbackLoopHazards)
{
Storage.QueueWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, flags);
if (feedbackLoopHazards != null && Storage.IsBound(this))
{
feedbackLoopHazards.Add(this);
_hazardUses++;
}
}
public void ClearUsage(List<TextureView> feedbackLoopHazards)
{
if (_hazardUses != 0 && feedbackLoopHazards != null)
{
feedbackLoopHazards.Remove(this);
_hazardUses--;
}
}
public void DecrementHazardUses()
{
if (_hazardUses != 0)
{
_hazardUses--;
}
}
public (RenderPassHolder rpHolder, Auto<DisposableFramebuffer> framebuffer) GetPassAndFramebuffer( public (RenderPassHolder rpHolder, Auto<DisposableFramebuffer> framebuffer) GetPassAndFramebuffer(
VulkanRenderer gd, VulkanRenderer gd,
Device device, Device device,

View File

@@ -21,7 +21,7 @@ namespace Ryujinx.Graphics.Vulkan
private const string AppName = "Ryujinx.Graphics.Vulkan"; private const string AppName = "Ryujinx.Graphics.Vulkan";
private const int QueuesCount = 2; private const int QueuesCount = 2;
private static readonly string[] _desirableExtensions = private static readonly string[] _desirableExtensions =
[ [
ExtConditionalRendering.ExtensionName, ExtConditionalRendering.ExtensionName,
ExtExtendedDynamicState.ExtensionName, ExtExtendedDynamicState.ExtensionName,
@@ -46,8 +46,6 @@ namespace Ryujinx.Graphics.Vulkan
"VK_EXT_4444_formats", "VK_EXT_4444_formats",
"VK_KHR_8bit_storage", "VK_KHR_8bit_storage",
"VK_KHR_maintenance2", "VK_KHR_maintenance2",
"VK_EXT_attachment_feedback_loop_layout",
"VK_EXT_attachment_feedback_loop_dynamic_state"
]; ];
private static readonly string[] _requiredExtensions = private static readonly string[] _requiredExtensions =
@@ -362,28 +360,6 @@ namespace Ryujinx.Graphics.Vulkan
features2.PNext = &supportedFeaturesDepthClipControl; features2.PNext = &supportedFeaturesDepthClipControl;
} }
PhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT supportedFeaturesAttachmentFeedbackLoopLayout = new()
{
SType = StructureType.PhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesExt,
PNext = features2.PNext,
};
if (physicalDevice.IsDeviceExtensionPresent("VK_EXT_attachment_feedback_loop_layout"))
{
features2.PNext = &supportedFeaturesAttachmentFeedbackLoopLayout;
}
PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT supportedFeaturesDynamicAttachmentFeedbackLoopLayout = new()
{
SType = StructureType.PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesExt,
PNext = features2.PNext,
};
if (physicalDevice.IsDeviceExtensionPresent("VK_EXT_attachment_feedback_loop_dynamic_state"))
{
features2.PNext = &supportedFeaturesDynamicAttachmentFeedbackLoopLayout;
}
PhysicalDeviceVulkan12Features supportedPhysicalDeviceVulkan12Features = new() PhysicalDeviceVulkan12Features supportedPhysicalDeviceVulkan12Features = new()
{ {
SType = StructureType.PhysicalDeviceVulkan12Features, SType = StructureType.PhysicalDeviceVulkan12Features,
@@ -558,36 +534,6 @@ namespace Ryujinx.Graphics.Vulkan
pExtendedFeatures = &featuresDepthClipControl; pExtendedFeatures = &featuresDepthClipControl;
} }
PhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT featuresAttachmentFeedbackLoopLayout;
if (physicalDevice.IsDeviceExtensionPresent("VK_EXT_attachment_feedback_loop_layout") &&
supportedFeaturesAttachmentFeedbackLoopLayout.AttachmentFeedbackLoopLayout)
{
featuresAttachmentFeedbackLoopLayout = new()
{
SType = StructureType.PhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesExt,
PNext = pExtendedFeatures,
AttachmentFeedbackLoopLayout = true,
};
pExtendedFeatures = &featuresAttachmentFeedbackLoopLayout;
}
PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT featuresDynamicAttachmentFeedbackLoopLayout;
if (physicalDevice.IsDeviceExtensionPresent("VK_EXT_attachment_feedback_loop_dynamic_state") &&
supportedFeaturesDynamicAttachmentFeedbackLoopLayout.AttachmentFeedbackLoopDynamicState)
{
featuresDynamicAttachmentFeedbackLoopLayout = new()
{
SType = StructureType.PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesExt,
PNext = pExtendedFeatures,
AttachmentFeedbackLoopDynamicState = true,
};
pExtendedFeatures = &featuresDynamicAttachmentFeedbackLoopLayout;
}
string[] enabledExtensions = _requiredExtensions.Union(_desirableExtensions.Intersect(physicalDevice.DeviceExtensions)).ToArray(); string[] enabledExtensions = _requiredExtensions.Union(_desirableExtensions.Intersect(physicalDevice.DeviceExtensions)).ToArray();
nint* ppEnabledExtensions = stackalloc nint[enabledExtensions.Length]; nint* ppEnabledExtensions = stackalloc nint[enabledExtensions.Length];

View File

@@ -44,7 +44,6 @@ namespace Ryujinx.Graphics.Vulkan
internal KhrPushDescriptor PushDescriptorApi { get; private set; } internal KhrPushDescriptor PushDescriptorApi { get; private set; }
internal ExtTransformFeedback TransformFeedbackApi { get; private set; } internal ExtTransformFeedback TransformFeedbackApi { get; private set; }
internal KhrDrawIndirectCount DrawIndirectCountApi { get; private set; } internal KhrDrawIndirectCount DrawIndirectCountApi { get; private set; }
internal ExtAttachmentFeedbackLoopDynamicState DynamicFeedbackLoopApi { get; private set; }
internal uint QueueFamilyIndex { get; private set; } internal uint QueueFamilyIndex { get; private set; }
internal Queue Queue { get; private set; } internal Queue Queue { get; private set; }
@@ -158,11 +157,6 @@ namespace Ryujinx.Graphics.Vulkan
DrawIndirectCountApi = drawIndirectCountApi; DrawIndirectCountApi = drawIndirectCountApi;
} }
if (Api.TryGetDeviceExtension(_instance.Instance, _device, out ExtAttachmentFeedbackLoopDynamicState dynamicFeedbackLoopApi))
{
DynamicFeedbackLoopApi = dynamicFeedbackLoopApi;
}
if (maxQueueCount >= 2) if (maxQueueCount >= 2)
{ {
Api.GetDeviceQueue(_device, queueFamilyIndex, 1, out Queue backgroundQueue); Api.GetDeviceQueue(_device, queueFamilyIndex, 1, out Queue backgroundQueue);
@@ -257,16 +251,6 @@ namespace Ryujinx.Graphics.Vulkan
SType = StructureType.PhysicalDeviceDepthClipControlFeaturesExt, SType = StructureType.PhysicalDeviceDepthClipControlFeaturesExt,
}; };
PhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT featuresAttachmentFeedbackLoop = new()
{
SType = StructureType.PhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesExt,
};
PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT featuresDynamicAttachmentFeedbackLoop = new()
{
SType = StructureType.PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesExt,
};
PhysicalDevicePortabilitySubsetFeaturesKHR featuresPortabilitySubset = new() PhysicalDevicePortabilitySubsetFeaturesKHR featuresPortabilitySubset = new()
{ {
SType = StructureType.PhysicalDevicePortabilitySubsetFeaturesKhr, SType = StructureType.PhysicalDevicePortabilitySubsetFeaturesKhr,
@@ -303,22 +287,6 @@ namespace Ryujinx.Graphics.Vulkan
features2.PNext = &featuresDepthClipControl; features2.PNext = &featuresDepthClipControl;
} }
bool supportsAttachmentFeedbackLoop = _physicalDevice.IsDeviceExtensionPresent("VK_EXT_attachment_feedback_loop_layout");
if (supportsAttachmentFeedbackLoop)
{
featuresAttachmentFeedbackLoop.PNext = features2.PNext;
features2.PNext = &featuresAttachmentFeedbackLoop;
}
bool supportsDynamicAttachmentFeedbackLoop = _physicalDevice.IsDeviceExtensionPresent("VK_EXT_attachment_feedback_loop_dynamic_state");
if (supportsDynamicAttachmentFeedbackLoop)
{
featuresDynamicAttachmentFeedbackLoop.PNext = features2.PNext;
features2.PNext = &featuresDynamicAttachmentFeedbackLoop;
}
bool usePortability = _physicalDevice.IsDeviceExtensionPresent("VK_KHR_portability_subset"); bool usePortability = _physicalDevice.IsDeviceExtensionPresent("VK_KHR_portability_subset");
if (usePortability) if (usePortability)
@@ -441,8 +409,6 @@ namespace Ryujinx.Graphics.Vulkan
_physicalDevice.IsDeviceExtensionPresent("VK_NV_viewport_array2"), _physicalDevice.IsDeviceExtensionPresent("VK_NV_viewport_array2"),
_physicalDevice.IsDeviceExtensionPresent(ExtExternalMemoryHost.ExtensionName), _physicalDevice.IsDeviceExtensionPresent(ExtExternalMemoryHost.ExtensionName),
supportsDepthClipControl && featuresDepthClipControl.DepthClipControl, supportsDepthClipControl && featuresDepthClipControl.DepthClipControl,
supportsAttachmentFeedbackLoop && featuresAttachmentFeedbackLoop.AttachmentFeedbackLoopLayout,
supportsDynamicAttachmentFeedbackLoop && featuresDynamicAttachmentFeedbackLoop.AttachmentFeedbackLoopDynamicState,
propertiesSubgroup.SubgroupSize, propertiesSubgroup.SubgroupSize,
supportedSampleCounts, supportedSampleCounts,
portabilityFlags, portabilityFlags,

View File

@@ -127,7 +127,10 @@ namespace Ryujinx.HLE.HOS.Services
} }
else else
{ {
string serviceName = (service is not DummyService dummyService) ? service.GetType().FullName : dummyService.ServiceName; string serviceName;
serviceName = (service is not DummyService dummyService) ? service.GetType().FullName : dummyService.ServiceName;
Logger.Warning?.Print(LogClass.KernelIpc, $"Missing service {serviceName}: {commandId} ignored"); Logger.Warning?.Print(LogClass.KernelIpc, $"Missing service {serviceName}: {commandId} ignored");
} }

View File

@@ -2,7 +2,6 @@ using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Common.PreciseSleep; using Ryujinx.Common.PreciseSleep;
using Ryujinx.Cpu;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Gpu; using Ryujinx.Graphics.Gpu;
using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap;
@@ -90,7 +89,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
} }
else else
{ {
_ticksPerFrame = ((Stopwatch.Frequency / _device.TargetVSyncInterval) * 100) / _device.TickScalar; _ticksPerFrame = Stopwatch.Frequency / _device.TargetVSyncInterval;
_targetVSyncInterval = _device.TargetVSyncInterval; _targetVSyncInterval = _device.TargetVSyncInterval;
} }
} }

View File

@@ -102,11 +102,6 @@ namespace Ryujinx.HLE
/// Control if the Profiled Translation Cache (PTC) should be used. /// Control if the Profiled Translation Cache (PTC) should be used.
/// </summary> /// </summary>
internal readonly bool EnablePtc; internal readonly bool EnablePtc;
/// <summary>
/// Control the arbitrary scalar applied to emulated CPU tick timing.
/// </summary>
public long TickScalar { get; set; }
/// <summary> /// <summary>
/// Control if the guest application should be told that there is a Internet connection available. /// Control if the guest application should be told that there is a Internet connection available.
@@ -206,7 +201,6 @@ namespace Ryujinx.HLE
VSyncMode vSyncMode, VSyncMode vSyncMode,
bool enableDockedMode, bool enableDockedMode,
bool enablePtc, bool enablePtc,
long tickScalar,
bool enableInternetAccess, bool enableInternetAccess,
IntegrityCheckLevel fsIntegrityCheckLevel, IntegrityCheckLevel fsIntegrityCheckLevel,
int fsGlobalAccessLogMode, int fsGlobalAccessLogMode,
@@ -232,7 +226,6 @@ namespace Ryujinx.HLE
CustomVSyncInterval = customVSyncInterval; CustomVSyncInterval = customVSyncInterval;
EnableDockedMode = enableDockedMode; EnableDockedMode = enableDockedMode;
EnablePtc = enablePtc; EnablePtc = enablePtc;
TickScalar = tickScalar;
EnableInternetAccess = enableInternetAccess; EnableInternetAccess = enableInternetAccess;
FsIntegrityCheckLevel = fsIntegrityCheckLevel; FsIntegrityCheckLevel = fsIntegrityCheckLevel;
FsGlobalAccessLogMode = fsGlobalAccessLogMode; FsGlobalAccessLogMode = fsGlobalAccessLogMode;

View File

@@ -6,8 +6,6 @@ namespace Ryujinx.HLE
{ {
public class PerformanceStatistics public class PerformanceStatistics
{ {
private readonly Switch _device;
private const int FrameTypeGame = 0; private const int FrameTypeGame = 0;
private const int PercentTypeFifo = 0; private const int PercentTypeFifo = 0;
@@ -30,10 +28,8 @@ namespace Ryujinx.HLE
private readonly System.Timers.Timer _resetTimer; private readonly System.Timers.Timer _resetTimer;
public PerformanceStatistics(Switch device) public PerformanceStatistics()
{ {
_device = device;
_frameRate = new double[1]; _frameRate = new double[1];
_accumulatedFrameTime = new double[1]; _accumulatedFrameTime = new double[1];
_previousFrameTime = new double[1]; _previousFrameTime = new double[1];
@@ -166,6 +162,14 @@ namespace Ryujinx.HLE
return 1000 / _frameRate[FrameTypeGame]; return 1000 / _frameRate[FrameTypeGame];
} }
public string FormatGameFrameRate()
{
double frameRate = GetGameFrameRate();
double frameTime = GetGameFrameTime();
return $"{frameRate:00.00} FPS ({frameTime:00.00}ms)";
}
public string FormatFifoPercent() public string FormatFifoPercent()
{ {
double fifoPercent = GetFifoPercent(); double fifoPercent = GetFifoPercent();

View File

@@ -4,7 +4,6 @@ using Ryujinx.Audio.Backends.CompatLayer;
using Ryujinx.Audio.Integration; using Ryujinx.Audio.Integration;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Cpu;
using Ryujinx.Graphics.Gpu; using Ryujinx.Graphics.Gpu;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS; using Ryujinx.HLE.HOS;
@@ -27,26 +26,18 @@ namespace Ryujinx.HLE
public GpuContext Gpu { get; } public GpuContext Gpu { get; }
public VirtualFileSystem FileSystem { get; } public VirtualFileSystem FileSystem { get; }
public HOS.Horizon System { get; } public HOS.Horizon System { get; }
public bool TurboMode = false;
public long TickScalar
{
get => System?.TickSource?.TickScalar ?? ITickSource.RealityTickScalar;
set => System.TickSource.TickScalar = value;
}
public ProcessLoader Processes { get; } public ProcessLoader Processes { get; }
public PerformanceStatistics Statistics { get; } public PerformanceStatistics Statistics { get; }
public Hid Hid { get; } public Hid Hid { get; }
public TamperMachine TamperMachine { get; } public TamperMachine TamperMachine { get; }
public IHostUIHandler UIHandler { get; } public IHostUIHandler UIHandler { get; }
public int CpuCoresCount = 4; // Switch has a quad-core Tegra X1 SoC public int CpuCoresCount = 4; //Switch 1 has 4 cores
public VSyncMode VSyncMode { get; set; } public VSyncMode VSyncMode { get; set; }
public bool CustomVSyncIntervalEnabled { get; set; } public bool CustomVSyncIntervalEnabled { get; set; }
public int CustomVSyncInterval { get; set; } public int CustomVSyncInterval { get; set; }
public long TargetVSyncInterval { get; set; } = 60; public long TargetVSyncInterval { get; set; } = 60;
public bool IsFrameAvailable => Gpu.Window.IsFrameAvailable; public bool IsFrameAvailable => Gpu.Window.IsFrameAvailable;
@@ -73,7 +64,7 @@ namespace Ryujinx.HLE
Memory = new MemoryBlock(Configuration.MemoryConfiguration.ToDramSize(), memoryAllocationFlags); Memory = new MemoryBlock(Configuration.MemoryConfiguration.ToDramSize(), memoryAllocationFlags);
Gpu = new GpuContext(Configuration.GpuRenderer, DirtyHacks); Gpu = new GpuContext(Configuration.GpuRenderer, DirtyHacks);
System = new HOS.Horizon(this); System = new HOS.Horizon(this);
Statistics = new PerformanceStatistics(this); Statistics = new PerformanceStatistics();
Hid = new Hid(this, System.HidStorage); Hid = new Hid(this, System.HidStorage);
Processes = new ProcessLoader(this); Processes = new ProcessLoader(this);
TamperMachine = new TamperMachine(); TamperMachine = new TamperMachine();
@@ -84,7 +75,6 @@ namespace Ryujinx.HLE
VSyncMode = Configuration.VSyncMode; VSyncMode = Configuration.VSyncMode;
CustomVSyncInterval = Configuration.CustomVSyncInterval; CustomVSyncInterval = Configuration.CustomVSyncInterval;
TickScalar = TurboMode ? Configuration.TickScalar : ITickSource.RealityTickScalar;
System.State.DockedMode = Configuration.EnableDockedMode; System.State.DockedMode = Configuration.EnableDockedMode;
System.PerformanceState.PerformanceMode = System.State.DockedMode ? PerformanceMode.Boost : PerformanceMode.Default; System.PerformanceState.PerformanceMode = System.State.DockedMode ? PerformanceMode.Boost : PerformanceMode.Default;
System.EnablePtc = Configuration.EnablePtc; System.EnablePtc = Configuration.EnablePtc;
@@ -136,12 +126,6 @@ namespace Ryujinx.HLE
} }
} }
public void ToggleTurbo()
{
TurboMode = !TurboMode;
TickScalar = TurboMode ? Configuration.TickScalar : ITickSource.RealityTickScalar;
}
public bool LoadCart(string exeFsDir, string romFsFile = null) => Processes.LoadUnpackedNca(exeFsDir, romFsFile); public bool LoadCart(string exeFsDir, string romFsFile = null) => Processes.LoadUnpackedNca(exeFsDir, romFsFile);
public bool LoadXci(string xciFile, ulong applicationId = 0) => Processes.LoadXci(xciFile, applicationId); public bool LoadXci(string xciFile, ulong applicationId = 0) => Processes.LoadXci(xciFile, applicationId);
public bool LoadNca(string ncaFile, BlitStruct<ApplicationControlProperty>? customNacpData = null) => Processes.LoadNca(ncaFile, customNacpData); public bool LoadNca(string ncaFile, BlitStruct<ApplicationControlProperty>? customNacpData = null) => Processes.LoadNca(ncaFile, customNacpData);

File diff suppressed because it is too large Load Diff

View File

@@ -14,6 +14,5 @@ namespace Ryujinx.Ava.Common
VolumeDown, VolumeDown,
CustomVSyncIntervalIncrement, CustomVSyncIntervalIncrement,
CustomVSyncIntervalDecrement, CustomVSyncIntervalDecrement,
TurboMode,
} }
} }

View File

@@ -61,13 +61,6 @@ namespace Ryujinx.Ava.Common.Locale
} }
} }
public static string GetUnformatted(LocaleKeys key) => Instance.Get(key);
public string Get(LocaleKeys key) =>
_localeStrings.TryGetValue(key, out string value)
? value
: key.ToString();
public string this[LocaleKeys key] public string this[LocaleKeys key]
{ {
get get

View File

@@ -11,7 +11,6 @@ using Ryujinx.Common.Configuration.Hid.Controller.Motion;
using Ryujinx.Common.Configuration.Hid.Keyboard; using Ryujinx.Common.Configuration.Hid.Keyboard;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using Ryujinx.Cpu;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.OpenGL; using Ryujinx.Graphics.OpenGL;
using Ryujinx.Graphics.Vulkan; using Ryujinx.Graphics.Vulkan;
@@ -312,7 +311,7 @@ namespace Ryujinx.Headless
return new OpenGLRenderer(); return new OpenGLRenderer();
} }
private static Switch InitializeEmulationContext(WindowBase window, IRenderer renderer, Options options) => private static Switch InitializeEmulationContext(WindowBase window, IRenderer renderer, Options options) =>
new( new(
new HleConfiguration( new HleConfiguration(
@@ -322,7 +321,6 @@ namespace Ryujinx.Headless
options.VSyncMode, options.VSyncMode,
!options.DisableDockedMode, !options.DisableDockedMode,
!options.DisablePTC, !options.DisablePTC,
ITickSource.RealityTickScalar,
options.EnableInternetAccess, options.EnableInternetAccess,
!options.DisableFsIntegrityChecks ? IntegrityCheckLevel.ErrorOnInvalid : IntegrityCheckLevel.None, !options.DisableFsIntegrityChecks ? IntegrityCheckLevel.ErrorOnInvalid : IntegrityCheckLevel.None,
options.FsGlobalAccessLogMode, options.FsGlobalAccessLogMode,

View File

@@ -142,8 +142,8 @@ namespace Ryujinx.Ava
// Logging system information. // Logging system information.
PrintSystemInfo(); PrintSystemInfo();
// Enable OGL multithreading on the driver, and some other flags. // Enable OGL multithreading on the driver, when available.
DriverUtilities.InitDriverConfig(ConfigurationState.Instance.Graphics.BackendThreading == BackendThreading.Off); DriverUtilities.ToggleOGLThreading(ConfigurationState.Instance.Graphics.BackendThreading == BackendThreading.Off);
// Check if keys exists. // Check if keys exists.
if (!File.Exists(Path.Combine(AppDataManager.KeysDirPath, "prod.keys"))) if (!File.Exists(Path.Combine(AppDataManager.KeysDirPath, "prod.keys")))

View File

@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<RuntimeIdentifiers>win-x64;osx-x64;linux-x64;win-arm64;osx-arm64;linux-arm64;</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;osx-x64;linux-x64</RuntimeIdentifiers>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Version>1.0.0-dirty</Version> <Version>1.0.0-dirty</Version>
@@ -29,18 +29,12 @@
<TrimMode>partial</TrimMode> <TrimMode>partial</TrimMode>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(RuntimeIdentifier)' == 'win-arm64'">
<PublishSingleFile>true</PublishSingleFile>
<PublishTrimmed>false</PublishTrimmed>
</PropertyGroup>
<!-- <!--
FluentAvalonia, used in the Avalonia UI, requires a workaround for the json serializer used internally when using .NET 8+ System.Text.Json. FluentAvalonia, used in the Avalonia UI, requires a workaround for the json serializer used internally when using .NET 8+ System.Text.Json.
See: See:
https://github.com/amwx/FluentAvalonia/issues/481 https://github.com/amwx/FluentAvalonia/issues/481
https://devblogs.microsoft.com/dotnet/system-text-json-in-dotnet-8/ https://devblogs.microsoft.com/dotnet/system-text-json-in-dotnet-8/
--> -->
<PropertyGroup> <PropertyGroup>
<JsonSerializerIsReflectionEnabledByDefault>true</JsonSerializerIsReflectionEnabledByDefault> <JsonSerializerIsReflectionEnabledByDefault>true</JsonSerializerIsReflectionEnabledByDefault>
</PropertyGroup> </PropertyGroup>
@@ -63,8 +57,8 @@
<PackageReference Include="Projektanker.Icons.Avalonia.MaterialDesign" /> <PackageReference Include="Projektanker.Icons.Avalonia.MaterialDesign" />
<PackageReference Include="OpenTK.Core" /> <PackageReference Include="OpenTK.Core" />
<PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" /> <PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" />
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies.AllArch" /> <PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" />
<PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'win-x64' AND '$(RuntimeIdentifier)' != 'win-arm64'" /> <PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'win-x64'" />
<PackageReference Include="securifybv.ShellLink" /> <PackageReference Include="securifybv.ShellLink" />
<PackageReference Include="Sep" /> <PackageReference Include="Sep" />
<PackageReference Include="Silk.NET.Vulkan" /> <PackageReference Include="Silk.NET.Vulkan" />
@@ -73,7 +67,7 @@
<PackageReference Include="SPB" /> <PackageReference Include="SPB" />
<PackageReference Include="SharpZipLib" /> <PackageReference Include="SharpZipLib" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Ryujinx.Audio.Backends.SDL2\Ryujinx.Audio.Backends.SDL2.csproj" /> <ProjectReference Include="..\Ryujinx.Audio.Backends.SDL2\Ryujinx.Audio.Backends.SDL2.csproj" />
<ProjectReference Include="..\Ryujinx.Graphics.Vulkan\Ryujinx.Graphics.Vulkan.csproj" /> <ProjectReference Include="..\Ryujinx.Graphics.Vulkan\Ryujinx.Graphics.Vulkan.csproj" />
@@ -90,7 +84,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="..\..\distribution\windows\alsoft.ini" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'"> <Content Include="..\..\distribution\windows\alsoft.ini" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64'">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
<TargetPath>alsoft.ini</TargetPath> <TargetPath>alsoft.ini</TargetPath>
</Content> </Content>

View File

@@ -4,7 +4,6 @@ using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Threading; using Avalonia.Threading;
using DiscordRPC; using DiscordRPC;
using Gommon;
using LibHac.Common; using LibHac.Common;
using LibHac.Ns; using LibHac.Ns;
using Ryujinx.Audio.Backends.Dummy; using Ryujinx.Audio.Backends.Dummy;
@@ -1116,23 +1115,11 @@ namespace Ryujinx.Ava.Systems
LocaleManager.Instance[LocaleKeys.VolumeShort] + $": {(int)(Device.GetVolume() * 100)}%", LocaleManager.Instance[LocaleKeys.VolumeShort] + $": {(int)(Device.GetVolume() * 100)}%",
dockedMode, dockedMode,
ConfigurationState.Instance.Graphics.AspectRatio.Value.ToText(), ConfigurationState.Instance.Graphics.AspectRatio.Value.ToText(),
FormatGameFrameRate(), Device.Statistics.FormatGameFrameRate(),
Device.Statistics.FormatFifoPercent(), Device.Statistics.FormatFifoPercent(),
_displayCount)); _displayCount));
} }
private string FormatGameFrameRate()
{
string frameRate = Device.Statistics.GetGameFrameRate().ToString("00.00");
string frameTime = Device.Statistics.GetGameFrameTime().ToString("00.00");
return Device.TurboMode
? LocaleManager.GetUnformatted(LocaleKeys.FpsTurboStatusBarText)
.Format(frameRate, frameTime, Device.TickScalar)
: LocaleManager.GetUnformatted(LocaleKeys.FpsStatusBarText)
.Format(frameRate, frameTime);
}
public async Task ShowExitPrompt() public async Task ShowExitPrompt()
{ {
bool shouldExit = !ConfigurationState.Instance.ShowConfirmExit; bool shouldExit = !ConfigurationState.Instance.ShowConfirmExit;
@@ -1228,12 +1215,6 @@ namespace Ryujinx.Ava.Systems
if (currentHotkeyState != _prevHotkeyState) if (currentHotkeyState != _prevHotkeyState)
{ {
if (ConfigurationState.Instance.Hid.Hotkeys.Value.TurboModeWhileHeld &&
_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.TurboMode) != Device.TurboMode)
{
Device.ToggleTurbo();
}
switch (currentHotkeyState) switch (currentHotkeyState)
{ {
case KeyboardHotkeyState.ToggleVSyncMode: case KeyboardHotkeyState.ToggleVSyncMode:
@@ -1245,12 +1226,6 @@ namespace Ryujinx.Ava.Systems
case KeyboardHotkeyState.CustomVSyncIntervalIncrement: case KeyboardHotkeyState.CustomVSyncIntervalIncrement:
_viewModel.CustomVSyncInterval = Device.IncrementCustomVSyncInterval(); _viewModel.CustomVSyncInterval = Device.IncrementCustomVSyncInterval();
break; break;
case KeyboardHotkeyState.TurboMode:
if (!ConfigurationState.Instance.Hid.Hotkeys.Value.TurboModeWhileHeld)
{
Device.ToggleTurbo();
}
break;
case KeyboardHotkeyState.Screenshot: case KeyboardHotkeyState.Screenshot:
ScreenshotRequested = true; ScreenshotRequested = true;
break; break;
@@ -1380,10 +1355,6 @@ namespace Ryujinx.Ava.Systems
{ {
state = KeyboardHotkeyState.CustomVSyncIntervalDecrement; state = KeyboardHotkeyState.CustomVSyncIntervalDecrement;
} }
else if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.TurboMode))
{
state = KeyboardHotkeyState.TurboMode;
}
return state; return state;
} }

View File

@@ -258,11 +258,6 @@ namespace Ryujinx.Ava.Systems.Configuration
/// Enables or disables low-power profiled translation cache persistency loading /// Enables or disables low-power profiled translation cache persistency loading
/// </summary> /// </summary>
public bool EnableLowPowerPtc { get; set; } public bool EnableLowPowerPtc { get; set; }
/// <summary>
/// Clock tick scalar, in percent points (100 = 1.0).
/// </summary>
public long TickScalar { get; set; }
/// <summary> /// <summary>
/// Enables or disables guest Internet access /// Enables or disables guest Internet access

View File

@@ -93,7 +93,6 @@ namespace Ryujinx.Ava.Systems.Configuration
System.EnableDockedMode.Value = cff.DockedMode; System.EnableDockedMode.Value = cff.DockedMode;
System.EnablePtc.Value = cff.EnablePtc; System.EnablePtc.Value = cff.EnablePtc;
System.EnableLowPowerPtc.Value = cff.EnableLowPowerPtc; System.EnableLowPowerPtc.Value = cff.EnableLowPowerPtc;
System.TickScalar.Value = cff.TickScalar;
System.EnableInternetAccess.Value = cff.EnableInternetAccess; System.EnableInternetAccess.Value = cff.EnableInternetAccess;
System.EnableFsIntegrityChecks.Value = cff.EnableFsIntegrityChecks; System.EnableFsIntegrityChecks.Value = cff.EnableFsIntegrityChecks;
System.FsGlobalAccessLogMode.Value = cff.FsGlobalAccessLogMode; System.FsGlobalAccessLogMode.Value = cff.FsGlobalAccessLogMode;
@@ -439,27 +438,9 @@ namespace Ryujinx.Ava.Systems.Configuration
(64, static cff => cff.LoggingEnableAvalonia = false), (64, static cff => cff.LoggingEnableAvalonia = false),
(65, static cff => cff.UpdateCheckerType = cff.CheckUpdatesOnStart ? UpdaterType.PromptAtStartup : UpdaterType.Off), (65, static cff => cff.UpdateCheckerType = cff.CheckUpdatesOnStart ? UpdaterType.PromptAtStartup : UpdaterType.Off),
(66, static cff => cff.DisableInputWhenOutOfFocus = false), (66, static cff => cff.DisableInputWhenOutOfFocus = false),
(67, static cff => cff.FocusLostActionType = cff.DisableInputWhenOutOfFocus ? FocusLostType.BlockInput : FocusLostType.DoNothing), (67, static cff => cff.FocusLostActionType = cff.DisableInputWhenOutOfFocus ? FocusLostType.BlockInput : FocusLostType.DoNothing)
(68, static cff => // 68 was the version that added per-game configs; the file structure did not change
{ // the version was increased so external tools could know that your Ryujinx version has per-game config capabilities.
cff.TickScalar = 200;
cff.Hotkeys = new KeyboardHotkeys
{
ToggleVSyncMode = cff.Hotkeys.ToggleVSyncMode,
Screenshot = cff.Hotkeys.Screenshot,
ShowUI = cff.Hotkeys.ShowUI,
Pause = cff.Hotkeys.Pause,
ToggleMute = cff.Hotkeys.ToggleMute,
ResScaleUp = cff.Hotkeys.ResScaleUp,
ResScaleDown = cff.Hotkeys.ResScaleDown,
VolumeUp = cff.Hotkeys.VolumeUp,
VolumeDown = cff.Hotkeys.VolumeDown,
CustomVSyncIntervalIncrement = cff.Hotkeys.CustomVSyncIntervalIncrement,
CustomVSyncIntervalDecrement = cff.Hotkeys.CustomVSyncIntervalDecrement,
TurboMode = Key.Unbound,
TurboModeWhileHeld = false
};
})
); );
} }
} }

View File

@@ -335,11 +335,6 @@ namespace Ryujinx.Ava.Systems.Configuration
/// Enables or disables persistent profiled translation cache /// Enables or disables persistent profiled translation cache
/// </summary> /// </summary>
public ReactiveObject<bool> EnablePtc { get; private set; } public ReactiveObject<bool> EnablePtc { get; private set; }
/// <summary>
/// Clock tick scalar, in percent points (100 = 1.0).
/// </summary>
public ReactiveObject<long> TickScalar { get; set; }
/// <summary> /// <summary>
/// Enables or disables low-power persistent profiled translation cache loading /// Enables or disables low-power persistent profiled translation cache loading
@@ -420,15 +415,6 @@ namespace Ryujinx.Ava.Systems.Configuration
EnableLowPowerPtc.LogChangesToValue(nameof(EnableLowPowerPtc)); EnableLowPowerPtc.LogChangesToValue(nameof(EnableLowPowerPtc));
EnableLowPowerPtc.Event += (_, evnt) EnableLowPowerPtc.Event += (_, evnt)
=> Optimizations.LowPower = evnt.NewValue; => Optimizations.LowPower = evnt.NewValue;
TickScalar = new ReactiveObject<long>();
TickScalar.LogChangesToValue(nameof(TickScalar));
TickScalar.Event += (_, evnt) =>
{
if (Switch.Shared is null)
return;
Switch.Shared.Configuration.TickScalar = evnt.NewValue;
};
EnableInternetAccess = new ReactiveObject<bool>(); EnableInternetAccess = new ReactiveObject<bool>();
EnableInternetAccess.LogChangesToValue(nameof(EnableInternetAccess)); EnableInternetAccess.LogChangesToValue(nameof(EnableInternetAccess));
EnableFsIntegrityChecks = new ReactiveObject<bool>(); EnableFsIntegrityChecks = new ReactiveObject<bool>();
@@ -856,7 +842,6 @@ namespace Ryujinx.Ava.Systems.Configuration
Graphics.VSyncMode, Graphics.VSyncMode,
System.EnableDockedMode, System.EnableDockedMode,
System.EnablePtc, System.EnablePtc,
System.TickScalar,
System.EnableInternetAccess, System.EnableInternetAccess,
System.EnableFsIntegrityChecks System.EnableFsIntegrityChecks
? IntegrityCheckLevel.ErrorOnInvalid ? IntegrityCheckLevel.ErrorOnInvalid
@@ -875,8 +860,8 @@ namespace Ryujinx.Ava.Systems.Configuration
Multiplayer.Mode, Multiplayer.Mode,
Multiplayer.DisableP2p, Multiplayer.DisableP2p,
Multiplayer.LdnPassphrase, Multiplayer.LdnPassphrase,
Multiplayer.GetLdnServer(), Instance.Multiplayer.GetLdnServer(),
Graphics.CustomVSyncInterval, Instance.Graphics.CustomVSyncInterval,
Hacks.ShowDirtyHacks ? Hacks.EnabledHacks : null); Instance.Hacks.ShowDirtyHacks ? Instance.Hacks.EnabledHacks : null);
} }
} }

View File

@@ -72,7 +72,6 @@ namespace Ryujinx.Ava.Systems.Configuration
EnableColorSpacePassthrough = Graphics.EnableColorSpacePassthrough, EnableColorSpacePassthrough = Graphics.EnableColorSpacePassthrough,
EnablePtc = System.EnablePtc, EnablePtc = System.EnablePtc,
EnableLowPowerPtc = System.EnableLowPowerPtc, EnableLowPowerPtc = System.EnableLowPowerPtc,
TickScalar = System.TickScalar,
EnableInternetAccess = System.EnableInternetAccess, EnableInternetAccess = System.EnableInternetAccess,
EnableFsIntegrityChecks = System.EnableFsIntegrityChecks, EnableFsIntegrityChecks = System.EnableFsIntegrityChecks,
FsGlobalAccessLogMode = System.FsGlobalAccessLogMode, FsGlobalAccessLogMode = System.FsGlobalAccessLogMode,
@@ -261,10 +260,6 @@ namespace Ryujinx.Ava.Systems.Configuration
ResScaleDown = Key.Unbound, ResScaleDown = Key.Unbound,
VolumeUp = Key.Unbound, VolumeUp = Key.Unbound,
VolumeDown = Key.Unbound, VolumeDown = Key.Unbound,
CustomVSyncIntervalIncrement = Key.Unbound,
CustomVSyncIntervalDecrement = Key.Unbound,
TurboMode = Key.Unbound,
TurboModeWhileHeld = false
}; };
Hid.RainbowSpeed.Value = 1f; Hid.RainbowSpeed.Value = 1f;
Hid.InputConfig.Value = Hid.InputConfig.Value =

View File

@@ -28,10 +28,6 @@ namespace Ryujinx.Ava.UI.Models.Input
[ObservableProperty] private Key _customVSyncIntervalDecrement; [ObservableProperty] private Key _customVSyncIntervalDecrement;
[ObservableProperty] private Key _turboMode;
[ObservableProperty] private bool _turboModeWhileHeld;
public HotkeyConfig(KeyboardHotkeys config) public HotkeyConfig(KeyboardHotkeys config)
{ {
if (config == null) if (config == null)
@@ -48,8 +44,6 @@ namespace Ryujinx.Ava.UI.Models.Input
VolumeDown = config.VolumeDown; VolumeDown = config.VolumeDown;
CustomVSyncIntervalIncrement = config.CustomVSyncIntervalIncrement; CustomVSyncIntervalIncrement = config.CustomVSyncIntervalIncrement;
CustomVSyncIntervalDecrement = config.CustomVSyncIntervalDecrement; CustomVSyncIntervalDecrement = config.CustomVSyncIntervalDecrement;
TurboMode = config.TurboMode;
TurboModeWhileHeld = config.TurboModeWhileHeld;
} }
public KeyboardHotkeys GetConfig() => public KeyboardHotkeys GetConfig() =>
@@ -66,8 +60,6 @@ namespace Ryujinx.Ava.UI.Models.Input
VolumeDown = VolumeDown, VolumeDown = VolumeDown,
CustomVSyncIntervalIncrement = CustomVSyncIntervalIncrement, CustomVSyncIntervalIncrement = CustomVSyncIntervalIncrement,
CustomVSyncIntervalDecrement = CustomVSyncIntervalDecrement, CustomVSyncIntervalDecrement = CustomVSyncIntervalDecrement,
TurboMode = TurboMode,
TurboModeWhileHeld = TurboModeWhileHeld
}; };
} }
} }

View File

@@ -432,7 +432,7 @@ namespace Ryujinx.Ava.UI.ViewModels
{ {
try try
{ {
HttpResponseMessage response = await _httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, "https://raw.githubusercontent.com/Ryubing/Nfc/refs/heads/main/tags.json")); HttpResponseMessage response = await _httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, "https://raw.githubusercontent.com/Ryubing/Ryujinx/refs/heads/master/assets/amiibo/Amiibo.json"));
if (response.IsSuccessStatusCode) if (response.IsSuccessStatusCode)
{ {
@@ -451,7 +451,7 @@ namespace Ryujinx.Ava.UI.ViewModels
{ {
try try
{ {
HttpResponseMessage response = await _httpClient.GetAsync("https://raw.githubusercontent.com/Ryubing/Nfc/refs/heads/main/tags.json"); HttpResponseMessage response = await _httpClient.GetAsync($"https://raw.githubusercontent.com/Ryubing/Ryujinx/refs/heads/master/assets/amiibo/Amiibo.json");
if (response.IsSuccessStatusCode) if (response.IsSuccessStatusCode)
{ {

View File

@@ -60,7 +60,6 @@ namespace Ryujinx.Ava.UI.ViewModels
private bool _enableCustomVSyncInterval; private bool _enableCustomVSyncInterval;
private int _customVSyncIntervalPercentageProxy; private int _customVSyncIntervalPercentageProxy;
private VSyncMode _vSyncMode; private VSyncMode _vSyncMode;
private long _turboModeMultiplier;
public event Action CloseWindow; public event Action CloseWindow;
public event Action SaveSettingsEvent; public event Action SaveSettingsEvent;
@@ -207,25 +206,6 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
public bool EnablePptc { get; set; } public bool EnablePptc { get; set; }
public bool EnableLowPowerPptc { get; set; } public bool EnableLowPowerPptc { get; set; }
public long TurboMultiplier
{
get => _turboModeMultiplier;
set
{
if (_turboModeMultiplier != value)
{
_turboModeMultiplier = value;
OnPropertyChanged();
OnPropertyChanged((nameof(TurboMultiplierPercentageText)));
}
}
}
public string TurboMultiplierPercentageText => $"{TurboMultiplier}%";
public bool EnableInternetAccess { get; set; } public bool EnableInternetAccess { get; set; }
public bool EnableFsIntegrityChecks { get; set; } public bool EnableFsIntegrityChecks { get; set; }
public bool IgnoreMissingServices { get; set; } public bool IgnoreMissingServices { get; set; }
@@ -612,7 +592,6 @@ namespace Ryujinx.Ava.UI.ViewModels
EnableLowPowerPptc = config.System.EnableLowPowerPtc; EnableLowPowerPptc = config.System.EnableLowPowerPtc;
MemoryMode = (int)config.System.MemoryManagerMode.Value; MemoryMode = (int)config.System.MemoryManagerMode.Value;
UseHypervisor = config.System.UseHypervisor; UseHypervisor = config.System.UseHypervisor;
TurboMultiplier = config.System.TickScalar;
// Graphics // Graphics
GraphicsBackendIndex = (int)config.Graphics.GraphicsBackend.Value; GraphicsBackendIndex = (int)config.Graphics.GraphicsBackend.Value;
@@ -715,7 +694,6 @@ namespace Ryujinx.Ava.UI.ViewModels
config.System.EnableLowPowerPtc.Value = EnableLowPowerPptc; config.System.EnableLowPowerPtc.Value = EnableLowPowerPptc;
config.System.MemoryManagerMode.Value = (MemoryManagerMode)MemoryMode; config.System.MemoryManagerMode.Value = (MemoryManagerMode)MemoryMode;
config.System.UseHypervisor.Value = UseHypervisor; config.System.UseHypervisor.Value = UseHypervisor;
config.System.TickScalar.Value = TurboMultiplier;
// Graphics // Graphics
config.Graphics.VSyncMode.Value = VSyncMode; config.Graphics.VSyncMode.Value = VSyncMode;

View File

@@ -7,7 +7,6 @@
xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup" xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup"
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
xmlns:helper="clr-namespace:Ryujinx.Common.Helper;assembly=Ryujinx.Common" xmlns:helper="clr-namespace:Ryujinx.Common.Helper;assembly=Ryujinx.Common"
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
mc:Ignorable="d" mc:Ignorable="d"
x:DataType="viewModels:SettingsViewModel"> x:DataType="viewModels:SettingsViewModel">
<Design.DataContext> <Design.DataContext>
@@ -77,57 +76,6 @@
ToolTip.Tip="{ext:Locale UseHypervisorTooltip}" /> ToolTip.Tip="{ext:Locale UseHypervisorTooltip}" />
</CheckBox> </CheckBox>
</StackPanel> </StackPanel>
<Separator Height="1" />
<StackPanel
Orientation="Vertical"
Spacing="5">
<TextBlock
Classes="h1"
Text="{ext:Locale SettingsTabSystemHacks}" />
<TextBlock
Foreground="{DynamicResource SecondaryTextColor}"
TextDecorations="Underline"
Text="{ext:Locale SettingsTabSystemHacksNote}" />
</StackPanel>
<StackPanel
Margin="10,0,0,0"
HorizontalAlignment="Stretch"
Orientation="Vertical">
<StackPanel Margin="0,0,0,10"
Orientation="Horizontal">
<TextBlock
VerticalAlignment="Center"
Background="Transparent"
Text="{ext:Locale SettingsTabSystemTurboMultiplier}"
ToolTip.Tip="{ext:Locale SettingsTabSystemTurboMultiplierToolTip}"
Width="250" />
<ui:NumberBox ToolTip.Tip="{ext:Locale SettingsTabSystemTurboMultiplierValueToolTip}"
Value="{Binding TurboMultiplier}"
Width="165"
SmallChange="1.0"
LargeChange="10"
SimpleNumberFormat="F0"
SpinButtonPlacementMode="Hidden"
Minimum="50"
Maximum="300" />
<Slider Value="{Binding TurboMultiplier}"
ToolTip.Tip="{ext:Locale SettingsTabSystemTurboMultiplierValueToolTip}"
MinWidth="175"
Margin="10,-3,0,0"
Height="32"
Padding="0,-5"
TickFrequency="1"
IsSnapToTickEnabled="True"
LargeChange="10"
SmallChange="1"
VerticalAlignment="Center"
Minimum="50"
Maximum="500" />
<TextBlock Margin="5,0"
Width="40"
Text="{Binding TurboMultiplierPercentageText}"/>
</StackPanel>
</StackPanel>
</StackPanel> </StackPanel>
</Border> </Border>
</ScrollViewer> </ScrollViewer>

View File

@@ -19,7 +19,7 @@
<Setter Property="Margin" Value="10, 0, 0, 0" /> <Setter Property="Margin" Value="10, 0, 0, 0" />
<Setter Property="Orientation" Value="Horizontal" /> <Setter Property="Orientation" Value="Horizontal" />
</Style> </Style>
<Style Selector="StackPanel > StackPanel > TextBlock.settingHeader"> <Style Selector="StackPanel > StackPanel > TextBlock">
<Setter Property="VerticalAlignment" Value="Center" /> <Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Width" Value="230" /> <Setter Property="Width" Value="230" />
</Style> </Style>
@@ -47,79 +47,71 @@
Classes="h1" Classes="h1"
Text="{ext:Locale SettingsTabHotkeysHotkeys}" /> Text="{ext:Locale SettingsTabHotkeysHotkeys}" />
<StackPanel> <StackPanel>
<TextBlock Text="{ext:Locale SettingsTabHotkeysToggleVSyncModeHotkey}" Classes="settingHeader" /> <TextBlock Text="{ext:Locale SettingsTabHotkeysToggleVSyncModeHotkey}" />
<ToggleButton Name="ToggleVSyncMode"> <ToggleButton Name="ToggleVSyncMode">
<TextBlock Text="{Binding KeyboardHotkey.ToggleVSyncMode, Converter={x:Static helpers:KeyValueConverter.Instance}}" /> <TextBlock Text="{Binding KeyboardHotkey.ToggleVSyncMode, Converter={x:Static helpers:KeyValueConverter.Instance}}" />
</ToggleButton> </ToggleButton>
</StackPanel> </StackPanel>
<StackPanel> <StackPanel>
<TextBlock Text="{ext:Locale SettingsTabHotkeysScreenshotHotkey}" Classes="settingHeader" /> <TextBlock Text="{ext:Locale SettingsTabHotkeysScreenshotHotkey}" />
<ToggleButton Name="Screenshot"> <ToggleButton Name="Screenshot">
<TextBlock Text="{Binding KeyboardHotkey.Screenshot, Converter={x:Static helpers:KeyValueConverter.Instance}}" /> <TextBlock Text="{Binding KeyboardHotkey.Screenshot, Converter={x:Static helpers:KeyValueConverter.Instance}}" />
</ToggleButton> </ToggleButton>
</StackPanel> </StackPanel>
<StackPanel> <StackPanel>
<TextBlock Text="{ext:Locale SettingsTabHotkeysShowUiHotkey}" Classes="settingHeader" /> <TextBlock Text="{ext:Locale SettingsTabHotkeysShowUiHotkey}" />
<ToggleButton Name="ShowUI"> <ToggleButton Name="ShowUI">
<TextBlock Text="{Binding KeyboardHotkey.ShowUI, Converter={x:Static helpers:KeyValueConverter.Instance}}" /> <TextBlock Text="{Binding KeyboardHotkey.ShowUI, Converter={x:Static helpers:KeyValueConverter.Instance}}" />
</ToggleButton> </ToggleButton>
</StackPanel> </StackPanel>
<StackPanel> <StackPanel>
<TextBlock Text="{ext:Locale SettingsTabHotkeysPauseHotkey}" Classes="settingHeader" /> <TextBlock Text="{ext:Locale SettingsTabHotkeysPauseHotkey}" />
<ToggleButton Name="Pause"> <ToggleButton Name="Pause">
<TextBlock Text="{Binding KeyboardHotkey.Pause, Converter={x:Static helpers:KeyValueConverter.Instance}}" /> <TextBlock Text="{Binding KeyboardHotkey.Pause, Converter={x:Static helpers:KeyValueConverter.Instance}}" />
</ToggleButton> </ToggleButton>
</StackPanel> </StackPanel>
<StackPanel> <StackPanel>
<TextBlock Text="{ext:Locale SettingsTabHotkeysToggleMuteHotkey}" Classes="settingHeader" /> <TextBlock Text="{ext:Locale SettingsTabHotkeysToggleMuteHotkey}" />
<ToggleButton Name="ToggleMute"> <ToggleButton Name="ToggleMute">
<TextBlock Text="{Binding KeyboardHotkey.ToggleMute, Converter={x:Static helpers:KeyValueConverter.Instance}}" /> <TextBlock Text="{Binding KeyboardHotkey.ToggleMute, Converter={x:Static helpers:KeyValueConverter.Instance}}" />
</ToggleButton> </ToggleButton>
</StackPanel> </StackPanel>
<StackPanel> <StackPanel>
<TextBlock Text="{ext:Locale SettingsTabHotkeysResScaleUpHotkey}" Classes="settingHeader" /> <TextBlock Text="{ext:Locale SettingsTabHotkeysResScaleUpHotkey}" />
<ToggleButton Name="ResScaleUp"> <ToggleButton Name="ResScaleUp">
<TextBlock Text="{Binding KeyboardHotkey.ResScaleUp, Converter={x:Static helpers:KeyValueConverter.Instance}}" /> <TextBlock Text="{Binding KeyboardHotkey.ResScaleUp, Converter={x:Static helpers:KeyValueConverter.Instance}}" />
</ToggleButton> </ToggleButton>
</StackPanel> </StackPanel>
<StackPanel> <StackPanel>
<TextBlock Text="{ext:Locale SettingsTabHotkeysResScaleDownHotkey}" Classes="settingHeader" /> <TextBlock Text="{ext:Locale SettingsTabHotkeysResScaleDownHotkey}" />
<ToggleButton Name="ResScaleDown"> <ToggleButton Name="ResScaleDown">
<TextBlock Text="{Binding KeyboardHotkey.ResScaleDown, Converter={x:Static helpers:KeyValueConverter.Instance}}" /> <TextBlock Text="{Binding KeyboardHotkey.ResScaleDown, Converter={x:Static helpers:KeyValueConverter.Instance}}" />
</ToggleButton> </ToggleButton>
</StackPanel> </StackPanel>
<StackPanel> <StackPanel>
<TextBlock Text="{ext:Locale SettingsTabHotkeysVolumeUpHotkey}" Classes="settingHeader" /> <TextBlock Text="{ext:Locale SettingsTabHotkeysVolumeUpHotkey}" />
<ToggleButton Name="VolumeUp"> <ToggleButton Name="VolumeUp">
<TextBlock Text="{Binding KeyboardHotkey.VolumeUp, Converter={x:Static helpers:KeyValueConverter.Instance}}" /> <TextBlock Text="{Binding KeyboardHotkey.VolumeUp, Converter={x:Static helpers:KeyValueConverter.Instance}}" />
</ToggleButton> </ToggleButton>
</StackPanel> </StackPanel>
<StackPanel> <StackPanel>
<TextBlock Text="{ext:Locale SettingsTabHotkeysVolumeDownHotkey}" Classes="settingHeader" /> <TextBlock Text="{ext:Locale SettingsTabHotkeysVolumeDownHotkey}" />
<ToggleButton Name="VolumeDown"> <ToggleButton Name="VolumeDown">
<TextBlock Text="{Binding KeyboardHotkey.VolumeDown, Converter={x:Static helpers:KeyValueConverter.Instance}}" /> <TextBlock Text="{Binding KeyboardHotkey.VolumeDown, Converter={x:Static helpers:KeyValueConverter.Instance}}" />
</ToggleButton> </ToggleButton>
</StackPanel> </StackPanel>
<StackPanel Margin="10,0,0,0" Orientation="Horizontal"> <StackPanel Margin="10,0,0,0" Orientation="Horizontal">
<TextBlock Text="{ext:Locale SettingsTabHotkeysIncrementCustomVSyncIntervalHotkey}" Classes="settingHeader" /> <TextBlock Text="{ext:Locale SettingsTabHotkeysIncrementCustomVSyncIntervalHotkey}" />
<ToggleButton Name="CustomVSyncIntervalIncrement"> <ToggleButton Name="CustomVSyncIntervalIncrement">
<TextBlock Text="{Binding KeyboardHotkey.CustomVSyncIntervalIncrement, Converter={x:Static helpers:KeyValueConverter.Instance}}" /> <TextBlock Text="{Binding KeyboardHotkey.CustomVSyncIntervalIncrement, Converter={x:Static helpers:KeyValueConverter.Instance}}" />
</ToggleButton> </ToggleButton>
</StackPanel> </StackPanel>
<StackPanel Margin="10,0,0,0" Orientation="Horizontal"> <StackPanel Margin="10,0,0,0" Orientation="Horizontal">
<TextBlock Text="{ext:Locale SettingsTabHotkeysDecrementCustomVSyncIntervalHotkey}" Classes="settingHeader" /> <TextBlock Text="{ext:Locale SettingsTabHotkeysDecrementCustomVSyncIntervalHotkey}" />
<ToggleButton Name="CustomVSyncIntervalDecrement"> <ToggleButton Name="CustomVSyncIntervalDecrement">
<TextBlock Text="{Binding KeyboardHotkey.CustomVSyncIntervalDecrement, Converter={x:Static helpers:KeyValueConverter.Instance}}" /> <TextBlock Text="{Binding KeyboardHotkey.CustomVSyncIntervalDecrement, Converter={x:Static helpers:KeyValueConverter.Instance}}" />
</ToggleButton> </ToggleButton>
</StackPanel> </StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{ext:Locale SettingsTabHotkeysTurboMode}" Classes="settingHeader" ToolTip.Tip="{ext:Locale SettingsTabHotkeysTurboModeToolTip}" Background="Transparent" />
<ToggleButton Name="TurboMode">
<TextBlock Text="{Binding KeyboardHotkey.TurboMode, Converter={x:Static helpers:KeyValueConverter.Instance}}" />
</ToggleButton>
<TextBlock Text="{ext:Locale SettingsTabHotkeysOnlyWhilePressed}" Margin="10,0" />
<CheckBox IsChecked="{Binding KeyboardHotkey.TurboModeWhileHeld}" />
</StackPanel>
</StackPanel> </StackPanel>
</Border> </Border>
</ScrollViewer> </ScrollViewer>

View File

@@ -121,9 +121,6 @@ namespace Ryujinx.Ava.UI.Views.Settings
ViewModel.KeyboardHotkey.CustomVSyncIntervalDecrement = ViewModel.KeyboardHotkey.CustomVSyncIntervalDecrement =
buttonValue.AsHidType<Key>(); buttonValue.AsHidType<Key>();
break; break;
case "TurboMode":
ViewModel.KeyboardHotkey.TurboMode = buttonValue.AsHidType<Key>();
break;
} }
}); });
} }