Compare commits
101 Commits
Author | SHA1 | Date | |
---|---|---|---|
5bd2c58ad6 | |||
cf4c78b9c8 | |||
52aa4b6c22 | |||
5a02433080 | |||
915a0f7173 | |||
0cc266ff19 | |||
9a1b74799d | |||
638f3761f3 | |||
193ca3c9a2 | |||
eb0bb36bbf | |||
0e95a8271a | |||
76b474e97b | |||
27ee86f33b | |||
f7ec310231 | |||
e94d24f508 | |||
2bf4555591 | |||
86de288142 | |||
f35aa8e9d6 | |||
0e8e735a6d | |||
0003a7c118 | |||
2cdcfe46d8 | |||
fe30c03cac | |||
5813b2e354 | |||
af1906ea04 | |||
68848000f7 | |||
d98da47a0f | |||
306f7e93a0 | |||
8954ff3af2 | |||
d2f3adbf69 | |||
d511c845b7 | |||
21c9ac6240 | |||
81c9052847 | |||
9367e3c35d | |||
52cf141874 | |||
8a352df3c6 | |||
c545c59851 | |||
96ea4e8c8e | |||
b8f48bcf64 | |||
6966211e07 | |||
57524a4c8a | |||
f4539c49d8 | |||
12c62fdbc2 | |||
e3c6be5e29 | |||
4741a05df9 | |||
c6676007bf | |||
92b0b7d753 | |||
232237bf28 | |||
c27e453fd3 | |||
0e037d0213 | |||
0dca1fbe12 | |||
35d91a0e58 | |||
a73a5d7e85 | |||
832a5e8852 | |||
96d1f0da2d | |||
597388ecda | |||
1cf6d7b7bb | |||
7bc9d0cdad | |||
dc0dbc50ab | |||
994f4dc77d | |||
c9e297b74c | |||
dd514a115c | |||
7e0b4bd538 | |||
378080eb87 | |||
e8f5e97fa4 | |||
f3873620a3 | |||
986ac9ff83 | |||
42b9c1e8fe | |||
3b375525fb | |||
e6658c133c | |||
5b42a4d2c4 | |||
8f0c89ffd6 | |||
2c9715acf6 | |||
274af65f69 | |||
4ca78eded5 | |||
6cb6b15612 | |||
2725e40838 | |||
c2e4c8f98e | |||
b53e7ffd46 | |||
ac66643346 | |||
21e88f17f6 | |||
5626f2ca1c | |||
402f05b8ef | |||
fb27042e01 | |||
69a9de33d3 | |||
bba51c2eeb | |||
fc26189fe1 | |||
a40c90e7dd | |||
f864a49014 | |||
ecbf303266 | |||
b3bf05356b | |||
cb4b58052f | |||
f8cdd5f484 | |||
22202be394 | |||
17ba217940 | |||
aae4595bdb | |||
880fd3cfcb | |||
f679f25e08 | |||
c2709b3bdd | |||
2b6e81deea | |||
7271f1b18e | |||
5fda543f84 |
19
.github/ISSUE_TEMPLATE/missing_shader_instruction.yml
vendored
Normal file
19
.github/ISSUE_TEMPLATE/missing_shader_instruction.yml
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
name: Missing Shader Instruction
|
||||
description: Shader Instruction is missing in Ryujinx.
|
||||
title: "[GPU]"
|
||||
labels: [gpu, not-implemented]
|
||||
body:
|
||||
- type: textarea
|
||||
id: instruction
|
||||
attributes:
|
||||
label: Shader instruction
|
||||
description: What shader instruction is missing?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: required
|
||||
attributes:
|
||||
label: Required by
|
||||
description: Add links to the [compatibility list page(s)](https://github.com/Ryujinx/Ryujinx-Games-List/issues) of the game(s) that require this instruction.
|
||||
validations:
|
||||
required: true
|
8
.github/assign/audio.yml
vendored
Normal file
8
.github/assign/audio.yml
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
addReviewers: true
|
||||
|
||||
reviewers:
|
||||
- marysaka
|
||||
|
||||
filterLabels:
|
||||
include:
|
||||
- audio
|
11
.github/assign/cpu.yml
vendored
Normal file
11
.github/assign/cpu.yml
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
addReviewers: true
|
||||
|
||||
reviewers:
|
||||
- gdkchan
|
||||
- riperiperi
|
||||
- marysaka
|
||||
- LDj3SNuD
|
||||
|
||||
filterLabels:
|
||||
include:
|
||||
- cpu
|
4
.github/assign/global.yml
vendored
Normal file
4
.github/assign/global.yml
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
addReviewers: true
|
||||
|
||||
reviewers:
|
||||
- Ryujinx/developers
|
10
.github/assign/gpu.yml
vendored
Normal file
10
.github/assign/gpu.yml
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
addReviewers: true
|
||||
|
||||
reviewers:
|
||||
- gdkchan
|
||||
- riperiperi
|
||||
- marysaka
|
||||
|
||||
filterLabels:
|
||||
include:
|
||||
- gpu
|
11
.github/assign/gui.yml
vendored
Normal file
11
.github/assign/gui.yml
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
addReviewers: true
|
||||
|
||||
reviewers:
|
||||
- Ack77
|
||||
- emmauss
|
||||
- TSRBerry
|
||||
- marysaka
|
||||
|
||||
filterLabels:
|
||||
include:
|
||||
- gui
|
11
.github/assign/horizon.yml
vendored
Normal file
11
.github/assign/horizon.yml
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
addReviewers: true
|
||||
|
||||
reviewers:
|
||||
- gdkchan
|
||||
- Ack77
|
||||
- marysaka
|
||||
- TSRBerry
|
||||
|
||||
filterLabels:
|
||||
include:
|
||||
- horizon
|
9
.github/assign/infra.yml
vendored
Normal file
9
.github/assign/infra.yml
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
addReviewers: true
|
||||
|
||||
reviewers:
|
||||
- marysaka
|
||||
- TSRBerry
|
||||
|
||||
filterLabels:
|
||||
include:
|
||||
- infra
|
33
.github/labeler.yml
vendored
Normal file
33
.github/labeler.yml
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
audio: 'src/Ryujinx.Audio*/**'
|
||||
|
||||
cpu:
|
||||
- 'src/ARMeilleure/**'
|
||||
- 'src/Ryujinx.Cpu/**'
|
||||
- 'src/Ryujinx.Memory/**'
|
||||
|
||||
gpu:
|
||||
- 'src/Ryujinx.Graphics.*/**'
|
||||
- 'src/Spv.Generator/**'
|
||||
- 'src/Ryujinx.ShaderTools/**'
|
||||
|
||||
'graphics-backend:opengl': 'src/Ryujinx.Graphics.OpenGL/**'
|
||||
'graphics-backend:vulkan':
|
||||
- 'src/Ryujinx.Graphics.Vulkan/**'
|
||||
- 'src/Spv.Generator/**'
|
||||
|
||||
gui:
|
||||
- 'src/Ryujinx/**'
|
||||
- 'src/Ryujinx.Ui.Common/**'
|
||||
- 'src/Ryujinx.Ui.LocaleGenerator/**'
|
||||
- 'src/Ryujinx.Ava/**'
|
||||
|
||||
horizon:
|
||||
- 'src/Ryujinx.HLE/**'
|
||||
- 'src/Ryujinx.Horizon*/**'
|
||||
|
||||
kernel: 'src/Ryujinx.HLE/HOS/Kernel/**'
|
||||
|
||||
infra:
|
||||
- '.github/**'
|
||||
- 'distribution/**'
|
||||
- 'Directory.Packages.props'
|
41
.github/workflows/build.yml
vendored
41
.github/workflows/build.yml
vendored
@ -3,20 +3,19 @@ name: Build job
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs: {}
|
||||
#push:
|
||||
# branches: [ master ]
|
||||
# paths-ignore:
|
||||
# - '.github/*'
|
||||
# - '.github/ISSUE_TEMPLATE/**'
|
||||
# - '*.yml'
|
||||
# - 'README.md'
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
paths-ignore:
|
||||
- '.github/*'
|
||||
- '.github/ISSUE_TEMPLATE/**'
|
||||
- '*.yml'
|
||||
- 'README.md'
|
||||
paths:
|
||||
- '!.github/**'
|
||||
- '!*.yml'
|
||||
- '!*.json'
|
||||
- '!*.config'
|
||||
- '!README.md'
|
||||
- '.github/workflows/*.yml'
|
||||
|
||||
concurrency:
|
||||
group: pr-checks-${{ github.event.number }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
POWERSHELL_TELEMETRY_OPTOUT: 1
|
||||
@ -27,6 +26,7 @@ jobs:
|
||||
build:
|
||||
name: ${{ matrix.OS_NAME }} (${{ matrix.configuration }})
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 45
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macOS-latest, windows-latest]
|
||||
@ -38,7 +38,7 @@ jobs:
|
||||
RELEASE_ZIP_OS_NAME: linux_x64
|
||||
|
||||
- os: macOS-latest
|
||||
OS_NAME: MacOS x64
|
||||
OS_NAME: macOS x64
|
||||
DOTNET_RUNTIME_IDENTIFIER: osx-x64
|
||||
RELEASE_ZIP_OS_NAME: osx_x64
|
||||
|
||||
@ -68,15 +68,15 @@ jobs:
|
||||
|
||||
- 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
|
||||
if: github.event_name == 'pull_request'
|
||||
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||
|
||||
- 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
|
||||
if: github.event_name == 'pull_request'
|
||||
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||
|
||||
- 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
|
||||
if: github.event_name == 'pull_request'
|
||||
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||
|
||||
- name: Set executable bit
|
||||
run: |
|
||||
@ -90,25 +90,26 @@ jobs:
|
||||
with:
|
||||
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
|
||||
path: publish
|
||||
if: github.event_name == 'pull_request'
|
||||
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||
|
||||
- name: Upload Ryujinx.Headless.SDL2 artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
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
|
||||
if: github.event_name == 'pull_request'
|
||||
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||
|
||||
- name: Upload Ryujinx.Ava artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ava-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
|
||||
path: publish_ava
|
||||
if: github.event_name == 'pull_request'
|
||||
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||
|
||||
build_macos:
|
||||
name: MacOS universal (${{ matrix.configuration }})
|
||||
name: macOS Universal (${{ matrix.configuration }})
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
strategy:
|
||||
matrix:
|
||||
configuration: [ Debug, Release ]
|
||||
|
1
.github/workflows/flatpak.yml
vendored
1
.github/workflows/flatpak.yml
vendored
@ -12,6 +12,7 @@ concurrency: flatpak-release
|
||||
|
||||
jobs:
|
||||
release:
|
||||
timeout-minutes: ${{ fromJSON(vars.JOB_TIMEOUT) }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
env:
|
||||
|
1
.github/workflows/nightly_pr_comment.yml
vendored
1
.github/workflows/nightly_pr_comment.yml
vendored
@ -7,6 +7,7 @@ jobs:
|
||||
pr_comment:
|
||||
if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: ${{ fromJSON(vars.JOB_TIMEOUT) }}
|
||||
steps:
|
||||
- uses: actions/github-script@v6
|
||||
with:
|
||||
|
58
.github/workflows/pr_triage.yml
vendored
Normal file
58
.github/workflows/pr_triage.yml
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
name: "Pull Request Triage"
|
||||
on:
|
||||
pull_request_target:
|
||||
|
||||
jobs:
|
||||
triage:
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Update labels based on changes
|
||||
uses: actions/labeler@v4
|
||||
with:
|
||||
sync-labels: true
|
||||
dot: true
|
||||
|
||||
- name: Auto Assign [Audio]
|
||||
uses: kentaro-m/auto-assign-action@v1.2.5
|
||||
with:
|
||||
configuration-path: '.github/assign/audio.yml'
|
||||
if: github.event.action == 'opened'
|
||||
|
||||
- name: Auto Assign [CPU]
|
||||
uses: kentaro-m/auto-assign-action@v1.2.5
|
||||
with:
|
||||
configuration-path: '.github/assign/cpu.yml'
|
||||
if: github.event.action == 'opened'
|
||||
|
||||
- name: Auto Assign [GPU]
|
||||
uses: kentaro-m/auto-assign-action@v1.2.5
|
||||
with:
|
||||
configuration-path: '.github/assign/gpu.yml'
|
||||
if: github.event.action == 'opened'
|
||||
|
||||
- name: Auto Assign [GUI]
|
||||
uses: kentaro-m/auto-assign-action@v1.2.5
|
||||
with:
|
||||
configuration-path: '.github/assign/gui.yml'
|
||||
if: github.event.action == 'opened'
|
||||
|
||||
- name: Auto Assign [Horizon]
|
||||
uses: kentaro-m/auto-assign-action@v1.2.5
|
||||
with:
|
||||
configuration-path: '.github/assign/horizon.yml'
|
||||
if: github.event.action == 'opened'
|
||||
|
||||
- name: Auto Assign [Infra]
|
||||
uses: kentaro-m/auto-assign-action@v1.2.5
|
||||
with:
|
||||
configuration-path: '.github/assign/infra.yml'
|
||||
if: github.event.action == 'opened'
|
||||
|
||||
- name: Auto Assign [Global]
|
||||
uses: kentaro-m/auto-assign-action@v1.2.5
|
||||
with:
|
||||
configuration-path: '.github/assign/global.yml'
|
||||
if: github.event.action == 'opened'
|
9
.github/workflows/release.yml
vendored
9
.github/workflows/release.yml
vendored
@ -6,9 +6,10 @@ on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
paths-ignore:
|
||||
- '.github/*'
|
||||
- '.github/ISSUE_TEMPLATE/**'
|
||||
- '.github/**'
|
||||
- '*.yml'
|
||||
- '*.json'
|
||||
- '*.config'
|
||||
- 'README.md'
|
||||
|
||||
concurrency: release
|
||||
@ -33,7 +34,7 @@ jobs:
|
||||
shell: bash
|
||||
|
||||
- name: Create tag
|
||||
uses: actions/github-script@v5
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
github.rest.git.createRef({
|
||||
@ -46,6 +47,7 @@ jobs:
|
||||
release:
|
||||
name: Release ${{ matrix.OS_NAME }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: ${{ fromJSON(vars.JOB_TIMEOUT) }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ ubuntu-latest, windows-latest ]
|
||||
@ -143,6 +145,7 @@ jobs:
|
||||
macos_release:
|
||||
name: Release MacOS universal
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: ${{ fromJSON(vars.JOB_TIMEOUT) }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
|
@ -3,17 +3,17 @@
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageVersion Include="Avalonia" Version="0.10.19" />
|
||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="0.10.19" />
|
||||
<PackageVersion Include="Avalonia.Desktop" Version="0.10.19" />
|
||||
<PackageVersion Include="Avalonia.Diagnostics" Version="0.10.19" />
|
||||
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="0.10.19" />
|
||||
<PackageVersion Include="Avalonia" Version="0.10.21" />
|
||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="0.10.21" />
|
||||
<PackageVersion Include="Avalonia.Desktop" Version="0.10.21" />
|
||||
<PackageVersion Include="Avalonia.Diagnostics" Version="0.10.21" />
|
||||
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="0.10.21" />
|
||||
<PackageVersion Include="Avalonia.Svg" Version="0.10.18" />
|
||||
<PackageVersion Include="Avalonia.Svg.Skia" Version="0.10.18" />
|
||||
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
||||
<PackageVersion Include="Concentus" Version="1.1.7" />
|
||||
<PackageVersion Include="DiscordRichPresence" Version="1.1.3.18" />
|
||||
<PackageVersion Include="DynamicData" Version="7.13.5" />
|
||||
<PackageVersion Include="DynamicData" Version="7.14.2" />
|
||||
<PackageVersion Include="FluentAvaloniaUI" Version="1.4.5" />
|
||||
<PackageVersion Include="GtkSharp.Dependencies" Version="1.1.1" />
|
||||
<PackageVersion Include="GtkSharp.Dependencies.osx" Version="0.0.5" />
|
||||
@ -21,7 +21,7 @@
|
||||
<PackageVersion Include="LibHac" Version="0.18.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.6.2" />
|
||||
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="2.3.2" />
|
||||
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
|
||||
<PackageVersion Include="NUnit" Version="3.13.3" />
|
||||
@ -44,7 +44,7 @@
|
||||
<PackageVersion Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta11" />
|
||||
<PackageVersion Include="SPB" Version="0.0.4-build28" />
|
||||
<PackageVersion Include="System.Drawing.Common" Version="7.0.0" />
|
||||
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="6.30.1" />
|
||||
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="6.31.0" />
|
||||
<PackageVersion Include="System.IO.Hashing" Version="7.0.0" />
|
||||
<PackageVersion Include="System.Management" Version="7.0.1" />
|
||||
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />
|
||||
|
@ -11,4 +11,10 @@ if [ -f "$SCRIPT_DIR/Ryujinx.Headless.SDL2" ]; then
|
||||
RYUJINX_BIN="Ryujinx.Headless.SDL2"
|
||||
fi
|
||||
|
||||
env DOTNET_EnableAlternateStackCheck=1 "$SCRIPT_DIR/$RYUJINX_BIN" "$@"
|
||||
COMMAND="env DOTNET_EnableAlternateStackCheck=1"
|
||||
|
||||
if command -v gamemoderun > /dev/null 2>&1; then
|
||||
COMMAND="$COMMAND gamemoderun"
|
||||
fi
|
||||
|
||||
$COMMAND "$SCRIPT_DIR/$RYUJINX_BIN" "$@"
|
@ -22,9 +22,9 @@ EXTRA_ARGS=$8
|
||||
|
||||
if [ "$VERSION" == "1.1.0" ];
|
||||
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
|
||||
RELEASE_TAR_FILE_NAME=Ryujinx-$VERSION-macos_universal.app.tar
|
||||
RELEASE_TAR_FILE_NAME=test-ava-ryujinx-$VERSION-macos_universal.app.tar
|
||||
fi
|
||||
|
||||
ARM64_APP_BUNDLE="$TEMP_DIRECTORY/output_arm64/Ryujinx.app"
|
||||
|
@ -27,13 +27,31 @@ error_handler() {
|
||||
|
||||
trap 'error_handler ${LINENO}' ERR
|
||||
|
||||
# Wait for Ryujinx to exit
|
||||
# NOTE: in case no fds are open, lsof could be returning with a process still living.
|
||||
# We wait 1s and assume the process stopped after that
|
||||
lsof -p $APP_PID +r 1 &>/dev/null
|
||||
# Wait for Ryujinx to exit.
|
||||
# If the main process is still acitve, we wait for 1 second and check it again.
|
||||
# After the fifth time checking, this script exits with status 1.
|
||||
|
||||
attempt=0
|
||||
while true; do
|
||||
if lsof -p $APP_PID +r 1 &>/dev/null || ps -p "$APP_PID" &>/dev/null; then
|
||||
if [ "$attempt" -eq 4 ]; then
|
||||
exit 1
|
||||
fi
|
||||
sleep 1
|
||||
else
|
||||
break
|
||||
fi
|
||||
(( attempt++ ))
|
||||
done
|
||||
|
||||
sleep 1
|
||||
|
||||
# Now replace and reopen.
|
||||
rm -rf "$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
|
||||
|
@ -168,8 +168,6 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
Logger.StartPass(PassName.CodeGeneration);
|
||||
|
||||
//Console.Error.WriteLine(IRDumper.GetDump(cfg));
|
||||
|
||||
bool relocatable = (cctx.Options & CompilerOptions.Relocatable) != 0;
|
||||
|
||||
CodeGenContext context = new(allocResult, maxCallArgs, cfg.Blocks.Count, relocatable);
|
||||
|
@ -179,6 +179,35 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
(uint)operation.GetSource(2).AsInt32());
|
||||
break;
|
||||
|
||||
case IntrinsicType.Vector128Unary:
|
||||
GenerateVectorUnary(
|
||||
context,
|
||||
1,
|
||||
0,
|
||||
info.Inst,
|
||||
operation.Destination,
|
||||
operation.GetSource(0));
|
||||
break;
|
||||
case IntrinsicType.Vector128Binary:
|
||||
GenerateVectorBinary(
|
||||
context,
|
||||
1,
|
||||
0,
|
||||
info.Inst,
|
||||
operation.Destination,
|
||||
operation.GetSource(0),
|
||||
operation.GetSource(1));
|
||||
break;
|
||||
case IntrinsicType.Vector128BinaryRd:
|
||||
GenerateVectorUnary(
|
||||
context,
|
||||
1,
|
||||
0,
|
||||
info.Inst,
|
||||
operation.Destination,
|
||||
operation.GetSource(1));
|
||||
break;
|
||||
|
||||
case IntrinsicType.VectorUnary:
|
||||
GenerateVectorUnary(
|
||||
context,
|
||||
|
@ -19,8 +19,8 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
Add(Intrinsic.Arm64AddvV, new IntrinsicInfo(0x0e31b800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64AddS, new IntrinsicInfo(0x5e208400u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64AddV, new IntrinsicInfo(0x0e208400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64AesdV, new IntrinsicInfo(0x4e285800u, IntrinsicType.Vector128Unary));
|
||||
Add(Intrinsic.Arm64AeseV, new IntrinsicInfo(0x4e284800u, IntrinsicType.Vector128Unary));
|
||||
Add(Intrinsic.Arm64AesdV, new IntrinsicInfo(0x4e285800u, IntrinsicType.Vector128BinaryRd));
|
||||
Add(Intrinsic.Arm64AeseV, new IntrinsicInfo(0x4e284800u, IntrinsicType.Vector128BinaryRd));
|
||||
Add(Intrinsic.Arm64AesimcV, new IntrinsicInfo(0x4e287800u, IntrinsicType.Vector128Unary));
|
||||
Add(Intrinsic.Arm64AesmcV, new IntrinsicInfo(0x4e286800u, IntrinsicType.Vector128Unary));
|
||||
Add(Intrinsic.Arm64AndV, new IntrinsicInfo(0x0e201c00u, IntrinsicType.VectorBinaryBitwise));
|
||||
|
@ -23,6 +23,10 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
ScalarTernaryShlRd,
|
||||
ScalarTernaryShrRd,
|
||||
|
||||
Vector128Unary,
|
||||
Vector128Binary,
|
||||
Vector128BinaryRd,
|
||||
|
||||
VectorUnary,
|
||||
VectorUnaryBitwise,
|
||||
VectorUnaryByElem,
|
||||
@ -50,9 +54,6 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
VectorTernaryShlRd,
|
||||
VectorTernaryShrRd,
|
||||
|
||||
Vector128Unary,
|
||||
Vector128Binary,
|
||||
|
||||
GetRegister,
|
||||
SetRegister
|
||||
}
|
||||
|
@ -746,6 +746,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
info.Type == IntrinsicType.ScalarTernaryFPRdByElem ||
|
||||
info.Type == IntrinsicType.ScalarTernaryShlRd ||
|
||||
info.Type == IntrinsicType.ScalarTernaryShrRd ||
|
||||
info.Type == IntrinsicType.Vector128BinaryRd ||
|
||||
info.Type == IntrinsicType.VectorBinaryRd ||
|
||||
info.Type == IntrinsicType.VectorInsertByElem ||
|
||||
info.Type == IntrinsicType.VectorTernaryRd ||
|
||||
|
@ -17,7 +17,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
Operand res;
|
||||
|
||||
if (Optimizations.UseAesni)
|
||||
if (Optimizations.UseArm64Aes)
|
||||
{
|
||||
res = context.AddIntrinsic(Intrinsic.Arm64AesdV, d, n);
|
||||
}
|
||||
else if (Optimizations.UseAesni)
|
||||
{
|
||||
res = context.AddIntrinsic(Intrinsic.X86Aesdeclast, context.AddIntrinsic(Intrinsic.X86Xorpd, d, n), context.VectorZero());
|
||||
}
|
||||
@ -38,7 +42,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
Operand res;
|
||||
|
||||
if (Optimizations.UseAesni)
|
||||
if (Optimizations.UseArm64Aes)
|
||||
{
|
||||
res = context.AddIntrinsic(Intrinsic.Arm64AeseV, d, n);
|
||||
}
|
||||
else if (Optimizations.UseAesni)
|
||||
{
|
||||
res = context.AddIntrinsic(Intrinsic.X86Aesenclast, context.AddIntrinsic(Intrinsic.X86Xorpd, d, n), context.VectorZero());
|
||||
}
|
||||
@ -58,7 +66,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
Operand res;
|
||||
|
||||
if (Optimizations.UseAesni)
|
||||
if (Optimizations.UseArm64Aes)
|
||||
{
|
||||
res = context.AddIntrinsic(Intrinsic.Arm64AesimcV, n);
|
||||
}
|
||||
else if (Optimizations.UseAesni)
|
||||
{
|
||||
res = context.AddIntrinsic(Intrinsic.X86Aesimc, n);
|
||||
}
|
||||
@ -78,7 +90,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
Operand res;
|
||||
|
||||
if (Optimizations.UseAesni)
|
||||
if (Optimizations.UseArm64Aes)
|
||||
{
|
||||
res = context.AddIntrinsic(Intrinsic.Arm64AesmcV, n);
|
||||
}
|
||||
else if (Optimizations.UseAesni)
|
||||
{
|
||||
Operand roundKey = context.VectorZero();
|
||||
|
||||
|
@ -17,7 +17,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
Operand res;
|
||||
|
||||
if (Optimizations.UseAesni)
|
||||
if (Optimizations.UseArm64Aes)
|
||||
{
|
||||
res = context.AddIntrinsic(Intrinsic.Arm64AesdV, d, n);
|
||||
}
|
||||
else if (Optimizations.UseAesni)
|
||||
{
|
||||
res = context.AddIntrinsic(Intrinsic.X86Aesdeclast, context.AddIntrinsic(Intrinsic.X86Xorpd, d, n), context.VectorZero());
|
||||
}
|
||||
@ -38,7 +42,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
Operand res;
|
||||
|
||||
if (Optimizations.UseAesni)
|
||||
if (Optimizations.UseArm64Aes)
|
||||
{
|
||||
res = context.AddIntrinsic(Intrinsic.Arm64AeseV, d, n);
|
||||
}
|
||||
else if (Optimizations.UseAesni)
|
||||
{
|
||||
res = context.AddIntrinsic(Intrinsic.X86Aesenclast, context.AddIntrinsic(Intrinsic.X86Xorpd, d, n), context.VectorZero());
|
||||
}
|
||||
@ -58,7 +66,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
Operand res;
|
||||
|
||||
if (Optimizations.UseAesni)
|
||||
if (Optimizations.UseArm64Aes)
|
||||
{
|
||||
res = context.AddIntrinsic(Intrinsic.Arm64AesimcV, n);
|
||||
}
|
||||
else if (Optimizations.UseAesni)
|
||||
{
|
||||
res = context.AddIntrinsic(Intrinsic.X86Aesimc, n);
|
||||
}
|
||||
@ -78,7 +90,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
Operand res;
|
||||
|
||||
if (Optimizations.UseAesni)
|
||||
if (Optimizations.UseArm64Aes)
|
||||
{
|
||||
res = context.AddIntrinsic(Intrinsic.Arm64AesmcV, n);
|
||||
}
|
||||
else if (Optimizations.UseAesni)
|
||||
{
|
||||
Operand roundKey = context.VectorZero();
|
||||
|
||||
|
@ -1,5 +1,8 @@
|
||||
using System;
|
||||
|
||||
namespace ARMeilleure.IntermediateRepresentation
|
||||
{
|
||||
[Flags]
|
||||
enum Intrinsic : ushort
|
||||
{
|
||||
// X86 (SSE and AVX)
|
||||
|
@ -13,6 +13,7 @@ namespace ARMeilleure
|
||||
public static bool UseUnmanagedDispatchLoop { get; set; } = true;
|
||||
|
||||
public static bool UseAdvSimdIfAvailable { get; set; } = true;
|
||||
public static bool UseArm64AesIfAvailable { get; set; } = true;
|
||||
public static bool UseArm64PmullIfAvailable { get; set; } = true;
|
||||
|
||||
public static bool UseSseIfAvailable { get; set; } = true;
|
||||
@ -41,6 +42,7 @@ namespace ARMeilleure
|
||||
}
|
||||
|
||||
internal static bool UseAdvSimd => UseAdvSimdIfAvailable && Arm64HardwareCapabilities.SupportsAdvSimd;
|
||||
internal static bool UseArm64Aes => UseArm64AesIfAvailable && Arm64HardwareCapabilities.SupportsAes;
|
||||
internal static bool UseArm64Pmull => UseArm64PmullIfAvailable && Arm64HardwareCapabilities.SupportsPmull;
|
||||
|
||||
internal static bool UseSse => UseSseIfAvailable && X86HardwareCapabilities.SupportsSse;
|
||||
|
@ -6,10 +6,11 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
|
||||
namespace ARMeilleure.Translation.Cache
|
||||
{
|
||||
static class JitCache
|
||||
static partial class JitCache
|
||||
{
|
||||
private const int PageSize = 4 * 1024;
|
||||
private const int PageMask = PageSize - 1;
|
||||
@ -27,6 +28,10 @@ namespace ARMeilleure.Translation.Cache
|
||||
private static readonly object _lock = new object();
|
||||
private static bool _initialized;
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
[LibraryImport("kernel32.dll", SetLastError = true)]
|
||||
public static partial IntPtr FlushInstructionCache(IntPtr hProcess, IntPtr lpAddress, UIntPtr dwSize);
|
||||
|
||||
public static void Initialize(IJitMemoryAllocator allocator)
|
||||
{
|
||||
if (_initialized) return;
|
||||
@ -36,7 +41,11 @@ namespace ARMeilleure.Translation.Cache
|
||||
if (_initialized) return;
|
||||
|
||||
_jitRegion = new ReservedRegion(allocator, CacheSize);
|
||||
|
||||
if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS())
|
||||
{
|
||||
_jitCacheInvalidator = new JitCacheInvalidation(allocator);
|
||||
}
|
||||
|
||||
_cacheAllocator = new CacheMemoryAllocator(CacheSize);
|
||||
|
||||
@ -77,7 +86,14 @@ namespace ARMeilleure.Translation.Cache
|
||||
Marshal.Copy(code, 0, funcPtr, code.Length);
|
||||
ReprotectAsExecutable(funcOffset, code.Length);
|
||||
|
||||
_jitCacheInvalidator.Invalidate(funcPtr, (ulong)code.Length);
|
||||
if (OperatingSystem.IsWindows() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
||||
{
|
||||
FlushInstructionCache(Process.GetCurrentProcess().Handle, funcPtr, (UIntPtr)code.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
_jitCacheInvalidator?.Invalidate(funcPtr, (ulong)code.Length);
|
||||
}
|
||||
}
|
||||
|
||||
Add(funcOffset, code.Length, func.UnwindInfo);
|
||||
|
@ -47,8 +47,8 @@ namespace ARMeilleure.Translation.Cache
|
||||
|
||||
public JitCacheInvalidation(IJitMemoryAllocator allocator)
|
||||
{
|
||||
// On macOS, a different path is used to write to the JIT cache, which does the invalidation.
|
||||
if (!OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
||||
// On macOS and Windows, a different path is used to write to the JIT cache, which does the invalidation.
|
||||
if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
||||
{
|
||||
ulong size = (ulong)_invalidationCode.Length * sizeof(int);
|
||||
ulong mask = (ulong)ReservedRegion.DefaultGranularity - 1;
|
||||
|
@ -30,7 +30,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
private const string OuterHeaderMagicString = "PTCohd\0\0";
|
||||
private const string InnerHeaderMagicString = "PTCihd\0\0";
|
||||
|
||||
private const uint InternalVersion = 4661; //! To be incremented manually for each change to the ARMeilleure project.
|
||||
private const uint InternalVersion = 5281; //! To be incremented manually for each change to the ARMeilleure project.
|
||||
|
||||
private const string ActualDir = "0";
|
||||
private const string BackupDir = "1";
|
||||
|
@ -5,6 +5,7 @@ using Ryujinx.Memory;
|
||||
using Ryujinx.SDL2.Common;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
using static Ryujinx.Audio.Integration.IHardwareDeviceDriver;
|
||||
@ -18,6 +19,13 @@ namespace Ryujinx.Audio.Backends.SDL2
|
||||
private readonly ManualResetEvent _pauseEvent;
|
||||
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()
|
||||
{
|
||||
_updateRequiredEvent = new ManualResetEvent(false);
|
||||
@ -25,6 +33,20 @@ namespace Ryujinx.Audio.Backends.SDL2
|
||||
_sessions = new ConcurrentDictionary<SDL2HardwareDeviceSession, byte>();
|
||||
|
||||
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();
|
||||
@ -164,6 +186,11 @@ namespace Ryujinx.Audio.Backends.SDL2
|
||||
|
||||
public bool SupportsChannelCount(uint channelCount)
|
||||
{
|
||||
if (channelCount == 6)
|
||||
{
|
||||
return _supportSurroundConfiguration;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ namespace Ryujinx.Audio.Renderer.Device
|
||||
/// <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="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;
|
||||
ChannelCount = channelCount;
|
||||
|
@ -1,3 +1,4 @@
|
||||
using Ryujinx.Audio.Integration;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Device
|
||||
@ -22,7 +23,23 @@ namespace Ryujinx.Audio.Renderer.Device
|
||||
/// The current active <see cref="VirtualDevice"/>.
|
||||
/// </summary>
|
||||
// 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>
|
||||
/// Get the associated <see cref="T:VirtualDeviceSession[]"/> from an AppletResourceId.
|
||||
|
@ -31,7 +31,6 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||
private AudioRendererRenderingDevice _renderingDevice;
|
||||
private AudioRendererExecutionMode _executionMode;
|
||||
private IWritableEvent _systemEvent;
|
||||
private ManualResetEvent _terminationEvent;
|
||||
private MemoryPoolState _dspMemoryPoolState;
|
||||
private VoiceContext _voiceContext;
|
||||
private MixContext _mixContext;
|
||||
@ -83,7 +82,6 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||
public AudioRenderSystem(AudioRendererManager manager, IWritableEvent systemEvent)
|
||||
{
|
||||
_manager = manager;
|
||||
_terminationEvent = new ManualResetEvent(false);
|
||||
_dspMemoryPoolState = MemoryPoolState.Create(MemoryPoolState.LocationType.Dsp);
|
||||
_voiceContext = new VoiceContext();
|
||||
_mixContext = new MixContext();
|
||||
@ -387,11 +385,6 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||
_isActive = false;
|
||||
}
|
||||
|
||||
if (_executionMode == AudioRendererExecutionMode.Auto)
|
||||
{
|
||||
_terminationEvent.WaitOne();
|
||||
}
|
||||
|
||||
Logger.Info?.Print(LogClass.AudioRenderer, $"Stopped renderer id {_sessionId}");
|
||||
}
|
||||
|
||||
@ -668,8 +661,6 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||
{
|
||||
if (_isActive)
|
||||
{
|
||||
_terminationEvent.Reset();
|
||||
|
||||
if (!_manager.Processor.HasRemainingCommands(_sessionId))
|
||||
{
|
||||
GenerateCommandList(out CommandList commands);
|
||||
@ -686,10 +677,6 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||
_isDspRunningBehind = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_terminationEvent.Set();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -857,7 +844,6 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||
}
|
||||
|
||||
_manager.Unregister(this);
|
||||
_terminationEvent.Dispose();
|
||||
_workBufferMemoryPin.Dispose();
|
||||
|
||||
if (MemoryManager is IRefCounted rc)
|
||||
|
@ -40,6 +40,7 @@ using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.Formats.Png;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using SixLabors.ImageSharp.Processing;
|
||||
using SPB.Graphics.Exceptions;
|
||||
using SPB.Graphics.Vulkan;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -86,12 +87,14 @@ namespace Ryujinx.Ava
|
||||
private KeyboardHotkeyState _prevHotkeyState;
|
||||
|
||||
private long _lastCursorMoveTime;
|
||||
private bool _isCursorInRenderer;
|
||||
private bool _isCursorInRenderer = true;
|
||||
|
||||
private bool _isStopped;
|
||||
private bool _isActive;
|
||||
private bool _renderingStarted;
|
||||
|
||||
private ManualResetEvent _gpuDoneEvent;
|
||||
|
||||
private IRenderer _renderer;
|
||||
private readonly Thread _renderingThread;
|
||||
private readonly CancellationTokenSource _gpuCancellationTokenSource;
|
||||
@ -160,7 +163,9 @@ namespace Ryujinx.Ava
|
||||
|
||||
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())
|
||||
{
|
||||
@ -181,9 +186,10 @@ namespace Ryujinx.Ava
|
||||
ConfigurationState.Instance.Multiplayer.LanInterfaceId.Event += UpdateLanInterfaceIdState;
|
||||
|
||||
_gpuCancellationTokenSource = new CancellationTokenSource();
|
||||
_gpuDoneEvent = new ManualResetEvent(false);
|
||||
}
|
||||
|
||||
private void TopLevel_PointerMoved(object sender, PointerEventArgs e)
|
||||
private void TopLevel_PointerEnterOrMoved(object sender, PointerEventArgs e)
|
||||
{
|
||||
if (sender is MainWindow window)
|
||||
{
|
||||
@ -201,6 +207,12 @@ namespace Ryujinx.Ava
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void TopLevel_PointerLeave(object sender, PointerEventArgs e)
|
||||
{
|
||||
_isCursorInRenderer = false;
|
||||
}
|
||||
|
||||
private void UpdateScalingFilterLevel(object sender, ReactiveEventArgs<int> e)
|
||||
{
|
||||
_renderer.Window?.SetScalingFilter((Graphics.GAL.ScalingFilter)ConfigurationState.Instance.Graphics.ScalingFilter.Value);
|
||||
@ -262,7 +274,7 @@ namespace Ryujinx.Ava
|
||||
|
||||
string directory = AppDataManager.Mode switch
|
||||
{
|
||||
AppDataManager.LaunchMode.Portable => Path.Combine(AppDataManager.BaseDirPath, "screenshots"),
|
||||
AppDataManager.LaunchMode.Portable or AppDataManager.LaunchMode.Custom => Path.Combine(AppDataManager.BaseDirPath, "screenshots"),
|
||||
_ => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), "Ryujinx")
|
||||
};
|
||||
|
||||
@ -415,10 +427,10 @@ namespace Ryujinx.Ava
|
||||
|
||||
_isActive = false;
|
||||
|
||||
if (_renderingThread.IsAlive)
|
||||
{
|
||||
_renderingThread.Join();
|
||||
}
|
||||
// NOTE: The render loop is allowed to stay alive until the renderer itself is disposed, as it may handle resource dispose.
|
||||
// We only need to wait for all commands submitted during the main gpu loop to be processed.
|
||||
_gpuDoneEvent.WaitOne();
|
||||
_gpuDoneEvent.Dispose();
|
||||
|
||||
DisplaySleep.Restore();
|
||||
|
||||
@ -446,7 +458,9 @@ namespace Ryujinx.Ava
|
||||
ConfigurationState.Instance.Graphics.ScalingFilterLevel.Event -= UpdateScalingFilterLevel;
|
||||
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.Dispose();
|
||||
@ -462,11 +476,20 @@ namespace Ryujinx.Ava
|
||||
_windowsMultimediaTimerResolution = null;
|
||||
}
|
||||
|
||||
(_rendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.MakeCurrent();
|
||||
if (_rendererHost.EmbeddedWindow is EmbeddedWindowOpenGL openGlWindow)
|
||||
{
|
||||
// Try to bind the OpenGL context before calling the shutdown event.
|
||||
openGlWindow.MakeCurrent(false, false);
|
||||
|
||||
Device.DisposeGpu();
|
||||
|
||||
(_rendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.MakeCurrent(null);
|
||||
// Unbind context and destroy everything.
|
||||
openGlWindow.MakeCurrent(true, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
Device.DisposeGpu();
|
||||
}
|
||||
}
|
||||
|
||||
private void HideCursorState_Changed(object sender, ReactiveEventArgs<HideCursorMode> state)
|
||||
@ -907,9 +930,17 @@ namespace Ryujinx.Ava
|
||||
UpdateStatus();
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure all commands in the run loop are fully executed before leaving the loop.
|
||||
if (Device.Gpu.Renderer is ThreadedRenderer threaded)
|
||||
{
|
||||
threaded.FlushThreadedCommands();
|
||||
}
|
||||
|
||||
_gpuDoneEvent.Set();
|
||||
});
|
||||
|
||||
(_rendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.MakeCurrent(null);
|
||||
(_rendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.MakeCurrent(true);
|
||||
}
|
||||
|
||||
public void UpdateStatus()
|
||||
@ -1023,7 +1054,7 @@ namespace Ryujinx.Ava
|
||||
ScreenshotRequested = true;
|
||||
break;
|
||||
case KeyboardHotkeyState.ShowUi:
|
||||
_viewModel.ShowMenuAndStatusBar = true;
|
||||
_viewModel.ShowMenuAndStatusBar = !_viewModel.ShowMenuAndStatusBar;
|
||||
break;
|
||||
case KeyboardHotkeyState.Pause:
|
||||
if (_viewModel.IsPaused)
|
||||
|
@ -74,6 +74,13 @@
|
||||
"GameListContextMenuExtractDataLogoToolTip": "Extract the Logo section from Application's current config (including updates)",
|
||||
"StatusBarGamesLoaded": "{0}/{1} Games Loaded",
|
||||
"StatusBarSystemVersion": "System Version: {0}",
|
||||
"LinuxVmMaxMapCountDialogTitle": "Low limit for memory mappings detected",
|
||||
"LinuxVmMaxMapCountDialogTextPrimary": "Would you like to increase the value of vm.max_map_count to {0}",
|
||||
"LinuxVmMaxMapCountDialogTextSecondary": "Some games might try to create more memory mappings than currently allowed. Ryujinx will crash as soon as this limit gets exceeded.",
|
||||
"LinuxVmMaxMapCountDialogButtonUntilRestart": "Yes, until the next restart",
|
||||
"LinuxVmMaxMapCountDialogButtonPersistent": "Yes, permanently",
|
||||
"LinuxVmMaxMapCountWarningTextPrimary": "Max amount of memory mappings is lower than recommended.",
|
||||
"LinuxVmMaxMapCountWarningTextSecondary": "The current value of vm.max_map_count ({0}) is lower than {1}. Some games might try to create more memory mappings than currently allowed. Ryujinx will crash as soon as this limit gets exceeded.\n\nYou might want to either manually increase the limit or install pkexec, which allows Ryujinx to assist with that.",
|
||||
"Settings": "Settings",
|
||||
"SettingsTabGeneral": "User Interface",
|
||||
"SettingsTabGeneralGeneral": "General",
|
||||
@ -216,26 +223,17 @@
|
||||
"ControllerSettingsDPadDown": "Down",
|
||||
"ControllerSettingsDPadLeft": "Left",
|
||||
"ControllerSettingsDPadRight": "Right",
|
||||
"ControllerSettingsStickButton": "Button",
|
||||
"ControllerSettingsStickUp": "Up",
|
||||
"ControllerSettingsStickDown": "Down",
|
||||
"ControllerSettingsStickLeft": "Left",
|
||||
"ControllerSettingsStickRight": "Right",
|
||||
"ControllerSettingsStickStick": "Stick",
|
||||
"ControllerSettingsStickInvertXAxis": "Invert Stick X",
|
||||
"ControllerSettingsStickInvertYAxis": "Invert Stick Y",
|
||||
"ControllerSettingsStickDeadzone": "Deadzone:",
|
||||
"ControllerSettingsLStick": "Left Stick",
|
||||
"ControllerSettingsLStickButton": "Button",
|
||||
"ControllerSettingsLStickUp": "Up",
|
||||
"ControllerSettingsLStickDown": "Down",
|
||||
"ControllerSettingsLStickLeft": "Left",
|
||||
"ControllerSettingsLStickRight": "Right",
|
||||
"ControllerSettingsLStickStick": "Stick",
|
||||
"ControllerSettingsLStickInvertXAxis": "Invert Stick X",
|
||||
"ControllerSettingsLStickInvertYAxis": "Invert Stick Y",
|
||||
"ControllerSettingsLStickDeadzone": "Deadzone:",
|
||||
"ControllerSettingsRStick": "Right Stick",
|
||||
"ControllerSettingsRStickButton": "Button",
|
||||
"ControllerSettingsRStickUp": "Up",
|
||||
"ControllerSettingsRStickDown": "Down",
|
||||
"ControllerSettingsRStickLeft": "Left",
|
||||
"ControllerSettingsRStickRight": "Right",
|
||||
"ControllerSettingsRStickStick": "Stick",
|
||||
"ControllerSettingsRStickInvertXAxis": "Invert Stick X",
|
||||
"ControllerSettingsRStickInvertYAxis": "Invert Stick Y",
|
||||
"ControllerSettingsRStickDeadzone": "Deadzone:",
|
||||
"ControllerSettingsTriggersLeft": "Triggers Left",
|
||||
"ControllerSettingsTriggersRight": "Triggers Right",
|
||||
"ControllerSettingsTriggersButtonsLeft": "Trigger Buttons Left",
|
||||
@ -291,6 +289,7 @@
|
||||
"ControllerSettingsSaveProfileToolTip": "Save Profile",
|
||||
"MenuBarFileToolsTakeScreenshot": "Take Screenshot",
|
||||
"MenuBarFileToolsHideUi": "Hide UI",
|
||||
"GameListContextMenuRunApplication": "Run Application",
|
||||
"GameListContextMenuToggleFavorite": "Toggle Favorite",
|
||||
"GameListContextMenuToggleFavoriteToolTip": "Toggle Favorite status of Game",
|
||||
"SettingsTabGeneralTheme": "Theme",
|
||||
@ -545,6 +544,9 @@
|
||||
"SwkbdMinCharacters": "Must be at least {0} characters long",
|
||||
"SwkbdMinRangeCharacters": "Must be {0}-{1} characters long",
|
||||
"SoftwareKeyboard": "Software Keyboard",
|
||||
"SoftwareKeyboardModeNumbersOnly": "Must be numbers only",
|
||||
"SoftwareKeyboardModeAlphabet": "Must be non CJK-characters only",
|
||||
"SoftwareKeyboardModeASCII": "Must be ASCII text only",
|
||||
"DialogControllerAppletMessagePlayerRange": "Application requests {0} player(s) with:\n\nTYPES: {1}\n\nPLAYERS: {2}\n\n{3}Please open Settings and reconfigure Input now or press Close.",
|
||||
"DialogControllerAppletMessage": "Application requests exactly {0} player(s) with:\n\nTYPES: {1}\n\nPLAYERS: {2}\n\n{3}Please open Settings and reconfigure Input now or press Close.",
|
||||
"DialogControllerAppletDockModeSet": "Docked mode set. Handheld is also invalid.\n\n",
|
||||
@ -629,7 +631,7 @@
|
||||
"Search": "Search",
|
||||
"UserProfilesRecoverLostAccounts": "Recover Lost Accounts",
|
||||
"Recover": "Recover",
|
||||
"UserProfilesRecoverHeading" : "Saves were found for the following accounts",
|
||||
"UserProfilesRecoverHeading": "Saves were found for the following accounts",
|
||||
"UserProfilesRecoverEmptyList": "No profiles to recover",
|
||||
"GraphicsAATooltip": "Applies anti-aliasing to the game render",
|
||||
"GraphicsAALabel": "Anti-Aliasing:",
|
||||
@ -641,10 +643,12 @@
|
||||
"SmaaMedium": "SMAA Medium",
|
||||
"SmaaHigh": "SMAA High",
|
||||
"SmaaUltra": "SMAA Ultra",
|
||||
"UserEditorTitle" : "Edit User",
|
||||
"UserEditorTitleCreate" : "Create User",
|
||||
"UserEditorTitle": "Edit User",
|
||||
"UserEditorTitleCreate": "Create User",
|
||||
"SettingsTabNetworkInterface": "Network Interface:",
|
||||
"NetworkInterfaceTooltip": "The network interface used for LAN features",
|
||||
"NetworkInterfaceDefault": "Default",
|
||||
"PackagingShaders": "Packaging Shaders"
|
||||
"PackagingShaders": "Packaging Shaders",
|
||||
"AboutChangelogButton": "View Changelog on GitHub",
|
||||
"AboutChangelogButtonTooltipMessage": "Click to open the changelog for this version in your default browser."
|
||||
}
|
@ -527,6 +527,9 @@
|
||||
"SwkbdMinCharacters": "至少应为 {0} 个字长",
|
||||
"SwkbdMinRangeCharacters": "必须为 {0}-{1} 个字长",
|
||||
"SoftwareKeyboard": "软件键盘",
|
||||
"SoftwareKeyboardModeNumbersOnly": "只接受数字",
|
||||
"SoftwareKeyboardModeAlphabet": "只接受英文字母",
|
||||
"SoftwareKeyboardModeASCII": "只接受 ASCII 符号",
|
||||
"DialogControllerAppletMessagePlayerRange": "游戏需要 {0} 个玩家并满足以下要求:\n\n手柄类型:{1}\n\n玩家类型:{2}\n\n{3}请打开设置窗口,重新配置手柄输入;或者关闭返回。",
|
||||
"DialogControllerAppletMessage": "游戏需要刚好 {0} 个玩家并满足以下要求:\n\n手柄类型:{1}\n\n玩家类型:{2}\n\n{3}请打开设置窗口,重新配置手柄输入;或者关闭返回。",
|
||||
"DialogControllerAppletDockModeSet": "目前处于主机模式,无法使用掌机操作方式",
|
||||
|
@ -527,6 +527,9 @@
|
||||
"SwkbdMinCharacters": "至少應為 {0} 個字長",
|
||||
"SwkbdMinRangeCharacters": "必須為 {0}-{1} 個字長",
|
||||
"SoftwareKeyboard": "軟體鍵盤",
|
||||
"SoftwareKeyboardModeNumbersOnly": "只接受數字",
|
||||
"SoftwareKeyboardModeAlphabet": "只接受英文字母",
|
||||
"SoftwareKeyboardModeASCII": "只接受 ASCII 符號",
|
||||
"DialogControllerAppletMessagePlayerRange": "本遊戲需要 {0} 個玩家持有:\n\n類型:{1}\n\n玩家:{2}\n\n{3}請打開設定畫面,配置手把,或者關閉本視窗。",
|
||||
"DialogControllerAppletMessage": "本遊戲需要剛好 {0} 個玩家持有:\n\n類型:{1}\n\n玩家:{2}\n\n{3}請打開設定畫面,配置手把,或者關閉本視窗。",
|
||||
"DialogControllerAppletDockModeSet": "現在處於主機模式,無法使用掌機操作方式\n\n",
|
||||
|
@ -193,7 +193,7 @@ namespace Ryujinx.Ava.Common
|
||||
if (nca.Header.ContentType == 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;
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using FluentAvalonia.Core;
|
||||
using Ryujinx.Input;
|
||||
using System;
|
||||
using System.Numerics;
|
||||
@ -30,14 +29,14 @@ namespace Ryujinx.Ava.Input
|
||||
_window = window;
|
||||
|
||||
_widget.PointerMoved += Parent_PointerMovedEvent;
|
||||
_widget.PointerPressed += Parent_PointerPressEvent;
|
||||
_widget.PointerReleased += Parent_PointerReleaseEvent;
|
||||
_widget.PointerWheelChanged += Parent_ScrollEvent;
|
||||
_widget.PointerPressed += Parent_PointerPressedEvent;
|
||||
_widget.PointerReleased += Parent_PointerReleasedEvent;
|
||||
_widget.PointerWheelChanged += Parent_PointerWheelChanged;
|
||||
|
||||
_window.PointerMoved += Parent_PointerMovedEvent;
|
||||
_window.PointerPressed += Parent_PointerPressEvent;
|
||||
_window.PointerReleased += Parent_PointerReleaseEvent;
|
||||
_window.PointerWheelChanged += Parent_ScrollEvent;
|
||||
_window.PointerPressed += Parent_PointerPressedEvent;
|
||||
_window.PointerReleased += Parent_PointerReleasedEvent;
|
||||
_window.PointerWheelChanged += Parent_PointerWheelChanged;
|
||||
|
||||
PressedButtons = new bool[(int)MouseButton.Count];
|
||||
|
||||
@ -63,26 +62,25 @@ namespace Ryujinx.Ava.Input
|
||||
_size = new Size((int)rect.Width, (int)rect.Height);
|
||||
}
|
||||
|
||||
private void Parent_ScrollEvent(object o, PointerWheelEventArgs args)
|
||||
private void Parent_PointerWheelChanged(object o, PointerWheelEventArgs args)
|
||||
{
|
||||
Scroll = new Vector2((float)args.Delta.X, (float)args.Delta.Y);
|
||||
}
|
||||
|
||||
private void Parent_PointerReleaseEvent(object o, PointerReleasedEventArgs args)
|
||||
private void Parent_PointerReleasedEvent(object o, PointerReleasedEventArgs args)
|
||||
{
|
||||
int button = (int)args.InitialPressMouseButton - 1;
|
||||
uint button = (uint)args.InitialPressMouseButton - 1;
|
||||
|
||||
if (PressedButtons.Count() >= button)
|
||||
if ((uint)PressedButtons.Length > button)
|
||||
{
|
||||
PressedButtons[button] = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void Parent_PointerPressEvent(object o, PointerPressedEventArgs args)
|
||||
private void Parent_PointerPressedEvent(object o, PointerPressedEventArgs args)
|
||||
{
|
||||
int button = (int)args.GetCurrentPoint(_widget).Properties.PointerUpdateKind;
|
||||
uint button = (uint)args.GetCurrentPoint(_widget).Properties.PointerUpdateKind;
|
||||
|
||||
if (PressedButtons.Count() >= button)
|
||||
if ((uint)PressedButtons.Length > button)
|
||||
{
|
||||
PressedButtons[button] = true;
|
||||
}
|
||||
@ -97,17 +95,17 @@ namespace Ryujinx.Ava.Input
|
||||
|
||||
public void SetMousePressed(MouseButton button)
|
||||
{
|
||||
if (PressedButtons.Count() >= (int)button)
|
||||
if ((uint)PressedButtons.Length > (uint)button)
|
||||
{
|
||||
PressedButtons[(int)button] = true;
|
||||
PressedButtons[(uint)button] = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetMouseReleased(MouseButton button)
|
||||
{
|
||||
if (PressedButtons.Count() >= (int)button)
|
||||
if ((uint)PressedButtons.Length > (uint)button)
|
||||
{
|
||||
PressedButtons[(int)button] = false;
|
||||
PressedButtons[(uint)button] = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,9 +116,9 @@ namespace Ryujinx.Ava.Input
|
||||
|
||||
public bool IsButtonPressed(MouseButton button)
|
||||
{
|
||||
if (PressedButtons.Count() >= (int)button)
|
||||
if ((uint)PressedButtons.Length > (uint)button)
|
||||
{
|
||||
return PressedButtons[(int)button];
|
||||
return PressedButtons[(uint)button];
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -146,14 +144,14 @@ namespace Ryujinx.Ava.Input
|
||||
_isDisposed = true;
|
||||
|
||||
_widget.PointerMoved -= Parent_PointerMovedEvent;
|
||||
_widget.PointerPressed -= Parent_PointerPressEvent;
|
||||
_widget.PointerReleased -= Parent_PointerReleaseEvent;
|
||||
_widget.PointerWheelChanged -= Parent_ScrollEvent;
|
||||
_widget.PointerPressed -= Parent_PointerPressedEvent;
|
||||
_widget.PointerReleased -= Parent_PointerReleasedEvent;
|
||||
_widget.PointerWheelChanged -= Parent_PointerWheelChanged;
|
||||
|
||||
_window.PointerMoved -= Parent_PointerMovedEvent;
|
||||
_window.PointerPressed -= Parent_PointerPressEvent;
|
||||
_window.PointerReleased -= Parent_PointerReleaseEvent;
|
||||
_window.PointerWheelChanged -= Parent_ScrollEvent;
|
||||
_window.PointerPressed -= Parent_PointerPressedEvent;
|
||||
_window.PointerReleased -= Parent_PointerReleasedEvent;
|
||||
_window.PointerWheelChanged -= Parent_PointerWheelChanged;
|
||||
|
||||
_widget = null;
|
||||
}
|
||||
|
@ -740,6 +740,18 @@ namespace Ryujinx.Modules
|
||||
{
|
||||
var files = Directory.EnumerateFiles(HomeDir); // All files directly in base dir.
|
||||
|
||||
// Determine and exclude user files only when the updater is running, not when cleaning old files
|
||||
if (_running && !OperatingSystem.IsMacOS())
|
||||
{
|
||||
// Compare the loose files in base directory against the loose files from the incoming update, and store foreign ones in a user list.
|
||||
var oldFiles = Directory.EnumerateFiles(HomeDir, "*", SearchOption.TopDirectoryOnly).Select(Path.GetFileName);
|
||||
var newFiles = Directory.EnumerateFiles(UpdatePublishDir, "*", SearchOption.TopDirectoryOnly).Select(Path.GetFileName);
|
||||
var userFiles = oldFiles.Except(newFiles).Select(filename => Path.Combine(HomeDir, filename));
|
||||
|
||||
// Remove user files from the paths in files.
|
||||
files = files.Except(userFiles);
|
||||
}
|
||||
|
||||
if (OperatingSystem.IsWindows())
|
||||
{
|
||||
foreach (string dir in WindowsDependencyDirs)
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
<PropertyGroup Condition="'$(RuntimeIdentifier)' != ''">
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
<TrimmerSingleWarn>false</TrimmerSingleWarn>
|
||||
<PublishTrimmed>true</PublishTrimmed>
|
||||
<TrimMode>partial</TrimMode>
|
||||
</PropertyGroup>
|
||||
|
@ -9,14 +9,17 @@ using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.HLE.HOS.Applets;
|
||||
using Ryujinx.HLE.HOS.Applets.SoftwareKeyboard;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Controls
|
||||
{
|
||||
internal partial class SwkbdAppletDialog : UserControl
|
||||
{
|
||||
private Predicate<int> _checkLength;
|
||||
private Predicate<int> _checkLength = _ => true;
|
||||
private Predicate<string> _checkInput = _ => true;
|
||||
private int _inputMax;
|
||||
private int _inputMin;
|
||||
private string _placeholder;
|
||||
@ -35,8 +38,6 @@ namespace Ryujinx.Ava.UI.Controls
|
||||
Input.Watermark = _placeholder;
|
||||
|
||||
Input.AddHandler(TextInputEvent, Message_TextInput, RoutingStrategies.Tunnel, true);
|
||||
|
||||
SetInputLengthValidation(0, int.MaxValue); // Disable by default.
|
||||
}
|
||||
|
||||
public SwkbdAppletDialog()
|
||||
@ -67,6 +68,7 @@ namespace Ryujinx.Ava.UI.Controls
|
||||
string input = string.Empty;
|
||||
|
||||
content.SetInputLengthValidation(args.StringLengthMin, args.StringLengthMax);
|
||||
content.SetInputValidation(args.KeyboardMode);
|
||||
|
||||
content._host = contentDialog;
|
||||
contentDialog.Title = title;
|
||||
@ -91,6 +93,12 @@ namespace Ryujinx.Ava.UI.Controls
|
||||
return (result, input);
|
||||
}
|
||||
|
||||
private void ApplyValidationInfo(string text)
|
||||
{
|
||||
Error.IsVisible = !string.IsNullOrEmpty(text);
|
||||
Error.Text = text;
|
||||
}
|
||||
|
||||
public void SetInputLengthValidation(int min, int max)
|
||||
{
|
||||
_inputMin = Math.Min(min, max);
|
||||
@ -99,6 +107,8 @@ namespace Ryujinx.Ava.UI.Controls
|
||||
Error.IsVisible = false;
|
||||
Error.FontStyle = FontStyle.Italic;
|
||||
|
||||
string validationInfoText = "";
|
||||
|
||||
if (_inputMin <= 0 && _inputMax == int.MaxValue) // Disable.
|
||||
{
|
||||
Error.IsVisible = false;
|
||||
@ -107,21 +117,48 @@ namespace Ryujinx.Ava.UI.Controls
|
||||
}
|
||||
else if (_inputMin > 0 && _inputMax == int.MaxValue)
|
||||
{
|
||||
Error.IsVisible = true;
|
||||
|
||||
Error.Text = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SwkbdMinCharacters, _inputMin);
|
||||
validationInfoText = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SwkbdMinCharacters, _inputMin);
|
||||
|
||||
_checkLength = length => _inputMin <= length;
|
||||
}
|
||||
else
|
||||
{
|
||||
Error.IsVisible = true;
|
||||
|
||||
Error.Text = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SwkbdMinRangeCharacters, _inputMin, _inputMax);
|
||||
validationInfoText = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SwkbdMinRangeCharacters, _inputMin, _inputMax);
|
||||
|
||||
_checkLength = length => _inputMin <= length && length <= _inputMax;
|
||||
}
|
||||
|
||||
ApplyValidationInfo(validationInfoText);
|
||||
Message_TextInput(this, new TextInputEventArgs());
|
||||
}
|
||||
|
||||
private void SetInputValidation(KeyboardMode mode)
|
||||
{
|
||||
string validationInfoText = Error.Text;
|
||||
string localeText;
|
||||
switch (mode)
|
||||
{
|
||||
case KeyboardMode.NumbersOnly:
|
||||
localeText = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SoftwareKeyboardModeNumbersOnly);
|
||||
validationInfoText = string.IsNullOrEmpty(validationInfoText) ? localeText : string.Join("\n", validationInfoText, localeText);
|
||||
_checkInput = text => text.All(char.IsDigit);
|
||||
break;
|
||||
case KeyboardMode.Alphabet:
|
||||
localeText = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SoftwareKeyboardModeAlphabet);
|
||||
validationInfoText = string.IsNullOrEmpty(validationInfoText) ? localeText : string.Join("\n", validationInfoText, localeText);
|
||||
_checkInput = text => text.All(value => !CJKCharacterValidation.IsCJK(value));
|
||||
break;
|
||||
case KeyboardMode.ASCII:
|
||||
localeText = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SoftwareKeyboardModeASCII);
|
||||
validationInfoText = string.IsNullOrEmpty(validationInfoText) ? localeText : string.Join("\n", validationInfoText, localeText);
|
||||
_checkInput = text => text.All(char.IsAscii);
|
||||
break;
|
||||
default:
|
||||
_checkInput = _ => true;
|
||||
break;
|
||||
}
|
||||
|
||||
ApplyValidationInfo(validationInfoText);
|
||||
Message_TextInput(this, new TextInputEventArgs());
|
||||
}
|
||||
|
||||
@ -129,7 +166,7 @@ namespace Ryujinx.Ava.UI.Controls
|
||||
{
|
||||
if (_host != null)
|
||||
{
|
||||
_host.IsPrimaryButtonEnabled = _checkLength(Message.Length);
|
||||
_host.IsPrimaryButtonEnabled = _checkLength(Message.Length) && _checkInput(Message);
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,7 +178,7 @@ namespace Ryujinx.Ava.UI.Controls
|
||||
}
|
||||
else
|
||||
{
|
||||
_host.IsPrimaryButtonEnabled = _checkLength(Message.Length);
|
||||
_host.IsPrimaryButtonEnabled = _checkLength(Message.Length) && _checkInput(Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,9 @@
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale">
|
||||
<MenuItem
|
||||
Click="RunApplication_Click"
|
||||
Header="{locale:Locale GameListContextMenuRunApplication}" />
|
||||
<MenuItem
|
||||
Click="ToggleFavorite_Click"
|
||||
Header="{locale:Locale GameListContextMenuToggleFavorite}"
|
||||
|
@ -323,5 +323,15 @@ namespace Ryujinx.Ava.UI.Controls
|
||||
await ApplicationHelper.ExtractSection(NcaSectionType.Logo, viewModel.SelectedApplication.Path, viewModel.SelectedApplication.TitleName);
|
||||
}
|
||||
}
|
||||
|
||||
public void RunApplication_Click(object sender, RoutedEventArgs args)
|
||||
{
|
||||
var viewModel = (sender as MenuItem)?.DataContext as MainWindowViewModel;
|
||||
|
||||
if (viewModel?.SelectedApplication != null)
|
||||
{
|
||||
viewModel.LoadApplication(viewModel.SelectedApplication.Path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -32,10 +32,10 @@
|
||||
<ListBox.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<flex:FlexPanel
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Stretch"
|
||||
AlignContent="FlexStart"
|
||||
JustifyContent="Center" />
|
||||
JustifyContent="FlexStart" />
|
||||
</ItemsPanelTemplate>
|
||||
</ListBox.ItemsPanel>
|
||||
<ListBox.Styles>
|
||||
|
@ -21,6 +21,7 @@ namespace Ryujinx.Ava.UI.Helpers
|
||||
if (value is byte[] buffer && targetType == typeof(IImage))
|
||||
{
|
||||
MemoryStream mem = new(buffer);
|
||||
|
||||
return new Bitmap(mem);
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,6 @@ using Avalonia.Threading;
|
||||
using FluentAvalonia.Core;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.UI.Controls;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Common.Logging;
|
||||
using System;
|
||||
@ -19,7 +18,7 @@ namespace Ryujinx.Ava.UI.Helpers
|
||||
{
|
||||
private static bool _isChoiceDialogOpen;
|
||||
|
||||
public async static Task<UserResult> ShowContentDialog(
|
||||
private async static Task<UserResult> ShowContentDialog(
|
||||
string title,
|
||||
object content,
|
||||
string primaryButton,
|
||||
@ -67,7 +66,7 @@ namespace Ryujinx.Ava.UI.Helpers
|
||||
return result;
|
||||
}
|
||||
|
||||
private async static Task<UserResult> ShowTextDialog(
|
||||
public async static Task<UserResult> ShowTextDialog(
|
||||
string title,
|
||||
string primaryText,
|
||||
string secondaryText,
|
||||
@ -319,7 +318,7 @@ namespace Ryujinx.Ava.UI.Helpers
|
||||
|
||||
Window parent = GetMainWindow();
|
||||
|
||||
if (parent != null && parent.IsActive && parent is MainWindow window && window.ViewModel.IsGameRunning)
|
||||
if (parent != null && parent.IsActive && (parent as MainWindow).ViewModel.IsGameRunning)
|
||||
{
|
||||
contentDialogOverlayWindow = new()
|
||||
{
|
||||
|
@ -3,10 +3,10 @@ using Avalonia.Controls;
|
||||
using Avalonia.Controls.Notifications;
|
||||
using Avalonia.Threading;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Common;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Helpers
|
||||
{
|
||||
@ -17,7 +17,6 @@ namespace Ryujinx.Ava.UI.Helpers
|
||||
|
||||
private static WindowNotificationManager _notificationManager;
|
||||
|
||||
private static readonly ManualResetEvent _templateAppliedEvent = new(false);
|
||||
private static readonly BlockingCollection<Notification> _notifications = new();
|
||||
|
||||
public static void SetNotificationManager(Window host)
|
||||
@ -29,25 +28,31 @@ namespace Ryujinx.Ava.UI.Helpers
|
||||
Margin = new Thickness(0, 0, 15, 40)
|
||||
};
|
||||
|
||||
_notificationManager.TemplateApplied += (sender, args) =>
|
||||
{
|
||||
_templateAppliedEvent.Set();
|
||||
};
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
_templateAppliedEvent.WaitOne();
|
||||
|
||||
foreach (var notification in _notifications.GetConsumingEnumerable())
|
||||
var maybeAsyncWorkQueue = new Lazy<AsyncWorkQueue<Notification>>(
|
||||
() => new AsyncWorkQueue<Notification>(notification =>
|
||||
{
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
_notificationManager.Show(notification);
|
||||
});
|
||||
},
|
||||
"UI.NotificationThread",
|
||||
_notifications),
|
||||
LazyThreadSafetyMode.ExecutionAndPublication);
|
||||
|
||||
await Task.Delay(NotificationDelayInMs / MaxNotifications);
|
||||
_notificationManager.TemplateApplied += (sender, args) =>
|
||||
{
|
||||
// NOTE: Force creation of the AsyncWorkQueue.
|
||||
_ = maybeAsyncWorkQueue.Value;
|
||||
};
|
||||
|
||||
host.Closing += (sender, args) =>
|
||||
{
|
||||
if (maybeAsyncWorkQueue.IsValueCreated)
|
||||
{
|
||||
maybeAsyncWorkQueue.Value.Dispose();
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
public static void Show(string title, string text, NotificationType type, bool waitingExit = false, Action onClick = null, Action onClose = null)
|
||||
|
@ -123,7 +123,7 @@ namespace Ryujinx.Ava.UI.Renderer
|
||||
}
|
||||
else
|
||||
{
|
||||
X11Window = PlatformHelper.CreateOpenGLWindow(FramebufferFormat.Default, 0, 0, 100, 100) as GLXWindow;
|
||||
X11Window = PlatformHelper.CreateOpenGLWindow(new FramebufferFormat(new ColorFormat(8, 8, 8, 0), 16, 0, ColorFormat.Zero, 0, 2, false), 0, 0, 100, 100) as GLXWindow;
|
||||
}
|
||||
|
||||
WindowHandle = X11Window.WindowHandle.RawHandle;
|
||||
|
@ -1,9 +1,11 @@
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Graphics.OpenGL;
|
||||
using Ryujinx.Ui.Common.Configuration;
|
||||
using SPB.Graphics;
|
||||
using SPB.Graphics.Exceptions;
|
||||
using SPB.Graphics.OpenGL;
|
||||
using SPB.Platform;
|
||||
using SPB.Platform.WGL;
|
||||
@ -18,8 +20,6 @@ namespace Ryujinx.Ava.UI.Renderer
|
||||
|
||||
public OpenGLContextBase Context { get; set; }
|
||||
|
||||
public EmbeddedWindowOpenGL() { }
|
||||
|
||||
protected override void OnWindowDestroying()
|
||||
{
|
||||
Context.Dispose();
|
||||
@ -62,14 +62,21 @@ namespace Ryujinx.Ava.UI.Renderer
|
||||
Context.MakeCurrent(null);
|
||||
}
|
||||
|
||||
public void MakeCurrent()
|
||||
public void MakeCurrent(bool unbind = false, bool shouldThrow = true)
|
||||
{
|
||||
Context?.MakeCurrent(_window);
|
||||
try
|
||||
{
|
||||
Context?.MakeCurrent(!unbind ? _window : null);
|
||||
}
|
||||
catch (ContextException e)
|
||||
{
|
||||
if (shouldThrow)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
public void MakeCurrent(NativeWindowBase window)
|
||||
{
|
||||
Context?.MakeCurrent(window);
|
||||
Logger.Warning?.Print(LogClass.Ui, $"Failed to {(!unbind ? "bind" : "unbind")} OpenGL context: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
public void SwapBuffers()
|
||||
|
@ -7,6 +7,7 @@ using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Input;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Ava.UI.Views.Input;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Configuration;
|
||||
@ -30,7 +31,7 @@ using Key = Ryujinx.Common.Configuration.Hid.Key;
|
||||
|
||||
namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
public class ControllerSettingsViewModel : BaseModel, IDisposable
|
||||
public class ControllerInputViewModel : BaseModel, IDisposable
|
||||
{
|
||||
private const string Disabled = "disabled";
|
||||
private const string ProControllerResource = "Ryujinx.Ui.Common/Resources/Controller_ProCon.svg";
|
||||
@ -231,7 +232,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
public InputConfig Config { get; set; }
|
||||
|
||||
public ControllerSettingsViewModel(UserControl owner) : this()
|
||||
public ControllerInputViewModel(UserControl owner) : this()
|
||||
{
|
||||
_owner = owner;
|
||||
|
||||
@ -258,7 +259,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public ControllerSettingsViewModel()
|
||||
public ControllerInputViewModel()
|
||||
{
|
||||
PlayerIndexes = new ObservableCollection<PlayerModel>();
|
||||
Controllers = new ObservableCollection<ControllerModel>();
|
||||
@ -328,12 +329,12 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
public async void ShowMotionConfig()
|
||||
{
|
||||
await MotionSettingsWindow.Show(this);
|
||||
await MotionInputView.Show(this);
|
||||
}
|
||||
|
||||
public async void ShowRumbleConfig()
|
||||
{
|
||||
await RumbleSettingsWindow.Show(this);
|
||||
await RumbleInputView.Show(this);
|
||||
}
|
||||
|
||||
private void LoadInputDriver()
|
@ -257,6 +257,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
OnPropertyChanged();
|
||||
OnPropertyChanged(nameof(EnableNonGameRunningControls));
|
||||
OnPropertyChanged(nameof(IsAppletMenuActive));
|
||||
OnPropertyChanged(nameof(StatusBarVisible));
|
||||
OnPropertyChanged(nameof(ShowFirmwareStatus));
|
||||
}
|
||||
@ -1529,6 +1530,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
double sessionTimePlayed = DateTime.UtcNow.Subtract(appMetadata.LastPlayed.Value).TotalSeconds;
|
||||
appMetadata.TimePlayed += Math.Round(sessionTimePlayed, MidpointRounding.AwayFromZero);
|
||||
}
|
||||
|
||||
appMetadata.LastPlayed = DateTime.UtcNow;
|
||||
});
|
||||
}
|
||||
|
||||
|
93
src/Ryujinx.Ava/UI/ViewModels/MotionInputViewModel.cs
Normal file
93
src/Ryujinx.Ava/UI/ViewModels/MotionInputViewModel.cs
Normal file
@ -0,0 +1,93 @@
|
||||
namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
public class MotionInputViewModel : BaseModel
|
||||
{
|
||||
private int _slot;
|
||||
public int Slot
|
||||
{
|
||||
get => _slot;
|
||||
set
|
||||
{
|
||||
_slot = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private int _altSlot;
|
||||
public int AltSlot
|
||||
{
|
||||
get => _altSlot;
|
||||
set
|
||||
{
|
||||
_altSlot = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private string _dsuServerHost;
|
||||
public string DsuServerHost
|
||||
{
|
||||
get => _dsuServerHost;
|
||||
set
|
||||
{
|
||||
_dsuServerHost = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private int _dsuServerPort;
|
||||
public int DsuServerPort
|
||||
{
|
||||
get => _dsuServerPort;
|
||||
set
|
||||
{
|
||||
_dsuServerPort = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private bool _mirrorInput;
|
||||
public bool MirrorInput
|
||||
{
|
||||
get => _mirrorInput;
|
||||
set
|
||||
{
|
||||
_mirrorInput = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private int _sensitivity;
|
||||
public int Sensitivity
|
||||
{
|
||||
get => _sensitivity;
|
||||
set
|
||||
{
|
||||
_sensitivity = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private double _gryoDeadzone;
|
||||
public double GyroDeadzone
|
||||
{
|
||||
get => _gryoDeadzone;
|
||||
set
|
||||
{
|
||||
_gryoDeadzone = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private bool _enableCemuHookMotion;
|
||||
public bool EnableCemuHookMotion
|
||||
{
|
||||
get => _enableCemuHookMotion;
|
||||
set
|
||||
{
|
||||
_enableCemuHookMotion = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
27
src/Ryujinx.Ava/UI/ViewModels/RumbleInputViewModel.cs
Normal file
27
src/Ryujinx.Ava/UI/ViewModels/RumbleInputViewModel.cs
Normal file
@ -0,0 +1,27 @@
|
||||
namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
public class RumbleInputViewModel : BaseModel
|
||||
{
|
||||
private float _strongRumble;
|
||||
public float StrongRumble
|
||||
{
|
||||
get => _strongRumble;
|
||||
set
|
||||
{
|
||||
_strongRumble = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private float _weakRumble;
|
||||
public float WeakRumble
|
||||
{
|
||||
get => _weakRumble;
|
||||
set
|
||||
{
|
||||
_weakRumble = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -311,7 +311,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
_gpuIds = new List<string>();
|
||||
List<string> names = new();
|
||||
var devices = VulkanRenderer.GetPhysicalDevices(Vk.GetApi());
|
||||
var devices = VulkanRenderer.GetPhysicalDevices();
|
||||
|
||||
if (devices.Length == 0)
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -4,7 +4,6 @@ using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.LogicalTree;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.UI.Controls;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
@ -13,18 +12,18 @@ using Ryujinx.Input;
|
||||
using Ryujinx.Input.Assigner;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Windows
|
||||
namespace Ryujinx.Ava.UI.Views.Input
|
||||
{
|
||||
public partial class ControllerSettingsWindow : UserControl
|
||||
public partial class ControllerInputView : UserControl
|
||||
{
|
||||
private bool _dialogOpen;
|
||||
|
||||
private ButtonKeyAssigner _currentAssigner;
|
||||
internal ControllerSettingsViewModel ViewModel { get; set; }
|
||||
internal ControllerInputViewModel ViewModel { get; set; }
|
||||
|
||||
public ControllerSettingsWindow()
|
||||
public ControllerInputView()
|
||||
{
|
||||
DataContext = ViewModel = new ControllerSettingsViewModel(this);
|
||||
DataContext = ViewModel = new ControllerInputViewModel(this);
|
||||
|
||||
InitializeComponent();
|
||||
|
@ -5,8 +5,11 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
||||
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
||||
mc:Ignorable="d"
|
||||
x:Class="Ryujinx.Ava.UI.Windows.MotionSettingsWindow"
|
||||
x:Class="Ryujinx.Ava.UI.Views.Input.MotionInputView"
|
||||
x:CompileBindings="True"
|
||||
x:DataType="viewModels:MotionInputViewModel"
|
||||
Focusable="True">
|
||||
<Grid Margin="10">
|
||||
<Grid.RowDefinitions>
|
||||
@ -14,7 +17,9 @@
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<StackPanel Orientation="Vertical">
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<StackPanel
|
||||
Orientation="Horizontal"
|
||||
HorizontalAlignment="Center">
|
||||
<TextBlock
|
||||
Margin="0"
|
||||
HorizontalAlignment="Center"
|
||||
@ -28,11 +33,14 @@
|
||||
Maximum="100"
|
||||
Minimum="0"
|
||||
Value="{Binding Sensitivity, Mode=TwoWay}" />
|
||||
<TextBlock HorizontalAlignment="Center"
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
Margin="5, 0"
|
||||
Text="{Binding Sensitivity, StringFormat=\{0:0\}%}" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<StackPanel
|
||||
Orientation="Horizontal"
|
||||
HorizontalAlignment="Center">
|
||||
<TextBlock
|
||||
Margin="0"
|
||||
HorizontalAlignment="Center"
|
||||
@ -51,16 +59,24 @@
|
||||
Margin="5, 0"
|
||||
Text="{Binding GyroDeadzone, StringFormat=\{0:0.00\}}" />
|
||||
</StackPanel>
|
||||
<Separator Height="1" Margin="0,5" />
|
||||
<CheckBox Margin="5" IsChecked="{Binding EnableCemuHookMotion}">
|
||||
<TextBlock Margin="0,3,0,0" VerticalAlignment="Center"
|
||||
<Separator
|
||||
Height="1"
|
||||
Margin="0,5" />
|
||||
<CheckBox
|
||||
Margin="5"
|
||||
IsChecked="{Binding EnableCemuHookMotion}">
|
||||
<TextBlock
|
||||
Margin="0,3,0,0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsMotionUseCemuhookCompatibleMotion}" />
|
||||
</CheckBox>
|
||||
</StackPanel>
|
||||
<Border Grid.Row="1"
|
||||
<Border
|
||||
Grid.Row="1"
|
||||
Padding="20,5"
|
||||
BorderBrush="{DynamicResource ThemeControlBorderColor}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="5"
|
||||
HorizontalAlignment="Stretch">
|
||||
<Grid VerticalAlignment="Top">
|
||||
<Grid.RowDefinitions>
|
||||
@ -109,18 +125,28 @@
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Margin="0,10,0,0" VerticalAlignment="Center"
|
||||
<TextBlock
|
||||
Margin="0,10,0,0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsMotionControllerSlot}" />
|
||||
<ui:NumberBox Grid.Row="0" Grid.Column="1"
|
||||
<ui:NumberBox
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Name="CemuHookSlotUpDown"
|
||||
SmallChange="1"
|
||||
LargeChange="1"
|
||||
Maximum="4"
|
||||
Minimum="0"
|
||||
Value="{Binding Slot}" />
|
||||
<TextBlock Margin="0,10,0,0" Grid.Row="1" Grid.Column="0" VerticalAlignment="Center"
|
||||
<TextBlock
|
||||
Margin="0,10,0,0"
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsMotionRightJoyConSlot}" />
|
||||
<ui:NumberBox Grid.Row="1" Grid.Column="1"
|
||||
<ui:NumberBox
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Name="CemuHookRightJoyConSlotUpDown"
|
||||
SmallChange="1"
|
||||
LargeChange="1"
|
||||
@ -129,9 +155,11 @@
|
||||
Value="{Binding AltSlot}" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
<CheckBox HorizontalAlignment="Center"
|
||||
<CheckBox
|
||||
HorizontalAlignment="Center"
|
||||
IsChecked="{Binding MirrorInput, Mode=TwoWay}">
|
||||
<TextBlock HorizontalAlignment="Center"
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsMotionMirrorInput}" />
|
||||
</CheckBox>
|
||||
</StackPanel>
|
@ -6,44 +6,42 @@ using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Windows
|
||||
namespace Ryujinx.Ava.UI.Views.Input
|
||||
{
|
||||
public partial class MotionSettingsWindow : UserControl
|
||||
public partial class MotionInputView : UserControl
|
||||
{
|
||||
private readonly InputConfiguration<GamepadInputId, StickInputId> _viewmodel;
|
||||
private MotionInputViewModel _viewModel;
|
||||
|
||||
public MotionSettingsWindow()
|
||||
public MotionInputView()
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = _viewmodel;
|
||||
}
|
||||
|
||||
public MotionSettingsWindow(ControllerSettingsViewModel viewmodel)
|
||||
public MotionInputView(ControllerInputViewModel viewModel)
|
||||
{
|
||||
var config = viewmodel.Configuration as InputConfiguration<GamepadInputId, StickInputId>;
|
||||
var config = viewModel.Configuration as InputConfiguration<GamepadInputId, StickInputId>;
|
||||
|
||||
_viewmodel = new InputConfiguration<GamepadInputId, StickInputId>()
|
||||
_viewModel = new MotionInputViewModel
|
||||
{
|
||||
Slot = config.Slot,
|
||||
AltSlot = config.AltSlot,
|
||||
DsuServerHost = config.DsuServerHost,
|
||||
DsuServerPort = config.DsuServerPort,
|
||||
MirrorInput = config.MirrorInput,
|
||||
EnableMotion = config.EnableMotion,
|
||||
Sensitivity = config.Sensitivity,
|
||||
GyroDeadzone = config.GyroDeadzone,
|
||||
EnableCemuHookMotion = config.EnableCemuHookMotion
|
||||
};
|
||||
|
||||
InitializeComponent();
|
||||
DataContext = _viewmodel;
|
||||
DataContext = _viewModel;
|
||||
}
|
||||
|
||||
public static async Task Show(ControllerSettingsViewModel viewmodel)
|
||||
public static async Task Show(ControllerInputViewModel viewModel)
|
||||
{
|
||||
MotionSettingsWindow content = new MotionSettingsWindow(viewmodel);
|
||||
MotionInputView content = new(viewModel);
|
||||
|
||||
ContentDialog contentDialog = new ContentDialog
|
||||
ContentDialog contentDialog = new()
|
||||
{
|
||||
Title = LocaleManager.Instance[LocaleKeys.ControllerMotionTitle],
|
||||
PrimaryButtonText = LocaleManager.Instance[LocaleKeys.ControllerSettingsSave],
|
||||
@ -53,16 +51,15 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
};
|
||||
contentDialog.PrimaryButtonClick += (sender, args) =>
|
||||
{
|
||||
var config = viewmodel.Configuration as InputConfiguration<GamepadInputId, StickInputId>;
|
||||
config.Slot = content._viewmodel.Slot;
|
||||
config.EnableMotion = content._viewmodel.EnableMotion;
|
||||
config.Sensitivity = content._viewmodel.Sensitivity;
|
||||
config.GyroDeadzone = content._viewmodel.GyroDeadzone;
|
||||
config.AltSlot = content._viewmodel.AltSlot;
|
||||
config.DsuServerHost = content._viewmodel.DsuServerHost;
|
||||
config.DsuServerPort = content._viewmodel.DsuServerPort;
|
||||
config.EnableCemuHookMotion = content._viewmodel.EnableCemuHookMotion;
|
||||
config.MirrorInput = content._viewmodel.MirrorInput;
|
||||
var config = viewModel.Configuration as InputConfiguration<GamepadInputId, StickInputId>;
|
||||
config.Slot = content._viewModel.Slot;
|
||||
config.Sensitivity = content._viewModel.Sensitivity;
|
||||
config.GyroDeadzone = content._viewModel.GyroDeadzone;
|
||||
config.AltSlot = content._viewModel.AltSlot;
|
||||
config.DsuServerHost = content._viewModel.DsuServerHost;
|
||||
config.DsuServerPort = content._viewModel.DsuServerPort;
|
||||
config.EnableCemuHookMotion = content._viewModel.EnableCemuHookMotion;
|
||||
config.MirrorInput = content._viewModel.MirrorInput;
|
||||
};
|
||||
|
||||
await contentDialog.ShowAsync();
|
@ -4,8 +4,11 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
||||
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
||||
mc:Ignorable="d"
|
||||
x:Class="Ryujinx.Ava.UI.Windows.RumbleSettingsWindow"
|
||||
x:Class="Ryujinx.Ava.UI.Views.Input.RumbleInputView"
|
||||
x:DataType="viewModels:RumbleInputViewModel"
|
||||
x:CompileBindings="True"
|
||||
Focusable="True">
|
||||
<Grid Margin="10">
|
||||
<Grid.RowDefinitions>
|
@ -6,36 +6,37 @@ using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Windows
|
||||
namespace Ryujinx.Ava.UI.Views.Input
|
||||
{
|
||||
public partial class RumbleSettingsWindow : UserControl
|
||||
public partial class RumbleInputView : UserControl
|
||||
{
|
||||
private readonly InputConfiguration<GamepadInputId, StickInputId> _viewmodel;
|
||||
private RumbleInputViewModel _viewModel;
|
||||
|
||||
public RumbleSettingsWindow()
|
||||
public RumbleInputView()
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = _viewmodel;
|
||||
}
|
||||
|
||||
public RumbleSettingsWindow(ControllerSettingsViewModel viewmodel)
|
||||
public RumbleInputView(ControllerInputViewModel viewModel)
|
||||
{
|
||||
var config = viewmodel.Configuration as InputConfiguration<GamepadInputId, StickInputId>;
|
||||
var config = viewModel.Configuration as InputConfiguration<GamepadInputId, StickInputId>;
|
||||
|
||||
_viewmodel = new InputConfiguration<GamepadInputId, StickInputId>()
|
||||
_viewModel = new RumbleInputViewModel
|
||||
{
|
||||
StrongRumble = config.StrongRumble, WeakRumble = config.WeakRumble
|
||||
StrongRumble = config.StrongRumble,
|
||||
WeakRumble = config.WeakRumble
|
||||
};
|
||||
|
||||
InitializeComponent();
|
||||
DataContext = _viewmodel;
|
||||
|
||||
DataContext = _viewModel;
|
||||
}
|
||||
|
||||
public static async Task Show(ControllerSettingsViewModel viewmodel)
|
||||
public static async Task Show(ControllerInputViewModel viewModel)
|
||||
{
|
||||
RumbleSettingsWindow content = new RumbleSettingsWindow(viewmodel);
|
||||
RumbleInputView content = new(viewModel);
|
||||
|
||||
ContentDialog contentDialog = new ContentDialog
|
||||
ContentDialog contentDialog = new()
|
||||
{
|
||||
Title = LocaleManager.Instance[LocaleKeys.ControllerRumbleTitle],
|
||||
PrimaryButtonText = LocaleManager.Instance[LocaleKeys.ControllerSettingsSave],
|
||||
@ -46,9 +47,9 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
|
||||
contentDialog.PrimaryButtonClick += (sender, args) =>
|
||||
{
|
||||
var config = viewmodel.Configuration as InputConfiguration<GamepadInputId, StickInputId>;
|
||||
config.StrongRumble = content._viewmodel.StrongRumble;
|
||||
config.WeakRumble = content._viewmodel.WeakRumble;
|
||||
var config = viewModel.Configuration as InputConfiguration<GamepadInputId, StickInputId>;
|
||||
config.StrongRumble = content._viewModel.StrongRumble;
|
||||
config.WeakRumble = content._viewModel.WeakRumble;
|
||||
};
|
||||
|
||||
await contentDialog.ShowAsync();
|
@ -9,9 +9,7 @@ using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using Ryujinx.HLE.HOS;
|
||||
using Ryujinx.Modules;
|
||||
using Ryujinx.Ui.App.Common;
|
||||
using Ryujinx.Ui.Common;
|
||||
using Ryujinx.Ui.Common.Configuration;
|
||||
using Ryujinx.Ui.Common.Helper;
|
||||
|
@ -16,6 +16,7 @@
|
||||
</Design.DataContext>
|
||||
<DockPanel
|
||||
Margin="0,0,0,5"
|
||||
Height="35"
|
||||
HorizontalAlignment="Stretch">
|
||||
<Button
|
||||
Width="40"
|
||||
|
@ -5,7 +5,7 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
||||
xmlns:window="clr-namespace:Ryujinx.Ava.UI.Windows"
|
||||
xmlns:views="clr-namespace:Ryujinx.Ava.UI.Views.Input"
|
||||
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
||||
mc:Ignorable="d"
|
||||
x:CompileBindings="True"
|
||||
@ -20,27 +20,49 @@
|
||||
HorizontalScrollBarVisibility="Disabled"
|
||||
VerticalScrollBarVisibility="Auto">
|
||||
<Border Classes="settings">
|
||||
<StackPanel Margin="4" Orientation="Vertical">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<CheckBox Margin="5,0"
|
||||
<Panel
|
||||
Margin="10">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<views:ControllerInputView
|
||||
Grid.Row="0"
|
||||
Name="ControllerSettings" />
|
||||
<StackPanel
|
||||
Orientation="Vertical"
|
||||
Grid.Row="2">
|
||||
<Separator
|
||||
Margin="0 10"
|
||||
Height="1" />
|
||||
<StackPanel
|
||||
Orientation="Horizontal"
|
||||
Spacing="10">
|
||||
<CheckBox
|
||||
ToolTip.Tip="{locale:Locale DockModeToggleTooltip}"
|
||||
MinWidth="0"
|
||||
IsChecked="{Binding EnableDockedMode}">
|
||||
<TextBlock VerticalAlignment="Center"
|
||||
<TextBlock
|
||||
Text="{locale:Locale SettingsTabInputEnableDockedMode}" />
|
||||
</CheckBox>
|
||||
<CheckBox Margin="5,0"
|
||||
<CheckBox
|
||||
ToolTip.Tip="{locale:Locale DirectKeyboardTooltip}"
|
||||
IsChecked="{Binding EnableKeyboard}">
|
||||
<TextBlock Text="{locale:Locale SettingsTabInputDirectKeyboardAccess}" />
|
||||
<TextBlock
|
||||
Text="{locale:Locale SettingsTabInputDirectKeyboardAccess}" />
|
||||
</CheckBox>
|
||||
<CheckBox Margin="5,0"
|
||||
<CheckBox
|
||||
ToolTip.Tip="{locale:Locale DirectMouseTooltip}"
|
||||
IsChecked="{Binding EnableMouse}">
|
||||
<TextBlock Text="{locale:Locale SettingsTabInputDirectMouseAccess}" />
|
||||
<TextBlock
|
||||
Text="{locale:Locale SettingsTabInputDirectMouseAccess}" />
|
||||
</CheckBox>
|
||||
</StackPanel>
|
||||
<window:ControllerSettingsWindow Name="ControllerSettings" Margin="0" MinHeight="600" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Panel>
|
||||
</Border>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
@ -58,11 +58,20 @@
|
||||
JustifyContent="SpaceAround"
|
||||
RowSpacing="2">
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="28"
|
||||
FontWeight="Bold"
|
||||
Text="Ryujinx"
|
||||
TextAlignment="Left" />
|
||||
<TextBlock Text="(REE-YOU-JINX)" TextAlignment="Left" />
|
||||
TextAlignment="Center"
|
||||
Width="100" />
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="11"
|
||||
Text="(REE-YOU-JINX)"
|
||||
TextAlignment="Center"
|
||||
Width="100" />
|
||||
</flex:FlexPanel>
|
||||
</Grid>
|
||||
<TextBlock
|
||||
@ -72,6 +81,18 @@
|
||||
LineHeight="12"
|
||||
Text="{Binding Version}"
|
||||
TextAlignment="Center" />
|
||||
<Button
|
||||
Padding="5"
|
||||
HorizontalAlignment="Center"
|
||||
Background="Transparent"
|
||||
Click="Button_OnClick"
|
||||
Tag="https://github.com/Ryujinx/Ryujinx/wiki/Changelog#ryujinx-changelog">
|
||||
<TextBlock
|
||||
FontSize="10"
|
||||
Text="{locale:Locale AboutChangelogButton}"
|
||||
TextAlignment="Center"
|
||||
ToolTip.Tip="{locale:Locale AboutChangelogButtonTooltipMessage}" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Grid.Row="2"
|
||||
|
@ -23,6 +23,7 @@ using Ryujinx.Ui.Common.Helper;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Threading.Tasks;
|
||||
using InputManager = Ryujinx.Input.HLE.InputManager;
|
||||
|
||||
@ -258,7 +259,64 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
ApplicationHelper.Initialize(VirtualFileSystem, AccountManager, LibHacHorizonManager.RyujinxClient, this);
|
||||
}
|
||||
|
||||
protected void CheckLaunchState()
|
||||
[SupportedOSPlatform("linux")]
|
||||
private static async void ShowVmMaxMapCountWarning()
|
||||
{
|
||||
LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.LinuxVmMaxMapCountWarningTextSecondary,
|
||||
LinuxHelper.VmMaxMapCount, LinuxHelper.RecommendedVmMaxMapCount);
|
||||
|
||||
await ContentDialogHelper.CreateWarningDialog(
|
||||
LocaleManager.Instance[LocaleKeys.LinuxVmMaxMapCountWarningTextPrimary],
|
||||
LocaleManager.Instance[LocaleKeys.LinuxVmMaxMapCountWarningTextSecondary]
|
||||
);
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("linux")]
|
||||
private static async void ShowVmMaxMapCountDialog()
|
||||
{
|
||||
LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.LinuxVmMaxMapCountDialogTextPrimary,
|
||||
LinuxHelper.RecommendedVmMaxMapCount);
|
||||
|
||||
UserResult response = await ContentDialogHelper.ShowTextDialog(
|
||||
$"Ryujinx - {LocaleManager.Instance[LocaleKeys.LinuxVmMaxMapCountDialogTitle]}",
|
||||
LocaleManager.Instance[LocaleKeys.LinuxVmMaxMapCountDialogTextPrimary],
|
||||
LocaleManager.Instance[LocaleKeys.LinuxVmMaxMapCountDialogTextSecondary],
|
||||
LocaleManager.Instance[LocaleKeys.LinuxVmMaxMapCountDialogButtonUntilRestart],
|
||||
LocaleManager.Instance[LocaleKeys.LinuxVmMaxMapCountDialogButtonPersistent],
|
||||
LocaleManager.Instance[LocaleKeys.InputDialogNo],
|
||||
(int)Symbol.Help
|
||||
);
|
||||
|
||||
int rc;
|
||||
|
||||
switch (response)
|
||||
{
|
||||
case UserResult.Ok:
|
||||
rc = LinuxHelper.RunPkExec($"echo {LinuxHelper.RecommendedVmMaxMapCount} > {LinuxHelper.VmMaxMapCountPath}");
|
||||
if (rc == 0)
|
||||
{
|
||||
Logger.Info?.Print(LogClass.Application, $"vm.max_map_count set to {LinuxHelper.VmMaxMapCount} until the next restart.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Unable to change vm.max_map_count. Process exited with code: {rc}");
|
||||
}
|
||||
break;
|
||||
case UserResult.No:
|
||||
rc = LinuxHelper.RunPkExec($"echo \"vm.max_map_count = {LinuxHelper.RecommendedVmMaxMapCount}\" > {LinuxHelper.SysCtlConfigPath} && sysctl -p {LinuxHelper.SysCtlConfigPath}");
|
||||
if (rc == 0)
|
||||
{
|
||||
Logger.Info?.Print(LogClass.Application, $"vm.max_map_count set to {LinuxHelper.VmMaxMapCount}. Written to config: {LinuxHelper.SysCtlConfigPath}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Unable to write new value for vm.max_map_count to config. Process exited with code: {rc}");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckLaunchState()
|
||||
{
|
||||
if (ShowKeyErrorOnLoad)
|
||||
{
|
||||
@ -268,6 +326,20 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
UserErrorDialog.ShowUserErrorDialog(UserError.NoKeys, this));
|
||||
}
|
||||
|
||||
if (OperatingSystem.IsLinux() && LinuxHelper.VmMaxMapCount < LinuxHelper.RecommendedVmMaxMapCount)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Application, $"The value of vm.max_map_count is lower than {LinuxHelper.RecommendedVmMaxMapCount}. ({LinuxHelper.VmMaxMapCount})");
|
||||
|
||||
if (LinuxHelper.PkExecPath is not null)
|
||||
{
|
||||
Dispatcher.UIThread.Post(ShowVmMaxMapCountDialog);
|
||||
}
|
||||
else
|
||||
{
|
||||
Dispatcher.UIThread.Post(ShowVmMaxMapCountWarning);
|
||||
}
|
||||
}
|
||||
|
||||
if (_deferLoad)
|
||||
{
|
||||
_deferLoad = false;
|
||||
|
@ -22,9 +22,11 @@ namespace Ryujinx.Common
|
||||
_cts = new CancellationTokenSource();
|
||||
_queue = collection;
|
||||
_workerAction = callback;
|
||||
_workerThread = new Thread(DoWork) { Name = name };
|
||||
|
||||
_workerThread.IsBackground = true;
|
||||
_workerThread = new Thread(DoWork)
|
||||
{
|
||||
Name = name,
|
||||
IsBackground = true
|
||||
};
|
||||
_workerThread.Start();
|
||||
}
|
||||
|
||||
|
@ -96,7 +96,7 @@ namespace Ryujinx.Common.Configuration
|
||||
if (OperatingSystem.IsMacOS() && Mode == LaunchMode.UserProfile)
|
||||
{
|
||||
string oldConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), DefaultBaseDir);
|
||||
if (Path.Exists(oldConfigPath) && !Path.Exists(BaseDirPath))
|
||||
if (Path.Exists(oldConfigPath) && !IsPathSymlink(oldConfigPath) && !Path.Exists(BaseDirPath))
|
||||
{
|
||||
CopyDirectory(oldConfigPath, BaseDirPath);
|
||||
Directory.Delete(oldConfigPath, true);
|
||||
@ -115,6 +115,14 @@ namespace Ryujinx.Common.Configuration
|
||||
Directory.CreateDirectory(KeysDirPath = Path.Combine(BaseDirPath, KeysDir));
|
||||
}
|
||||
|
||||
// Check if existing old baseDirPath is a symlink, to prevent possible errors.
|
||||
// Should be removed, when the existance of the old directory isn't checked anymore.
|
||||
private static bool IsPathSymlink(string path)
|
||||
{
|
||||
FileAttributes attributes = File.GetAttributes(path);
|
||||
return (attributes & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint;
|
||||
}
|
||||
|
||||
private static void CopyDirectory(string sourceDir, string destinationDir)
|
||||
{
|
||||
var dir = new DirectoryInfo(sourceDir);
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System.Text;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
namespace Ryujinx.Common.Logging
|
||||
namespace Ryujinx.Common.Logging.Formatters
|
||||
{
|
||||
internal class DefaultLogFormatter : ILogFormatter
|
||||
{
|
||||
@ -27,6 +28,14 @@ namespace Ryujinx.Common.Logging
|
||||
|
||||
if (args.Data is not null)
|
||||
{
|
||||
if (args.Data is StackTrace trace)
|
||||
{
|
||||
sb.Append('\n');
|
||||
sb.Append(trace);
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
sb.Append(' ');
|
||||
DynamicObjectFormatter.Format(sb, args.Data);
|
||||
}
|
||||
|
@ -3,9 +3,9 @@ using System;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace Ryujinx.Common.Logging
|
||||
namespace Ryujinx.Common.Logging.Formatters
|
||||
{
|
||||
internal class DynamicObjectFormatter
|
||||
internal static class DynamicObjectFormatter
|
||||
{
|
||||
private static readonly ObjectPool<StringBuilder> StringBuilderPool = SharedPools.Default<StringBuilder>();
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Ryujinx.Common.Logging
|
||||
namespace Ryujinx.Common.Logging.Formatters
|
||||
{
|
||||
interface ILogFormatter
|
||||
{
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Ryujinx.Common.Logging.Formatters;
|
||||
using System;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Ryujinx.Common.Logging
|
||||
|
@ -1,3 +1,4 @@
|
||||
using Ryujinx.Common.Logging.Targets;
|
||||
using Ryujinx.Common.SystemInterop;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -55,6 +56,16 @@ namespace Ryujinx.Common.Logging
|
||||
}
|
||||
}
|
||||
|
||||
[StackTraceHidden]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void PrintStack(LogClass logClass, string message, [CallerMemberName] string caller = "")
|
||||
{
|
||||
if (m_EnabledClasses[(int)logClass])
|
||||
{
|
||||
Updated?.Invoke(null, new LogEventArgs(Level, m_Time.Elapsed, Thread.CurrentThread.Name, FormatMessage(logClass, caller, message), new StackTrace(true)));
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void PrintStub(LogClass logClass, string message = "", [CallerMemberName] string caller = "")
|
||||
{
|
||||
|
@ -2,7 +2,7 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading;
|
||||
|
||||
namespace Ryujinx.Common.Logging
|
||||
namespace Ryujinx.Common.Logging.Targets
|
||||
{
|
||||
public enum AsyncLogTargetOverflowAction
|
||||
{
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using Ryujinx.Common.Logging.Formatters;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Common.Logging
|
||||
namespace Ryujinx.Common.Logging.Targets
|
||||
{
|
||||
public class ConsoleLogTarget : ILogTarget
|
||||
{
|
||||
|
@ -1,8 +1,9 @@
|
||||
using System;
|
||||
using Ryujinx.Common.Logging.Formatters;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Ryujinx.Common.Logging
|
||||
namespace Ryujinx.Common.Logging.Targets
|
||||
{
|
||||
public class FileLogTarget : ILogTarget
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Common.Logging
|
||||
namespace Ryujinx.Common.Logging.Targets
|
||||
{
|
||||
public interface ILogTarget : IDisposable
|
||||
{
|
||||
|
@ -1,7 +1,7 @@
|
||||
using Ryujinx.Common.Utilities;
|
||||
using System.IO;
|
||||
|
||||
namespace Ryujinx.Common.Logging
|
||||
namespace Ryujinx.Common.Logging.Targets
|
||||
{
|
||||
public class JsonLogTarget : ILogTarget
|
||||
{
|
||||
|
@ -24,6 +24,24 @@ namespace Ryujinx.Common.Memory
|
||||
return value;
|
||||
}
|
||||
|
||||
public bool TryRead<T>(out T value) where T : unmanaged
|
||||
{
|
||||
int valueSize = Unsafe.SizeOf<T>();
|
||||
|
||||
if (valueSize > _input.Length)
|
||||
{
|
||||
value = default;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
value = MemoryMarshal.Cast<byte, T>(_input)[0];
|
||||
|
||||
_input = _input.Slice(valueSize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public ReadOnlySpan<byte> GetSpan(int size)
|
||||
{
|
||||
ReadOnlySpan<byte> data = _input.Slice(0, size);
|
||||
|
@ -1,4 +1,5 @@
|
||||
#nullable enable
|
||||
using Ryujinx.Common.Logging;
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
@ -18,12 +19,14 @@ namespace Ryujinx.Common.Utilities
|
||||
public override TEnum Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
var enumValue = reader.GetString();
|
||||
if (string.IsNullOrEmpty(enumValue))
|
||||
|
||||
if (Enum.TryParse(enumValue, out TEnum value))
|
||||
{
|
||||
return default;
|
||||
return value;
|
||||
}
|
||||
|
||||
return Enum.Parse<TEnum>(enumValue);
|
||||
Logger.Warning?.Print(LogClass.Configuration, $"Failed to parse enum value \"{enumValue}\" for {typeof(TEnum)}, using default \"{default(TEnum)}\"");
|
||||
return default;
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, TEnum value, JsonSerializerOptions options)
|
||||
|
@ -28,17 +28,21 @@ namespace Ryujinx.Graphics.GAL
|
||||
public readonly bool SupportsFragmentShaderOrderingIntel;
|
||||
public readonly bool SupportsGeometryShader;
|
||||
public readonly bool SupportsGeometryShaderPassthrough;
|
||||
public readonly bool SupportsTransformFeedback;
|
||||
public readonly bool SupportsImageLoadFormatted;
|
||||
public readonly bool SupportsLayerVertexTessellation;
|
||||
public readonly bool SupportsMismatchingViewFormat;
|
||||
public readonly bool SupportsCubemapView;
|
||||
public readonly bool SupportsNonConstantTextureOffset;
|
||||
public readonly bool SupportsShaderBallot;
|
||||
public readonly bool SupportsShaderBarrierDivergence;
|
||||
public readonly bool SupportsShaderFloat64;
|
||||
public readonly bool SupportsTextureShadowLod;
|
||||
public readonly bool SupportsViewportIndexVertexTessellation;
|
||||
public readonly bool SupportsViewportMask;
|
||||
public readonly bool SupportsViewportSwizzle;
|
||||
public readonly bool SupportsIndirectParameters;
|
||||
public readonly bool SupportsDepthClipControl;
|
||||
|
||||
public readonly uint MaximumUniformBuffersPerStage;
|
||||
public readonly uint MaximumStorageBuffersPerStage;
|
||||
@ -74,17 +78,21 @@ namespace Ryujinx.Graphics.GAL
|
||||
bool supportsFragmentShaderOrderingIntel,
|
||||
bool supportsGeometryShader,
|
||||
bool supportsGeometryShaderPassthrough,
|
||||
bool supportsTransformFeedback,
|
||||
bool supportsImageLoadFormatted,
|
||||
bool supportsLayerVertexTessellation,
|
||||
bool supportsMismatchingViewFormat,
|
||||
bool supportsCubemapView,
|
||||
bool supportsNonConstantTextureOffset,
|
||||
bool supportsShaderBallot,
|
||||
bool supportsShaderBarrierDivergence,
|
||||
bool supportsShaderFloat64,
|
||||
bool supportsTextureShadowLod,
|
||||
bool supportsViewportIndexVertexTessellation,
|
||||
bool supportsViewportMask,
|
||||
bool supportsViewportSwizzle,
|
||||
bool supportsIndirectParameters,
|
||||
bool supportsDepthClipControl,
|
||||
uint maximumUniformBuffersPerStage,
|
||||
uint maximumStorageBuffersPerStage,
|
||||
uint maximumTexturesPerStage,
|
||||
@ -116,17 +124,21 @@ namespace Ryujinx.Graphics.GAL
|
||||
SupportsFragmentShaderOrderingIntel = supportsFragmentShaderOrderingIntel;
|
||||
SupportsGeometryShader = supportsGeometryShader;
|
||||
SupportsGeometryShaderPassthrough = supportsGeometryShaderPassthrough;
|
||||
SupportsTransformFeedback = supportsTransformFeedback;
|
||||
SupportsImageLoadFormatted = supportsImageLoadFormatted;
|
||||
SupportsLayerVertexTessellation = supportsLayerVertexTessellation;
|
||||
SupportsMismatchingViewFormat = supportsMismatchingViewFormat;
|
||||
SupportsCubemapView = supportsCubemapView;
|
||||
SupportsNonConstantTextureOffset = supportsNonConstantTextureOffset;
|
||||
SupportsShaderBallot = supportsShaderBallot;
|
||||
SupportsShaderBarrierDivergence = supportsShaderBarrierDivergence;
|
||||
SupportsShaderFloat64 = supportsShaderFloat64;
|
||||
SupportsTextureShadowLod = supportsTextureShadowLod;
|
||||
SupportsViewportIndexVertexTessellation = supportsViewportIndexVertexTessellation;
|
||||
SupportsViewportMask = supportsViewportMask;
|
||||
SupportsViewportSwizzle = supportsViewportSwizzle;
|
||||
SupportsIndirectParameters = supportsIndirectParameters;
|
||||
SupportsDepthClipControl = supportsDepthClipControl;
|
||||
MaximumUniformBuffersPerStage = maximumUniformBuffersPerStage;
|
||||
MaximumStorageBuffersPerStage = maximumStorageBuffersPerStage;
|
||||
MaximumTexturesPerStage = maximumTexturesPerStage;
|
||||
|
@ -383,6 +383,7 @@ namespace Ryujinx.Graphics.GAL
|
||||
case Format.R10G10B10A2Unorm:
|
||||
case Format.R10G10B10A2Uint:
|
||||
case Format.R11G11B10Float:
|
||||
case Format.B8G8R8A8Unorm:
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
using Ryujinx.Common.Configuration;
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Ryujinx.Graphics.GAL
|
||||
{
|
||||
@ -52,7 +53,7 @@ namespace Ryujinx.Graphics.GAL
|
||||
|
||||
void ResetCounter(CounterType type);
|
||||
|
||||
void RunLoop(Action gpuLoop)
|
||||
void RunLoop(ThreadStart gpuLoop)
|
||||
{
|
||||
gpuLoop();
|
||||
}
|
||||
|
@ -30,7 +30,6 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
||||
private IRenderer _baseRenderer;
|
||||
private Thread _gpuThread;
|
||||
private Thread _backendThread;
|
||||
private bool _disposed;
|
||||
private bool _running;
|
||||
|
||||
private AutoResetEvent _frameComplete = new AutoResetEvent(true);
|
||||
@ -98,19 +97,17 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
||||
_refQueue = new object[MaxRefsPerCommand * QueueCount];
|
||||
}
|
||||
|
||||
public void RunLoop(Action gpuLoop)
|
||||
public void RunLoop(ThreadStart gpuLoop)
|
||||
{
|
||||
_running = true;
|
||||
|
||||
_backendThread = Thread.CurrentThread;
|
||||
|
||||
_gpuThread = new Thread(() => {
|
||||
gpuLoop();
|
||||
_running = false;
|
||||
_galWorkAvailable.Set();
|
||||
});
|
||||
_gpuThread = new Thread(gpuLoop)
|
||||
{
|
||||
Name = "GPU.MainThread"
|
||||
};
|
||||
|
||||
_gpuThread.Name = "GPU.MainThread";
|
||||
_gpuThread.Start();
|
||||
|
||||
RenderLoop();
|
||||
@ -120,7 +117,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
||||
{
|
||||
// Power through the render queue until the Gpu thread work is done.
|
||||
|
||||
while (_running && !_disposed)
|
||||
while (_running)
|
||||
{
|
||||
_galWorkAvailable.Wait();
|
||||
_galWorkAvailable.Reset();
|
||||
@ -488,12 +485,23 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
||||
return _baseRenderer.PrepareHostMapping(address, size);
|
||||
}
|
||||
|
||||
public void FlushThreadedCommands()
|
||||
{
|
||||
SpinWait wait = new();
|
||||
|
||||
while (Volatile.Read(ref _commandCount) > 0)
|
||||
{
|
||||
wait.SpinOnce();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// Dispose must happen from the render thread, after all commands have completed.
|
||||
|
||||
// Stop the GPU thread.
|
||||
_disposed = true;
|
||||
_running = false;
|
||||
_galWorkAvailable.Set();
|
||||
|
||||
if (_gpuThread != null && _gpuThread.IsAlive)
|
||||
{
|
||||
|
@ -63,6 +63,8 @@ namespace Ryujinx.Graphics.GAL
|
||||
public bool PrimitiveRestartEnable;
|
||||
public uint PatchControlPoints;
|
||||
|
||||
public DepthMode DepthMode;
|
||||
|
||||
public void SetVertexAttribs(ReadOnlySpan<VertexAttribDescriptor> vertexAttribs)
|
||||
{
|
||||
VertexAttribCount = vertexAttribs.Length;
|
||||
|
179
src/Ryujinx.Graphics.GAL/ResourceLayout.cs
Normal file
179
src/Ryujinx.Graphics.GAL/ResourceLayout.cs
Normal file
@ -0,0 +1,179 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Ryujinx.Graphics.GAL
|
||||
{
|
||||
public enum ResourceType : byte
|
||||
{
|
||||
UniformBuffer,
|
||||
StorageBuffer,
|
||||
Texture,
|
||||
Sampler,
|
||||
TextureAndSampler,
|
||||
Image,
|
||||
BufferTexture,
|
||||
BufferImage
|
||||
}
|
||||
|
||||
public enum ResourceAccess : byte
|
||||
{
|
||||
None = 0,
|
||||
Read = 1,
|
||||
Write = 2,
|
||||
ReadWrite = Read | Write
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum ResourceStages : byte
|
||||
{
|
||||
None = 0,
|
||||
Compute = 1 << 0,
|
||||
Vertex = 1 << 1,
|
||||
TessellationControl = 1 << 2,
|
||||
TessellationEvaluation = 1 << 3,
|
||||
Geometry = 1 << 4,
|
||||
Fragment = 1 << 5
|
||||
}
|
||||
|
||||
public readonly struct ResourceDescriptor : IEquatable<ResourceDescriptor>
|
||||
{
|
||||
public int Binding { get; }
|
||||
public int Count { get; }
|
||||
public ResourceType Type { get; }
|
||||
public ResourceStages Stages { get; }
|
||||
|
||||
public ResourceDescriptor(int binding, int count, ResourceType type, ResourceStages stages)
|
||||
{
|
||||
Binding = binding;
|
||||
Count = count;
|
||||
Type = type;
|
||||
Stages = stages;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(Binding, Count, Type, Stages);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is ResourceDescriptor other && Equals(other);
|
||||
}
|
||||
|
||||
public bool Equals(ResourceDescriptor other)
|
||||
{
|
||||
return Binding == other.Binding && Count == other.Count && Type == other.Type && Stages == other.Stages;
|
||||
}
|
||||
}
|
||||
|
||||
public readonly struct ResourceUsage : IEquatable<ResourceUsage>
|
||||
{
|
||||
public int Binding { get; }
|
||||
public ResourceType Type { get; }
|
||||
public ResourceStages Stages { get; }
|
||||
public ResourceAccess Access { get; }
|
||||
|
||||
public ResourceUsage(int binding, ResourceType type, ResourceStages stages, ResourceAccess access)
|
||||
{
|
||||
Binding = binding;
|
||||
Type = type;
|
||||
Stages = stages;
|
||||
Access = access;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(Binding, Type, Stages, Access);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is ResourceUsage other && Equals(other);
|
||||
}
|
||||
|
||||
public bool Equals(ResourceUsage other)
|
||||
{
|
||||
return Binding == other.Binding && Type == other.Type && Stages == other.Stages && Access == other.Access;
|
||||
}
|
||||
}
|
||||
|
||||
public readonly struct ResourceDescriptorCollection
|
||||
{
|
||||
public ReadOnlyCollection<ResourceDescriptor> Descriptors { get; }
|
||||
|
||||
public ResourceDescriptorCollection(ReadOnlyCollection<ResourceDescriptor> descriptors)
|
||||
{
|
||||
Descriptors = descriptors;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
HashCode hasher = new HashCode();
|
||||
|
||||
if (Descriptors != null)
|
||||
{
|
||||
foreach (var descriptor in Descriptors)
|
||||
{
|
||||
hasher.Add(descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
return hasher.ToHashCode();
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is ResourceDescriptorCollection other && Equals(other);
|
||||
}
|
||||
|
||||
public bool Equals(ResourceDescriptorCollection other)
|
||||
{
|
||||
if ((Descriptors == null) != (other.Descriptors == null))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Descriptors != null)
|
||||
{
|
||||
if (Descriptors.Count != other.Descriptors.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int index = 0; index < Descriptors.Count; index++)
|
||||
{
|
||||
if (!Descriptors[index].Equals(other.Descriptors[index]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public readonly struct ResourceUsageCollection
|
||||
{
|
||||
public ReadOnlyCollection<ResourceUsage> Usages { get; }
|
||||
|
||||
public ResourceUsageCollection(ReadOnlyCollection<ResourceUsage> usages)
|
||||
{
|
||||
Usages = usages;
|
||||
}
|
||||
}
|
||||
|
||||
public readonly struct ResourceLayout
|
||||
{
|
||||
public ReadOnlyCollection<ResourceDescriptorCollection> Sets { get; }
|
||||
public ReadOnlyCollection<ResourceUsageCollection> SetUsages { get; }
|
||||
|
||||
public ResourceLayout(
|
||||
ReadOnlyCollection<ResourceDescriptorCollection> sets,
|
||||
ReadOnlyCollection<ResourceUsageCollection> setUsages)
|
||||
{
|
||||
Sets = sets;
|
||||
SetUsages = setUsages;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Graphics.GAL
|
||||
{
|
||||
public readonly struct ShaderBindings
|
||||
{
|
||||
public IReadOnlyCollection<int> UniformBufferBindings { get; }
|
||||
public IReadOnlyCollection<int> StorageBufferBindings { get; }
|
||||
public IReadOnlyCollection<int> TextureBindings { get; }
|
||||
public IReadOnlyCollection<int> ImageBindings { get; }
|
||||
|
||||
public ShaderBindings(
|
||||
IReadOnlyCollection<int> uniformBufferBindings,
|
||||
IReadOnlyCollection<int> storageBufferBindings,
|
||||
IReadOnlyCollection<int> textureBindings,
|
||||
IReadOnlyCollection<int> imageBindings)
|
||||
{
|
||||
UniformBufferBindings = uniformBufferBindings;
|
||||
StorageBufferBindings = storageBufferBindings;
|
||||
TextureBindings = textureBindings;
|
||||
ImageBindings = imageBindings;
|
||||
}
|
||||
}
|
||||
}
|
@ -3,19 +3,22 @@ namespace Ryujinx.Graphics.GAL
|
||||
public struct ShaderInfo
|
||||
{
|
||||
public int FragmentOutputMap { get; }
|
||||
public ResourceLayout ResourceLayout { get; }
|
||||
public ProgramPipelineState? State { get; }
|
||||
public bool FromCache { get; set; }
|
||||
|
||||
public ShaderInfo(int fragmentOutputMap, ProgramPipelineState state, bool fromCache = false)
|
||||
public ShaderInfo(int fragmentOutputMap, ResourceLayout resourceLayout, ProgramPipelineState state, bool fromCache = false)
|
||||
{
|
||||
FragmentOutputMap = fragmentOutputMap;
|
||||
ResourceLayout = resourceLayout;
|
||||
State = state;
|
||||
FromCache = fromCache;
|
||||
}
|
||||
|
||||
public ShaderInfo(int fragmentOutputMap, bool fromCache = false)
|
||||
public ShaderInfo(int fragmentOutputMap, ResourceLayout resourceLayout, bool fromCache = false)
|
||||
{
|
||||
FragmentOutputMap = fragmentOutputMap;
|
||||
ResourceLayout = resourceLayout;
|
||||
State = null;
|
||||
FromCache = fromCache;
|
||||
}
|
||||
|
@ -7,24 +7,22 @@ namespace Ryujinx.Graphics.GAL
|
||||
{
|
||||
public string Code { get; }
|
||||
public byte[] BinaryCode { get; }
|
||||
public ShaderBindings Bindings { get; }
|
||||
public ShaderStage Stage { get; }
|
||||
public TargetLanguage Language { get; }
|
||||
|
||||
public ShaderSource(string code, byte[] binaryCode, ShaderBindings bindings, ShaderStage stage, TargetLanguage language)
|
||||
public ShaderSource(string code, byte[] binaryCode, ShaderStage stage, TargetLanguage language)
|
||||
{
|
||||
Code = code;
|
||||
BinaryCode = binaryCode;
|
||||
Bindings = bindings;
|
||||
Stage = stage;
|
||||
Language = language;
|
||||
}
|
||||
|
||||
public ShaderSource(string code, ShaderBindings bindings, ShaderStage stage, TargetLanguage language) : this(code, null, bindings, stage, language)
|
||||
public ShaderSource(string code, ShaderStage stage, TargetLanguage language) : this(code, null, stage, language)
|
||||
{
|
||||
}
|
||||
|
||||
public ShaderSource(byte[] binaryCode, ShaderBindings bindings, ShaderStage stage, TargetLanguage language) : this(null, binaryCode, bindings, stage, language)
|
||||
public ShaderSource(byte[] binaryCode, ShaderStage stage, TargetLanguage language) : this(null, binaryCode, stage, language)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -40,22 +40,6 @@ namespace Ryujinx.Graphics.Gpu
|
||||
/// </summary>
|
||||
public const int TotalTransformFeedbackBuffers = 4;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum number of textures on a single shader stage.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The maximum number of textures is API limited, the hardware supports an unlimited amount.
|
||||
/// </remarks>
|
||||
public const int TotalTextures = 32;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum number of images on a single shader stage.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The maximum number of images is API limited, the hardware supports an unlimited amount.
|
||||
/// </remarks>
|
||||
public const int TotalImages = 8;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum number of render target color buffers.
|
||||
/// </summary>
|
||||
@ -97,8 +81,13 @@ namespace Ryujinx.Graphics.Gpu
|
||||
public const int GobAlignment = 64;
|
||||
|
||||
/// <summary>
|
||||
/// Expected byte alignment for storage buffers
|
||||
/// Number of the uniform buffer reserved by the driver to store the storage buffer base addresses.
|
||||
/// </summary>
|
||||
public const int StorageAlignment = 16;
|
||||
public const int DriverReservedUniformBuffer = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum size that an storage buffer is assumed to have when the correct size is unknown.
|
||||
/// </summary>
|
||||
public const ulong MaxUnknownStorageSize = 0x100000;
|
||||
}
|
||||
}
|
@ -151,8 +151,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
|
||||
|
||||
ShaderProgramInfo info = cs.Shaders[0].Info;
|
||||
|
||||
bool hasUnaligned = _channel.BufferManager.HasUnalignedStorageBuffers;
|
||||
|
||||
for (int index = 0; index < info.SBuffers.Count; index++)
|
||||
{
|
||||
BufferDescriptor sb = info.SBuffers[index];
|
||||
@ -162,12 +160,32 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
|
||||
|
||||
SbDescriptor sbDescriptor = _channel.MemoryManager.Physical.Read<SbDescriptor>(sbDescAddress);
|
||||
|
||||
_channel.BufferManager.SetComputeStorageBuffer(sb.Slot, sbDescriptor.PackAddress(), (uint)sbDescriptor.Size, sb.Flags);
|
||||
uint size;
|
||||
if (sb.SbCbSlot == Constants.DriverReservedUniformBuffer)
|
||||
{
|
||||
// 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(), Constants.MaxUnknownStorageSize);
|
||||
}
|
||||
|
||||
if ((_channel.BufferManager.HasUnalignedStorageBuffers) != hasUnaligned)
|
||||
_channel.BufferManager.SetComputeStorageBuffer(sb.Slot, sbDescriptor.PackAddress(), size, sb.Flags);
|
||||
}
|
||||
|
||||
if (_channel.BufferManager.HasUnalignedStorageBuffers != computeState.HasUnalignedStorageBuffer)
|
||||
{
|
||||
// Refetch the shader, as assumptions about storage buffer alignment have changed.
|
||||
computeState = new GpuChannelComputeState(
|
||||
qmd.CtaThreadDimension0,
|
||||
qmd.CtaThreadDimension1,
|
||||
qmd.CtaThreadDimension2,
|
||||
localMemorySize,
|
||||
sharedMemorySize,
|
||||
_channel.BufferManager.HasUnalignedStorageBuffers);
|
||||
|
||||
cs = memoryManager.Physical.ShaderCache.GetComputeShader(_channel, poolState, computeState, shaderGpuVa);
|
||||
|
||||
_context.Renderer.Pipeline.SetProgram(cs.HostProgram);
|
||||
@ -175,30 +193,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
|
||||
info = cs.Shaders[0].Info;
|
||||
}
|
||||
|
||||
for (int index = 0; index < info.CBuffers.Count; index++)
|
||||
{
|
||||
BufferDescriptor cb = info.CBuffers[index];
|
||||
|
||||
// NVN uses the "hardware" constant buffer for anything that is less than 8,
|
||||
// and those are already bound above.
|
||||
// Anything greater than or equal to 8 uses the emulated constant buffers.
|
||||
// They are emulated using global memory loads.
|
||||
if (cb.Slot < 8)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ulong cbDescAddress = _channel.BufferManager.GetComputeUniformBufferAddress(0);
|
||||
|
||||
int cbDescOffset = 0x260 + (cb.Slot - 8) * 0x10;
|
||||
|
||||
cbDescAddress += (ulong)cbDescOffset;
|
||||
|
||||
SbDescriptor cbDescriptor = _channel.MemoryManager.Physical.Read<SbDescriptor>(cbDescAddress);
|
||||
|
||||
_channel.BufferManager.SetComputeUniformBuffer(cb.Slot, cbDescriptor.PackAddress(), (uint)cbDescriptor.Size);
|
||||
}
|
||||
|
||||
_channel.BufferManager.SetComputeBufferBindings(cs.Bindings);
|
||||
|
||||
_channel.TextureManager.SetComputeBindings(cs.Bindings);
|
||||
|
@ -100,22 +100,22 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
|
||||
{
|
||||
#pragma warning disable CS0649
|
||||
public uint SetObject;
|
||||
public int SetObjectClassId => (int)((SetObject >> 0) & 0xFFFF);
|
||||
public int SetObjectClassId => (int)(SetObject & 0xFFFF);
|
||||
public int SetObjectEngineId => (int)((SetObject >> 16) & 0x1F);
|
||||
public fixed uint Reserved04[63];
|
||||
public uint NoOperation;
|
||||
public uint SetNotifyA;
|
||||
public int SetNotifyAAddressUpper => (int)((SetNotifyA >> 0) & 0xFF);
|
||||
public int SetNotifyAAddressUpper => (int)(SetNotifyA & 0xFF);
|
||||
public uint SetNotifyB;
|
||||
public uint Notify;
|
||||
public NotifyType NotifyType => (NotifyType)(Notify);
|
||||
public uint WaitForIdle;
|
||||
public fixed uint Reserved114[7];
|
||||
public uint SetGlobalRenderEnableA;
|
||||
public int SetGlobalRenderEnableAOffsetUpper => (int)((SetGlobalRenderEnableA >> 0) & 0xFF);
|
||||
public int SetGlobalRenderEnableAOffsetUpper => (int)(SetGlobalRenderEnableA & 0xFF);
|
||||
public uint SetGlobalRenderEnableB;
|
||||
public uint SetGlobalRenderEnableC;
|
||||
public int SetGlobalRenderEnableCMode => (int)((SetGlobalRenderEnableC >> 0) & 0x7);
|
||||
public int SetGlobalRenderEnableCMode => (int)(SetGlobalRenderEnableC & 0x7);
|
||||
public uint SendGoIdle;
|
||||
public uint PmTrigger;
|
||||
public uint PmTriggerWfi;
|
||||
@ -126,11 +126,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
|
||||
public uint LineLengthIn;
|
||||
public uint LineCount;
|
||||
public uint OffsetOutUpper;
|
||||
public int OffsetOutUpperValue => (int)((OffsetOutUpper >> 0) & 0xFF);
|
||||
public int OffsetOutUpperValue => (int)(OffsetOutUpper & 0xFF);
|
||||
public uint OffsetOut;
|
||||
public uint PitchOut;
|
||||
public uint SetDstBlockSize;
|
||||
public SetDstBlockSizeWidth SetDstBlockSizeWidth => (SetDstBlockSizeWidth)((SetDstBlockSize >> 0) & 0xF);
|
||||
public SetDstBlockSizeWidth SetDstBlockSizeWidth => (SetDstBlockSizeWidth)(SetDstBlockSize & 0xF);
|
||||
public SetDstBlockSizeHeight SetDstBlockSizeHeight => (SetDstBlockSizeHeight)((SetDstBlockSize >> 4) & 0xF);
|
||||
public SetDstBlockSizeDepth SetDstBlockSizeDepth => (SetDstBlockSizeDepth)((SetDstBlockSize >> 8) & 0xF);
|
||||
public uint SetDstWidth;
|
||||
@ -138,11 +138,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
|
||||
public uint SetDstDepth;
|
||||
public uint SetDstLayer;
|
||||
public uint SetDstOriginBytesX;
|
||||
public int SetDstOriginBytesXV => (int)((SetDstOriginBytesX >> 0) & 0xFFFFF);
|
||||
public int SetDstOriginBytesXV => (int)(SetDstOriginBytesX & 0xFFFFF);
|
||||
public uint SetDstOriginSamplesY;
|
||||
public int SetDstOriginSamplesYV => (int)((SetDstOriginSamplesY >> 0) & 0xFFFF);
|
||||
public int SetDstOriginSamplesYV => (int)(SetDstOriginSamplesY & 0xFFFF);
|
||||
public uint LaunchDma;
|
||||
public LaunchDmaDstMemoryLayout LaunchDmaDstMemoryLayout => (LaunchDmaDstMemoryLayout)((LaunchDma >> 0) & 0x1);
|
||||
public LaunchDmaDstMemoryLayout LaunchDmaDstMemoryLayout => (LaunchDmaDstMemoryLayout)(LaunchDma & 0x1);
|
||||
public LaunchDmaCompletionType LaunchDmaCompletionType => (LaunchDmaCompletionType)((LaunchDma >> 4) & 0x3);
|
||||
public LaunchDmaInterruptType LaunchDmaInterruptType => (LaunchDmaInterruptType)((LaunchDma >> 8) & 0x3);
|
||||
public LaunchDmaSemaphoreStructSize LaunchDmaSemaphoreStructSize => (LaunchDmaSemaphoreStructSize)((LaunchDma >> 12) & 0x1);
|
||||
@ -153,7 +153,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
|
||||
public uint LoadInlineData;
|
||||
public fixed uint Reserved1B8[9];
|
||||
public uint SetI2mSemaphoreA;
|
||||
public int SetI2mSemaphoreAOffsetUpper => (int)((SetI2mSemaphoreA >> 0) & 0xFF);
|
||||
public int SetI2mSemaphoreAOffsetUpper => (int)(SetI2mSemaphoreA & 0xFF);
|
||||
public uint SetI2mSemaphoreB;
|
||||
public uint SetI2mSemaphoreC;
|
||||
public fixed uint Reserved1E8[2];
|
||||
@ -162,7 +162,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
|
||||
public uint SetI2mSpareNoop02;
|
||||
public uint SetI2mSpareNoop03;
|
||||
public uint SetValidSpanOverflowAreaA;
|
||||
public int SetValidSpanOverflowAreaAAddressUpper => (int)((SetValidSpanOverflowAreaA >> 0) & 0xFF);
|
||||
public int SetValidSpanOverflowAreaAAddressUpper => (int)(SetValidSpanOverflowAreaA & 0xFF);
|
||||
public uint SetValidSpanOverflowAreaB;
|
||||
public uint SetValidSpanOverflowAreaC;
|
||||
public uint SetCoalesceWaitingPeriodUnit;
|
||||
@ -185,12 +185,12 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
|
||||
public uint SetReservedSwMethod06;
|
||||
public uint SetReservedSwMethod07;
|
||||
public uint SetCwdControl;
|
||||
public SetCwdControlSmSelection SetCwdControlSmSelection => (SetCwdControlSmSelection)((SetCwdControl >> 0) & 0x1);
|
||||
public SetCwdControlSmSelection SetCwdControlSmSelection => (SetCwdControlSmSelection)(SetCwdControl & 0x1);
|
||||
public uint InvalidateTextureHeaderCacheNoWfi;
|
||||
public InvalidateCacheLines InvalidateTextureHeaderCacheNoWfiLines => (InvalidateCacheLines)((InvalidateTextureHeaderCacheNoWfi >> 0) & 0x1);
|
||||
public InvalidateCacheLines InvalidateTextureHeaderCacheNoWfiLines => (InvalidateCacheLines)(InvalidateTextureHeaderCacheNoWfi & 0x1);
|
||||
public int InvalidateTextureHeaderCacheNoWfiTag => (int)((InvalidateTextureHeaderCacheNoWfi >> 4) & 0x3FFFFF);
|
||||
public uint SetCwdRefCounter;
|
||||
public int SetCwdRefCounterSelect => (int)((SetCwdRefCounter >> 0) & 0x3F);
|
||||
public int SetCwdRefCounterSelect => (int)(SetCwdRefCounter & 0x3F);
|
||||
public int SetCwdRefCounterValue => (int)((SetCwdRefCounter >> 8) & 0xFFFF);
|
||||
public uint SetReservedSwMethod08;
|
||||
public uint SetReservedSwMethod09;
|
||||
@ -201,28 +201,28 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
|
||||
public uint SetReservedSwMethod14;
|
||||
public uint SetReservedSwMethod15;
|
||||
public uint SetGwcScgType;
|
||||
public SetGwcScgTypeScgType SetGwcScgTypeScgType => (SetGwcScgTypeScgType)((SetGwcScgType >> 0) & 0x1);
|
||||
public SetGwcScgTypeScgType SetGwcScgTypeScgType => (SetGwcScgTypeScgType)(SetGwcScgType & 0x1);
|
||||
public uint SetScgControl;
|
||||
public int SetScgControlCompute1MaxSmCount => (int)((SetScgControl >> 0) & 0x1FF);
|
||||
public int SetScgControlCompute1MaxSmCount => (int)(SetScgControl & 0x1FF);
|
||||
public uint InvalidateConstantBufferCacheA;
|
||||
public int InvalidateConstantBufferCacheAAddressUpper => (int)((InvalidateConstantBufferCacheA >> 0) & 0xFF);
|
||||
public int InvalidateConstantBufferCacheAAddressUpper => (int)(InvalidateConstantBufferCacheA & 0xFF);
|
||||
public uint InvalidateConstantBufferCacheB;
|
||||
public uint InvalidateConstantBufferCacheC;
|
||||
public int InvalidateConstantBufferCacheCByteCount => (int)((InvalidateConstantBufferCacheC >> 0) & 0x1FFFF);
|
||||
public int InvalidateConstantBufferCacheCByteCount => (int)(InvalidateConstantBufferCacheC & 0x1FFFF);
|
||||
public bool InvalidateConstantBufferCacheCThruL2 => (InvalidateConstantBufferCacheC & 0x80000000) != 0;
|
||||
public uint SetComputeClassVersion;
|
||||
public int SetComputeClassVersionCurrent => (int)((SetComputeClassVersion >> 0) & 0xFFFF);
|
||||
public int SetComputeClassVersionCurrent => (int)(SetComputeClassVersion & 0xFFFF);
|
||||
public int SetComputeClassVersionOldestSupported => (int)((SetComputeClassVersion >> 16) & 0xFFFF);
|
||||
public uint CheckComputeClassVersion;
|
||||
public int CheckComputeClassVersionCurrent => (int)((CheckComputeClassVersion >> 0) & 0xFFFF);
|
||||
public int CheckComputeClassVersionCurrent => (int)(CheckComputeClassVersion & 0xFFFF);
|
||||
public int CheckComputeClassVersionOldestSupported => (int)((CheckComputeClassVersion >> 16) & 0xFFFF);
|
||||
public uint SetQmdVersion;
|
||||
public int SetQmdVersionCurrent => (int)((SetQmdVersion >> 0) & 0xFFFF);
|
||||
public int SetQmdVersionCurrent => (int)(SetQmdVersion & 0xFFFF);
|
||||
public int SetQmdVersionOldestSupported => (int)((SetQmdVersion >> 16) & 0xFFFF);
|
||||
public uint SetWfiConfig;
|
||||
public bool SetWfiConfigEnableScgTypeWfi => (SetWfiConfig & 0x1) != 0;
|
||||
public uint CheckQmdVersion;
|
||||
public int CheckQmdVersionCurrent => (int)((CheckQmdVersion >> 0) & 0xFFFF);
|
||||
public int CheckQmdVersionCurrent => (int)(CheckQmdVersion & 0xFFFF);
|
||||
public int CheckQmdVersionOldestSupported => (int)((CheckQmdVersion >> 16) & 0xFFFF);
|
||||
public uint WaitForIdleScgType;
|
||||
public uint InvalidateSkedCaches;
|
||||
@ -231,28 +231,28 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
|
||||
public bool SetScgRenderEnableControlCompute1UsesRenderEnable => (SetScgRenderEnableControl & 0x1) != 0;
|
||||
public fixed uint Reserved2A0[4];
|
||||
public uint SetCwdSlotCount;
|
||||
public int SetCwdSlotCountV => (int)((SetCwdSlotCount >> 0) & 0xFF);
|
||||
public int SetCwdSlotCountV => (int)(SetCwdSlotCount & 0xFF);
|
||||
public uint SendPcasA;
|
||||
public uint SendPcasB;
|
||||
public int SendPcasBFrom => (int)((SendPcasB >> 0) & 0xFFFFFF);
|
||||
public int SendPcasBFrom => (int)(SendPcasB & 0xFFFFFF);
|
||||
public int SendPcasBDelta => (int)((SendPcasB >> 24) & 0xFF);
|
||||
public uint SendSignalingPcasB;
|
||||
public bool SendSignalingPcasBInvalidate => (SendSignalingPcasB & 0x1) != 0;
|
||||
public bool SendSignalingPcasBSchedule => (SendSignalingPcasB & 0x2) != 0;
|
||||
public fixed uint Reserved2C0[9];
|
||||
public uint SetShaderLocalMemoryNonThrottledA;
|
||||
public int SetShaderLocalMemoryNonThrottledASizeUpper => (int)((SetShaderLocalMemoryNonThrottledA >> 0) & 0xFF);
|
||||
public int SetShaderLocalMemoryNonThrottledASizeUpper => (int)(SetShaderLocalMemoryNonThrottledA & 0xFF);
|
||||
public uint SetShaderLocalMemoryNonThrottledB;
|
||||
public uint SetShaderLocalMemoryNonThrottledC;
|
||||
public int SetShaderLocalMemoryNonThrottledCMaxSmCount => (int)((SetShaderLocalMemoryNonThrottledC >> 0) & 0x1FF);
|
||||
public int SetShaderLocalMemoryNonThrottledCMaxSmCount => (int)(SetShaderLocalMemoryNonThrottledC & 0x1FF);
|
||||
public uint SetShaderLocalMemoryThrottledA;
|
||||
public int SetShaderLocalMemoryThrottledASizeUpper => (int)((SetShaderLocalMemoryThrottledA >> 0) & 0xFF);
|
||||
public int SetShaderLocalMemoryThrottledASizeUpper => (int)(SetShaderLocalMemoryThrottledA & 0xFF);
|
||||
public uint SetShaderLocalMemoryThrottledB;
|
||||
public uint SetShaderLocalMemoryThrottledC;
|
||||
public int SetShaderLocalMemoryThrottledCMaxSmCount => (int)((SetShaderLocalMemoryThrottledC >> 0) & 0x1FF);
|
||||
public int SetShaderLocalMemoryThrottledCMaxSmCount => (int)(SetShaderLocalMemoryThrottledC & 0x1FF);
|
||||
public fixed uint Reserved2FC[5];
|
||||
public uint SetSpaVersion;
|
||||
public int SetSpaVersionMinor => (int)((SetSpaVersion >> 0) & 0xFF);
|
||||
public int SetSpaVersionMinor => (int)(SetSpaVersion & 0xFF);
|
||||
public int SetSpaVersionMajor => (int)((SetSpaVersion >> 8) & 0xFF);
|
||||
public fixed uint Reserved314[123];
|
||||
public uint SetFalcon00;
|
||||
@ -291,14 +291,14 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
|
||||
public uint SetShaderLocalMemoryWindow;
|
||||
public fixed uint Reserved780[4];
|
||||
public uint SetShaderLocalMemoryA;
|
||||
public int SetShaderLocalMemoryAAddressUpper => (int)((SetShaderLocalMemoryA >> 0) & 0xFF);
|
||||
public int SetShaderLocalMemoryAAddressUpper => (int)(SetShaderLocalMemoryA & 0xFF);
|
||||
public uint SetShaderLocalMemoryB;
|
||||
public fixed uint Reserved798[383];
|
||||
public uint SetShaderCacheControl;
|
||||
public bool SetShaderCacheControlIcachePrefetchEnable => (SetShaderCacheControl & 0x1) != 0;
|
||||
public fixed uint ReservedD98[19];
|
||||
public uint SetSmTimeoutInterval;
|
||||
public int SetSmTimeoutIntervalCounterBit => (int)((SetSmTimeoutInterval >> 0) & 0x3F);
|
||||
public int SetSmTimeoutIntervalCounterBit => (int)(SetSmTimeoutInterval & 0x3F);
|
||||
public fixed uint ReservedDE8[87];
|
||||
public uint SetSpareNoop12;
|
||||
public uint SetSpareNoop13;
|
||||
@ -324,48 +324,48 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
|
||||
public bool InvalidateTextureHeaderCacheAllV => (InvalidateTextureHeaderCacheAll & 0x1) != 0;
|
||||
public fixed uint Reserved1214[29];
|
||||
public uint InvalidateTextureDataCacheNoWfi;
|
||||
public InvalidateCacheLines InvalidateTextureDataCacheNoWfiLines => (InvalidateCacheLines)((InvalidateTextureDataCacheNoWfi >> 0) & 0x1);
|
||||
public InvalidateCacheLines InvalidateTextureDataCacheNoWfiLines => (InvalidateCacheLines)(InvalidateTextureDataCacheNoWfi & 0x1);
|
||||
public int InvalidateTextureDataCacheNoWfiTag => (int)((InvalidateTextureDataCacheNoWfi >> 4) & 0x3FFFFF);
|
||||
public fixed uint Reserved128C[7];
|
||||
public uint ActivatePerfSettingsForComputeContext;
|
||||
public bool ActivatePerfSettingsForComputeContextAll => (ActivatePerfSettingsForComputeContext & 0x1) != 0;
|
||||
public fixed uint Reserved12AC[33];
|
||||
public uint InvalidateSamplerCache;
|
||||
public InvalidateCacheLines InvalidateSamplerCacheLines => (InvalidateCacheLines)((InvalidateSamplerCache >> 0) & 0x1);
|
||||
public InvalidateCacheLines InvalidateSamplerCacheLines => (InvalidateCacheLines)(InvalidateSamplerCache & 0x1);
|
||||
public int InvalidateSamplerCacheTag => (int)((InvalidateSamplerCache >> 4) & 0x3FFFFF);
|
||||
public uint InvalidateTextureHeaderCache;
|
||||
public InvalidateCacheLines InvalidateTextureHeaderCacheLines => (InvalidateCacheLines)((InvalidateTextureHeaderCache >> 0) & 0x1);
|
||||
public InvalidateCacheLines InvalidateTextureHeaderCacheLines => (InvalidateCacheLines)(InvalidateTextureHeaderCache & 0x1);
|
||||
public int InvalidateTextureHeaderCacheTag => (int)((InvalidateTextureHeaderCache >> 4) & 0x3FFFFF);
|
||||
public uint InvalidateTextureDataCache;
|
||||
public InvalidateCacheLines InvalidateTextureDataCacheLines => (InvalidateCacheLines)((InvalidateTextureDataCache >> 0) & 0x1);
|
||||
public InvalidateCacheLines InvalidateTextureDataCacheLines => (InvalidateCacheLines)(InvalidateTextureDataCache & 0x1);
|
||||
public int InvalidateTextureDataCacheTag => (int)((InvalidateTextureDataCache >> 4) & 0x3FFFFF);
|
||||
public fixed uint Reserved133C[58];
|
||||
public uint InvalidateSamplerCacheNoWfi;
|
||||
public InvalidateCacheLines InvalidateSamplerCacheNoWfiLines => (InvalidateCacheLines)((InvalidateSamplerCacheNoWfi >> 0) & 0x1);
|
||||
public InvalidateCacheLines InvalidateSamplerCacheNoWfiLines => (InvalidateCacheLines)(InvalidateSamplerCacheNoWfi & 0x1);
|
||||
public int InvalidateSamplerCacheNoWfiTag => (int)((InvalidateSamplerCacheNoWfi >> 4) & 0x3FFFFF);
|
||||
public fixed uint Reserved1428[64];
|
||||
public uint SetShaderExceptions;
|
||||
public bool SetShaderExceptionsEnable => (SetShaderExceptions & 0x1) != 0;
|
||||
public fixed uint Reserved152C[9];
|
||||
public uint SetRenderEnableA;
|
||||
public int SetRenderEnableAOffsetUpper => (int)((SetRenderEnableA >> 0) & 0xFF);
|
||||
public int SetRenderEnableAOffsetUpper => (int)(SetRenderEnableA & 0xFF);
|
||||
public uint SetRenderEnableB;
|
||||
public uint SetRenderEnableC;
|
||||
public int SetRenderEnableCMode => (int)((SetRenderEnableC >> 0) & 0x7);
|
||||
public int SetRenderEnableCMode => (int)(SetRenderEnableC & 0x7);
|
||||
public uint SetTexSamplerPoolA;
|
||||
public int SetTexSamplerPoolAOffsetUpper => (int)((SetTexSamplerPoolA >> 0) & 0xFF);
|
||||
public int SetTexSamplerPoolAOffsetUpper => (int)(SetTexSamplerPoolA & 0xFF);
|
||||
public uint SetTexSamplerPoolB;
|
||||
public uint SetTexSamplerPoolC;
|
||||
public int SetTexSamplerPoolCMaximumIndex => (int)((SetTexSamplerPoolC >> 0) & 0xFFFFF);
|
||||
public int SetTexSamplerPoolCMaximumIndex => (int)(SetTexSamplerPoolC & 0xFFFFF);
|
||||
public fixed uint Reserved1568[3];
|
||||
public uint SetTexHeaderPoolA;
|
||||
public int SetTexHeaderPoolAOffsetUpper => (int)((SetTexHeaderPoolA >> 0) & 0xFF);
|
||||
public int SetTexHeaderPoolAOffsetUpper => (int)(SetTexHeaderPoolA & 0xFF);
|
||||
public uint SetTexHeaderPoolB;
|
||||
public uint SetTexHeaderPoolC;
|
||||
public int SetTexHeaderPoolCMaximumIndex => (int)((SetTexHeaderPoolC >> 0) & 0x3FFFFF);
|
||||
public int SetTexHeaderPoolCMaximumIndex => (int)(SetTexHeaderPoolC & 0x3FFFFF);
|
||||
public fixed uint Reserved1580[34];
|
||||
public uint SetProgramRegionA;
|
||||
public int SetProgramRegionAAddressUpper => (int)((SetProgramRegionA >> 0) & 0xFF);
|
||||
public int SetProgramRegionAAddressUpper => (int)(SetProgramRegionA & 0xFF);
|
||||
public uint SetProgramRegionB;
|
||||
public fixed uint Reserved1610[34];
|
||||
public uint InvalidateShaderCachesNoWfi;
|
||||
@ -374,7 +374,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
|
||||
public bool InvalidateShaderCachesNoWfiConstant => (InvalidateShaderCachesNoWfi & 0x1000) != 0;
|
||||
public fixed uint Reserved169C[170];
|
||||
public uint SetRenderEnableOverride;
|
||||
public SetRenderEnableOverrideMode SetRenderEnableOverrideMode => (SetRenderEnableOverrideMode)((SetRenderEnableOverride >> 0) & 0x3);
|
||||
public SetRenderEnableOverrideMode SetRenderEnableOverrideMode => (SetRenderEnableOverrideMode)(SetRenderEnableOverride & 0x3);
|
||||
public fixed uint Reserved1948[57];
|
||||
public uint PipeNop;
|
||||
public uint SetSpare00;
|
||||
@ -383,11 +383,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
|
||||
public uint SetSpare03;
|
||||
public fixed uint Reserved1A40[48];
|
||||
public uint SetReportSemaphoreA;
|
||||
public int SetReportSemaphoreAOffsetUpper => (int)((SetReportSemaphoreA >> 0) & 0xFF);
|
||||
public int SetReportSemaphoreAOffsetUpper => (int)(SetReportSemaphoreA & 0xFF);
|
||||
public uint SetReportSemaphoreB;
|
||||
public uint SetReportSemaphoreC;
|
||||
public uint SetReportSemaphoreD;
|
||||
public SetReportSemaphoreDOperation SetReportSemaphoreDOperation => (SetReportSemaphoreDOperation)((SetReportSemaphoreD >> 0) & 0x3);
|
||||
public SetReportSemaphoreDOperation SetReportSemaphoreDOperation => (SetReportSemaphoreDOperation)(SetReportSemaphoreD & 0x3);
|
||||
public bool SetReportSemaphoreDAwakenEnable => (SetReportSemaphoreD & 0x100000) != 0;
|
||||
public SetReportSemaphoreDStructureSize SetReportSemaphoreDStructureSize => (SetReportSemaphoreDStructureSize)((SetReportSemaphoreD >> 28) & 0x1);
|
||||
public bool SetReportSemaphoreDFlushDisable => (SetReportSemaphoreD & 0x4) != 0;
|
||||
@ -396,7 +396,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
|
||||
public SetReportSemaphoreDReductionFormat SetReportSemaphoreDReductionFormat => (SetReportSemaphoreDReductionFormat)((SetReportSemaphoreD >> 17) & 0x3);
|
||||
public fixed uint Reserved1B10[702];
|
||||
public uint SetBindlessTexture;
|
||||
public int SetBindlessTextureConstantBufferSlotSelect => (int)((SetBindlessTexture >> 0) & 0x7);
|
||||
public int SetBindlessTextureConstantBufferSlotSelect => (int)(SetBindlessTexture & 0x7);
|
||||
public uint SetTrapHandler;
|
||||
public fixed uint Reserved2610[843];
|
||||
public Array8<uint> SetShaderPerformanceCounterValueUpper;
|
||||
@ -423,11 +423,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
|
||||
public bool SetShaderPerformanceCounterControlBWindowed(int i) => (SetShaderPerformanceCounterControlB[i] & 0x8) != 0;
|
||||
public int SetShaderPerformanceCounterControlBFunc(int i) => (int)((SetShaderPerformanceCounterControlB[i] >> 4) & 0xFFFF);
|
||||
public uint SetShaderPerformanceCounterTrapControl;
|
||||
public int SetShaderPerformanceCounterTrapControlMask => (int)((SetShaderPerformanceCounterTrapControl >> 0) & 0xFF);
|
||||
public int SetShaderPerformanceCounterTrapControlMask => (int)(SetShaderPerformanceCounterTrapControl & 0xFF);
|
||||
public uint StartShaderPerformanceCounter;
|
||||
public int StartShaderPerformanceCounterCounterMask => (int)((StartShaderPerformanceCounter >> 0) & 0xFF);
|
||||
public int StartShaderPerformanceCounterCounterMask => (int)(StartShaderPerformanceCounter & 0xFF);
|
||||
public uint StopShaderPerformanceCounter;
|
||||
public int StopShaderPerformanceCounterCounterMask => (int)((StopShaderPerformanceCounter >> 0) & 0xFF);
|
||||
public int StopShaderPerformanceCounterCounterMask => (int)(StopShaderPerformanceCounter & 0xFF);
|
||||
public fixed uint Reserved33E8[6];
|
||||
public MmeShadowScratch SetMmeShadowScratch;
|
||||
#pragma warning restore CS0649
|
||||
|
@ -186,22 +186,22 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
|
||||
public uint PmTrigger;
|
||||
public fixed uint Reserved144[63];
|
||||
public uint SetSemaphoreA;
|
||||
public int SetSemaphoreAUpper => (int)((SetSemaphoreA >> 0) & 0xFF);
|
||||
public int SetSemaphoreAUpper => (int)(SetSemaphoreA & 0xFF);
|
||||
public uint SetSemaphoreB;
|
||||
public uint SetSemaphorePayload;
|
||||
public fixed uint Reserved24C[2];
|
||||
public uint SetRenderEnableA;
|
||||
public int SetRenderEnableAUpper => (int)((SetRenderEnableA >> 0) & 0xFF);
|
||||
public int SetRenderEnableAUpper => (int)(SetRenderEnableA & 0xFF);
|
||||
public uint SetRenderEnableB;
|
||||
public uint SetRenderEnableC;
|
||||
public int SetRenderEnableCMode => (int)((SetRenderEnableC >> 0) & 0x7);
|
||||
public int SetRenderEnableCMode => (int)(SetRenderEnableC & 0x7);
|
||||
public uint SetSrcPhysMode;
|
||||
public SetPhysModeTarget SetSrcPhysModeTarget => (SetPhysModeTarget)((SetSrcPhysMode >> 0) & 0x3);
|
||||
public SetPhysModeTarget SetSrcPhysModeTarget => (SetPhysModeTarget)(SetSrcPhysMode & 0x3);
|
||||
public uint SetDstPhysMode;
|
||||
public SetPhysModeTarget SetDstPhysModeTarget => (SetPhysModeTarget)((SetDstPhysMode >> 0) & 0x3);
|
||||
public SetPhysModeTarget SetDstPhysModeTarget => (SetPhysModeTarget)(SetDstPhysMode & 0x3);
|
||||
public fixed uint Reserved268[38];
|
||||
public uint LaunchDma;
|
||||
public LaunchDmaDataTransferType LaunchDmaDataTransferType => (LaunchDmaDataTransferType)((LaunchDma >> 0) & 0x3);
|
||||
public LaunchDmaDataTransferType LaunchDmaDataTransferType => (LaunchDmaDataTransferType)(LaunchDma & 0x3);
|
||||
public bool LaunchDmaFlushEnable => (LaunchDma & 0x4) != 0;
|
||||
public LaunchDmaSemaphoreType LaunchDmaSemaphoreType => (LaunchDmaSemaphoreType)((LaunchDma >> 3) & 0x3);
|
||||
public LaunchDmaInterruptType LaunchDmaInterruptType => (LaunchDmaInterruptType)((LaunchDma >> 5) & 0x3);
|
||||
@ -218,10 +218,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
|
||||
public LaunchDmaBypassL2 LaunchDmaBypassL2 => (LaunchDmaBypassL2)((LaunchDma >> 20) & 0x1);
|
||||
public fixed uint Reserved304[63];
|
||||
public uint OffsetInUpper;
|
||||
public int OffsetInUpperUpper => (int)((OffsetInUpper >> 0) & 0xFF);
|
||||
public int OffsetInUpperUpper => (int)(OffsetInUpper & 0xFF);
|
||||
public uint OffsetInLower;
|
||||
public uint OffsetOutUpper;
|
||||
public int OffsetOutUpperUpper => (int)((OffsetOutUpper >> 0) & 0xFF);
|
||||
public int OffsetOutUpperUpper => (int)(OffsetOutUpper & 0xFF);
|
||||
public uint OffsetOutLower;
|
||||
public uint PitchIn;
|
||||
public uint PitchOut;
|
||||
@ -231,7 +231,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
|
||||
public uint SetRemapConstA;
|
||||
public uint SetRemapConstB;
|
||||
public uint SetRemapComponents;
|
||||
public SetRemapComponentsDst SetRemapComponentsDstX => (SetRemapComponentsDst)((SetRemapComponents >> 0) & 0x7);
|
||||
public SetRemapComponentsDst SetRemapComponentsDstX => (SetRemapComponentsDst)(SetRemapComponents & 0x7);
|
||||
public SetRemapComponentsDst SetRemapComponentsDstY => (SetRemapComponentsDst)((SetRemapComponents >> 4) & 0x7);
|
||||
public SetRemapComponentsDst SetRemapComponentsDstZ => (SetRemapComponentsDst)((SetRemapComponents >> 8) & 0x7);
|
||||
public SetRemapComponentsDst SetRemapComponentsDstW => (SetRemapComponentsDst)((SetRemapComponents >> 12) & 0x7);
|
||||
@ -239,7 +239,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
|
||||
public SetRemapComponentsNumComponents SetRemapComponentsNumSrcComponents => (SetRemapComponentsNumComponents)((SetRemapComponents >> 20) & 0x3);
|
||||
public SetRemapComponentsNumComponents SetRemapComponentsNumDstComponents => (SetRemapComponentsNumComponents)((SetRemapComponents >> 24) & 0x3);
|
||||
public uint SetDstBlockSize;
|
||||
public SetBlockSizeWidth SetDstBlockSizeWidth => (SetBlockSizeWidth)((SetDstBlockSize >> 0) & 0xF);
|
||||
public SetBlockSizeWidth SetDstBlockSizeWidth => (SetBlockSizeWidth)(SetDstBlockSize & 0xF);
|
||||
public SetBlockSizeHeight SetDstBlockSizeHeight => (SetBlockSizeHeight)((SetDstBlockSize >> 4) & 0xF);
|
||||
public SetBlockSizeDepth SetDstBlockSizeDepth => (SetBlockSizeDepth)((SetDstBlockSize >> 8) & 0xF);
|
||||
public SetBlockSizeGobHeight SetDstBlockSizeGobHeight => (SetBlockSizeGobHeight)((SetDstBlockSize >> 12) & 0xF);
|
||||
@ -248,11 +248,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
|
||||
public uint SetDstDepth;
|
||||
public uint SetDstLayer;
|
||||
public uint SetDstOrigin;
|
||||
public int SetDstOriginX => (int)((SetDstOrigin >> 0) & 0xFFFF);
|
||||
public int SetDstOriginX => (int)(SetDstOrigin & 0xFFFF);
|
||||
public int SetDstOriginY => (int)((SetDstOrigin >> 16) & 0xFFFF);
|
||||
public uint Reserved724;
|
||||
public uint SetSrcBlockSize;
|
||||
public SetBlockSizeWidth SetSrcBlockSizeWidth => (SetBlockSizeWidth)((SetSrcBlockSize >> 0) & 0xF);
|
||||
public SetBlockSizeWidth SetSrcBlockSizeWidth => (SetBlockSizeWidth)(SetSrcBlockSize & 0xF);
|
||||
public SetBlockSizeHeight SetSrcBlockSizeHeight => (SetBlockSizeHeight)((SetSrcBlockSize >> 4) & 0xF);
|
||||
public SetBlockSizeDepth SetSrcBlockSizeDepth => (SetBlockSizeDepth)((SetSrcBlockSize >> 8) & 0xF);
|
||||
public SetBlockSizeGobHeight SetSrcBlockSizeGobHeight => (SetBlockSizeGobHeight)((SetSrcBlockSize >> 12) & 0xF);
|
||||
@ -261,7 +261,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
|
||||
public uint SetSrcDepth;
|
||||
public uint SetSrcLayer;
|
||||
public uint SetSrcOrigin;
|
||||
public int SetSrcOriginX => (int)((SetSrcOrigin >> 0) & 0xFFFF);
|
||||
public int SetSrcOriginX => (int)(SetSrcOrigin & 0xFFFF);
|
||||
public int SetSrcOriginY => (int)((SetSrcOrigin >> 16) & 0xFFFF);
|
||||
public fixed uint Reserved740[629];
|
||||
public uint PmTriggerEnd;
|
||||
|
@ -29,7 +29,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
|
||||
public uint Method;
|
||||
#pragma warning restore CS0649
|
||||
public int MethodAddressOld => (int)((Method >> 2) & 0x7FF);
|
||||
public int MethodAddress => (int)((Method >> 0) & 0xFFF);
|
||||
public int MethodAddress => (int)(Method & 0xFFF);
|
||||
public int SubdeviceMask => (int)((Method >> 4) & 0xFFF);
|
||||
public int MethodSubchannel => (int)((Method >> 13) & 0x7);
|
||||
public TertOp TertOp => (TertOp)((Method >> 16) & 0x3);
|
||||
|
@ -39,17 +39,17 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
|
||||
#pragma warning disable CS0649
|
||||
public uint Entry0;
|
||||
#pragma warning restore CS0649
|
||||
public Entry0Fetch Entry0Fetch => (Entry0Fetch)((Entry0 >> 0) & 0x1);
|
||||
public Entry0Fetch Entry0Fetch => (Entry0Fetch)(Entry0 & 0x1);
|
||||
public int Entry0Get => (int)((Entry0 >> 2) & 0x3FFFFFFF);
|
||||
public int Entry0Operand => (int)(Entry0);
|
||||
#pragma warning disable CS0649
|
||||
public uint Entry1;
|
||||
#pragma warning restore CS0649
|
||||
public int Entry1GetHi => (int)((Entry1 >> 0) & 0xFF);
|
||||
public int Entry1GetHi => (int)(Entry1 & 0xFF);
|
||||
public Entry1Priv Entry1Priv => (Entry1Priv)((Entry1 >> 8) & 0x1);
|
||||
public Entry1Level Entry1Level => (Entry1Level)((Entry1 >> 9) & 0x1);
|
||||
public int Entry1Length => (int)((Entry1 >> 10) & 0x1FFFFF);
|
||||
public Entry1Sync Entry1Sync => (Entry1Sync)((Entry1 >> 31) & 0x1);
|
||||
public Entry1Opcode Entry1Opcode => (Entry1Opcode)((Entry1 >> 0) & 0xFF);
|
||||
public Entry1Opcode Entry1Opcode => (Entry1Opcode)(Entry1 & 0xFF);
|
||||
}
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
|
||||
{
|
||||
#pragma warning disable CS0649
|
||||
public uint SetObject;
|
||||
public int SetObjectNvclass => (int)((SetObject >> 0) & 0xFFFF);
|
||||
public int SetObjectNvclass => (int)(SetObject & 0xFFFF);
|
||||
public int SetObjectEngine => (int)((SetObject >> 16) & 0x1F);
|
||||
public uint Illegal;
|
||||
public int IllegalHandle => (int)(Illegal);
|
||||
@ -161,13 +161,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
|
||||
public int NopHandle => (int)(Nop);
|
||||
public uint Reserved0C;
|
||||
public uint Semaphorea;
|
||||
public int SemaphoreaOffsetUpper => (int)((Semaphorea >> 0) & 0xFF);
|
||||
public int SemaphoreaOffsetUpper => (int)(Semaphorea & 0xFF);
|
||||
public uint Semaphoreb;
|
||||
public int SemaphorebOffsetLower => (int)((Semaphoreb >> 2) & 0x3FFFFFFF);
|
||||
public uint Semaphorec;
|
||||
public int SemaphorecPayload => (int)(Semaphorec);
|
||||
public uint Semaphored;
|
||||
public SemaphoredOperation SemaphoredOperation => (SemaphoredOperation)((Semaphored >> 0) & 0x1F);
|
||||
public SemaphoredOperation SemaphoredOperation => (SemaphoredOperation)(Semaphored & 0x1F);
|
||||
public SemaphoredAcquireSwitch SemaphoredAcquireSwitch => (SemaphoredAcquireSwitch)((Semaphored >> 12) & 0x1);
|
||||
public SemaphoredReleaseWfi SemaphoredReleaseWfi => (SemaphoredReleaseWfi)((Semaphored >> 20) & 0x1);
|
||||
public SemaphoredReleaseSize SemaphoredReleaseSize => (SemaphoredReleaseSize)((Semaphored >> 24) & 0x1);
|
||||
@ -181,14 +181,14 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
|
||||
public uint Reserved2C;
|
||||
public uint MemOpC;
|
||||
public int MemOpCOperandLow => (int)((MemOpC >> 2) & 0x3FFFFFFF);
|
||||
public MemOpCTlbInvalidatePdb MemOpCTlbInvalidatePdb => (MemOpCTlbInvalidatePdb)((MemOpC >> 0) & 0x1);
|
||||
public MemOpCTlbInvalidatePdb MemOpCTlbInvalidatePdb => (MemOpCTlbInvalidatePdb)(MemOpC & 0x1);
|
||||
public MemOpCTlbInvalidateGpc MemOpCTlbInvalidateGpc => (MemOpCTlbInvalidateGpc)((MemOpC >> 1) & 0x1);
|
||||
public MemOpCTlbInvalidateTarget MemOpCTlbInvalidateTarget => (MemOpCTlbInvalidateTarget)((MemOpC >> 10) & 0x3);
|
||||
public int MemOpCTlbInvalidateAddrLo => (int)((MemOpC >> 12) & 0xFFFFF);
|
||||
public uint MemOpD;
|
||||
public int MemOpDOperandHigh => (int)((MemOpD >> 0) & 0xFF);
|
||||
public int MemOpDOperandHigh => (int)(MemOpD & 0xFF);
|
||||
public MemOpDOperation MemOpDOperation => (MemOpDOperation)((MemOpD >> 27) & 0x1F);
|
||||
public int MemOpDTlbInvalidateAddrHi => (int)((MemOpD >> 0) & 0xFF);
|
||||
public int MemOpDTlbInvalidateAddrHi => (int)(MemOpD & 0xFF);
|
||||
public uint Reserved38;
|
||||
public uint Reserved3C;
|
||||
public uint Reserved40;
|
||||
@ -207,15 +207,15 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
|
||||
public uint Syncpointa;
|
||||
public int SyncpointaPayload => (int)(Syncpointa);
|
||||
public uint Syncpointb;
|
||||
public SyncpointbOperation SyncpointbOperation => (SyncpointbOperation)((Syncpointb >> 0) & 0x1);
|
||||
public SyncpointbOperation SyncpointbOperation => (SyncpointbOperation)(Syncpointb & 0x1);
|
||||
public SyncpointbWaitSwitch SyncpointbWaitSwitch => (SyncpointbWaitSwitch)((Syncpointb >> 4) & 0x1);
|
||||
public int SyncpointbSyncptIndex => (int)((Syncpointb >> 8) & 0xFFF);
|
||||
public uint Wfi;
|
||||
public WfiScope WfiScope => (WfiScope)((Wfi >> 0) & 0x1);
|
||||
public WfiScope WfiScope => (WfiScope)(Wfi & 0x1);
|
||||
public uint CrcCheck;
|
||||
public int CrcCheckValue => (int)(CrcCheck);
|
||||
public uint Yield;
|
||||
public YieldOp YieldOp => (YieldOp)((Yield >> 0) & 0x3);
|
||||
public YieldOp YieldOp => (YieldOp)(Yield & 0x3);
|
||||
// TODO: Eventually move this to per-engine state.
|
||||
public Array31<uint> Reserved84;
|
||||
public uint NoOperation;
|
||||
|
@ -113,22 +113,22 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory
|
||||
{
|
||||
#pragma warning disable CS0649
|
||||
public uint SetObject;
|
||||
public int SetObjectClassId => (int)((SetObject >> 0) & 0xFFFF);
|
||||
public int SetObjectClassId => (int)(SetObject & 0xFFFF);
|
||||
public int SetObjectEngineId => (int)((SetObject >> 16) & 0x1F);
|
||||
public fixed uint Reserved04[63];
|
||||
public uint NoOperation;
|
||||
public uint SetNotifyA;
|
||||
public int SetNotifyAAddressUpper => (int)((SetNotifyA >> 0) & 0xFF);
|
||||
public int SetNotifyAAddressUpper => (int)(SetNotifyA & 0xFF);
|
||||
public uint SetNotifyB;
|
||||
public uint Notify;
|
||||
public NotifyType NotifyType => (NotifyType)(Notify);
|
||||
public uint WaitForIdle;
|
||||
public fixed uint Reserved114[7];
|
||||
public uint SetGlobalRenderEnableA;
|
||||
public int SetGlobalRenderEnableAOffsetUpper => (int)((SetGlobalRenderEnableA >> 0) & 0xFF);
|
||||
public int SetGlobalRenderEnableAOffsetUpper => (int)(SetGlobalRenderEnableA & 0xFF);
|
||||
public uint SetGlobalRenderEnableB;
|
||||
public uint SetGlobalRenderEnableC;
|
||||
public int SetGlobalRenderEnableCMode => (int)((SetGlobalRenderEnableC >> 0) & 0x7);
|
||||
public int SetGlobalRenderEnableCMode => (int)(SetGlobalRenderEnableC & 0x7);
|
||||
public uint SendGoIdle;
|
||||
public uint PmTrigger;
|
||||
public uint PmTriggerWfi;
|
||||
@ -139,11 +139,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory
|
||||
public uint LineLengthIn;
|
||||
public uint LineCount;
|
||||
public uint OffsetOutUpper;
|
||||
public int OffsetOutUpperValue => (int)((OffsetOutUpper >> 0) & 0xFF);
|
||||
public int OffsetOutUpperValue => (int)(OffsetOutUpper & 0xFF);
|
||||
public uint OffsetOut;
|
||||
public uint PitchOut;
|
||||
public uint SetDstBlockSize;
|
||||
public SetDstBlockSizeWidth SetDstBlockSizeWidth => (SetDstBlockSizeWidth)((SetDstBlockSize >> 0) & 0xF);
|
||||
public SetDstBlockSizeWidth SetDstBlockSizeWidth => (SetDstBlockSizeWidth)(SetDstBlockSize & 0xF);
|
||||
public SetDstBlockSizeHeight SetDstBlockSizeHeight => (SetDstBlockSizeHeight)((SetDstBlockSize >> 4) & 0xF);
|
||||
public SetDstBlockSizeDepth SetDstBlockSizeDepth => (SetDstBlockSizeDepth)((SetDstBlockSize >> 8) & 0xF);
|
||||
public uint SetDstWidth;
|
||||
@ -151,11 +151,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory
|
||||
public uint SetDstDepth;
|
||||
public uint SetDstLayer;
|
||||
public uint SetDstOriginBytesX;
|
||||
public int SetDstOriginBytesXV => (int)((SetDstOriginBytesX >> 0) & 0xFFFFF);
|
||||
public int SetDstOriginBytesXV => (int)(SetDstOriginBytesX & 0xFFFFF);
|
||||
public uint SetDstOriginSamplesY;
|
||||
public int SetDstOriginSamplesYV => (int)((SetDstOriginSamplesY >> 0) & 0xFFFF);
|
||||
public int SetDstOriginSamplesYV => (int)(SetDstOriginSamplesY & 0xFFFF);
|
||||
public uint LaunchDma;
|
||||
public LaunchDmaDstMemoryLayout LaunchDmaDstMemoryLayout => (LaunchDmaDstMemoryLayout)((LaunchDma >> 0) & 0x1);
|
||||
public LaunchDmaDstMemoryLayout LaunchDmaDstMemoryLayout => (LaunchDmaDstMemoryLayout)(LaunchDma & 0x1);
|
||||
public LaunchDmaCompletionType LaunchDmaCompletionType => (LaunchDmaCompletionType)((LaunchDma >> 4) & 0x3);
|
||||
public LaunchDmaInterruptType LaunchDmaInterruptType => (LaunchDmaInterruptType)((LaunchDma >> 8) & 0x3);
|
||||
public LaunchDmaSemaphoreStructSize LaunchDmaSemaphoreStructSize => (LaunchDmaSemaphoreStructSize)((LaunchDma >> 12) & 0x1);
|
||||
@ -166,7 +166,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory
|
||||
public uint LoadInlineData;
|
||||
public fixed uint Reserved1B8[9];
|
||||
public uint SetI2mSemaphoreA;
|
||||
public int SetI2mSemaphoreAOffsetUpper => (int)((SetI2mSemaphoreA >> 0) & 0xFF);
|
||||
public int SetI2mSemaphoreAOffsetUpper => (int)(SetI2mSemaphoreA & 0xFF);
|
||||
public uint SetI2mSemaphoreB;
|
||||
public uint SetI2mSemaphoreC;
|
||||
public fixed uint Reserved1E8[2];
|
||||
|
@ -539,6 +539,14 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
|
||||
engine.UpdateState();
|
||||
|
||||
if (instanceCount > 1)
|
||||
{
|
||||
// Must be called after UpdateState as it assumes the shader state
|
||||
// has already been set, and that bindings have been updated already.
|
||||
|
||||
_channel.BufferManager.SetInstancedDrawVertexCount(count);
|
||||
}
|
||||
|
||||
if (indexed)
|
||||
{
|
||||
_context.Renderer.Pipeline.DrawIndexed(count, instanceCount, firstIndex, firstVertex, firstInstance);
|
||||
@ -676,6 +684,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
_channel.BufferManager.SetIndexBuffer(br, IndexType.UInt);
|
||||
}
|
||||
|
||||
_channel.BufferManager.SetInstancedDrawVertexCount(_instancedIndexCount);
|
||||
|
||||
_context.Renderer.Pipeline.DrawIndexed(
|
||||
_instancedIndexCount,
|
||||
_instanceIndex + 1,
|
||||
@ -685,6 +695,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
}
|
||||
else
|
||||
{
|
||||
_channel.BufferManager.SetInstancedDrawVertexCount(_instancedDrawStateCount);
|
||||
|
||||
_context.Renderer.Pipeline.Draw(
|
||||
_instancedDrawStateCount,
|
||||
_instanceIndex + 1,
|
||||
|
@ -269,7 +269,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
_prevFirstVertex = _state.State.FirstVertex;
|
||||
}
|
||||
|
||||
bool tfEnable = _state.State.TfEnable;
|
||||
bool tfEnable = _state.State.TfEnable && _context.Capabilities.SupportsTransformFeedback;
|
||||
|
||||
if (!tfEnable && _prevTfEnable)
|
||||
{
|
||||
@ -356,7 +356,19 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
|
||||
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 == Constants.DriverReservedUniformBuffer)
|
||||
{
|
||||
// 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(), Constants.MaxUnknownStorageSize);
|
||||
}
|
||||
|
||||
_channel.BufferManager.SetGraphicsStorageBuffer(stage, sb.Slot, sbDescriptor.PackAddress(), size, sb.Flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -759,7 +771,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
/// </summary>
|
||||
private void UpdateDepthMode()
|
||||
{
|
||||
_context.Renderer.Pipeline.SetDepthMode(GetDepthMode());
|
||||
DepthMode mode = GetDepthMode();
|
||||
|
||||
_pipeline.DepthMode = mode;
|
||||
|
||||
_context.Renderer.Pipeline.SetDepthMode(mode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -1351,6 +1367,22 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
_vsUsesDrawParameters = gs.Shaders[1]?.Info.UsesDrawParameters ?? false;
|
||||
_vsClipDistancesWritten = gs.Shaders[1]?.Info.ClipDistancesWritten ?? 0;
|
||||
|
||||
bool hasTransformFeedback = gs.SpecializationState.TransformFeedbackDescriptors != null;
|
||||
if (hasTransformFeedback != _channel.BufferManager.HasTransformFeedbackOutputs)
|
||||
{
|
||||
if (!_context.Capabilities.SupportsTransformFeedback)
|
||||
{
|
||||
// If host does not support transform feedback, and the shader changed,
|
||||
// we might need to update bindings as transform feedback emulation
|
||||
// uses storage buffer bindings that might have been used for something
|
||||
// else in a previous draw.
|
||||
|
||||
_channel.BufferManager.ForceTransformFeedbackAndStorageBuffersDirty();
|
||||
}
|
||||
|
||||
_channel.BufferManager.HasTransformFeedbackOutputs = hasTransformFeedback;
|
||||
}
|
||||
|
||||
if (oldVsClipDistancesWritten != _vsClipDistancesWritten)
|
||||
{
|
||||
UpdateUserClipState();
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user