Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
fc26189fe1 | ||
|
a40c90e7dd | ||
|
f864a49014 | ||
|
ecbf303266 | ||
|
b3bf05356b | ||
|
cb4b58052f | ||
|
f8cdd5f484 | ||
|
22202be394 | ||
|
17ba217940 | ||
|
aae4595bdb | ||
|
880fd3cfcb | ||
|
f679f25e08 | ||
|
c2709b3bdd |
18
.github/workflows/build.yml
vendored
18
.github/workflows/build.yml
vendored
@@ -27,6 +27,7 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
name: ${{ matrix.OS_NAME }} (${{ matrix.configuration }})
|
name: ${{ matrix.OS_NAME }} (${{ matrix.configuration }})
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
timeout-minutes: 35
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest, macOS-latest, windows-latest]
|
os: [ubuntu-latest, macOS-latest, windows-latest]
|
||||||
@@ -38,7 +39,7 @@ jobs:
|
|||||||
RELEASE_ZIP_OS_NAME: linux_x64
|
RELEASE_ZIP_OS_NAME: linux_x64
|
||||||
|
|
||||||
- os: macOS-latest
|
- os: macOS-latest
|
||||||
OS_NAME: MacOS x64
|
OS_NAME: macOS x64
|
||||||
DOTNET_RUNTIME_IDENTIFIER: osx-x64
|
DOTNET_RUNTIME_IDENTIFIER: osx-x64
|
||||||
RELEASE_ZIP_OS_NAME: osx_x64
|
RELEASE_ZIP_OS_NAME: osx_x64
|
||||||
|
|
||||||
@@ -68,15 +69,15 @@ jobs:
|
|||||||
|
|
||||||
- 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
|
||||||
if: github.event_name == 'pull_request'
|
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||||
|
|
||||||
- name: Publish Ryujinx.Headless.SDL2
|
- name: Publish Ryujinx.Headless.SDL2
|
||||||
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_sdl2_headless -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx.Headless.SDL2 --self-contained true
|
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_sdl2_headless -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx.Headless.SDL2 --self-contained true
|
||||||
if: github.event_name == 'pull_request'
|
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||||
|
|
||||||
- name: Publish Ryujinx.Ava
|
- name: Publish Ryujinx.Ava
|
||||||
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_ava -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx.Ava --self-contained true
|
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_ava -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx.Ava --self-contained true
|
||||||
if: github.event_name == 'pull_request'
|
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||||
|
|
||||||
- name: Set executable bit
|
- name: Set executable bit
|
||||||
run: |
|
run: |
|
||||||
@@ -90,25 +91,26 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
|
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
|
||||||
path: publish
|
path: publish
|
||||||
if: github.event_name == 'pull_request'
|
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||||
|
|
||||||
- name: Upload Ryujinx.Headless.SDL2 artifact
|
- name: Upload Ryujinx.Headless.SDL2 artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: sdl2-ryujinx-headless-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
|
name: sdl2-ryujinx-headless-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
|
||||||
path: publish_sdl2_headless
|
path: publish_sdl2_headless
|
||||||
if: github.event_name == 'pull_request'
|
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||||
|
|
||||||
- name: Upload Ryujinx.Ava artifact
|
- name: Upload Ryujinx.Ava artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: ava-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
|
name: ava-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
|
||||||
path: publish_ava
|
path: publish_ava
|
||||||
if: github.event_name == 'pull_request'
|
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||||
|
|
||||||
build_macos:
|
build_macos:
|
||||||
name: MacOS universal (${{ matrix.configuration }})
|
name: macOS Universal (${{ matrix.configuration }})
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 35
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
configuration: [ Debug, Release ]
|
configuration: [ Debug, Release ]
|
||||||
|
1
.github/workflows/flatpak.yml
vendored
1
.github/workflows/flatpak.yml
vendored
@@ -12,6 +12,7 @@ concurrency: flatpak-release
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
release:
|
||||||
|
timeout-minutes: 35
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
3
.github/workflows/nightly_pr_comment.yml
vendored
3
.github/workflows/nightly_pr_comment.yml
vendored
@@ -7,6 +7,7 @@ jobs:
|
|||||||
pr_comment:
|
pr_comment:
|
||||||
if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success'
|
if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 35
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/github-script@v6
|
- uses: actions/github-script@v6
|
||||||
with:
|
with:
|
||||||
@@ -65,4 +66,4 @@ jobs:
|
|||||||
} else {
|
} else {
|
||||||
core.info(`Creating a comment`);
|
core.info(`Creating a comment`);
|
||||||
await github.rest.issues.createComment({repo, owner, issue_number, body});
|
await github.rest.issues.createComment({repo, owner, issue_number, body});
|
||||||
}
|
}
|
6
.github/workflows/release.yml
vendored
6
.github/workflows/release.yml
vendored
@@ -46,6 +46,7 @@ jobs:
|
|||||||
release:
|
release:
|
||||||
name: Release ${{ matrix.OS_NAME }}
|
name: Release ${{ matrix.OS_NAME }}
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
timeout-minutes: 35
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ ubuntu-latest, windows-latest ]
|
os: [ ubuntu-latest, windows-latest ]
|
||||||
@@ -143,13 +144,14 @@ jobs:
|
|||||||
macos_release:
|
macos_release:
|
||||||
name: Release MacOS universal
|
name: Release MacOS universal
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 35
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- uses: actions/setup-dotnet@v3
|
- uses: actions/setup-dotnet@v3
|
||||||
with:
|
with:
|
||||||
global-json-file: global.json
|
global-json-file: global.json
|
||||||
|
|
||||||
- name: Setup LLVM 14
|
- name: Setup LLVM 14
|
||||||
run: |
|
run: |
|
||||||
wget https://apt.llvm.org/llvm.sh
|
wget https://apt.llvm.org/llvm.sh
|
||||||
@@ -205,4 +207,4 @@ jobs:
|
|||||||
needs: release
|
needs: release
|
||||||
with:
|
with:
|
||||||
ryujinx_version: "1.1.${{ github.run_number }}"
|
ryujinx_version: "1.1.${{ github.run_number }}"
|
||||||
secrets: inherit
|
secrets: inherit
|
@@ -13,7 +13,7 @@
|
|||||||
<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.1.3.18" />
|
||||||
<PackageVersion Include="DynamicData" Version="7.13.5" />
|
<PackageVersion Include="DynamicData" Version="7.13.8" />
|
||||||
<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" />
|
||||||
<PackageVersion Include="GtkSharp.Dependencies.osx" Version="0.0.5" />
|
<PackageVersion Include="GtkSharp.Dependencies.osx" Version="0.0.5" />
|
||||||
|
@@ -22,9 +22,9 @@ EXTRA_ARGS=$8
|
|||||||
|
|
||||||
if [ "$VERSION" == "1.1.0" ];
|
if [ "$VERSION" == "1.1.0" ];
|
||||||
then
|
then
|
||||||
RELEASE_TAR_FILE_NAME=Ryujinx-$CONFIGURATION-$VERSION+$SOURCE_REVISION_ID-macos_universal.app.tar
|
RELEASE_TAR_FILE_NAME=test-ava-ryujinx-$CONFIGURATION-$VERSION+$SOURCE_REVISION_ID-macos_universal.app.tar
|
||||||
else
|
else
|
||||||
RELEASE_TAR_FILE_NAME=Ryujinx-$VERSION-macos_universal.app.tar
|
RELEASE_TAR_FILE_NAME=test-ava-ryujinx-$VERSION-macos_universal.app.tar
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ARM64_APP_BUNDLE="$TEMP_DIRECTORY/output_arm64/Ryujinx.app"
|
ARM64_APP_BUNDLE="$TEMP_DIRECTORY/output_arm64/Ryujinx.app"
|
||||||
|
@@ -36,4 +36,9 @@ sleep 1
|
|||||||
# Now replace and reopen.
|
# Now replace and reopen.
|
||||||
rm -rf "$INSTALL_DIRECTORY"
|
rm -rf "$INSTALL_DIRECTORY"
|
||||||
mv "$NEW_APP_DIRECTORY" "$INSTALL_DIRECTORY"
|
mv "$NEW_APP_DIRECTORY" "$INSTALL_DIRECTORY"
|
||||||
open -a "$INSTALL_DIRECTORY" --args "$APP_ARGUMENTS"
|
|
||||||
|
if [ "$#" -le 3 ]; then
|
||||||
|
open -a "$INSTALL_DIRECTORY"
|
||||||
|
else
|
||||||
|
open -a "$INSTALL_DIRECTORY" --args "$APP_ARGUMENTS"
|
||||||
|
fi
|
||||||
|
@@ -5,6 +5,7 @@ using Ryujinx.Memory;
|
|||||||
using Ryujinx.SDL2.Common;
|
using Ryujinx.SDL2.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
using static Ryujinx.Audio.Integration.IHardwareDeviceDriver;
|
using static Ryujinx.Audio.Integration.IHardwareDeviceDriver;
|
||||||
@@ -18,6 +19,13 @@ namespace Ryujinx.Audio.Backends.SDL2
|
|||||||
private readonly ManualResetEvent _pauseEvent;
|
private readonly ManualResetEvent _pauseEvent;
|
||||||
private readonly ConcurrentDictionary<SDL2HardwareDeviceSession, byte> _sessions;
|
private readonly ConcurrentDictionary<SDL2HardwareDeviceSession, byte> _sessions;
|
||||||
|
|
||||||
|
private bool _supportSurroundConfiguration;
|
||||||
|
|
||||||
|
// TODO: Add this to SDL2-CS
|
||||||
|
// NOTE: We use a DllImport here because of marshaling issue for spec.
|
||||||
|
[DllImport("SDL2")]
|
||||||
|
private static extern int SDL_GetDefaultAudioInfo(IntPtr name, out SDL_AudioSpec spec, int isCapture);
|
||||||
|
|
||||||
public SDL2HardwareDeviceDriver()
|
public SDL2HardwareDeviceDriver()
|
||||||
{
|
{
|
||||||
_updateRequiredEvent = new ManualResetEvent(false);
|
_updateRequiredEvent = new ManualResetEvent(false);
|
||||||
@@ -25,6 +33,20 @@ namespace Ryujinx.Audio.Backends.SDL2
|
|||||||
_sessions = new ConcurrentDictionary<SDL2HardwareDeviceSession, byte>();
|
_sessions = new ConcurrentDictionary<SDL2HardwareDeviceSession, byte>();
|
||||||
|
|
||||||
SDL2Driver.Instance.Initialize();
|
SDL2Driver.Instance.Initialize();
|
||||||
|
|
||||||
|
int res = SDL_GetDefaultAudioInfo(IntPtr.Zero, out var spec, 0);
|
||||||
|
|
||||||
|
if (res != 0)
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Application,
|
||||||
|
$"SDL_GetDefaultAudioInfo failed with error \"{SDL_GetError()}\"");
|
||||||
|
|
||||||
|
_supportSurroundConfiguration = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_supportSurroundConfiguration = spec.channels == 6;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsSupported => IsSupportedInternal();
|
public static bool IsSupported => IsSupportedInternal();
|
||||||
@@ -164,6 +186,11 @@ namespace Ryujinx.Audio.Backends.SDL2
|
|||||||
|
|
||||||
public bool SupportsChannelCount(uint channelCount)
|
public bool SupportsChannelCount(uint channelCount)
|
||||||
{
|
{
|
||||||
|
if (channelCount == 6)
|
||||||
|
{
|
||||||
|
return _supportSurroundConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -45,7 +45,7 @@ namespace Ryujinx.Audio.Renderer.Device
|
|||||||
/// <param name="name">The name of the <see cref="VirtualDevice"/>.</param>
|
/// <param name="name">The name of the <see cref="VirtualDevice"/>.</param>
|
||||||
/// <param name="channelCount">The count of channels supported by the <see cref="VirtualDevice"/>.</param>
|
/// <param name="channelCount">The count of channels supported by the <see cref="VirtualDevice"/>.</param>
|
||||||
/// <param name="isExternalOutput">Indicate if the <see cref="VirtualDevice"/> is provided by an external interface.</param>
|
/// <param name="isExternalOutput">Indicate if the <see cref="VirtualDevice"/> is provided by an external interface.</param>
|
||||||
private VirtualDevice(string name, uint channelCount, bool isExternalOutput)
|
public VirtualDevice(string name, uint channelCount, bool isExternalOutput)
|
||||||
{
|
{
|
||||||
Name = name;
|
Name = name;
|
||||||
ChannelCount = channelCount;
|
ChannelCount = channelCount;
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
using Ryujinx.Audio.Integration;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Audio.Renderer.Device
|
namespace Ryujinx.Audio.Renderer.Device
|
||||||
@@ -22,7 +23,23 @@ namespace Ryujinx.Audio.Renderer.Device
|
|||||||
/// The current active <see cref="VirtualDevice"/>.
|
/// The current active <see cref="VirtualDevice"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
// TODO: make this configurable
|
// TODO: make this configurable
|
||||||
public VirtualDevice ActiveDevice = VirtualDevice.Devices[2];
|
public VirtualDevice ActiveDevice { get; }
|
||||||
|
|
||||||
|
public VirtualDeviceSessionRegistry(IHardwareDeviceDriver driver)
|
||||||
|
{
|
||||||
|
uint channelCount;
|
||||||
|
|
||||||
|
if (driver.GetRealDeviceDriver().SupportsChannelCount(6))
|
||||||
|
{
|
||||||
|
channelCount = 6;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
channelCount = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
ActiveDevice = new VirtualDevice("AudioTvOutput", channelCount, false);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the associated <see cref="T:VirtualDeviceSession[]"/> from an AppletResourceId.
|
/// Get the associated <see cref="T:VirtualDeviceSession[]"/> from an AppletResourceId.
|
||||||
|
@@ -86,7 +86,7 @@ namespace Ryujinx.Ava
|
|||||||
private KeyboardHotkeyState _prevHotkeyState;
|
private KeyboardHotkeyState _prevHotkeyState;
|
||||||
|
|
||||||
private long _lastCursorMoveTime;
|
private long _lastCursorMoveTime;
|
||||||
private bool _isCursorInRenderer;
|
private bool _isCursorInRenderer = true;
|
||||||
|
|
||||||
private bool _isStopped;
|
private bool _isStopped;
|
||||||
private bool _isActive;
|
private bool _isActive;
|
||||||
@@ -160,7 +160,9 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
ConfigurationState.Instance.HideCursor.Event += HideCursorState_Changed;
|
ConfigurationState.Instance.HideCursor.Event += HideCursorState_Changed;
|
||||||
|
|
||||||
_topLevel.PointerMoved += TopLevel_PointerMoved;
|
_topLevel.PointerMoved += TopLevel_PointerEnterOrMoved;
|
||||||
|
_topLevel.PointerEnter += TopLevel_PointerEnterOrMoved;
|
||||||
|
_topLevel.PointerLeave += TopLevel_PointerLeave;
|
||||||
|
|
||||||
if (OperatingSystem.IsWindows())
|
if (OperatingSystem.IsWindows())
|
||||||
{
|
{
|
||||||
@@ -183,7 +185,7 @@ namespace Ryujinx.Ava
|
|||||||
_gpuCancellationTokenSource = new CancellationTokenSource();
|
_gpuCancellationTokenSource = new CancellationTokenSource();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TopLevel_PointerMoved(object sender, PointerEventArgs e)
|
private void TopLevel_PointerEnterOrMoved(object sender, PointerEventArgs e)
|
||||||
{
|
{
|
||||||
if (sender is MainWindow window)
|
if (sender is MainWindow window)
|
||||||
{
|
{
|
||||||
@@ -201,6 +203,12 @@ namespace Ryujinx.Ava
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void TopLevel_PointerLeave(object sender, PointerEventArgs e)
|
||||||
|
{
|
||||||
|
_isCursorInRenderer = false;
|
||||||
|
}
|
||||||
|
|
||||||
private void UpdateScalingFilterLevel(object sender, ReactiveEventArgs<int> e)
|
private void UpdateScalingFilterLevel(object sender, ReactiveEventArgs<int> e)
|
||||||
{
|
{
|
||||||
_renderer.Window?.SetScalingFilter((Graphics.GAL.ScalingFilter)ConfigurationState.Instance.Graphics.ScalingFilter.Value);
|
_renderer.Window?.SetScalingFilter((Graphics.GAL.ScalingFilter)ConfigurationState.Instance.Graphics.ScalingFilter.Value);
|
||||||
@@ -446,7 +454,9 @@ namespace Ryujinx.Ava
|
|||||||
ConfigurationState.Instance.Graphics.ScalingFilterLevel.Event -= UpdateScalingFilterLevel;
|
ConfigurationState.Instance.Graphics.ScalingFilterLevel.Event -= UpdateScalingFilterLevel;
|
||||||
ConfigurationState.Instance.Graphics.AntiAliasing.Event -= UpdateAntiAliasing;
|
ConfigurationState.Instance.Graphics.AntiAliasing.Event -= UpdateAntiAliasing;
|
||||||
|
|
||||||
_topLevel.PointerMoved -= TopLevel_PointerMoved;
|
_topLevel.PointerMoved -= TopLevel_PointerEnterOrMoved;
|
||||||
|
_topLevel.PointerEnter -= TopLevel_PointerEnterOrMoved;
|
||||||
|
_topLevel.PointerLeave -= TopLevel_PointerLeave;
|
||||||
|
|
||||||
_gpuCancellationTokenSource.Cancel();
|
_gpuCancellationTokenSource.Cancel();
|
||||||
_gpuCancellationTokenSource.Dispose();
|
_gpuCancellationTokenSource.Dispose();
|
||||||
|
@@ -193,7 +193,7 @@ namespace Ryujinx.Ava.Common
|
|||||||
if (nca.Header.ContentType == NcaContentType.Program)
|
if (nca.Header.ContentType == NcaContentType.Program)
|
||||||
{
|
{
|
||||||
int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);
|
int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);
|
||||||
if (nca.Header.GetFsHeader(dataIndex).IsPatchSection())
|
if (nca.SectionExists(NcaSectionType.Data) && nca.Header.GetFsHeader(dataIndex).IsPatchSection())
|
||||||
{
|
{
|
||||||
patchNca = nca;
|
patchNca = nca;
|
||||||
}
|
}
|
||||||
|
@@ -23,6 +23,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
public const int PrimitiveRestartStateIndex = 12;
|
public const int PrimitiveRestartStateIndex = 12;
|
||||||
public const int RenderTargetStateIndex = 27;
|
public const int RenderTargetStateIndex = 27;
|
||||||
|
|
||||||
|
private const ulong MaxUnknownStorageSize = 0x100000;
|
||||||
|
|
||||||
private readonly GpuContext _context;
|
private readonly GpuContext _context;
|
||||||
private readonly GpuChannel _channel;
|
private readonly GpuChannel _channel;
|
||||||
private readonly DeviceStateWithShadow<ThreedClassState> _state;
|
private readonly DeviceStateWithShadow<ThreedClassState> _state;
|
||||||
@@ -356,7 +358,19 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
|
|
||||||
SbDescriptor sbDescriptor = _channel.MemoryManager.Physical.Read<SbDescriptor>(sbDescAddress);
|
SbDescriptor sbDescriptor = _channel.MemoryManager.Physical.Read<SbDescriptor>(sbDescAddress);
|
||||||
|
|
||||||
_channel.BufferManager.SetGraphicsStorageBuffer(stage, sb.Slot, sbDescriptor.PackAddress(), (uint)sbDescriptor.Size, sb.Flags);
|
uint size;
|
||||||
|
if (sb.SbCbSlot == 0)
|
||||||
|
{
|
||||||
|
// Only trust the SbDescriptor size if it comes from slot 0.
|
||||||
|
size = (uint)sbDescriptor.Size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: Use full mapped size and somehow speed up buffer sync.
|
||||||
|
size = (uint)_channel.MemoryManager.GetMappedSize(sbDescriptor.PackAddress(), MaxUnknownStorageSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
_channel.BufferManager.SetGraphicsStorageBuffer(stage, sb.Slot, sbDescriptor.PackAddress(), size, sb.Flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -99,6 +99,7 @@ namespace Ryujinx.Graphics.Gpu
|
|||||||
private bool _pendingSync;
|
private bool _pendingSync;
|
||||||
|
|
||||||
private long _modifiedSequence;
|
private long _modifiedSequence;
|
||||||
|
private ulong _firstTimestamp;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new instance of the GPU emulation context.
|
/// Creates a new instance of the GPU emulation context.
|
||||||
@@ -123,6 +124,8 @@ namespace Ryujinx.Graphics.Gpu
|
|||||||
DeferredActions = new Queue<Action>();
|
DeferredActions = new Queue<Action>();
|
||||||
|
|
||||||
PhysicalMemoryRegistry = new ConcurrentDictionary<ulong, PhysicalMemory>();
|
PhysicalMemoryRegistry = new ConcurrentDictionary<ulong, PhysicalMemory>();
|
||||||
|
|
||||||
|
_firstTimestamp = ConvertNanosecondsToTicks((ulong)PerformanceCounter.ElapsedNanoseconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -217,7 +220,8 @@ namespace Ryujinx.Graphics.Gpu
|
|||||||
/// <returns>The current GPU timestamp</returns>
|
/// <returns>The current GPU timestamp</returns>
|
||||||
public ulong GetTimestamp()
|
public ulong GetTimestamp()
|
||||||
{
|
{
|
||||||
ulong ticks = ConvertNanosecondsToTicks((ulong)PerformanceCounter.ElapsedNanoseconds);
|
// Guest timestamp will start at 0, instead of host value.
|
||||||
|
ulong ticks = ConvertNanosecondsToTicks((ulong)PerformanceCounter.ElapsedNanoseconds) - _firstTimestamp;
|
||||||
|
|
||||||
if (GraphicsConfig.FastGpuTime)
|
if (GraphicsConfig.FastGpuTime)
|
||||||
{
|
{
|
||||||
|
@@ -637,6 +637,33 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
return UnpackPaFromPte(pte) + (va & PageMask);
|
return UnpackPaFromPte(pte) + (va & PageMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Translates a GPU virtual address and returns the number of bytes that are mapped after it.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="va">GPU virtual address to be translated</param>
|
||||||
|
/// <param name="maxSize">Maximum size in bytes to scan</param>
|
||||||
|
/// <returns>Number of bytes, 0 if unmapped</returns>
|
||||||
|
public ulong GetMappedSize(ulong va, ulong maxSize)
|
||||||
|
{
|
||||||
|
if (!ValidateAddress(va))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ulong startVa = va;
|
||||||
|
ulong endVa = va + maxSize;
|
||||||
|
|
||||||
|
ulong pte = GetPte(va);
|
||||||
|
|
||||||
|
while (pte != PteUnmapped && va < endVa)
|
||||||
|
{
|
||||||
|
va += PageSize - (va & PageMask);
|
||||||
|
pte = GetPte(va);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.Min(maxSize, va - startVa);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the kind of a given memory page.
|
/// Gets the kind of a given memory page.
|
||||||
/// This might indicate the type of resource that can be allocated on the page, and also texture tiling.
|
/// This might indicate the type of resource that can be allocated on the page, and also texture tiling.
|
||||||
|
@@ -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 = 4892;
|
private const uint CodeGenVersion = 4578;
|
||||||
|
|
||||||
private const string SharedTocFileName = "shared.toc";
|
private const string SharedTocFileName = "shared.toc";
|
||||||
private const string SharedDataFileName = "shared.data";
|
private const string SharedDataFileName = "shared.data";
|
||||||
|
@@ -306,6 +306,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||||||
int offset = WriteToPbo2D(range.Offset, layer, level);
|
int offset = WriteToPbo2D(range.Offset, layer, level);
|
||||||
|
|
||||||
Debug.Assert(offset == 0);
|
Debug.Assert(offset == 0);
|
||||||
|
|
||||||
|
GL.BindBuffer(BufferTarget.PixelPackBuffer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteToPbo(int offset, bool forceBgra)
|
public void WriteToPbo(int offset, bool forceBgra)
|
||||||
|
@@ -93,7 +93,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
oldView.Dispose();
|
oldView.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, drawFramebuffer);
|
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, drawFramebuffer);
|
||||||
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, readFramebuffer);
|
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, readFramebuffer);
|
||||||
|
|
||||||
|
@@ -20,6 +20,12 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||||||
GlobalToStorage.RunPass(blocks[blkIndex], config, ref sbUseMask, ref ubeUseMask);
|
GlobalToStorage.RunPass(blocks[blkIndex], config, ref sbUseMask, ref ubeUseMask);
|
||||||
BindlessToIndexed.RunPass(blocks[blkIndex], config);
|
BindlessToIndexed.RunPass(blocks[blkIndex], config);
|
||||||
BindlessElimination.RunPass(blocks[blkIndex], config);
|
BindlessElimination.RunPass(blocks[blkIndex], config);
|
||||||
|
|
||||||
|
// FragmentCoord only exists on fragment shaders, so we don't need to check other stages.
|
||||||
|
if (config.Stage == ShaderStage.Fragment)
|
||||||
|
{
|
||||||
|
EliminateMultiplyByFragmentCoordW(blocks[blkIndex]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
config.SetAccessibleBufferMasks(sbUseMask, ubeUseMask);
|
config.SetAccessibleBufferMasks(sbUseMask, ubeUseMask);
|
||||||
@@ -281,6 +287,75 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||||||
return modified;
|
return modified;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void EliminateMultiplyByFragmentCoordW(BasicBlock block)
|
||||||
|
{
|
||||||
|
foreach (INode node in block.Operations)
|
||||||
|
{
|
||||||
|
if (node is Operation operation)
|
||||||
|
{
|
||||||
|
EliminateMultiplyByFragmentCoordW(operation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void EliminateMultiplyByFragmentCoordW(Operation operation)
|
||||||
|
{
|
||||||
|
// We're looking for the pattern:
|
||||||
|
// y = x * gl_FragCoord.w
|
||||||
|
// v = y * (1.0 / gl_FragCoord.w)
|
||||||
|
// Then we transform it into:
|
||||||
|
// v = x
|
||||||
|
// This pattern is common on fragment shaders due to the way how perspective correction is done.
|
||||||
|
|
||||||
|
// We are expecting a multiplication by the reciprocal of gl_FragCoord.w.
|
||||||
|
if (operation.Inst != (Instruction.FP32 | Instruction.Multiply))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Operand lhs = operation.GetSource(0);
|
||||||
|
Operand rhs = operation.GetSource(1);
|
||||||
|
|
||||||
|
// Check LHS of the the main multiplication operation. We expect an input being multiplied by gl_FragCoord.w.
|
||||||
|
if (!(lhs.AsgOp is Operation attrMulOp) || attrMulOp.Inst != (Instruction.FP32 | Instruction.Multiply))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Operand attrMulLhs = attrMulOp.GetSource(0);
|
||||||
|
Operand attrMulRhs = attrMulOp.GetSource(1);
|
||||||
|
|
||||||
|
// LHS should be any input, RHS should be exactly gl_FragCoord.w.
|
||||||
|
if (!Utils.IsInputLoad(attrMulLhs.AsgOp) || !Utils.IsInputLoad(attrMulRhs.AsgOp, IoVariable.FragmentCoord, 3))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RHS of the main multiplication should be a reciprocal operation (1.0 / x).
|
||||||
|
if (!(rhs.AsgOp is Operation reciprocalOp) || reciprocalOp.Inst != (Instruction.FP32 | Instruction.Divide))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Operand reciprocalLhs = reciprocalOp.GetSource(0);
|
||||||
|
Operand reciprocalRhs = reciprocalOp.GetSource(1);
|
||||||
|
|
||||||
|
// Check if the divisor is a constant equal to 1.0.
|
||||||
|
if (reciprocalLhs.Type != OperandType.Constant || reciprocalLhs.AsFloat() != 1.0f)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the dividend is gl_FragCoord.w.
|
||||||
|
if (!Utils.IsInputLoad(reciprocalRhs.AsgOp, IoVariable.FragmentCoord, 3))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If everything matches, we can replace the operation with the input load result.
|
||||||
|
operation.TurnIntoCopy(attrMulLhs);
|
||||||
|
}
|
||||||
|
|
||||||
private static void RemoveNode(BasicBlock block, LinkedListNode<INode> llNode)
|
private static void RemoveNode(BasicBlock block, LinkedListNode<INode> llNode)
|
||||||
{
|
{
|
||||||
// Remove a node from the nodes list, and also remove itself
|
// Remove a node from the nodes list, and also remove itself
|
||||||
|
@@ -4,6 +4,35 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||||||
{
|
{
|
||||||
static class Utils
|
static class Utils
|
||||||
{
|
{
|
||||||
|
public static bool IsInputLoad(INode node)
|
||||||
|
{
|
||||||
|
return (node is Operation operation) &&
|
||||||
|
operation.Inst == Instruction.Load &&
|
||||||
|
operation.StorageKind == StorageKind.Input;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsInputLoad(INode node, IoVariable ioVariable, int elemIndex)
|
||||||
|
{
|
||||||
|
if (!(node is Operation operation) ||
|
||||||
|
operation.Inst != Instruction.Load ||
|
||||||
|
operation.StorageKind != StorageKind.Input ||
|
||||||
|
operation.SourcesCount != 2)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Operand ioVariableSrc = operation.GetSource(0);
|
||||||
|
|
||||||
|
if (ioVariableSrc.Type != OperandType.Constant || (IoVariable)ioVariableSrc.Value != ioVariable)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Operand elemIndexSrc = operation.GetSource(1);
|
||||||
|
|
||||||
|
return elemIndexSrc.Type == OperandType.Constant && elemIndexSrc.Value == elemIndex;
|
||||||
|
}
|
||||||
|
|
||||||
private static Operation FindBranchSource(BasicBlock block)
|
private static Operation FindBranchSource(BasicBlock block)
|
||||||
{
|
{
|
||||||
foreach (BasicBlock sourceBlock in block.Predecessors)
|
foreach (BasicBlock sourceBlock in block.Predecessors)
|
||||||
|
@@ -56,6 +56,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
private int _writeCount;
|
private int _writeCount;
|
||||||
private int _flushCount;
|
private int _flushCount;
|
||||||
private int _flushTemp;
|
private int _flushTemp;
|
||||||
|
private int _lastFlushWrite = -1;
|
||||||
|
|
||||||
private ReaderWriterLock _flushLock;
|
private ReaderWriterLock _flushLock;
|
||||||
private FenceHolder _flushFence;
|
private FenceHolder _flushFence;
|
||||||
@@ -200,14 +201,21 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
if (_baseType == BufferAllocationType.Auto)
|
if (_baseType == BufferAllocationType.Auto)
|
||||||
{
|
{
|
||||||
if (_writeCount >= WriteCountThreshold || _setCount >= SetCountThreshold || _flushCount >= FlushCountThreshold)
|
// When flushed, wait for a bit more info to make a decision.
|
||||||
|
bool wasFlushed = _flushTemp > 0;
|
||||||
|
int multiplier = wasFlushed ? 2 : 0;
|
||||||
|
if (_writeCount >= (WriteCountThreshold << multiplier) || _setCount >= (SetCountThreshold << multiplier) || _flushCount >= (FlushCountThreshold << multiplier))
|
||||||
{
|
{
|
||||||
if (_flushCount > 0 || _flushTemp-- > 0)
|
if (_flushCount > 0 || _flushTemp-- > 0)
|
||||||
{
|
{
|
||||||
// Buffers that flush should ideally be mapped in host address space for easy copies.
|
// Buffers that flush should ideally be mapped in host address space for easy copies.
|
||||||
// If the buffer is large it will do better on GPU memory, as there will be more writes than data flushes (typically individual pages).
|
// If the buffer is large it will do better on GPU memory, as there will be more writes than data flushes (typically individual pages).
|
||||||
// If it is small, then it's likely most of the buffer will be flushed so we want it on host memory, as access is cached.
|
// If it is small, then it's likely most of the buffer will be flushed so we want it on host memory, as access is cached.
|
||||||
DesiredType = Size > DeviceLocalSizeThreshold ? BufferAllocationType.DeviceLocalMapped : BufferAllocationType.HostMapped;
|
|
||||||
|
bool hostMappingSensitive = _gd.Vendor == Vendor.Nvidia;
|
||||||
|
bool deviceLocalMapped = Size > DeviceLocalSizeThreshold || (wasFlushed && _writeCount > _flushCount * 10 && hostMappingSensitive) || _currentType == BufferAllocationType.DeviceLocalMapped;
|
||||||
|
|
||||||
|
DesiredType = deviceLocalMapped ? BufferAllocationType.DeviceLocalMapped : BufferAllocationType.HostMapped;
|
||||||
|
|
||||||
// It's harder for a buffer that is flushed to revert to another type of mapping.
|
// It's harder for a buffer that is flushed to revert to another type of mapping.
|
||||||
if (_flushCount > 0)
|
if (_flushCount > 0)
|
||||||
@@ -215,17 +223,18 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_flushTemp = 1000;
|
_flushTemp = 1000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (_writeCount >= WriteCountThreshold)
|
else if (_writeCount >= (WriteCountThreshold << multiplier))
|
||||||
{
|
{
|
||||||
// Buffers that are written often should ideally be in the device local heap. (Storage buffers)
|
// Buffers that are written often should ideally be in the device local heap. (Storage buffers)
|
||||||
DesiredType = BufferAllocationType.DeviceLocal;
|
DesiredType = BufferAllocationType.DeviceLocal;
|
||||||
}
|
}
|
||||||
else if (_setCount > SetCountThreshold)
|
else if (_setCount > (SetCountThreshold << multiplier))
|
||||||
{
|
{
|
||||||
// Buffers that have their data set often should ideally be host mapped. (Constant buffers)
|
// Buffers that have their data set often should ideally be host mapped. (Constant buffers)
|
||||||
DesiredType = BufferAllocationType.HostMapped;
|
DesiredType = BufferAllocationType.HostMapped;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_lastFlushWrite = -1;
|
||||||
_flushCount = 0;
|
_flushCount = 0;
|
||||||
_writeCount = 0;
|
_writeCount = 0;
|
||||||
_setCount = 0;
|
_setCount = 0;
|
||||||
@@ -418,7 +427,12 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
WaitForFlushFence();
|
WaitForFlushFence();
|
||||||
|
|
||||||
_flushCount++;
|
if (_lastFlushWrite != _writeCount)
|
||||||
|
{
|
||||||
|
// If it's on the same page as the last flush, ignore it.
|
||||||
|
_lastFlushWrite = _writeCount;
|
||||||
|
_flushCount++;
|
||||||
|
}
|
||||||
|
|
||||||
Span<byte> result;
|
Span<byte> result;
|
||||||
|
|
||||||
|
@@ -228,7 +228,12 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
SignalDirty(DirtyFlags.Storage);
|
SignalDirty(DirtyFlags.Storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetTextureAndSampler(CommandBufferScoped cbs, ShaderStage stage, int binding, ITexture texture, ISampler sampler)
|
public void SetTextureAndSampler(
|
||||||
|
CommandBufferScoped cbs,
|
||||||
|
ShaderStage stage,
|
||||||
|
int binding,
|
||||||
|
ITexture texture,
|
||||||
|
ISampler sampler)
|
||||||
{
|
{
|
||||||
if (texture is TextureBuffer textureBuffer)
|
if (texture is TextureBuffer textureBuffer)
|
||||||
{
|
{
|
||||||
@@ -251,6 +256,28 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
SignalDirty(DirtyFlags.Texture);
|
SignalDirty(DirtyFlags.Texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetTextureAndSamplerIdentitySwizzle(
|
||||||
|
CommandBufferScoped cbs,
|
||||||
|
ShaderStage stage,
|
||||||
|
int binding,
|
||||||
|
ITexture texture,
|
||||||
|
ISampler sampler)
|
||||||
|
{
|
||||||
|
if (texture is TextureView view)
|
||||||
|
{
|
||||||
|
view.Storage.InsertWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, stage.ConvertToPipelineStageFlags());
|
||||||
|
|
||||||
|
_textureRefs[binding] = view.GetIdentityImageView();
|
||||||
|
_samplerRefs[binding] = ((SamplerHolder)sampler)?.GetSampler();
|
||||||
|
|
||||||
|
SignalDirty(DirtyFlags.Texture);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetTextureAndSampler(cbs, stage, binding, texture, sampler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void SetUniformBuffers(CommandBuffer commandBuffer, ReadOnlySpan<BufferAssignment> buffers)
|
public void SetUniformBuffers(CommandBuffer commandBuffer, ReadOnlySpan<BufferAssignment> buffers)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < buffers.Length; i++)
|
for (int i = 0; i < buffers.Length; i++)
|
||||||
|
@@ -415,7 +415,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
var sampler = linearFilter ? _samplerLinear : _samplerNearest;
|
var sampler = linearFilter ? _samplerLinear : _samplerNearest;
|
||||||
|
|
||||||
_pipeline.SetTextureAndSampler(ShaderStage.Fragment, 0, src, sampler);
|
_pipeline.SetTextureAndSamplerIdentitySwizzle(ShaderStage.Fragment, 0, src, sampler);
|
||||||
|
|
||||||
Span<float> region = stackalloc float[RegionBufferSize / sizeof(float)];
|
Span<float> region = stackalloc float[RegionBufferSize / sizeof(float)];
|
||||||
|
|
||||||
@@ -625,7 +625,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
private void BlitDepthStencilDraw(TextureView src, bool isDepth)
|
private void BlitDepthStencilDraw(TextureView src, bool isDepth)
|
||||||
{
|
{
|
||||||
_pipeline.SetTextureAndSampler(ShaderStage.Fragment, 0, src, _samplerNearest);
|
_pipeline.SetTextureAndSamplerIdentitySwizzle(ShaderStage.Fragment, 0, src, _samplerNearest);
|
||||||
|
|
||||||
if (isDepth)
|
if (isDepth)
|
||||||
{
|
{
|
||||||
@@ -1037,7 +1037,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
var srcView = Create2DLayerView(src, srcLayer + z, srcLevel + l, srcFormat);
|
var srcView = Create2DLayerView(src, srcLayer + z, srcLevel + l, srcFormat);
|
||||||
var dstView = Create2DLayerView(dst, dstLayer + z, dstLevel + l);
|
var dstView = Create2DLayerView(dst, dstLayer + z, dstLevel + l);
|
||||||
|
|
||||||
_pipeline.SetTextureAndSampler(ShaderStage.Compute, 0, srcView, null);
|
_pipeline.SetTextureAndSamplerIdentitySwizzle(ShaderStage.Compute, 0, srcView, null);
|
||||||
_pipeline.SetImage(0, dstView, dstFormat);
|
_pipeline.SetImage(0, dstView, dstFormat);
|
||||||
|
|
||||||
int dispatchX = (Math.Min(srcView.Info.Width, dstView.Info.Width) + 31) / 32;
|
int dispatchX = (Math.Min(srcView.Info.Width, dstView.Info.Width) + 31) / 32;
|
||||||
@@ -1177,7 +1177,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
var srcView = Create2DLayerView(src, srcLayer + z, 0, format);
|
var srcView = Create2DLayerView(src, srcLayer + z, 0, format);
|
||||||
var dstView = Create2DLayerView(dst, dstLayer + z, 0);
|
var dstView = Create2DLayerView(dst, dstLayer + z, 0);
|
||||||
|
|
||||||
_pipeline.SetTextureAndSampler(ShaderStage.Compute, 0, srcView, null);
|
_pipeline.SetTextureAndSamplerIdentitySwizzle(ShaderStage.Compute, 0, srcView, null);
|
||||||
_pipeline.SetImage(0, dstView, format);
|
_pipeline.SetImage(0, dstView, format);
|
||||||
|
|
||||||
_pipeline.DispatchCompute(dispatchX, dispatchY, 1);
|
_pipeline.DispatchCompute(dispatchX, dispatchY, 1);
|
||||||
@@ -1313,7 +1313,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
var srcView = Create2DLayerView(src, srcLayer + z, 0, format);
|
var srcView = Create2DLayerView(src, srcLayer + z, 0, format);
|
||||||
var dstView = Create2DLayerView(dst, dstLayer + z, 0);
|
var dstView = Create2DLayerView(dst, dstLayer + z, 0);
|
||||||
|
|
||||||
_pipeline.SetTextureAndSampler(ShaderStage.Fragment, 0, srcView, null);
|
_pipeline.SetTextureAndSamplerIdentitySwizzle(ShaderStage.Fragment, 0, srcView, null);
|
||||||
_pipeline.SetRenderTarget(
|
_pipeline.SetRenderTarget(
|
||||||
((TextureView)dstView).GetView(format).GetImageViewForAttachment(),
|
((TextureView)dstView).GetView(format).GetImageViewForAttachment(),
|
||||||
(uint)dst.Width,
|
(uint)dst.Width,
|
||||||
@@ -1384,7 +1384,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
private void CopyMSAspectDraw(TextureView src, bool fromMS, bool isDepth)
|
private void CopyMSAspectDraw(TextureView src, bool fromMS, bool isDepth)
|
||||||
{
|
{
|
||||||
_pipeline.SetTextureAndSampler(ShaderStage.Fragment, 0, src, _samplerNearest);
|
_pipeline.SetTextureAndSamplerIdentitySwizzle(ShaderStage.Fragment, 0, src, _samplerNearest);
|
||||||
|
|
||||||
if (isDepth)
|
if (isDepth)
|
||||||
{
|
{
|
||||||
|
@@ -1098,6 +1098,11 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_descriptorSetUpdater.SetTextureAndSampler(Cbs, stage, binding, texture, sampler);
|
_descriptorSetUpdater.SetTextureAndSampler(Cbs, stage, binding, texture, sampler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetTextureAndSamplerIdentitySwizzle(ShaderStage stage, int binding, ITexture texture, ISampler sampler)
|
||||||
|
{
|
||||||
|
_descriptorSetUpdater.SetTextureAndSamplerIdentitySwizzle(Cbs, stage, binding, texture, sampler);
|
||||||
|
}
|
||||||
|
|
||||||
public void SetTransformFeedbackBuffers(ReadOnlySpan<BufferRange> buffers)
|
public void SetTransformFeedbackBuffers(ReadOnlySpan<BufferRange> buffers)
|
||||||
{
|
{
|
||||||
PauseTransformFeedbackInternal();
|
PauseTransformFeedbackInternal();
|
||||||
|
@@ -261,7 +261,7 @@ namespace Ryujinx.HLE.HOS
|
|||||||
AudioInputManager = new AudioInputManager();
|
AudioInputManager = new AudioInputManager();
|
||||||
AudioRendererManager = new AudioRendererManager(tickSource);
|
AudioRendererManager = new AudioRendererManager(tickSource);
|
||||||
AudioRendererManager.SetVolume(Device.Configuration.AudioVolume);
|
AudioRendererManager.SetVolume(Device.Configuration.AudioVolume);
|
||||||
AudioDeviceSessionRegistry = new VirtualDeviceSessionRegistry();
|
AudioDeviceSessionRegistry = new VirtualDeviceSessionRegistry(Device.AudioDeviceDriver);
|
||||||
|
|
||||||
IWritableEvent[] audioOutputRegisterBufferEvents = new IWritableEvent[Constants.AudioOutSessionCountMax];
|
IWritableEvent[] audioOutputRegisterBufferEvents = new IWritableEvent[Constants.AudioOutSessionCountMax];
|
||||||
|
|
||||||
|
@@ -321,27 +321,27 @@ namespace Ryujinx.Ui
|
|||||||
|
|
||||||
_toggleDockedMode = toggleDockedMode;
|
_toggleDockedMode = toggleDockedMode;
|
||||||
|
|
||||||
if (ConfigurationState.Instance.Hid.EnableMouse.Value)
|
if (_isMouseInClient)
|
||||||
{
|
{
|
||||||
if (_isMouseInClient)
|
if (ConfigurationState.Instance.Hid.EnableMouse.Value)
|
||||||
{
|
{
|
||||||
Window.Cursor = _invisibleCursor;
|
Window.Cursor = _invisibleCursor;
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
else
|
|
||||||
{
|
|
||||||
switch (_hideCursorMode)
|
|
||||||
{
|
{
|
||||||
case HideCursorMode.OnIdle:
|
switch (_hideCursorMode)
|
||||||
long cursorMoveDelta = Stopwatch.GetTimestamp() - _lastCursorMoveTime;
|
{
|
||||||
Window.Cursor = (cursorMoveDelta >= CursorHideIdleTime * Stopwatch.Frequency) ? _invisibleCursor : null;
|
case HideCursorMode.OnIdle:
|
||||||
break;
|
long cursorMoveDelta = Stopwatch.GetTimestamp() - _lastCursorMoveTime;
|
||||||
case HideCursorMode.Always:
|
Window.Cursor = (cursorMoveDelta >= CursorHideIdleTime * Stopwatch.Frequency) ? _invisibleCursor : null;
|
||||||
Window.Cursor = _invisibleCursor;
|
break;
|
||||||
break;
|
case HideCursorMode.Always:
|
||||||
case HideCursorMode.Never:
|
Window.Cursor = _invisibleCursor;
|
||||||
Window.Cursor = null;
|
break;
|
||||||
break;
|
case HideCursorMode.Never:
|
||||||
|
Window.Cursor = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user