Compare commits

..

14 Commits

Author SHA1 Message Date
Keaton
3a4af9b1d7 Merge 1909e5a615 into 6b402847d2 2025-03-11 14:43:51 +03:30
Daniel Nylander
6b402847d2 Updated Swedish in locales.json (#748) 2025-03-11 05:16:33 -05:00
Evan Husted
1909e5a615 Merge branch 'master' into revert-vulkan-barriers 2025-03-11 01:55:42 -05:00
shinyoyo
3b06f4cb78 Updated Zh-CN Simplified Chinese. (#737) 2025-03-11 01:35:19 -05:00
Evan Husted
cdf60eecc0 small readme update (test) 2025-03-11 06:06:10 +00:00
Evan Husted
1219f329c1 misc: chore: [ci skip] fully fix changelog urls for stable 2025-03-10 01:24:06 -05:00
Evan Husted
d5527f87cb UI: [ci skip] fix changelog urls on new release channel 2025-03-08 21:07:03 -06:00
Evan Husted
fc75dbc8b8 Update release.yml 2025-03-08 20:49:21 -06:00
Evan Husted
04361b864a stable release channel repo 2025-03-08 20:45:47 -06:00
rrondo
7271e7050d Ukrainian localization update (#755) 2025-03-07 23:28:25 -06:00
Evan Husted
1ca4484148 UI: Fix overlapping text when window is made too small 2025-03-06 04:31:28 -06:00
Evan Husted
056f56bc70 UI: Fix off-screen compat entry game names 2025-03-06 04:15:02 -06:00
Evan Husted
bda699f68e UI: Inline game/autoload dir & motion/rumble/led 2025-03-06 04:12:34 -06:00
KeatonTheBot
d9587ffa28 Revert "Vulkan: Feedback loop detection and barriers (#7226)"
This reverts commit ca59c3f499.
2025-02-26 15:38:52 -06:00
27 changed files with 404 additions and 852 deletions

View File

@@ -12,7 +12,8 @@ env:
RYUJINX_BASE_VERSION: "1.2" RYUJINX_BASE_VERSION: "1.2"
RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "release" RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "release"
RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "Ryubing" RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "Ryubing"
RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Ryujinx" RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO: "Ryujinx"
RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Stable-Releases"
RELEASE: 1 RELEASE: 1
jobs: jobs:
@@ -33,7 +34,7 @@ jobs:
script: | script: |
github.rest.git.createRef({ github.rest.git.createRef({
owner: "${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}", owner: "${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}",
repo: "${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}", repo: "${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}",
ref: 'refs/tags/${{ steps.version_info.outputs.build_version }}', ref: 'refs/tags/${{ steps.version_info.outputs.build_version }}',
sha: context.sha sha: context.sha
}) })
@@ -52,7 +53,7 @@ jobs:
| Linux ARM 64-bit | [Stable 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-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) | | Linux ARM 64-bit | [Stable 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-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) |
| macOS | [Stable 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-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) | | macOS | [Stable 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-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) |
**Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }} **Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}
omitBodyDuringUpdate: true omitBodyDuringUpdate: true
owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }} owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}
repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }} repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}
@@ -92,7 +93,7 @@ jobs:
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
shell: bash shell: bash
@@ -173,7 +174,7 @@ jobs:
| Linux ARM 64-bit | [Stable 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-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) | | Linux ARM 64-bit | [Stable 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-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) |
| macOS | [Stable 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-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) | | macOS | [Stable 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-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) |
**Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }} **Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}
omitBodyDuringUpdate: true omitBodyDuringUpdate: true
allowUpdates: true allowUpdates: true
replacesArtifacts: true replacesArtifacts: true
@@ -222,7 +223,7 @@ jobs:
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
shell: bash shell: bash

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/GreemDev/ryuassets/refs/heads/main/RyujinxApp_1024.png" alt="Ryujinx" > <img src="https://raw.githubusercontent.com/Ryubing/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/GreemDev/Ryujinx)](https://github.com/Ryubing/Ryujinx/releases/latest) [![Latest release](https://img.shields.io/github/v/release/Ryubing/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

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

@@ -37,9 +37,9 @@ namespace Ryujinx.Common
public static string GetChangelogUrl(Version currentVersion, Version newVersion) => public static string GetChangelogUrl(Version currentVersion, Version newVersion) =>
IsCanaryBuild IsCanaryBuild
? $"https://github.com/{ReleaseChannelOwner}/{ReleaseChannelSourceRepo}/compare/Canary-{currentVersion}...Canary-{newVersion}" ? $"https://github.com/{ReleaseChannelOwner}/{ReleaseChannelSourceRepo}/compare/Canary-{currentVersion}...Canary-{newVersion}"
: $"https://github.com/{ReleaseChannelOwner}/{ReleaseChannelSourceRepo}/releases/tag/{newVersion}"; : GetChangelogForVersion(newVersion);
public static string GetChangelogForVersion(Version version) => public static string GetChangelogForVersion(Version version) =>
$"https://github.com/{ReleaseChannelOwner}/{ReleaseChannelRepo}/releases/tag/{version}"; $"https://github.com/{ReleaseChannelOwner}/{ReleaseChannelRepo}/releases/{version}";
} }
} }

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

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

@@ -1664,7 +1664,7 @@
"pl_PL": "Rozszerzenie pliku: {0}", "pl_PL": "Rozszerzenie pliku: {0}",
"pt_BR": "Extensão: {0}", "pt_BR": "Extensão: {0}",
"ru_RU": "Расширение файла: {0}", "ru_RU": "Расширение файла: {0}",
"sv_SE": "Filänd: {0}", "sv_SE": "Filändelse: {0}",
"th_TH": "นามสกุลไฟล์: {0}", "th_TH": "นามสกุลไฟล์: {0}",
"tr_TR": "Dosya Uzantısı: {0}", "tr_TR": "Dosya Uzantısı: {0}",
"uk_UA": "Розширення файлу: {0}", "uk_UA": "Розширення файлу: {0}",
@@ -1789,7 +1789,7 @@
"pl_PL": "Rozszerzenie pliku", "pl_PL": "Rozszerzenie pliku",
"pt_BR": "Extensão", "pt_BR": "Extensão",
"ru_RU": "Расширение файла", "ru_RU": "Расширение файла",
"sv_SE": "Filänd", "sv_SE": "Filändelse",
"th_TH": "นามสกุลไฟล์", "th_TH": "นามสกุลไฟล์",
"tr_TR": "Dosya Uzantısı", "tr_TR": "Dosya Uzantısı",
"uk_UA": "Розширення файлу", "uk_UA": "Розширення файлу",
@@ -2767,8 +2767,8 @@
"sv_SE": "", "sv_SE": "",
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "", "uk_UA": "Створити користувацьку конфігурацію",
"zh_CN": "", "zh_CN": "创建自定义设置",
"zh_TW": "" "zh_TW": ""
} }
}, },
@@ -2792,8 +2792,8 @@
"sv_SE": "", "sv_SE": "",
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "", "uk_UA": "Редагувати користувацьку конфігурацію",
"zh_CN": "", "zh_CN": "编辑自定义设置",
"zh_TW": "" "zh_TW": ""
} }
}, },
@@ -2842,7 +2842,7 @@
"sv_SE": "Skapar en oberoende konfiguration för det aktuella spelet", "sv_SE": "Skapar en oberoende konfiguration för det aktuella spelet",
"th_TH": "สร้างการกำหนดค่าที่เป็นอิสระสำหรับเกมปัจจุบัน", "th_TH": "สร้างการกำหนดค่าที่เป็นอิสระสำหรับเกมปัจจุบัน",
"tr_TR": "Mevcut oyun için bağımsız bir yapılandırma oluşturur", "tr_TR": "Mevcut oyun için bağımsız bir yapılandırma oluşturur",
"uk_UA": "Створює незалежну конфігурацію для поточної гри", "uk_UA": "Створюйте незалежну конфігурацію для поточної гри",
"zh_CN": "为当前游戏创建独立的配置", "zh_CN": "为当前游戏创建独立的配置",
"zh_TW": "為當前遊戲創建獨立的配置" "zh_TW": "為當前遊戲創建獨立的配置"
} }
@@ -2867,8 +2867,8 @@
"sv_SE": "", "sv_SE": "",
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "", "uk_UA": "Відредагувати наявну індивідуальну конфігурацію для цієї гри.",
"zh_CN": "", "zh_CN": "编辑选定游戏的现存独立配置",
"zh_TW": "" "zh_TW": ""
} }
}, },
@@ -3442,7 +3442,7 @@
"sv_SE": "Användargränssnitt", "sv_SE": "Användargränssnitt",
"th_TH": "หน้าจอผู้ใช้", "th_TH": "หน้าจอผู้ใช้",
"tr_TR": "Kullancı Arayüzü", "tr_TR": "Kullancı Arayüzü",
"uk_UA": "Інтерфейс користувача", "uk_UA": "Інтерфейс",
"zh_CN": "用户界面", "zh_CN": "用户界面",
"zh_TW": "使用者介面" "zh_TW": "使用者介面"
} }
@@ -3817,7 +3817,7 @@
"sv_SE": "Inaktivera inmatning när fokus tappas", "sv_SE": "Inaktivera inmatning när fokus tappas",
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "", "uk_UA": "Вимкнути введення, якщо вікно неактивне",
"zh_CN": "在后台时禁用输入", "zh_CN": "在后台时禁用输入",
"zh_TW": "" "zh_TW": ""
} }
@@ -3842,8 +3842,8 @@
"sv_SE": "", "sv_SE": "",
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "", "uk_UA": "Показати оригінальний UI (Потрібен перезапуск)",
"zh_CN": "", "zh_CN": "显示原始 UI 样式 (需要重启)",
"zh_TW": "" "zh_TW": ""
} }
}, },
@@ -3867,8 +3867,8 @@
"sv_SE": "", "sv_SE": "",
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "", "uk_UA": "Показати старий інтерфейс Avalonia Ryujinx, який був у Ryujinx 1.1.1403. Ця опція активна за замовчуванням на всіх інших, окрім Windows платформах.\nПовернеться класична панель заголовка, а всі суттєві зміни інтерфейсу будуть скасовані, зокрема горизонтальне розміщення навігації в налаштуваннях.",
"zh_CN": "", "zh_CN": "显示旧的类似 Ryujinx 1.1.1403 的 Avalonia Ryujinx UI。在非 Windows 平台上默认启用此选项。\n经典样式的标题栏已回归并且恢复了对窗口布局的重大重构;例如在工具提示上方放置设置导航。",
"zh_TW": "" "zh_TW": ""
} }
}, },
@@ -4014,7 +4014,7 @@
"pl_PL": "", "pl_PL": "",
"pt_BR": "Carregar Automaticamente Pasta de DLC e Atualizações", "pt_BR": "Carregar Automaticamente Pasta de DLC e Atualizações",
"ru_RU": "Автозагрузка папки с DLC/Обновлениями", "ru_RU": "Автозагрузка папки с DLC/Обновлениями",
"sv_SE": "Läs automatisk in DLC/speluppdateringar", "sv_SE": "Läs automatiskt in DLC/speluppdateringar",
"th_TH": "โหลดไดเรกทอรี DLC/ไฟล์อัปเดต อัตโนมัติ", "th_TH": "โหลดไดเรกทอรี DLC/ไฟล์อัปเดต อัตโนมัติ",
"tr_TR": "", "tr_TR": "",
"uk_UA": "Автозавантаження теки DLC/Оновлень", "uk_UA": "Автозавантаження теки DLC/Оновлень",
@@ -4867,7 +4867,7 @@
"sv_SE": "Matcha systemtid", "sv_SE": "Matcha systemtid",
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "", "uk_UA": "Синхронізувати з системним годинником",
"zh_CN": "与系统时间同步", "zh_CN": "与系统时间同步",
"zh_TW": "" "zh_TW": ""
} }
@@ -7264,7 +7264,7 @@
"pl_PL": "Przyciski", "pl_PL": "Przyciski",
"pt_BR": "Botões", "pt_BR": "Botões",
"ru_RU": "Кнопки", "ru_RU": "Кнопки",
"sv_SE": "Knappar", "sv_SE": "Handlingsknappar",
"th_TH": "ปุ่มกด", "th_TH": "ปุ่มกด",
"tr_TR": "Tuşlar", "tr_TR": "Tuşlar",
"uk_UA": "Кнопки", "uk_UA": "Кнопки",
@@ -8467,7 +8467,7 @@
"sv_SE": "", "sv_SE": "",
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "", "uk_UA": "LED-підсвітка",
"zh_CN": "", "zh_CN": "",
"zh_TW": "" "zh_TW": ""
} }
@@ -8492,7 +8492,7 @@
"sv_SE": "Inaktivera", "sv_SE": "Inaktivera",
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "", "uk_UA": "Вимкнути",
"zh_CN": "关闭", "zh_CN": "关闭",
"zh_TW": "" "zh_TW": ""
} }
@@ -8517,7 +8517,7 @@
"sv_SE": "Regnbåge", "sv_SE": "Regnbåge",
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "", "uk_UA": "Веселка",
"zh_CN": "彩虹", "zh_CN": "彩虹",
"zh_TW": "" "zh_TW": ""
} }
@@ -8542,7 +8542,7 @@
"sv_SE": "Regnbågshastighet", "sv_SE": "Regnbågshastighet",
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "", "uk_UA": "Швидкість зміни кольорів",
"zh_CN": "彩虹滚动速度", "zh_CN": "彩虹滚动速度",
"zh_TW": "" "zh_TW": ""
} }
@@ -9167,7 +9167,7 @@
"sv_SE": "", "sv_SE": "",
"th_TH": "", "th_TH": "",
"tr_TR": "Esc", "tr_TR": "Esc",
"uk_UA": "", "uk_UA": "Esc",
"zh_CN": "Esc", "zh_CN": "Esc",
"zh_TW": "Esc 鍵" "zh_TW": "Esc 鍵"
} }
@@ -10867,7 +10867,7 @@
"sv_SE": "Diverse", "sv_SE": "Diverse",
"th_TH": "", "th_TH": "",
"tr_TR": "Diğer", "tr_TR": "Diğer",
"uk_UA": "", "uk_UA": "Інше",
"zh_CN": "截图键", "zh_CN": "截图键",
"zh_TW": "其他按鍵" "zh_TW": "其他按鍵"
} }
@@ -14914,7 +14914,7 @@
"pl_PL": "Wielowątkowość Backendu Graficznego:", "pl_PL": "Wielowątkowość Backendu Graficznego:",
"pt_BR": "Multi Enfileiramento do Renderizador Gráfico:", "pt_BR": "Multi Enfileiramento do Renderizador Gráfico:",
"ru_RU": "Многопоточность графического бэкенда:", "ru_RU": "Многопоточность графического бэкенда:",
"sv_SE": "Multithreading för grafikbakände:", "sv_SE": "Multitrådning för grafikbakände:",
"th_TH": "มัลติเธรด กราฟิกเบื้องหลัง:", "th_TH": "มัลติเธรด กราฟิกเบื้องหลัง:",
"tr_TR": "Grafik Backend Multithreading:", "tr_TR": "Grafik Backend Multithreading:",
"uk_UA": "Багатопотоковість графічного сервера:", "uk_UA": "Багатопотоковість графічного сервера:",
@@ -17692,7 +17692,7 @@
"sv_SE": "Ändra ljudvolym", "sv_SE": "Ändra ljudvolym",
"th_TH": "ปรับระดับเสียง", "th_TH": "ปรับระดับเสียง",
"tr_TR": "Ses seviyesini değiştirir", "tr_TR": "Ses seviyesini değiştirir",
"uk_UA": "Змінити гучність звуку", "uk_UA": "Регулювання гучності",
"zh_CN": "调节音量", "zh_CN": "调节音量",
"zh_TW": "調節音量" "zh_TW": "調節音量"
} }
@@ -18714,7 +18714,7 @@
"pl_PL": "", "pl_PL": "",
"pt_BR": "Não Reduzido", "pt_BR": "Não Reduzido",
"ru_RU": "Не обрезан", "ru_RU": "Не обрезан",
"sv_SE": "Inte optimerad", "sv_SE": "Orörd",
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "Необрізані", "uk_UA": "Необрізані",
@@ -19592,7 +19592,7 @@
"sv_SE": "Alla tangentbord", "sv_SE": "Alla tangentbord",
"th_TH": "คีย์บอร์ดทั้งหมด", "th_TH": "คีย์บอร์ดทั้งหมด",
"tr_TR": "Tüm Klavyeler", "tr_TR": "Tüm Klavyeler",
"uk_UA": "Всі клавіатури", "uk_UA": "Усі клавіатури",
"zh_CN": "所有键盘", "zh_CN": "所有键盘",
"zh_TW": "所有鍵盤" "zh_TW": "所有鍵盤"
} }
@@ -19742,7 +19742,7 @@
"sv_SE": "Snabbtangenter för tangentbord", "sv_SE": "Snabbtangenter för tangentbord",
"th_TH": "ปุ่มลัดของคีย์บอร์ด", "th_TH": "ปุ่มลัดของคีย์บอร์ด",
"tr_TR": "Klavye Kısayolları", "tr_TR": "Klavye Kısayolları",
"uk_UA": "Гарячі клавіші клавіатури", "uk_UA": "Гарячі клавіші",
"zh_CN": "快捷键", "zh_CN": "快捷键",
"zh_TW": "鍵盤快速鍵" "zh_TW": "鍵盤快速鍵"
} }
@@ -22467,7 +22467,7 @@
"sv_SE": "Tillämpar anti-aliasing på spelrenderaren.\n\nFXAA kommer att sudda det mesta av bilden, medan SMAA kommer att försöka hitta taggiga kanter och släta ut dem.\n\nRekommenderas inte att använda tillsammans med skalfiltret FSR.\n\nDet här alternativet kan ändras medan ett spel körs genom att klicka på \"Tillämpa\" nedan. Du kan helt enkelt flytta inställningsfönstret åt sidan och experimentera tills du hittar ditt föredragna utseende för ett spel.\n\nLämna som INGEN om du är osäker.", "sv_SE": "Tillämpar anti-aliasing på spelrenderaren.\n\nFXAA kommer att sudda det mesta av bilden, medan SMAA kommer att försöka hitta taggiga kanter och släta ut dem.\n\nRekommenderas inte att använda tillsammans med skalfiltret FSR.\n\nDet här alternativet kan ändras medan ett spel körs genom att klicka på \"Tillämpa\" nedan. Du kan helt enkelt flytta inställningsfönstret åt sidan och experimentera tills du hittar ditt föredragna utseende för ett spel.\n\nLämna som INGEN om du är osäker.",
"th_TH": "ใช้การลดรอยหยักกับการเรนเดอร์เกม\n\nFXAA จะเบลอภาพส่วนใหญ่ ในขณะที่ SMAA จะพยายามค้นหารอยหยักและปรับให้เรียบ\n\nไม่แนะนำให้ใช้ร่วมกับตัวกรองสเกล FSR\n\nตัวเลือกนี้สามารถเปลี่ยนแปลงได้ในขณะที่เกมกำลังทำงานอยู่โดยคลิก \"นำไปใช้\" ด้านล่าง คุณสามารถย้ายหน้าต่างการตั้งค่าไปด้านข้างและทดลองจนกว่าคุณจะพบรูปลักษณ์ที่คุณต้องการสำหรับเกม\n\nปล่อยไว้ที่ NONE หากไม่แน่ใจ", "th_TH": "ใช้การลดรอยหยักกับการเรนเดอร์เกม\n\nFXAA จะเบลอภาพส่วนใหญ่ ในขณะที่ SMAA จะพยายามค้นหารอยหยักและปรับให้เรียบ\n\nไม่แนะนำให้ใช้ร่วมกับตัวกรองสเกล FSR\n\nตัวเลือกนี้สามารถเปลี่ยนแปลงได้ในขณะที่เกมกำลังทำงานอยู่โดยคลิก \"นำไปใช้\" ด้านล่าง คุณสามารถย้ายหน้าต่างการตั้งค่าไปด้านข้างและทดลองจนกว่าคุณจะพบรูปลักษณ์ที่คุณต้องการสำหรับเกม\n\nปล่อยไว้ที่ NONE หากไม่แน่ใจ",
"tr_TR": "", "tr_TR": "",
"uk_UA": "Застосовує згладження до рендера гри.\n\nFXAA розмиє більшість зображення, а SMAA спробує знайти нерівні краї та згладити їх.\n\nНе рекомендується використовувати разом з фільтром масштабування FSR.\n\nЦю опцію можна міняти коли гра запущена кліком на \"Застосувати; ви можете відсунути вікно налаштувань і поекспериментувати з видом гри.\n\nЗалиште на \"Немає\", якщо не впевнені.", "uk_UA": "Застосовує згладження до рендера гри.\n\nFXAA розмиє більшість зображення, а SMAA спробує знайти нерівні краї та згладити їх.\n\nНе рекомендується використовувати разом з фільтром масштабування FSR.\n\nЦю опцію можна міняти коли гра запущена кліком на \"Застосувати; ви можете відсунути вікно налаштувань і поекспериментувати з видом гри.\n\nЗалиште \"Немає\", якщо не впевнені.",
"zh_CN": "抗锯齿是一种图形处理技术,用于减少图像边缘的锯齿状现象,使图像更加平滑。\n\nFXAA快速近似抗锯齿是一种性能开销相对较小的抗锯齿方法但可能会使得整体图像看起来有些模糊。\n\nSMAA增强型子像素抗锯齿则更加精细它会尝试找到锯齿边缘并平滑它们相比 FXAA 有更好的图像质量,但性能开销可能会稍大一些。\n\n如果开启了 FSRFidelityFX Super Resolution超级分辨率锐画技术来提高性能或图像质量不建议再启用抗锯齿因为它们会产生不必要的图形处理开销或者相互之间效果不协调。\n\n在游戏运行时通过点击下面的“应用”按钮可以使设置生效你可以将设置窗口移开并试验找到您喜欢的游戏画面效果。\n\n如果不确定请保持为“无”。", "zh_CN": "抗锯齿是一种图形处理技术,用于减少图像边缘的锯齿状现象,使图像更加平滑。\n\nFXAA快速近似抗锯齿是一种性能开销相对较小的抗锯齿方法但可能会使得整体图像看起来有些模糊。\n\nSMAA增强型子像素抗锯齿则更加精细它会尝试找到锯齿边缘并平滑它们相比 FXAA 有更好的图像质量,但性能开销可能会稍大一些。\n\n如果开启了 FSRFidelityFX Super Resolution超级分辨率锐画技术来提高性能或图像质量不建议再启用抗锯齿因为它们会产生不必要的图形处理开销或者相互之间效果不协调。\n\n在游戏运行时通过点击下面的“应用”按钮可以使设置生效你可以将设置窗口移开并试验找到您喜欢的游戏画面效果。\n\n如果不确定请保持为“无”。",
"zh_TW": "對遊戲繪製進行反鋸齒處理。\n\nFXAA 會模糊大部分圖像,而 SMAA 則會嘗試找出鋸齒邊緣並將其平滑化。\n\n不建議與 FSR 縮放濾鏡一起使用。\n\n此選項可在遊戲執行時透過點選下方的「套用」進行變更您只需將設定視窗移到一旁然後進行試驗直到找到您喜歡的遊戲效果。\n\n如果不確定請選擇無狀態。" "zh_TW": "對遊戲繪製進行反鋸齒處理。\n\nFXAA 會模糊大部分圖像,而 SMAA 則會嘗試找出鋸齒邊緣並將其平滑化。\n\n不建議與 FSR 縮放濾鏡一起使用。\n\n此選項可在遊戲執行時透過點選下方的「套用」進行變更您只需將設定視窗移到一旁然後進行試驗直到找到您喜歡的遊戲效果。\n\n如果不確定請選擇無狀態。"
} }
@@ -22542,7 +22542,7 @@
"sv_SE": "Välj det skalfilter som ska tillämpas vid användning av upplösningsskala.\n\nBilinjär fungerar bra för 3D-spel och är ett säkert standardalternativ.\n\nNärmast rekommenderas för pixel art-spel.\n\nFSR 1.0 är bara ett skarpningsfilter, rekommenderas inte för FXAA eller SMAA.\n\nOmrådesskalning rekommenderas vid nedskalning av upplösning som är större än utdatafönstret. Det kan användas för att uppnå en supersamplad anti-alias-effekt vid nedskalning med mer än 2x.\n\nDetta alternativ kan ändras medan ett spel körs genom att klicka på \"Tillämpa\" nedan. du kan helt enkelt flytta inställningsfönstret åt sidan och experimentera tills du hittar ditt föredragna utseende för ett spel.\n\nLämna som BILINJÄR om du är osäker.", "sv_SE": "Välj det skalfilter som ska tillämpas vid användning av upplösningsskala.\n\nBilinjär fungerar bra för 3D-spel och är ett säkert standardalternativ.\n\nNärmast rekommenderas för pixel art-spel.\n\nFSR 1.0 är bara ett skarpningsfilter, rekommenderas inte för FXAA eller SMAA.\n\nOmrådesskalning rekommenderas vid nedskalning av upplösning som är större än utdatafönstret. Det kan användas för att uppnå en supersamplad anti-alias-effekt vid nedskalning med mer än 2x.\n\nDetta alternativ kan ändras medan ett spel körs genom att klicka på \"Tillämpa\" nedan. du kan helt enkelt flytta inställningsfönstret åt sidan och experimentera tills du hittar ditt föredragna utseende för ett spel.\n\nLämna som BILINJÄR om du är osäker.",
"th_TH": "เลือกตัวกรองสเกลที่จะใช้เมื่อใช้สเกลความละเอียด\n\nBilinear ทำงานได้ดีกับเกม 3D และเป็นตัวเลือกเริ่มต้นที่ปลอดภัย\n\nแนะนำให้ใช้เกมภาพพิกเซลที่ใกล้เคียงที่สุด\n\nFSR 1.0 เป็นเพียงตัวกรองความคมชัด ไม่แนะนำให้ใช้กับ FXAA หรือ SMAA\n\nตัวเลือกนี้สามารถเปลี่ยนแปลงได้ในขณะที่เกมกำลังทำงานอยู่โดยคลิก \"นำไปใช้\" ด้านล่าง คุณสามารถย้ายหน้าต่างการตั้งค่าไปด้านข้างและทดลองจนกว่าคุณจะพบรูปลักษณ์ที่คุณต้องการสำหรับเกม", "th_TH": "เลือกตัวกรองสเกลที่จะใช้เมื่อใช้สเกลความละเอียด\n\nBilinear ทำงานได้ดีกับเกม 3D และเป็นตัวเลือกเริ่มต้นที่ปลอดภัย\n\nแนะนำให้ใช้เกมภาพพิกเซลที่ใกล้เคียงที่สุด\n\nFSR 1.0 เป็นเพียงตัวกรองความคมชัด ไม่แนะนำให้ใช้กับ FXAA หรือ SMAA\n\nตัวเลือกนี้สามารถเปลี่ยนแปลงได้ในขณะที่เกมกำลังทำงานอยู่โดยคลิก \"นำไปใช้\" ด้านล่าง คุณสามารถย้ายหน้าต่างการตั้งค่าไปด้านข้างและทดลองจนกว่าคุณจะพบรูปลักษณ์ที่คุณต้องการสำหรับเกม",
"tr_TR": "Choose the scaling filter that will be applied when using resolution scale.\n\nBilinear works well for 3D games and is a safe default option.\n\nNearest is recommended for pixel art games.\n\nFSR 1.0 is merely a sharpening filter, not recommended for use with FXAA or SMAA.\n\nThis option can be changed while a game is running by clicking \"Apply\" below; you can simply move the settings window aside and experiment until you find your preferred look for a game.\n\nLeave on BILINEAR if unsure.", "tr_TR": "Choose the scaling filter that will be applied when using resolution scale.\n\nBilinear works well for 3D games and is a safe default option.\n\nNearest is recommended for pixel art games.\n\nFSR 1.0 is merely a sharpening filter, not recommended for use with FXAA or SMAA.\n\nThis option can be changed while a game is running by clicking \"Apply\" below; you can simply move the settings window aside and experiment until you find your preferred look for a game.\n\nLeave on BILINEAR if unsure.",
"uk_UA": "Виберіть фільтр масштабування, що використається при збільшенні роздільної здатності.\n\n\"Білінійний\" добре виглядає в 3D іграх, і хороше налаштування за умовчуванням.\n\n\"Найближчий\" рекомендується для ігор з піксель-артом.\n\n\"FSR 1.0\" - фільтр різкості. Не варто використовувати разом з FXAA або SMAA.\n\nЦю опцію можна змінювати під час гри кліком на \"Застосувати\" нижче; ви можете відсунути вікно налаштувань і поекспериментувати з тим, як відображатиметься гра.\n\nЗалиште на \"Білінійний\", якщо не впевнені.", "uk_UA": "Виберіть фільтр масштабування, що використається при збільшенні роздільної здатності.\n\n\"Білінійний\" добре виглядає в 3D іграх, і хороше налаштування за умовчуванням.\n\n\"Найближчий\" рекомендується для ігор з піксель-артом.\n\n\"FSR 1.0\" - фільтр різкості. Не варто використовувати разом з FXAA або SMAA.\n\nЦю опцію можна змінювати під час гри кліком на \"Застосувати\" нижче; ви можете відсунути вікно налаштувань і поекспериментувати з тим, як відображатиметься гра.\n\nЗалиште \"Білінійний\", якщо не впевнені.",
"zh_CN": "选择在分辨率缩放时将使用的缩放过滤器。\n\nBilinear双线性过滤对于3D游戏效果较好是一个安全的默认选项。\n\nNearest最近邻过滤推荐用于像素艺术游戏。\n\nFSR超级分辨率锐画只是一个锐化过滤器不推荐与 FXAA 或 SMAA 抗锯齿一起使用。\n\nArea局部过滤当渲染分辨率大于窗口实际分辨率推荐该选项。该选项在渲染比例大于2.0的情况下,可以实现超采样的效果。\n\n在游戏运行时通过点击下面的“应用”按钮可以使设置生效你可以将设置窗口移开并试验找到您喜欢的游戏画面效果。\n\n如果不确定请保持为“Bilinear双线性过滤”。", "zh_CN": "选择在分辨率缩放时将使用的缩放过滤器。\n\nBilinear双线性过滤对于3D游戏效果较好是一个安全的默认选项。\n\nNearest最近邻过滤推荐用于像素艺术游戏。\n\nFSR超级分辨率锐画只是一个锐化过滤器不推荐与 FXAA 或 SMAA 抗锯齿一起使用。\n\nArea局部过滤当渲染分辨率大于窗口实际分辨率推荐该选项。该选项在渲染比例大于2.0的情况下,可以实现超采样的效果。\n\n在游戏运行时通过点击下面的“应用”按钮可以使设置生效你可以将设置窗口移开并试验找到您喜欢的游戏画面效果。\n\n如果不确定请保持为“Bilinear双线性过滤”。",
"zh_TW": "選擇使用解析度縮放時套用的縮放過濾器。\n\n雙線性 (Bilinear) 濾鏡適用於 3D 遊戲,是一個安全的預設選項。\n\n建議像素美術遊戲使用近鄰性 (Nearest) 濾鏡。\n\nFSR 1.0 只是一個銳化濾鏡,不建議與 FXAA 或 SMAA 一起使用。\n\n此選項可在遊戲執行時透過點選下方的「套用」進行變更您只需將設定視窗移到一旁然後進行試驗直到找到您喜歡的遊戲效果。\n\n如果不確定請保持雙線性 (Bilinear) 狀態。" "zh_TW": "選擇使用解析度縮放時套用的縮放過濾器。\n\n雙線性 (Bilinear) 濾鏡適用於 3D 遊戲,是一個安全的預設選項。\n\n建議像素美術遊戲使用近鄰性 (Nearest) 濾鏡。\n\nFSR 1.0 只是一個銳化濾鏡,不建議與 FXAA 或 SMAA 一起使用。\n\n此選項可在遊戲執行時透過點選下方的「套用」進行變更您只需將設定視窗移到一旁然後進行試驗直到找到您喜歡的遊戲效果。\n\n如果不確定請保持雙線性 (Bilinear) 狀態。"
} }
@@ -23867,8 +23867,8 @@
"sv_SE": "", "sv_SE": "",
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "", "uk_UA": "Список сумісності — {0} ігор",
"zh_CN": "", "zh_CN": "兼容性列表 - {0} 条",
"zh_TW": "" "zh_TW": ""
} }
}, },
@@ -23942,8 +23942,8 @@
"sv_SE": "", "sv_SE": "",
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "", "uk_UA": "Шукати серед {0} перевірених ігор...",
"zh_CN": "", "zh_CN": "搜索 {0} 兼容性条目...",
"zh_TW": "" "zh_TW": ""
} }
}, },
@@ -24017,7 +24017,7 @@
"sv_SE": "Spelbart", "sv_SE": "Spelbart",
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "Оптимально", "uk_UA": "Справна",
"zh_CN": "可游玩", "zh_CN": "可游玩",
"zh_TW": "可暢順遊玩" "zh_TW": "可暢順遊玩"
} }
@@ -24267,8 +24267,8 @@
"sv_SE": "", "sv_SE": "",
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "", "uk_UA": "Власна конфігурація",
"zh_CN": "", "zh_CN": "自定义配置",
"zh_TW": "" "zh_TW": ""
} }
}, },
@@ -24292,8 +24292,8 @@
"sv_SE": "", "sv_SE": "",
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "", "uk_UA": "(Глобальні)",
"zh_CN": "", "zh_CN": "(全局)",
"zh_TW": "" "zh_TW": ""
} }
}, },

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

@@ -4,10 +4,10 @@
xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup" xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls" xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels.Input" xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels.Input"
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers" xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
xmlns:pt="using:Projektanker.Icons.Avalonia"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
d:DesignHeight="800" d:DesignHeight="800"
@@ -507,65 +507,49 @@
CornerRadius="5" CornerRadius="5"
VerticalAlignment="Bottom" VerticalAlignment="Bottom"
HorizontalAlignment="Stretch"> HorizontalAlignment="Stretch">
<Grid ColumnDefinitions="*,Auto"> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<CheckBox <StackPanel Orientation="Vertical" Spacing="5">
Margin="10" <CheckBox
MinWidth="0" Margin="10, 10, 10, 0"
Grid.Column="0" MinWidth="0"
IsChecked="{Binding Config.EnableMotion, Mode=TwoWay}"> IsChecked="{Binding Config.EnableMotion, Mode=TwoWay}">
<TextBlock Text="{ext:Locale ControllerSettingsMotion}" /> <TextBlock Text="{ext:Locale ControllerSettingsMotion}" />
</CheckBox> </CheckBox>
<Button <Button
Margin="10" Margin="10, 0, 10, 10"
Grid.Column="1" Command="{Binding ShowMotionConfig}">
Command="{Binding ShowMotionConfig}"> <pt:Icon Value="fa-solid fa-gear" />
<TextBlock Text="{ext:Locale ControllerSettingsConfigureGeneral}" /> </Button>
</Button> </StackPanel>
</Grid> <controls:MiniVerticalSeparator Height="64"/>
</Border> <StackPanel Orientation="Vertical" Spacing="5">
<Border <CheckBox
BorderBrush="{DynamicResource ThemeControlBorderColor}" Margin="10, 10, 10, 0"
BorderThickness="1" MinWidth="0"
CornerRadius="5" IsChecked="{Binding Config.EnableRumble, Mode=TwoWay}">
HorizontalAlignment="Stretch" <TextBlock Text="{ext:Locale ControllerSettingsRumble}" />
Margin="0,-1,0,0"> </CheckBox>
<Grid ColumnDefinitions="*,Auto"> <Button
<CheckBox Margin="10, 0, 10, 10"
Margin="10" Command="{Binding ShowRumbleConfig}">
MinWidth="0" <pt:Icon Value="fa-solid fa-gear" />
Grid.Column="0" </Button>
IsChecked="{Binding Config.EnableRumble, Mode=TwoWay}"> </StackPanel>
<TextBlock Text="{ext:Locale ControllerSettingsRumble}" /> <controls:MiniVerticalSeparator Height="64" IsVisible="{Binding ParentModel.HasLed}"/>
</CheckBox> <StackPanel Orientation="Vertical" Spacing="5">
<Button <CheckBox
Margin="10" Margin="10, 10, 10, 0"
Grid.Column="1" MinWidth="0"
Command="{Binding ShowRumbleConfig}"> IsChecked="{Binding Config.EnableLedChanging, Mode=TwoWay}">
<TextBlock Text="{ext:Locale ControllerSettingsConfigureGeneral}" /> <TextBlock Text="{ext:Locale ControllerSettingsLed}" />
</Button> </CheckBox>
</Grid> <Button
</Border> Margin="10, 0, 10, 10"
<Border Command="{Binding ShowLedConfig}">
BorderBrush="{DynamicResource ThemeControlBorderColor}" <pt:Icon Value="fa-solid fa-gear" />
BorderThickness="1" </Button>
CornerRadius="5" </StackPanel>
HorizontalAlignment="Stretch" </StackPanel>
Margin="0,-1,0,0">
<Grid IsVisible="{Binding ParentModel.HasLed}" ColumnDefinitions="*,Auto">
<CheckBox
Margin="10, 10, 5, 10"
MinWidth="0"
Grid.Column="0"
IsChecked="{Binding Config.EnableLedChanging, Mode=TwoWay}">
<TextBlock Text="{ext:Locale ControllerSettingsLed}" />
</CheckBox>
<Button
Margin="10"
Grid.Column="1"
Command="{Binding ShowLedConfig}">
<TextBlock Text="{ext:Locale ControllerSettingsConfigureGeneral}" />
</Button>
</Grid>
</Border> </Border>
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>

View File

@@ -6,7 +6,6 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
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"
mc:Ignorable="d" mc:Ignorable="d"
x:DataType="viewModels:SettingsViewModel"> x:DataType="viewModels:SettingsViewModel">
<Design.DataContext> <Design.DataContext>
@@ -19,246 +18,265 @@
HorizontalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto"> VerticalScrollBarVisibility="Auto">
<Border Classes="settings"> <Border Classes="settings">
<StackPanel <Grid ColumnDefinitions="Auto,Auto,*" HorizontalAlignment="Stretch">
Margin="10" <StackPanel
HorizontalAlignment="Stretch" Grid.Column="0"
Orientation="Vertical" Margin="10"
Spacing="10"> HorizontalAlignment="Stretch"
<TextBlock Classes="h1" Text="{ext:Locale SettingsTabGeneralGeneral}" /> Orientation="Vertical"
<StackPanel Margin="10,0,0,0" Orientation="Vertical"> Spacing="10">
<CheckBox IsChecked="{Binding EnableDiscordIntegration}"> <TextBlock Classes="h1" Text="{ext:Locale SettingsTabGeneralGeneral}" />
<StackPanel Orientation="Horizontal"> <StackPanel Margin="10,0,0,0" Orientation="Vertical">
<CheckBox IsChecked="{Binding EnableDiscordIntegration}">
<StackPanel Orientation="Horizontal">
<TextBlock VerticalAlignment="Center"
ToolTip.Tip="{ext:Locale ToggleDiscordTooltip}"
Text="{ext:Locale SettingsTabGeneralEnableDiscordRichPresence}" />
</StackPanel>
</CheckBox>
<CheckBox
IsEnabled="{Binding !IsGameTitleNotNull}"
Opacity="{Binding PanelOpacity}"
IsChecked="{Binding ShowConfirmExit}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{ext:Locale SettingsTabGeneralShowConfirmExitDialog}" />
<TextBlock Classes="globalConfigMarker" IsVisible="{Binding IsGameTitleNotNull}" />
</StackPanel>
</CheckBox>
<CheckBox
IsEnabled="{Binding !IsGameTitleNotNull}"
Opacity="{Binding PanelOpacity}"
IsChecked="{Binding RememberWindowState}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{ext:Locale SettingsTabGeneralRememberWindowState}" />
<TextBlock Classes="globalConfigMarker" IsVisible="{Binding IsGameTitleNotNull}" />
</StackPanel>
</CheckBox>
<CheckBox
IsEnabled="{Binding !IsGameTitleNotNull}"
Opacity="{Binding PanelOpacity}"
IsChecked="{Binding ShowOldUI}"
ToolTip.Tip="{ext:Locale SettingsTabGeneralShowOldUIToolTip}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{ext:Locale SettingsTabGeneralShowOldUI}" />
<TextBlock Classes="globalConfigMarker" IsVisible="{Binding IsGameTitleNotNull}" />
</StackPanel>
</CheckBox>
<StackPanel
Margin="0, 15, 0, 0"
Orientation="Horizontal">
<TextBlock VerticalAlignment="Center" <TextBlock VerticalAlignment="Center"
ToolTip.Tip="{ext:Locale ToggleDiscordTooltip}" Text="{ext:Locale SettingsTabGeneralFocusLossType}"
Text="{ext:Locale SettingsTabGeneralEnableDiscordRichPresence}" /> Width="150" />
<ComboBox SelectedIndex="{Binding FocusLostActionType}"
HorizontalContentAlignment="Left"
MinWidth="100">
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabGeneralFocusLossTypeDoNothing}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabGeneralFocusLossTypeBlockInput}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabGeneralFocusLossTypeMuteAudio}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock
Text="{ext:Locale SettingsTabGeneralFocusLossTypeBlockInputAndMuteAudio}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabGeneralFocusLossTypePauseEmulation}" />
</ComboBoxItem>
</ComboBox>
</StackPanel> </StackPanel>
</CheckBox> <StackPanel
<CheckBox IsEnabled="{Binding !IsGameTitleNotNull}"
IsEnabled="{Binding !IsGameTitleNotNull}" Opacity="{Binding PanelOpacity}"
Opacity="{Binding PanelOpacity}" Margin="0, 15, 0, 0"
IsChecked="{Binding ShowConfirmExit}"> Orientation="Horizontal">
<StackPanel Orientation="Horizontal"> <TextBlock VerticalAlignment="Center"
<TextBlock Text="{ext:Locale SettingsTabGeneralShowConfirmExitDialog}" /> Text="{ext:Locale SettingsTabGeneralCheckUpdatesOnLaunch}"
Width="150" />
<ComboBox SelectedIndex="{Binding UpdateCheckerType}"
HorizontalContentAlignment="Left"
MinWidth="100">
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabGeneralCheckUpdatesOnLaunchOff}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock
Text="{ext:Locale SettingsTabGeneralCheckUpdatesOnLaunchPromptAtStartup}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabGeneralCheckUpdatesOnLaunchBackground}" />
</ComboBoxItem>
</ComboBox>
<TextBlock Classes="globalConfigMarker" IsVisible="{Binding IsGameTitleNotNull}" /> <TextBlock Classes="globalConfigMarker" IsVisible="{Binding IsGameTitleNotNull}" />
</StackPanel> </StackPanel>
</CheckBox> <StackPanel
<CheckBox Margin="0, 15, 0, 0"
IsEnabled="{Binding !IsGameTitleNotNull}" Orientation="Horizontal">
Opacity="{Binding PanelOpacity}" <TextBlock VerticalAlignment="Center"
IsChecked="{Binding RememberWindowState}"> Text="{ext:Locale SettingsTabGeneralHideCursor}"
<StackPanel Orientation="Horizontal"> Width="150" />
<TextBlock Text="{ext:Locale SettingsTabGeneralRememberWindowState}" /> <ComboBox SelectedIndex="{Binding HideCursor}"
HorizontalContentAlignment="Left"
MinWidth="100">
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabGeneralHideCursorNever}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabGeneralHideCursorOnIdle}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabGeneralHideCursorAlways}" />
</ComboBoxItem>
</ComboBox>
</StackPanel>
<StackPanel
IsEnabled="{Binding !IsGameTitleNotNull}"
Opacity="{Binding PanelOpacity}"
Margin="0, 15, 0, 10"
Orientation="Horizontal">
<TextBlock
VerticalAlignment="Center"
Text="{ext:Locale SettingsTabGeneralTheme}"
Width="150" />
<ComboBox SelectedIndex="{Binding BaseStyleIndex}"
HorizontalContentAlignment="Left"
MinWidth="100">
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabGeneralThemeAuto}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabGeneralThemeLight}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabGeneralThemeDark}" />
</ComboBoxItem>
</ComboBox>
<TextBlock Classes="globalConfigMarker" IsVisible="{Binding IsGameTitleNotNull}" /> <TextBlock Classes="globalConfigMarker" IsVisible="{Binding IsGameTitleNotNull}" />
</StackPanel> </StackPanel>
</CheckBox>
<CheckBox
IsEnabled="{Binding !IsGameTitleNotNull}"
Opacity="{Binding PanelOpacity}"
IsChecked="{Binding ShowOldUI}"
ToolTip.Tip="{ext:Locale SettingsTabGeneralShowOldUIToolTip}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{ext:Locale SettingsTabGeneralShowOldUI}" />
<TextBlock Classes="globalConfigMarker" IsVisible="{Binding IsGameTitleNotNull}" />
</StackPanel>
</CheckBox>
<StackPanel
Margin="0, 15, 0, 0"
Orientation="Horizontal">
<TextBlock VerticalAlignment="Center"
Text="{ext:Locale SettingsTabGeneralFocusLossType}"
Width="150" />
<ComboBox SelectedIndex="{Binding FocusLostActionType}"
HorizontalContentAlignment="Left"
MinWidth="100">
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabGeneralFocusLossTypeDoNothing}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabGeneralFocusLossTypeBlockInput}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabGeneralFocusLossTypeMuteAudio}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabGeneralFocusLossTypeBlockInputAndMuteAudio}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabGeneralFocusLossTypePauseEmulation}" />
</ComboBoxItem>
</ComboBox>
</StackPanel>
<StackPanel
IsEnabled="{Binding !IsGameTitleNotNull}"
Opacity="{Binding PanelOpacity}"
Margin="0, 15, 0, 0"
Orientation="Horizontal">
<TextBlock VerticalAlignment="Center"
Text="{ext:Locale SettingsTabGeneralCheckUpdatesOnLaunch}"
Width="150" />
<ComboBox SelectedIndex="{Binding UpdateCheckerType}"
HorizontalContentAlignment="Left"
MinWidth="100">
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabGeneralCheckUpdatesOnLaunchOff}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabGeneralCheckUpdatesOnLaunchPromptAtStartup}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabGeneralCheckUpdatesOnLaunchBackground}" />
</ComboBoxItem>
</ComboBox>
<TextBlock Classes="globalConfigMarker" IsVisible="{Binding IsGameTitleNotNull}"/>
</StackPanel>
<StackPanel
Margin="0, 15, 0, 0"
Orientation="Horizontal">
<TextBlock VerticalAlignment="Center"
Text="{ext:Locale SettingsTabGeneralHideCursor}"
Width="150" />
<ComboBox SelectedIndex="{Binding HideCursor}"
HorizontalContentAlignment="Left"
MinWidth="100">
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabGeneralHideCursorNever}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabGeneralHideCursorOnIdle}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabGeneralHideCursorAlways}" />
</ComboBoxItem>
</ComboBox>
</StackPanel>
<StackPanel
IsEnabled="{Binding !IsGameTitleNotNull}"
Opacity="{Binding PanelOpacity}"
Margin="0, 15, 0, 10"
Orientation="Horizontal">
<TextBlock
VerticalAlignment="Center"
Text="{ext:Locale SettingsTabGeneralTheme}"
Width="150" />
<ComboBox SelectedIndex="{Binding BaseStyleIndex}"
HorizontalContentAlignment="Left"
MinWidth="100">
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabGeneralThemeAuto}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabGeneralThemeLight}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabGeneralThemeDark}" />
</ComboBoxItem>
</ComboBox>
<TextBlock Classes="globalConfigMarker" IsVisible="{Binding IsGameTitleNotNull}"/>
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>
<Separator Height="1" /> <Border Grid.Column="1"
<StackPanel Orientation="Horizontal"> HorizontalAlignment="Center"
<TextBlock Classes="h1" Text="{ext:Locale SettingsTabGeneralGameDirectories}" /> VerticalAlignment="Top"
<TextBlock Classes="globalConfigMarker" IsVisible="{Binding IsGameTitleNotNull}"/> Margin="10, 10, 10, 0"
</StackPanel> Height="405"
BorderBrush="Gray"
Background="Gray"
Width="1" />
<StackPanel <StackPanel
IsEnabled="{Binding !IsGameTitleNotNull}" Margin="10"
Opacity="{Binding PanelOpacity}" Spacing="10"
Margin="10,0,0,0" Grid.Column="2"
HorizontalAlignment="Stretch" Orientation="Vertical" HorizontalAlignment="Stretch">
Orientation="Vertical"
Spacing="10">
<ListBox
Name="GameDirsList"
MinHeight="120"
ItemsSource="{Binding GameDirectories}">
<ListBox.Styles>
<Style Selector="ListBoxItem">
<Setter Property="Padding" Value="10" />
<Setter Property="Background" Value="{DynamicResource ListBoxBackground}" />
</Style>
</ListBox.Styles>
</ListBox>
<Grid HorizontalAlignment="Stretch" ColumnDefinitions="*,Auto,Auto">
<TextBox
Name="GameDirPathBox"
Margin="0"
ToolTip.Tip="{ext:Locale AddGameDirBoxTooltip}"
VerticalAlignment="Stretch" />
<Button
Name="AddGameDirButton"
Grid.Column="1"
MinWidth="90"
Margin="10,0,0,0"
ToolTip.Tip="{ext:Locale AddGameDirTooltip}">
<TextBlock HorizontalAlignment="Center"
Text="{ext:Locale SettingsTabGeneralAdd}" />
</Button>
<Button
Name="RemoveGameDirButton"
Grid.Column="2"
MinWidth="90"
Margin="10,0,0,0"
ToolTip.Tip="{ext:Locale RemoveGameDirTooltip}"
Click="RemoveGameDirButton_OnClick">
<TextBlock HorizontalAlignment="Center"
Text="{ext:Locale SettingsTabGeneralRemove}" />
</Button>
</Grid>
</StackPanel>
<Separator Height="1" />
<StackPanel Orientation="Vertical" Spacing="5">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<TextBlock Classes="h1" Text="{ext:Locale SettingsTabGeneralAutoloadDirectories}" /> <TextBlock Classes="h1" Text="{ext:Locale SettingsTabGeneralGameDirectories}" />
<TextBlock Classes="globalConfigMarker" IsVisible="{Binding IsGameTitleNotNull}"/> <TextBlock Classes="globalConfigMarker" IsVisible="{Binding IsGameTitleNotNull}" />
</StackPanel>
<StackPanel
IsEnabled="{Binding !IsGameTitleNotNull}"
Opacity="{Binding PanelOpacity}"
Margin="10,0,0,0"
HorizontalAlignment="Stretch"
Orientation="Vertical"
Spacing="10">
<ListBox
Name="GameDirsList"
MinHeight="120"
ItemsSource="{Binding GameDirectories}">
<ListBox.Styles>
<Style Selector="ListBoxItem">
<Setter Property="Padding" Value="10" />
<Setter Property="Background" Value="{DynamicResource ListBoxBackground}" />
</Style>
</ListBox.Styles>
</ListBox>
<Grid HorizontalAlignment="Stretch" ColumnDefinitions="*,Auto,Auto">
<TextBox
Name="GameDirPathBox"
Margin="0"
ToolTip.Tip="{ext:Locale AddGameDirBoxTooltip}"
VerticalAlignment="Stretch" />
<Button
Name="AddGameDirButton"
Grid.Column="1"
MinWidth="90"
Margin="10,0,0,0"
ToolTip.Tip="{ext:Locale AddGameDirTooltip}">
<TextBlock HorizontalAlignment="Center"
Text="{ext:Locale SettingsTabGeneralAdd}" />
</Button>
<Button
Name="RemoveGameDirButton"
Grid.Column="2"
MinWidth="90"
Margin="10,0,0,0"
ToolTip.Tip="{ext:Locale RemoveGameDirTooltip}"
Click="RemoveGameDirButton_OnClick">
<TextBlock HorizontalAlignment="Center"
Text="{ext:Locale SettingsTabGeneralRemove}" />
</Button>
</Grid>
</StackPanel>
<Separator Height="1" />
<StackPanel Orientation="Vertical" Spacing="5">
<StackPanel Orientation="Horizontal">
<TextBlock Classes="h1" Text="{ext:Locale SettingsTabGeneralAutoloadDirectories}" />
<TextBlock Classes="globalConfigMarker" IsVisible="{Binding IsGameTitleNotNull}" />
</StackPanel>
<TextBlock Foreground="{DynamicResource SecondaryTextColor}"
Text="{ext:Locale SettingsTabGeneralAutoloadNote}" />
</StackPanel>
<StackPanel
IsEnabled="{Binding !IsGameTitleNotNull}"
Opacity="{Binding PanelOpacity}"
Margin="10,0,0,0"
HorizontalAlignment="Stretch"
Orientation="Vertical"
Spacing="10">
<ListBox
Name="AutoloadDirsList"
MinHeight="100"
ItemsSource="{Binding AutoloadDirectories}">
<ListBox.Styles>
<Style Selector="ListBoxItem">
<Setter Property="Padding" Value="10" />
<Setter Property="Background" Value="{DynamicResource ListBoxBackground}" />
</Style>
</ListBox.Styles>
</ListBox>
<Grid HorizontalAlignment="Stretch" ColumnDefinitions="*,Auto,Auto">
<TextBox
Name="AutoloadDirPathBox"
Margin="0"
ToolTip.Tip="{ext:Locale AddAutoloadDirBoxTooltip}"
VerticalAlignment="Stretch" />
<Button
Name="AddAutoloadDirButton"
Grid.Column="1"
MinWidth="90"
Margin="10,0,0,0"
ToolTip.Tip="{ext:Locale AddAutoloadDirTooltip}">
<TextBlock HorizontalAlignment="Center"
Text="{ext:Locale SettingsTabGeneralAdd}" />
</Button>
<Button
Name="RemoveAutoloadDirButton"
Grid.Column="2"
MinWidth="90"
Margin="10,0,0,0"
ToolTip.Tip="{ext:Locale RemoveAutoloadDirTooltip}"
Click="RemoveAutoloadDirButton_OnClick">
<TextBlock HorizontalAlignment="Center"
Text="{ext:Locale SettingsTabGeneralRemove}" />
</Button>
</Grid>
</StackPanel> </StackPanel>
<TextBlock Foreground="{DynamicResource SecondaryTextColor}" Text="{ext:Locale SettingsTabGeneralAutoloadNote}" />
</StackPanel> </StackPanel>
<StackPanel </Grid>
IsEnabled="{Binding !IsGameTitleNotNull}"
Opacity="{Binding PanelOpacity}"
Margin="10,0,0,0"
HorizontalAlignment="Stretch"
Orientation="Vertical"
Spacing="10">
<ListBox
Name="AutoloadDirsList"
MinHeight="100"
ItemsSource="{Binding AutoloadDirectories}">
<ListBox.Styles>
<Style Selector="ListBoxItem">
<Setter Property="Padding" Value="10" />
<Setter Property="Background" Value="{DynamicResource ListBoxBackground}" />
</Style>
</ListBox.Styles>
</ListBox>
<Grid HorizontalAlignment="Stretch" ColumnDefinitions="*,Auto,Auto">
<TextBox
Name="AutoloadDirPathBox"
Margin="0"
ToolTip.Tip="{ext:Locale AddAutoloadDirBoxTooltip}"
VerticalAlignment="Stretch" />
<Button
Name="AddAutoloadDirButton"
Grid.Column="1"
MinWidth="90"
Margin="10,0,0,0"
ToolTip.Tip="{ext:Locale AddAutoloadDirTooltip}">
<TextBlock HorizontalAlignment="Center"
Text="{ext:Locale SettingsTabGeneralAdd}" />
</Button>
<Button
Name="RemoveAutoloadDirButton"
Grid.Column="2"
MinWidth="90"
Margin="10,0,0,0"
ToolTip.Tip="{ext:Locale RemoveAutoloadDirTooltip}"
Click="RemoveAutoloadDirButton_OnClick">
<TextBlock HorizontalAlignment="Center"
Text="{ext:Locale SettingsTabGeneralRemove}" />
</Button>
</Grid>
</StackPanel>
</StackPanel>
</Border> </Border>
</ScrollViewer> </ScrollViewer>
</UserControl> </UserControl>

View File

@@ -40,7 +40,7 @@
<DataTemplate DataType="{x:Type systems:CompatibilityEntry}"> <DataTemplate DataType="{x:Type systems:CompatibilityEntry}">
<Grid MinWidth="800" <Grid MinWidth="800"
Margin="10" Margin="10"
ColumnDefinitions="*,Auto,Auto,*" ColumnDefinitions="Auto,Auto,Auto,*"
Background="Transparent" Background="Transparent"
ToolTip.Tip="{Binding LocalizedLastUpdated}"> ToolTip.Tip="{Binding LocalizedLastUpdated}">
<TextBlock Grid.Column="0" <TextBlock Grid.Column="0"

View File

@@ -13,7 +13,7 @@
xmlns:helper="clr-namespace:Ryujinx.Common.Helper;assembly=Ryujinx.Common" xmlns:helper="clr-namespace:Ryujinx.Common.Helper;assembly=Ryujinx.Common"
Width="1100" Width="1100"
Height="910" Height="910"
MinWidth="800" MinWidth="1037"
MinHeight="480" MinHeight="480"
WindowStartupLocation="CenterOwner" WindowStartupLocation="CenterOwner"
x:DataType="viewModels:SettingsViewModel" x:DataType="viewModels:SettingsViewModel"

View File

@@ -13,7 +13,7 @@
xmlns:helper="clr-namespace:Ryujinx.Common.Helper;assembly=Ryujinx.Common" xmlns:helper="clr-namespace:Ryujinx.Common.Helper;assembly=Ryujinx.Common"
xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls" xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
Width="1100" Width="1100"
MinWidth="800" MinWidth="844"
MinHeight="480" MinHeight="480"
Title="{ext:WindowTitle Settings}" Title="{ext:WindowTitle Settings}"
WindowStartupLocation="CenterOwner" WindowStartupLocation="CenterOwner"

View File

@@ -31,8 +31,8 @@ namespace Ryujinx.Ava.UI.Windows
: NavigationViewPaneDisplayMode.Top; : NavigationViewPaneDisplayMode.Top;
Height = ConfigurationState.Instance.ShowOldUI Height = ConfigurationState.Instance.ShowOldUI
? 927 ? 906
: 993; // nav panel is put on top with custom title bar so account for new height : 954; // nav panel is put on top with custom title bar so account for new height
Load(); Load();
} }