Compare commits

..

9 Commits

Author SHA1 Message Date
gdkchan
70d65d3d8e Enable copy dependency between RGBA8 and RGBA32 formats (#5943)
* Enable copy dependency between RGBA8 and RGBA32 formats

* Take packed flag into account for texture formats

* Account for widths not being a multiple of each other

* Don't try to alias depth textures as color, fix log condition

* PR feedback
2023-11-19 15:27:34 -03:00
gdkchan
0b58f46266 Extend bindless elimination to see through Phis with the same results (#5957)
* Extend bindless elimination to see through Phis with the same results

* Shader cache version bump
2023-11-19 15:10:44 -03:00
MutantAura
aa96dcb1be misc: Default to Vulkan if available or running on macOS (#5913)
* Addition of default backend check. Vulkan is preferred if available or macOS.

* import ordering format fix

* Update src/Ryujinx/Program.cs

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

* remove redundant load types

---------

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2023-11-18 17:42:45 -03:00
gdkchan
82a638230e Fix JitCache.Unmap called with the same address freeing memory in use (#5937) 2023-11-16 17:52:21 -03:00
Isaac Marovitz
d11fe26aa3 Fix macOS Path (#5941) 2023-11-16 16:09:15 -03:00
gdkchan
dcf10561b9 Fix missing texture flush for draw then DMA copy sequence without render target change (#5933)
* Unbind render targets before DMA copy

* Move DirtyAction to TextureGroupHandle

* Fix lost copy dependency bug

* XML doc
2023-11-15 21:36:25 -03:00
Mary Guillemard
cdc8fed64f chore: Update OpenTK to 4.8.1 (#5912)
OpenTK.OpenAL was renamed to OpenTK.Audio.OpenAL.

Signed-off-by: Mary Guillemard <mary@mary.zone>
2023-11-15 19:08:46 +01:00
Mary Guillemard
388446c255 infra: Workaround Microsoft.NET.ILLink.Tasks restore failure on Flathub
This package seems to be required for triming now but isn't restored by default.
This changes the flatpak pusher to publish so we are sure that the package is in the cache.

Signed-off-by: Mary Guillemard <mary@mary.zone>
2023-11-15 18:12:19 +01:00
Zoltan Csizmadia
29e192f241 Migrate to .NET 8 (#5887)
* Change TargetFramework to net8.0

* Disable info messages

* Fix warings

* Disable additional analyzer messages

* Fix typo

* Add whitespace

* Fix ref vs in warnings

* Use explicit [In] on array parameters

* No need to guard Remove with Contains

* Use 'ArgumentOutOfRangeException.ThrowIf...' instead of explicitly throwing a new exception instance

* Bump .NET SDK version

* Enable JsonSerializerIsReflectionEnabledByDefault

* Use 8.0.100 GA release

* Bump System package versions

---------

Co-authored-by: Zoltan Csizmadia <Zoltan.Csizmadia@vericast.com>
2023-11-15 17:41:31 +01:00
74 changed files with 362 additions and 282 deletions

View File

@@ -233,6 +233,29 @@ dotnet_naming_style.IPascalCase.required_suffix =
dotnet_naming_style.IPascalCase.word_separator = dotnet_naming_style.IPascalCase.word_separator =
dotnet_naming_style.IPascalCase.capitalization = pascal_case dotnet_naming_style.IPascalCase.capitalization = pascal_case
# TODO:
# .NET 8 migration (new warnings are caused by the NET 8 C# compiler and analyzer)
# The following info messages might need to be fixed in the source code instead of hiding the actual message
# Without the following lines, dotnet format would fail
# Disable "Collection initialization can be simplified"
dotnet_diagnostic.IDE0028.severity = none
dotnet_diagnostic.IDE0300.severity = none
dotnet_diagnostic.IDE0301.severity = none
dotnet_diagnostic.IDE0302.severity = none
dotnet_diagnostic.IDE0305.severity = none
# Disable "'new' expression can be simplified"
dotnet_diagnostic.IDE0090.severity = none
# Disable "Use primary constructor"
dotnet_diagnostic.IDE0290.severity = none
# Disable "Member '' does not access instance data and can be marked as static"
dotnet_diagnostic.CA1822.severity = none
# Disable "Change type of field '' from '' to '' for improved performance"
dotnet_diagnostic.CA1859.severity = none
# Disable "Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array"
dotnet_diagnostic.CA1861.severity = none
# Disable "Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'"
dotnet_diagnostic.CA1862.severity = none
[src/Ryujinx.HLE/HOS/Services/**.cs] [src/Ryujinx.HLE/HOS/Services/**.cs]
# Disable "mark members as static" rule for services # Disable "mark members as static" rule for services
dotnet_diagnostic.CA1822.severity = none dotnet_diagnostic.CA1822.severity = none

View File

@@ -30,7 +30,7 @@ jobs:
- os: windows-latest - os: windows-latest
OS_NAME: Windows x64 OS_NAME: Windows x64
DOTNET_RUNTIME_IDENTIFIER: win10-x64 DOTNET_RUNTIME_IDENTIFIER: win-x64
RELEASE_ZIP_OS_NAME: win_x64 RELEASE_ZIP_OS_NAME: win_x64
fail-fast: false fail-fast: false

View File

@@ -49,7 +49,9 @@ jobs:
run: python -m pip install PyYAML lxml run: python -m pip install PyYAML lxml
- name: Restore Nuget packages - name: Restore Nuget packages
run: dotnet restore Ryujinx/${{ env.RYUJINX_PROJECT_FILE }} # With .NET 8.0.100, Microsoft.NET.ILLink.Tasks isn't restored by default and only seems to appears when publishing.
# So we just publish to grab the dependencies
run: dotnet publish -c Release -r linux-x64 Ryujinx/${{ env.RYUJINX_PROJECT_FILE }} --self-contained
- name: Generate nuget_sources.json - name: Generate nuget_sources.json
shell: python shell: python

View File

@@ -59,7 +59,7 @@ jobs:
- os: windows-latest - os: windows-latest
OS_NAME: Windows x64 OS_NAME: Windows x64
DOTNET_RUNTIME_IDENTIFIER: win10-x64 DOTNET_RUNTIME_IDENTIFIER: win-x64
RELEASE_ZIP_OS_NAME: win_x64 RELEASE_ZIP_OS_NAME: win_x64
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4

View File

@@ -21,16 +21,16 @@
<PackageVersion Include="LibHac" Version="0.19.0" /> <PackageVersion Include="LibHac" Version="0.19.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" /> <PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.7.0" /> <PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.7.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.7.2" /> <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="2.3.2" /> <PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="2.3.2" />
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" /> <PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
<PackageVersion Include="NetCoreServer" Version="7.0.0" /> <PackageVersion Include="NetCoreServer" Version="7.0.0" />
<PackageVersion Include="NUnit" Version="3.13.3" /> <PackageVersion Include="NUnit" Version="3.13.3" />
<PackageVersion Include="NUnit3TestAdapter" Version="4.1.0" /> <PackageVersion Include="NUnit3TestAdapter" Version="4.1.0" />
<PackageVersion Include="OpenTK.Core" Version="4.7.7" /> <PackageVersion Include="OpenTK.Core" Version="4.8.1" />
<PackageVersion Include="OpenTK.Graphics" Version="4.7.7" /> <PackageVersion Include="OpenTK.Graphics" Version="4.8.1" />
<PackageVersion Include="OpenTK.OpenAL" Version="4.7.7" /> <PackageVersion Include="OpenTK.Audio.OpenAL" Version="4.8.1" />
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.7.7" /> <PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.8.1" />
<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" Version="5.0.1-build13" /> <PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.1-build13" />
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" /> <PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
@@ -45,10 +45,10 @@
<PackageVersion Include="SixLabors.ImageSharp" Version="1.0.4" /> <PackageVersion Include="SixLabors.ImageSharp" Version="1.0.4" />
<PackageVersion Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta11" /> <PackageVersion Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta11" />
<PackageVersion Include="SPB" Version="0.0.4-build28" /> <PackageVersion Include="SPB" Version="0.0.4-build28" />
<PackageVersion Include="System.Drawing.Common" Version="7.0.0" /> <PackageVersion Include="System.Drawing.Common" Version="8.0.0" />
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="7.0.0" /> <PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="7.0.3" />
<PackageVersion Include="System.IO.Hashing" Version="7.0.0" /> <PackageVersion Include="System.IO.Hashing" Version="8.0.0" />
<PackageVersion Include="System.Management" Version="7.0.2" /> <PackageVersion Include="System.Management" Version="8.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

@@ -68,7 +68,7 @@ The latest automatic build for Windows, macOS, and Linux can be found on the [Of
If you wish to build the emulator yourself, follow these steps: If you wish to build the emulator yourself, follow these steps:
### Step 1 ### Step 1
Install the X64 version of [.NET 7.0 (or higher) SDK](https://dotnet.microsoft.com/download/dotnet/7.0). Install the X64 version of [.NET 8.0 (or higher) SDK](https://dotnet.microsoft.com/download/dotnet/8.0).
### Step 2 ### Step 2
Either use `git clone https://github.com/Ryujinx/Ryujinx` on the command line to clone the repository or use Code --> Download zip button to get the files. Either use `git clone https://github.com/Ryujinx/Ryujinx` on the command line to clone the repository or use Code --> Download zip button to get the files.

View File

@@ -1,6 +1,6 @@
{ {
"sdk": { "sdk": {
"version": "7.0.200", "version": "8.0.100",
"rollForward": "latestFeature" "rollForward": "latestFeature"
} }
} }

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>

View File

@@ -117,12 +117,11 @@ namespace ARMeilleure.Translation.Cache
int funcOffset = (int)(pointer.ToInt64() - _jitRegion.Pointer.ToInt64()); int funcOffset = (int)(pointer.ToInt64() - _jitRegion.Pointer.ToInt64());
bool result = TryFind(funcOffset, out CacheEntry entry); if (TryFind(funcOffset, out CacheEntry entry, out int entryIndex) && entry.Offset == funcOffset)
Debug.Assert(result); {
_cacheAllocator.Free(funcOffset, AlignCodeSize(entry.Size));
_cacheAllocator.Free(funcOffset, AlignCodeSize(entry.Size)); _cacheEntries.RemoveAt(entryIndex);
}
Remove(funcOffset);
} }
} }
@@ -181,22 +180,7 @@ namespace ARMeilleure.Translation.Cache
_cacheEntries.Insert(index, entry); _cacheEntries.Insert(index, entry);
} }
private static void Remove(int offset) public static bool TryFind(int offset, out CacheEntry entry, out int entryIndex)
{
int index = _cacheEntries.BinarySearch(new CacheEntry(offset, 0, default));
if (index < 0)
{
index = ~index - 1;
}
if (index >= 0)
{
_cacheEntries.RemoveAt(index);
}
}
public static bool TryFind(int offset, out CacheEntry entry)
{ {
lock (_lock) lock (_lock)
{ {
@@ -210,11 +194,13 @@ namespace ARMeilleure.Translation.Cache
if (index >= 0) if (index >= 0)
{ {
entry = _cacheEntries[index]; entry = _cacheEntries[index];
entryIndex = index;
return true; return true;
} }
} }
entry = default; entry = default;
entryIndex = 0;
return false; return false;
} }
} }

View File

@@ -95,7 +95,7 @@ namespace ARMeilleure.Translation.Cache
{ {
int offset = (int)((long)controlPc - context.ToInt64()); int offset = (int)((long)controlPc - context.ToInt64());
if (!JitCache.TryFind(offset, out CacheEntry funcEntry)) if (!JitCache.TryFind(offset, out CacheEntry funcEntry, out _))
{ {
return null; // Not found. return null; // Not found.
} }

View File

@@ -1,11 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="OpenTK.OpenAL" /> <PackageReference Include="OpenTK.Audio.OpenAL" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>

View File

@@ -1,9 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<RuntimeIdentifiers>win10-x64;linux-x64;osx-x64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;osx-x64;linux-x64</RuntimeIdentifiers>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@@ -15,11 +15,11 @@
<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)' != 'win10-x64'"> <ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.dylib" Condition="'$(RuntimeIdentifier)' != 'linux-x64' 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)' != 'win10-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'"> <ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.so" Condition="'$(RuntimeIdentifier)' != 'win-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>libsoundio.so</TargetPath> <TargetPath>libsoundio.so</TargetPath>
</ContentWithTargetPath> </ContentWithTargetPath>

View File

@@ -25,7 +25,7 @@ namespace Ryujinx.Audio.Renderer.Utils
throw new ArgumentOutOfRangeException(nameof(backingMemory), backingMemory.Length, null); throw new ArgumentOutOfRangeException(nameof(backingMemory), backingMemory.Length, null);
} }
MemoryMarshal.Write(backingMemory.Span[..size], ref data); MemoryMarshal.Write(backingMemory.Span[..size], in data);
backingMemory = backingMemory[size..]; backingMemory = backingMemory[size..];
} }
@@ -45,7 +45,7 @@ namespace Ryujinx.Audio.Renderer.Utils
throw new ArgumentOutOfRangeException(nameof(backingMemory), backingMemory.Length, null); throw new ArgumentOutOfRangeException(nameof(backingMemory), backingMemory.Length, null);
} }
MemoryMarshal.Write(backingMemory[..size], ref data); MemoryMarshal.Write(backingMemory[..size], in data);
backingMemory = backingMemory[size..]; backingMemory = backingMemory[size..];
} }

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<RuntimeIdentifiers>win10-x64;osx-x64;linux-x64</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>
@@ -25,6 +25,16 @@
<TrimMode>partial</TrimMode> <TrimMode>partial</TrimMode>
</PropertyGroup> </PropertyGroup>
<!--
FluentAvalonia, used in the Avalonia UI, requires a workaround for the json serializer used internally when using .NET 8+ System.Text.Json.
See:
https://github.com/amwx/FluentAvalonia/issues/481
https://devblogs.microsoft.com/dotnet/system-text-json-in-dotnet-8/
-->
<PropertyGroup>
<JsonSerializerIsReflectionEnabledByDefault>true</JsonSerializerIsReflectionEnabledByDefault>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Avalonia" /> <PackageReference Include="Avalonia" />
<PackageReference Include="Avalonia.Desktop" /> <PackageReference Include="Avalonia.Desktop" />
@@ -40,7 +50,7 @@
<PackageReference Include="OpenTK.Core" /> <PackageReference Include="OpenTK.Core" />
<PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" /> <PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" />
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" /> <PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" />
<PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'win10-x64'" /> <PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'win-x64'" />
<PackageReference Include="Silk.NET.Vulkan" /> <PackageReference Include="Silk.NET.Vulkan" />
<PackageReference Include="Silk.NET.Vulkan.Extensions.EXT" /> <PackageReference Include="Silk.NET.Vulkan.Extensions.EXT" />
<PackageReference Include="Silk.NET.Vulkan.Extensions.KHR" /> <PackageReference Include="Silk.NET.Vulkan.Extensions.KHR" />

View File

@@ -86,7 +86,7 @@ namespace Ryujinx.Ava.UI.Helpers
public static partial IntPtr SetCursor(IntPtr handle); public static partial IntPtr SetCursor(IntPtr handle);
[LibraryImport("user32.dll")] [LibraryImport("user32.dll")]
public static partial IntPtr CreateCursor(IntPtr hInst, int xHotSpot, int yHotSpot, int nWidth, int nHeight, byte[] pvAndPlane, byte[] pvXorPlane); public static partial IntPtr CreateCursor(IntPtr hInst, int xHotSpot, int yHotSpot, int nWidth, int nHeight, [In] byte[] pvAndPlane, [In] byte[] pvXorPlane);
[LibraryImport("user32.dll", SetLastError = true, EntryPoint = "RegisterClassExW")] [LibraryImport("user32.dll", SetLastError = true, EntryPoint = "RegisterClassExW")]
public static partial ushort RegisterClassEx(ref WndClassEx param); public static partial ushort RegisterClassEx(ref WndClassEx param);

View File

@@ -48,7 +48,7 @@ namespace Ryujinx.Common.Configuration
string appDataPath; string appDataPath;
if (OperatingSystem.IsMacOS()) if (OperatingSystem.IsMacOS())
{ {
appDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "Library", "Application Support"); appDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Library", "Application Support");
} }
else else
{ {

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefineConstants Condition=" '$(ExtraDefineConstants)' != '' ">$(DefineConstants);$(ExtraDefineConstants)</DefineConstants> <DefineConstants Condition=" '$(ExtraDefineConstants)' != '' ">$(DefineConstants);$(ExtraDefineConstants)</DefineConstants>
</PropertyGroup> </PropertyGroup>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
</Project> </Project>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">

View File

@@ -211,6 +211,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
int xCount = (int)_state.State.LineLengthIn; int xCount = (int)_state.State.LineLengthIn;
int yCount = (int)_state.State.LineCount; int yCount = (int)_state.State.LineCount;
_channel.TextureManager.RefreshModifiedTextures();
_3dEngine.CreatePendingSyncs(); _3dEngine.CreatePendingSyncs();
_3dEngine.FlushUboDirty(); _3dEngine.FlushUboDirty();

View File

@@ -651,9 +651,35 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <returns>True if the format is valid, false otherwise</returns> /// <returns>True if the format is valid, false otherwise</returns>
public static bool TryGetTextureFormat(uint encoded, bool isSrgb, out FormatInfo format) public static bool TryGetTextureFormat(uint encoded, bool isSrgb, out FormatInfo format)
{ {
encoded |= (isSrgb ? 1u << 19 : 0u); bool isPacked = (encoded & 0x80000000u) != 0;
if (isPacked)
{
encoded &= ~0x80000000u;
}
return _textureFormats.TryGetValue((TextureFormat)encoded, out format); encoded |= isSrgb ? 1u << 19 : 0u;
bool found = _textureFormats.TryGetValue((TextureFormat)encoded, out format);
if (found && isPacked && !format.Format.IsDepthOrStencil())
{
// If the packed flag is set, then the components of the pixel are tightly packed into the
// GPU registers on the shader.
// We can get the same behaviour by aliasing the texture as a format with the same amount of
// bytes per pixel, but only a single or the lowest possible number of components.
format = format.BytesPerPixel switch
{
1 => new FormatInfo(Format.R8Unorm, 1, 1, 1, 1),
2 => new FormatInfo(Format.R16Unorm, 1, 1, 2, 1),
4 => new FormatInfo(Format.R32Float, 1, 1, 4, 1),
8 => new FormatInfo(Format.R32G32Float, 1, 1, 8, 2),
16 => new FormatInfo(Format.R32G32B32A32Float, 1, 1, 16, 4),
_ => format,
};
}
return found;
} }
/// <summary> /// <summary>

View File

@@ -101,11 +101,6 @@ namespace Ryujinx.Graphics.Gpu.Image
/// </summary> /// </summary>
public bool AlwaysFlushOnOverlap { get; private set; } public bool AlwaysFlushOnOverlap { get; private set; }
/// <summary>
/// Indicates that the texture was modified since the last time it was flushed.
/// </summary>
public bool ModifiedSinceLastFlush { get; set; }
/// <summary> /// <summary>
/// Increments when the host texture is swapped, or when the texture is removed from all pools. /// Increments when the host texture is swapped, or when the texture is removed from all pools.
/// </summary> /// </summary>
@@ -1443,7 +1438,7 @@ namespace Ryujinx.Graphics.Gpu.Image
if (_modifiedStale || Group.HasCopyDependencies || Group.HasFlushBuffer) if (_modifiedStale || Group.HasCopyDependencies || Group.HasFlushBuffer)
{ {
_modifiedStale = false; _modifiedStale = false;
Group.SignalModifying(this, bound, bound || ModifiedSinceLastFlush || Group.HasCopyDependencies || Group.HasFlushBuffer); Group.SignalModifying(this, bound);
} }
_physicalMemory.TextureCache.Lift(this); _physicalMemory.TextureCache.Lift(this);

View File

@@ -2,6 +2,8 @@ using Ryujinx.Common;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Texture; using Ryujinx.Graphics.Texture;
using System; using System;
using System.Diagnostics;
using System.Numerics;
namespace Ryujinx.Graphics.Gpu.Image namespace Ryujinx.Graphics.Gpu.Image
{ {
@@ -339,7 +341,20 @@ namespace Ryujinx.Graphics.Gpu.Image
if (lhs.FormatInfo.BytesPerPixel != rhs.FormatInfo.BytesPerPixel && IsIncompatibleFormatAliasingAllowed(lhs.FormatInfo, rhs.FormatInfo)) if (lhs.FormatInfo.BytesPerPixel != rhs.FormatInfo.BytesPerPixel && IsIncompatibleFormatAliasingAllowed(lhs.FormatInfo, rhs.FormatInfo))
{ {
alignedWidthMatches = lhsSize.Width * lhs.FormatInfo.BytesPerPixel == rhsSize.Width * rhs.FormatInfo.BytesPerPixel; // If the formats are incompatible, but the texture strides match,
// we might allow them to be copy compatible depending on the format.
// The strides are aligned because the format with higher bytes per pixel
// might need a bit of padding at the end due to one width not being a multiple of the other.
Debug.Assert((1 << BitOperations.Log2((uint)lhs.FormatInfo.BytesPerPixel)) == lhs.FormatInfo.BytesPerPixel);
Debug.Assert((1 << BitOperations.Log2((uint)rhs.FormatInfo.BytesPerPixel)) == rhs.FormatInfo.BytesPerPixel);
int alignment = Math.Max(lhs.FormatInfo.BytesPerPixel, rhs.FormatInfo.BytesPerPixel);
int lhsStride = BitUtils.AlignUp(lhsSize.Width * lhs.FormatInfo.BytesPerPixel, alignment);
int rhsStride = BitUtils.AlignUp(rhsSize.Width * rhs.FormatInfo.BytesPerPixel, alignment);
alignedWidthMatches = lhsStride == rhsStride;
} }
TextureViewCompatibility result = TextureViewCompatibility.Full; TextureViewCompatibility result = TextureViewCompatibility.Full;
@@ -718,7 +733,8 @@ namespace Ryujinx.Graphics.Gpu.Image
(lhsFormat, rhsFormat) = (rhsFormat, lhsFormat); (lhsFormat, rhsFormat) = (rhsFormat, lhsFormat);
} }
return lhsFormat.Format == Format.R8Unorm && rhsFormat.Format == Format.R8G8B8A8Unorm; return (lhsFormat.Format == Format.R8G8B8A8Unorm && rhsFormat.Format == Format.R32G32B32A32Float) ||
(lhsFormat.Format == Format.R8Unorm && rhsFormat.Format == Format.R8G8B8A8Unorm);
} }
/// <summary> /// <summary>

View File

@@ -709,8 +709,7 @@ namespace Ryujinx.Graphics.Gpu.Image
/// </summary> /// </summary>
/// <param name="texture">The texture that has been modified</param> /// <param name="texture">The texture that has been modified</param>
/// <param name="bound">True if this texture is being bound, false if unbound</param> /// <param name="bound">True if this texture is being bound, false if unbound</param>
/// <param name="setModified">Indicates if the modified flag should be set</param> public void SignalModifying(Texture texture, bool bound)
public void SignalModifying(Texture texture, bool bound, bool setModified)
{ {
ModifiedSequence = _context.GetModifiedSequence(); ModifiedSequence = _context.GetModifiedSequence();
@@ -722,7 +721,7 @@ namespace Ryujinx.Graphics.Gpu.Image
{ {
TextureGroupHandle group = _handles[baseHandle + i]; TextureGroupHandle group = _handles[baseHandle + i];
group.SignalModifying(bound, _context, setModified); group.SignalModifying(bound, _context);
} }
}); });
} }
@@ -993,26 +992,6 @@ namespace Ryujinx.Graphics.Gpu.Image
} }
} }
/// <summary>
/// The action to perform when a memory tracking handle is flipped to dirty.
/// This notifies overlapping textures that the memory needs to be synchronized.
/// </summary>
/// <param name="groupHandle">The handle that a dirty flag was set on</param>
private void DirtyAction(TextureGroupHandle groupHandle)
{
// Notify all textures that belong to this handle.
Storage.SignalGroupDirty();
lock (groupHandle.Overlaps)
{
foreach (Texture overlap in groupHandle.Overlaps)
{
overlap.SignalGroupDirty();
}
}
}
/// <summary> /// <summary>
/// Generate a CpuRegionHandle for a given address and size range in CPU VA. /// Generate a CpuRegionHandle for a given address and size range in CPU VA.
/// </summary> /// </summary>
@@ -1084,11 +1063,6 @@ namespace Ryujinx.Graphics.Gpu.Image
views, views,
result.ToArray()); result.ToArray());
foreach (RegionHandle handle in result)
{
handle.RegisterDirtyEvent(() => DirtyAction(groupHandle));
}
return groupHandle; return groupHandle;
} }
@@ -1360,11 +1334,6 @@ namespace Ryujinx.Graphics.Gpu.Image
var groupHandle = new TextureGroupHandle(this, 0, Storage.Size, _views, 0, 0, 0, _allOffsets.Length, cpuRegionHandles); var groupHandle = new TextureGroupHandle(this, 0, Storage.Size, _views, 0, 0, 0, _allOffsets.Length, cpuRegionHandles);
foreach (RegionHandle handle in cpuRegionHandles)
{
handle.RegisterDirtyEvent(() => DirtyAction(groupHandle));
}
handles = new TextureGroupHandle[] { groupHandle }; handles = new TextureGroupHandle[] { groupHandle };
} }
else else
@@ -1620,6 +1589,7 @@ namespace Ryujinx.Graphics.Gpu.Image
if ((ignore == null || !handle.HasDependencyTo(ignore)) && handle.Modified) if ((ignore == null || !handle.HasDependencyTo(ignore)) && handle.Modified)
{ {
handle.Modified = false; handle.Modified = false;
handle.DeferredCopy = null;
Storage.SignalModifiedDirty(); Storage.SignalModifiedDirty();
lock (handle.Overlaps) lock (handle.Overlaps)
@@ -1666,8 +1636,6 @@ namespace Ryujinx.Graphics.Gpu.Image
return; return;
} }
Storage.ModifiedSinceLastFlush = false;
// There is a small gap here where the action is removed but _actionRegistered is still 1. // There is a small gap here where the action is removed but _actionRegistered is still 1.
// In this case it will skip registering the action, but here we are already handling it, // In this case it will skip registering the action, but here we are already handling it,
// so there shouldn't be any issue as it's the same handler for all actions. // so there shouldn't be any issue as it's the same handler for all actions.

View File

@@ -152,6 +152,32 @@ namespace Ryujinx.Graphics.Gpu.Image
// Linear textures are presumed to be used for readback initially. // Linear textures are presumed to be used for readback initially.
_flushBalance = FlushBalanceThreshold + FlushBalanceIncrement; _flushBalance = FlushBalanceThreshold + FlushBalanceIncrement;
} }
foreach (RegionHandle handle in handles)
{
handle.RegisterDirtyEvent(DirtyAction);
}
}
/// <summary>
/// The action to perform when a memory tracking handle is flipped to dirty.
/// This notifies overlapping textures that the memory needs to be synchronized.
/// </summary>
private void DirtyAction()
{
// Notify all textures that belong to this handle.
_group.Storage.SignalGroupDirty();
lock (Overlaps)
{
foreach (Texture overlap in Overlaps)
{
overlap.SignalGroupDirty();
}
}
DeferredCopy = null;
} }
/// <summary> /// <summary>
@@ -304,17 +330,9 @@ namespace Ryujinx.Graphics.Gpu.Image
/// </summary> /// </summary>
/// <param name="bound">True if this handle is being bound, false if unbound</param> /// <param name="bound">True if this handle is being bound, false if unbound</param>
/// <param name="context">The GPU context to register a sync action on</param> /// <param name="context">The GPU context to register a sync action on</param>
/// <param name="setModified">Indicates if the modified flag should be set</param> public void SignalModifying(bool bound, GpuContext context)
public void SignalModifying(bool bound, GpuContext context, bool setModified)
{ {
if (setModified) SignalModified(context);
{
SignalModified(context);
}
else
{
RegisterSync(context);
}
if (!bound && _syncActionRegistered && NextSyncCopies()) if (!bound && _syncActionRegistered && NextSyncCopies())
{ {
@@ -457,7 +475,6 @@ namespace Ryujinx.Graphics.Gpu.Image
public void DeferCopy(TextureGroupHandle copyFrom) public void DeferCopy(TextureGroupHandle copyFrom)
{ {
Modified = false; Modified = false;
DeferredCopy = copyFrom; DeferredCopy = copyFrom;
_group.Storage.SignalGroupDirty(); _group.Storage.SignalGroupDirty();
@@ -514,7 +531,7 @@ namespace Ryujinx.Graphics.Gpu.Image
{ {
existing.Other.Handle.CreateCopyDependency(this); existing.Other.Handle.CreateCopyDependency(this);
if (copyToOther) if (copyToOther && Modified)
{ {
existing.Other.Handle.DeferCopy(this); existing.Other.Handle.DeferCopy(this);
} }
@@ -558,10 +575,10 @@ namespace Ryujinx.Graphics.Gpu.Image
if (fromHandle != null) if (fromHandle != null)
{ {
// Only copy if the copy texture is still modified. // Only copy if the copy texture is still modified.
// It will be set as unmodified if new data is written from CPU, as the data previously in the texture will flush. // DeferredCopy will be set to null if new data is written from CPU (see the DirtyAction method).
// It will also set as unmodified if a copy is deferred to it. // It will also set as unmodified if a copy is deferred to it.
shouldCopy = fromHandle.Modified; shouldCopy = true;
if (fromHandle._bindCount == 0) if (fromHandle._bindCount == 0)
{ {

View File

@@ -20,8 +20,10 @@ namespace Ryujinx.Graphics.Gpu.Image
private readonly Texture[] _rtColors; private readonly Texture[] _rtColors;
private readonly ITexture[] _rtHostColors; private readonly ITexture[] _rtHostColors;
private readonly bool[] _rtColorsBound;
private Texture _rtDepthStencil; private Texture _rtDepthStencil;
private ITexture _rtHostDs; private ITexture _rtHostDs;
private bool _rtDsBound;
public int ClipRegionWidth { get; private set; } public int ClipRegionWidth { get; private set; }
public int ClipRegionHeight { get; private set; } public int ClipRegionHeight { get; private set; }
@@ -51,6 +53,7 @@ namespace Ryujinx.Graphics.Gpu.Image
_rtColors = new Texture[Constants.TotalRenderTargets]; _rtColors = new Texture[Constants.TotalRenderTargets];
_rtHostColors = new ITexture[Constants.TotalRenderTargets]; _rtHostColors = new ITexture[Constants.TotalRenderTargets];
_rtColorsBound = new bool[Constants.TotalRenderTargets];
} }
/// <summary> /// <summary>
@@ -154,7 +157,14 @@ namespace Ryujinx.Graphics.Gpu.Image
if (_rtColors[index] != color) if (_rtColors[index] != color)
{ {
_rtColors[index]?.SignalModifying(false); if (_rtColorsBound[index])
{
_rtColors[index]?.SignalModifying(false);
}
else
{
_rtColorsBound[index] = true;
}
if (color != null) if (color != null)
{ {
@@ -180,7 +190,14 @@ namespace Ryujinx.Graphics.Gpu.Image
if (_rtDepthStencil != depthStencil) if (_rtDepthStencil != depthStencil)
{ {
_rtDepthStencil?.SignalModifying(false); if (_rtDsBound)
{
_rtDepthStencil?.SignalModifying(false);
}
else
{
_rtDsBound = true;
}
if (depthStencil != null) if (depthStencil != null)
{ {
@@ -419,7 +436,12 @@ namespace Ryujinx.Graphics.Gpu.Image
if (dsTexture != null) if (dsTexture != null)
{ {
hostDsTexture = dsTexture.HostTexture; hostDsTexture = dsTexture.HostTexture;
dsTexture.ModifiedSinceLastFlush = true;
if (!_rtDsBound)
{
dsTexture.SignalModifying(true);
_rtDsBound = true;
}
} }
if (_rtHostDs != hostDsTexture) if (_rtHostDs != hostDsTexture)
@@ -436,7 +458,12 @@ namespace Ryujinx.Graphics.Gpu.Image
if (texture != null) if (texture != null)
{ {
hostTexture = texture.HostTexture; hostTexture = texture.HostTexture;
texture.ModifiedSinceLastFlush = true;
if (!_rtColorsBound[index])
{
texture.SignalModifying(true);
_rtColorsBound[index] = true;
}
} }
if (_rtHostColors[index] != hostTexture) if (_rtHostColors[index] != hostTexture)
@@ -466,6 +493,31 @@ namespace Ryujinx.Graphics.Gpu.Image
_context.Renderer.Pipeline.SetRenderTargets(_rtHostColors, _rtHostDs); _context.Renderer.Pipeline.SetRenderTargets(_rtHostColors, _rtHostDs);
} }
/// <summary>
/// Marks all currently bound render target textures as modified, and also makes them be set as modified again on next use.
/// </summary>
public void RefreshModifiedTextures()
{
Texture dsTexture = _rtDepthStencil;
if (dsTexture != null && _rtDsBound)
{
dsTexture.SignalModifying(false);
_rtDsBound = false;
}
for (int index = 0; index < _rtColors.Length; index++)
{
Texture texture = _rtColors[index];
if (texture != null && _rtColorsBound[index])
{
texture.SignalModifying(false);
_rtColorsBound[index] = false;
}
}
}
/// <summary> /// <summary>
/// Forces the texture and sampler pools to be re-loaded from the cache on next use. /// Forces the texture and sampler pools to be re-loaded from the cache on next use.
/// </summary> /// </summary>
@@ -502,11 +554,19 @@ namespace Ryujinx.Graphics.Gpu.Image
for (int i = 0; i < _rtColors.Length; i++) for (int i = 0; i < _rtColors.Length; i++)
{ {
_rtColors[i]?.DecrementReferenceCount(); if (_rtColorsBound[i])
{
_rtColors[i]?.DecrementReferenceCount();
}
_rtColors[i] = null; _rtColors[i] = null;
} }
_rtDepthStencil?.DecrementReferenceCount(); if (_rtDsBound)
{
_rtDepthStencil?.DecrementReferenceCount();
}
_rtDepthStencil = null; _rtDepthStencil = null;
} }
} }

View File

@@ -430,7 +430,7 @@ namespace Ryujinx.Graphics.Gpu.Image
if (!FormatTable.TryGetTextureFormat(format, srgb, out FormatInfo formatInfo)) if (!FormatTable.TryGetTextureFormat(format, srgb, out FormatInfo formatInfo))
{ {
if (gpuVa != 0 && (int)format > 0) if (gpuVa != 0 && format != 0)
{ {
Logger.Error?.Print(LogClass.Gpu, $"Invalid texture format 0x{format:X} (sRGB: {srgb})."); Logger.Error?.Print(LogClass.Gpu, $"Invalid texture format 0x{format:X} (sRGB: {srgb}).");
} }

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>

View File

@@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
private const ushort FileFormatVersionMajor = 1; private const ushort FileFormatVersionMajor = 1;
private const ushort FileFormatVersionMinor = 2; private const ushort FileFormatVersionMinor = 2;
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor; private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
private const uint CodeGenVersion = 5791; private const uint CodeGenVersion = 5957;
private const string SharedTocFileName = "shared.toc"; private const string SharedTocFileName = "shared.toc";
private const string SharedDataFileName = "shared.data"; private const string SharedDataFileName = "shared.data";

View File

@@ -37,10 +37,7 @@ namespace Ryujinx.Graphics.Gpu.Synchronization
/// <returns>The incremented value of the syncpoint</returns> /// <returns>The incremented value of the syncpoint</returns>
public uint IncrementSyncpoint(uint id) public uint IncrementSyncpoint(uint id)
{ {
if (id >= MaxHardwareSyncpoints) ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(id, (uint)MaxHardwareSyncpoints);
{
throw new ArgumentOutOfRangeException(nameof(id));
}
return _syncpoints[id].Increment(); return _syncpoints[id].Increment();
} }
@@ -53,10 +50,7 @@ namespace Ryujinx.Graphics.Gpu.Synchronization
/// <returns>The value of the syncpoint</returns> /// <returns>The value of the syncpoint</returns>
public uint GetSyncpointValue(uint id) public uint GetSyncpointValue(uint id)
{ {
if (id >= MaxHardwareSyncpoints) ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(id, (uint)MaxHardwareSyncpoints);
{
throw new ArgumentOutOfRangeException(nameof(id));
}
return _syncpoints[id].Value; return _syncpoints[id].Value;
} }
@@ -72,10 +66,7 @@ namespace Ryujinx.Graphics.Gpu.Synchronization
/// <returns>The created SyncpointWaiterHandle object or null if already past threshold</returns> /// <returns>The created SyncpointWaiterHandle object or null if already past threshold</returns>
public SyncpointWaiterHandle RegisterCallbackOnSyncpoint(uint id, uint threshold, Action<SyncpointWaiterHandle> callback) public SyncpointWaiterHandle RegisterCallbackOnSyncpoint(uint id, uint threshold, Action<SyncpointWaiterHandle> callback)
{ {
if (id >= MaxHardwareSyncpoints) ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(id, (uint)MaxHardwareSyncpoints);
{
throw new ArgumentOutOfRangeException(nameof(id));
}
return _syncpoints[id].RegisterCallback(threshold, callback); return _syncpoints[id].RegisterCallback(threshold, callback);
} }
@@ -88,10 +79,7 @@ namespace Ryujinx.Graphics.Gpu.Synchronization
/// <exception cref="System.ArgumentOutOfRangeException">Thrown when id >= MaxHardwareSyncpoints</exception> /// <exception cref="System.ArgumentOutOfRangeException">Thrown when id >= MaxHardwareSyncpoints</exception>
public void UnregisterCallback(uint id, SyncpointWaiterHandle waiterInformation) public void UnregisterCallback(uint id, SyncpointWaiterHandle waiterInformation)
{ {
if (id >= MaxHardwareSyncpoints) ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(id, (uint)MaxHardwareSyncpoints);
{
throw new ArgumentOutOfRangeException(nameof(id));
}
_syncpoints[id].UnregisterCallback(waiterInformation); _syncpoints[id].UnregisterCallback(waiterInformation);
} }
@@ -107,10 +95,7 @@ namespace Ryujinx.Graphics.Gpu.Synchronization
/// <returns>True if timed out</returns> /// <returns>True if timed out</returns>
public bool WaitOnSyncpoint(uint id, uint threshold, TimeSpan timeout) public bool WaitOnSyncpoint(uint id, uint threshold, TimeSpan timeout)
{ {
if (id >= MaxHardwareSyncpoints) ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(id, (uint)MaxHardwareSyncpoints);
{
throw new ArgumentOutOfRangeException(nameof(id));
}
// TODO: Remove this when GPU channel scheduling will be implemented. // TODO: Remove this when GPU channel scheduling will be implemented.
if (timeout == Timeout.InfiniteTimeSpan) if (timeout == Timeout.InfiniteTimeSpan)

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>

View File

@@ -69,10 +69,7 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
public Operand GetDest(int index) public Operand GetDest(int index)
{ {
if (index != 0) ArgumentOutOfRangeException.ThrowIfNotEqual(index, 0);
{
throw new ArgumentOutOfRangeException(nameof(index));
}
return _dest; return _dest;
} }

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -55,7 +55,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
continue; continue;
} }
if (bindlessHandle.AsgOp is not Operation handleCombineOp) if (!TryGetOperation(bindlessHandle.AsgOp, out Operation handleCombineOp))
{ {
continue; continue;
} }
@@ -199,9 +199,64 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
} }
} }
private static bool TryGetOperation(INode asgOp, out Operation outOperation)
{
if (asgOp is PhiNode phi)
{
// If we have a phi, let's check if all inputs are effectively the same value.
// If so, we can "see through" the phi and pick any of the inputs (since they are all the same).
Operand firstSrc = phi.GetSource(0);
for (int index = 1; index < phi.SourcesCount; index++)
{
if (!IsSameOperand(firstSrc, phi.GetSource(index)))
{
outOperation = null;
return false;
}
}
asgOp = firstSrc.AsgOp;
}
if (asgOp is Operation operation)
{
outOperation = operation;
return true;
}
outOperation = null;
return false;
}
private static bool IsSameOperand(Operand x, Operand y)
{
if (x.Type == y.Type && x.Type == OperandType.LocalVariable)
{
return x.AsgOp is Operation xOp &&
y.AsgOp is Operation yOp &&
xOp.Inst == Instruction.BitwiseOr &&
yOp.Inst == Instruction.BitwiseOr &&
AreBothEqualConstantBuffers(xOp.GetSource(0), yOp.GetSource(0)) &&
AreBothEqualConstantBuffers(xOp.GetSource(1), yOp.GetSource(1));
}
return false;
}
private static bool AreBothEqualConstantBuffers(Operand x, Operand y)
{
return x.Type == y.Type && x.Value == y.Value && x.Type == OperandType.ConstantBuffer;
}
private static Operand GetSourceForMaskedHandle(Operation asgOp, uint mask) private static Operand GetSourceForMaskedHandle(Operation asgOp, uint mask)
{ {
// Assume it was already checked that the operation is bitwise AND. // Assume it was already checked that the operation is bitwise AND.
Operand src0 = asgOp.GetSource(0); Operand src0 = asgOp.GetSource(0);
Operand src1 = asgOp.GetSource(1); Operand src1 = asgOp.GetSource(1);
@@ -210,6 +265,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
// We can't check if the mask matches here as both operands are from a constant buffer. // We can't check if the mask matches here as both operands are from a constant buffer.
// Be optimistic and assume it matches. Avoid constant buffer 1 as official drivers // Be optimistic and assume it matches. Avoid constant buffer 1 as official drivers
// uses this one to store compiler constants. // uses this one to store compiler constants.
return src0.GetCbufSlot() == 1 ? src1 : src0; return src0.GetCbufSlot() == 1 ? src1 : src0;
} }
else if (src0.Type == OperandType.ConstantBuffer && src1.Type == OperandType.Constant) else if (src0.Type == OperandType.ConstantBuffer && src1.Type == OperandType.Constant)

View File

@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>

View File

@@ -1,4 +1,5 @@
using System; using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics; using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86; using System.Runtime.Intrinsics.X86;
@@ -102,11 +103,11 @@ namespace Ryujinx.Graphics.Texture.Utils
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static RgbaColor32 operator <<(RgbaColor32 x, int shift) public static RgbaColor32 operator <<(RgbaColor32 x, [ConstantExpected] byte shift)
{ {
if (Sse2.IsSupported) if (Sse2.IsSupported)
{ {
return new RgbaColor32(Sse2.ShiftLeftLogical(x._color, (byte)shift)); return new RgbaColor32(Sse2.ShiftLeftLogical(x._color, shift));
} }
else else
{ {
@@ -115,11 +116,11 @@ namespace Ryujinx.Graphics.Texture.Utils
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static RgbaColor32 operator >>(RgbaColor32 x, int shift) public static RgbaColor32 operator >>(RgbaColor32 x, [ConstantExpected] byte shift)
{ {
if (Sse2.IsSupported) if (Sse2.IsSupported)
{ {
return new RgbaColor32(Sse2.ShiftRightLogical(x._color, (byte)shift)); return new RgbaColor32(Sse2.ShiftRightLogical(x._color, shift));
} }
else else
{ {

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -189,7 +189,7 @@ namespace Ryujinx.Graphics.Vulkan
PipelineStageFlags.AllCommandsBit, PipelineStageFlags.AllCommandsBit,
0, 0,
1, 1,
new ReadOnlySpan<MemoryBarrier>(memoryBarrier), new ReadOnlySpan<MemoryBarrier>(in memoryBarrier),
0, 0,
ReadOnlySpan<BufferMemoryBarrier>.Empty, ReadOnlySpan<BufferMemoryBarrier>.Empty,
0, 0,

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">

View File

@@ -33,9 +33,5 @@ namespace Ryujinx.Graphics.Vulkan
public VulkanException(string message, Exception innerException) : base(message, innerException) public VulkanException(string message, Exception innerException) : base(message, innerException)
{ {
} }
protected VulkanException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
} }
} }

View File

@@ -35,8 +35,6 @@ namespace Ryujinx.HLE.Exceptions
Request = context.Request; Request = context.Request;
} }
protected ServiceNotImplementedException(SerializationInfo info, StreamingContext context) : base(info, context) { }
public override string Message public override string Message
{ {
get get

View File

@@ -420,10 +420,7 @@ namespace Ryujinx.HLE.FileSystem
if (locationList != null) if (locationList != null)
{ {
if (locationList.Contains(entry)) locationList.Remove(entry);
{
locationList.Remove(entry);
}
locationList.AddLast(entry); locationList.AddLast(entry);
} }

View File

@@ -85,10 +85,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl
public void SetSyncpointMinEqualSyncpointMax(uint id) public void SetSyncpointMinEqualSyncpointMax(uint id)
{ {
if (id >= SynchronizationManager.MaxHardwareSyncpoints) ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(id, (uint)SynchronizationManager.MaxHardwareSyncpoints);
{
throw new ArgumentOutOfRangeException(nameof(id));
}
int value = (int)ReadSyncpointValue(id); int value = (int)ReadSyncpointValue(id);

View File

@@ -27,7 +27,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Types
int controlLength = message.Control == null ? 0 : message.Control.Length; int controlLength = message.Control == null ? 0 : message.Control.Length;
BsdSocketFlags flags = message.Flags; BsdSocketFlags flags = message.Flags;
if (!MemoryMarshal.TryWrite(rawData, ref msgNameLength)) if (!MemoryMarshal.TryWrite(rawData, in msgNameLength))
{ {
return LinuxError.EFAULT; return LinuxError.EFAULT;
} }
@@ -45,7 +45,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Types
rawData = rawData[msgNameLength..]; rawData = rawData[msgNameLength..];
} }
if (!MemoryMarshal.TryWrite(rawData, ref iovCount)) if (!MemoryMarshal.TryWrite(rawData, in iovCount))
{ {
return LinuxError.EFAULT; return LinuxError.EFAULT;
} }
@@ -58,7 +58,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Types
{ {
ulong iovLength = (ulong)message.Iov[index].Length; ulong iovLength = (ulong)message.Iov[index].Length;
if (!MemoryMarshal.TryWrite(rawData, ref iovLength)) if (!MemoryMarshal.TryWrite(rawData, in iovLength))
{ {
return LinuxError.EFAULT; return LinuxError.EFAULT;
} }
@@ -78,7 +78,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Types
} }
} }
if (!MemoryMarshal.TryWrite(rawData, ref controlLength)) if (!MemoryMarshal.TryWrite(rawData, in controlLength))
{ {
return LinuxError.EFAULT; return LinuxError.EFAULT;
} }
@@ -96,14 +96,14 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Types
rawData = rawData[controlLength..]; rawData = rawData[controlLength..];
} }
if (!MemoryMarshal.TryWrite(rawData, ref flags)) if (!MemoryMarshal.TryWrite(rawData, in flags))
{ {
return LinuxError.EFAULT; return LinuxError.EFAULT;
} }
rawData = rawData[sizeof(BsdSocketFlags)..]; rawData = rawData[sizeof(BsdSocketFlags)..];
if (!MemoryMarshal.TryWrite(rawData, ref message.Length)) if (!MemoryMarshal.TryWrite(rawData, in message.Length))
{ {
return LinuxError.EFAULT; return LinuxError.EFAULT;
} }

View File

@@ -654,7 +654,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres
} }
uint sentinel = 0; uint sentinel = 0;
MemoryMarshal.Write(data, ref sentinel); MemoryMarshal.Write(data, in sentinel);
data = data[sizeof(uint)..]; data = data[sizeof(uint)..];
return region.Memory.Span.Length - data.Length; return region.Memory.Span.Length - data.Length;

View File

@@ -94,7 +94,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres.Types
Header.ToNetworkOrder(); Header.ToNetworkOrder();
MemoryMarshal.Write(buffer, ref Header); MemoryMarshal.Write(buffer, in Header);
buffer = buffer[Unsafe.SizeOf<AddrInfoSerializedHeader>()..]; buffer = buffer[Unsafe.SizeOf<AddrInfoSerializedHeader>()..];
@@ -103,7 +103,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres.Types
AddrInfo4 socketAddress = SocketAddress.Value; AddrInfo4 socketAddress = SocketAddress.Value;
socketAddress.ToNetworkOrder(); socketAddress.ToNetworkOrder();
MemoryMarshal.Write(buffer, ref socketAddress); MemoryMarshal.Write(buffer, in socketAddress);
buffer = buffer[Unsafe.SizeOf<AddrInfo4>()..]; buffer = buffer[Unsafe.SizeOf<AddrInfo4>()..];
} }
@@ -117,7 +117,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres.Types
Array4<byte> rawIPv4Address = RawIPv4Address.Value; Array4<byte> rawIPv4Address = RawIPv4Address.Value;
AddrInfo4.RawIpv4AddressNetworkEndianSwap(ref rawIPv4Address); AddrInfo4.RawIpv4AddressNetworkEndianSwap(ref rawIPv4Address);
MemoryMarshal.Write(buffer, ref rawIPv4Address); MemoryMarshal.Write(buffer, in rawIPv4Address);
buffer = buffer[Unsafe.SizeOf<Array4<byte>>()..]; buffer = buffer[Unsafe.SizeOf<Array4<byte>>()..];
} }

View File

@@ -161,7 +161,7 @@ namespace Ryujinx.HLE.HOS.Services.Ssl.SslService
} }
else else
{ {
throw exception; throw;
} }
} }
finally finally
@@ -206,7 +206,7 @@ namespace Ryujinx.HLE.HOS.Services.Ssl.SslService
} }
else else
{ {
throw exception; throw;
} }
} }
finally finally

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<RuntimeIdentifiers>win10-x64;osx-x64;linux-x64</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>
@@ -34,7 +34,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="CommandLineParser" /> <PackageReference Include="CommandLineParser" />
<PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'win10-x64'" /> <PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'win-x64'" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>

View File

@@ -52,10 +52,7 @@ namespace Ryujinx.Memory.Range
{ {
if (HasSingleRange) if (HasSingleRange)
{ {
if (_singleRange.Size - offset < size) ArgumentOutOfRangeException.ThrowIfGreaterThan(size, _singleRange.Size - offset);
{
throw new ArgumentOutOfRangeException(nameof(size));
}
return new MultiRange(_singleRange.Address + offset, size); return new MultiRange(_singleRange.Address + offset, size);
} }
@@ -108,10 +105,7 @@ namespace Ryujinx.Memory.Range
{ {
if (HasSingleRange) if (HasSingleRange)
{ {
if (index != 0) ArgumentOutOfRangeException.ThrowIfNotEqual(index, 0);
{
throw new ArgumentOutOfRangeException(nameof(index));
}
return _singleRange; return _singleRange;
} }

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<Configurations>Debug;Release</Configurations> <Configurations>Debug;Release</Configurations>
</PropertyGroup> </PropertyGroup>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Configurations>Debug;Release</Configurations> <Configurations>Debug;Release</Configurations>
</PropertyGroup> </PropertyGroup>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>

View File

@@ -1,9 +0,0 @@
namespace Ryujinx.Ui.Common.Configuration
{
public enum ConfigurationLoadResult
{
Success = 0,
NotLoaded = 1,
MigratedFromPreVulkan = 1 << 8,
}
}

View File

@@ -5,6 +5,7 @@ using Ryujinx.Common.Configuration.Hid.Controller;
using Ryujinx.Common.Configuration.Hid.Keyboard; using Ryujinx.Common.Configuration.Hid.Keyboard;
using Ryujinx.Common.Configuration.Multiplayer; using Ryujinx.Common.Configuration.Multiplayer;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Graphics.Vulkan;
using Ryujinx.Ui.Common.Configuration.System; using Ryujinx.Ui.Common.Configuration.System;
using Ryujinx.Ui.Common.Configuration.Ui; using Ryujinx.Ui.Common.Configuration.Ui;
using Ryujinx.Ui.Common.Helper; using Ryujinx.Ui.Common.Helper;
@@ -763,7 +764,7 @@ namespace Ryujinx.Ui.Common.Configuration
Graphics.ResScaleCustom.Value = 1.0f; Graphics.ResScaleCustom.Value = 1.0f;
Graphics.MaxAnisotropy.Value = -1.0f; Graphics.MaxAnisotropy.Value = -1.0f;
Graphics.AspectRatio.Value = AspectRatio.Fixed16x9; Graphics.AspectRatio.Value = AspectRatio.Fixed16x9;
Graphics.GraphicsBackend.Value = OperatingSystem.IsMacOS() ? GraphicsBackend.Vulkan : GraphicsBackend.OpenGl; Graphics.GraphicsBackend.Value = DefaultGraphicsBackend();
Graphics.PreferredGpu.Value = ""; Graphics.PreferredGpu.Value = "";
Graphics.ShadersDumpPath.Value = ""; Graphics.ShadersDumpPath.Value = "";
Logger.EnableDebug.Value = false; Logger.EnableDebug.Value = false;
@@ -907,7 +908,7 @@ namespace Ryujinx.Ui.Common.Configuration
}; };
} }
public ConfigurationLoadResult Load(ConfigurationFileFormat configurationFileFormat, string configurationFilePath) public void Load(ConfigurationFileFormat configurationFileFormat, string configurationFilePath)
{ {
bool configurationFileUpdated = false; bool configurationFileUpdated = false;
@@ -916,12 +917,8 @@ namespace Ryujinx.Ui.Common.Configuration
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Unsupported configuration version {configurationFileFormat.Version}, loading default."); Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Unsupported configuration version {configurationFileFormat.Version}, loading default.");
LoadDefault(); LoadDefault();
return ConfigurationLoadResult.NotLoaded;
} }
ConfigurationLoadResult result = ConfigurationLoadResult.Success;
if (configurationFileFormat.Version < 2) if (configurationFileFormat.Version < 2)
{ {
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 2."); Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 2.");
@@ -1336,8 +1333,6 @@ namespace Ryujinx.Ui.Common.Configuration
configurationFileFormat.GraphicsBackend = GraphicsBackend.OpenGl; configurationFileFormat.GraphicsBackend = GraphicsBackend.OpenGl;
result |= ConfigurationLoadResult.MigratedFromPreVulkan;
configurationFileUpdated = true; configurationFileUpdated = true;
} }
@@ -1535,8 +1530,18 @@ namespace Ryujinx.Ui.Common.Configuration
Ryujinx.Common.Logging.Logger.Notice.Print(LogClass.Application, $"Configuration file updated to version {ConfigurationFileFormat.CurrentVersion}"); Ryujinx.Common.Logging.Logger.Notice.Print(LogClass.Application, $"Configuration file updated to version {ConfigurationFileFormat.CurrentVersion}");
} }
}
return result; private static GraphicsBackend DefaultGraphicsBackend()
{
// Any system running macOS or returning any amount of valid Vulkan devices should default to Vulkan.
// Checks for if the Vulkan version and featureset is compatible should be performed within VulkanRenderer.
if (OperatingSystem.IsMacOS() || VulkanRenderer.GetPhysicalDevices().Length > 0)
{
return GraphicsBackend.Vulkan;
}
return GraphicsBackend.OpenGl;
} }
private static void LogValueChange<T>(ReactiveEventArgs<T> eventArgs, string valueName) private static void LogValueChange<T>(ReactiveEventArgs<T> eventArgs, string valueName)

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>
@@ -62,6 +62,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" /> <ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
<ProjectReference Include="..\Ryujinx.HLE\Ryujinx.HLE.csproj" /> <ProjectReference Include="..\Ryujinx.HLE\Ryujinx.HLE.csproj" />
<ProjectReference Include="..\Ryujinx.Graphics.Vulkan\Ryujinx.Graphics.Vulkan.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -177,8 +177,6 @@ namespace Ryujinx
? appDataConfigurationPath ? appDataConfigurationPath
: null; : null;
bool showVulkanPrompt = false;
if (ConfigurationPath == null) if (ConfigurationPath == null)
{ {
// No configuration, we load the default values and save it to disk // No configuration, we load the default values and save it to disk
@@ -186,26 +184,17 @@ namespace Ryujinx
ConfigurationState.Instance.LoadDefault(); ConfigurationState.Instance.LoadDefault();
ConfigurationState.Instance.ToFileFormat().SaveConfig(ConfigurationPath); ConfigurationState.Instance.ToFileFormat().SaveConfig(ConfigurationPath);
showVulkanPrompt = true;
} }
else else
{ {
if (ConfigurationFileFormat.TryLoad(ConfigurationPath, out ConfigurationFileFormat configurationFileFormat)) if (ConfigurationFileFormat.TryLoad(ConfigurationPath, out ConfigurationFileFormat configurationFileFormat))
{ {
ConfigurationLoadResult result = ConfigurationState.Instance.Load(configurationFileFormat, ConfigurationPath); ConfigurationState.Instance.Load(configurationFileFormat, ConfigurationPath);
if ((result & ConfigurationLoadResult.MigratedFromPreVulkan) != 0)
{
showVulkanPrompt = true;
}
} }
else else
{ {
ConfigurationState.Instance.LoadDefault(); ConfigurationState.Instance.LoadDefault();
showVulkanPrompt = true;
Logger.Warning?.PrintMsg(LogClass.Application, $"Failed to load config! Loading the default config instead.\nFailed config location {ConfigurationPath}"); Logger.Warning?.PrintMsg(LogClass.Application, $"Failed to load config! Loading the default config instead.\nFailed config location {ConfigurationPath}");
} }
} }
@@ -216,12 +205,10 @@ namespace Ryujinx
if (CommandLineState.OverrideGraphicsBackend.ToLower() == "opengl") if (CommandLineState.OverrideGraphicsBackend.ToLower() == "opengl")
{ {
ConfigurationState.Instance.Graphics.GraphicsBackend.Value = GraphicsBackend.OpenGl; ConfigurationState.Instance.Graphics.GraphicsBackend.Value = GraphicsBackend.OpenGl;
showVulkanPrompt = false;
} }
else if (CommandLineState.OverrideGraphicsBackend.ToLower() == "vulkan") else if (CommandLineState.OverrideGraphicsBackend.ToLower() == "vulkan")
{ {
ConfigurationState.Instance.Graphics.GraphicsBackend.Value = GraphicsBackend.Vulkan; ConfigurationState.Instance.Graphics.GraphicsBackend.Value = GraphicsBackend.Vulkan;
showVulkanPrompt = false;
} }
} }
@@ -343,35 +330,6 @@ namespace Ryujinx
}, TaskContinuationOptions.OnlyOnFaulted); }, TaskContinuationOptions.OnlyOnFaulted);
} }
if (showVulkanPrompt)
{
var buttonTexts = new Dictionary<int, string>()
{
{ 0, "Yes (Vulkan)" },
{ 1, "No (OpenGL)" },
};
ResponseType response = GtkDialog.CreateCustomDialog(
"Ryujinx - Default graphics backend",
"Use Vulkan as default graphics backend?",
"Ryujinx now supports the Vulkan API. " +
"Vulkan greatly improves shader compilation performance, " +
"and fixes some graphical glitches; however, since it is a new feature, " +
"you may experience some issues that did not occur with OpenGL.\n\n" +
"Note that you will also lose any existing shader cache the first time you start a game " +
"on version 1.1.200 onwards, because Vulkan required changes to the shader cache that makes it incompatible with previous versions.\n\n" +
"Would you like to set Vulkan as the default graphics backend? " +
"You can change this at any time on the settings window.",
buttonTexts,
MessageType.Question);
ConfigurationState.Instance.Graphics.GraphicsBackend.Value = response == 0
? GraphicsBackend.Vulkan
: GraphicsBackend.OpenGl;
ConfigurationState.Instance.ToFileFormat().SaveConfig(ConfigurationPath);
}
Application.Run(); Application.Run();
} }

View File

@@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<RuntimeIdentifiers>win10-x64;osx-x64;linux-x64</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>
@@ -25,7 +25,7 @@
<PackageReference Include="GtkSharp.Dependencies.osx" Condition="'$(RuntimeIdentifier)' == 'osx-x64' OR '$(RuntimeIdentifier)' == 'osx-arm64'" /> <PackageReference Include="GtkSharp.Dependencies.osx" Condition="'$(RuntimeIdentifier)' == 'osx-x64' OR '$(RuntimeIdentifier)' == 'osx-arm64'" />
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" /> <PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" />
<PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" /> <PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" />
<PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'win10-x64'" /> <PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'win-x64'" />
<PackageReference Include="OpenTK.Core" /> <PackageReference Include="OpenTK.Core" />
<PackageReference Include="OpenTK.Graphics" /> <PackageReference Include="OpenTK.Graphics" />
<PackageReference Include="SPB" /> <PackageReference Include="SPB" />

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
</Project> </Project>