Compare commits

..

8 Commits

Author SHA1 Message Date
jcm
773e239db7 Implement color space passthrough option (#5531)
Co-authored-by: jcm <butt@butts.com>
2023-08-07 18:54:05 +01:00
42750a74f8 Do not add more code after alpha test discard on fragment shader (#5529)
* Do not add more code after alpha test discard on fragment shader

* Shader cache version bump
2023-08-07 12:20:37 -03:00
3ab0a71c7b Fix PR build concurrency and stop auto assigning reviewers for draft PRs (#5519)
* build: Remove concurrency

It's called by checks anyway.

* Only assign reviewers for PRs that are ready for reviews
2023-08-06 23:25:02 +02:00
6e784e0aca GPU: Don't sync/bind index buffer when it's not in use (#5526)
* GPU: Don't sync/bind index buffer when it's not in use

Sometimes draws don't use an index buffer. It's not necessary to check or upload data for the current index buffer binding as it won't be used.

This fixes Pokemon: Legends Arceus updating a stale index buffer for every draw during its TFB pass, which was all non-indexed draws.

This probably didn't cost much on normal PCs, but it had a large impact on MacOS, which the macos1 release build avoided by mirroring index buffers (the PR currently does not). Needs buffer mirrors still for the rest of the performance.

There are additional cases where index buffers are bound or checked with non-indexed draws on the backend, but this one was straightforward to fix and has the largest impact. Testing is welcome to ensure nothing weird broke.

* Fix case with _rebind
2023-08-06 16:29:20 -03:00
5a0aa074b6 Enable VK_EXT_4444_formats (#5525) 2023-08-03 17:46:23 -03:00
93aa40f1fb nuget: bump DiscordRichPresence from 1.1.3.18 to 1.2.1.24 (#5515)
Bumps [DiscordRichPresence](https://github.com/Lachee/discord-rpc-csharp) from 1.1.3.18 to 1.2.1.24.
- [Release notes](https://github.com/Lachee/discord-rpc-csharp/releases)
- [Commits](https://github.com/Lachee/discord-rpc-csharp/commits)

---
updated-dependencies:
- dependency-name: DiscordRichPresence
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-02 17:19:38 +02:00
bedee64af5 Add slightly better workaround for current workflow issues (#5507)
* checks: Add retry logic to dotnet format style step as well

I can't imagine dotnet format whitespace ever segfaulting,
so hopefully it won't be needed there.

* checks: Replace bash scripts with unstable-commands action

* build: Add unstable-commands action for test step
2023-08-01 00:15:37 +02:00
86931cc3f1 (Graphics.Shader): Handle EmitSuatom constant dests and EmitSuld zero dest reg. (#5504)
* (Graphics.Shader): Handle EmitSuatom constant dests.

* Proper fix for EmitSuatom; fix EmitSuld.
2023-07-30 22:31:57 -03:00
24 changed files with 167 additions and 54 deletions

View File

@ -14,6 +14,13 @@ tab_width = 4
end_of_line = lf end_of_line = lf
insert_final_newline = true insert_final_newline = true
# JSON files
[*.json]
# Indentation and spacing
indent_size = 2
tab_width = 2
# C# files # C# files
[*.cs] [*.cs]

View File

@ -3,10 +3,6 @@ name: Build job
on: on:
workflow_call: workflow_call:
concurrency:
group: pr-builds-${{ github.event.number }}
cancel-in-progress: true
env: env:
POWERSHELL_TELEMETRY_OPTOUT: 1 POWERSHELL_TELEMETRY_OPTOUT: 1
DOTNET_CLI_TELEMETRY_OPTOUT: 1 DOTNET_CLI_TELEMETRY_OPTOUT: 1
@ -54,7 +50,11 @@ jobs:
run: dotnet build -c "${{ matrix.configuration }}" -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER run: dotnet build -c "${{ matrix.configuration }}" -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER
- name: Test - name: Test
run: dotnet test --no-build -c "${{ matrix.configuration }}" uses: TSRBerry/unstable-commands@v1
with:
commands: dotnet test --no-build -c "${{ matrix.configuration }}"
timeout-minutes: 10
retry-codes: 139
- name: Publish Ryujinx - name: Publish Ryujinx
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx --self-contained true run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx --self-contained true
@ -141,4 +141,4 @@ jobs:
with: with:
name: ava-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal name: ava-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
path: "publish_ava/*.tar.gz" path: "publish_ava/*.tar.gz"
if: github.event_name == 'pull_request' if: github.event_name == 'pull_request'

View File

@ -40,23 +40,23 @@ jobs:
run: | run: |
dotnet format whitespace --verify-no-changes --report ./whitespace-report.json -v d dotnet format whitespace --verify-no-changes --report ./whitespace-report.json -v d
# For some unknown reason this step sometimes fails with exit code 139 (segfault?),
# so in that case we'll try again (3 tries max).
- name: Run dotnet format style - name: Run dotnet format style
run: | uses: TSRBerry/unstable-commands@v1
dotnet format style --severity info --verify-no-changes --report ./style-report.json -v d with:
commands: dotnet format style --severity info --verify-no-changes --report ./style-report.json -v d
timeout-minutes: 5
retry-codes: 139
# For some reason this step sometimes fails with exit code 139 (segfault?), # For some unknown reason this step sometimes fails with exit code 139 (segfault?),
# so should that be the case we'll try again (3 tries max). # so in that case we'll try again (3 tries max).
- name: Run dotnet format analyzers - name: Run dotnet format analyzers
run: | uses: TSRBerry/unstable-commands@v1
attempt=0 with:
exit_code=139 commands: dotnet format analyzers --severity info --verify-no-changes --report ./analyzers-report.json -v d
until [ $attempt -ge 3 ] || [ $exit_code -ne 139 ]; do timeout-minutes: 5
((attempt+=1)) retry-codes: 139
exit_code=0
echo "Attempt: ${attempt}/3"
dotnet format analyzers --severity info --verify-no-changes --report ./analyzers-report.json -v d || exit_code=$?
done
exit $exit_code
- name: Upload report - name: Upload report
if: failure() if: failure()

View File

@ -28,6 +28,7 @@ jobs:
dot: true dot: true
- name: Assign reviewers - name: Assign reviewers
if: ! github.event.pull_request.draft
run: | run: |
pip3 install PyGithub pip3 install PyGithub
python3 .github/update_reviewers.py ${{ secrets.GITHUB_TOKEN }} ${{ github.repository }} ${{ github.event.pull_request.number }} .github/reviewers.yml python3 .github/update_reviewers.py ${{ secrets.GITHUB_TOKEN }} ${{ github.repository }} ${{ github.event.pull_request.number }} .github/reviewers.yml

View File

@ -12,7 +12,7 @@
<PackageVersion Include="Avalonia.Svg.Skia" Version="0.10.18" /> <PackageVersion Include="Avalonia.Svg.Skia" Version="0.10.18" />
<PackageVersion Include="CommandLineParser" Version="2.9.1" /> <PackageVersion Include="CommandLineParser" Version="2.9.1" />
<PackageVersion Include="Concentus" Version="1.1.7" /> <PackageVersion Include="Concentus" Version="1.1.7" />
<PackageVersion Include="DiscordRichPresence" Version="1.1.3.18" /> <PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" />
<PackageVersion Include="DynamicData" Version="7.14.2" /> <PackageVersion Include="DynamicData" Version="7.14.2" />
<PackageVersion Include="FluentAvaloniaUI" Version="1.4.5" /> <PackageVersion Include="FluentAvaloniaUI" Version="1.4.5" />
<PackageVersion Include="GtkSharp.Dependencies" Version="1.1.1" /> <PackageVersion Include="GtkSharp.Dependencies" Version="1.1.1" />

View File

@ -186,6 +186,7 @@ namespace Ryujinx.Ava
ConfigurationState.Instance.Graphics.AntiAliasing.Event += UpdateAntiAliasing; ConfigurationState.Instance.Graphics.AntiAliasing.Event += UpdateAntiAliasing;
ConfigurationState.Instance.Graphics.ScalingFilter.Event += UpdateScalingFilter; ConfigurationState.Instance.Graphics.ScalingFilter.Event += UpdateScalingFilter;
ConfigurationState.Instance.Graphics.ScalingFilterLevel.Event += UpdateScalingFilterLevel; ConfigurationState.Instance.Graphics.ScalingFilterLevel.Event += UpdateScalingFilterLevel;
ConfigurationState.Instance.Graphics.EnableColorSpacePassthrough.Event += UpdateColorSpacePassthrough;
ConfigurationState.Instance.Multiplayer.LanInterfaceId.Event += UpdateLanInterfaceIdState; ConfigurationState.Instance.Multiplayer.LanInterfaceId.Event += UpdateLanInterfaceIdState;
@ -229,6 +230,11 @@ namespace Ryujinx.Ava
_renderer.Window?.SetScalingFilterLevel(ConfigurationState.Instance.Graphics.ScalingFilterLevel.Value); _renderer.Window?.SetScalingFilterLevel(ConfigurationState.Instance.Graphics.ScalingFilterLevel.Value);
} }
private void UpdateColorSpacePassthrough(object sender, ReactiveEventArgs<bool> e)
{
_renderer.Window?.SetColorSpacePassthrough((bool)ConfigurationState.Instance.Graphics.EnableColorSpacePassthrough.Value);
}
private void ShowCursor() private void ShowCursor()
{ {
Dispatcher.UIThread.Post(() => Dispatcher.UIThread.Post(() =>
@ -461,6 +467,7 @@ namespace Ryujinx.Ava
ConfigurationState.Instance.Graphics.ScalingFilter.Event -= UpdateScalingFilter; ConfigurationState.Instance.Graphics.ScalingFilter.Event -= UpdateScalingFilter;
ConfigurationState.Instance.Graphics.ScalingFilterLevel.Event -= UpdateScalingFilterLevel; ConfigurationState.Instance.Graphics.ScalingFilterLevel.Event -= UpdateScalingFilterLevel;
ConfigurationState.Instance.Graphics.AntiAliasing.Event -= UpdateAntiAliasing; ConfigurationState.Instance.Graphics.AntiAliasing.Event -= UpdateAntiAliasing;
ConfigurationState.Instance.Graphics.EnableColorSpacePassthrough.Event -= UpdateColorSpacePassthrough;
_topLevel.PointerMoved -= TopLevel_PointerEnterOrMoved; _topLevel.PointerMoved -= TopLevel_PointerEnterOrMoved;
_topLevel.PointerEnter -= TopLevel_PointerEnterOrMoved; _topLevel.PointerEnter -= TopLevel_PointerEnterOrMoved;
@ -887,6 +894,7 @@ namespace Ryujinx.Ava
_renderer?.Window?.SetAntiAliasing((Graphics.GAL.AntiAliasing)ConfigurationState.Instance.Graphics.AntiAliasing.Value); _renderer?.Window?.SetAntiAliasing((Graphics.GAL.AntiAliasing)ConfigurationState.Instance.Graphics.AntiAliasing.Value);
_renderer?.Window?.SetScalingFilter((Graphics.GAL.ScalingFilter)ConfigurationState.Instance.Graphics.ScalingFilter.Value); _renderer?.Window?.SetScalingFilter((Graphics.GAL.ScalingFilter)ConfigurationState.Instance.Graphics.ScalingFilter.Value);
_renderer?.Window?.SetScalingFilterLevel(ConfigurationState.Instance.Graphics.ScalingFilterLevel.Value); _renderer?.Window?.SetScalingFilterLevel(ConfigurationState.Instance.Graphics.ScalingFilterLevel.Value);
_renderer?.Window?.SetColorSpacePassthrough(ConfigurationState.Instance.Graphics.EnableColorSpacePassthrough.Value);
Width = (int)RendererHost.Bounds.Width; Width = (int)RendererHost.Bounds.Width;
Height = (int)RendererHost.Bounds.Height; Height = (int)RendererHost.Bounds.Height;

View File

@ -620,6 +620,8 @@
"SettingsTabHotkeysVolumeDownHotkey": "Decrease Volume:", "SettingsTabHotkeysVolumeDownHotkey": "Decrease Volume:",
"SettingsEnableMacroHLE": "Enable Macro HLE", "SettingsEnableMacroHLE": "Enable Macro HLE",
"SettingsEnableMacroHLETooltip": "High-level emulation of GPU Macro code.\n\nImproves performance, but may cause graphical glitches in some games.\n\nLeave ON if unsure.", "SettingsEnableMacroHLETooltip": "High-level emulation of GPU Macro code.\n\nImproves performance, but may cause graphical glitches in some games.\n\nLeave ON if unsure.",
"SettingsEnableColorSpacePassthrough": "Color Space Passthrough",
"SettingsEnableColorSpacePassthroughTooltip": "Directs the Vulkan backend to pass through color information without specifying a color space. For users with wide gamut displays, this may result in more vibrant colors, at the cost of color correctness.",
"VolumeShort": "Vol", "VolumeShort": "Vol",
"UserProfilesManageSaves": "Manage Saves", "UserProfilesManageSaves": "Manage Saves",
"DeleteUserSave": "Do you want to delete user save for this game?", "DeleteUserSave": "Do you want to delete user save for this game?",

View File

@ -145,6 +145,7 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool EnableShaderCache { get; set; } public bool EnableShaderCache { get; set; }
public bool EnableTextureRecompression { get; set; } public bool EnableTextureRecompression { get; set; }
public bool EnableMacroHLE { get; set; } public bool EnableMacroHLE { get; set; }
public bool EnableColorSpacePassthrough { get; set; }
public bool EnableFileLog { get; set; } public bool EnableFileLog { get; set; }
public bool EnableStub { get; set; } public bool EnableStub { get; set; }
public bool EnableInfo { get; set; } public bool EnableInfo { get; set; }
@ -419,6 +420,7 @@ namespace Ryujinx.Ava.UI.ViewModels
EnableShaderCache = config.Graphics.EnableShaderCache; EnableShaderCache = config.Graphics.EnableShaderCache;
EnableTextureRecompression = config.Graphics.EnableTextureRecompression; EnableTextureRecompression = config.Graphics.EnableTextureRecompression;
EnableMacroHLE = config.Graphics.EnableMacroHLE; EnableMacroHLE = config.Graphics.EnableMacroHLE;
EnableColorSpacePassthrough = config.Graphics.EnableColorSpacePassthrough;
ResolutionScale = config.Graphics.ResScale == -1 ? 4 : config.Graphics.ResScale - 1; ResolutionScale = config.Graphics.ResScale == -1 ? 4 : config.Graphics.ResScale - 1;
CustomResolutionScale = config.Graphics.ResScaleCustom; CustomResolutionScale = config.Graphics.ResScaleCustom;
MaxAnisotropy = config.Graphics.MaxAnisotropy == -1 ? 0 : (int)(MathF.Log2(config.Graphics.MaxAnisotropy)); MaxAnisotropy = config.Graphics.MaxAnisotropy == -1 ? 0 : (int)(MathF.Log2(config.Graphics.MaxAnisotropy));
@ -506,6 +508,7 @@ namespace Ryujinx.Ava.UI.ViewModels
config.Graphics.EnableShaderCache.Value = EnableShaderCache; config.Graphics.EnableShaderCache.Value = EnableShaderCache;
config.Graphics.EnableTextureRecompression.Value = EnableTextureRecompression; config.Graphics.EnableTextureRecompression.Value = EnableTextureRecompression;
config.Graphics.EnableMacroHLE.Value = EnableMacroHLE; config.Graphics.EnableMacroHLE.Value = EnableMacroHLE;
config.Graphics.EnableColorSpacePassthrough.Value = EnableColorSpacePassthrough;
config.Graphics.ResScale.Value = ResolutionScale == 4 ? -1 : ResolutionScale + 1; config.Graphics.ResScale.Value = ResolutionScale == 4 ? -1 : ResolutionScale + 1;
config.Graphics.ResScaleCustom.Value = CustomResolutionScale; config.Graphics.ResScaleCustom.Value = CustomResolutionScale;
config.Graphics.MaxAnisotropy.Value = MaxAnisotropy == 0 ? -1 : MathF.Pow(2, MaxAnisotropy); config.Graphics.MaxAnisotropy.Value = MaxAnisotropy == 0 ? -1 : MathF.Pow(2, MaxAnisotropy);

View File

@ -73,6 +73,10 @@
ToolTip.Tip="{locale:Locale SettingsEnableMacroHLETooltip}"> ToolTip.Tip="{locale:Locale SettingsEnableMacroHLETooltip}">
<TextBlock Text="{locale:Locale SettingsEnableMacroHLE}" /> <TextBlock Text="{locale:Locale SettingsEnableMacroHLE}" />
</CheckBox> </CheckBox>
<CheckBox IsChecked="{Binding EnableColorSpacePassthrough}"
ToolTip.Tip="{locale:Locale SettingsEnableColorSpacePassthroughTooltip}">
<TextBlock Text="{locale:Locale SettingsEnableColorSpacePassthrough}" />
</CheckBox>
</StackPanel> </StackPanel>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<TextBlock VerticalAlignment="Center" <TextBlock VerticalAlignment="Center"

View File

@ -13,5 +13,6 @@ namespace Ryujinx.Graphics.GAL
void SetAntiAliasing(AntiAliasing antialiasing); void SetAntiAliasing(AntiAliasing antialiasing);
void SetScalingFilter(ScalingFilter type); void SetScalingFilter(ScalingFilter type);
void SetScalingFilterLevel(float level); void SetScalingFilterLevel(float level);
void SetColorSpacePassthrough(bool colorSpacePassThroughEnabled);
} }
} }

View File

@ -38,5 +38,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
public void SetScalingFilter(ScalingFilter type) { } public void SetScalingFilter(ScalingFilter type) { }
public void SetScalingFilterLevel(float level) { } public void SetScalingFilterLevel(float level) { }
public void SetColorSpacePassthrough(bool colorSpacePassthroughEnabled) { }
} }
} }

View File

@ -331,7 +331,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
UpdateShaderState(); UpdateShaderState();
} }
_channel.BufferManager.CommitGraphicsBindings(); _channel.BufferManager.CommitGraphicsBindings(_drawState.DrawIndexed);
} }
/// <summary> /// <summary>

View File

@ -67,6 +67,11 @@ namespace Ryujinx.Graphics.Gpu
/// Enables or disables recompression of compressed textures that are not natively supported by the host. /// Enables or disables recompression of compressed textures that are not natively supported by the host.
/// </summary> /// </summary>
public static bool EnableTextureRecompression = false; public static bool EnableTextureRecompression = false;
/// <summary>
/// Enables or disables color space passthrough, if available.
/// </summary>
public static bool EnableColorSpacePassthrough = false;
} }
#pragma warning restore CA2211 #pragma warning restore CA2211
} }

View File

@ -515,24 +515,32 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// Ensures that the graphics engine bindings are visible to the host GPU. /// Ensures that the graphics engine bindings are visible to the host GPU.
/// Note: this actually performs the binding using the host graphics API. /// Note: this actually performs the binding using the host graphics API.
/// </summary> /// </summary>
public void CommitGraphicsBindings() /// <param name="indexed">True if the index buffer is in use</param>
public void CommitGraphicsBindings(bool indexed)
{ {
var bufferCache = _channel.MemoryManager.Physical.BufferCache; var bufferCache = _channel.MemoryManager.Physical.BufferCache;
if (_indexBufferDirty || _rebind) if (indexed)
{ {
_indexBufferDirty = false; if (_indexBufferDirty || _rebind)
if (_indexBuffer.Address != 0)
{ {
BufferRange buffer = bufferCache.GetBufferRange(_indexBuffer.Address, _indexBuffer.Size); _indexBufferDirty = false;
_context.Renderer.Pipeline.SetIndexBuffer(buffer, _indexBuffer.Type); if (_indexBuffer.Address != 0)
{
BufferRange buffer = bufferCache.GetBufferRange(_indexBuffer.Address, _indexBuffer.Size);
_context.Renderer.Pipeline.SetIndexBuffer(buffer, _indexBuffer.Type);
}
}
else if (_indexBuffer.Address != 0)
{
bufferCache.SynchronizeBufferRange(_indexBuffer.Address, _indexBuffer.Size);
} }
} }
else if (_indexBuffer.Address != 0) else if (_rebind)
{ {
bufferCache.SynchronizeBufferRange(_indexBuffer.Address, _indexBuffer.Size); _indexBufferDirty = true;
} }
uint vbEnableMask = _vertexBuffersEnableMask; uint vbEnableMask = _vertexBuffersEnableMask;

View File

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

View File

@ -307,6 +307,8 @@ namespace Ryujinx.Graphics.OpenGL
_updateScalingFilter = true; _updateScalingFilter = true;
} }
public void SetColorSpacePassthrough(bool colorSpacePassthroughEnabled) { }
private void UpdateEffect() private void UpdateEffect()
{ {
if (_updateEffect) if (_updateEffect)

View File

@ -162,8 +162,10 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (op.Ccc == Ccc.T) if (op.Ccc == Ccc.T)
{ {
context.PrepareForReturn(); if (context.PrepareForReturn())
context.Return(); {
context.Return();
}
} }
else else
{ {
@ -174,8 +176,12 @@ namespace Ryujinx.Graphics.Shader.Instructions
{ {
Operand lblSkip = Label(); Operand lblSkip = Label();
context.BranchIfFalse(lblSkip, cond); context.BranchIfFalse(lblSkip, cond);
context.PrepareForReturn();
context.Return(); if (context.PrepareForReturn())
{
context.Return();
}
context.MarkLabel(lblSkip); context.MarkLabel(lblSkip);
} }
} }

View File

@ -218,7 +218,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
return context.Copy(Register(srcB++, RegisterType.Gpr)); return context.Copy(Register(srcB++, RegisterType.Gpr));
} }
Operand d = dest != RegisterConsts.RegisterZeroIndex ? Register(dest, RegisterType.Gpr) : null; Operand d = Register(dest, RegisterType.Gpr);
List<Operand> sourcesList = new(); List<Operand> sourcesList = new();
@ -304,6 +304,11 @@ namespace Ryujinx.Graphics.Shader.Instructions
bool byteAddress, bool byteAddress,
bool isBindless) bool isBindless)
{ {
if (srcB == RegisterConsts.RegisterZeroIndex)
{
return;
}
context.Config.SetUsedFeature(FeatureFlags.IntegerSampling); context.Config.SetUsedFeature(FeatureFlags.IntegerSampling);
SamplerType type = ConvertSamplerType(dimensions); SamplerType type = ConvertSamplerType(dimensions);

View File

@ -304,11 +304,11 @@ namespace Ryujinx.Graphics.Shader.Translation
PrepareForVertexReturn(); PrepareForVertexReturn();
} }
public void PrepareForReturn() public bool PrepareForReturn()
{ {
if (IsNonMain) if (IsNonMain)
{ {
return; return true;
} }
if (Config.LastInVertexPipeline && if (Config.LastInVertexPipeline &&
@ -383,13 +383,13 @@ namespace Ryujinx.Graphics.Shader.Translation
AlphaTestOp alphaTestOp = Config.GpuAccessor.QueryAlphaTestCompare(); AlphaTestOp alphaTestOp = Config.GpuAccessor.QueryAlphaTestCompare();
if (alphaTestOp != AlphaTestOp.Always && (Config.OmapTargets & 8) != 0) if (alphaTestOp != AlphaTestOp.Always)
{ {
if (alphaTestOp == AlphaTestOp.Never) if (alphaTestOp == AlphaTestOp.Never)
{ {
this.Discard(); this.Discard();
} }
else else if ((Config.OmapTargets & 8) != 0)
{ {
Instruction comparator = alphaTestOp switch Instruction comparator = alphaTestOp switch
{ {
@ -415,6 +415,12 @@ namespace Ryujinx.Graphics.Shader.Translation
} }
} }
// We don't need to output anything if alpha test always fails.
if (alphaTestOp == AlphaTestOp.Never)
{
return false;
}
int regIndexBase = 0; int regIndexBase = 0;
for (int rtIndex = 0; rtIndex < 8; rtIndex++) for (int rtIndex = 0; rtIndex < 8; rtIndex++)
@ -462,6 +468,8 @@ namespace Ryujinx.Graphics.Shader.Translation
} }
} }
} }
return true;
} }
private void GenerateAlphaToCoverageDitherDiscard() private void GenerateAlphaToCoverageDitherDiscard()

View File

@ -42,6 +42,7 @@ namespace Ryujinx.Graphics.Vulkan
"VK_NV_viewport_array2", "VK_NV_viewport_array2",
"VK_EXT_depth_clip_control", "VK_EXT_depth_clip_control",
"VK_KHR_portability_subset", // As per spec, we should enable this if present. "VK_KHR_portability_subset", // As per spec, we should enable this if present.
"VK_EXT_4444_formats",
}; };
private static readonly string[] _requiredExtensions = { private static readonly string[] _requiredExtensions = {

View File

@ -28,7 +28,7 @@ namespace Ryujinx.Graphics.Vulkan
private int _width; private int _width;
private int _height; private int _height;
private bool _vsyncEnabled; private bool _vsyncEnabled;
private bool _vsyncModeChanged; private bool _swapchainIsDirty;
private VkFormat _format; private VkFormat _format;
private AntiAliasing _currentAntiAliasing; private AntiAliasing _currentAntiAliasing;
private bool _updateEffect; private bool _updateEffect;
@ -38,6 +38,7 @@ namespace Ryujinx.Graphics.Vulkan
private float _scalingFilterLevel; private float _scalingFilterLevel;
private bool _updateScalingFilter; private bool _updateScalingFilter;
private ScalingFilter _currentScalingFilter; private ScalingFilter _currentScalingFilter;
private bool _colorSpacePassthroughEnabled;
public unsafe Window(VulkanRenderer gd, SurfaceKHR surface, PhysicalDevice physicalDevice, Device device) public unsafe Window(VulkanRenderer gd, SurfaceKHR surface, PhysicalDevice physicalDevice, Device device)
{ {
@ -60,7 +61,7 @@ namespace Ryujinx.Graphics.Vulkan
private void RecreateSwapchain() private void RecreateSwapchain()
{ {
var oldSwapchain = _swapchain; var oldSwapchain = _swapchain;
_vsyncModeChanged = false; _swapchainIsDirty = false;
for (int i = 0; i < _swapchainImageViews.Length; i++) for (int i = 0; i < _swapchainImageViews.Length; i++)
{ {
@ -106,7 +107,7 @@ namespace Ryujinx.Graphics.Vulkan
imageCount = capabilities.MaxImageCount; imageCount = capabilities.MaxImageCount;
} }
var surfaceFormat = ChooseSwapSurfaceFormat(surfaceFormats); var surfaceFormat = ChooseSwapSurfaceFormat(surfaceFormats, _colorSpacePassthroughEnabled);
var extent = ChooseSwapExtent(capabilities); var extent = ChooseSwapExtent(capabilities);
@ -178,22 +179,40 @@ namespace Ryujinx.Graphics.Vulkan
return new Auto<DisposableImageView>(new DisposableImageView(_gd.Api, _device, imageView)); return new Auto<DisposableImageView>(new DisposableImageView(_gd.Api, _device, imageView));
} }
private static SurfaceFormatKHR ChooseSwapSurfaceFormat(SurfaceFormatKHR[] availableFormats) private static SurfaceFormatKHR ChooseSwapSurfaceFormat(SurfaceFormatKHR[] availableFormats, bool colorSpacePassthroughEnabled)
{ {
if (availableFormats.Length == 1 && availableFormats[0].Format == VkFormat.Undefined) if (availableFormats.Length == 1 && availableFormats[0].Format == VkFormat.Undefined)
{ {
return new SurfaceFormatKHR(VkFormat.B8G8R8A8Unorm, ColorSpaceKHR.PaceSrgbNonlinearKhr); return new SurfaceFormatKHR(VkFormat.B8G8R8A8Unorm, ColorSpaceKHR.PaceSrgbNonlinearKhr);
} }
var formatToReturn = availableFormats[0];
foreach (var format in availableFormats) if (colorSpacePassthroughEnabled)
{ {
if (format.Format == VkFormat.B8G8R8A8Unorm && format.ColorSpace == ColorSpaceKHR.PaceSrgbNonlinearKhr) foreach (var format in availableFormats)
{ {
return format; if (format.Format == VkFormat.B8G8R8A8Unorm && format.ColorSpace == ColorSpaceKHR.SpacePassThroughExt)
{
formatToReturn = format;
break;
}
else if (format.Format == VkFormat.B8G8R8A8Unorm && format.ColorSpace == ColorSpaceKHR.PaceSrgbNonlinearKhr)
{
formatToReturn = format;
}
} }
} }
else
return availableFormats[0]; {
foreach (var format in availableFormats)
{
if (format.Format == VkFormat.B8G8R8A8Unorm && format.ColorSpace == ColorSpaceKHR.PaceSrgbNonlinearKhr)
{
formatToReturn = format;
break;
}
}
}
return formatToReturn;
} }
private static CompositeAlphaFlagsKHR ChooseCompositeAlpha(CompositeAlphaFlagsKHR supportedFlags) private static CompositeAlphaFlagsKHR ChooseCompositeAlpha(CompositeAlphaFlagsKHR supportedFlags)
@ -259,7 +278,7 @@ namespace Ryujinx.Graphics.Vulkan
if (acquireResult == Result.ErrorOutOfDateKhr || if (acquireResult == Result.ErrorOutOfDateKhr ||
acquireResult == Result.SuboptimalKhr || acquireResult == Result.SuboptimalKhr ||
_vsyncModeChanged) _swapchainIsDirty)
{ {
RecreateSwapchain(); RecreateSwapchain();
} }
@ -443,6 +462,12 @@ namespace Ryujinx.Graphics.Vulkan
_updateScalingFilter = true; _updateScalingFilter = true;
} }
public override void SetColorSpacePassthrough(bool colorSpacePassthroughEnabled)
{
_colorSpacePassthroughEnabled = colorSpacePassthroughEnabled;
_swapchainIsDirty = true;
}
private void UpdateEffect() private void UpdateEffect()
{ {
if (_updateEffect) if (_updateEffect)
@ -559,7 +584,7 @@ namespace Ryujinx.Graphics.Vulkan
public override void ChangeVSyncMode(bool vsyncEnabled) public override void ChangeVSyncMode(bool vsyncEnabled)
{ {
_vsyncEnabled = vsyncEnabled; _vsyncEnabled = vsyncEnabled;
_vsyncModeChanged = true; _swapchainIsDirty = true;
} }
protected virtual void Dispose(bool disposing) protected virtual void Dispose(bool disposing)

View File

@ -14,5 +14,6 @@ namespace Ryujinx.Graphics.Vulkan
public abstract void SetAntiAliasing(AntiAliasing effect); public abstract void SetAntiAliasing(AntiAliasing effect);
public abstract void SetScalingFilter(ScalingFilter scalerType); public abstract void SetScalingFilter(ScalingFilter scalerType);
public abstract void SetScalingFilterLevel(float scale); public abstract void SetScalingFilterLevel(float scale);
public abstract void SetColorSpacePassthrough(bool colorSpacePassthroughEnabled);
} }
} }

View File

@ -14,7 +14,7 @@ namespace Ryujinx.Ui.Common.Configuration
/// <summary> /// <summary>
/// The current version of the file format /// The current version of the file format
/// </summary> /// </summary>
public const int CurrentVersion = 47; public const int CurrentVersion = 48;
/// <summary> /// <summary>
/// Version of the configuration file format /// Version of the configuration file format
@ -186,6 +186,11 @@ namespace Ryujinx.Ui.Common.Configuration
/// </summary> /// </summary>
public bool EnableMacroHLE { get; set; } public bool EnableMacroHLE { get; set; }
/// <summary>
/// Enables or disables color space passthrough, if available.
/// </summary>
public bool EnableColorSpacePassthrough { get; set; }
/// <summary> /// <summary>
/// Enables or disables profiled translation cache persistency /// Enables or disables profiled translation cache persistency
/// </summary> /// </summary>

View File

@ -485,6 +485,11 @@ namespace Ryujinx.Ui.Common.Configuration
/// </summary> /// </summary>
public ReactiveObject<bool> EnableMacroHLE { get; private set; } public ReactiveObject<bool> EnableMacroHLE { get; private set; }
/// <summary>
/// Enables or disables color space passthrough, if available.
/// </summary>
public ReactiveObject<bool> EnableColorSpacePassthrough { get; private set; }
/// <summary> /// <summary>
/// Graphics backend /// Graphics backend
/// </summary> /// </summary>
@ -535,6 +540,8 @@ namespace Ryujinx.Ui.Common.Configuration
PreferredGpu.Event += static (sender, e) => LogValueChange(e, nameof(PreferredGpu)); PreferredGpu.Event += static (sender, e) => LogValueChange(e, nameof(PreferredGpu));
EnableMacroHLE = new ReactiveObject<bool>(); EnableMacroHLE = new ReactiveObject<bool>();
EnableMacroHLE.Event += static (sender, e) => LogValueChange(e, nameof(EnableMacroHLE)); EnableMacroHLE.Event += static (sender, e) => LogValueChange(e, nameof(EnableMacroHLE));
EnableColorSpacePassthrough = new ReactiveObject<bool>();
EnableColorSpacePassthrough.Event += static (sender, e) => LogValueChange(e, nameof(EnableColorSpacePassthrough));
AntiAliasing = new ReactiveObject<AntiAliasing>(); AntiAliasing = new ReactiveObject<AntiAliasing>();
AntiAliasing.Event += static (sender, e) => LogValueChange(e, nameof(AntiAliasing)); AntiAliasing.Event += static (sender, e) => LogValueChange(e, nameof(AntiAliasing));
ScalingFilter = new ReactiveObject<ScalingFilter>(); ScalingFilter = new ReactiveObject<ScalingFilter>();
@ -667,6 +674,7 @@ namespace Ryujinx.Ui.Common.Configuration
EnableShaderCache = Graphics.EnableShaderCache, EnableShaderCache = Graphics.EnableShaderCache,
EnableTextureRecompression = Graphics.EnableTextureRecompression, EnableTextureRecompression = Graphics.EnableTextureRecompression,
EnableMacroHLE = Graphics.EnableMacroHLE, EnableMacroHLE = Graphics.EnableMacroHLE,
EnableColorSpacePassthrough = Graphics.EnableColorSpacePassthrough,
EnablePtc = System.EnablePtc, EnablePtc = System.EnablePtc,
EnableInternetAccess = System.EnableInternetAccess, EnableInternetAccess = System.EnableInternetAccess,
EnableFsIntegrityChecks = System.EnableFsIntegrityChecks, EnableFsIntegrityChecks = System.EnableFsIntegrityChecks,
@ -772,6 +780,7 @@ namespace Ryujinx.Ui.Common.Configuration
Graphics.EnableShaderCache.Value = true; Graphics.EnableShaderCache.Value = true;
Graphics.EnableTextureRecompression.Value = false; Graphics.EnableTextureRecompression.Value = false;
Graphics.EnableMacroHLE.Value = true; Graphics.EnableMacroHLE.Value = true;
Graphics.EnableColorSpacePassthrough.Value = false;
Graphics.AntiAliasing.Value = AntiAliasing.None; Graphics.AntiAliasing.Value = AntiAliasing.None;
Graphics.ScalingFilter.Value = ScalingFilter.Bilinear; Graphics.ScalingFilter.Value = ScalingFilter.Bilinear;
Graphics.ScalingFilterLevel.Value = 80; Graphics.ScalingFilterLevel.Value = 80;
@ -1391,6 +1400,15 @@ namespace Ryujinx.Ui.Common.Configuration
configurationFileUpdated = true; configurationFileUpdated = true;
} }
if (configurationFileFormat.Version < 48)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 48.");
configurationFileFormat.EnableColorSpacePassthrough = false;
configurationFileUpdated = true;
}
Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog; Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog;
Graphics.ResScale.Value = configurationFileFormat.ResScale; Graphics.ResScale.Value = configurationFileFormat.ResScale;
Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom; Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom;
@ -1426,6 +1444,7 @@ namespace Ryujinx.Ui.Common.Configuration
Graphics.EnableShaderCache.Value = configurationFileFormat.EnableShaderCache; Graphics.EnableShaderCache.Value = configurationFileFormat.EnableShaderCache;
Graphics.EnableTextureRecompression.Value = configurationFileFormat.EnableTextureRecompression; Graphics.EnableTextureRecompression.Value = configurationFileFormat.EnableTextureRecompression;
Graphics.EnableMacroHLE.Value = configurationFileFormat.EnableMacroHLE; Graphics.EnableMacroHLE.Value = configurationFileFormat.EnableMacroHLE;
Graphics.EnableColorSpacePassthrough.Value = configurationFileFormat.EnableColorSpacePassthrough;
System.EnablePtc.Value = configurationFileFormat.EnablePtc; System.EnablePtc.Value = configurationFileFormat.EnablePtc;
System.EnableInternetAccess.Value = configurationFileFormat.EnableInternetAccess; System.EnableInternetAccess.Value = configurationFileFormat.EnableInternetAccess;
System.EnableFsIntegrityChecks.Value = configurationFileFormat.EnableFsIntegrityChecks; System.EnableFsIntegrityChecks.Value = configurationFileFormat.EnableFsIntegrityChecks;