mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2025-09-11 12:25:16 +00:00
Compare commits
219 Commits
Canary-1.2
...
Canary-1.2
Author | SHA1 | Date | |
---|---|---|---|
|
4d7ca5c0f0 | ||
|
a375faecc1 | ||
|
1728b0f20c | ||
|
5aa071c59b | ||
|
1018c9db8b | ||
|
01ccd18726 | ||
|
abfbc6f4bc | ||
|
6a4bc02d7a | ||
|
814c0526d2 | ||
|
a5a4ef38e6 | ||
|
c17e3bfcdf | ||
|
017f46f318 | ||
|
fd4d801bfd | ||
|
f1dee50275 | ||
|
c2ae49eb47 | ||
|
47c71966d0 | ||
|
f9e8f4bc29 | ||
|
7694c8c046 | ||
|
0dd789e8a5 | ||
|
4e0aafd005 | ||
|
c5091f499e | ||
|
41c8fd8194 | ||
|
d4a7ee25ea | ||
|
3141c560fb | ||
|
de341b285b | ||
|
cc95e80ee9 | ||
|
d75ce52bd4 | ||
|
4a4ea557de | ||
|
33f42adb11 | ||
|
918ec1bde3 | ||
|
cca429d46a | ||
|
845c86f545 | ||
|
27993b789f | ||
|
bdd890cf6f | ||
|
c5574b41a1 | ||
|
292e27f0da | ||
|
606e149bd3 | ||
|
a8c3407d11 | ||
|
daa8168985 | ||
|
f580521e99 | ||
|
2226521f6c | ||
|
384416953d | ||
|
1343fabe41 | ||
|
1e52af5e29 | ||
|
672f5df0f9 | ||
|
804d9c1efe | ||
|
9270b35648 | ||
|
5a6d01db3c | ||
|
ef9c1416ec | ||
|
5efa7d5dfa | ||
|
a82569d615 | ||
|
ed5832ca73 | ||
|
574aa9ff9c | ||
|
8a29428de2 | ||
|
f4272b05fa | ||
|
d8265f7772 | ||
|
259526430c | ||
|
b5fafb6394 | ||
|
323c356d9c | ||
|
30b22ce6ba | ||
|
9acecc9eb2 | ||
|
4193a37a91 | ||
|
c4cc657b89 | ||
|
9726b0feb0 | ||
|
159ff828a1 | ||
|
6fa2bfc736 | ||
|
2c24df0247 | ||
|
13efc3e544 | ||
|
845dd9a8db | ||
|
b661bdd997 | ||
|
cc84041270 | ||
|
987ab9be41 | ||
|
8a2bc3957a | ||
|
850df38f1e | ||
|
c8d598d5ac | ||
|
3e5b2bda38 | ||
|
9bb50fc6dd | ||
|
e956864697 | ||
|
f43442f774 | ||
|
88d11d3d8d | ||
|
391f57bdd2 | ||
|
fd2b5a7fc1 | ||
|
37c165e9fc | ||
|
003a6d322b | ||
|
978d2c132b | ||
|
5d63706cea | ||
|
732aafd3bb | ||
|
3fa714bb72 | ||
|
7c01633f13 | ||
|
27c5cba10b | ||
|
3525d5ecd4 | ||
|
6286501550 | ||
|
61ae427a4d | ||
|
19d2883a35 | ||
|
617c03119f | ||
|
e43d899e1d | ||
|
0cd09ea0c5 | ||
|
4135d74e4d | ||
|
bd29f658b1 | ||
|
df150f0788 | ||
|
e50198b37d | ||
|
f426945fec | ||
|
172869bfba | ||
|
b6f88514f9 | ||
|
e92f52e56c | ||
|
318498eab0 | ||
|
a5cde8e006 | ||
|
d0a344d632 | ||
|
ca66298817 | ||
|
9ae1c4380d | ||
|
c88518bce2 | ||
|
a3888ed7cf | ||
|
7cbbd02973 | ||
|
b2e1e553e4 | ||
|
699e1962b1 | ||
|
e486b902b1 | ||
|
0ab5b41c4b | ||
|
d10a478cce | ||
|
ec1020b165 | ||
|
4082ebad1a | ||
|
da8ea06074 | ||
|
7f9dccb293 | ||
|
8e4a77aba0 | ||
|
8fd8a776c9 | ||
|
eec92c242c | ||
|
42a739d34c | ||
|
f362bef43d | ||
|
f5ce539de9 | ||
|
4f699afe7a | ||
|
6caab1aa37 | ||
|
9baaa2b8f8 | ||
|
7f376b4f45 | ||
|
32cdccde12 | ||
|
cbd851d00e | ||
|
f463ea1c5d | ||
|
1dd69912b1 | ||
|
1fbb0d8e7d | ||
|
9ee3f1ff36 | ||
|
d052d74ac4 | ||
|
df91c4c57a | ||
|
2aaaa7872f | ||
|
b5999583d6 | ||
|
8b3a945b5f | ||
|
09107b67ff | ||
|
12b264af44 | ||
|
0c21b07f19 | ||
|
18625cf775 | ||
|
77a9246825 | ||
|
709eeda94a | ||
|
7d54424048 | ||
|
664c63c6a8 | ||
|
153d1ef06b | ||
|
e1e4e5d2d5 | ||
|
44ee4190e6 | ||
|
9408452f93 | ||
|
38833ff60a | ||
|
1faa72f22f | ||
|
56e45ae648 | ||
|
07074272ca | ||
|
9eb273a0f7 | ||
|
ccddaa77d1 | ||
|
01c2e67334 | ||
|
4c646721d6 | ||
|
d3bc3a1081 | ||
|
c69881a0a2 | ||
|
1bc0159139 | ||
|
0733b7d0a1 | ||
|
9df1366fa1 | ||
|
c73b5bdf46 | ||
|
9754d247b5 | ||
|
267e9f6350 | ||
|
d7b3dd12d1 | ||
|
c9b2a6b1f1 | ||
|
17233d30da | ||
|
2bf48f57d2 | ||
|
412d4065b8 | ||
|
e6644626fc | ||
|
0bacdb8765 | ||
|
0ca4d6e921 | ||
|
f0aa7eedf6 | ||
|
41acc4b1f3 | ||
|
7aede70ba9 | ||
|
a0a4f78cff | ||
|
16a60fdf12 | ||
|
4d7350fc6e | ||
|
b05eab21a2 | ||
|
ff667a5c84 | ||
|
2f540dc88c | ||
|
3cb996bf5c | ||
|
852823104f | ||
|
3094df54dd | ||
|
278fe9d4f0 | ||
|
a560d2efdb | ||
|
a270dc721c | ||
|
23b0b22400 | ||
|
3dfbf55611 | ||
|
cb355f504d | ||
|
b5483d8fe0 | ||
|
8259f790d7 | ||
|
1ea345faa7 | ||
|
5913ceda40 | ||
|
decd37ce6d | ||
|
67ec10feea | ||
|
4c7cb54ec6 | ||
|
f898a5ecf4 | ||
|
2fac0f4db1 | ||
|
0f18df982f | ||
|
d9fe0da345 | ||
|
1f0fa525a3 | ||
|
e15a207656 | ||
|
77ef82d92a | ||
|
ba199f4325 | ||
|
4171913baf | ||
|
5b36a9cf9f | ||
|
a460eda195 | ||
|
c77c1acd08 | ||
|
d68295e57d | ||
|
bb3d95722e | ||
|
2fa3a7bfa1 |
2
.github/labeler.yml
vendored
2
.github/labeler.yml
vendored
@@ -32,7 +32,7 @@ kernel:
|
|||||||
|
|
||||||
infra:
|
infra:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-any-file: ['.github/**', 'distribution/**', 'Directory.Packages.props']
|
- any-glob-to-any-file: ['.github/**', 'distribution/**', 'Directory.Packages.props', 'src/Ryujinx.BuildValidationTasks/**']
|
||||||
|
|
||||||
documentation:
|
documentation:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
|
27
.github/workflows/build.yml
vendored
27
.github/workflows/build.yml
vendored
@@ -64,14 +64,9 @@ jobs:
|
|||||||
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.platform.name }}" -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
|
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.platform.name }}" -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
|
||||||
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
|
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
|
||||||
|
|
||||||
- name: Publish Ryujinx.Headless.SDL2
|
|
||||||
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.platform.name }}" -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
|
|
||||||
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
|
|
||||||
|
|
||||||
- name: Set executable bit
|
- name: Set executable bit
|
||||||
run: |
|
run: |
|
||||||
chmod +x ./publish/Ryujinx ./publish/Ryujinx.sh
|
chmod +x ./publish/Ryujinx ./publish/Ryujinx.sh
|
||||||
chmod +x ./publish_sdl2_headless/Ryujinx.Headless.SDL2 ./publish_sdl2_headless/Ryujinx.sh
|
|
||||||
if: github.event_name == 'pull_request' && matrix.platform.os == 'ubuntu-latest'
|
if: github.event_name == 'pull_request' && matrix.platform.os == 'ubuntu-latest'
|
||||||
|
|
||||||
- name: Build AppImage
|
- name: Build AppImage
|
||||||
@@ -119,13 +114,6 @@ jobs:
|
|||||||
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.platform.zip_os_name }}-AppImage
|
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.platform.zip_os_name }}-AppImage
|
||||||
path: publish_appimage
|
path: publish_appimage
|
||||||
|
|
||||||
- name: Upload Ryujinx.Headless.SDL2 artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: nogui-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.platform.zip_os_name }}
|
|
||||||
path: publish_sdl2_headless
|
|
||||||
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
|
|
||||||
|
|
||||||
build_macos:
|
build_macos:
|
||||||
name: macOS Universal (${{ matrix.configuration }})
|
name: macOS Universal (${{ matrix.configuration }})
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -141,11 +129,11 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
global-json-file: global.json
|
global-json-file: global.json
|
||||||
|
|
||||||
- name: Setup LLVM 14
|
- name: Setup LLVM 17
|
||||||
run: |
|
run: |
|
||||||
wget https://apt.llvm.org/llvm.sh
|
wget https://apt.llvm.org/llvm.sh
|
||||||
chmod +x llvm.sh
|
chmod +x llvm.sh
|
||||||
sudo ./llvm.sh 14
|
sudo ./llvm.sh 17
|
||||||
|
|
||||||
- name: Install rcodesign
|
- name: Install rcodesign
|
||||||
run: |
|
run: |
|
||||||
@@ -171,20 +159,9 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
./distribution/macos/create_macos_build_ava.sh . publish_tmp publish ./distribution/macos/entitlements.xml "${{ env.RYUJINX_BASE_VERSION }}" "${{ steps.git_short_hash.outputs.result }}" "${{ matrix.configuration }}" "-p:ExtraDefineConstants=DISABLE_UPDATER"
|
./distribution/macos/create_macos_build_ava.sh . publish_tmp publish ./distribution/macos/entitlements.xml "${{ env.RYUJINX_BASE_VERSION }}" "${{ steps.git_short_hash.outputs.result }}" "${{ matrix.configuration }}" "-p:ExtraDefineConstants=DISABLE_UPDATER"
|
||||||
|
|
||||||
- name: Publish macOS Ryujinx.Headless.SDL2
|
|
||||||
run: |
|
|
||||||
./distribution/macos/create_macos_build_headless.sh . publish_tmp_headless publish_headless ./distribution/macos/entitlements.xml "${{ env.RYUJINX_BASE_VERSION }}" "${{ steps.git_short_hash.outputs.result }}" "${{ matrix.configuration }}" "-p:ExtraDefineConstants=DISABLE_UPDATER"
|
|
||||||
|
|
||||||
- name: Upload Ryujinx artifact
|
- name: Upload Ryujinx artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
|
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
|
||||||
path: "publish/*.tar.gz"
|
path: "publish/*.tar.gz"
|
||||||
if: github.event_name == 'pull_request'
|
if: github.event_name == 'pull_request'
|
||||||
|
|
||||||
- name: Upload Ryujinx.Headless.SDL2 artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: nogui-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
|
|
||||||
path: "publish_headless/*.tar.gz"
|
|
||||||
if: github.event_name == 'pull_request'
|
|
||||||
|
143
.github/workflows/canary.yml
vendored
143
.github/workflows/canary.yml
vendored
@@ -21,9 +21,9 @@ env:
|
|||||||
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||||
RYUJINX_BASE_VERSION: "1.2"
|
RYUJINX_BASE_VERSION: "1.2"
|
||||||
RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "canary"
|
RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "canary"
|
||||||
RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "GreemDev"
|
RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "Ryubing"
|
||||||
RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO: "Ryujinx"
|
RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO: "Ryujinx"
|
||||||
RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Ryujinx-Canary"
|
RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Canary-Releases"
|
||||||
RELEASE: 1
|
RELEASE: 1
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -43,8 +43,8 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
github.rest.git.createRef({
|
github.rest.git.createRef({
|
||||||
owner: context.repo.owner,
|
owner: "${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}",
|
||||||
repo: context.repo.repo,
|
repo: "${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}",
|
||||||
ref: 'refs/tags/Canary-${{ steps.version_info.outputs.build_version }}',
|
ref: 'refs/tags/Canary-${{ steps.version_info.outputs.build_version }}',
|
||||||
sha: context.sha
|
sha: context.sha
|
||||||
})
|
})
|
||||||
@@ -61,10 +61,10 @@ jobs:
|
|||||||
|
|
||||||
| Platform | Artifact |
|
| Platform | Artifact |
|
||||||
|--|--|
|
|--|--|
|
||||||
| Windows 64 bit | [Canary Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip) |
|
| Windows 64-bit | [Canary Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip) |
|
||||||
| Linux 64 bit | [Canary Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) |
|
| Linux 64-bit | [Canary Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) |
|
||||||
| Linux arm 64 bit | [Canary Linux arm Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) |
|
| Linux ARM 64-bit | [Canary Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) |
|
||||||
| macOS | [Canary macOS artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) |
|
| macOS | [Canary macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) |
|
||||||
|
|
||||||
**Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }}
|
**Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }}
|
||||||
omitBodyDuringUpdate: true
|
omitBodyDuringUpdate: true
|
||||||
@@ -108,6 +108,7 @@ jobs:
|
|||||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||||
sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||||
|
sed -r --in-place '/^Name=Ryujinx$/s/Name=Ryujinx/Name=Ryujinx-Canary/' distribution/linux/Ryujinx.desktop
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
- name: Create output dir
|
- name: Create output dir
|
||||||
@@ -115,97 +116,83 @@ jobs:
|
|||||||
|
|
||||||
- name: Publish
|
- name: Publish
|
||||||
run: |
|
run: |
|
||||||
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish_ava/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx --self-contained
|
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx --self-contained
|
||||||
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish_sdl2_headless/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx.Headless.SDL2 --self-contained
|
|
||||||
|
|
||||||
- name: Packing Windows builds
|
- name: Packing Windows builds
|
||||||
if: matrix.platform.os == 'windows-latest'
|
if: matrix.platform.os == 'windows-latest'
|
||||||
run: |
|
run: |
|
||||||
pushd publish_ava
|
pushd publish
|
||||||
rm publish/libarmeilleure-jitsupport.dylib
|
rm libarmeilleure-jitsupport.dylib
|
||||||
7z a ../release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip publish
|
7z a ../release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish
|
||||||
popd
|
|
||||||
|
|
||||||
pushd publish_sdl2_headless
|
|
||||||
rm publish/libarmeilleure-jitsupport.dylib
|
|
||||||
7z a ../release_output/nogui-ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip publish
|
|
||||||
popd
|
popd
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
- name: Packing Linux builds
|
- name: Packing Linux builds
|
||||||
if: matrix.platform.os == 'ubuntu-latest'
|
if: matrix.platform.os == 'ubuntu-latest'
|
||||||
run: |
|
run: |
|
||||||
pushd publish_ava
|
pushd publish
|
||||||
rm publish/libarmeilleure-jitsupport.dylib
|
rm libarmeilleure-jitsupport.dylib
|
||||||
chmod +x publish/Ryujinx.sh publish/Ryujinx
|
chmod +x Ryujinx.sh Ryujinx
|
||||||
tar -czvf ../release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz publish
|
tar -czvf ../release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish
|
||||||
popd
|
|
||||||
|
|
||||||
pushd publish_sdl2_headless
|
|
||||||
rm publish/libarmeilleure-jitsupport.dylib
|
|
||||||
chmod +x publish/Ryujinx.sh publish/Ryujinx.Headless.SDL2
|
|
||||||
tar -czvf ../release_output/nogui-ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz publish
|
|
||||||
popd
|
popd
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
#- name: Build AppImage (Linux)
|
- name: Build AppImage (Linux)
|
||||||
# if: matrix.platform.os == 'ubuntu-latest'
|
if: matrix.platform.os == 'ubuntu-latest'
|
||||||
# run: |
|
run: |
|
||||||
# BUILD_VERSION="${{ steps.version_info.outputs.build_version }}"
|
BUILD_VERSION="${{ steps.version_info.outputs.build_version }}"
|
||||||
# PLATFORM_NAME="${{ matrix.platform.name }}"
|
PLATFORM_NAME="${{ matrix.platform.name }}"
|
||||||
|
|
||||||
# sudo apt install -y zsync desktop-file-utils appstream
|
sudo apt install -y zsync desktop-file-utils appstream
|
||||||
|
|
||||||
# mkdir -p tools
|
mkdir -p tools
|
||||||
# export PATH="$PATH:$(readlink -f tools)"
|
export PATH="$PATH:$(readlink -f tools)"
|
||||||
|
|
||||||
# Setup appimagetool
|
# Setup appimagetool
|
||||||
# wget -q -O tools/appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
|
wget -q -O tools/appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
|
||||||
# chmod +x tools/appimagetool
|
chmod +x tools/appimagetool
|
||||||
# chmod +x distribution/linux/appimage/build-appimage.sh
|
chmod +x distribution/linux/appimage/build-appimage.sh
|
||||||
|
|
||||||
# Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name)
|
# Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name)
|
||||||
# if [ "$PLATFORM_NAME" = "linux-x64" ]; then
|
if [ "$PLATFORM_NAME" = "linux-x64" ]; then
|
||||||
# ARCH_NAME=x64
|
ARCH_NAME=x64
|
||||||
# export ARCH=x86_64
|
export ARCH=x86_64
|
||||||
# elif [ "$PLATFORM_NAME" = "linux-arm64" ]; then
|
elif [ "$PLATFORM_NAME" = "linux-arm64" ]; then
|
||||||
# ARCH_NAME=arm64
|
ARCH_NAME=arm64
|
||||||
# export ARCH=aarch64
|
export ARCH=aarch64
|
||||||
# else
|
else
|
||||||
# echo "Unexpected PLATFORM_NAME "$PLATFORM_NAME""
|
echo "Unexpected PLATFORM_NAME "$PLATFORM_NAME""
|
||||||
# exit 1
|
exit 1
|
||||||
# fi
|
fi
|
||||||
|
|
||||||
# export UFLAG="gh-releases-zsync|${{ github.repository_owner }}|${{ github.event.repository.name }}|latest|*-$ARCH_NAME.AppImage.zsync"
|
export UFLAG="gh-releases-zsync|${{ github.repository_owner }}|Canary-Releases|latest|*-$ARCH_NAME.AppImage.zsync"
|
||||||
# BUILDDIR=publish_ava OUTDIR=publish_ava_appimage distribution/linux/appimage/build-appimage.sh
|
BUILDDIR=publish OUTDIR=publish_appimage distribution/linux/appimage/build-appimage.sh
|
||||||
|
|
||||||
# Add to release output
|
pushd publish_appimage
|
||||||
# pushd publish_ava_appimage
|
mv Ryujinx.AppImage ../release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage
|
||||||
# mv Ryujinx.AppImage ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage
|
mv Ryujinx.AppImage.zsync ../release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync
|
||||||
# mv Ryujinx.AppImage.zsync ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync
|
popd
|
||||||
# popd
|
shell: bash
|
||||||
# shell: bash
|
|
||||||
|
|
||||||
- name: Pushing new release
|
- name: Pushing new release
|
||||||
uses: ncipollo/release-action@v1
|
uses: ncipollo/release-action@v1
|
||||||
with:
|
with:
|
||||||
name: ${{ steps.version_info.outputs.build_version }}
|
name: ${{ steps.version_info.outputs.build_version }}
|
||||||
artifacts: "release_output/*.tar.gz,release_output/*.zip"
|
artifacts: "release_output/*.tar.gz,release_output/*.zip,release_output/*AppImage*"
|
||||||
#artifacts: "release_output/*.tar.gz,release_output/*.zip/*AppImage*"
|
|
||||||
tag: ${{ steps.version_info.outputs.build_version }}
|
tag: ${{ steps.version_info.outputs.build_version }}
|
||||||
body: |
|
body: |
|
||||||
# Canary builds:
|
# Canary builds:
|
||||||
|
|
||||||
These builds are experimental and may sometimes not work, use [regular builds](https://github.com/GreemDev/Ryujinx/releases/latest) instead if that sounds like something you don't want to deal with.
|
These builds are experimental and may sometimes not work, use [regular builds](https://github.com/${{ github.repository }}/releases/latest) instead if that sounds like something you don't want to deal with.
|
||||||
|
|
||||||
| Platform | Artifact |
|
| Platform | Artifact |
|
||||||
|--|--|
|
|--|--|
|
||||||
| Windows 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip |
|
| Windows 64-bit | [Canary Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip) |
|
||||||
| Linux 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz |
|
| Linux 64-bit | [Canary Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) |
|
||||||
| Linux arm 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz |
|
| Linux ARM 64-bit | [Canary Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) |
|
||||||
| Macos | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz |
|
| macOS | [Canary macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) |
|
||||||
|
|
||||||
"**Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }}"
|
**Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }}
|
||||||
omitBodyDuringUpdate: true
|
omitBodyDuringUpdate: true
|
||||||
allowUpdates: true
|
allowUpdates: true
|
||||||
replacesArtifacts: true
|
replacesArtifacts: true
|
||||||
@@ -223,11 +210,11 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
global-json-file: global.json
|
global-json-file: global.json
|
||||||
|
|
||||||
- name: Setup LLVM 15
|
- name: Setup LLVM 17
|
||||||
run: |
|
run: |
|
||||||
wget https://apt.llvm.org/llvm.sh
|
wget https://apt.llvm.org/llvm.sh
|
||||||
chmod +x llvm.sh
|
chmod +x llvm.sh
|
||||||
sudo ./llvm.sh 15
|
sudo ./llvm.sh 17
|
||||||
|
|
||||||
- name: Install rcodesign
|
- name: Install rcodesign
|
||||||
run: |
|
run: |
|
||||||
@@ -262,29 +249,13 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish_ava ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 1
|
./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish_ava ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 1
|
||||||
|
|
||||||
- name: Publish macOS Ryujinx.Headless.SDL2
|
|
||||||
run: |
|
|
||||||
./distribution/macos/create_macos_build_headless.sh . publish_tmp_headless publish_headless ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 1
|
|
||||||
|
|
||||||
- name: Pushing new release
|
- name: Pushing new release
|
||||||
uses: ncipollo/release-action@v1
|
uses: ncipollo/release-action@v1
|
||||||
with:
|
with:
|
||||||
name: "Canary ${{ steps.version_info.outputs.build_version }}"
|
name: "Canary ${{ steps.version_info.outputs.build_version }}"
|
||||||
artifacts: "publish_ava/*.tar.gz, publish_headless/*.tar.gz"
|
artifacts: "publish_ava/*.tar.gz"
|
||||||
tag: ${{ steps.version_info.outputs.build_version }}
|
tag: ${{ steps.version_info.outputs.build_version }}
|
||||||
body: |
|
body: ""
|
||||||
# Canary builds:
|
|
||||||
|
|
||||||
These builds are experimental and may sometimes not work, use [regular builds](https://github.com/GreemDev/Ryujinx/releases/latest) instead if that sounds like something you don't want to deal with.
|
|
||||||
|
|
||||||
| Platform | Artifact |
|
|
||||||
|--|--|
|
|
||||||
| Windows 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip |
|
|
||||||
| Linux 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz |
|
|
||||||
| Linux arm 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz |
|
|
||||||
| Macos | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz |
|
|
||||||
|
|
||||||
"**Full Changelog**: https://github.com/${{ github.repository }}/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }}"
|
|
||||||
omitBodyDuringUpdate: true
|
omitBodyDuringUpdate: true
|
||||||
allowUpdates: true
|
allowUpdates: true
|
||||||
replacesArtifacts: true
|
replacesArtifacts: true
|
||||||
|
12
.github/workflows/nightly_pr_comment.yml
vendored
12
.github/workflows/nightly_pr_comment.yml
vendored
@@ -38,20 +38,16 @@ jobs:
|
|||||||
return core.error(`No artifacts found`);
|
return core.error(`No artifacts found`);
|
||||||
}
|
}
|
||||||
let body = `Download the artifacts for this pull request:\n`;
|
let body = `Download the artifacts for this pull request:\n`;
|
||||||
let hidden_headless_artifacts = `\n\n <details><summary>GUI-less</summary>\n`;
|
|
||||||
let hidden_debug_artifacts = `\n\n <details><summary>Only for Developers</summary>\n`;
|
let hidden_debug_artifacts = `\n\n <details><summary>Only for Developers</summary>\n`;
|
||||||
for (const art of artifacts) {
|
for (const art of artifacts) {
|
||||||
if(art.name.includes('Debug')) {
|
const url = `https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip`;
|
||||||
hidden_debug_artifacts += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`;
|
if (art.name.includes('Debug')) {
|
||||||
} else if(art.name.includes('nogui-ryujinx')) {
|
hidden_debug_artifacts += `\n* [${art.name}](${url})`;
|
||||||
hidden_headless_artifacts += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`;
|
|
||||||
} else {
|
} else {
|
||||||
body += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`;
|
body += `\n* [${art.name}](${url})`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hidden_headless_artifacts += `\n</details>`;
|
|
||||||
hidden_debug_artifacts += `\n</details>`;
|
hidden_debug_artifacts += `\n</details>`;
|
||||||
body += hidden_headless_artifacts;
|
|
||||||
body += hidden_debug_artifacts;
|
body += hidden_debug_artifacts;
|
||||||
|
|
||||||
const {data: comments} = await github.rest.issues.listComments({repo, owner, issue_number});
|
const {data: comments} = await github.rest.issues.listComments({repo, owner, issue_number});
|
||||||
|
86
.github/workflows/release.yml
vendored
86
.github/workflows/release.yml
vendored
@@ -3,16 +3,6 @@ name: Release job
|
|||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs: {}
|
inputs: {}
|
||||||
push:
|
|
||||||
branches: [ release ]
|
|
||||||
paths-ignore:
|
|
||||||
- '.github/**'
|
|
||||||
- 'docs/**'
|
|
||||||
- 'assets/**'
|
|
||||||
- '*.yml'
|
|
||||||
- '*.json'
|
|
||||||
- '*.config'
|
|
||||||
- '*.md'
|
|
||||||
|
|
||||||
concurrency: release
|
concurrency: release
|
||||||
|
|
||||||
@@ -21,7 +11,7 @@ env:
|
|||||||
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||||
RYUJINX_BASE_VERSION: "1.2"
|
RYUJINX_BASE_VERSION: "1.2"
|
||||||
RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "release"
|
RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "release"
|
||||||
RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "GreemDev"
|
RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "Ryubing"
|
||||||
RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Ryujinx"
|
RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Ryujinx"
|
||||||
RELEASE: 1
|
RELEASE: 1
|
||||||
|
|
||||||
@@ -42,8 +32,8 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
github.rest.git.createRef({
|
github.rest.git.createRef({
|
||||||
owner: context.repo.owner,
|
owner: "${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}",
|
||||||
repo: context.repo.repo,
|
repo: "${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}",
|
||||||
ref: 'refs/tags/${{ steps.version_info.outputs.build_version }}',
|
ref: 'refs/tags/${{ steps.version_info.outputs.build_version }}',
|
||||||
sha: context.sha
|
sha: context.sha
|
||||||
})
|
})
|
||||||
@@ -54,13 +44,13 @@ jobs:
|
|||||||
name: ${{ steps.version_info.outputs.build_version }}
|
name: ${{ steps.version_info.outputs.build_version }}
|
||||||
tag: ${{ steps.version_info.outputs.build_version }}
|
tag: ${{ steps.version_info.outputs.build_version }}
|
||||||
body: |
|
body: |
|
||||||
# Regular builds:
|
# Stable builds:
|
||||||
| Platform | Artifact |
|
| Platform | Artifact |
|
||||||
|--|--|
|
|--|--|
|
||||||
| Windows 64 bit | [Release Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip) |
|
| Windows 64-bit | [Stable Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip) |
|
||||||
| Linux 64 bit | [Release Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) |
|
| Linux 64-bit | [Stable Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) |
|
||||||
| Linux arm 64 bit | [Release Linux arm Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) |
|
| Linux ARM 64-bit | [Stable Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) |
|
||||||
| macOS | [Release macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) |
|
| macOS | [Stable macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) |
|
||||||
|
|
||||||
**Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}
|
**Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}
|
||||||
omitBodyDuringUpdate: true
|
omitBodyDuringUpdate: true
|
||||||
@@ -112,7 +102,6 @@ jobs:
|
|||||||
- name: Publish
|
- name: Publish
|
||||||
run: |
|
run: |
|
||||||
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx --self-contained
|
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx --self-contained
|
||||||
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish_sdl2_headless -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx.Headless.SDL2 --self-contained
|
|
||||||
|
|
||||||
- name: Packing Windows builds
|
- name: Packing Windows builds
|
||||||
if: matrix.platform.os == 'windows-latest'
|
if: matrix.platform.os == 'windows-latest'
|
||||||
@@ -121,10 +110,14 @@ jobs:
|
|||||||
rm libarmeilleure-jitsupport.dylib
|
rm libarmeilleure-jitsupport.dylib
|
||||||
7z a ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish
|
7z a ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish
|
||||||
popd
|
popd
|
||||||
|
shell: bash
|
||||||
|
|
||||||
pushd publish_sdl2_headless
|
- name: Packing Linux builds
|
||||||
rm libarmeilleure-jitsupport.dylib
|
if: matrix.platform.os == 'ubuntu-latest'
|
||||||
7z a ../release_output/nogui-ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish
|
run: |
|
||||||
|
pushd publish
|
||||||
|
chmod +x Ryujinx.sh Ryujinx
|
||||||
|
tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish
|
||||||
popd
|
popd
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
@@ -163,20 +156,6 @@ jobs:
|
|||||||
mv Ryujinx.AppImage ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage
|
mv Ryujinx.AppImage ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage
|
||||||
mv Ryujinx.AppImage.zsync ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync
|
mv Ryujinx.AppImage.zsync ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync
|
||||||
popd
|
popd
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Packing Linux builds
|
|
||||||
if: matrix.platform.os == 'ubuntu-latest'
|
|
||||||
run: |
|
|
||||||
pushd publish
|
|
||||||
chmod +x Ryujinx.sh Ryujinx
|
|
||||||
tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish
|
|
||||||
popd
|
|
||||||
|
|
||||||
pushd publish_sdl2_headless
|
|
||||||
chmod +x Ryujinx.sh Ryujinx.Headless.SDL2
|
|
||||||
tar -czvf ../release_output/nogui-ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish
|
|
||||||
popd
|
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
- name: Pushing new release
|
- name: Pushing new release
|
||||||
@@ -186,15 +165,15 @@ jobs:
|
|||||||
artifacts: "release_output/*.tar.gz,release_output/*.zip,release_output/*AppImage*"
|
artifacts: "release_output/*.tar.gz,release_output/*.zip,release_output/*AppImage*"
|
||||||
tag: ${{ steps.version_info.outputs.build_version }}
|
tag: ${{ steps.version_info.outputs.build_version }}
|
||||||
body: |
|
body: |
|
||||||
# Regular builds:
|
# Stable builds:
|
||||||
| Platform | Artifact |
|
| Platform | Artifact |
|
||||||
|--|--|
|
|--|--|
|
||||||
| Windows 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip |
|
| Windows 64-bit | [Stable Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip) |
|
||||||
| Linux 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz |
|
| Linux 64-bit | [Stable Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) |
|
||||||
| Linux arm 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz |
|
| Linux ARM 64-bit | [Stable Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) |
|
||||||
| Macos | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz |
|
| macOS | [Stable macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) |
|
||||||
|
|
||||||
"**Full Changelog**: https://github.com/${{ github.repository }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}"
|
**Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}
|
||||||
omitBodyDuringUpdate: true
|
omitBodyDuringUpdate: true
|
||||||
allowUpdates: true
|
allowUpdates: true
|
||||||
replacesArtifacts: true
|
replacesArtifacts: true
|
||||||
@@ -212,11 +191,11 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
global-json-file: global.json
|
global-json-file: global.json
|
||||||
|
|
||||||
- name: Setup LLVM 15
|
- name: Setup LLVM 17
|
||||||
run: |
|
run: |
|
||||||
wget https://apt.llvm.org/llvm.sh
|
wget https://apt.llvm.org/llvm.sh
|
||||||
chmod +x llvm.sh
|
chmod +x llvm.sh
|
||||||
sudo ./llvm.sh 15
|
sudo ./llvm.sh 17
|
||||||
|
|
||||||
- name: Install rcodesign
|
- name: Install rcodesign
|
||||||
run: |
|
run: |
|
||||||
@@ -251,26 +230,13 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 0
|
./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 0
|
||||||
|
|
||||||
- name: Publish macOS Ryujinx.Headless.SDL2
|
|
||||||
run: |
|
|
||||||
./distribution/macos/create_macos_build_headless.sh . publish_tmp_headless publish_headless ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 0
|
|
||||||
|
|
||||||
- name: Pushing new release
|
- name: Pushing new release
|
||||||
uses: ncipollo/release-action@v1
|
uses: ncipollo/release-action@v1
|
||||||
with:
|
with:
|
||||||
name: ${{ steps.version_info.outputs.build_version }}
|
name: ${{ steps.version_info.outputs.build_version }}
|
||||||
artifacts: "publish/*.tar.gz, publish_headless/*.tar.gz"
|
artifacts: "publish/*.tar.gz"
|
||||||
tag: ${{ steps.version_info.outputs.build_version }}
|
tag: ${{ steps.version_info.outputs.build_version }}
|
||||||
body: |
|
body: ""
|
||||||
# Regular builds:
|
|
||||||
| Platform | Artifact |
|
|
||||||
|--|--|
|
|
||||||
| Windows 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip |
|
|
||||||
| Linux 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz |
|
|
||||||
| Linux arm 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz |
|
|
||||||
| Macos | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz |
|
|
||||||
|
|
||||||
"**Full Changelog**: https://github.com/${{ github.repository }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}"
|
|
||||||
omitBodyDuringUpdate: true
|
omitBodyDuringUpdate: true
|
||||||
allowUpdates: true
|
allowUpdates: true
|
||||||
replacesArtifacts: true
|
replacesArtifacts: true
|
||||||
|
@@ -3,13 +3,13 @@
|
|||||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageVersion Include="Avalonia" Version="11.0.10" />
|
<PackageVersion Include="Avalonia" Version="11.0.13" />
|
||||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.0.10" />
|
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.0.13" />
|
||||||
<PackageVersion Include="Avalonia.Desktop" Version="11.0.10" />
|
<PackageVersion Include="Avalonia.Desktop" Version="11.0.13" />
|
||||||
<PackageVersion Include="Avalonia.Diagnostics" Version="11.0.10" />
|
<PackageVersion Include="Avalonia.Diagnostics" Version="11.0.13" />
|
||||||
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.0.10" />
|
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.0.13" />
|
||||||
<PackageVersion Include="Avalonia.Svg" Version="11.0.0.18" />
|
<PackageVersion Include="Avalonia.Svg" Version="11.0.0.19" />
|
||||||
<PackageVersion Include="Avalonia.Svg.Skia" Version="11.0.0.18" />
|
<PackageVersion Include="Avalonia.Svg.Skia" Version="11.0.0.19" />
|
||||||
<PackageVersion Include="Microsoft.Build.Framework" Version="17.11.4" />
|
<PackageVersion Include="Microsoft.Build.Framework" Version="17.11.4" />
|
||||||
<PackageVersion Include="Microsoft.Build.Utilities.Core" Version="17.12.6" />
|
<PackageVersion Include="Microsoft.Build.Utilities.Core" Version="17.12.6" />
|
||||||
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
@@ -17,7 +17,8 @@
|
|||||||
<PackageVersion Include="Projektanker.Icons.Avalonia.FontAwesome" Version="9.4.0"/>
|
<PackageVersion Include="Projektanker.Icons.Avalonia.FontAwesome" Version="9.4.0"/>
|
||||||
<PackageVersion Include="Projektanker.Icons.Avalonia.MaterialDesign" Version="9.4.0"/>
|
<PackageVersion Include="Projektanker.Icons.Avalonia.MaterialDesign" Version="9.4.0"/>
|
||||||
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
||||||
<PackageVersion Include="Concentus" Version="2.2.0" />
|
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0"/>
|
||||||
|
<PackageVersion Include="Concentus" Version="2.2.2" />
|
||||||
<PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" />
|
<PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" />
|
||||||
<PackageVersion Include="DynamicData" Version="9.0.4" />
|
<PackageVersion Include="DynamicData" Version="9.0.4" />
|
||||||
<PackageVersion Include="FluentAvaloniaUI" Version="2.0.5" />
|
<PackageVersion Include="FluentAvaloniaUI" Version="2.0.5" />
|
||||||
@@ -25,7 +26,7 @@
|
|||||||
<PackageVersion Include="LibHac" Version="0.19.0" />
|
<PackageVersion Include="LibHac" Version="0.19.0" />
|
||||||
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
|
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
|
||||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2" />
|
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2" />
|
||||||
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.1.2" />
|
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.3.0" />
|
||||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||||
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.1" />
|
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.1" />
|
||||||
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
|
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
|
||||||
@@ -41,15 +42,17 @@
|
|||||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.3-build14" />
|
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.3-build14" />
|
||||||
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
||||||
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
|
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
|
||||||
<PackageVersion Include="Gommon" Version="2.6.8" />
|
<PackageVersion Include="Gommon" Version="2.7.0.2" />
|
||||||
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
||||||
|
<PackageVersion Include="Sep" Version="0.6.0" />
|
||||||
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
||||||
|
<PackageVersion Include="SharpMetal" Version="1.0.0-preview21" />
|
||||||
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
|
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
|
||||||
<PackageVersion Include="Silk.NET.Vulkan" Version="2.21.0" />
|
<PackageVersion Include="Silk.NET.Vulkan" Version="2.22.0" />
|
||||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.21.0" />
|
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.22.0" />
|
||||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.21.0" />
|
<PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.22.0" />
|
||||||
<PackageVersion Include="SkiaSharp" Version="2.88.7" />
|
<PackageVersion Include="SkiaSharp" Version="2.88.9" />
|
||||||
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.7" />
|
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.9" />
|
||||||
<PackageVersion Include="SPB" Version="0.0.4-build32" />
|
<PackageVersion Include="SPB" Version="0.0.4-build32" />
|
||||||
<PackageVersion Include="System.IO.Hashing" Version="9.0.0" />
|
<PackageVersion Include="System.IO.Hashing" Version="9.0.0" />
|
||||||
<PackageVersion Include="System.Management" Version="9.0.0" />
|
<PackageVersion Include="System.Management" Version="9.0.0" />
|
||||||
|
32
Ryujinx.sln
32
Ryujinx.sln
@@ -57,14 +57,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.SDL2.Common", "src\
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.SDL2", "src\Ryujinx.Audio.Backends.SDL2\Ryujinx.Audio.Backends.SDL2.csproj", "{D99A395A-8569-4DB0-B336-900647890052}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.SDL2", "src\Ryujinx.Audio.Backends.SDL2\Ryujinx.Audio.Backends.SDL2.csproj", "{D99A395A-8569-4DB0-B336-900647890052}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Headless.SDL2", "src\Ryujinx.Headless.SDL2\Ryujinx.Headless.SDL2.csproj", "{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Nvdec.FFmpeg", "src\Ryujinx.Graphics.Nvdec.FFmpeg\Ryujinx.Graphics.Nvdec.FFmpeg.csproj", "{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Nvdec.FFmpeg", "src\Ryujinx.Graphics.Nvdec.FFmpeg\Ryujinx.Graphics.Nvdec.FFmpeg.csproj", "{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx", "src\Ryujinx\Ryujinx.csproj", "{7C1B2721-13DA-4B62-B046-C626605ECCE6}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx", "src\Ryujinx\Ryujinx.csproj", "{7C1B2721-13DA-4B62-B046-C626605ECCE6}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.UI.Common", "src\Ryujinx.UI.Common\Ryujinx.UI.Common.csproj", "{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Generators", "src\Ryujinx.Horizon.Generators\Ryujinx.Horizon.Generators.csproj", "{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Generators", "src\Ryujinx.Horizon.Generators\Ryujinx.Horizon.Generators.csproj", "{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Vulkan", "src\Ryujinx.Graphics.Vulkan\Ryujinx.Graphics.Vulkan.csproj", "{D4D09B08-D580-4D69-B886-C35D2853F6C8}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Vulkan", "src\Ryujinx.Graphics.Vulkan\Ryujinx.Graphics.Vulkan.csproj", "{D4D09B08-D580-4D69-B886-C35D2853F6C8}"
|
||||||
@@ -81,6 +77,15 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Kernel.Gene
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE.Generators", "src\Ryujinx.HLE.Generators\Ryujinx.HLE.Generators.csproj", "{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE.Generators", "src\Ryujinx.HLE.Generators\Ryujinx.HLE.Generators.csproj", "{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.Graphics.Metal", "src\Ryujinx.Graphics.Metal\Ryujinx.Graphics.Metal.csproj", "{C08931FA-1191-417A-864F-3882D93E683B}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E} = {A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.BuildValidationTasks", "src\Ryujinx.BuildValidationTasks\Ryujinx.BuildValidationTasks.csproj", "{4A89A234-4F19-497D-A576-DDE8CDFC5B22}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.Graphics.Metal.SharpMetalExtensions", "src/Ryujinx.Graphics.Metal.SharpMetalExtensions\Ryujinx.Graphics.Metal.SharpMetalExtensions.csproj", "{81EA598C-DBA1-40B0-8DA4-4796B78F2037}"
|
||||||
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36F870C1-3E5F-485F-B426-F0645AF78751}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36F870C1-3E5F-485F-B426-F0645AF78751}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
.editorconfig = .editorconfig
|
.editorconfig = .editorconfig
|
||||||
@@ -90,8 +95,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
|||||||
.github\workflows\release.yml = .github\workflows\release.yml
|
.github\workflows\release.yml = .github\workflows\release.yml
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.BuildValidationTasks", "src\Ryujinx.BuildValidationTasks\Ryujinx.BuildValidationTasks.csproj", "{4A89A234-4F19-497D-A576-DDE8CDFC5B22}"
|
|
||||||
EndProject
|
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -206,10 +209,6 @@ Global
|
|||||||
{D99A395A-8569-4DB0-B336-900647890052}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{D99A395A-8569-4DB0-B336-900647890052}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{D99A395A-8569-4DB0-B336-900647890052}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{D99A395A-8569-4DB0-B336-900647890052}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{D99A395A-8569-4DB0-B336-900647890052}.Release|Any CPU.Build.0 = Release|Any CPU
|
{D99A395A-8569-4DB0-B336-900647890052}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
@@ -218,10 +217,6 @@ Global
|
|||||||
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|Any CPU.Build.0 = Release|Any CPU
|
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
@@ -254,9 +249,16 @@ Global
|
|||||||
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.Build.0 = Release|Any CPU
|
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{C08931FA-1191-417A-864F-3882D93E683B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C08931FA-1191-417A-864F-3882D93E683B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C08931FA-1191-417A-864F-3882D93E683B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C08931FA-1191-417A-864F-3882D93E683B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@@ -6,14 +6,14 @@ cd "$ROOTDIR"
|
|||||||
|
|
||||||
BUILDDIR=${BUILDDIR:-publish}
|
BUILDDIR=${BUILDDIR:-publish}
|
||||||
OUTDIR=${OUTDIR:-publish_appimage}
|
OUTDIR=${OUTDIR:-publish_appimage}
|
||||||
UFLAG=${UFLAG:-"gh-releases-zsync|GreemDev|ryujinx|latest|*-x64.AppImage.zsync"}
|
UFLAG=${UFLAG:-"gh-releases-zsync|Ryubing|ryujinx|latest|*-x64.AppImage.zsync"}
|
||||||
|
|
||||||
rm -rf AppDir
|
rm -rf AppDir
|
||||||
mkdir -p AppDir/usr/bin
|
mkdir -p AppDir/usr/bin
|
||||||
|
|
||||||
cp distribution/linux/Ryujinx.desktop AppDir/Ryujinx.desktop
|
cp distribution/linux/Ryujinx.desktop AppDir/Ryujinx.desktop
|
||||||
cp distribution/linux/appimage/AppRun AppDir/AppRun
|
cp distribution/linux/appimage/AppRun AppDir/AppRun
|
||||||
cp src/Ryujinx.UI.Common/Resources/Logo_Ryujinx.png AppDir/Ryujinx.svg
|
cp distribution/misc/Logo.svg AppDir/Ryujinx.svg
|
||||||
|
|
||||||
|
|
||||||
cp -r "$BUILDDIR"/* AppDir/usr/bin/
|
cp -r "$BUILDDIR"/* AppDir/usr/bin/
|
||||||
|
@@ -19,7 +19,7 @@ if platform.system() == "Darwin":
|
|||||||
else:
|
else:
|
||||||
OTOOL = shutil.which("llvm-otool")
|
OTOOL = shutil.which("llvm-otool")
|
||||||
if OTOOL is None:
|
if OTOOL is None:
|
||||||
for llvm_ver in [15, 14, 13]:
|
for llvm_ver in [17, 16, 15, 14, 13]:
|
||||||
otool_path = shutil.which(f"llvm-otool-{llvm_ver}")
|
otool_path = shutil.which(f"llvm-otool-{llvm_ver}")
|
||||||
if otool_path is not None:
|
if otool_path is not None:
|
||||||
OTOOL = otool_path
|
OTOOL = otool_path
|
||||||
|
@@ -26,7 +26,7 @@ else:
|
|||||||
LIPO = shutil.which("llvm-lipo")
|
LIPO = shutil.which("llvm-lipo")
|
||||||
|
|
||||||
if LIPO is None:
|
if LIPO is None:
|
||||||
for llvm_ver in [15, 14, 13]:
|
for llvm_ver in [17, 16, 15, 14, 13]:
|
||||||
lipo_path = shutil.which(f"llvm-lipo-{llvm_ver}")
|
lipo_path = shutil.which(f"llvm-lipo-{llvm_ver}")
|
||||||
if lipo_path is not None:
|
if lipo_path is not None:
|
||||||
LIPO = lipo_path
|
LIPO = lipo_path
|
||||||
|
@@ -67,11 +67,11 @@ python3 "$BASE_DIR/distribution/macos/construct_universal_dylib.py" "$ARM64_APP_
|
|||||||
|
|
||||||
if ! [ -x "$(command -v lipo)" ];
|
if ! [ -x "$(command -v lipo)" ];
|
||||||
then
|
then
|
||||||
if ! [ -x "$(command -v llvm-lipo-14)" ];
|
if ! [ -x "$(command -v llvm-lipo-17)" ];
|
||||||
then
|
then
|
||||||
LIPO=llvm-lipo
|
LIPO=llvm-lipo
|
||||||
else
|
else
|
||||||
LIPO=llvm-lipo-14
|
LIPO=llvm-lipo-17
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
LIPO=lipo
|
LIPO=lipo
|
||||||
|
@@ -62,11 +62,11 @@ python3 "$BASE_DIR/distribution/macos/construct_universal_dylib.py" "$ARM64_OUTP
|
|||||||
|
|
||||||
if ! [ -x "$(command -v lipo)" ];
|
if ! [ -x "$(command -v lipo)" ];
|
||||||
then
|
then
|
||||||
if ! [ -x "$(command -v llvm-lipo-14)" ];
|
if ! [ -x "$(command -v llvm-lipo-17)" ];
|
||||||
then
|
then
|
||||||
LIPO=llvm-lipo
|
LIPO=llvm-lipo
|
||||||
else
|
else
|
||||||
LIPO=llvm-lipo-14
|
LIPO=llvm-lipo-17
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
LIPO=lipo
|
LIPO=lipo
|
||||||
|
3424
docs/compatibility.csv
Normal file
3424
docs/compatibility.csv
Normal file
File diff suppressed because it is too large
Load Diff
@@ -406,7 +406,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
Operand res = EmitSoftFloatCall(context, nameof(SoftFloat32.FPSub), op1, op2);
|
Operand res = EmitSoftFloatCall(context, nameof(SoftFloat32.FPSub), op1, op2);
|
||||||
|
|
||||||
return EmitUnaryMathCall(context, nameof(Math.Abs), res);
|
return EmitUnaryMathCall(context, nameof(MathHelper.Abs), res);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -451,7 +451,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
Operand res = EmitSoftFloatCall(context, nameof(SoftFloat32.FPSub), op1, op2);
|
Operand res = EmitSoftFloatCall(context, nameof(SoftFloat32.FPSub), op1, op2);
|
||||||
|
|
||||||
return EmitUnaryMathCall(context, nameof(Math.Abs), res);
|
return EmitUnaryMathCall(context, nameof(MathHelper.Abs), res);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -483,7 +483,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
EmitScalarUnaryOpF(context, (op1) =>
|
EmitScalarUnaryOpF(context, (op1) =>
|
||||||
{
|
{
|
||||||
return EmitUnaryMathCall(context, nameof(Math.Abs), op1);
|
return EmitUnaryMathCall(context, nameof(MathHelper.Abs), op1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -522,7 +522,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
EmitVectorUnaryOpF(context, (op1) =>
|
EmitVectorUnaryOpF(context, (op1) =>
|
||||||
{
|
{
|
||||||
return EmitUnaryMathCall(context, nameof(Math.Abs), op1);
|
return EmitUnaryMathCall(context, nameof(MathHelper.Abs), op1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2246,7 +2246,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
EmitScalarUnaryOpF(context, (op1) =>
|
EmitScalarUnaryOpF(context, (op1) =>
|
||||||
{
|
{
|
||||||
return EmitUnaryMathCall(context, nameof(Math.Floor), op1);
|
return EmitUnaryMathCall(context, nameof(MathHelper.Floor), op1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2265,7 +2265,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
EmitVectorUnaryOpF(context, (op1) =>
|
EmitVectorUnaryOpF(context, (op1) =>
|
||||||
{
|
{
|
||||||
return EmitUnaryMathCall(context, nameof(Math.Floor), op1);
|
return EmitUnaryMathCall(context, nameof(MathHelper.Floor), op1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2322,7 +2322,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
EmitScalarUnaryOpF(context, (op1) =>
|
EmitScalarUnaryOpF(context, (op1) =>
|
||||||
{
|
{
|
||||||
return EmitUnaryMathCall(context, nameof(Math.Ceiling), op1);
|
return EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), op1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2341,7 +2341,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
EmitVectorUnaryOpF(context, (op1) =>
|
EmitVectorUnaryOpF(context, (op1) =>
|
||||||
{
|
{
|
||||||
return EmitUnaryMathCall(context, nameof(Math.Ceiling), op1);
|
return EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), op1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2390,7 +2390,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
EmitScalarUnaryOpF(context, (op1) =>
|
EmitScalarUnaryOpF(context, (op1) =>
|
||||||
{
|
{
|
||||||
return EmitUnaryMathCall(context, nameof(Math.Truncate), op1);
|
return EmitUnaryMathCall(context, nameof(MathHelper.Truncate), op1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2409,7 +2409,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
EmitVectorUnaryOpF(context, (op1) =>
|
EmitVectorUnaryOpF(context, (op1) =>
|
||||||
{
|
{
|
||||||
return EmitUnaryMathCall(context, nameof(Math.Truncate), op1);
|
return EmitUnaryMathCall(context, nameof(MathHelper.Truncate), op1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -43,7 +43,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EmitScalarUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Abs), op1));
|
EmitScalarUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Abs), op1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EmitVectorUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Abs), op1));
|
EmitVectorUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Abs), op1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@@ -726,8 +726,8 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
if (absolute)
|
if (absolute)
|
||||||
{
|
{
|
||||||
ne = EmitUnaryMathCall(context, nameof(Math.Abs), ne);
|
ne = EmitUnaryMathCall(context, nameof(MathHelper.Abs), ne);
|
||||||
me = EmitUnaryMathCall(context, nameof(Math.Abs), me);
|
me = EmitUnaryMathCall(context, nameof(MathHelper.Abs), me);
|
||||||
}
|
}
|
||||||
|
|
||||||
Operand e = EmitSoftFloatCall(context, name, ne, me);
|
Operand e = EmitSoftFloatCall(context, name, ne, me);
|
||||||
|
@@ -333,7 +333,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EmitFcvt_s_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Floor), op1));
|
EmitFcvt_s_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Floor), op1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -349,7 +349,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EmitFcvt(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Floor), op1), signed: true, scalar: false);
|
EmitFcvt(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Floor), op1), signed: true, scalar: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,7 +365,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EmitFcvt_u_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Floor), op1));
|
EmitFcvt_u_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Floor), op1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -538,7 +538,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EmitFcvt_s_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Ceiling), op1));
|
EmitFcvt_s_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), op1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -554,7 +554,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EmitFcvt_u_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Ceiling), op1));
|
EmitFcvt_u_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), op1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -357,10 +357,10 @@ namespace ARMeilleure.Instructions
|
|||||||
toConvert = EmitRoundMathCall(context, MidpointRounding.ToEven, toConvert);
|
toConvert = EmitRoundMathCall(context, MidpointRounding.ToEven, toConvert);
|
||||||
break;
|
break;
|
||||||
case 0b10: // Towards positive infinity
|
case 0b10: // Towards positive infinity
|
||||||
toConvert = EmitUnaryMathCall(context, nameof(Math.Ceiling), toConvert);
|
toConvert = EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), toConvert);
|
||||||
break;
|
break;
|
||||||
case 0b11: // Towards negative infinity
|
case 0b11: // Towards negative infinity
|
||||||
toConvert = EmitUnaryMathCall(context, nameof(Math.Floor), toConvert);
|
toConvert = EmitUnaryMathCall(context, nameof(MathHelper.Floor), toConvert);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -494,10 +494,10 @@ namespace ARMeilleure.Instructions
|
|||||||
toConvert = EmitRoundMathCall(context, MidpointRounding.ToEven, toConvert);
|
toConvert = EmitRoundMathCall(context, MidpointRounding.ToEven, toConvert);
|
||||||
break;
|
break;
|
||||||
case 0b10: // Towards positive infinity
|
case 0b10: // Towards positive infinity
|
||||||
toConvert = EmitUnaryMathCall(context, nameof(Math.Ceiling), toConvert);
|
toConvert = EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), toConvert);
|
||||||
break;
|
break;
|
||||||
case 0b11: // Towards negative infinity
|
case 0b11: // Towards negative infinity
|
||||||
toConvert = EmitUnaryMathCall(context, nameof(Math.Floor), toConvert);
|
toConvert = EmitUnaryMathCall(context, nameof(MathHelper.Floor), toConvert);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -534,7 +534,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EmitVectorUnaryOpF32(context, (m) => EmitUnaryMathCall(context, nameof(Math.Floor), m));
|
EmitVectorUnaryOpF32(context, (m) => EmitUnaryMathCall(context, nameof(MathHelper.Floor), m));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -574,7 +574,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EmitVectorUnaryOpF32(context, (m) => EmitUnaryMathCall(context, nameof(Math.Ceiling), m));
|
EmitVectorUnaryOpF32(context, (m) => EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), m));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -613,7 +613,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EmitScalarUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Truncate), op1));
|
EmitScalarUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Truncate), op1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -460,8 +460,8 @@ namespace ARMeilleure.Instructions
|
|||||||
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
|
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
|
||||||
|
|
||||||
MethodInfo info = (op.Size & 1) == 0
|
MethodInfo info = (op.Size & 1) == 0
|
||||||
? typeof(MathF).GetMethod(name, new Type[] { typeof(float) })
|
? typeof(MathHelperF).GetMethod(name, new Type[] { typeof(float) })
|
||||||
: typeof(Math).GetMethod(name, new Type[] { typeof(double) });
|
: typeof(MathHelper).GetMethod(name, new Type[] { typeof(double) });
|
||||||
|
|
||||||
return context.Call(info, n);
|
return context.Call(info, n);
|
||||||
}
|
}
|
||||||
@@ -470,11 +470,11 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
|
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
|
||||||
|
|
||||||
string name = nameof(Math.Round);
|
string name = nameof(MathHelper.Round);
|
||||||
|
|
||||||
MethodInfo info = (op.Size & 1) == 0
|
MethodInfo info = (op.Size & 1) == 0
|
||||||
? typeof(MathF).GetMethod(name, new Type[] { typeof(float), typeof(MidpointRounding) })
|
? typeof(MathHelperF).GetMethod(name, new Type[] { typeof(float), typeof(int) })
|
||||||
: typeof(Math).GetMethod(name, new Type[] { typeof(double), typeof(MidpointRounding) });
|
: typeof(MathHelper).GetMethod(name, new Type[] { typeof(double), typeof(int) });
|
||||||
|
|
||||||
return context.Call(info, n, Const((int)roundMode));
|
return context.Call(info, n, Const((int)roundMode));
|
||||||
}
|
}
|
||||||
@@ -510,16 +510,16 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
context.MarkLabel(lbl1);
|
context.MarkLabel(lbl1);
|
||||||
context.BranchIf(lbl2, rMode, rP, Comparison.NotEqual);
|
context.BranchIf(lbl2, rMode, rP, Comparison.NotEqual);
|
||||||
context.Copy(res, EmitUnaryMathCall(context, nameof(Math.Ceiling), op));
|
context.Copy(res, EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), op));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lbl2);
|
context.MarkLabel(lbl2);
|
||||||
context.BranchIf(lbl3, rMode, rM, Comparison.NotEqual);
|
context.BranchIf(lbl3, rMode, rM, Comparison.NotEqual);
|
||||||
context.Copy(res, EmitUnaryMathCall(context, nameof(Math.Floor), op));
|
context.Copy(res, EmitUnaryMathCall(context, nameof(MathHelper.Floor), op));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lbl3);
|
context.MarkLabel(lbl3);
|
||||||
context.Copy(res, EmitUnaryMathCall(context, nameof(Math.Truncate), op));
|
context.Copy(res, EmitUnaryMathCall(context, nameof(MathHelper.Truncate), op));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lblEnd);
|
context.MarkLabel(lblEnd);
|
||||||
|
71
src/ARMeilleure/Instructions/MathHelper.cs
Normal file
71
src/ARMeilleure/Instructions/MathHelper.cs
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace ARMeilleure.Instructions
|
||||||
|
{
|
||||||
|
static class MathHelper
|
||||||
|
{
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
public static double Abs(double value)
|
||||||
|
{
|
||||||
|
return Math.Abs(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
public static double Ceiling(double value)
|
||||||
|
{
|
||||||
|
return Math.Ceiling(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
public static double Floor(double value)
|
||||||
|
{
|
||||||
|
return Math.Floor(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
public static double Round(double value, int mode)
|
||||||
|
{
|
||||||
|
return Math.Round(value, (MidpointRounding)mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
public static double Truncate(double value)
|
||||||
|
{
|
||||||
|
return Math.Truncate(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class MathHelperF
|
||||||
|
{
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
public static float Abs(float value)
|
||||||
|
{
|
||||||
|
return MathF.Abs(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
public static float Ceiling(float value)
|
||||||
|
{
|
||||||
|
return MathF.Ceiling(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
public static float Floor(float value)
|
||||||
|
{
|
||||||
|
return MathF.Floor(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
public static float Round(float value, int mode)
|
||||||
|
{
|
||||||
|
return MathF.Round(value, (MidpointRounding)mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
public static float Truncate(float value)
|
||||||
|
{
|
||||||
|
return MathF.Truncate(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -2,6 +2,7 @@ using ARMeilleure.Memory;
|
|||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
using ARMeilleure.Translation;
|
using ARMeilleure.Translation;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace ARMeilleure.Instructions
|
namespace ARMeilleure.Instructions
|
||||||
{
|
{
|
||||||
@@ -34,6 +35,7 @@ namespace ARMeilleure.Instructions
|
|||||||
Context = null;
|
Context = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static void Break(ulong address, int imm)
|
public static void Break(ulong address, int imm)
|
||||||
{
|
{
|
||||||
Statistics.PauseTimer();
|
Statistics.PauseTimer();
|
||||||
@@ -43,6 +45,7 @@ namespace ARMeilleure.Instructions
|
|||||||
Statistics.ResumeTimer();
|
Statistics.ResumeTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static void SupervisorCall(ulong address, int imm)
|
public static void SupervisorCall(ulong address, int imm)
|
||||||
{
|
{
|
||||||
Statistics.PauseTimer();
|
Statistics.PauseTimer();
|
||||||
@@ -52,6 +55,7 @@ namespace ARMeilleure.Instructions
|
|||||||
Statistics.ResumeTimer();
|
Statistics.ResumeTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static void Undefined(ulong address, int opCode)
|
public static void Undefined(ulong address, int opCode)
|
||||||
{
|
{
|
||||||
Statistics.PauseTimer();
|
Statistics.PauseTimer();
|
||||||
@@ -62,26 +66,31 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
|
|
||||||
#region "System registers"
|
#region "System registers"
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static ulong GetCtrEl0()
|
public static ulong GetCtrEl0()
|
||||||
{
|
{
|
||||||
return GetContext().CtrEl0;
|
return GetContext().CtrEl0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static ulong GetDczidEl0()
|
public static ulong GetDczidEl0()
|
||||||
{
|
{
|
||||||
return GetContext().DczidEl0;
|
return GetContext().DczidEl0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static ulong GetCntfrqEl0()
|
public static ulong GetCntfrqEl0()
|
||||||
{
|
{
|
||||||
return GetContext().CntfrqEl0;
|
return GetContext().CntfrqEl0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static ulong GetCntpctEl0()
|
public static ulong GetCntpctEl0()
|
||||||
{
|
{
|
||||||
return GetContext().CntpctEl0;
|
return GetContext().CntpctEl0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static ulong GetCntvctEl0()
|
public static ulong GetCntvctEl0()
|
||||||
{
|
{
|
||||||
return GetContext().CntvctEl0;
|
return GetContext().CntvctEl0;
|
||||||
@@ -89,26 +98,31 @@ namespace ARMeilleure.Instructions
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "Read"
|
#region "Read"
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static byte ReadByte(ulong address)
|
public static byte ReadByte(ulong address)
|
||||||
{
|
{
|
||||||
return GetMemoryManager().ReadGuest<byte>(address);
|
return GetMemoryManager().ReadGuest<byte>(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static ushort ReadUInt16(ulong address)
|
public static ushort ReadUInt16(ulong address)
|
||||||
{
|
{
|
||||||
return GetMemoryManager().ReadGuest<ushort>(address);
|
return GetMemoryManager().ReadGuest<ushort>(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static uint ReadUInt32(ulong address)
|
public static uint ReadUInt32(ulong address)
|
||||||
{
|
{
|
||||||
return GetMemoryManager().ReadGuest<uint>(address);
|
return GetMemoryManager().ReadGuest<uint>(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static ulong ReadUInt64(ulong address)
|
public static ulong ReadUInt64(ulong address)
|
||||||
{
|
{
|
||||||
return GetMemoryManager().ReadGuest<ulong>(address);
|
return GetMemoryManager().ReadGuest<ulong>(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static V128 ReadVector128(ulong address)
|
public static V128 ReadVector128(ulong address)
|
||||||
{
|
{
|
||||||
return GetMemoryManager().ReadGuest<V128>(address);
|
return GetMemoryManager().ReadGuest<V128>(address);
|
||||||
@@ -116,47 +130,56 @@ namespace ARMeilleure.Instructions
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "Write"
|
#region "Write"
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static void WriteByte(ulong address, byte value)
|
public static void WriteByte(ulong address, byte value)
|
||||||
{
|
{
|
||||||
GetMemoryManager().WriteGuest(address, value);
|
GetMemoryManager().WriteGuest(address, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static void WriteUInt16(ulong address, ushort value)
|
public static void WriteUInt16(ulong address, ushort value)
|
||||||
{
|
{
|
||||||
GetMemoryManager().WriteGuest(address, value);
|
GetMemoryManager().WriteGuest(address, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static void WriteUInt32(ulong address, uint value)
|
public static void WriteUInt32(ulong address, uint value)
|
||||||
{
|
{
|
||||||
GetMemoryManager().WriteGuest(address, value);
|
GetMemoryManager().WriteGuest(address, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static void WriteUInt64(ulong address, ulong value)
|
public static void WriteUInt64(ulong address, ulong value)
|
||||||
{
|
{
|
||||||
GetMemoryManager().WriteGuest(address, value);
|
GetMemoryManager().WriteGuest(address, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static void WriteVector128(ulong address, V128 value)
|
public static void WriteVector128(ulong address, V128 value)
|
||||||
{
|
{
|
||||||
GetMemoryManager().WriteGuest(address, value);
|
GetMemoryManager().WriteGuest(address, value);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static void EnqueueForRejit(ulong address)
|
public static void EnqueueForRejit(ulong address)
|
||||||
{
|
{
|
||||||
Context.Translator.EnqueueForRejit(address, GetContext().ExecutionMode);
|
Context.Translator.EnqueueForRejit(address, GetContext().ExecutionMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SignalMemoryTracking(ulong address, ulong size, bool write)
|
[UnmanagedCallersOnly]
|
||||||
|
public static void SignalMemoryTracking(ulong address, ulong size, byte write)
|
||||||
{
|
{
|
||||||
GetMemoryManager().SignalMemoryTracking(address, size, write);
|
GetMemoryManager().SignalMemoryTracking(address, size, write == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static void ThrowInvalidMemoryAccess(ulong address)
|
public static void ThrowInvalidMemoryAccess(ulong address)
|
||||||
{
|
{
|
||||||
throw new InvalidAccessException(address);
|
throw new InvalidAccessException(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static ulong GetFunctionAddress(ulong address)
|
public static ulong GetFunctionAddress(ulong address)
|
||||||
{
|
{
|
||||||
TranslatedFunction function = Context.Translator.GetOrTranslate(address, GetContext().ExecutionMode);
|
TranslatedFunction function = Context.Translator.GetOrTranslate(address, GetContext().ExecutionMode);
|
||||||
@@ -164,12 +187,14 @@ namespace ARMeilleure.Instructions
|
|||||||
return (ulong)function.FuncPointer.ToInt64();
|
return (ulong)function.FuncPointer.ToInt64();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static void InvalidateCacheLine(ulong address)
|
public static void InvalidateCacheLine(ulong address)
|
||||||
{
|
{
|
||||||
Context.Translator.InvalidateJitCacheRegion(address, InstEmit.DczSizeInBytes);
|
Context.Translator.InvalidateJitCacheRegion(address, InstEmit.DczSizeInBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool CheckSynchronization()
|
[UnmanagedCallersOnly]
|
||||||
|
public static byte CheckSynchronization()
|
||||||
{
|
{
|
||||||
Statistics.PauseTimer();
|
Statistics.PauseTimer();
|
||||||
|
|
||||||
@@ -179,7 +204,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
Statistics.ResumeTimer();
|
Statistics.ResumeTimer();
|
||||||
|
|
||||||
return context.Running;
|
return (byte)(context.Running ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ExecutionContext GetContext()
|
public static ExecutionContext GetContext()
|
||||||
|
@@ -1,11 +1,13 @@
|
|||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace ARMeilleure.Instructions
|
namespace ARMeilleure.Instructions
|
||||||
{
|
{
|
||||||
static class SoftFallback
|
static class SoftFallback
|
||||||
{
|
{
|
||||||
#region "ShrImm64"
|
#region "ShrImm64"
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static long SignedShrImm64(long value, long roundConst, int shift)
|
public static long SignedShrImm64(long value, long roundConst, int shift)
|
||||||
{
|
{
|
||||||
if (roundConst == 0L)
|
if (roundConst == 0L)
|
||||||
@@ -48,6 +50,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static ulong UnsignedShrImm64(ulong value, long roundConst, int shift)
|
public static ulong UnsignedShrImm64(ulong value, long roundConst, int shift)
|
||||||
{
|
{
|
||||||
if (roundConst == 0L)
|
if (roundConst == 0L)
|
||||||
@@ -92,6 +95,7 @@ namespace ARMeilleure.Instructions
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "Saturation"
|
#region "Saturation"
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static int SatF32ToS32(float value)
|
public static int SatF32ToS32(float value)
|
||||||
{
|
{
|
||||||
if (float.IsNaN(value))
|
if (float.IsNaN(value))
|
||||||
@@ -103,6 +107,7 @@ namespace ARMeilleure.Instructions
|
|||||||
value <= int.MinValue ? int.MinValue : (int)value;
|
value <= int.MinValue ? int.MinValue : (int)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static long SatF32ToS64(float value)
|
public static long SatF32ToS64(float value)
|
||||||
{
|
{
|
||||||
if (float.IsNaN(value))
|
if (float.IsNaN(value))
|
||||||
@@ -114,6 +119,7 @@ namespace ARMeilleure.Instructions
|
|||||||
value <= long.MinValue ? long.MinValue : (long)value;
|
value <= long.MinValue ? long.MinValue : (long)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static uint SatF32ToU32(float value)
|
public static uint SatF32ToU32(float value)
|
||||||
{
|
{
|
||||||
if (float.IsNaN(value))
|
if (float.IsNaN(value))
|
||||||
@@ -125,6 +131,7 @@ namespace ARMeilleure.Instructions
|
|||||||
value <= uint.MinValue ? uint.MinValue : (uint)value;
|
value <= uint.MinValue ? uint.MinValue : (uint)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static ulong SatF32ToU64(float value)
|
public static ulong SatF32ToU64(float value)
|
||||||
{
|
{
|
||||||
if (float.IsNaN(value))
|
if (float.IsNaN(value))
|
||||||
@@ -136,6 +143,7 @@ namespace ARMeilleure.Instructions
|
|||||||
value <= ulong.MinValue ? ulong.MinValue : (ulong)value;
|
value <= ulong.MinValue ? ulong.MinValue : (ulong)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static int SatF64ToS32(double value)
|
public static int SatF64ToS32(double value)
|
||||||
{
|
{
|
||||||
if (double.IsNaN(value))
|
if (double.IsNaN(value))
|
||||||
@@ -147,6 +155,7 @@ namespace ARMeilleure.Instructions
|
|||||||
value <= int.MinValue ? int.MinValue : (int)value;
|
value <= int.MinValue ? int.MinValue : (int)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static long SatF64ToS64(double value)
|
public static long SatF64ToS64(double value)
|
||||||
{
|
{
|
||||||
if (double.IsNaN(value))
|
if (double.IsNaN(value))
|
||||||
@@ -158,6 +167,7 @@ namespace ARMeilleure.Instructions
|
|||||||
value <= long.MinValue ? long.MinValue : (long)value;
|
value <= long.MinValue ? long.MinValue : (long)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static uint SatF64ToU32(double value)
|
public static uint SatF64ToU32(double value)
|
||||||
{
|
{
|
||||||
if (double.IsNaN(value))
|
if (double.IsNaN(value))
|
||||||
@@ -169,6 +179,7 @@ namespace ARMeilleure.Instructions
|
|||||||
value <= uint.MinValue ? uint.MinValue : (uint)value;
|
value <= uint.MinValue ? uint.MinValue : (uint)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static ulong SatF64ToU64(double value)
|
public static ulong SatF64ToU64(double value)
|
||||||
{
|
{
|
||||||
if (double.IsNaN(value))
|
if (double.IsNaN(value))
|
||||||
@@ -182,6 +193,7 @@ namespace ARMeilleure.Instructions
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "Count"
|
#region "Count"
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static ulong CountLeadingSigns(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
|
public static ulong CountLeadingSigns(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
|
||||||
{
|
{
|
||||||
value ^= value >> 1;
|
value ^= value >> 1;
|
||||||
@@ -201,6 +213,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
private static ReadOnlySpan<byte> ClzNibbleTbl => new byte[] { 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
|
private static ReadOnlySpan<byte> ClzNibbleTbl => new byte[] { 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static ulong CountLeadingZeros(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
|
public static ulong CountLeadingZeros(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
|
||||||
{
|
{
|
||||||
if (value == 0ul)
|
if (value == 0ul)
|
||||||
@@ -224,41 +237,49 @@ namespace ARMeilleure.Instructions
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "Table"
|
#region "Table"
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static V128 Tbl1(V128 vector, int bytes, V128 tb0)
|
public static V128 Tbl1(V128 vector, int bytes, V128 tb0)
|
||||||
{
|
{
|
||||||
return TblOrTbx(default, vector, bytes, tb0);
|
return TblOrTbx(default, vector, bytes, tb0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static V128 Tbl2(V128 vector, int bytes, V128 tb0, V128 tb1)
|
public static V128 Tbl2(V128 vector, int bytes, V128 tb0, V128 tb1)
|
||||||
{
|
{
|
||||||
return TblOrTbx(default, vector, bytes, tb0, tb1);
|
return TblOrTbx(default, vector, bytes, tb0, tb1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static V128 Tbl3(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2)
|
public static V128 Tbl3(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2)
|
||||||
{
|
{
|
||||||
return TblOrTbx(default, vector, bytes, tb0, tb1, tb2);
|
return TblOrTbx(default, vector, bytes, tb0, tb1, tb2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static V128 Tbl4(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3)
|
public static V128 Tbl4(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3)
|
||||||
{
|
{
|
||||||
return TblOrTbx(default, vector, bytes, tb0, tb1, tb2, tb3);
|
return TblOrTbx(default, vector, bytes, tb0, tb1, tb2, tb3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static V128 Tbx1(V128 dest, V128 vector, int bytes, V128 tb0)
|
public static V128 Tbx1(V128 dest, V128 vector, int bytes, V128 tb0)
|
||||||
{
|
{
|
||||||
return TblOrTbx(dest, vector, bytes, tb0);
|
return TblOrTbx(dest, vector, bytes, tb0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static V128 Tbx2(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1)
|
public static V128 Tbx2(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1)
|
||||||
{
|
{
|
||||||
return TblOrTbx(dest, vector, bytes, tb0, tb1);
|
return TblOrTbx(dest, vector, bytes, tb0, tb1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static V128 Tbx3(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2)
|
public static V128 Tbx3(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2)
|
||||||
{
|
{
|
||||||
return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2);
|
return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static V128 Tbx4(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3)
|
public static V128 Tbx4(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3)
|
||||||
{
|
{
|
||||||
return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2, tb3);
|
return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2, tb3);
|
||||||
@@ -300,14 +321,22 @@ namespace ARMeilleure.Instructions
|
|||||||
private const uint Crc32RevPoly = 0xedb88320;
|
private const uint Crc32RevPoly = 0xedb88320;
|
||||||
private const uint Crc32cRevPoly = 0x82f63b78;
|
private const uint Crc32cRevPoly = 0x82f63b78;
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static uint Crc32b(uint crc, byte value) => Crc32(crc, Crc32RevPoly, value);
|
public static uint Crc32b(uint crc, byte value) => Crc32(crc, Crc32RevPoly, value);
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static uint Crc32h(uint crc, ushort value) => Crc32h(crc, Crc32RevPoly, value);
|
public static uint Crc32h(uint crc, ushort value) => Crc32h(crc, Crc32RevPoly, value);
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static uint Crc32w(uint crc, uint value) => Crc32w(crc, Crc32RevPoly, value);
|
public static uint Crc32w(uint crc, uint value) => Crc32w(crc, Crc32RevPoly, value);
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static uint Crc32x(uint crc, ulong value) => Crc32x(crc, Crc32RevPoly, value);
|
public static uint Crc32x(uint crc, ulong value) => Crc32x(crc, Crc32RevPoly, value);
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static uint Crc32cb(uint crc, byte value) => Crc32(crc, Crc32cRevPoly, value);
|
public static uint Crc32cb(uint crc, byte value) => Crc32(crc, Crc32cRevPoly, value);
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static uint Crc32ch(uint crc, ushort value) => Crc32h(crc, Crc32cRevPoly, value);
|
public static uint Crc32ch(uint crc, ushort value) => Crc32h(crc, Crc32cRevPoly, value);
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static uint Crc32cw(uint crc, uint value) => Crc32w(crc, Crc32cRevPoly, value);
|
public static uint Crc32cw(uint crc, uint value) => Crc32w(crc, Crc32cRevPoly, value);
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static uint Crc32cx(uint crc, ulong value) => Crc32x(crc, Crc32cRevPoly, value);
|
public static uint Crc32cx(uint crc, ulong value) => Crc32x(crc, Crc32cRevPoly, value);
|
||||||
|
|
||||||
private static uint Crc32h(uint crc, uint poly, ushort val)
|
private static uint Crc32h(uint crc, uint poly, ushort val)
|
||||||
@@ -358,21 +387,25 @@ namespace ARMeilleure.Instructions
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "Aes"
|
#region "Aes"
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static V128 Decrypt(V128 value, V128 roundKey)
|
public static V128 Decrypt(V128 value, V128 roundKey)
|
||||||
{
|
{
|
||||||
return CryptoHelper.AesInvSubBytes(CryptoHelper.AesInvShiftRows(value ^ roundKey));
|
return CryptoHelper.AesInvSubBytes(CryptoHelper.AesInvShiftRows(value ^ roundKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static V128 Encrypt(V128 value, V128 roundKey)
|
public static V128 Encrypt(V128 value, V128 roundKey)
|
||||||
{
|
{
|
||||||
return CryptoHelper.AesSubBytes(CryptoHelper.AesShiftRows(value ^ roundKey));
|
return CryptoHelper.AesSubBytes(CryptoHelper.AesShiftRows(value ^ roundKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static V128 InverseMixColumns(V128 value)
|
public static V128 InverseMixColumns(V128 value)
|
||||||
{
|
{
|
||||||
return CryptoHelper.AesInvMixColumns(value);
|
return CryptoHelper.AesInvMixColumns(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static V128 MixColumns(V128 value)
|
public static V128 MixColumns(V128 value)
|
||||||
{
|
{
|
||||||
return CryptoHelper.AesMixColumns(value);
|
return CryptoHelper.AesMixColumns(value);
|
||||||
@@ -380,6 +413,7 @@ namespace ARMeilleure.Instructions
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "Sha1"
|
#region "Sha1"
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static V128 HashChoose(V128 hash_abcd, uint hash_e, V128 wk)
|
public static V128 HashChoose(V128 hash_abcd, uint hash_e, V128 wk)
|
||||||
{
|
{
|
||||||
for (int e = 0; e <= 3; e++)
|
for (int e = 0; e <= 3; e++)
|
||||||
@@ -400,11 +434,13 @@ namespace ARMeilleure.Instructions
|
|||||||
return hash_abcd;
|
return hash_abcd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static uint FixedRotate(uint hash_e)
|
public static uint FixedRotate(uint hash_e)
|
||||||
{
|
{
|
||||||
return hash_e.Rol(30);
|
return hash_e.Rol(30);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static V128 HashMajority(V128 hash_abcd, uint hash_e, V128 wk)
|
public static V128 HashMajority(V128 hash_abcd, uint hash_e, V128 wk)
|
||||||
{
|
{
|
||||||
for (int e = 0; e <= 3; e++)
|
for (int e = 0; e <= 3; e++)
|
||||||
@@ -425,6 +461,7 @@ namespace ARMeilleure.Instructions
|
|||||||
return hash_abcd;
|
return hash_abcd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static V128 HashParity(V128 hash_abcd, uint hash_e, V128 wk)
|
public static V128 HashParity(V128 hash_abcd, uint hash_e, V128 wk)
|
||||||
{
|
{
|
||||||
for (int e = 0; e <= 3; e++)
|
for (int e = 0; e <= 3; e++)
|
||||||
@@ -445,6 +482,7 @@ namespace ARMeilleure.Instructions
|
|||||||
return hash_abcd;
|
return hash_abcd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static V128 Sha1SchedulePart1(V128 w0_3, V128 w4_7, V128 w8_11)
|
public static V128 Sha1SchedulePart1(V128 w0_3, V128 w4_7, V128 w8_11)
|
||||||
{
|
{
|
||||||
ulong t2 = w4_7.Extract<ulong>(0);
|
ulong t2 = w4_7.Extract<ulong>(0);
|
||||||
@@ -455,6 +493,7 @@ namespace ARMeilleure.Instructions
|
|||||||
return result ^ (w0_3 ^ w8_11);
|
return result ^ (w0_3 ^ w8_11);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static V128 Sha1SchedulePart2(V128 tw0_3, V128 w12_15)
|
public static V128 Sha1SchedulePart2(V128 tw0_3, V128 w12_15)
|
||||||
{
|
{
|
||||||
V128 t = tw0_3 ^ (w12_15 >> 32);
|
V128 t = tw0_3 ^ (w12_15 >> 32);
|
||||||
@@ -499,16 +538,19 @@ namespace ARMeilleure.Instructions
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "Sha256"
|
#region "Sha256"
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static V128 HashLower(V128 hash_abcd, V128 hash_efgh, V128 wk)
|
public static V128 HashLower(V128 hash_abcd, V128 hash_efgh, V128 wk)
|
||||||
{
|
{
|
||||||
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: true);
|
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static V128 HashUpper(V128 hash_abcd, V128 hash_efgh, V128 wk)
|
public static V128 HashUpper(V128 hash_abcd, V128 hash_efgh, V128 wk)
|
||||||
{
|
{
|
||||||
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: false);
|
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static V128 Sha256SchedulePart1(V128 w0_3, V128 w4_7)
|
public static V128 Sha256SchedulePart1(V128 w0_3, V128 w4_7)
|
||||||
{
|
{
|
||||||
V128 result = new();
|
V128 result = new();
|
||||||
@@ -527,6 +569,7 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static V128 Sha256SchedulePart2(V128 w0_3, V128 w8_11, V128 w12_15)
|
public static V128 Sha256SchedulePart2(V128 w0_3, V128 w8_11, V128 w12_15)
|
||||||
{
|
{
|
||||||
V128 result = new();
|
V128 result = new();
|
||||||
@@ -628,6 +671,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static V128 PolynomialMult64_128(ulong op1, ulong op2)
|
public static V128 PolynomialMult64_128(ulong op1, ulong op2)
|
||||||
{
|
{
|
||||||
V128 result = V128.Zero;
|
V128 result = V128.Zero;
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace ARMeilleure.Instructions
|
namespace ARMeilleure.Instructions
|
||||||
{
|
{
|
||||||
@@ -312,6 +313,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
static class SoftFloat16_32
|
static class SoftFloat16_32
|
||||||
{
|
{
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static float FPConvert(ushort valueBits)
|
public static float FPConvert(ushort valueBits)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -487,6 +489,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
static class SoftFloat16_64
|
static class SoftFloat16_64
|
||||||
{
|
{
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static double FPConvert(ushort valueBits)
|
public static double FPConvert(ushort valueBits)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -662,6 +665,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
static class SoftFloat32_16
|
static class SoftFloat32_16
|
||||||
{
|
{
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static ushort FPConvert(float value)
|
public static ushort FPConvert(float value)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -781,12 +785,19 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
static class SoftFloat32
|
static class SoftFloat32
|
||||||
{
|
{
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static float FPAdd(float value1, float value2)
|
public static float FPAdd(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPAddFpscr(value1, value2, false);
|
return FPAddFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float FPAddFpscr(float value1, float value2, bool standardFpscr)
|
[UnmanagedCallersOnly]
|
||||||
|
public static float FPAddFpscr(float value1, float value2, byte standardFpscr)
|
||||||
|
{
|
||||||
|
return FPAddFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float FPAddFpscrImpl(float value1, float value2, bool standardFpscr)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -837,7 +848,8 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int FPCompare(float value1, float value2, bool signalNaNs)
|
[UnmanagedCallersOnly]
|
||||||
|
public static int FPCompare(float value1, float value2, byte signalNaNs)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = context.Fpcr;
|
FPCR fpcr = context.Fpcr;
|
||||||
@@ -851,7 +863,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
result = 0b0011;
|
result = 0b0011;
|
||||||
|
|
||||||
if (type1 == FPType.SNaN || type2 == FPType.SNaN || signalNaNs)
|
if (type1 == FPType.SNaN || type2 == FPType.SNaN || signalNaNs == 1)
|
||||||
{
|
{
|
||||||
SoftFloat.FPProcessException(FPException.InvalidOp, context, fpcr);
|
SoftFloat.FPProcessException(FPException.InvalidOp, context, fpcr);
|
||||||
}
|
}
|
||||||
@@ -875,12 +887,13 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static float FPCompareEQ(float value1, float value2)
|
public static float FPCompareEQ(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPCompareEQFpscr(value1, value2, false);
|
return FPCompareEQFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float FPCompareEQFpscr(float value1, float value2, bool standardFpscr)
|
private static float FPCompareEQFpscrImpl(float value1, float value2, bool standardFpscr)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -907,12 +920,25 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float FPCompareGE(float value1, float value2)
|
[UnmanagedCallersOnly]
|
||||||
|
public static float FPCompareEQFpscr(float value1, float value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPCompareGEFpscr(value1, value2, false);
|
return FPCompareEQFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float FPCompareGEFpscr(float value1, float value2, bool standardFpscr)
|
[UnmanagedCallersOnly]
|
||||||
|
public static float FPCompareGE(float value1, float value2)
|
||||||
|
{
|
||||||
|
return FPCompareGEFpscrImpl(value1, value2, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
public static float FPCompareGEFpscr(float value1, float value2, byte standardFpscr)
|
||||||
|
{
|
||||||
|
return FPCompareGEFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float FPCompareGEFpscrImpl(float value1, float value2, bool standardFpscr)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -936,12 +962,19 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static float FPCompareGT(float value1, float value2)
|
public static float FPCompareGT(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPCompareGTFpscr(value1, value2, false);
|
return FPCompareGTFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float FPCompareGTFpscr(float value1, float value2, bool standardFpscr)
|
[UnmanagedCallersOnly]
|
||||||
|
public static float FPCompareGTFpscr(float value1, float value2, byte standardFpscr)
|
||||||
|
{
|
||||||
|
return FPCompareGTFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float FPCompareGTFpscrImpl(float value1, float value2, bool standardFpscr)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -965,26 +998,31 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static float FPCompareLE(float value1, float value2)
|
public static float FPCompareLE(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPCompareGE(value2, value1);
|
return FPCompareGEFpscrImpl(value2, value1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static float FPCompareLT(float value1, float value2)
|
public static float FPCompareLT(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPCompareGT(value2, value1);
|
return FPCompareGTFpscrImpl(value2, value1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float FPCompareLEFpscr(float value1, float value2, bool standardFpscr)
|
[UnmanagedCallersOnly]
|
||||||
|
public static float FPCompareLEFpscr(float value1, float value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPCompareGEFpscr(value2, value1, standardFpscr);
|
return FPCompareGEFpscrImpl(value2, value1, standardFpscr == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float FPCompareLTFpscr(float value1, float value2, bool standardFpscr)
|
[UnmanagedCallersOnly]
|
||||||
|
public static float FPCompareLTFpscr(float value1, float value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPCompareGTFpscr(value2, value1, standardFpscr);
|
return FPCompareGEFpscrImpl(value2, value1, standardFpscr == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static float FPDiv(float value1, float value2)
|
public static float FPDiv(float value1, float value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -1037,12 +1075,19 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static float FPMax(float value1, float value2)
|
public static float FPMax(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPMaxFpscr(value1, value2, false);
|
return FPMaxFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float FPMaxFpscr(float value1, float value2, bool standardFpscr)
|
[UnmanagedCallersOnly]
|
||||||
|
public static float FPMaxFpscr(float value1, float value2, byte standardFpscr)
|
||||||
|
{
|
||||||
|
return FPMaxFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float FPMaxFpscrImpl(float value1, float value2, bool standardFpscr)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -1103,12 +1148,13 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static float FPMaxNum(float value1, float value2)
|
public static float FPMaxNum(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPMaxNumFpscr(value1, value2, false);
|
return FPMaxNumFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float FPMaxNumFpscr(float value1, float value2, bool standardFpscr)
|
private static float FPMaxNumFpscrImpl(float value1, float value2, bool standardFpscr)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -1125,15 +1171,28 @@ namespace ARMeilleure.Instructions
|
|||||||
value2 = FPInfinity(true);
|
value2 = FPInfinity(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return FPMaxFpscr(value1, value2, standardFpscr);
|
return FPMaxFpscrImpl(value1, value2, standardFpscr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
public static float FPMaxNumFpscr(float value1, float value2, byte standardFpscr)
|
||||||
|
{
|
||||||
|
return FPMaxNumFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static float FPMin(float value1, float value2)
|
public static float FPMin(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPMinFpscr(value1, value2, false);
|
return FPMinFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float FPMinFpscr(float value1, float value2, bool standardFpscr)
|
[UnmanagedCallersOnly]
|
||||||
|
public static float FPMinFpscr(float value1, float value2, byte standardFpscr)
|
||||||
|
{
|
||||||
|
return FPMinFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float FPMinFpscrImpl(float value1, float value2, bool standardFpscr)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -1194,12 +1253,19 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static float FPMinNum(float value1, float value2)
|
public static float FPMinNum(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPMinNumFpscr(value1, value2, false);
|
return FPMinNumFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float FPMinNumFpscr(float value1, float value2, bool standardFpscr)
|
[UnmanagedCallersOnly]
|
||||||
|
public static float FPMinNumFpscr(float value1, float value2, byte standardFpscr)
|
||||||
|
{
|
||||||
|
return FPMinNumFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float FPMinNumFpscrImpl(float value1, float value2, bool standardFpscr)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -1216,15 +1282,22 @@ namespace ARMeilleure.Instructions
|
|||||||
value2 = FPInfinity(false);
|
value2 = FPInfinity(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return FPMinFpscr(value1, value2, standardFpscr);
|
return FPMinFpscrImpl(value1, value2, standardFpscr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static float FPMul(float value1, float value2)
|
public static float FPMul(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPMulFpscr(value1, value2, false);
|
return FPMulFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float FPMulFpscr(float value1, float value2, bool standardFpscr)
|
[UnmanagedCallersOnly]
|
||||||
|
public static float FPMulFpscr(float value1, float value2, byte standardFpscr)
|
||||||
|
{
|
||||||
|
return FPMulFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float FPMulFpscrImpl(float value1, float value2, bool standardFpscr)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -1271,12 +1344,19 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static float FPMulAdd(float valueA, float value1, float value2)
|
public static float FPMulAdd(float valueA, float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPMulAddFpscr(valueA, value1, value2, false);
|
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float FPMulAddFpscr(float valueA, float value1, float value2, bool standardFpscr)
|
[UnmanagedCallersOnly]
|
||||||
|
public static float FPMulAddFpscr(float valueA, float value1, float value2, byte standardFpscr)
|
||||||
|
{
|
||||||
|
return FPMulAddFpscrImpl(valueA, value1, value2, standardFpscr == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float FPMulAddFpscrImpl(float valueA, float value1, float value2, bool standardFpscr)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -1342,20 +1422,23 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static float FPMulSub(float valueA, float value1, float value2)
|
public static float FPMulSub(float valueA, float value1, float value2)
|
||||||
{
|
{
|
||||||
value1 = value1.FPNeg();
|
value1 = value1.FPNeg();
|
||||||
|
|
||||||
return FPMulAdd(valueA, value1, value2);
|
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float FPMulSubFpscr(float valueA, float value1, float value2, bool standardFpscr)
|
[UnmanagedCallersOnly]
|
||||||
|
public static float FPMulSubFpscr(float valueA, float value1, float value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
value1 = value1.FPNeg();
|
value1 = value1.FPNeg();
|
||||||
|
|
||||||
return FPMulAddFpscr(valueA, value1, value2, standardFpscr);
|
return FPMulAddFpscrImpl(valueA, value1, value2, standardFpscr == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static float FPMulX(float value1, float value2)
|
public static float FPMulX(float value1, float value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -1401,27 +1484,36 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static float FPNegMulAdd(float valueA, float value1, float value2)
|
public static float FPNegMulAdd(float valueA, float value1, float value2)
|
||||||
{
|
{
|
||||||
valueA = valueA.FPNeg();
|
valueA = valueA.FPNeg();
|
||||||
value1 = value1.FPNeg();
|
value1 = value1.FPNeg();
|
||||||
|
|
||||||
return FPMulAdd(valueA, value1, value2);
|
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static float FPNegMulSub(float valueA, float value1, float value2)
|
public static float FPNegMulSub(float valueA, float value1, float value2)
|
||||||
{
|
{
|
||||||
valueA = valueA.FPNeg();
|
valueA = valueA.FPNeg();
|
||||||
|
|
||||||
return FPMulAdd(valueA, value1, value2);
|
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static float FPRecipEstimate(float value)
|
public static float FPRecipEstimate(float value)
|
||||||
{
|
{
|
||||||
return FPRecipEstimateFpscr(value, false);
|
return FPRecipEstimateFpscrImpl(value, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float FPRecipEstimateFpscr(float value, bool standardFpscr)
|
[UnmanagedCallersOnly]
|
||||||
|
public static float FPRecipEstimateFpscr(float value, byte standardFpscr)
|
||||||
|
{
|
||||||
|
return FPRecipEstimateFpscrImpl(value, standardFpscr == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float FPRecipEstimateFpscrImpl(float value, bool standardFpscr)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -1508,6 +1600,7 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static float FPRecipStep(float value1, float value2)
|
public static float FPRecipStep(float value1, float value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -1533,15 +1626,16 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
product = FPMulFpscr(value1, value2, true);
|
product = FPMulFpscrImpl(value1, value2, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
result = FPSubFpscr(FPTwo(false), product, true);
|
result = FPSubFpscrImpl(FPTwo(false), product, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static float FPRecipStepFused(float value1, float value2)
|
public static float FPRecipStepFused(float value1, float value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -1585,6 +1679,7 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static float FPRecpX(float value)
|
public static float FPRecpX(float value)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -1610,12 +1705,19 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static float FPRSqrtEstimate(float value)
|
public static float FPRSqrtEstimate(float value)
|
||||||
{
|
{
|
||||||
return FPRSqrtEstimateFpscr(value, false);
|
return FPRSqrtEstimateFpscrImpl(value, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float FPRSqrtEstimateFpscr(float value, bool standardFpscr)
|
[UnmanagedCallersOnly]
|
||||||
|
public static float FPRSqrtEstimateFpscr(float value, byte standardFpscr)
|
||||||
|
{
|
||||||
|
return FPRSqrtEstimateFpscrImpl(value, standardFpscr == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float FPRSqrtEstimateFpscrImpl(float value, bool standardFpscr)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -1729,6 +1831,7 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static float FPRSqrtStep(float value1, float value2)
|
public static float FPRSqrtStep(float value1, float value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -1754,7 +1857,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
product = FPMulFpscr(value1, value2, true);
|
product = FPMulFpscrImpl(value1, value2, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
result = FPHalvedSub(FPThree(false), product, context, fpcr);
|
result = FPHalvedSub(FPThree(false), product, context, fpcr);
|
||||||
@@ -1763,6 +1866,7 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static float FPRSqrtStepFused(float value1, float value2)
|
public static float FPRSqrtStepFused(float value1, float value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -1806,6 +1910,7 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static float FPSqrt(float value)
|
public static float FPSqrt(float value)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -1848,12 +1953,13 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static float FPSub(float value1, float value2)
|
public static float FPSub(float value1, float value2)
|
||||||
{
|
{
|
||||||
return FPSubFpscr(value1, value2, false);
|
return FPSubFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float FPSubFpscr(float value1, float value2, bool standardFpscr)
|
private static float FPSubFpscrImpl(float value1, float value2, bool standardFpscr)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -2094,6 +2200,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
static class SoftFloat64_16
|
static class SoftFloat64_16
|
||||||
{
|
{
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static ushort FPConvert(double value)
|
public static ushort FPConvert(double value)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -2213,12 +2320,19 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
static class SoftFloat64
|
static class SoftFloat64
|
||||||
{
|
{
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static double FPAdd(double value1, double value2)
|
public static double FPAdd(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPAddFpscr(value1, value2, false);
|
return FPAddFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double FPAddFpscr(double value1, double value2, bool standardFpscr)
|
[UnmanagedCallersOnly]
|
||||||
|
public static double FPAddFpscr(double value1, double value2, byte standardFpscr)
|
||||||
|
{
|
||||||
|
return FPAddFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double FPAddFpscrImpl(double value1, double value2, bool standardFpscr)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -2269,7 +2383,8 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int FPCompare(double value1, double value2, bool signalNaNs)
|
[UnmanagedCallersOnly]
|
||||||
|
public static int FPCompare(double value1, double value2, byte signalNaNs)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = context.Fpcr;
|
FPCR fpcr = context.Fpcr;
|
||||||
@@ -2283,7 +2398,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
result = 0b0011;
|
result = 0b0011;
|
||||||
|
|
||||||
if (type1 == FPType.SNaN || type2 == FPType.SNaN || signalNaNs)
|
if (type1 == FPType.SNaN || type2 == FPType.SNaN || signalNaNs == 1)
|
||||||
{
|
{
|
||||||
SoftFloat.FPProcessException(FPException.InvalidOp, context, fpcr);
|
SoftFloat.FPProcessException(FPException.InvalidOp, context, fpcr);
|
||||||
}
|
}
|
||||||
@@ -2307,12 +2422,19 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static double FPCompareEQ(double value1, double value2)
|
public static double FPCompareEQ(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPCompareEQFpscr(value1, value2, false);
|
return FPCompareEQFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double FPCompareEQFpscr(double value1, double value2, bool standardFpscr)
|
[UnmanagedCallersOnly]
|
||||||
|
public static double FPCompareEQFpscr(double value1, double value2, byte standardFpscr)
|
||||||
|
{
|
||||||
|
return FPCompareEQFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double FPCompareEQFpscrImpl(double value1, double value2, bool standardFpscr)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -2339,12 +2461,19 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static double FPCompareGE(double value1, double value2)
|
public static double FPCompareGE(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPCompareGEFpscr(value1, value2, false);
|
return FPCompareGEFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double FPCompareGEFpscr(double value1, double value2, bool standardFpscr)
|
[UnmanagedCallersOnly]
|
||||||
|
public static double FPCompareGEFpscr(double value1, double value2, byte standardFpscr)
|
||||||
|
{
|
||||||
|
return FPCompareGEFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double FPCompareGEFpscrImpl(double value1, double value2, bool standardFpscr)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -2368,12 +2497,19 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static double FPCompareGT(double value1, double value2)
|
public static double FPCompareGT(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPCompareGTFpscr(value1, value2, false);
|
return FPCompareGTFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double FPCompareGTFpscr(double value1, double value2, bool standardFpscr)
|
[UnmanagedCallersOnly]
|
||||||
|
public static double FPCompareGTFpscr(double value1, double value2, byte standardFpscr)
|
||||||
|
{
|
||||||
|
return FPCompareGTFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double FPCompareGTFpscrImpl(double value1, double value2, bool standardFpscr)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -2397,26 +2533,31 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static double FPCompareLE(double value1, double value2)
|
public static double FPCompareLE(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPCompareGE(value2, value1);
|
return FPCompareGEFpscrImpl(value2, value1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static double FPCompareLT(double value1, double value2)
|
public static double FPCompareLT(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPCompareGT(value2, value1);
|
return FPCompareGTFpscrImpl(value2, value1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double FPCompareLEFpscr(double value1, double value2, bool standardFpscr)
|
[UnmanagedCallersOnly]
|
||||||
|
public static double FPCompareLEFpscr(double value1, double value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPCompareGEFpscr(value2, value1, standardFpscr);
|
return FPCompareGEFpscrImpl(value2, value1, standardFpscr == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double FPCompareLTFpscr(double value1, double value2, bool standardFpscr)
|
[UnmanagedCallersOnly]
|
||||||
|
public static double FPCompareLTFpscr(double value1, double value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
return FPCompareGTFpscr(value2, value1, standardFpscr);
|
return FPCompareGTFpscrImpl(value2, value1, standardFpscr == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static double FPDiv(double value1, double value2)
|
public static double FPDiv(double value1, double value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -2469,12 +2610,19 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static double FPMax(double value1, double value2)
|
public static double FPMax(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPMaxFpscr(value1, value2, false);
|
return FPMaxFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double FPMaxFpscr(double value1, double value2, bool standardFpscr)
|
[UnmanagedCallersOnly]
|
||||||
|
public static double FPMaxFpscr(double value1, double value2, byte standardFpscr)
|
||||||
|
{
|
||||||
|
return FPMaxFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double FPMaxFpscrImpl(double value1, double value2, bool standardFpscr)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -2535,12 +2683,19 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static double FPMaxNum(double value1, double value2)
|
public static double FPMaxNum(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPMaxNumFpscr(value1, value2, false);
|
return FPMaxNumFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double FPMaxNumFpscr(double value1, double value2, bool standardFpscr)
|
[UnmanagedCallersOnly]
|
||||||
|
public static double FPMaxNumFpscr(double value1, double value2, byte standardFpscr)
|
||||||
|
{
|
||||||
|
return FPMaxNumFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double FPMaxNumFpscrImpl(double value1, double value2, bool standardFpscr)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -2557,15 +2712,22 @@ namespace ARMeilleure.Instructions
|
|||||||
value2 = FPInfinity(true);
|
value2 = FPInfinity(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return FPMaxFpscr(value1, value2, standardFpscr);
|
return FPMaxFpscrImpl(value1, value2, standardFpscr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static double FPMin(double value1, double value2)
|
public static double FPMin(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPMinFpscr(value1, value2, false);
|
return FPMinFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double FPMinFpscr(double value1, double value2, bool standardFpscr)
|
[UnmanagedCallersOnly]
|
||||||
|
public static double FPMinFpscr(double value1, double value2, byte standardFpscr)
|
||||||
|
{
|
||||||
|
return FPMinFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double FPMinFpscrImpl(double value1, double value2, bool standardFpscr)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -2626,12 +2788,19 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static double FPMinNum(double value1, double value2)
|
public static double FPMinNum(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPMinNumFpscr(value1, value2, false);
|
return FPMinNumFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double FPMinNumFpscr(double value1, double value2, bool standardFpscr)
|
[UnmanagedCallersOnly]
|
||||||
|
public static double FPMinNumFpscr(double value1, double value2, byte standardFpscr)
|
||||||
|
{
|
||||||
|
return FPMinNumFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double FPMinNumFpscrImpl(double value1, double value2, bool standardFpscr)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -2648,15 +2817,22 @@ namespace ARMeilleure.Instructions
|
|||||||
value2 = FPInfinity(false);
|
value2 = FPInfinity(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return FPMinFpscr(value1, value2, standardFpscr);
|
return FPMinFpscrImpl(value1, value2, standardFpscr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static double FPMul(double value1, double value2)
|
public static double FPMul(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPMulFpscr(value1, value2, false);
|
return FPMulFpscrImpl(value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double FPMulFpscr(double value1, double value2, bool standardFpscr)
|
[UnmanagedCallersOnly]
|
||||||
|
public static double FPMulFpscr(double value1, double value2, byte standardFpscr)
|
||||||
|
{
|
||||||
|
return FPMulFpscrImpl(value1, value2, standardFpscr == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double FPMulFpscrImpl(double value1, double value2, bool standardFpscr)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -2703,12 +2879,19 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static double FPMulAdd(double valueA, double value1, double value2)
|
public static double FPMulAdd(double valueA, double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPMulAddFpscr(valueA, value1, value2, false);
|
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double FPMulAddFpscr(double valueA, double value1, double value2, bool standardFpscr)
|
[UnmanagedCallersOnly]
|
||||||
|
public static double FPMulAddFpscr(double valueA, double value1, double value2, byte standardFpscr)
|
||||||
|
{
|
||||||
|
return FPMulAddFpscrImpl(valueA, value1, value2, standardFpscr == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double FPMulAddFpscrImpl(double valueA, double value1, double value2, bool standardFpscr)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -2774,20 +2957,23 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static double FPMulSub(double valueA, double value1, double value2)
|
public static double FPMulSub(double valueA, double value1, double value2)
|
||||||
{
|
{
|
||||||
value1 = value1.FPNeg();
|
value1 = value1.FPNeg();
|
||||||
|
|
||||||
return FPMulAdd(valueA, value1, value2);
|
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double FPMulSubFpscr(double valueA, double value1, double value2, bool standardFpscr)
|
[UnmanagedCallersOnly]
|
||||||
|
public static double FPMulSubFpscr(double valueA, double value1, double value2, byte standardFpscr)
|
||||||
{
|
{
|
||||||
value1 = value1.FPNeg();
|
value1 = value1.FPNeg();
|
||||||
|
|
||||||
return FPMulAddFpscr(valueA, value1, value2, standardFpscr);
|
return FPMulAddFpscrImpl(valueA, value1, value2, standardFpscr == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static double FPMulX(double value1, double value2)
|
public static double FPMulX(double value1, double value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -2833,27 +3019,36 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static double FPNegMulAdd(double valueA, double value1, double value2)
|
public static double FPNegMulAdd(double valueA, double value1, double value2)
|
||||||
{
|
{
|
||||||
valueA = valueA.FPNeg();
|
valueA = valueA.FPNeg();
|
||||||
value1 = value1.FPNeg();
|
value1 = value1.FPNeg();
|
||||||
|
|
||||||
return FPMulAdd(valueA, value1, value2);
|
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static double FPNegMulSub(double valueA, double value1, double value2)
|
public static double FPNegMulSub(double valueA, double value1, double value2)
|
||||||
{
|
{
|
||||||
valueA = valueA.FPNeg();
|
valueA = valueA.FPNeg();
|
||||||
|
|
||||||
return FPMulAdd(valueA, value1, value2);
|
return FPMulAddFpscrImpl(valueA, value1, value2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static double FPRecipEstimate(double value)
|
public static double FPRecipEstimate(double value)
|
||||||
{
|
{
|
||||||
return FPRecipEstimateFpscr(value, false);
|
return FPRecipEstimateFpscrImpl(value, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double FPRecipEstimateFpscr(double value, bool standardFpscr)
|
[UnmanagedCallersOnly]
|
||||||
|
public static double FPRecipEstimateFpscr(double value, byte standardFpscr)
|
||||||
|
{
|
||||||
|
return FPRecipEstimateFpscrImpl(value, standardFpscr == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double FPRecipEstimateFpscrImpl(double value, bool standardFpscr)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -2940,6 +3135,7 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static double FPRecipStep(double value1, double value2)
|
public static double FPRecipStep(double value1, double value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -2965,7 +3161,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
product = FPMulFpscr(value1, value2, true);
|
product = FPMulFpscrImpl(value1, value2, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
result = FPSubFpscr(FPTwo(false), product, true);
|
result = FPSubFpscr(FPTwo(false), product, true);
|
||||||
@@ -2974,6 +3170,7 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static double FPRecipStepFused(double value1, double value2)
|
public static double FPRecipStepFused(double value1, double value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -3017,6 +3214,7 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static double FPRecpX(double value)
|
public static double FPRecpX(double value)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -3042,12 +3240,19 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static double FPRSqrtEstimate(double value)
|
public static double FPRSqrtEstimate(double value)
|
||||||
{
|
{
|
||||||
return FPRSqrtEstimateFpscr(value, false);
|
return FPRSqrtEstimateFpscrImpl(value, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double FPRSqrtEstimateFpscr(double value, bool standardFpscr)
|
[UnmanagedCallersOnly]
|
||||||
|
public static double FPRSqrtEstimateFpscr(double value, byte standardFpscr)
|
||||||
|
{
|
||||||
|
return FPRSqrtEstimateFpscrImpl(value, standardFpscr == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double FPRSqrtEstimateFpscrImpl(double value, bool standardFpscr)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||||
@@ -3161,6 +3366,7 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static double FPRSqrtStep(double value1, double value2)
|
public static double FPRSqrtStep(double value1, double value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -3186,7 +3392,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
product = FPMulFpscr(value1, value2, true);
|
product = FPMulFpscrImpl(value1, value2, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
result = FPHalvedSub(FPThree(false), product, context, fpcr);
|
result = FPHalvedSub(FPThree(false), product, context, fpcr);
|
||||||
@@ -3195,6 +3401,7 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static double FPRSqrtStepFused(double value1, double value2)
|
public static double FPRSqrtStepFused(double value1, double value2)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -3238,6 +3445,7 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static double FPSqrt(double value)
|
public static double FPSqrt(double value)
|
||||||
{
|
{
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
ExecutionContext context = NativeInterface.GetContext();
|
||||||
@@ -3280,6 +3488,7 @@ namespace ARMeilleure.Instructions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
public static double FPSub(double value1, double value2)
|
public static double FPSub(double value1, double value2)
|
||||||
{
|
{
|
||||||
return FPSubFpscr(value1, value2, false);
|
return FPSubFpscr(value1, value2, false);
|
||||||
|
@@ -4,15 +4,9 @@ namespace ARMeilleure.Translation
|
|||||||
{
|
{
|
||||||
class DelegateInfo
|
class DelegateInfo
|
||||||
{
|
{
|
||||||
#pragma warning disable IDE0052 // Remove unread private member
|
public nint FuncPtr { get; private set; }
|
||||||
private readonly Delegate _dlg; // Ensure that this delegate will not be garbage collected.
|
public DelegateInfo(nint funcPtr)
|
||||||
#pragma warning restore IDE0052
|
|
||||||
|
|
||||||
public nint FuncPtr { get; }
|
|
||||||
|
|
||||||
public DelegateInfo(Delegate dlg, nint funcPtr)
|
|
||||||
{
|
{
|
||||||
_dlg = dlg;
|
|
||||||
FuncPtr = funcPtr;
|
FuncPtr = funcPtr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,7 @@
|
|||||||
using ARMeilleure.Instructions;
|
using ARMeilleure.Instructions;
|
||||||
using ARMeilleure.State;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace ARMeilleure.Translation
|
namespace ARMeilleure.Translation
|
||||||
{
|
{
|
||||||
@@ -34,21 +32,7 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
return _delegates.Values[index].FuncPtr; // O(1).
|
return _delegates.Values[index].FuncPtr; // O(1).
|
||||||
}
|
}
|
||||||
|
|
||||||
public static nint GetDelegateFuncPtr(MethodInfo info)
|
|
||||||
{
|
|
||||||
ArgumentNullException.ThrowIfNull(info);
|
|
||||||
|
|
||||||
string key = GetKey(info);
|
|
||||||
|
|
||||||
if (!_delegates.TryGetValue(key, out DelegateInfo dlgInfo)) // O(log(n)).
|
|
||||||
{
|
|
||||||
throw new KeyNotFoundException($"({nameof(key)} = {key})");
|
|
||||||
}
|
|
||||||
|
|
||||||
return dlgInfo.FuncPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int GetDelegateIndex(MethodInfo info)
|
public static int GetDelegateIndex(MethodInfo info)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(info);
|
ArgumentNullException.ThrowIfNull(info);
|
||||||
@@ -64,12 +48,12 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SetDelegateInfo(Delegate dlg, nint funcPtr)
|
private static void SetDelegateInfo(MethodInfo method)
|
||||||
{
|
{
|
||||||
string key = GetKey(dlg.Method);
|
string key = GetKey(method);
|
||||||
|
|
||||||
_delegates.Add(key, new DelegateInfo(dlg, funcPtr)); // ArgumentException (key).
|
_delegates.Add(key, new DelegateInfo(method.MethodHandle.GetFunctionPointer())); // ArgumentException (key).
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetKey(MethodInfo info)
|
private static string GetKey(MethodInfo info)
|
||||||
@@ -83,528 +67,179 @@ namespace ARMeilleure.Translation
|
|||||||
{
|
{
|
||||||
_delegates = new SortedList<string, DelegateInfo>();
|
_delegates = new SortedList<string, DelegateInfo>();
|
||||||
|
|
||||||
var dlgMathAbs = new MathAbs(Math.Abs);
|
SetDelegateInfo(typeof(MathHelper).GetMethod(nameof(MathHelper.Abs)));
|
||||||
var dlgMathCeiling = new MathCeiling(Math.Ceiling);
|
SetDelegateInfo(typeof(MathHelper).GetMethod(nameof(MathHelper.Ceiling)));
|
||||||
var dlgMathFloor = new MathFloor(Math.Floor);
|
SetDelegateInfo(typeof(MathHelper).GetMethod(nameof(MathHelper.Floor)));
|
||||||
var dlgMathRound = new MathRound(Math.Round);
|
SetDelegateInfo(typeof(MathHelper).GetMethod(nameof(MathHelper.Round)));
|
||||||
var dlgMathTruncate = new MathTruncate(Math.Truncate);
|
SetDelegateInfo(typeof(MathHelper).GetMethod(nameof(MathHelper.Truncate)));
|
||||||
|
|
||||||
var dlgMathFAbs = new MathFAbs(MathF.Abs);
|
SetDelegateInfo(typeof(MathHelperF).GetMethod(nameof(MathHelperF.Abs)));
|
||||||
var dlgMathFCeiling = new MathFCeiling(MathF.Ceiling);
|
SetDelegateInfo(typeof(MathHelperF).GetMethod(nameof(MathHelperF.Ceiling)));
|
||||||
var dlgMathFFloor = new MathFFloor(MathF.Floor);
|
SetDelegateInfo(typeof(MathHelperF).GetMethod(nameof(MathHelperF.Floor)));
|
||||||
var dlgMathFRound = new MathFRound(MathF.Round);
|
SetDelegateInfo(typeof(MathHelperF).GetMethod(nameof(MathHelperF.Round)));
|
||||||
var dlgMathFTruncate = new MathFTruncate(MathF.Truncate);
|
SetDelegateInfo(typeof(MathHelperF).GetMethod(nameof(MathHelperF.Truncate)));
|
||||||
|
|
||||||
var dlgNativeInterfaceBreak = new NativeInterfaceBreak(NativeInterface.Break);
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.Break)));
|
||||||
var dlgNativeInterfaceCheckSynchronization = new NativeInterfaceCheckSynchronization(NativeInterface.CheckSynchronization);
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.CheckSynchronization)));
|
||||||
var dlgNativeInterfaceEnqueueForRejit = new NativeInterfaceEnqueueForRejit(NativeInterface.EnqueueForRejit);
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.EnqueueForRejit)));
|
||||||
var dlgNativeInterfaceGetCntfrqEl0 = new NativeInterfaceGetCntfrqEl0(NativeInterface.GetCntfrqEl0);
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntfrqEl0)));
|
||||||
var dlgNativeInterfaceGetCntpctEl0 = new NativeInterfaceGetCntpctEl0(NativeInterface.GetCntpctEl0);
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntpctEl0)));
|
||||||
var dlgNativeInterfaceGetCntvctEl0 = new NativeInterfaceGetCntvctEl0(NativeInterface.GetCntvctEl0);
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntvctEl0)));
|
||||||
var dlgNativeInterfaceGetCtrEl0 = new NativeInterfaceGetCtrEl0(NativeInterface.GetCtrEl0);
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCtrEl0)));
|
||||||
var dlgNativeInterfaceGetDczidEl0 = new NativeInterfaceGetDczidEl0(NativeInterface.GetDczidEl0);
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetDczidEl0)));
|
||||||
var dlgNativeInterfaceGetFunctionAddress = new NativeInterfaceGetFunctionAddress(NativeInterface.GetFunctionAddress);
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)));
|
||||||
var dlgNativeInterfaceInvalidateCacheLine = new NativeInterfaceInvalidateCacheLine(NativeInterface.InvalidateCacheLine);
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.InvalidateCacheLine)));
|
||||||
var dlgNativeInterfaceReadByte = new NativeInterfaceReadByte(NativeInterface.ReadByte);
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadByte)));
|
||||||
var dlgNativeInterfaceReadUInt16 = new NativeInterfaceReadUInt16(NativeInterface.ReadUInt16);
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt16)));
|
||||||
var dlgNativeInterfaceReadUInt32 = new NativeInterfaceReadUInt32(NativeInterface.ReadUInt32);
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt32)));
|
||||||
var dlgNativeInterfaceReadUInt64 = new NativeInterfaceReadUInt64(NativeInterface.ReadUInt64);
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64)));
|
||||||
var dlgNativeInterfaceReadVector128 = new NativeInterfaceReadVector128(NativeInterface.ReadVector128);
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadVector128)));
|
||||||
var dlgNativeInterfaceSignalMemoryTracking = new NativeInterfaceSignalMemoryTracking(NativeInterface.SignalMemoryTracking);
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SignalMemoryTracking)));
|
||||||
var dlgNativeInterfaceSupervisorCall = new NativeInterfaceSupervisorCall(NativeInterface.SupervisorCall);
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SupervisorCall)));
|
||||||
var dlgNativeInterfaceThrowInvalidMemoryAccess = new NativeInterfaceThrowInvalidMemoryAccess(NativeInterface.ThrowInvalidMemoryAccess);
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ThrowInvalidMemoryAccess)));
|
||||||
var dlgNativeInterfaceUndefined = new NativeInterfaceUndefined(NativeInterface.Undefined);
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.Undefined)));
|
||||||
var dlgNativeInterfaceWriteByte = new NativeInterfaceWriteByte(NativeInterface.WriteByte);
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteByte)));
|
||||||
var dlgNativeInterfaceWriteUInt16 = new NativeInterfaceWriteUInt16(NativeInterface.WriteUInt16);
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt16)));
|
||||||
var dlgNativeInterfaceWriteUInt32 = new NativeInterfaceWriteUInt32(NativeInterface.WriteUInt32);
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt32)));
|
||||||
var dlgNativeInterfaceWriteUInt64 = new NativeInterfaceWriteUInt64(NativeInterface.WriteUInt64);
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64)));
|
||||||
var dlgNativeInterfaceWriteVector128 = new NativeInterfaceWriteVector128(NativeInterface.WriteVector128);
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteVector128)));
|
||||||
|
|
||||||
var dlgSoftFallbackCountLeadingSigns = new SoftFallbackCountLeadingSigns(SoftFallback.CountLeadingSigns);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.CountLeadingSigns)));
|
||||||
var dlgSoftFallbackCountLeadingZeros = new SoftFallbackCountLeadingZeros(SoftFallback.CountLeadingZeros);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.CountLeadingZeros)));
|
||||||
var dlgSoftFallbackCrc32b = new SoftFallbackCrc32b(SoftFallback.Crc32b);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32b)));
|
||||||
var dlgSoftFallbackCrc32cb = new SoftFallbackCrc32cb(SoftFallback.Crc32cb);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32cb)));
|
||||||
var dlgSoftFallbackCrc32ch = new SoftFallbackCrc32ch(SoftFallback.Crc32ch);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32ch)));
|
||||||
var dlgSoftFallbackCrc32cw = new SoftFallbackCrc32cw(SoftFallback.Crc32cw);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32cw)));
|
||||||
var dlgSoftFallbackCrc32cx = new SoftFallbackCrc32cx(SoftFallback.Crc32cx);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32cx)));
|
||||||
var dlgSoftFallbackCrc32h = new SoftFallbackCrc32h(SoftFallback.Crc32h);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32h)));
|
||||||
var dlgSoftFallbackCrc32w = new SoftFallbackCrc32w(SoftFallback.Crc32w);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32w)));
|
||||||
var dlgSoftFallbackCrc32x = new SoftFallbackCrc32x(SoftFallback.Crc32x);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32x)));
|
||||||
var dlgSoftFallbackDecrypt = new SoftFallbackDecrypt(SoftFallback.Decrypt);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Decrypt)));
|
||||||
var dlgSoftFallbackEncrypt = new SoftFallbackEncrypt(SoftFallback.Encrypt);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Encrypt)));
|
||||||
var dlgSoftFallbackFixedRotate = new SoftFallbackFixedRotate(SoftFallback.FixedRotate);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.FixedRotate)));
|
||||||
var dlgSoftFallbackHashChoose = new SoftFallbackHashChoose(SoftFallback.HashChoose);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashChoose)));
|
||||||
var dlgSoftFallbackHashLower = new SoftFallbackHashLower(SoftFallback.HashLower);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashLower)));
|
||||||
var dlgSoftFallbackHashMajority = new SoftFallbackHashMajority(SoftFallback.HashMajority);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashMajority)));
|
||||||
var dlgSoftFallbackHashParity = new SoftFallbackHashParity(SoftFallback.HashParity);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashParity)));
|
||||||
var dlgSoftFallbackHashUpper = new SoftFallbackHashUpper(SoftFallback.HashUpper);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashUpper)));
|
||||||
var dlgSoftFallbackInverseMixColumns = new SoftFallbackInverseMixColumns(SoftFallback.InverseMixColumns);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.InverseMixColumns)));
|
||||||
var dlgSoftFallbackMixColumns = new SoftFallbackMixColumns(SoftFallback.MixColumns);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.MixColumns)));
|
||||||
var dlgSoftFallbackPolynomialMult64_128 = new SoftFallbackPolynomialMult64_128(SoftFallback.PolynomialMult64_128);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.PolynomialMult64_128)));
|
||||||
var dlgSoftFallbackSatF32ToS32 = new SoftFallbackSatF32ToS32(SoftFallback.SatF32ToS32);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS32)));
|
||||||
var dlgSoftFallbackSatF32ToS64 = new SoftFallbackSatF32ToS64(SoftFallback.SatF32ToS64);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS64)));
|
||||||
var dlgSoftFallbackSatF32ToU32 = new SoftFallbackSatF32ToU32(SoftFallback.SatF32ToU32);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU32)));
|
||||||
var dlgSoftFallbackSatF32ToU64 = new SoftFallbackSatF32ToU64(SoftFallback.SatF32ToU64);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU64)));
|
||||||
var dlgSoftFallbackSatF64ToS32 = new SoftFallbackSatF64ToS32(SoftFallback.SatF64ToS32);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToS32)));
|
||||||
var dlgSoftFallbackSatF64ToS64 = new SoftFallbackSatF64ToS64(SoftFallback.SatF64ToS64);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToS64)));
|
||||||
var dlgSoftFallbackSatF64ToU32 = new SoftFallbackSatF64ToU32(SoftFallback.SatF64ToU32);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToU32)));
|
||||||
var dlgSoftFallbackSatF64ToU64 = new SoftFallbackSatF64ToU64(SoftFallback.SatF64ToU64);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToU64)));
|
||||||
var dlgSoftFallbackSha1SchedulePart1 = new SoftFallbackSha1SchedulePart1(SoftFallback.Sha1SchedulePart1);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha1SchedulePart1)));
|
||||||
var dlgSoftFallbackSha1SchedulePart2 = new SoftFallbackSha1SchedulePart2(SoftFallback.Sha1SchedulePart2);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha1SchedulePart2)));
|
||||||
var dlgSoftFallbackSha256SchedulePart1 = new SoftFallbackSha256SchedulePart1(SoftFallback.Sha256SchedulePart1);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart1)));
|
||||||
var dlgSoftFallbackSha256SchedulePart2 = new SoftFallbackSha256SchedulePart2(SoftFallback.Sha256SchedulePart2);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart2)));
|
||||||
var dlgSoftFallbackSignedShrImm64 = new SoftFallbackSignedShrImm64(SoftFallback.SignedShrImm64);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShrImm64)));
|
||||||
var dlgSoftFallbackTbl1 = new SoftFallbackTbl1(SoftFallback.Tbl1);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl1)));
|
||||||
var dlgSoftFallbackTbl2 = new SoftFallbackTbl2(SoftFallback.Tbl2);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl2)));
|
||||||
var dlgSoftFallbackTbl3 = new SoftFallbackTbl3(SoftFallback.Tbl3);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl3)));
|
||||||
var dlgSoftFallbackTbl4 = new SoftFallbackTbl4(SoftFallback.Tbl4);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl4)));
|
||||||
var dlgSoftFallbackTbx1 = new SoftFallbackTbx1(SoftFallback.Tbx1);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx1)));
|
||||||
var dlgSoftFallbackTbx2 = new SoftFallbackTbx2(SoftFallback.Tbx2);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx2)));
|
||||||
var dlgSoftFallbackTbx3 = new SoftFallbackTbx3(SoftFallback.Tbx3);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx3)));
|
||||||
var dlgSoftFallbackTbx4 = new SoftFallbackTbx4(SoftFallback.Tbx4);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx4)));
|
||||||
var dlgSoftFallbackUnsignedShrImm64 = new SoftFallbackUnsignedShrImm64(SoftFallback.UnsignedShrImm64);
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShrImm64)));
|
||||||
|
|
||||||
var dlgSoftFloat16_32FPConvert = new SoftFloat16_32FPConvert(SoftFloat16_32.FPConvert);
|
SetDelegateInfo(typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert)));
|
||||||
var dlgSoftFloat16_64FPConvert = new SoftFloat16_64FPConvert(SoftFloat16_64.FPConvert);
|
SetDelegateInfo(typeof(SoftFloat16_64).GetMethod(nameof(SoftFloat16_64.FPConvert)));
|
||||||
|
|
||||||
var dlgSoftFloat32FPAdd = new SoftFloat32FPAdd(SoftFloat32.FPAdd);
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPAdd)));
|
||||||
var dlgSoftFloat32FPAddFpscr = new SoftFloat32FPAddFpscr(SoftFloat32.FPAddFpscr); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPAddFpscr))); // A32 only.
|
||||||
var dlgSoftFloat32FPCompare = new SoftFloat32FPCompare(SoftFloat32.FPCompare);
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompare)));
|
||||||
var dlgSoftFloat32FPCompareEQ = new SoftFloat32FPCompareEQ(SoftFloat32.FPCompareEQ);
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareEQ)));
|
||||||
var dlgSoftFloat32FPCompareEQFpscr = new SoftFloat32FPCompareEQFpscr(SoftFloat32.FPCompareEQFpscr); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareEQFpscr))); // A32 only.
|
||||||
var dlgSoftFloat32FPCompareGE = new SoftFloat32FPCompareGE(SoftFloat32.FPCompareGE);
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGE)));
|
||||||
var dlgSoftFloat32FPCompareGEFpscr = new SoftFloat32FPCompareGEFpscr(SoftFloat32.FPCompareGEFpscr); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGEFpscr))); // A32 only.
|
||||||
var dlgSoftFloat32FPCompareGT = new SoftFloat32FPCompareGT(SoftFloat32.FPCompareGT);
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGT)));
|
||||||
var dlgSoftFloat32FPCompareGTFpscr = new SoftFloat32FPCompareGTFpscr(SoftFloat32.FPCompareGTFpscr); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGTFpscr))); // A32 only.
|
||||||
var dlgSoftFloat32FPCompareLE = new SoftFloat32FPCompareLE(SoftFloat32.FPCompareLE);
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLE)));
|
||||||
var dlgSoftFloat32FPCompareLEFpscr = new SoftFloat32FPCompareLEFpscr(SoftFloat32.FPCompareLEFpscr); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLEFpscr))); // A32 only.
|
||||||
var dlgSoftFloat32FPCompareLT = new SoftFloat32FPCompareLT(SoftFloat32.FPCompareLT);
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLT)));
|
||||||
var dlgSoftFloat32FPCompareLTFpscr = new SoftFloat32FPCompareLTFpscr(SoftFloat32.FPCompareLTFpscr); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLTFpscr))); // A32 only.
|
||||||
var dlgSoftFloat32FPDiv = new SoftFloat32FPDiv(SoftFloat32.FPDiv);
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPDiv)));
|
||||||
var dlgSoftFloat32FPMax = new SoftFloat32FPMax(SoftFloat32.FPMax);
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMax)));
|
||||||
var dlgSoftFloat32FPMaxFpscr = new SoftFloat32FPMaxFpscr(SoftFloat32.FPMaxFpscr); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxFpscr))); // A32 only.
|
||||||
var dlgSoftFloat32FPMaxNum = new SoftFloat32FPMaxNum(SoftFloat32.FPMaxNum);
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxNum)));
|
||||||
var dlgSoftFloat32FPMaxNumFpscr = new SoftFloat32FPMaxNumFpscr(SoftFloat32.FPMaxNumFpscr); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxNumFpscr))); // A32 only.
|
||||||
var dlgSoftFloat32FPMin = new SoftFloat32FPMin(SoftFloat32.FPMin);
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMin)));
|
||||||
var dlgSoftFloat32FPMinFpscr = new SoftFloat32FPMinFpscr(SoftFloat32.FPMinFpscr); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinFpscr))); // A32 only.
|
||||||
var dlgSoftFloat32FPMinNum = new SoftFloat32FPMinNum(SoftFloat32.FPMinNum);
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinNum)));
|
||||||
var dlgSoftFloat32FPMinNumFpscr = new SoftFloat32FPMinNumFpscr(SoftFloat32.FPMinNumFpscr); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinNumFpscr))); // A32 only.
|
||||||
var dlgSoftFloat32FPMul = new SoftFloat32FPMul(SoftFloat32.FPMul);
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMul)));
|
||||||
var dlgSoftFloat32FPMulFpscr = new SoftFloat32FPMulFpscr(SoftFloat32.FPMulFpscr); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulFpscr))); // A32 only.
|
||||||
var dlgSoftFloat32FPMulAdd = new SoftFloat32FPMulAdd(SoftFloat32.FPMulAdd);
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulAdd)));
|
||||||
var dlgSoftFloat32FPMulAddFpscr = new SoftFloat32FPMulAddFpscr(SoftFloat32.FPMulAddFpscr); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulAddFpscr))); // A32 only.
|
||||||
var dlgSoftFloat32FPMulSub = new SoftFloat32FPMulSub(SoftFloat32.FPMulSub);
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulSub)));
|
||||||
var dlgSoftFloat32FPMulSubFpscr = new SoftFloat32FPMulSubFpscr(SoftFloat32.FPMulSubFpscr); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulSubFpscr))); // A32 only.
|
||||||
var dlgSoftFloat32FPMulX = new SoftFloat32FPMulX(SoftFloat32.FPMulX);
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulX)));
|
||||||
var dlgSoftFloat32FPNegMulAdd = new SoftFloat32FPNegMulAdd(SoftFloat32.FPNegMulAdd);
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPNegMulAdd)));
|
||||||
var dlgSoftFloat32FPNegMulSub = new SoftFloat32FPNegMulSub(SoftFloat32.FPNegMulSub);
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPNegMulSub)));
|
||||||
var dlgSoftFloat32FPRecipEstimate = new SoftFloat32FPRecipEstimate(SoftFloat32.FPRecipEstimate);
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipEstimate)));
|
||||||
var dlgSoftFloat32FPRecipEstimateFpscr = new SoftFloat32FPRecipEstimateFpscr(SoftFloat32.FPRecipEstimateFpscr); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipEstimateFpscr))); // A32 only.
|
||||||
var dlgSoftFloat32FPRecipStep = new SoftFloat32FPRecipStep(SoftFloat32.FPRecipStep); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipStep))); // A32 only.
|
||||||
var dlgSoftFloat32FPRecipStepFused = new SoftFloat32FPRecipStepFused(SoftFloat32.FPRecipStepFused);
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipStepFused)));
|
||||||
var dlgSoftFloat32FPRecpX = new SoftFloat32FPRecpX(SoftFloat32.FPRecpX);
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecpX)));
|
||||||
var dlgSoftFloat32FPRSqrtEstimate = new SoftFloat32FPRSqrtEstimate(SoftFloat32.FPRSqrtEstimate);
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtEstimate)));
|
||||||
var dlgSoftFloat32FPRSqrtEstimateFpscr = new SoftFloat32FPRSqrtEstimateFpscr(SoftFloat32.FPRSqrtEstimateFpscr); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtEstimateFpscr))); // A32 only.
|
||||||
var dlgSoftFloat32FPRSqrtStep = new SoftFloat32FPRSqrtStep(SoftFloat32.FPRSqrtStep); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtStep))); // A32 only.
|
||||||
var dlgSoftFloat32FPRSqrtStepFused = new SoftFloat32FPRSqrtStepFused(SoftFloat32.FPRSqrtStepFused);
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtStepFused)));
|
||||||
var dlgSoftFloat32FPSqrt = new SoftFloat32FPSqrt(SoftFloat32.FPSqrt);
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPSqrt)));
|
||||||
var dlgSoftFloat32FPSub = new SoftFloat32FPSub(SoftFloat32.FPSub);
|
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPSub)));
|
||||||
|
|
||||||
var dlgSoftFloat32_16FPConvert = new SoftFloat32_16FPConvert(SoftFloat32_16.FPConvert);
|
SetDelegateInfo(typeof(SoftFloat32_16).GetMethod(nameof(SoftFloat32_16.FPConvert)));
|
||||||
|
|
||||||
var dlgSoftFloat64FPAdd = new SoftFloat64FPAdd(SoftFloat64.FPAdd);
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPAdd)));
|
||||||
var dlgSoftFloat64FPAddFpscr = new SoftFloat64FPAddFpscr(SoftFloat64.FPAddFpscr); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPAddFpscr))); // A32 only.
|
||||||
var dlgSoftFloat64FPCompare = new SoftFloat64FPCompare(SoftFloat64.FPCompare);
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompare)));
|
||||||
var dlgSoftFloat64FPCompareEQ = new SoftFloat64FPCompareEQ(SoftFloat64.FPCompareEQ);
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareEQ)));
|
||||||
var dlgSoftFloat64FPCompareEQFpscr = new SoftFloat64FPCompareEQFpscr(SoftFloat64.FPCompareEQFpscr); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareEQFpscr))); // A32 only.
|
||||||
var dlgSoftFloat64FPCompareGE = new SoftFloat64FPCompareGE(SoftFloat64.FPCompareGE);
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGE)));
|
||||||
var dlgSoftFloat64FPCompareGEFpscr = new SoftFloat64FPCompareGEFpscr(SoftFloat64.FPCompareGEFpscr); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGEFpscr))); // A32 only.
|
||||||
var dlgSoftFloat64FPCompareGT = new SoftFloat64FPCompareGT(SoftFloat64.FPCompareGT);
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGT)));
|
||||||
var dlgSoftFloat64FPCompareGTFpscr = new SoftFloat64FPCompareGTFpscr(SoftFloat64.FPCompareGTFpscr); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGTFpscr))); // A32 only.
|
||||||
var dlgSoftFloat64FPCompareLE = new SoftFloat64FPCompareLE(SoftFloat64.FPCompareLE);
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLE)));
|
||||||
var dlgSoftFloat64FPCompareLEFpscr = new SoftFloat64FPCompareLEFpscr(SoftFloat64.FPCompareLEFpscr); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLEFpscr))); // A32 only.
|
||||||
var dlgSoftFloat64FPCompareLT = new SoftFloat64FPCompareLT(SoftFloat64.FPCompareLT);
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLT)));
|
||||||
var dlgSoftFloat64FPCompareLTFpscr = new SoftFloat64FPCompareLTFpscr(SoftFloat64.FPCompareLTFpscr); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLTFpscr))); // A32 only.
|
||||||
var dlgSoftFloat64FPDiv = new SoftFloat64FPDiv(SoftFloat64.FPDiv);
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPDiv)));
|
||||||
var dlgSoftFloat64FPMax = new SoftFloat64FPMax(SoftFloat64.FPMax);
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMax)));
|
||||||
var dlgSoftFloat64FPMaxFpscr = new SoftFloat64FPMaxFpscr(SoftFloat64.FPMaxFpscr); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMaxFpscr))); // A32 only.
|
||||||
var dlgSoftFloat64FPMaxNum = new SoftFloat64FPMaxNum(SoftFloat64.FPMaxNum);
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMaxNum)));
|
||||||
var dlgSoftFloat64FPMaxNumFpscr = new SoftFloat64FPMaxNumFpscr(SoftFloat64.FPMaxNumFpscr); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMaxNumFpscr))); // A32 only.
|
||||||
var dlgSoftFloat64FPMin = new SoftFloat64FPMin(SoftFloat64.FPMin);
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMin)));
|
||||||
var dlgSoftFloat64FPMinFpscr = new SoftFloat64FPMinFpscr(SoftFloat64.FPMinFpscr); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMinFpscr))); // A32 only.
|
||||||
var dlgSoftFloat64FPMinNum = new SoftFloat64FPMinNum(SoftFloat64.FPMinNum);
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMinNum)));
|
||||||
var dlgSoftFloat64FPMinNumFpscr = new SoftFloat64FPMinNumFpscr(SoftFloat64.FPMinNumFpscr); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMinNumFpscr))); // A32 only.
|
||||||
var dlgSoftFloat64FPMul = new SoftFloat64FPMul(SoftFloat64.FPMul);
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMul)));
|
||||||
var dlgSoftFloat64FPMulFpscr = new SoftFloat64FPMulFpscr(SoftFloat64.FPMulFpscr); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulFpscr))); // A32 only.
|
||||||
var dlgSoftFloat64FPMulAdd = new SoftFloat64FPMulAdd(SoftFloat64.FPMulAdd);
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulAdd)));
|
||||||
var dlgSoftFloat64FPMulAddFpscr = new SoftFloat64FPMulAddFpscr(SoftFloat64.FPMulAddFpscr); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulAddFpscr))); // A32 only.
|
||||||
var dlgSoftFloat64FPMulSub = new SoftFloat64FPMulSub(SoftFloat64.FPMulSub);
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulSub)));
|
||||||
var dlgSoftFloat64FPMulSubFpscr = new SoftFloat64FPMulSubFpscr(SoftFloat64.FPMulSubFpscr); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulSubFpscr))); // A32 only.
|
||||||
var dlgSoftFloat64FPMulX = new SoftFloat64FPMulX(SoftFloat64.FPMulX);
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulX)));
|
||||||
var dlgSoftFloat64FPNegMulAdd = new SoftFloat64FPNegMulAdd(SoftFloat64.FPNegMulAdd);
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPNegMulAdd)));
|
||||||
var dlgSoftFloat64FPNegMulSub = new SoftFloat64FPNegMulSub(SoftFloat64.FPNegMulSub);
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPNegMulSub)));
|
||||||
var dlgSoftFloat64FPRecipEstimate = new SoftFloat64FPRecipEstimate(SoftFloat64.FPRecipEstimate);
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipEstimate)));
|
||||||
var dlgSoftFloat64FPRecipEstimateFpscr = new SoftFloat64FPRecipEstimateFpscr(SoftFloat64.FPRecipEstimateFpscr); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipEstimateFpscr))); // A32 only.
|
||||||
var dlgSoftFloat64FPRecipStep = new SoftFloat64FPRecipStep(SoftFloat64.FPRecipStep); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipStep))); // A32 only.
|
||||||
var dlgSoftFloat64FPRecipStepFused = new SoftFloat64FPRecipStepFused(SoftFloat64.FPRecipStepFused);
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipStepFused)));
|
||||||
var dlgSoftFloat64FPRecpX = new SoftFloat64FPRecpX(SoftFloat64.FPRecpX);
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecpX)));
|
||||||
var dlgSoftFloat64FPRSqrtEstimate = new SoftFloat64FPRSqrtEstimate(SoftFloat64.FPRSqrtEstimate);
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtEstimate)));
|
||||||
var dlgSoftFloat64FPRSqrtEstimateFpscr = new SoftFloat64FPRSqrtEstimateFpscr(SoftFloat64.FPRSqrtEstimateFpscr); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtEstimateFpscr))); // A32 only.
|
||||||
var dlgSoftFloat64FPRSqrtStep = new SoftFloat64FPRSqrtStep(SoftFloat64.FPRSqrtStep); // A32 only.
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtStep))); // A32 only.
|
||||||
var dlgSoftFloat64FPRSqrtStepFused = new SoftFloat64FPRSqrtStepFused(SoftFloat64.FPRSqrtStepFused);
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtStepFused)));
|
||||||
var dlgSoftFloat64FPSqrt = new SoftFloat64FPSqrt(SoftFloat64.FPSqrt);
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPSqrt)));
|
||||||
var dlgSoftFloat64FPSub = new SoftFloat64FPSub(SoftFloat64.FPSub);
|
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPSub)));
|
||||||
|
|
||||||
var dlgSoftFloat64_16FPConvert = new SoftFloat64_16FPConvert(SoftFloat64_16.FPConvert);
|
SetDelegateInfo(typeof(SoftFloat64_16).GetMethod(nameof(SoftFloat64_16.FPConvert)));
|
||||||
|
|
||||||
SetDelegateInfo(dlgMathAbs, Marshal.GetFunctionPointerForDelegate<MathAbs>(dlgMathAbs));
|
|
||||||
SetDelegateInfo(dlgMathCeiling, Marshal.GetFunctionPointerForDelegate<MathCeiling>(dlgMathCeiling));
|
|
||||||
SetDelegateInfo(dlgMathFloor, Marshal.GetFunctionPointerForDelegate<MathFloor>(dlgMathFloor));
|
|
||||||
SetDelegateInfo(dlgMathRound, Marshal.GetFunctionPointerForDelegate<MathRound>(dlgMathRound));
|
|
||||||
SetDelegateInfo(dlgMathTruncate, Marshal.GetFunctionPointerForDelegate<MathTruncate>(dlgMathTruncate));
|
|
||||||
|
|
||||||
SetDelegateInfo(dlgMathFAbs, Marshal.GetFunctionPointerForDelegate<MathFAbs>(dlgMathFAbs));
|
|
||||||
SetDelegateInfo(dlgMathFCeiling, Marshal.GetFunctionPointerForDelegate<MathFCeiling>(dlgMathFCeiling));
|
|
||||||
SetDelegateInfo(dlgMathFFloor, Marshal.GetFunctionPointerForDelegate<MathFFloor>(dlgMathFFloor));
|
|
||||||
SetDelegateInfo(dlgMathFRound, Marshal.GetFunctionPointerForDelegate<MathFRound>(dlgMathFRound));
|
|
||||||
SetDelegateInfo(dlgMathFTruncate, Marshal.GetFunctionPointerForDelegate<MathFTruncate>(dlgMathFTruncate));
|
|
||||||
|
|
||||||
SetDelegateInfo(dlgNativeInterfaceBreak, Marshal.GetFunctionPointerForDelegate<NativeInterfaceBreak>(dlgNativeInterfaceBreak));
|
|
||||||
SetDelegateInfo(dlgNativeInterfaceCheckSynchronization, Marshal.GetFunctionPointerForDelegate<NativeInterfaceCheckSynchronization>(dlgNativeInterfaceCheckSynchronization));
|
|
||||||
SetDelegateInfo(dlgNativeInterfaceEnqueueForRejit, Marshal.GetFunctionPointerForDelegate<NativeInterfaceEnqueueForRejit>(dlgNativeInterfaceEnqueueForRejit));
|
|
||||||
SetDelegateInfo(dlgNativeInterfaceGetCntfrqEl0, Marshal.GetFunctionPointerForDelegate<NativeInterfaceGetCntfrqEl0>(dlgNativeInterfaceGetCntfrqEl0));
|
|
||||||
SetDelegateInfo(dlgNativeInterfaceGetCntpctEl0, Marshal.GetFunctionPointerForDelegate<NativeInterfaceGetCntpctEl0>(dlgNativeInterfaceGetCntpctEl0));
|
|
||||||
SetDelegateInfo(dlgNativeInterfaceGetCntvctEl0, Marshal.GetFunctionPointerForDelegate<NativeInterfaceGetCntvctEl0>(dlgNativeInterfaceGetCntvctEl0));
|
|
||||||
SetDelegateInfo(dlgNativeInterfaceGetCtrEl0, Marshal.GetFunctionPointerForDelegate<NativeInterfaceGetCtrEl0>(dlgNativeInterfaceGetCtrEl0));
|
|
||||||
SetDelegateInfo(dlgNativeInterfaceGetDczidEl0, Marshal.GetFunctionPointerForDelegate<NativeInterfaceGetDczidEl0>(dlgNativeInterfaceGetDczidEl0));
|
|
||||||
SetDelegateInfo(dlgNativeInterfaceGetFunctionAddress, Marshal.GetFunctionPointerForDelegate<NativeInterfaceGetFunctionAddress>(dlgNativeInterfaceGetFunctionAddress));
|
|
||||||
SetDelegateInfo(dlgNativeInterfaceInvalidateCacheLine, Marshal.GetFunctionPointerForDelegate<NativeInterfaceInvalidateCacheLine>(dlgNativeInterfaceInvalidateCacheLine));
|
|
||||||
SetDelegateInfo(dlgNativeInterfaceReadByte, Marshal.GetFunctionPointerForDelegate<NativeInterfaceReadByte>(dlgNativeInterfaceReadByte));
|
|
||||||
SetDelegateInfo(dlgNativeInterfaceReadUInt16, Marshal.GetFunctionPointerForDelegate<NativeInterfaceReadUInt16>(dlgNativeInterfaceReadUInt16));
|
|
||||||
SetDelegateInfo(dlgNativeInterfaceReadUInt32, Marshal.GetFunctionPointerForDelegate<NativeInterfaceReadUInt32>(dlgNativeInterfaceReadUInt32));
|
|
||||||
SetDelegateInfo(dlgNativeInterfaceReadUInt64, Marshal.GetFunctionPointerForDelegate<NativeInterfaceReadUInt64>(dlgNativeInterfaceReadUInt64));
|
|
||||||
SetDelegateInfo(dlgNativeInterfaceReadVector128, Marshal.GetFunctionPointerForDelegate<NativeInterfaceReadVector128>(dlgNativeInterfaceReadVector128));
|
|
||||||
SetDelegateInfo(dlgNativeInterfaceSignalMemoryTracking, Marshal.GetFunctionPointerForDelegate<NativeInterfaceSignalMemoryTracking>(dlgNativeInterfaceSignalMemoryTracking));
|
|
||||||
SetDelegateInfo(dlgNativeInterfaceSupervisorCall, Marshal.GetFunctionPointerForDelegate<NativeInterfaceSupervisorCall>(dlgNativeInterfaceSupervisorCall));
|
|
||||||
SetDelegateInfo(dlgNativeInterfaceThrowInvalidMemoryAccess, Marshal.GetFunctionPointerForDelegate<NativeInterfaceThrowInvalidMemoryAccess>(dlgNativeInterfaceThrowInvalidMemoryAccess));
|
|
||||||
SetDelegateInfo(dlgNativeInterfaceUndefined, Marshal.GetFunctionPointerForDelegate<NativeInterfaceUndefined>(dlgNativeInterfaceUndefined));
|
|
||||||
SetDelegateInfo(dlgNativeInterfaceWriteByte, Marshal.GetFunctionPointerForDelegate<NativeInterfaceWriteByte>(dlgNativeInterfaceWriteByte));
|
|
||||||
SetDelegateInfo(dlgNativeInterfaceWriteUInt16, Marshal.GetFunctionPointerForDelegate<NativeInterfaceWriteUInt16>(dlgNativeInterfaceWriteUInt16));
|
|
||||||
SetDelegateInfo(dlgNativeInterfaceWriteUInt32, Marshal.GetFunctionPointerForDelegate<NativeInterfaceWriteUInt32>(dlgNativeInterfaceWriteUInt32));
|
|
||||||
SetDelegateInfo(dlgNativeInterfaceWriteUInt64, Marshal.GetFunctionPointerForDelegate<NativeInterfaceWriteUInt64>(dlgNativeInterfaceWriteUInt64));
|
|
||||||
SetDelegateInfo(dlgNativeInterfaceWriteVector128, Marshal.GetFunctionPointerForDelegate<NativeInterfaceWriteVector128>(dlgNativeInterfaceWriteVector128));
|
|
||||||
|
|
||||||
SetDelegateInfo(dlgSoftFallbackCountLeadingSigns, Marshal.GetFunctionPointerForDelegate<SoftFallbackCountLeadingSigns>(dlgSoftFallbackCountLeadingSigns));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackCountLeadingZeros, Marshal.GetFunctionPointerForDelegate<SoftFallbackCountLeadingZeros>(dlgSoftFallbackCountLeadingZeros));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackCrc32b, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32b>(dlgSoftFallbackCrc32b));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackCrc32cb, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32cb>(dlgSoftFallbackCrc32cb));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackCrc32ch, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32ch>(dlgSoftFallbackCrc32ch));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackCrc32cw, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32cw>(dlgSoftFallbackCrc32cw));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackCrc32cx, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32cx>(dlgSoftFallbackCrc32cx));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackCrc32h, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32h>(dlgSoftFallbackCrc32h));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackCrc32w, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32w>(dlgSoftFallbackCrc32w));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackCrc32x, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32x>(dlgSoftFallbackCrc32x));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackDecrypt, Marshal.GetFunctionPointerForDelegate<SoftFallbackDecrypt>(dlgSoftFallbackDecrypt));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackEncrypt, Marshal.GetFunctionPointerForDelegate<SoftFallbackEncrypt>(dlgSoftFallbackEncrypt));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackFixedRotate, Marshal.GetFunctionPointerForDelegate<SoftFallbackFixedRotate>(dlgSoftFallbackFixedRotate));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackHashChoose, Marshal.GetFunctionPointerForDelegate<SoftFallbackHashChoose>(dlgSoftFallbackHashChoose));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackHashLower, Marshal.GetFunctionPointerForDelegate<SoftFallbackHashLower>(dlgSoftFallbackHashLower));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackHashMajority, Marshal.GetFunctionPointerForDelegate<SoftFallbackHashMajority>(dlgSoftFallbackHashMajority));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackHashParity, Marshal.GetFunctionPointerForDelegate<SoftFallbackHashParity>(dlgSoftFallbackHashParity));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackHashUpper, Marshal.GetFunctionPointerForDelegate<SoftFallbackHashUpper>(dlgSoftFallbackHashUpper));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackInverseMixColumns, Marshal.GetFunctionPointerForDelegate<SoftFallbackInverseMixColumns>(dlgSoftFallbackInverseMixColumns));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackMixColumns, Marshal.GetFunctionPointerForDelegate<SoftFallbackMixColumns>(dlgSoftFallbackMixColumns));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackPolynomialMult64_128, Marshal.GetFunctionPointerForDelegate<SoftFallbackPolynomialMult64_128>(dlgSoftFallbackPolynomialMult64_128));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackSatF32ToS32, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF32ToS32>(dlgSoftFallbackSatF32ToS32));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackSatF32ToS64, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF32ToS64>(dlgSoftFallbackSatF32ToS64));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackSatF32ToU32, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF32ToU32>(dlgSoftFallbackSatF32ToU32));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackSatF32ToU64, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF32ToU64>(dlgSoftFallbackSatF32ToU64));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackSatF64ToS32, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF64ToS32>(dlgSoftFallbackSatF64ToS32));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackSatF64ToS64, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF64ToS64>(dlgSoftFallbackSatF64ToS64));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackSatF64ToU32, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF64ToU32>(dlgSoftFallbackSatF64ToU32));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackSatF64ToU64, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF64ToU64>(dlgSoftFallbackSatF64ToU64));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackSha1SchedulePart1, Marshal.GetFunctionPointerForDelegate<SoftFallbackSha1SchedulePart1>(dlgSoftFallbackSha1SchedulePart1));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackSha1SchedulePart2, Marshal.GetFunctionPointerForDelegate<SoftFallbackSha1SchedulePart2>(dlgSoftFallbackSha1SchedulePart2));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackSha256SchedulePart1, Marshal.GetFunctionPointerForDelegate<SoftFallbackSha256SchedulePart1>(dlgSoftFallbackSha256SchedulePart1));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackSha256SchedulePart2, Marshal.GetFunctionPointerForDelegate<SoftFallbackSha256SchedulePart2>(dlgSoftFallbackSha256SchedulePart2));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackSignedShrImm64, Marshal.GetFunctionPointerForDelegate<SoftFallbackSignedShrImm64>(dlgSoftFallbackSignedShrImm64));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackTbl1, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbl1>(dlgSoftFallbackTbl1));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackTbl2, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbl2>(dlgSoftFallbackTbl2));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackTbl3, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbl3>(dlgSoftFallbackTbl3));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackTbl4, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbl4>(dlgSoftFallbackTbl4));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackTbx1, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbx1>(dlgSoftFallbackTbx1));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackTbx2, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbx2>(dlgSoftFallbackTbx2));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackTbx3, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbx3>(dlgSoftFallbackTbx3));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackTbx4, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbx4>(dlgSoftFallbackTbx4));
|
|
||||||
SetDelegateInfo(dlgSoftFallbackUnsignedShrImm64, Marshal.GetFunctionPointerForDelegate<SoftFallbackUnsignedShrImm64>(dlgSoftFallbackUnsignedShrImm64));
|
|
||||||
|
|
||||||
SetDelegateInfo(dlgSoftFloat16_32FPConvert, Marshal.GetFunctionPointerForDelegate<SoftFloat16_32FPConvert>(dlgSoftFloat16_32FPConvert));
|
|
||||||
SetDelegateInfo(dlgSoftFloat16_64FPConvert, Marshal.GetFunctionPointerForDelegate<SoftFloat16_64FPConvert>(dlgSoftFloat16_64FPConvert));
|
|
||||||
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPAdd, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPAdd>(dlgSoftFloat32FPAdd));
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPAddFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPAddFpscr>(dlgSoftFloat32FPAddFpscr)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPCompare, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompare>(dlgSoftFloat32FPCompare));
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPCompareEQ, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareEQ>(dlgSoftFloat32FPCompareEQ));
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPCompareEQFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareEQFpscr>(dlgSoftFloat32FPCompareEQFpscr)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPCompareGE, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareGE>(dlgSoftFloat32FPCompareGE));
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPCompareGEFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareGEFpscr>(dlgSoftFloat32FPCompareGEFpscr)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPCompareGT, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareGT>(dlgSoftFloat32FPCompareGT));
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPCompareGTFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareGTFpscr>(dlgSoftFloat32FPCompareGTFpscr)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPCompareLE, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareLE>(dlgSoftFloat32FPCompareLE));
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPCompareLEFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareLEFpscr>(dlgSoftFloat32FPCompareLEFpscr)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPCompareLT, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareLT>(dlgSoftFloat32FPCompareLT));
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPCompareLTFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareLTFpscr>(dlgSoftFloat32FPCompareLTFpscr)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPDiv, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPDiv>(dlgSoftFloat32FPDiv));
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPMax, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMax>(dlgSoftFloat32FPMax));
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPMaxFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMaxFpscr>(dlgSoftFloat32FPMaxFpscr)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPMaxNum, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMaxNum>(dlgSoftFloat32FPMaxNum));
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPMaxNumFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMaxNumFpscr>(dlgSoftFloat32FPMaxNumFpscr)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPMin, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMin>(dlgSoftFloat32FPMin));
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPMinFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMinFpscr>(dlgSoftFloat32FPMinFpscr)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPMinNum, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMinNum>(dlgSoftFloat32FPMinNum));
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPMinNumFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMinNumFpscr>(dlgSoftFloat32FPMinNumFpscr)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPMul, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMul>(dlgSoftFloat32FPMul));
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPMulFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMulFpscr>(dlgSoftFloat32FPMulFpscr)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPMulAdd, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMulAdd>(dlgSoftFloat32FPMulAdd));
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPMulAddFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMulAddFpscr>(dlgSoftFloat32FPMulAddFpscr)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPMulSub, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMulSub>(dlgSoftFloat32FPMulSub));
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPMulSubFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMulSubFpscr>(dlgSoftFloat32FPMulSubFpscr)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPMulX, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMulX>(dlgSoftFloat32FPMulX));
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPNegMulAdd, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPNegMulAdd>(dlgSoftFloat32FPNegMulAdd));
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPNegMulSub, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPNegMulSub>(dlgSoftFloat32FPNegMulSub));
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPRecipEstimate, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRecipEstimate>(dlgSoftFloat32FPRecipEstimate));
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPRecipEstimateFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRecipEstimateFpscr>(dlgSoftFloat32FPRecipEstimateFpscr)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPRecipStep, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRecipStep>(dlgSoftFloat32FPRecipStep)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPRecipStepFused, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRecipStepFused>(dlgSoftFloat32FPRecipStepFused));
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPRecpX, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRecpX>(dlgSoftFloat32FPRecpX));
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPRSqrtEstimate, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRSqrtEstimate>(dlgSoftFloat32FPRSqrtEstimate));
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPRSqrtEstimateFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRSqrtEstimateFpscr>(dlgSoftFloat32FPRSqrtEstimateFpscr)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPRSqrtStep, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRSqrtStep>(dlgSoftFloat32FPRSqrtStep)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPRSqrtStepFused, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRSqrtStepFused>(dlgSoftFloat32FPRSqrtStepFused));
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPSqrt, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPSqrt>(dlgSoftFloat32FPSqrt));
|
|
||||||
SetDelegateInfo(dlgSoftFloat32FPSub, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPSub>(dlgSoftFloat32FPSub));
|
|
||||||
|
|
||||||
SetDelegateInfo(dlgSoftFloat32_16FPConvert, Marshal.GetFunctionPointerForDelegate<SoftFloat32_16FPConvert>(dlgSoftFloat32_16FPConvert));
|
|
||||||
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPAdd, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPAdd>(dlgSoftFloat64FPAdd));
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPAddFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPAddFpscr>(dlgSoftFloat64FPAddFpscr)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPCompare, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompare>(dlgSoftFloat64FPCompare));
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPCompareEQ, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareEQ>(dlgSoftFloat64FPCompareEQ));
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPCompareEQFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareEQFpscr>(dlgSoftFloat64FPCompareEQFpscr)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPCompareGE, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareGE>(dlgSoftFloat64FPCompareGE));
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPCompareGEFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareGEFpscr>(dlgSoftFloat64FPCompareGEFpscr)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPCompareGT, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareGT>(dlgSoftFloat64FPCompareGT));
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPCompareGTFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareGTFpscr>(dlgSoftFloat64FPCompareGTFpscr)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPCompareLE, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareLE>(dlgSoftFloat64FPCompareLE));
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPCompareLEFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareLEFpscr>(dlgSoftFloat64FPCompareLEFpscr)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPCompareLT, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareLT>(dlgSoftFloat64FPCompareLT));
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPCompareLTFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareLTFpscr>(dlgSoftFloat64FPCompareLTFpscr)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPDiv, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPDiv>(dlgSoftFloat64FPDiv));
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPMax, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMax>(dlgSoftFloat64FPMax));
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPMaxFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMaxFpscr>(dlgSoftFloat64FPMaxFpscr)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPMaxNum, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMaxNum>(dlgSoftFloat64FPMaxNum));
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPMaxNumFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMaxNumFpscr>(dlgSoftFloat64FPMaxNumFpscr)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPMin, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMin>(dlgSoftFloat64FPMin));
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPMinFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMinFpscr>(dlgSoftFloat64FPMinFpscr)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPMinNum, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMinNum>(dlgSoftFloat64FPMinNum));
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPMinNumFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMinNumFpscr>(dlgSoftFloat64FPMinNumFpscr)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPMul, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMul>(dlgSoftFloat64FPMul));
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPMulFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMulFpscr>(dlgSoftFloat64FPMulFpscr)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPMulAdd, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMulAdd>(dlgSoftFloat64FPMulAdd));
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPMulAddFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMulAddFpscr>(dlgSoftFloat64FPMulAddFpscr)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPMulSub, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMulSub>(dlgSoftFloat64FPMulSub));
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPMulSubFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMulSubFpscr>(dlgSoftFloat64FPMulSubFpscr)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPMulX, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMulX>(dlgSoftFloat64FPMulX));
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPNegMulAdd, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPNegMulAdd>(dlgSoftFloat64FPNegMulAdd));
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPNegMulSub, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPNegMulSub>(dlgSoftFloat64FPNegMulSub));
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPRecipEstimate, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRecipEstimate>(dlgSoftFloat64FPRecipEstimate));
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPRecipEstimateFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRecipEstimateFpscr>(dlgSoftFloat64FPRecipEstimateFpscr)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPRecipStep, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRecipStep>(dlgSoftFloat64FPRecipStep)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPRecipStepFused, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRecipStepFused>(dlgSoftFloat64FPRecipStepFused));
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPRecpX, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRecpX>(dlgSoftFloat64FPRecpX));
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPRSqrtEstimate, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRSqrtEstimate>(dlgSoftFloat64FPRSqrtEstimate));
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPRSqrtEstimateFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRSqrtEstimateFpscr>(dlgSoftFloat64FPRSqrtEstimateFpscr)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPRSqrtStep, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRSqrtStep>(dlgSoftFloat64FPRSqrtStep)); // A32 only.
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPRSqrtStepFused, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRSqrtStepFused>(dlgSoftFloat64FPRSqrtStepFused));
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPSqrt, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPSqrt>(dlgSoftFloat64FPSqrt));
|
|
||||||
SetDelegateInfo(dlgSoftFloat64FPSub, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPSub>(dlgSoftFloat64FPSub));
|
|
||||||
|
|
||||||
SetDelegateInfo(dlgSoftFloat64_16FPConvert, Marshal.GetFunctionPointerForDelegate<SoftFloat64_16FPConvert>(dlgSoftFloat64_16FPConvert));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private delegate double MathAbs(double value);
|
|
||||||
private delegate double MathCeiling(double a);
|
|
||||||
private delegate double MathFloor(double d);
|
|
||||||
private delegate double MathRound(double value, MidpointRounding mode);
|
|
||||||
private delegate double MathTruncate(double d);
|
|
||||||
|
|
||||||
private delegate float MathFAbs(float x);
|
|
||||||
private delegate float MathFCeiling(float x);
|
|
||||||
private delegate float MathFFloor(float x);
|
|
||||||
private delegate float MathFRound(float x, MidpointRounding mode);
|
|
||||||
private delegate float MathFTruncate(float x);
|
|
||||||
|
|
||||||
private delegate void NativeInterfaceBreak(ulong address, int imm);
|
|
||||||
private delegate bool NativeInterfaceCheckSynchronization();
|
|
||||||
private delegate void NativeInterfaceEnqueueForRejit(ulong address);
|
|
||||||
private delegate ulong NativeInterfaceGetCntfrqEl0();
|
|
||||||
private delegate ulong NativeInterfaceGetCntpctEl0();
|
|
||||||
private delegate ulong NativeInterfaceGetCntvctEl0();
|
|
||||||
private delegate ulong NativeInterfaceGetCtrEl0();
|
|
||||||
private delegate ulong NativeInterfaceGetDczidEl0();
|
|
||||||
private delegate ulong NativeInterfaceGetFunctionAddress(ulong address);
|
|
||||||
private delegate void NativeInterfaceInvalidateCacheLine(ulong address);
|
|
||||||
private delegate byte NativeInterfaceReadByte(ulong address);
|
|
||||||
private delegate ushort NativeInterfaceReadUInt16(ulong address);
|
|
||||||
private delegate uint NativeInterfaceReadUInt32(ulong address);
|
|
||||||
private delegate ulong NativeInterfaceReadUInt64(ulong address);
|
|
||||||
private delegate V128 NativeInterfaceReadVector128(ulong address);
|
|
||||||
private delegate void NativeInterfaceSignalMemoryTracking(ulong address, ulong size, bool write);
|
|
||||||
private delegate void NativeInterfaceSupervisorCall(ulong address, int imm);
|
|
||||||
private delegate void NativeInterfaceThrowInvalidMemoryAccess(ulong address);
|
|
||||||
private delegate void NativeInterfaceUndefined(ulong address, int opCode);
|
|
||||||
private delegate void NativeInterfaceWriteByte(ulong address, byte value);
|
|
||||||
private delegate void NativeInterfaceWriteUInt16(ulong address, ushort value);
|
|
||||||
private delegate void NativeInterfaceWriteUInt32(ulong address, uint value);
|
|
||||||
private delegate void NativeInterfaceWriteUInt64(ulong address, ulong value);
|
|
||||||
private delegate void NativeInterfaceWriteVector128(ulong address, V128 value);
|
|
||||||
|
|
||||||
private delegate ulong SoftFallbackCountLeadingSigns(ulong value, int size);
|
|
||||||
private delegate ulong SoftFallbackCountLeadingZeros(ulong value, int size);
|
|
||||||
private delegate uint SoftFallbackCrc32b(uint crc, byte value);
|
|
||||||
private delegate uint SoftFallbackCrc32cb(uint crc, byte value);
|
|
||||||
private delegate uint SoftFallbackCrc32ch(uint crc, ushort value);
|
|
||||||
private delegate uint SoftFallbackCrc32cw(uint crc, uint value);
|
|
||||||
private delegate uint SoftFallbackCrc32cx(uint crc, ulong value);
|
|
||||||
private delegate uint SoftFallbackCrc32h(uint crc, ushort value);
|
|
||||||
private delegate uint SoftFallbackCrc32w(uint crc, uint value);
|
|
||||||
private delegate uint SoftFallbackCrc32x(uint crc, ulong value);
|
|
||||||
private delegate V128 SoftFallbackDecrypt(V128 value, V128 roundKey);
|
|
||||||
private delegate V128 SoftFallbackEncrypt(V128 value, V128 roundKey);
|
|
||||||
private delegate uint SoftFallbackFixedRotate(uint hash_e);
|
|
||||||
private delegate V128 SoftFallbackHashChoose(V128 hash_abcd, uint hash_e, V128 wk);
|
|
||||||
private delegate V128 SoftFallbackHashLower(V128 hash_abcd, V128 hash_efgh, V128 wk);
|
|
||||||
private delegate V128 SoftFallbackHashMajority(V128 hash_abcd, uint hash_e, V128 wk);
|
|
||||||
private delegate V128 SoftFallbackHashParity(V128 hash_abcd, uint hash_e, V128 wk);
|
|
||||||
private delegate V128 SoftFallbackHashUpper(V128 hash_abcd, V128 hash_efgh, V128 wk);
|
|
||||||
private delegate V128 SoftFallbackInverseMixColumns(V128 value);
|
|
||||||
private delegate V128 SoftFallbackMixColumns(V128 value);
|
|
||||||
private delegate V128 SoftFallbackPolynomialMult64_128(ulong op1, ulong op2);
|
|
||||||
private delegate int SoftFallbackSatF32ToS32(float value);
|
|
||||||
private delegate long SoftFallbackSatF32ToS64(float value);
|
|
||||||
private delegate uint SoftFallbackSatF32ToU32(float value);
|
|
||||||
private delegate ulong SoftFallbackSatF32ToU64(float value);
|
|
||||||
private delegate int SoftFallbackSatF64ToS32(double value);
|
|
||||||
private delegate long SoftFallbackSatF64ToS64(double value);
|
|
||||||
private delegate uint SoftFallbackSatF64ToU32(double value);
|
|
||||||
private delegate ulong SoftFallbackSatF64ToU64(double value);
|
|
||||||
private delegate V128 SoftFallbackSha1SchedulePart1(V128 w0_3, V128 w4_7, V128 w8_11);
|
|
||||||
private delegate V128 SoftFallbackSha1SchedulePart2(V128 tw0_3, V128 w12_15);
|
|
||||||
private delegate V128 SoftFallbackSha256SchedulePart1(V128 w0_3, V128 w4_7);
|
|
||||||
private delegate V128 SoftFallbackSha256SchedulePart2(V128 w0_3, V128 w8_11, V128 w12_15);
|
|
||||||
private delegate long SoftFallbackSignedShrImm64(long value, long roundConst, int shift);
|
|
||||||
private delegate V128 SoftFallbackTbl1(V128 vector, int bytes, V128 tb0);
|
|
||||||
private delegate V128 SoftFallbackTbl2(V128 vector, int bytes, V128 tb0, V128 tb1);
|
|
||||||
private delegate V128 SoftFallbackTbl3(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2);
|
|
||||||
private delegate V128 SoftFallbackTbl4(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3);
|
|
||||||
private delegate V128 SoftFallbackTbx1(V128 dest, V128 vector, int bytes, V128 tb0);
|
|
||||||
private delegate V128 SoftFallbackTbx2(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1);
|
|
||||||
private delegate V128 SoftFallbackTbx3(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2);
|
|
||||||
private delegate V128 SoftFallbackTbx4(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3);
|
|
||||||
private delegate ulong SoftFallbackUnsignedShrImm64(ulong value, long roundConst, int shift);
|
|
||||||
|
|
||||||
private delegate float SoftFloat16_32FPConvert(ushort valueBits);
|
|
||||||
|
|
||||||
private delegate double SoftFloat16_64FPConvert(ushort valueBits);
|
|
||||||
|
|
||||||
private delegate float SoftFloat32FPAdd(float value1, float value2);
|
|
||||||
private delegate float SoftFloat32FPAddFpscr(float value1, float value2, bool standardFpscr);
|
|
||||||
private delegate int SoftFloat32FPCompare(float value1, float value2, bool signalNaNs);
|
|
||||||
private delegate float SoftFloat32FPCompareEQ(float value1, float value2);
|
|
||||||
private delegate float SoftFloat32FPCompareEQFpscr(float value1, float value2, bool standardFpscr);
|
|
||||||
private delegate float SoftFloat32FPCompareGE(float value1, float value2);
|
|
||||||
private delegate float SoftFloat32FPCompareGEFpscr(float value1, float value2, bool standardFpscr);
|
|
||||||
private delegate float SoftFloat32FPCompareGT(float value1, float value2);
|
|
||||||
private delegate float SoftFloat32FPCompareGTFpscr(float value1, float value2, bool standardFpscr);
|
|
||||||
private delegate float SoftFloat32FPCompareLE(float value1, float value2);
|
|
||||||
private delegate float SoftFloat32FPCompareLEFpscr(float value1, float value2, bool standardFpscr);
|
|
||||||
private delegate float SoftFloat32FPCompareLT(float value1, float value2);
|
|
||||||
private delegate float SoftFloat32FPCompareLTFpscr(float value1, float value2, bool standardFpscr);
|
|
||||||
private delegate float SoftFloat32FPDiv(float value1, float value2);
|
|
||||||
private delegate float SoftFloat32FPMax(float value1, float value2);
|
|
||||||
private delegate float SoftFloat32FPMaxFpscr(float value1, float value2, bool standardFpscr);
|
|
||||||
private delegate float SoftFloat32FPMaxNum(float value1, float value2);
|
|
||||||
private delegate float SoftFloat32FPMaxNumFpscr(float value1, float value2, bool standardFpscr);
|
|
||||||
private delegate float SoftFloat32FPMin(float value1, float value2);
|
|
||||||
private delegate float SoftFloat32FPMinFpscr(float value1, float value2, bool standardFpscr);
|
|
||||||
private delegate float SoftFloat32FPMinNum(float value1, float value2);
|
|
||||||
private delegate float SoftFloat32FPMinNumFpscr(float value1, float value2, bool standardFpscr);
|
|
||||||
private delegate float SoftFloat32FPMul(float value1, float value2);
|
|
||||||
private delegate float SoftFloat32FPMulFpscr(float value1, float value2, bool standardFpscr);
|
|
||||||
private delegate float SoftFloat32FPMulAdd(float valueA, float value1, float value2);
|
|
||||||
private delegate float SoftFloat32FPMulAddFpscr(float valueA, float value1, float value2, bool standardFpscr);
|
|
||||||
private delegate float SoftFloat32FPMulSub(float valueA, float value1, float value2);
|
|
||||||
private delegate float SoftFloat32FPMulSubFpscr(float valueA, float value1, float value2, bool standardFpscr);
|
|
||||||
private delegate float SoftFloat32FPMulX(float value1, float value2);
|
|
||||||
private delegate float SoftFloat32FPNegMulAdd(float valueA, float value1, float value2);
|
|
||||||
private delegate float SoftFloat32FPNegMulSub(float valueA, float value1, float value2);
|
|
||||||
private delegate float SoftFloat32FPRecipEstimate(float value);
|
|
||||||
private delegate float SoftFloat32FPRecipEstimateFpscr(float value, bool standardFpscr);
|
|
||||||
private delegate float SoftFloat32FPRecipStep(float value1, float value2);
|
|
||||||
private delegate float SoftFloat32FPRecipStepFused(float value1, float value2);
|
|
||||||
private delegate float SoftFloat32FPRecpX(float value);
|
|
||||||
private delegate float SoftFloat32FPRSqrtEstimate(float value);
|
|
||||||
private delegate float SoftFloat32FPRSqrtEstimateFpscr(float value, bool standardFpscr);
|
|
||||||
private delegate float SoftFloat32FPRSqrtStep(float value1, float value2);
|
|
||||||
private delegate float SoftFloat32FPRSqrtStepFused(float value1, float value2);
|
|
||||||
private delegate float SoftFloat32FPSqrt(float value);
|
|
||||||
private delegate float SoftFloat32FPSub(float value1, float value2);
|
|
||||||
|
|
||||||
private delegate ushort SoftFloat32_16FPConvert(float value);
|
|
||||||
|
|
||||||
private delegate double SoftFloat64FPAdd(double value1, double value2);
|
|
||||||
private delegate double SoftFloat64FPAddFpscr(double value1, double value2, bool standardFpscr);
|
|
||||||
private delegate int SoftFloat64FPCompare(double value1, double value2, bool signalNaNs);
|
|
||||||
private delegate double SoftFloat64FPCompareEQ(double value1, double value2);
|
|
||||||
private delegate double SoftFloat64FPCompareEQFpscr(double value1, double value2, bool standardFpscr);
|
|
||||||
private delegate double SoftFloat64FPCompareGE(double value1, double value2);
|
|
||||||
private delegate double SoftFloat64FPCompareGEFpscr(double value1, double value2, bool standardFpscr);
|
|
||||||
private delegate double SoftFloat64FPCompareGT(double value1, double value2);
|
|
||||||
private delegate double SoftFloat64FPCompareGTFpscr(double value1, double value2, bool standardFpscr);
|
|
||||||
private delegate double SoftFloat64FPCompareLE(double value1, double value2);
|
|
||||||
private delegate double SoftFloat64FPCompareLEFpscr(double value1, double value2, bool standardFpscr);
|
|
||||||
private delegate double SoftFloat64FPCompareLT(double value1, double value2);
|
|
||||||
private delegate double SoftFloat64FPCompareLTFpscr(double value1, double value2, bool standardFpscr);
|
|
||||||
private delegate double SoftFloat64FPDiv(double value1, double value2);
|
|
||||||
private delegate double SoftFloat64FPMax(double value1, double value2);
|
|
||||||
private delegate double SoftFloat64FPMaxFpscr(double value1, double value2, bool standardFpscr);
|
|
||||||
private delegate double SoftFloat64FPMaxNum(double value1, double value2);
|
|
||||||
private delegate double SoftFloat64FPMaxNumFpscr(double value1, double value2, bool standardFpscr);
|
|
||||||
private delegate double SoftFloat64FPMin(double value1, double value2);
|
|
||||||
private delegate double SoftFloat64FPMinFpscr(double value1, double value2, bool standardFpscr);
|
|
||||||
private delegate double SoftFloat64FPMinNum(double value1, double value2);
|
|
||||||
private delegate double SoftFloat64FPMinNumFpscr(double value1, double value2, bool standardFpscr);
|
|
||||||
private delegate double SoftFloat64FPMul(double value1, double value2);
|
|
||||||
private delegate double SoftFloat64FPMulFpscr(double value1, double value2, bool standardFpscr);
|
|
||||||
private delegate double SoftFloat64FPMulAdd(double valueA, double value1, double value2);
|
|
||||||
private delegate double SoftFloat64FPMulAddFpscr(double valueA, double value1, double value2, bool standardFpscr);
|
|
||||||
private delegate double SoftFloat64FPMulSub(double valueA, double value1, double value2);
|
|
||||||
private delegate double SoftFloat64FPMulSubFpscr(double valueA, double value1, double value2, bool standardFpscr);
|
|
||||||
private delegate double SoftFloat64FPMulX(double value1, double value2);
|
|
||||||
private delegate double SoftFloat64FPNegMulAdd(double valueA, double value1, double value2);
|
|
||||||
private delegate double SoftFloat64FPNegMulSub(double valueA, double value1, double value2);
|
|
||||||
private delegate double SoftFloat64FPRecipEstimate(double value);
|
|
||||||
private delegate double SoftFloat64FPRecipEstimateFpscr(double value, bool standardFpscr);
|
|
||||||
private delegate double SoftFloat64FPRecipStep(double value1, double value2);
|
|
||||||
private delegate double SoftFloat64FPRecipStepFused(double value1, double value2);
|
|
||||||
private delegate double SoftFloat64FPRecpX(double value);
|
|
||||||
private delegate double SoftFloat64FPRSqrtEstimate(double value);
|
|
||||||
private delegate double SoftFloat64FPRSqrtEstimateFpscr(double value, bool standardFpscr);
|
|
||||||
private delegate double SoftFloat64FPRSqrtStep(double value1, double value2);
|
|
||||||
private delegate double SoftFloat64FPRSqrtStepFused(double value1, double value2);
|
|
||||||
private delegate double SoftFloat64FPSqrt(double value);
|
|
||||||
private delegate double SoftFloat64FPSub(double value1, double value2);
|
|
||||||
|
|
||||||
private delegate ushort SoftFloat64_16FPConvert(double value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -97,7 +97,7 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
public virtual Operand Call(MethodInfo info, params Operand[] callArgs)
|
public virtual Operand Call(MethodInfo info, params Operand[] callArgs)
|
||||||
{
|
{
|
||||||
nint funcPtr = Delegates.GetDelegateFuncPtr(info);
|
nint funcPtr = info.MethodHandle.GetFunctionPointer();
|
||||||
|
|
||||||
OperandType returnType = GetOperandType(info.ReturnType);
|
OperandType returnType = GetOperandType(info.ReturnType);
|
||||||
|
|
||||||
|
@@ -29,8 +29,8 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
{
|
{
|
||||||
private const string OuterHeaderMagicString = "PTCohd\0\0";
|
private const string OuterHeaderMagicString = "PTCohd\0\0";
|
||||||
private const string InnerHeaderMagicString = "PTCihd\0\0";
|
private const string InnerHeaderMagicString = "PTCihd\0\0";
|
||||||
|
|
||||||
private const uint InternalVersion = 6997; //! To be incremented manually for each change to the ARMeilleure project.
|
private const uint InternalVersion = 6998; //! To be incremented manually for each change to the ARMeilleure project.
|
||||||
|
|
||||||
private const string ActualDir = "0";
|
private const string ActualDir = "0";
|
||||||
private const string BackupDir = "1";
|
private const string BackupDir = "1";
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
|
using Humanizer;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
@@ -58,8 +59,8 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
{
|
{
|
||||||
_ptc = ptc;
|
_ptc = ptc;
|
||||||
|
|
||||||
_timer = new Timer(SaveInterval * 1000d);
|
_timer = new Timer(SaveInterval.Seconds());
|
||||||
_timer.Elapsed += PreSave;
|
_timer.Elapsed += TimerElapsed;
|
||||||
|
|
||||||
_outerHeaderMagic = BinaryPrimitives.ReadUInt64LittleEndian(EncodingCache.UTF8NoBOM.GetBytes(OuterHeaderMagicString).AsSpan());
|
_outerHeaderMagic = BinaryPrimitives.ReadUInt64LittleEndian(EncodingCache.UTF8NoBOM.GetBytes(OuterHeaderMagicString).AsSpan());
|
||||||
|
|
||||||
@@ -72,6 +73,9 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
Enabled = false;
|
Enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void TimerElapsed(object _, ElapsedEventArgs __)
|
||||||
|
=> new Thread(PreSave) { Name = "Ptc.DiskWriter" }.Start();
|
||||||
|
|
||||||
public void AddEntry(ulong address, ExecutionMode mode, bool highCq)
|
public void AddEntry(ulong address, ExecutionMode mode, bool highCq)
|
||||||
{
|
{
|
||||||
if (IsAddressInStaticCodeRange(address))
|
if (IsAddressInStaticCodeRange(address))
|
||||||
@@ -262,7 +266,7 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
compressedStream.SetLength(0L);
|
compressedStream.SetLength(0L);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PreSave(object source, ElapsedEventArgs e)
|
private void PreSave()
|
||||||
{
|
{
|
||||||
_waitEvent.Reset();
|
_waitEvent.Reset();
|
||||||
|
|
||||||
@@ -428,7 +432,7 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
{
|
{
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
|
|
||||||
_timer.Elapsed -= PreSave;
|
_timer.Elapsed -= TimerElapsed;
|
||||||
_timer.Dispose();
|
_timer.Dispose();
|
||||||
|
|
||||||
Wait();
|
Wait();
|
||||||
|
@@ -9,20 +9,12 @@ namespace Ryujinx.Audio.Backends.Dummy
|
|||||||
{
|
{
|
||||||
public class DummyHardwareDeviceDriver : IHardwareDeviceDriver
|
public class DummyHardwareDeviceDriver : IHardwareDeviceDriver
|
||||||
{
|
{
|
||||||
private readonly ManualResetEvent _updateRequiredEvent;
|
private readonly ManualResetEvent _updateRequiredEvent = new(false);
|
||||||
private readonly ManualResetEvent _pauseEvent;
|
private readonly ManualResetEvent _pauseEvent = new(true);
|
||||||
|
|
||||||
public static bool IsSupported => true;
|
public static bool IsSupported => true;
|
||||||
|
|
||||||
public float Volume { get; set; }
|
public float Volume { get; set; } = 1f;
|
||||||
|
|
||||||
public DummyHardwareDeviceDriver()
|
|
||||||
{
|
|
||||||
_updateRequiredEvent = new ManualResetEvent(false);
|
|
||||||
_pauseEvent = new ManualResetEvent(true);
|
|
||||||
|
|
||||||
Volume = 1f;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount)
|
public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount)
|
||||||
{
|
{
|
||||||
@@ -60,7 +52,7 @@ namespace Ryujinx.Audio.Backends.Dummy
|
|||||||
Dispose(true);
|
Dispose(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
private void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
|
7
src/Ryujinx.BuildValidationTasks/IValidationTask.cs
Normal file
7
src/Ryujinx.BuildValidationTasks/IValidationTask.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Ryujinx.BuildValidationTasks
|
||||||
|
{
|
||||||
|
public interface IValidationTask
|
||||||
|
{
|
||||||
|
public bool Execute(string projectPath, bool isGitRunner);
|
||||||
|
}
|
||||||
|
}
|
@@ -1,76 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.Build.Utilities;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.IO;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Microsoft.Build.Framework;
|
|
||||||
|
|
||||||
namespace Ryujinx.BuildValidationTasks
|
|
||||||
{
|
|
||||||
public class LocaleValidationTask : Task
|
|
||||||
{
|
|
||||||
public override bool Execute()
|
|
||||||
{
|
|
||||||
string path = System.Reflection.Assembly.GetExecutingAssembly().Location;
|
|
||||||
|
|
||||||
if (path.Split(new string[] { "src" }, StringSplitOptions.None).Length == 1 )
|
|
||||||
{
|
|
||||||
//i assume that we are in a build directory in the solution dir
|
|
||||||
path = new FileInfo(path).Directory.Parent.GetDirectories("src")[0].GetDirectories("Ryujinx")[0].GetDirectories("Assets")[0].GetFiles("locales.json")[0].FullName;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
path = path.Split(new string[] { "src" }, StringSplitOptions.None)[0];
|
|
||||||
path = new FileInfo(path).Directory.GetDirectories("src")[0].GetDirectories("Ryujinx")[0].GetDirectories("Assets")[0].GetFiles("locales.json")[0].FullName;
|
|
||||||
}
|
|
||||||
|
|
||||||
string data;
|
|
||||||
|
|
||||||
using (StreamReader sr = new StreamReader(path))
|
|
||||||
{
|
|
||||||
data = sr.ReadToEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
LocalesJson json = JsonConvert.DeserializeObject<LocalesJson>(data);
|
|
||||||
|
|
||||||
for (int i = 0; i < json.Locales.Count; i++)
|
|
||||||
{
|
|
||||||
LocalesEntry locale = json.Locales[i];
|
|
||||||
|
|
||||||
foreach (string language in json.Languages)
|
|
||||||
{
|
|
||||||
if (!locale.Translations.ContainsKey(language))
|
|
||||||
{
|
|
||||||
locale.Translations.Add(language, "");
|
|
||||||
Log.LogMessage(MessageImportance.High, $"Added {{{language}}} to Locale {{{locale.ID}}}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
locale.Translations = locale.Translations.OrderBy(pair => pair.Key).ToDictionary(pair => pair.Key, pair => pair.Value);
|
|
||||||
json.Locales[i] = locale;
|
|
||||||
}
|
|
||||||
|
|
||||||
string jsonString = JsonConvert.SerializeObject(json, Formatting.Indented);
|
|
||||||
|
|
||||||
using (StreamWriter sw = new StreamWriter(path))
|
|
||||||
{
|
|
||||||
sw.Write(jsonString);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct LocalesJson
|
|
||||||
{
|
|
||||||
public List<string> Languages { get; set; }
|
|
||||||
public List<LocalesEntry> Locales { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
struct LocalesEntry
|
|
||||||
{
|
|
||||||
public string ID { get; set; }
|
|
||||||
public Dictionary<string, string> Translations { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
117
src/Ryujinx.BuildValidationTasks/LocalesValidationTask.cs
Normal file
117
src/Ryujinx.BuildValidationTasks/LocalesValidationTask.cs
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Encodings.Web;
|
||||||
|
|
||||||
|
namespace Ryujinx.BuildValidationTasks
|
||||||
|
{
|
||||||
|
public class LocalesValidationTask : IValidationTask
|
||||||
|
{
|
||||||
|
public LocalesValidationTask() { }
|
||||||
|
|
||||||
|
public bool Execute(string projectPath, bool isGitRunner)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Running Locale Validation Task...");
|
||||||
|
|
||||||
|
string path = projectPath + "src/Ryujinx/Assets/locales.json";
|
||||||
|
string data;
|
||||||
|
|
||||||
|
using (StreamReader sr = new(path))
|
||||||
|
{
|
||||||
|
data = sr.ReadToEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalesJson json;
|
||||||
|
|
||||||
|
if (isGitRunner && data.Contains("\r\n"))
|
||||||
|
throw new FormatException("locales.json is using CRLF line endings! It should be using LF line endings, build locally to fix...");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
json = JsonSerializer.Deserialize<LocalesJson>(data);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (JsonException e)
|
||||||
|
{
|
||||||
|
throw new JsonException(e.Message); //shorter and easier stacktrace
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool encounteredIssue = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < json.Locales.Count; i++)
|
||||||
|
{
|
||||||
|
LocalesEntry locale = json.Locales[i];
|
||||||
|
|
||||||
|
foreach (string langCode in json.Languages.Where(lang => !locale.Translations.ContainsKey(lang)))
|
||||||
|
{
|
||||||
|
encounteredIssue = true;
|
||||||
|
|
||||||
|
if (!isGitRunner)
|
||||||
|
{
|
||||||
|
locale.Translations.Add(langCode, string.Empty);
|
||||||
|
Console.WriteLine($"Added '{langCode}' to Locale '{locale.ID}'");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Missing '{langCode}' in Locale '{locale.ID}'!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string langCode in json.Languages.Where(lang => locale.Translations.ContainsKey(lang) && lang != "en_US" && locale.Translations[lang] == locale.Translations["en_US"]))
|
||||||
|
{
|
||||||
|
encounteredIssue = true;
|
||||||
|
|
||||||
|
if (!isGitRunner)
|
||||||
|
{
|
||||||
|
locale.Translations[langCode] = string.Empty;
|
||||||
|
Console.WriteLine($"Lanugage '{langCode}' is a duplicate of en_US in Locale '{locale.ID}'! Resetting it...");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Lanugage '{langCode}' is a duplicate of en_US in Locale '{locale.ID}'!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
locale.Translations = locale.Translations.OrderBy(pair => pair.Key).ToDictionary(pair => pair.Key, pair => pair.Value);
|
||||||
|
json.Locales[i] = locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isGitRunner && encounteredIssue)
|
||||||
|
throw new JsonException("1 or more locales are invalid!");
|
||||||
|
|
||||||
|
JsonSerializerOptions jsonOptions = new JsonSerializerOptions()
|
||||||
|
{
|
||||||
|
WriteIndented = true,
|
||||||
|
NewLine = "\n",
|
||||||
|
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
|
||||||
|
};
|
||||||
|
|
||||||
|
string jsonString = JsonSerializer.Serialize(json, jsonOptions);
|
||||||
|
|
||||||
|
using (StreamWriter sw = new(path))
|
||||||
|
{
|
||||||
|
sw.Write(jsonString);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("Finished Locale Validation Task!");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LocalesJson
|
||||||
|
{
|
||||||
|
public List<string> Languages { get; set; }
|
||||||
|
public List<LocalesEntry> Locales { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LocalesEntry
|
||||||
|
{
|
||||||
|
public string ID { get; set; }
|
||||||
|
public Dictionary<string, string> Translations { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
37
src/Ryujinx.BuildValidationTasks/Program.cs
Normal file
37
src/Ryujinx.BuildValidationTasks/Program.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Ryujinx.BuildValidationTasks
|
||||||
|
{
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
// Display the number of command line arguments.
|
||||||
|
if (args.Length == 0)
|
||||||
|
throw new ArgumentException("Error: too few arguments!");
|
||||||
|
|
||||||
|
string path = args[0];
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(path))
|
||||||
|
throw new ArgumentException("Error: path is null or empty!");
|
||||||
|
|
||||||
|
if (!Path.Exists(path))
|
||||||
|
throw new FileLoadException($"path {{{path}}} does not exist!");
|
||||||
|
|
||||||
|
path = Path.GetFullPath(path);
|
||||||
|
|
||||||
|
if (!Directory.GetDirectories(path).Contains($"{path}src"))
|
||||||
|
throw new FileLoadException($"path {{{path}}} is not a valid ryujinx project!");
|
||||||
|
|
||||||
|
bool isGitRunner = path.Contains("runner") || path.Contains("D:\\a\\Ryujinx\\Ryujinx");
|
||||||
|
if (isGitRunner)
|
||||||
|
Console.WriteLine("Is Git Runner!");
|
||||||
|
|
||||||
|
// Run tasks
|
||||||
|
// Pass extra info needed in the task constructors
|
||||||
|
new LocalesValidationTask().Execute(path, isGitRunner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,19 +1,17 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<OutputType>Exe</OutputType>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<Target Name="PostBuildTarget" AfterTargets="AfterBuild">
|
||||||
<PackageReference Include="Microsoft.Build.Utilities.Core" />
|
<Message Text="Running Validation Project" Importance="high" />
|
||||||
<PackageReference Include="Newtonsoft.Json" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<UsingTask TaskName="Ryujinx.BuildValidationTasks.LocaleValidationTask" TaskFactory="TaskHostFactory" AssemblyFile="$(OutDir)Ryujinx.BuildValidationTasks.dll" />
|
<Exec WorkingDirectory="$(ProjectDir)bin\Debug\$(TargetFramework)\"
|
||||||
|
Command="dotnet Ryujinx.BuildValidationTasks.dll "$(ProjectDir)..\..\\""
|
||||||
<Target Name="LocalesJsonValidation" AfterTargets="AfterRebuild">
|
ConsoleToMsBuild="true"
|
||||||
<LocaleValidationTask />
|
Condition="'$(RuntimeIdentifier)' == ''"
|
||||||
|
/>
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
@@ -35,6 +35,8 @@ namespace Ryujinx.Common.Configuration
|
|||||||
#pragma warning restore IDE0055
|
#pragma warning restore IDE0055
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static float ToFloatY(this AspectRatio aspectRatio)
|
public static float ToFloatY(this AspectRatio aspectRatio)
|
||||||
{
|
{
|
||||||
|
60
src/Ryujinx.Common/Configuration/DirtyHack.cs
Normal file
60
src/Ryujinx.Common/Configuration/DirtyHack.cs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
using Gommon;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Ryujinx.Common.Configuration
|
||||||
|
{
|
||||||
|
[Flags]
|
||||||
|
public enum DirtyHack : byte
|
||||||
|
{
|
||||||
|
Xc2MenuSoftlockFix = 1,
|
||||||
|
ShaderTranslationDelay = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly struct EnabledDirtyHack(DirtyHack hack, int value)
|
||||||
|
{
|
||||||
|
public DirtyHack Hack => hack;
|
||||||
|
public int Value => value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public ulong Pack() => Raw.PackBitFields(PackedFormat);
|
||||||
|
|
||||||
|
public static EnabledDirtyHack Unpack(ulong packedHack)
|
||||||
|
{
|
||||||
|
var unpackedFields = packedHack.UnpackBitFields(PackedFormat);
|
||||||
|
if (unpackedFields is not [var hack, var value])
|
||||||
|
throw new Exception("The unpack operation on the integer resulted in an invalid unpacked result.");
|
||||||
|
|
||||||
|
return new EnabledDirtyHack((DirtyHack)hack, (int)value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private uint[] Raw => [(uint)Hack, (uint)Value.CoerceAtLeast(0)];
|
||||||
|
|
||||||
|
public static readonly byte[] PackedFormat = [8, 32];
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DirtyHacks : Dictionary<DirtyHack, int>
|
||||||
|
{
|
||||||
|
public DirtyHacks(IEnumerable<EnabledDirtyHack> hacks)
|
||||||
|
=> hacks.ForEach(edh => Add(edh.Hack, edh.Value));
|
||||||
|
|
||||||
|
public DirtyHacks(ulong[] packedHacks) : this(packedHacks.Select(EnabledDirtyHack.Unpack)) {}
|
||||||
|
|
||||||
|
public ulong[] PackEntries()
|
||||||
|
=> Entries.Select(it => it.Pack()).ToArray();
|
||||||
|
|
||||||
|
public EnabledDirtyHack[] Entries
|
||||||
|
=> this
|
||||||
|
.Select(it => new EnabledDirtyHack(it.Key, it.Value))
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
public static implicit operator DirtyHacks(EnabledDirtyHack[] hacks) => new(hacks);
|
||||||
|
public static implicit operator DirtyHacks(ulong[] packedHacks) => new(packedHacks);
|
||||||
|
|
||||||
|
public new int this[DirtyHack hack] => TryGetValue(hack, out var value) ? value : -1;
|
||||||
|
|
||||||
|
public bool IsEnabled(DirtyHack hack) => ContainsKey(hack);
|
||||||
|
}
|
||||||
|
}
|
@@ -6,7 +6,9 @@ namespace Ryujinx.Common.Configuration
|
|||||||
[JsonConverter(typeof(TypedStringEnumConverter<GraphicsBackend>))]
|
[JsonConverter(typeof(TypedStringEnumConverter<GraphicsBackend>))]
|
||||||
public enum GraphicsBackend
|
public enum GraphicsBackend
|
||||||
{
|
{
|
||||||
|
Auto,
|
||||||
Vulkan,
|
Vulkan,
|
||||||
OpenGl,
|
OpenGl,
|
||||||
|
Metal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,5 +9,6 @@ namespace Ryujinx.Common.Configuration
|
|||||||
Bilinear,
|
Bilinear,
|
||||||
Nearest,
|
Nearest,
|
||||||
Fsr,
|
Fsr,
|
||||||
|
Area,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,10 +8,10 @@ namespace Ryujinx.Common
|
|||||||
public static class StreamExtensions
|
public static class StreamExtensions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Writes a <see cref="ReadOnlySpan{int}" /> to this stream.
|
/// Writes an int span to this stream.
|
||||||
///
|
///
|
||||||
/// This default implementation converts each buffer value to a stack-allocated
|
/// This default implementation converts each buffer value to a stack-allocated
|
||||||
/// byte array, then writes it to the Stream using <cref="System.Stream.Write(byte[])" />.
|
/// byte array, then writes it to the Stream using <see cref="Stream.Write(ReadOnlySpan{byte})" />.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="stream">The stream to be written to</param>
|
/// <param name="stream">The stream to be written to</param>
|
||||||
/// <param name="buffer">The buffer of values to be written</param>
|
/// <param name="buffer">The buffer of values to be written</param>
|
||||||
|
@@ -3,7 +3,7 @@ using System;
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
namespace Ryujinx.UI.Common.Helper
|
namespace Ryujinx.Common.Helper
|
||||||
{
|
{
|
||||||
public static partial class ConsoleHelper
|
public static partial class ConsoleHelper
|
||||||
{
|
{
|
@@ -8,7 +8,7 @@ using System.Linq;
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
namespace Ryujinx.UI.Common.Helper
|
namespace Ryujinx.Common.Helper
|
||||||
{
|
{
|
||||||
public static partial class FileAssociationHelper
|
public static partial class FileAssociationHelper
|
||||||
{
|
{
|
||||||
@@ -23,7 +23,7 @@ namespace Ryujinx.UI.Common.Helper
|
|||||||
[LibraryImport("shell32.dll", SetLastError = true)]
|
[LibraryImport("shell32.dll", SetLastError = true)]
|
||||||
public static partial void SHChangeNotify(uint wEventId, uint uFlags, nint dwItem1, nint dwItem2);
|
public static partial void SHChangeNotify(uint wEventId, uint uFlags, nint dwItem1, nint dwItem2);
|
||||||
|
|
||||||
public static bool IsTypeAssociationSupported => (OperatingSystem.IsLinux() || OperatingSystem.IsWindows()) && !ReleaseInformation.IsFlatHubBuild;
|
public static bool IsTypeAssociationSupported => (OperatingSystem.IsLinux() || OperatingSystem.IsWindows());
|
||||||
|
|
||||||
public static bool AreMimeTypesRegistered
|
public static bool AreMimeTypesRegistered
|
||||||
{
|
{
|
||||||
@@ -132,7 +132,7 @@ namespace Ryujinx.UI.Common.Helper
|
|||||||
|
|
||||||
if (uninstall)
|
if (uninstall)
|
||||||
{
|
{
|
||||||
// If the types don't already exist, there's nothing to do and we can call this operation successful.
|
// If the types don't already exist, there's nothing to do, and we can call this operation successful.
|
||||||
if (!AreMimeTypesRegisteredWindows())
|
if (!AreMimeTypesRegisteredWindows())
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
@@ -3,7 +3,7 @@ using System.Diagnostics;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
namespace Ryujinx.UI.Common.Helper
|
namespace Ryujinx.Common.Helper
|
||||||
{
|
{
|
||||||
[SupportedOSPlatform("linux")]
|
[SupportedOSPlatform("linux")]
|
||||||
public static class LinuxHelper
|
public static class LinuxHelper
|
@@ -2,7 +2,7 @@ using System;
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
namespace Ryujinx.UI.Common.Helper
|
namespace Ryujinx.Common.Helper
|
||||||
{
|
{
|
||||||
[SupportedOSPlatform("macos")]
|
[SupportedOSPlatform("macos")]
|
||||||
public static partial class ObjectiveC
|
public static partial class ObjectiveC
|
@@ -1,10 +1,11 @@
|
|||||||
|
using Gommon;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Ryujinx.UI.Common.Helper
|
namespace Ryujinx.Common.Helper
|
||||||
{
|
{
|
||||||
public static partial class OpenHelper
|
public static partial class OpenHelper
|
||||||
{
|
{
|
||||||
@@ -34,6 +35,8 @@ namespace Ryujinx.UI.Common.Helper
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void OpenFolder(FilePath path) => OpenFolder(path.Path);
|
||||||
|
|
||||||
public static void LocateFile(string path)
|
public static void LocateFile(string path)
|
||||||
{
|
{
|
||||||
if (File.Exists(path))
|
if (File.Exists(path))
|
@@ -4,6 +4,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
@@ -157,21 +158,16 @@ namespace Ryujinx.Common.Logging
|
|||||||
_time.Restart();
|
_time.Restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ILogTarget GetTarget(string targetName)
|
private static ILogTarget GetTarget(string targetName)
|
||||||
{
|
=> _logTargets.FirstOrDefault(target => target.Name.Equals(targetName));
|
||||||
foreach (var target in _logTargets)
|
|
||||||
{
|
|
||||||
if (target.Name.Equals(targetName))
|
|
||||||
{
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void AddTarget(ILogTarget target)
|
public static void AddTarget(ILogTarget target)
|
||||||
{
|
{
|
||||||
|
if (_logTargets.Any(t => t.Name == target.Name))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_logTargets.Add(target);
|
_logTargets.Add(target);
|
||||||
|
|
||||||
Updated += target.Log;
|
Updated += target.Log;
|
||||||
|
@@ -27,11 +27,7 @@ namespace Ryujinx.Common.Logging.Targets
|
|||||||
|
|
||||||
private readonly int _overflowTimeout;
|
private readonly int _overflowTimeout;
|
||||||
|
|
||||||
string ILogTarget.Name { get => _target.Name; }
|
string ILogTarget.Name => _target.Name;
|
||||||
|
|
||||||
public AsyncLogTargetWrapper(ILogTarget target)
|
|
||||||
: this(target, -1)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public AsyncLogTargetWrapper(ILogTarget target, int queueLimit = -1, AsyncLogTargetOverflowAction overflowAction = AsyncLogTargetOverflowAction.Block)
|
public AsyncLogTargetWrapper(ILogTarget target, int queueLimit = -1, AsyncLogTargetOverflowAction overflowAction = AsyncLogTargetOverflowAction.Block)
|
||||||
{
|
{
|
||||||
|
@@ -53,6 +53,9 @@ namespace Ryujinx.Common
|
|||||||
{
|
{
|
||||||
public static void LogValueChange<T>(LogClass logClass, ReactiveEventArgs<T> eventArgs, string valueName)
|
public static void LogValueChange<T>(LogClass logClass, ReactiveEventArgs<T> eventArgs, string valueName)
|
||||||
{
|
{
|
||||||
|
if (eventArgs.AreValuesEqual)
|
||||||
|
return;
|
||||||
|
|
||||||
string message = string.Create(CultureInfo.InvariantCulture, $"{valueName} set to: {eventArgs.NewValue}");
|
string message = string.Create(CultureInfo.InvariantCulture, $"{valueName} set to: {eventArgs.NewValue}");
|
||||||
|
|
||||||
Logger.Info?.Print(logClass, message);
|
Logger.Info?.Print(logClass, message);
|
||||||
@@ -65,5 +68,22 @@ namespace Ryujinx.Common
|
|||||||
{
|
{
|
||||||
public T OldValue { get; } = oldValue;
|
public T OldValue { get; } = oldValue;
|
||||||
public T NewValue { get; } = newValue;
|
public T NewValue { get; } = newValue;
|
||||||
|
|
||||||
|
public bool AreValuesEqual
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (OldValue == null && NewValue == null)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (OldValue == null && NewValue != null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (OldValue != null && NewValue == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return OldValue!.Equals(NewValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,7 +6,6 @@ namespace Ryujinx.Common
|
|||||||
// DO NOT EDIT, filled by CI
|
// DO NOT EDIT, filled by CI
|
||||||
public static class ReleaseInformation
|
public static class ReleaseInformation
|
||||||
{
|
{
|
||||||
private const string FlatHubChannel = "flathub";
|
|
||||||
private const string CanaryChannel = "canary";
|
private const string CanaryChannel = "canary";
|
||||||
private const string ReleaseChannel = "release";
|
private const string ReleaseChannel = "release";
|
||||||
|
|
||||||
@@ -29,8 +28,6 @@ namespace Ryujinx.Common
|
|||||||
!ReleaseChannelRepo.StartsWith("%%") &&
|
!ReleaseChannelRepo.StartsWith("%%") &&
|
||||||
!ConfigFileName.StartsWith("%%");
|
!ConfigFileName.StartsWith("%%");
|
||||||
|
|
||||||
public static bool IsFlatHubBuild => IsValid && ReleaseChannelOwner.Equals(FlatHubChannel);
|
|
||||||
|
|
||||||
public static bool IsCanaryBuild => IsValid && ReleaseChannelName.Equals(CanaryChannel);
|
public static bool IsCanaryBuild => IsValid && ReleaseChannelName.Equals(CanaryChannel);
|
||||||
|
|
||||||
public static bool IsReleaseBuild => IsValid && ReleaseChannelName.Equals(ReleaseChannel);
|
public static bool IsReleaseBuild => IsValid && ReleaseChannelName.Equals(ReleaseChannel);
|
||||||
|
10
src/Ryujinx.Common/RyujinxException.cs
Normal file
10
src/Ryujinx.Common/RyujinxException.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.Common
|
||||||
|
{
|
||||||
|
public class RyujinxException : Exception
|
||||||
|
{
|
||||||
|
public RyujinxException(string message) : base(message)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
}
|
@@ -1,129 +1,51 @@
|
|||||||
using DiscordRPC;
|
using Gommon;
|
||||||
using Humanizer;
|
using Ryujinx.Common.Configuration;
|
||||||
using Humanizer.Localisation;
|
using System;
|
||||||
using Ryujinx.Common;
|
|
||||||
using Ryujinx.HLE.Loaders.Processes;
|
|
||||||
using Ryujinx.UI.App.Common;
|
|
||||||
using Ryujinx.UI.Common.Configuration;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Ryujinx.UI.Common
|
namespace Ryujinx.Common
|
||||||
{
|
{
|
||||||
public static class DiscordIntegrationModule
|
public static class TitleIDs
|
||||||
{
|
{
|
||||||
public static Timestamps StartedAt { get; set; }
|
public static ReactiveObject<Optional<string>> CurrentApplication { get; set; } = new();
|
||||||
|
|
||||||
private static string VersionString
|
public static GraphicsBackend SelectGraphicsBackend(string titleId, GraphicsBackend currentBackend)
|
||||||
=> (ReleaseInformation.IsCanaryBuild ? "Canary " : string.Empty) + $"v{ReleaseInformation.Version}";
|
|
||||||
|
|
||||||
private static readonly string _description =
|
|
||||||
ReleaseInformation.IsValid
|
|
||||||
? $"{VersionString} {ReleaseInformation.ReleaseChannelOwner}/{ReleaseInformation.ReleaseChannelSourceRepo}@{ReleaseInformation.BuildGitHash}"
|
|
||||||
: "dev build";
|
|
||||||
|
|
||||||
private const string ApplicationId = "1293250299716173864";
|
|
||||||
|
|
||||||
private const int ApplicationByteLimit = 128;
|
|
||||||
private const string Ellipsis = "…";
|
|
||||||
|
|
||||||
private static DiscordRpcClient _discordClient;
|
|
||||||
private static RichPresence _discordPresenceMain;
|
|
||||||
|
|
||||||
public static void Initialize()
|
|
||||||
{
|
{
|
||||||
_discordPresenceMain = new RichPresence
|
switch (currentBackend)
|
||||||
{
|
{
|
||||||
Assets = new Assets
|
case GraphicsBackend.OpenGl when OperatingSystem.IsMacOS():
|
||||||
{
|
return GraphicsBackend.Vulkan;
|
||||||
LargeImageKey = "ryujinx",
|
case GraphicsBackend.Vulkan or GraphicsBackend.OpenGl or GraphicsBackend.Metal:
|
||||||
LargeImageText = TruncateToByteLength(_description)
|
return currentBackend;
|
||||||
},
|
|
||||||
Details = "Main Menu",
|
|
||||||
State = "Idling",
|
|
||||||
Timestamps = StartedAt
|
|
||||||
};
|
|
||||||
|
|
||||||
ConfigurationState.Instance.EnableDiscordIntegration.Event += Update;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void Update(object sender, ReactiveEventArgs<bool> evnt)
|
|
||||||
{
|
|
||||||
if (evnt.OldValue != evnt.NewValue)
|
|
||||||
{
|
|
||||||
// If the integration was active, disable it and unload everything
|
|
||||||
if (evnt.OldValue)
|
|
||||||
{
|
|
||||||
_discordClient?.Dispose();
|
|
||||||
|
|
||||||
_discordClient = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we need to activate it and the client isn't active, initialize it
|
|
||||||
if (evnt.NewValue && _discordClient == null)
|
|
||||||
{
|
|
||||||
_discordClient = new DiscordRpcClient(ApplicationId);
|
|
||||||
|
|
||||||
_discordClient.Initialize();
|
|
||||||
_discordClient.SetPresence(_discordPresenceMain);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SwitchToPlayingState(ApplicationMetadata appMeta, ProcessResult procRes)
|
|
||||||
{
|
|
||||||
_discordClient?.SetPresence(new RichPresence
|
|
||||||
{
|
|
||||||
Assets = new Assets
|
|
||||||
{
|
|
||||||
LargeImageKey = _discordGameAssetKeys.Contains(procRes.ProgramIdText) ? procRes.ProgramIdText : "game",
|
|
||||||
LargeImageText = TruncateToByteLength($"{appMeta.Title} (v{procRes.DisplayVersion})"),
|
|
||||||
SmallImageKey = "ryujinx",
|
|
||||||
SmallImageText = TruncateToByteLength(_description)
|
|
||||||
},
|
|
||||||
Details = TruncateToByteLength($"Playing {appMeta.Title}"),
|
|
||||||
State = appMeta.LastPlayed.HasValue && appMeta.TimePlayed.TotalSeconds > 5
|
|
||||||
? $"Total play time: {appMeta.TimePlayed.Humanize(2, false, maxUnit: TimeUnit.Hour)}"
|
|
||||||
: "Never played",
|
|
||||||
Timestamps = Timestamps.Now
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SwitchToMainState() => _discordClient?.SetPresence(_discordPresenceMain);
|
|
||||||
|
|
||||||
private static string TruncateToByteLength(string input)
|
|
||||||
{
|
|
||||||
if (Encoding.UTF8.GetByteCount(input) <= ApplicationByteLimit)
|
|
||||||
{
|
|
||||||
return input;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the length to trim the string to guarantee we have space for the trailing ellipsis.
|
if (!(OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture is Architecture.Arm64))
|
||||||
int trimLimit = ApplicationByteLimit - Encoding.UTF8.GetByteCount(Ellipsis);
|
return GraphicsBackend.Vulkan;
|
||||||
|
|
||||||
// Make sure the string is long enough to perform the basic trim.
|
return GreatMetalTitles.ContainsIgnoreCase(titleId) ? GraphicsBackend.Metal : GraphicsBackend.Vulkan;
|
||||||
// Amount of bytes != Length of the string
|
|
||||||
if (input.Length > trimLimit)
|
|
||||||
{
|
|
||||||
// Basic trim to best case scenario of 1 byte characters.
|
|
||||||
input = input[..trimLimit];
|
|
||||||
}
|
|
||||||
|
|
||||||
while (Encoding.UTF8.GetByteCount(input) > trimLimit)
|
|
||||||
{
|
|
||||||
// Remove one character from the end of the string at a time.
|
|
||||||
input = input[..^1];
|
|
||||||
}
|
|
||||||
|
|
||||||
return input.TrimEnd() + Ellipsis;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static readonly string[] GreatMetalTitles =
|
||||||
|
[
|
||||||
|
"01006f8002326000", // Animal Crossings: New Horizons
|
||||||
|
"01009bf0072d4000", // Captain Toad: Treasure Tracker
|
||||||
|
"0100a5c00d162000", // Cuphead
|
||||||
|
"010023800d64a000", // Deltarune
|
||||||
|
"010028600EBDA000", // Mario 3D World
|
||||||
|
"0100152000022000", // Mario Kart 8 Deluxe
|
||||||
|
"01005CA01580E000", // Persona 5
|
||||||
|
"0100187003A36000", // Pokémon: Let's Go, Evoli!
|
||||||
|
"010003f003a34000", // Pokémon: Let's Go, Pikachu!
|
||||||
|
"01008C0016544000", // Sea of Stars
|
||||||
|
"01006A800016E000", // Smash Ultimate
|
||||||
|
"0100000000010000", // Super Mario Odyessy
|
||||||
|
];
|
||||||
|
|
||||||
|
public static string GetDiscordGameAsset(string titleId)
|
||||||
|
=> DiscordGameAssetKeys.Contains(titleId) ? titleId : "game";
|
||||||
|
|
||||||
public static void Exit()
|
public static readonly string[] DiscordGameAssetKeys =
|
||||||
{
|
|
||||||
_discordClient?.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static readonly string[] _discordGameAssetKeys =
|
|
||||||
[
|
[
|
||||||
"010055d009f78000", // Fire Emblem: Three Houses
|
"010055d009f78000", // Fire Emblem: Three Houses
|
||||||
"0100a12011cc8000", // Fire Emblem: Shadow Dragon
|
"0100a12011cc8000", // Fire Emblem: Shadow Dragon
|
||||||
@@ -249,6 +171,7 @@ namespace Ryujinx.UI.Common
|
|||||||
"0100b41013c82000", // Cruis'n Blast
|
"0100b41013c82000", // Cruis'n Blast
|
||||||
"01001b300b9be000", // Diablo III: Eternal Collection
|
"01001b300b9be000", // Diablo III: Eternal Collection
|
||||||
"01008c8012920000", // Dying Light Platinum Edition
|
"01008c8012920000", // Dying Light Platinum Edition
|
||||||
|
"01001cc01b2d4000", // Goat Simulator 3
|
||||||
"010073c01af34000", // LEGO Horizon Adventures
|
"010073c01af34000", // LEGO Horizon Adventures
|
||||||
"0100770008dd8000", // Monster Hunter Generations Ultimate
|
"0100770008dd8000", // Monster Hunter Generations Ultimate
|
||||||
"0100b04011742000", // Monster Hunter Rise
|
"0100b04011742000", // Monster Hunter Rise
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Ryujinx.UI.Common
|
namespace Ryujinx.Common.UI
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represent a common error that could be reported to the user by the emulator.
|
/// Represent a common error that could be reported to the user by the emulator.
|
@@ -40,5 +40,35 @@ namespace Ryujinx.Common
|
|||||||
|
|
||||||
return (value >> 32) | (value << 32);
|
return (value >> 32) | (value << 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Never actually written bit packing logic before, so I looked it up.
|
||||||
|
// This code is from https://gist.github.com/Alan-FGR/04938e93e2bffdf5802ceb218a37c195
|
||||||
|
|
||||||
|
public static ulong PackBitFields(this uint[] values, byte[] bitFields)
|
||||||
|
{
|
||||||
|
ulong retVal = values[0]; //we set the first value right away
|
||||||
|
for (int f = 1; f < values.Length; f++)
|
||||||
|
{
|
||||||
|
retVal <<= bitFields[f]; // we shift the previous value
|
||||||
|
retVal += values[f];// and add our current value
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static uint[] UnpackBitFields(this ulong packed, byte[] bitFields)
|
||||||
|
{
|
||||||
|
int fields = bitFields.Length - 1; // number of fields to unpack
|
||||||
|
uint[] retArr = new uint[fields + 1]; // init return array
|
||||||
|
int curPos = 0; // current field bit position (start)
|
||||||
|
int lastEnd; // position where last field ended
|
||||||
|
for (int f = fields; f >= 0; f--) // loop from last
|
||||||
|
{
|
||||||
|
lastEnd = curPos; // we store where the last value ended
|
||||||
|
curPos += bitFields[f]; // we get where the current value starts
|
||||||
|
int leftShift = 64 - curPos; // we figure how much left shift we gotta apply for the other numbers to overflow into oblivion
|
||||||
|
retArr[f] = (uint)((packed << leftShift) >> leftShift + lastEnd); // we do magic
|
||||||
|
}
|
||||||
|
return retArr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
@@ -27,9 +28,14 @@ namespace Ryujinx.Common.Utilities
|
|||||||
ReadCommentHandling = JsonCommentHandling.Skip
|
ReadCommentHandling = JsonCommentHandling.Skip
|
||||||
};
|
};
|
||||||
|
|
||||||
public static string Serialize<T>(T value, JsonTypeInfo<T> typeInfo) => JsonSerializer.Serialize(value, typeInfo);
|
public static string Serialize<T>(T value, JsonTypeInfo<T> typeInfo)
|
||||||
|
=> JsonSerializer.Serialize(value, typeInfo);
|
||||||
|
|
||||||
public static T Deserialize<T>(string value, JsonTypeInfo<T> typeInfo) => JsonSerializer.Deserialize(value, typeInfo);
|
public static T Deserialize<T>(string value, JsonTypeInfo<T> typeInfo)
|
||||||
|
=> JsonSerializer.Deserialize(value, typeInfo);
|
||||||
|
|
||||||
|
public static T Deserialize<T>(ReadOnlySpan<byte> utf8Value, JsonTypeInfo<T> typeInfo)
|
||||||
|
=> JsonSerializer.Deserialize<T>(utf8Value, typeInfo);
|
||||||
|
|
||||||
public static void SerializeToFile<T>(string filePath, T value, JsonTypeInfo<T> typeInfo)
|
public static void SerializeToFile<T>(string filePath, T value, JsonTypeInfo<T> typeInfo)
|
||||||
{
|
{
|
||||||
|
@@ -230,25 +230,20 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
{
|
{
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
{
|
{
|
||||||
return Enumerable.Empty<HostMemoryRange>();
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var guestRegions = GetPhysicalRegionsImpl(va, size);
|
var guestRegions = GetPhysicalRegionsImpl(va, size);
|
||||||
if (guestRegions == null)
|
if (guestRegions == null)
|
||||||
{
|
{
|
||||||
return null;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var regions = new HostMemoryRange[guestRegions.Count];
|
foreach (var guestRegion in guestRegions)
|
||||||
|
|
||||||
for (int i = 0; i < regions.Length; i++)
|
|
||||||
{
|
{
|
||||||
var guestRegion = guestRegions[i];
|
|
||||||
nint pointer = _backingMemory.GetPointer(guestRegion.Address, guestRegion.Size);
|
nint pointer = _backingMemory.GetPointer(guestRegion.Address, guestRegion.Size);
|
||||||
regions[i] = new HostMemoryRange((nuint)(ulong)pointer, guestRegion.Size);
|
yield return new HostMemoryRange((nuint)(ulong)pointer, guestRegion.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return regions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
@@ -256,23 +251,24 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
{
|
{
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
{
|
{
|
||||||
return Enumerable.Empty<MemoryRange>();
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetPhysicalRegionsImpl(va, size);
|
foreach (var physicalRegion in GetPhysicalRegionsImpl(va, size))
|
||||||
|
{
|
||||||
|
yield return physicalRegion;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<MemoryRange> GetPhysicalRegionsImpl(ulong va, ulong size)
|
private IEnumerable<MemoryRange> GetPhysicalRegionsImpl(ulong va, ulong size)
|
||||||
{
|
{
|
||||||
if (!ValidateAddress(va) || !ValidateAddressAndSize(va, size))
|
if (!ValidateAddress(va) || !ValidateAddressAndSize(va, size))
|
||||||
{
|
{
|
||||||
return null;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pages = GetPagesCount(va, (uint)size, out va);
|
int pages = GetPagesCount(va, (uint)size, out va);
|
||||||
|
|
||||||
var regions = new List<MemoryRange>();
|
|
||||||
|
|
||||||
ulong regionStart = GetPhysicalAddressInternal(va);
|
ulong regionStart = GetPhysicalAddressInternal(va);
|
||||||
ulong regionSize = PageSize;
|
ulong regionSize = PageSize;
|
||||||
|
|
||||||
@@ -280,14 +276,14 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
{
|
{
|
||||||
if (!ValidateAddress(va + PageSize))
|
if (!ValidateAddress(va + PageSize))
|
||||||
{
|
{
|
||||||
return null;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong newPa = GetPhysicalAddressInternal(va + PageSize);
|
ulong newPa = GetPhysicalAddressInternal(va + PageSize);
|
||||||
|
|
||||||
if (GetPhysicalAddressInternal(va) + PageSize != newPa)
|
if (GetPhysicalAddressInternal(va) + PageSize != newPa)
|
||||||
{
|
{
|
||||||
regions.Add(new MemoryRange(regionStart, regionSize));
|
yield return new MemoryRange(regionStart, regionSize);
|
||||||
regionStart = newPa;
|
regionStart = newPa;
|
||||||
regionSize = 0;
|
regionSize = 0;
|
||||||
}
|
}
|
||||||
@@ -296,9 +292,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
regionSize += PageSize;
|
regionSize += PageSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
regions.Add(new MemoryRange(regionStart, regionSize));
|
yield return new MemoryRange(regionStart, regionSize);
|
||||||
|
|
||||||
return regions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
|
@@ -115,6 +115,9 @@ namespace Ryujinx.Cpu.Jit.HostTracked
|
|||||||
}
|
}
|
||||||
|
|
||||||
private readonly AddressIntrusiveRedBlackTree<Mapping> _mappingTree;
|
private readonly AddressIntrusiveRedBlackTree<Mapping> _mappingTree;
|
||||||
|
|
||||||
|
// type is not Lock due to the unique usage of this mechanism,
|
||||||
|
// an arbitrary object is used as the lock passed in by constructor.
|
||||||
private readonly object _lock;
|
private readonly object _lock;
|
||||||
|
|
||||||
public Block(MemoryTracking tracking, Func<ulong, ulong> readPtCallback, MemoryBlock memory, ulong size, object locker) : base(memory, size)
|
public Block(MemoryTracking tracking, Func<ulong, ulong> readPtCallback, MemoryBlock memory, ulong size, object locker) : base(memory, size)
|
||||||
@@ -174,6 +177,9 @@ namespace Ryujinx.Cpu.Jit.HostTracked
|
|||||||
|
|
||||||
private readonly MemoryTracking _tracking;
|
private readonly MemoryTracking _tracking;
|
||||||
private readonly Func<ulong, ulong> _readPtCallback;
|
private readonly Func<ulong, ulong> _readPtCallback;
|
||||||
|
|
||||||
|
// type is not Lock due to the unique usage of this mechanism,
|
||||||
|
// an arbitrary object is used as the lock passed in by constructor.
|
||||||
private readonly object _lock;
|
private readonly object _lock;
|
||||||
|
|
||||||
public AddressSpacePartitionAllocator(
|
public AddressSpacePartitionAllocator(
|
||||||
|
@@ -250,25 +250,20 @@ namespace Ryujinx.Cpu.Jit
|
|||||||
{
|
{
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
{
|
{
|
||||||
return Enumerable.Empty<HostMemoryRange>();
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var guestRegions = GetPhysicalRegionsImpl(va, size);
|
var guestRegions = GetPhysicalRegionsImpl(va, size);
|
||||||
if (guestRegions == null)
|
if (guestRegions == null)
|
||||||
{
|
{
|
||||||
return null;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var regions = new HostMemoryRange[guestRegions.Count];
|
foreach (var guestRegion in guestRegions)
|
||||||
|
|
||||||
for (int i = 0; i < regions.Length; i++)
|
|
||||||
{
|
{
|
||||||
var guestRegion = guestRegions[i];
|
|
||||||
nint pointer = _backingMemory.GetPointer(guestRegion.Address, guestRegion.Size);
|
nint pointer = _backingMemory.GetPointer(guestRegion.Address, guestRegion.Size);
|
||||||
regions[i] = new HostMemoryRange((nuint)(ulong)pointer, guestRegion.Size);
|
yield return new HostMemoryRange((nuint)(ulong)pointer, guestRegion.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return regions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
@@ -276,23 +271,24 @@ namespace Ryujinx.Cpu.Jit
|
|||||||
{
|
{
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
{
|
{
|
||||||
return Enumerable.Empty<MemoryRange>();
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetPhysicalRegionsImpl(va, size);
|
foreach (var physicalRegion in GetPhysicalRegionsImpl(va, size))
|
||||||
|
{
|
||||||
|
yield return physicalRegion;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<MemoryRange> GetPhysicalRegionsImpl(ulong va, ulong size)
|
private IEnumerable<MemoryRange> GetPhysicalRegionsImpl(ulong va, ulong size)
|
||||||
{
|
{
|
||||||
if (!ValidateAddress(va) || !ValidateAddressAndSize(va, size))
|
if (!ValidateAddress(va) || !ValidateAddressAndSize(va, size))
|
||||||
{
|
{
|
||||||
return null;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pages = GetPagesCount(va, (uint)size, out va);
|
int pages = GetPagesCount(va, (uint)size, out va);
|
||||||
|
|
||||||
var regions = new List<MemoryRange>();
|
|
||||||
|
|
||||||
ulong regionStart = GetPhysicalAddressInternal(va);
|
ulong regionStart = GetPhysicalAddressInternal(va);
|
||||||
ulong regionSize = PageSize;
|
ulong regionSize = PageSize;
|
||||||
|
|
||||||
@@ -300,14 +296,14 @@ namespace Ryujinx.Cpu.Jit
|
|||||||
{
|
{
|
||||||
if (!ValidateAddress(va + PageSize))
|
if (!ValidateAddress(va + PageSize))
|
||||||
{
|
{
|
||||||
return null;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong newPa = GetPhysicalAddressInternal(va + PageSize);
|
ulong newPa = GetPhysicalAddressInternal(va + PageSize);
|
||||||
|
|
||||||
if (GetPhysicalAddressInternal(va) + PageSize != newPa)
|
if (GetPhysicalAddressInternal(va) + PageSize != newPa)
|
||||||
{
|
{
|
||||||
regions.Add(new MemoryRange(regionStart, regionSize));
|
yield return new MemoryRange(regionStart, regionSize);
|
||||||
regionStart = newPa;
|
regionStart = newPa;
|
||||||
regionSize = 0;
|
regionSize = 0;
|
||||||
}
|
}
|
||||||
@@ -316,9 +312,7 @@ namespace Ryujinx.Cpu.Jit
|
|||||||
regionSize += PageSize;
|
regionSize += PageSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
regions.Add(new MemoryRange(regionStart, regionSize));
|
yield return new MemoryRange(regionStart, regionSize);
|
||||||
|
|
||||||
return regions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
@@ -475,17 +475,15 @@ namespace Ryujinx.Cpu.Jit
|
|||||||
return GetPhysicalRegionsImpl(va, size);
|
return GetPhysicalRegionsImpl(va, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<MemoryRange> GetPhysicalRegionsImpl(ulong va, ulong size)
|
private IEnumerable<MemoryRange> GetPhysicalRegionsImpl(ulong va, ulong size)
|
||||||
{
|
{
|
||||||
if (!ValidateAddress(va) || !ValidateAddressAndSize(va, size))
|
if (!ValidateAddress(va) || !ValidateAddressAndSize(va, size))
|
||||||
{
|
{
|
||||||
return null;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pages = GetPagesCount(va, (uint)size, out va);
|
int pages = GetPagesCount(va, (uint)size, out va);
|
||||||
|
|
||||||
var regions = new List<MemoryRange>();
|
|
||||||
|
|
||||||
ulong regionStart = GetPhysicalAddressInternal(va);
|
ulong regionStart = GetPhysicalAddressInternal(va);
|
||||||
ulong regionSize = PageSize;
|
ulong regionSize = PageSize;
|
||||||
|
|
||||||
@@ -493,14 +491,14 @@ namespace Ryujinx.Cpu.Jit
|
|||||||
{
|
{
|
||||||
if (!ValidateAddress(va + PageSize))
|
if (!ValidateAddress(va + PageSize))
|
||||||
{
|
{
|
||||||
return null;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong newPa = GetPhysicalAddressInternal(va + PageSize);
|
ulong newPa = GetPhysicalAddressInternal(va + PageSize);
|
||||||
|
|
||||||
if (GetPhysicalAddressInternal(va) + PageSize != newPa)
|
if (GetPhysicalAddressInternal(va) + PageSize != newPa)
|
||||||
{
|
{
|
||||||
regions.Add(new MemoryRange(regionStart, regionSize));
|
yield return new MemoryRange(regionStart, regionSize);
|
||||||
regionStart = newPa;
|
regionStart = newPa;
|
||||||
regionSize = 0;
|
regionSize = 0;
|
||||||
}
|
}
|
||||||
@@ -509,9 +507,7 @@ namespace Ryujinx.Cpu.Jit
|
|||||||
regionSize += PageSize;
|
regionSize += PageSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
regions.Add(new MemoryRange(regionStart, regionSize));
|
yield return new MemoryRange(regionStart, regionSize);
|
||||||
|
|
||||||
return regions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
@@ -8,8 +8,6 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
|
|||||||
{
|
{
|
||||||
public IEnumerable<ulong> GetCallStack(nint framePointer, nint codeRegionStart, int codeRegionSize, nint codeRegion2Start, int codeRegion2Size)
|
public IEnumerable<ulong> GetCallStack(nint framePointer, nint codeRegionStart, int codeRegionSize, nint codeRegion2Start, int codeRegion2Size)
|
||||||
{
|
{
|
||||||
List<ulong> functionPointers = new();
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
nint functionPointer = Marshal.ReadIntPtr(framePointer, nint.Size);
|
nint functionPointer = Marshal.ReadIntPtr(framePointer, nint.Size);
|
||||||
@@ -20,11 +18,9 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
functionPointers.Add((ulong)functionPointer - 4);
|
yield return (ulong)functionPointer - 4;
|
||||||
framePointer = Marshal.ReadIntPtr(framePointer);
|
framePointer = Marshal.ReadIntPtr(framePointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return functionPointers;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,12 +0,0 @@
|
|||||||
namespace Ryujinx.Graphics.GAL
|
|
||||||
{
|
|
||||||
public enum AntiAliasing
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
Fxaa,
|
|
||||||
SmaaLow,
|
|
||||||
SmaaMedium,
|
|
||||||
SmaaHigh,
|
|
||||||
SmaaUltra,
|
|
||||||
}
|
|
||||||
}
|
|
18
src/Ryujinx.Graphics.GAL/ComputeSize.cs
Normal file
18
src/Ryujinx.Graphics.GAL/ComputeSize.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
namespace Ryujinx.Graphics.GAL
|
||||||
|
{
|
||||||
|
public readonly struct ComputeSize
|
||||||
|
{
|
||||||
|
public readonly static ComputeSize VtgAsCompute = new ComputeSize(32, 32, 1);
|
||||||
|
|
||||||
|
public readonly int X;
|
||||||
|
public readonly int Y;
|
||||||
|
public readonly int Z;
|
||||||
|
|
||||||
|
public ComputeSize(int x, int y, int z)
|
||||||
|
{
|
||||||
|
X = x;
|
||||||
|
Y = y;
|
||||||
|
Z = z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -339,6 +339,84 @@ namespace Ryujinx.Graphics.GAL
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get bytes per element for this format.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="format">Texture format</param>
|
||||||
|
/// <returns>Byte size for an element of this format (pixel, vertex attribute, etc)</returns>
|
||||||
|
public static int GetBytesPerElement(this Format format)
|
||||||
|
{
|
||||||
|
int scalarSize = format.GetScalarSize();
|
||||||
|
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case Format.R8G8Unorm:
|
||||||
|
case Format.R8G8Snorm:
|
||||||
|
case Format.R8G8Uint:
|
||||||
|
case Format.R8G8Sint:
|
||||||
|
case Format.R8G8Uscaled:
|
||||||
|
case Format.R8G8Sscaled:
|
||||||
|
case Format.R16G16Float:
|
||||||
|
case Format.R16G16Unorm:
|
||||||
|
case Format.R16G16Snorm:
|
||||||
|
case Format.R16G16Uint:
|
||||||
|
case Format.R16G16Sint:
|
||||||
|
case Format.R16G16Uscaled:
|
||||||
|
case Format.R16G16Sscaled:
|
||||||
|
case Format.R32G32Float:
|
||||||
|
case Format.R32G32Uint:
|
||||||
|
case Format.R32G32Sint:
|
||||||
|
case Format.R32G32Uscaled:
|
||||||
|
case Format.R32G32Sscaled:
|
||||||
|
return 2 * scalarSize;
|
||||||
|
|
||||||
|
case Format.R8G8B8Unorm:
|
||||||
|
case Format.R8G8B8Snorm:
|
||||||
|
case Format.R8G8B8Uint:
|
||||||
|
case Format.R8G8B8Sint:
|
||||||
|
case Format.R8G8B8Uscaled:
|
||||||
|
case Format.R8G8B8Sscaled:
|
||||||
|
case Format.R16G16B16Float:
|
||||||
|
case Format.R16G16B16Unorm:
|
||||||
|
case Format.R16G16B16Snorm:
|
||||||
|
case Format.R16G16B16Uint:
|
||||||
|
case Format.R16G16B16Sint:
|
||||||
|
case Format.R16G16B16Uscaled:
|
||||||
|
case Format.R16G16B16Sscaled:
|
||||||
|
case Format.R32G32B32Float:
|
||||||
|
case Format.R32G32B32Uint:
|
||||||
|
case Format.R32G32B32Sint:
|
||||||
|
case Format.R32G32B32Uscaled:
|
||||||
|
case Format.R32G32B32Sscaled:
|
||||||
|
return 3 * scalarSize;
|
||||||
|
|
||||||
|
case Format.R8G8B8A8Unorm:
|
||||||
|
case Format.R8G8B8A8Snorm:
|
||||||
|
case Format.R8G8B8A8Uint:
|
||||||
|
case Format.R8G8B8A8Sint:
|
||||||
|
case Format.R8G8B8A8Srgb:
|
||||||
|
case Format.R8G8B8A8Uscaled:
|
||||||
|
case Format.R8G8B8A8Sscaled:
|
||||||
|
case Format.B8G8R8A8Unorm:
|
||||||
|
case Format.B8G8R8A8Srgb:
|
||||||
|
case Format.R16G16B16A16Float:
|
||||||
|
case Format.R16G16B16A16Unorm:
|
||||||
|
case Format.R16G16B16A16Snorm:
|
||||||
|
case Format.R16G16B16A16Uint:
|
||||||
|
case Format.R16G16B16A16Sint:
|
||||||
|
case Format.R16G16B16A16Uscaled:
|
||||||
|
case Format.R16G16B16A16Sscaled:
|
||||||
|
case Format.R32G32B32A32Float:
|
||||||
|
case Format.R32G32B32A32Uint:
|
||||||
|
case Format.R32G32B32A32Sint:
|
||||||
|
case Format.R32G32B32A32Uscaled:
|
||||||
|
case Format.R32G32B32A32Sscaled:
|
||||||
|
return 4 * scalarSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return scalarSize;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if the texture format is a depth or depth-stencil format.
|
/// Checks if the texture format is a depth or depth-stencil format.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
using Ryujinx.Common.Configuration;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.GAL
|
namespace Ryujinx.Graphics.GAL
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Graphics.GAL.Multithreading.Commands.Window;
|
using Ryujinx.Graphics.GAL.Multithreading.Commands.Window;
|
||||||
using Ryujinx.Graphics.GAL.Multithreading.Model;
|
using Ryujinx.Graphics.GAL.Multithreading.Model;
|
||||||
using Ryujinx.Graphics.GAL.Multithreading.Resources;
|
using Ryujinx.Graphics.GAL.Multithreading.Resources;
|
||||||
|
@@ -4,23 +4,22 @@ namespace Ryujinx.Graphics.GAL
|
|||||||
{
|
{
|
||||||
public int FragmentOutputMap { get; }
|
public int FragmentOutputMap { get; }
|
||||||
public ResourceLayout ResourceLayout { get; }
|
public ResourceLayout ResourceLayout { get; }
|
||||||
|
public ComputeSize ComputeLocalSize { get; }
|
||||||
public ProgramPipelineState? State { get; }
|
public ProgramPipelineState? State { get; }
|
||||||
public bool FromCache { get; set; }
|
public bool FromCache { get; set; }
|
||||||
|
|
||||||
public ShaderInfo(int fragmentOutputMap, ResourceLayout resourceLayout, ProgramPipelineState state, bool fromCache = false)
|
public ShaderInfo(
|
||||||
|
int fragmentOutputMap,
|
||||||
|
ResourceLayout resourceLayout,
|
||||||
|
ComputeSize computeLocalSize,
|
||||||
|
ProgramPipelineState? state,
|
||||||
|
bool fromCache = false)
|
||||||
{
|
{
|
||||||
FragmentOutputMap = fragmentOutputMap;
|
FragmentOutputMap = fragmentOutputMap;
|
||||||
ResourceLayout = resourceLayout;
|
ResourceLayout = resourceLayout;
|
||||||
|
ComputeLocalSize = computeLocalSize;
|
||||||
State = state;
|
State = state;
|
||||||
FromCache = fromCache;
|
FromCache = fromCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ShaderInfo(int fragmentOutputMap, ResourceLayout resourceLayout, bool fromCache = false)
|
|
||||||
{
|
|
||||||
FragmentOutputMap = fragmentOutputMap;
|
|
||||||
ResourceLayout = resourceLayout;
|
|
||||||
State = null;
|
|
||||||
FromCache = fromCache;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,10 +0,0 @@
|
|||||||
namespace Ryujinx.Graphics.GAL
|
|
||||||
{
|
|
||||||
public enum ScalingFilter
|
|
||||||
{
|
|
||||||
Bilinear,
|
|
||||||
Nearest,
|
|
||||||
Fsr,
|
|
||||||
Area,
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,9 +0,0 @@
|
|||||||
namespace Ryujinx.Graphics.GAL
|
|
||||||
{
|
|
||||||
public enum VSyncMode
|
|
||||||
{
|
|
||||||
Switch,
|
|
||||||
Unbounded,
|
|
||||||
Custom
|
|
||||||
}
|
|
||||||
}
|
|
@@ -11,8 +11,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
class VtgAsComputeContext : IDisposable
|
class VtgAsComputeContext : IDisposable
|
||||||
{
|
{
|
||||||
private const int DummyBufferSize = 16;
|
|
||||||
|
|
||||||
private readonly GpuContext _context;
|
private readonly GpuContext _context;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -48,7 +46,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
|
|||||||
1,
|
1,
|
||||||
1,
|
1,
|
||||||
1,
|
1,
|
||||||
1,
|
format.GetBytesPerElement(),
|
||||||
format,
|
format,
|
||||||
DepthStencilMode.Depth,
|
DepthStencilMode.Depth,
|
||||||
Target.TextureBuffer,
|
Target.TextureBuffer,
|
||||||
@@ -521,21 +519,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
|
|||||||
return new BufferRange(_geometryIndexDataBuffer.Handle, offset, size, write);
|
return new BufferRange(_geometryIndexDataBuffer.Handle, offset, size, write);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the range for a dummy 16 bytes buffer, filled with zeros.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>Dummy buffer range</returns>
|
|
||||||
public BufferRange GetDummyBufferRange()
|
|
||||||
{
|
|
||||||
if (_dummyBuffer == BufferHandle.Null)
|
|
||||||
{
|
|
||||||
_dummyBuffer = _context.Renderer.CreateBuffer(DummyBufferSize, BufferAccess.DeviceMemory);
|
|
||||||
_context.Renderer.Pipeline.ClearBuffer(_dummyBuffer, 0, DummyBufferSize, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new BufferRange(_dummyBuffer, 0, DummyBufferSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the range for a sequential index buffer, with ever incrementing index values.
|
/// Gets the range for a sequential index buffer, with ever incrementing index values.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@@ -147,7 +147,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
|
|||||||
{
|
{
|
||||||
_vacContext.VertexInfoBufferUpdater.SetVertexStride(index, 0, componentsCount);
|
_vacContext.VertexInfoBufferUpdater.SetVertexStride(index, 0, componentsCount);
|
||||||
_vacContext.VertexInfoBufferUpdater.SetVertexOffset(index, 0, 0);
|
_vacContext.VertexInfoBufferUpdater.SetVertexOffset(index, 0, 0);
|
||||||
SetDummyBufferTexture(_vertexAsCompute.Reservations, index, format);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,15 +162,12 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
|
|||||||
{
|
{
|
||||||
_vacContext.VertexInfoBufferUpdater.SetVertexStride(index, 0, componentsCount);
|
_vacContext.VertexInfoBufferUpdater.SetVertexStride(index, 0, componentsCount);
|
||||||
_vacContext.VertexInfoBufferUpdater.SetVertexOffset(index, 0, 0);
|
_vacContext.VertexInfoBufferUpdater.SetVertexOffset(index, 0, 0);
|
||||||
SetDummyBufferTexture(_vertexAsCompute.Reservations, index, format);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vbStride = vertexBuffer.UnpackStride();
|
int vbStride = vertexBuffer.UnpackStride();
|
||||||
ulong vbSize = GetVertexBufferSize(address, endAddress.Pack(), vbStride, _indexed, instanced, _firstVertex, _count);
|
ulong vbSize = GetVertexBufferSize(address, endAddress.Pack(), vbStride, _indexed, instanced, _firstVertex, _count);
|
||||||
|
|
||||||
ulong oldVbSize = vbSize;
|
|
||||||
|
|
||||||
ulong attributeOffset = (ulong)vertexAttrib.UnpackOffset();
|
ulong attributeOffset = (ulong)vertexAttrib.UnpackOffset();
|
||||||
int componentSize = format.GetScalarSize();
|
int componentSize = format.GetScalarSize();
|
||||||
|
|
||||||
@@ -345,20 +341,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
|
|||||||
return maxOutputVertices / verticesPerPrimitive;
|
return maxOutputVertices / verticesPerPrimitive;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binds a dummy buffer as vertex buffer into a buffer texture.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="reservations">Shader resource binding reservations</param>
|
|
||||||
/// <param name="index">Buffer texture index</param>
|
|
||||||
/// <param name="format">Buffer texture format</param>
|
|
||||||
private readonly void SetDummyBufferTexture(ResourceReservations reservations, int index, Format format)
|
|
||||||
{
|
|
||||||
ITexture bufferTexture = _vacContext.EnsureBufferTexture(index + 2, format);
|
|
||||||
bufferTexture.SetStorage(_vacContext.GetDummyBufferRange());
|
|
||||||
|
|
||||||
_context.Renderer.Pipeline.SetTextureAndSampler(ShaderStage.Compute, reservations.GetVertexBufferTextureBinding(index), bufferTexture, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Binds a vertex buffer into a buffer texture.
|
/// Binds a vertex buffer into a buffer texture.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Graphics.Device;
|
using Ryujinx.Graphics.Device;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using Ryujinx.Graphics.Gpu.Engine.GPFifo;
|
using Ryujinx.Graphics.Gpu.Engine.GPFifo;
|
||||||
@@ -90,6 +91,13 @@ namespace Ryujinx.Graphics.Gpu
|
|||||||
/// Support buffer updater.
|
/// Support buffer updater.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal SupportBufferUpdater SupportBufferUpdater { get; }
|
internal SupportBufferUpdater SupportBufferUpdater { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enabled dirty hacks.
|
||||||
|
/// Used for workarounds to emulator bugs we can't fix/don't know how to fix yet.
|
||||||
|
/// </summary>
|
||||||
|
internal DirtyHacks DirtyHacks { get; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Host hardware capabilities.
|
/// Host hardware capabilities.
|
||||||
@@ -113,7 +121,7 @@ namespace Ryujinx.Graphics.Gpu
|
|||||||
/// Creates a new instance of the GPU emulation context.
|
/// Creates a new instance of the GPU emulation context.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="renderer">Host renderer</param>
|
/// <param name="renderer">Host renderer</param>
|
||||||
public GpuContext(IRenderer renderer)
|
public GpuContext(IRenderer renderer, DirtyHacks hacks)
|
||||||
{
|
{
|
||||||
Renderer = renderer;
|
Renderer = renderer;
|
||||||
|
|
||||||
@@ -136,6 +144,8 @@ namespace Ryujinx.Graphics.Gpu
|
|||||||
|
|
||||||
SupportBufferUpdater = new SupportBufferUpdater(renderer);
|
SupportBufferUpdater = new SupportBufferUpdater(renderer);
|
||||||
|
|
||||||
|
DirtyHacks = hacks;
|
||||||
|
|
||||||
_firstTimestamp = ConvertNanosecondsToTicks((ulong)PerformanceCounter.ElapsedNanoseconds);
|
_firstTimestamp = ConvertNanosecondsToTicks((ulong)PerformanceCounter.ElapsedNanoseconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -46,7 +46,7 @@ namespace Ryujinx.Graphics.Gpu
|
|||||||
/// Enables or disables high-level emulation of common GPU Macro code.
|
/// Enables or disables high-level emulation of common GPU Macro code.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool EnableMacroHLE = true;
|
public static bool EnableMacroHLE = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Title id of the current running game.
|
/// Title id of the current running game.
|
||||||
/// Used by the shader cache.
|
/// Used by the shader cache.
|
||||||
|
@@ -324,6 +324,11 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||||||
|
|
||||||
bool loadHostCache = header.CodeGenVersion == CodeGenVersion;
|
bool loadHostCache = header.CodeGenVersion == CodeGenVersion;
|
||||||
|
|
||||||
|
if (context.Capabilities.Api == TargetApi.Metal)
|
||||||
|
{
|
||||||
|
loadHostCache = false;
|
||||||
|
}
|
||||||
|
|
||||||
int programIndex = 0;
|
int programIndex = 0;
|
||||||
|
|
||||||
DataEntry entry = new();
|
DataEntry entry = new();
|
||||||
@@ -392,7 +397,8 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||||||
context,
|
context,
|
||||||
shaders,
|
shaders,
|
||||||
specState.PipelineState,
|
specState.PipelineState,
|
||||||
specState.TransformFeedbackDescriptors != null);
|
specState.TransformFeedbackDescriptors != null,
|
||||||
|
specState.ComputeState.GetLocalSize());
|
||||||
|
|
||||||
IProgram hostProgram;
|
IProgram hostProgram;
|
||||||
|
|
||||||
@@ -629,7 +635,10 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteHostCode(context, hostCode, program.Shaders, streams, timestamp);
|
if (context.Capabilities.Api != TargetApi.Metal)
|
||||||
|
{
|
||||||
|
WriteHostCode(context, hostCode, program.Shaders, streams, timestamp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using Ryujinx.Graphics.Shader;
|
using Ryujinx.Graphics.Shader;
|
||||||
@@ -366,6 +367,9 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if (_context.Capabilities.Api == TargetApi.Metal && _context.DirtyHacks.IsEnabled(DirtyHack.ShaderTranslationDelay))
|
||||||
|
Thread.Sleep(_context.DirtyHacks[DirtyHack.ShaderTranslationDelay]);
|
||||||
|
|
||||||
AsyncProgramTranslation asyncTranslation = new(guestShaders, specState, programIndex, isCompute);
|
AsyncProgramTranslation asyncTranslation = new(guestShaders, specState, programIndex, isCompute);
|
||||||
_asyncTranslationQueue.Add(asyncTranslation, _cancellationToken);
|
_asyncTranslationQueue.Add(asyncTranslation, _cancellationToken);
|
||||||
}
|
}
|
||||||
@@ -490,7 +494,12 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||||||
{
|
{
|
||||||
ShaderSource[] shaderSources = new ShaderSource[compilation.TranslatedStages.Length];
|
ShaderSource[] shaderSources = new ShaderSource[compilation.TranslatedStages.Length];
|
||||||
|
|
||||||
ShaderInfoBuilder shaderInfoBuilder = new(_context, compilation.SpecializationState.TransformFeedbackDescriptors != null);
|
ref GpuChannelComputeState computeState = ref compilation.SpecializationState.ComputeState;
|
||||||
|
|
||||||
|
ShaderInfoBuilder shaderInfoBuilder = new(
|
||||||
|
_context,
|
||||||
|
compilation.SpecializationState.TransformFeedbackDescriptors != null,
|
||||||
|
computeLocalSize: computeState.GetLocalSize());
|
||||||
|
|
||||||
for (int index = 0; index < compilation.TranslatedStages.Length; index++)
|
for (int index = 0; index < compilation.TranslatedStages.Length; index++)
|
||||||
{
|
{
|
||||||
|
@@ -16,7 +16,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
private readonly GpuAccessorState _state;
|
private readonly GpuAccessorState _state;
|
||||||
private readonly int _stageIndex;
|
private readonly int _stageIndex;
|
||||||
private readonly bool _compute;
|
private readonly bool _compute;
|
||||||
private readonly bool _isVulkan;
|
private readonly bool _isOpenGL;
|
||||||
private readonly bool _hasGeometryShader;
|
private readonly bool _hasGeometryShader;
|
||||||
private readonly bool _supportsQuads;
|
private readonly bool _supportsQuads;
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
_channel = channel;
|
_channel = channel;
|
||||||
_state = state;
|
_state = state;
|
||||||
_stageIndex = stageIndex;
|
_stageIndex = stageIndex;
|
||||||
_isVulkan = context.Capabilities.Api == TargetApi.Vulkan;
|
_isOpenGL = context.Capabilities.Api == TargetApi.OpenGL;
|
||||||
_hasGeometryShader = hasGeometryShader;
|
_hasGeometryShader = hasGeometryShader;
|
||||||
_supportsQuads = context.Capabilities.SupportsQuads;
|
_supportsQuads = context.Capabilities.SupportsQuads;
|
||||||
|
|
||||||
@@ -116,10 +116,10 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
public GpuGraphicsState QueryGraphicsState()
|
public GpuGraphicsState QueryGraphicsState()
|
||||||
{
|
{
|
||||||
return _state.GraphicsState.CreateShaderGraphicsState(
|
return _state.GraphicsState.CreateShaderGraphicsState(
|
||||||
!_isVulkan,
|
_isOpenGL,
|
||||||
_supportsQuads,
|
_supportsQuads,
|
||||||
_hasGeometryShader,
|
_hasGeometryShader,
|
||||||
_isVulkan || _state.GraphicsState.YNegateEnabled);
|
!_isOpenGL || _state.GraphicsState.YNegateEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
@@ -55,7 +55,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
{
|
{
|
||||||
int binding;
|
int binding;
|
||||||
|
|
||||||
if (_context.Capabilities.Api == TargetApi.Vulkan)
|
if (_context.Capabilities.Api != TargetApi.OpenGL)
|
||||||
{
|
{
|
||||||
binding = GetBindingFromIndex(index, _context.Capabilities.MaximumUniformBuffersPerStage, "Uniform buffer");
|
binding = GetBindingFromIndex(index, _context.Capabilities.MaximumUniformBuffersPerStage, "Uniform buffer");
|
||||||
}
|
}
|
||||||
@@ -71,7 +71,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
{
|
{
|
||||||
int binding;
|
int binding;
|
||||||
|
|
||||||
if (_context.Capabilities.Api == TargetApi.Vulkan)
|
if (_context.Capabilities.Api != TargetApi.OpenGL)
|
||||||
{
|
{
|
||||||
if (count == 1)
|
if (count == 1)
|
||||||
{
|
{
|
||||||
@@ -103,7 +103,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
{
|
{
|
||||||
int binding;
|
int binding;
|
||||||
|
|
||||||
if (_context.Capabilities.Api == TargetApi.Vulkan)
|
if (_context.Capabilities.Api != TargetApi.OpenGL)
|
||||||
{
|
{
|
||||||
binding = GetBindingFromIndex(index, _context.Capabilities.MaximumStorageBuffersPerStage, "Storage buffer");
|
binding = GetBindingFromIndex(index, _context.Capabilities.MaximumStorageBuffersPerStage, "Storage buffer");
|
||||||
}
|
}
|
||||||
@@ -119,7 +119,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
{
|
{
|
||||||
int binding;
|
int binding;
|
||||||
|
|
||||||
if (_context.Capabilities.Api == TargetApi.Vulkan)
|
if (_context.Capabilities.Api != TargetApi.OpenGL)
|
||||||
{
|
{
|
||||||
if (count == 1)
|
if (count == 1)
|
||||||
{
|
{
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
using Ryujinx.Graphics.GAL;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gpu.Shader
|
namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -61,5 +63,14 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
SharedMemorySize = sharedMemorySize;
|
SharedMemorySize = sharedMemorySize;
|
||||||
HasUnalignedStorageBuffer = hasUnalignedStorageBuffer;
|
HasUnalignedStorageBuffer = hasUnalignedStorageBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the local group size of the shader in a GAL compatible struct.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Local group size</returns>
|
||||||
|
public ComputeSize GetLocalSize()
|
||||||
|
{
|
||||||
|
return new ComputeSize(LocalSizeX, LocalSizeY, LocalSizeZ);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
@@ -224,7 +225,10 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
TranslatedShader translatedShader = TranslateShader(_dumper, channel, translatorContext, cachedGuestCode, asCompute: false);
|
TranslatedShader translatedShader = TranslateShader(_dumper, channel, translatorContext, cachedGuestCode, asCompute: false);
|
||||||
|
|
||||||
ShaderSource[] shaderSourcesArray = new ShaderSource[] { CreateShaderSource(translatedShader.Program) };
|
ShaderSource[] shaderSourcesArray = new ShaderSource[] { CreateShaderSource(translatedShader.Program) };
|
||||||
ShaderInfo info = ShaderInfoBuilder.BuildForCompute(_context, translatedShader.Program.Info);
|
ShaderInfo info = ShaderInfoBuilder.BuildForCompute(
|
||||||
|
_context,
|
||||||
|
translatedShader.Program.Info,
|
||||||
|
computeState.GetLocalSize());
|
||||||
IProgram hostProgram = _context.Renderer.CreateProgram(shaderSourcesArray, info);
|
IProgram hostProgram = _context.Renderer.CreateProgram(shaderSourcesArray, info);
|
||||||
|
|
||||||
cpShader = new CachedShaderProgram(hostProgram, specState, translatedShader.Shader);
|
cpShader = new CachedShaderProgram(hostProgram, specState, translatedShader.Shader);
|
||||||
@@ -425,7 +429,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
|
|
||||||
TranslatorContext lastInVertexPipeline = geometryToCompute ? translatorContexts[4] ?? currentStage : currentStage;
|
TranslatorContext lastInVertexPipeline = geometryToCompute ? translatorContexts[4] ?? currentStage : currentStage;
|
||||||
|
|
||||||
program = lastInVertexPipeline.GenerateVertexPassthroughForCompute();
|
(program, ShaderProgramInfo vacInfo) = lastInVertexPipeline.GenerateVertexPassthroughForCompute();
|
||||||
|
infoBuilder.AddStageInfoVac(vacInfo);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -530,7 +535,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
private ShaderAsCompute CreateHostVertexAsComputeProgram(ShaderProgram program, TranslatorContext context, bool tfEnabled)
|
private ShaderAsCompute CreateHostVertexAsComputeProgram(ShaderProgram program, TranslatorContext context, bool tfEnabled)
|
||||||
{
|
{
|
||||||
ShaderSource source = new(program.Code, program.BinaryCode, ShaderStage.Compute, program.Language);
|
ShaderSource source = new(program.Code, program.BinaryCode, ShaderStage.Compute, program.Language);
|
||||||
ShaderInfo info = ShaderInfoBuilder.BuildForVertexAsCompute(_context, program.Info, tfEnabled);
|
ShaderInfo info = ShaderInfoBuilder.BuildForVertexAsCompute(_context, program.Info, context.GetVertexAsComputeInfo(), tfEnabled);
|
||||||
|
|
||||||
return new(_context.Renderer.CreateProgram(new[] { source }, info), program.Info, context.GetResourceReservations());
|
return new(_context.Renderer.CreateProgram(new[] { source }, info), program.Info, context.GetResourceReservations());
|
||||||
}
|
}
|
||||||
@@ -822,16 +827,20 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates shader translation options with the requested graphics API and flags.
|
/// Creates shader translation options with the requested graphics API and flags.
|
||||||
/// The shader language is choosen based on the current configuration and graphics API.
|
/// The shader language is chosen based on the current configuration and graphics API.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="api">Target graphics API</param>
|
/// <param name="api">Target graphics API</param>
|
||||||
/// <param name="flags">Translation flags</param>
|
/// <param name="flags">Translation flags</param>
|
||||||
/// <returns>Translation options</returns>
|
/// <returns>Translation options</returns>
|
||||||
private static TranslationOptions CreateTranslationOptions(TargetApi api, TranslationFlags flags)
|
private static TranslationOptions CreateTranslationOptions(TargetApi api, TranslationFlags flags)
|
||||||
{
|
{
|
||||||
TargetLanguage lang = GraphicsConfig.EnableSpirvCompilationOnVulkan && api == TargetApi.Vulkan
|
TargetLanguage lang = api switch
|
||||||
? TargetLanguage.Spirv
|
{
|
||||||
: TargetLanguage.Glsl;
|
TargetApi.OpenGL => TargetLanguage.Glsl,
|
||||||
|
TargetApi.Vulkan => GraphicsConfig.EnableSpirvCompilationOnVulkan ? TargetLanguage.Spirv : TargetLanguage.Glsl,
|
||||||
|
TargetApi.Metal => TargetLanguage.Msl,
|
||||||
|
_ => throw new NotImplementedException()
|
||||||
|
};
|
||||||
|
|
||||||
return new TranslationOptions(lang, api, flags);
|
return new TranslationOptions(lang, api, flags);
|
||||||
}
|
}
|
||||||
|
@@ -22,6 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
ResourceStages.Geometry;
|
ResourceStages.Geometry;
|
||||||
|
|
||||||
private readonly GpuContext _context;
|
private readonly GpuContext _context;
|
||||||
|
private readonly ComputeSize _computeLocalSize;
|
||||||
|
|
||||||
private int _fragmentOutputMap;
|
private int _fragmentOutputMap;
|
||||||
|
|
||||||
@@ -39,9 +40,11 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
/// <param name="context">GPU context that owns the shaders that will be added to the builder</param>
|
/// <param name="context">GPU context that owns the shaders that will be added to the builder</param>
|
||||||
/// <param name="tfEnabled">Indicates if the graphics shader is used with transform feedback enabled</param>
|
/// <param name="tfEnabled">Indicates if the graphics shader is used with transform feedback enabled</param>
|
||||||
/// <param name="vertexAsCompute">Indicates that the vertex shader will be emulated on a compute shader</param>
|
/// <param name="vertexAsCompute">Indicates that the vertex shader will be emulated on a compute shader</param>
|
||||||
public ShaderInfoBuilder(GpuContext context, bool tfEnabled, bool vertexAsCompute = false)
|
/// <param name="computeLocalSize">Indicates the local thread size for a compute shader</param>
|
||||||
|
public ShaderInfoBuilder(GpuContext context, bool tfEnabled, bool vertexAsCompute = false, ComputeSize computeLocalSize = default)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
|
_computeLocalSize = computeLocalSize;
|
||||||
|
|
||||||
_fragmentOutputMap = -1;
|
_fragmentOutputMap = -1;
|
||||||
|
|
||||||
@@ -95,7 +98,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
private void PopulateDescriptorAndUsages(ResourceStages stages, ResourceType type, int setIndex, int start, int count, bool write = false)
|
private void PopulateDescriptorAndUsages(ResourceStages stages, ResourceType type, int setIndex, int start, int count, bool write = false)
|
||||||
{
|
{
|
||||||
AddDescriptor(stages, type, setIndex, start, count);
|
AddDescriptor(stages, type, setIndex, start, count);
|
||||||
AddUsage(stages, type, setIndex, start, count, write);
|
// AddUsage(stages, type, setIndex, start, count, write);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -159,6 +162,25 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
AddUsage(info.Images, stages, isImage: true);
|
AddUsage(info.Images, stages, isImage: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AddStageInfoVac(ShaderProgramInfo info)
|
||||||
|
{
|
||||||
|
ResourceStages stages = info.Stage switch
|
||||||
|
{
|
||||||
|
ShaderStage.Compute => ResourceStages.Compute,
|
||||||
|
ShaderStage.Vertex => ResourceStages.Vertex,
|
||||||
|
ShaderStage.TessellationControl => ResourceStages.TessellationControl,
|
||||||
|
ShaderStage.TessellationEvaluation => ResourceStages.TessellationEvaluation,
|
||||||
|
ShaderStage.Geometry => ResourceStages.Geometry,
|
||||||
|
ShaderStage.Fragment => ResourceStages.Fragment,
|
||||||
|
_ => ResourceStages.None,
|
||||||
|
};
|
||||||
|
|
||||||
|
AddUsage(info.CBuffers, stages, isStorage: false);
|
||||||
|
AddUsage(info.SBuffers, stages, isStorage: true);
|
||||||
|
AddUsage(info.Textures, stages, isImage: false);
|
||||||
|
AddUsage(info.Images, stages, isImage: true);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a resource descriptor to the list of descriptors.
|
/// Adds a resource descriptor to the list of descriptors.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -361,14 +383,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
|
|
||||||
ResourceLayout resourceLayout = new(descriptors.AsReadOnly(), usages.AsReadOnly());
|
ResourceLayout resourceLayout = new(descriptors.AsReadOnly(), usages.AsReadOnly());
|
||||||
|
|
||||||
if (pipeline.HasValue)
|
return new ShaderInfo(_fragmentOutputMap, resourceLayout, _computeLocalSize, pipeline, fromCache);
|
||||||
{
|
|
||||||
return new ShaderInfo(_fragmentOutputMap, resourceLayout, pipeline.Value, fromCache);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return new ShaderInfo(_fragmentOutputMap, resourceLayout, fromCache);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -378,14 +393,16 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
/// <param name="programs">Shaders from the disk cache</param>
|
/// <param name="programs">Shaders from the disk cache</param>
|
||||||
/// <param name="pipeline">Optional pipeline for background compilation</param>
|
/// <param name="pipeline">Optional pipeline for background compilation</param>
|
||||||
/// <param name="tfEnabled">Indicates if the graphics shader is used with transform feedback enabled</param>
|
/// <param name="tfEnabled">Indicates if the graphics shader is used with transform feedback enabled</param>
|
||||||
|
/// <param name="computeLocalSize">Compute local thread size</param>
|
||||||
/// <returns>Shader information</returns>
|
/// <returns>Shader information</returns>
|
||||||
public static ShaderInfo BuildForCache(
|
public static ShaderInfo BuildForCache(
|
||||||
GpuContext context,
|
GpuContext context,
|
||||||
IEnumerable<CachedShaderStage> programs,
|
IEnumerable<CachedShaderStage> programs,
|
||||||
ProgramPipelineState? pipeline,
|
ProgramPipelineState? pipeline,
|
||||||
bool tfEnabled)
|
bool tfEnabled,
|
||||||
|
ComputeSize computeLocalSize)
|
||||||
{
|
{
|
||||||
ShaderInfoBuilder builder = new(context, tfEnabled);
|
ShaderInfoBuilder builder = new(context, tfEnabled, computeLocalSize: computeLocalSize);
|
||||||
|
|
||||||
foreach (CachedShaderStage program in programs)
|
foreach (CachedShaderStage program in programs)
|
||||||
{
|
{
|
||||||
@@ -403,11 +420,12 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="context">GPU context that owns the shader</param>
|
/// <param name="context">GPU context that owns the shader</param>
|
||||||
/// <param name="info">Compute shader information</param>
|
/// <param name="info">Compute shader information</param>
|
||||||
|
/// <param name="computeLocalSize">Compute local thread size</param>
|
||||||
/// <param name="fromCache">True if the compute shader comes from a disk cache, false otherwise</param>
|
/// <param name="fromCache">True if the compute shader comes from a disk cache, false otherwise</param>
|
||||||
/// <returns>Shader information</returns>
|
/// <returns>Shader information</returns>
|
||||||
public static ShaderInfo BuildForCompute(GpuContext context, ShaderProgramInfo info, bool fromCache = false)
|
public static ShaderInfo BuildForCompute(GpuContext context, ShaderProgramInfo info, ComputeSize computeLocalSize, bool fromCache = false)
|
||||||
{
|
{
|
||||||
ShaderInfoBuilder builder = new(context, tfEnabled: false, vertexAsCompute: false);
|
ShaderInfoBuilder builder = new(context, tfEnabled: false, vertexAsCompute: false, computeLocalSize: computeLocalSize);
|
||||||
|
|
||||||
builder.AddStageInfo(info);
|
builder.AddStageInfo(info);
|
||||||
|
|
||||||
@@ -422,10 +440,11 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
/// <param name="tfEnabled">Indicates if the graphics shader is used with transform feedback enabled</param>
|
/// <param name="tfEnabled">Indicates if the graphics shader is used with transform feedback enabled</param>
|
||||||
/// <param name="fromCache">True if the compute shader comes from a disk cache, false otherwise</param>
|
/// <param name="fromCache">True if the compute shader comes from a disk cache, false otherwise</param>
|
||||||
/// <returns>Shader information</returns>
|
/// <returns>Shader information</returns>
|
||||||
public static ShaderInfo BuildForVertexAsCompute(GpuContext context, ShaderProgramInfo info, bool tfEnabled, bool fromCache = false)
|
public static ShaderInfo BuildForVertexAsCompute(GpuContext context, ShaderProgramInfo info, ShaderProgramInfo info2, bool tfEnabled, bool fromCache = false)
|
||||||
{
|
{
|
||||||
ShaderInfoBuilder builder = new(context, tfEnabled, vertexAsCompute: true);
|
ShaderInfoBuilder builder = new(context, tfEnabled, vertexAsCompute: true, computeLocalSize: ComputeSize.VtgAsCompute);
|
||||||
|
|
||||||
|
builder.AddStageInfoVac(info2);
|
||||||
builder.AddStageInfo(info, vertexAsCompute: true);
|
builder.AddStageInfo(info, vertexAsCompute: true);
|
||||||
|
|
||||||
return builder.Build(null, fromCache);
|
return builder.Build(null, fromCache);
|
||||||
|
@@ -0,0 +1,22 @@
|
|||||||
|
using SharpMetal;
|
||||||
|
using SharpMetal.Foundation;
|
||||||
|
using SharpMetal.ObjectiveCCore;
|
||||||
|
using SharpMetal.QuartzCore;
|
||||||
|
using System.Runtime.Versioning;
|
||||||
|
// ReSharper disable InconsistentNaming
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Metal.SharpMetalExtensions
|
||||||
|
{
|
||||||
|
[SupportedOSPlatform("macOS")]
|
||||||
|
public static class CAMetalLayerExtensions
|
||||||
|
{
|
||||||
|
private static readonly Selector sel_developerHUDProperties = "developerHUDProperties";
|
||||||
|
private static readonly Selector sel_setDeveloperHUDProperties = "setDeveloperHUDProperties:";
|
||||||
|
|
||||||
|
public static NSDictionary GetDeveloperHudProperties(this CAMetalLayer metalLayer)
|
||||||
|
=> new(ObjectiveCRuntime.IntPtr_objc_msgSend(metalLayer.NativePtr, sel_developerHUDProperties));
|
||||||
|
|
||||||
|
public static void SetDeveloperHudProperties(this CAMetalLayer metalLayer, NSDictionary dictionary)
|
||||||
|
=> ObjectiveCRuntime.objc_msgSend(metalLayer.NativePtr, sel_setDeveloperHUDProperties, dictionary);
|
||||||
|
}
|
||||||
|
}
|
32
src/Ryujinx.Graphics.Metal.SharpMetalExtensions/NSHelper.cs
Normal file
32
src/Ryujinx.Graphics.Metal.SharpMetalExtensions/NSHelper.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
using SharpMetal.Foundation;
|
||||||
|
using SharpMetal.ObjectiveCCore;
|
||||||
|
using System.Runtime.Versioning;
|
||||||
|
// ReSharper disable InconsistentNaming
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Metal.SharpMetalExtensions
|
||||||
|
{
|
||||||
|
[SupportedOSPlatform("macOS")]
|
||||||
|
public static class NSHelper
|
||||||
|
{
|
||||||
|
private static readonly Selector sel_getCStringMaxLengthEncoding = "getCString:maxLength:encoding:";
|
||||||
|
private static readonly Selector sel_stringWithUTF8String = "stringWithUTF8String:";
|
||||||
|
|
||||||
|
public static unsafe string ToDotNetString(this NSString source)
|
||||||
|
{
|
||||||
|
char[] sourceBuffer = new char[source.Length];
|
||||||
|
fixed (char* pSourceBuffer = sourceBuffer)
|
||||||
|
{
|
||||||
|
ObjectiveC.bool_objc_msgSend(source,
|
||||||
|
sel_getCStringMaxLengthEncoding,
|
||||||
|
pSourceBuffer,
|
||||||
|
source.MaximumLengthOfBytes(NSStringEncoding.UTF16) + 1,
|
||||||
|
(ulong)NSStringEncoding.UTF16);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new string(sourceBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NSString ToNSString(this string source)
|
||||||
|
=> new(ObjectiveC.IntPtr_objc_msgSend(new ObjectiveCClass(nameof(NSString)), sel_stringWithUTF8String, source));
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,11 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="SharpMetal" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
146
src/Ryujinx.Graphics.Metal/Auto.cs
Normal file
146
src/Ryujinx.Graphics.Metal/Auto.cs
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Runtime.Versioning;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Metal
|
||||||
|
{
|
||||||
|
interface IAuto
|
||||||
|
{
|
||||||
|
bool HasCommandBufferDependency(CommandBufferScoped cbs);
|
||||||
|
|
||||||
|
void IncrementReferenceCount();
|
||||||
|
void DecrementReferenceCount(int cbIndex);
|
||||||
|
void DecrementReferenceCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IAutoPrivate : IAuto
|
||||||
|
{
|
||||||
|
void AddCommandBufferDependencies(CommandBufferScoped cbs);
|
||||||
|
}
|
||||||
|
|
||||||
|
[SupportedOSPlatform("macos")]
|
||||||
|
class Auto<T> : IAutoPrivate, IDisposable where T : IDisposable
|
||||||
|
{
|
||||||
|
private int _referenceCount;
|
||||||
|
private T _value;
|
||||||
|
|
||||||
|
private readonly BitMap _cbOwnership;
|
||||||
|
private readonly MultiFenceHolder _waitable;
|
||||||
|
|
||||||
|
private bool _disposed;
|
||||||
|
private bool _destroyed;
|
||||||
|
|
||||||
|
public Auto(T value)
|
||||||
|
{
|
||||||
|
_referenceCount = 1;
|
||||||
|
_value = value;
|
||||||
|
_cbOwnership = new BitMap(CommandBufferPool.MaxCommandBuffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Auto(T value, MultiFenceHolder waitable) : this(value)
|
||||||
|
{
|
||||||
|
_waitable = waitable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Get(CommandBufferScoped cbs, int offset, int size, bool write = false)
|
||||||
|
{
|
||||||
|
_waitable?.AddBufferUse(cbs.CommandBufferIndex, offset, size, write);
|
||||||
|
return Get(cbs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T GetUnsafe()
|
||||||
|
{
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Get(CommandBufferScoped cbs)
|
||||||
|
{
|
||||||
|
if (!_destroyed)
|
||||||
|
{
|
||||||
|
AddCommandBufferDependencies(cbs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasCommandBufferDependency(CommandBufferScoped cbs)
|
||||||
|
{
|
||||||
|
return _cbOwnership.IsSet(cbs.CommandBufferIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasRentedCommandBufferDependency(CommandBufferPool cbp)
|
||||||
|
{
|
||||||
|
return _cbOwnership.AnySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddCommandBufferDependencies(CommandBufferScoped cbs)
|
||||||
|
{
|
||||||
|
// We don't want to add a reference to this object to the command buffer
|
||||||
|
// more than once, so if we detect that the command buffer already has ownership
|
||||||
|
// of this object, then we can just return without doing anything else.
|
||||||
|
if (_cbOwnership.Set(cbs.CommandBufferIndex))
|
||||||
|
{
|
||||||
|
if (_waitable != null)
|
||||||
|
{
|
||||||
|
cbs.AddWaitable(_waitable);
|
||||||
|
}
|
||||||
|
|
||||||
|
cbs.AddDependant(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryIncrementReferenceCount()
|
||||||
|
{
|
||||||
|
int lastValue;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
lastValue = _referenceCount;
|
||||||
|
|
||||||
|
if (lastValue == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (Interlocked.CompareExchange(ref _referenceCount, lastValue + 1, lastValue) != lastValue);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void IncrementReferenceCount()
|
||||||
|
{
|
||||||
|
if (Interlocked.Increment(ref _referenceCount) == 1)
|
||||||
|
{
|
||||||
|
Interlocked.Decrement(ref _referenceCount);
|
||||||
|
throw new InvalidOperationException("Attempted to increment the reference count of an object that was already destroyed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DecrementReferenceCount(int cbIndex)
|
||||||
|
{
|
||||||
|
_cbOwnership.Clear(cbIndex);
|
||||||
|
DecrementReferenceCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DecrementReferenceCount()
|
||||||
|
{
|
||||||
|
if (Interlocked.Decrement(ref _referenceCount) == 0)
|
||||||
|
{
|
||||||
|
_value.Dispose();
|
||||||
|
_value = default;
|
||||||
|
_destroyed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.Assert(_referenceCount >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (!_disposed)
|
||||||
|
{
|
||||||
|
DecrementReferenceCount();
|
||||||
|
_disposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
107
src/Ryujinx.Graphics.Metal/BackgroundResources.cs
Normal file
107
src/Ryujinx.Graphics.Metal/BackgroundResources.cs
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
using SharpMetal.Metal;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.Versioning;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Metal
|
||||||
|
{
|
||||||
|
[SupportedOSPlatform("macos")]
|
||||||
|
class BackgroundResource : IDisposable
|
||||||
|
{
|
||||||
|
private readonly MetalRenderer _renderer;
|
||||||
|
|
||||||
|
private CommandBufferPool _pool;
|
||||||
|
private PersistentFlushBuffer _flushBuffer;
|
||||||
|
|
||||||
|
public BackgroundResource(MetalRenderer renderer)
|
||||||
|
{
|
||||||
|
_renderer = renderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandBufferPool GetPool()
|
||||||
|
{
|
||||||
|
if (_pool == null)
|
||||||
|
{
|
||||||
|
MTLCommandQueue queue = _renderer.BackgroundQueue;
|
||||||
|
_pool = new CommandBufferPool(queue, true);
|
||||||
|
_pool.Initialize(null); // TODO: Proper encoder factory for background render/compute
|
||||||
|
}
|
||||||
|
|
||||||
|
return _pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersistentFlushBuffer GetFlushBuffer()
|
||||||
|
{
|
||||||
|
_flushBuffer ??= new PersistentFlushBuffer(_renderer);
|
||||||
|
|
||||||
|
return _flushBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_pool?.Dispose();
|
||||||
|
_flushBuffer?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[SupportedOSPlatform("macos")]
|
||||||
|
class BackgroundResources : IDisposable
|
||||||
|
{
|
||||||
|
private readonly MetalRenderer _renderer;
|
||||||
|
|
||||||
|
private readonly Dictionary<Thread, BackgroundResource> _resources;
|
||||||
|
|
||||||
|
public BackgroundResources(MetalRenderer renderer)
|
||||||
|
{
|
||||||
|
_renderer = renderer;
|
||||||
|
|
||||||
|
_resources = new Dictionary<Thread, BackgroundResource>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Cleanup()
|
||||||
|
{
|
||||||
|
lock (_resources)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<Thread, BackgroundResource> tuple in _resources)
|
||||||
|
{
|
||||||
|
if (!tuple.Key.IsAlive)
|
||||||
|
{
|
||||||
|
tuple.Value.Dispose();
|
||||||
|
_resources.Remove(tuple.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public BackgroundResource Get()
|
||||||
|
{
|
||||||
|
Thread thread = Thread.CurrentThread;
|
||||||
|
|
||||||
|
lock (_resources)
|
||||||
|
{
|
||||||
|
if (!_resources.TryGetValue(thread, out BackgroundResource resource))
|
||||||
|
{
|
||||||
|
Cleanup();
|
||||||
|
|
||||||
|
resource = new BackgroundResource(_renderer);
|
||||||
|
|
||||||
|
_resources[thread] = resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
lock (_resources)
|
||||||
|
{
|
||||||
|
foreach (var resource in _resources.Values)
|
||||||
|
{
|
||||||
|
resource.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
157
src/Ryujinx.Graphics.Metal/BitMap.cs
Normal file
157
src/Ryujinx.Graphics.Metal/BitMap.cs
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
namespace Ryujinx.Graphics.Metal
|
||||||
|
{
|
||||||
|
readonly struct BitMap
|
||||||
|
{
|
||||||
|
public const int IntSize = 64;
|
||||||
|
|
||||||
|
private const int IntShift = 6;
|
||||||
|
private const int IntMask = IntSize - 1;
|
||||||
|
|
||||||
|
private readonly long[] _masks;
|
||||||
|
|
||||||
|
public BitMap(int count)
|
||||||
|
{
|
||||||
|
_masks = new long[(count + IntMask) / IntSize];
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AnySet()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _masks.Length; i++)
|
||||||
|
{
|
||||||
|
if (_masks[i] != 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsSet(int bit)
|
||||||
|
{
|
||||||
|
int wordIndex = bit >> IntShift;
|
||||||
|
int wordBit = bit & IntMask;
|
||||||
|
|
||||||
|
long wordMask = 1L << wordBit;
|
||||||
|
|
||||||
|
return (_masks[wordIndex] & wordMask) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsSet(int start, int end)
|
||||||
|
{
|
||||||
|
if (start == end)
|
||||||
|
{
|
||||||
|
return IsSet(start);
|
||||||
|
}
|
||||||
|
|
||||||
|
int startIndex = start >> IntShift;
|
||||||
|
int startBit = start & IntMask;
|
||||||
|
long startMask = -1L << startBit;
|
||||||
|
|
||||||
|
int endIndex = end >> IntShift;
|
||||||
|
int endBit = end & IntMask;
|
||||||
|
long endMask = (long)(ulong.MaxValue >> (IntMask - endBit));
|
||||||
|
|
||||||
|
if (startIndex == endIndex)
|
||||||
|
{
|
||||||
|
return (_masks[startIndex] & startMask & endMask) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((_masks[startIndex] & startMask) != 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = startIndex + 1; i < endIndex; i++)
|
||||||
|
{
|
||||||
|
if (_masks[i] != 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((_masks[endIndex] & endMask) != 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Set(int bit)
|
||||||
|
{
|
||||||
|
int wordIndex = bit >> IntShift;
|
||||||
|
int wordBit = bit & IntMask;
|
||||||
|
|
||||||
|
long wordMask = 1L << wordBit;
|
||||||
|
|
||||||
|
if ((_masks[wordIndex] & wordMask) != 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_masks[wordIndex] |= wordMask;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetRange(int start, int end)
|
||||||
|
{
|
||||||
|
if (start == end)
|
||||||
|
{
|
||||||
|
Set(start);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int startIndex = start >> IntShift;
|
||||||
|
int startBit = start & IntMask;
|
||||||
|
long startMask = -1L << startBit;
|
||||||
|
|
||||||
|
int endIndex = end >> IntShift;
|
||||||
|
int endBit = end & IntMask;
|
||||||
|
long endMask = (long)(ulong.MaxValue >> (IntMask - endBit));
|
||||||
|
|
||||||
|
if (startIndex == endIndex)
|
||||||
|
{
|
||||||
|
_masks[startIndex] |= startMask & endMask;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_masks[startIndex] |= startMask;
|
||||||
|
|
||||||
|
for (int i = startIndex + 1; i < endIndex; i++)
|
||||||
|
{
|
||||||
|
_masks[i] |= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
_masks[endIndex] |= endMask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear(int bit)
|
||||||
|
{
|
||||||
|
int wordIndex = bit >> IntShift;
|
||||||
|
int wordBit = bit & IntMask;
|
||||||
|
|
||||||
|
long wordMask = 1L << wordBit;
|
||||||
|
|
||||||
|
_masks[wordIndex] &= ~wordMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _masks.Length; i++)
|
||||||
|
{
|
||||||
|
_masks[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearInt(int start, int end)
|
||||||
|
{
|
||||||
|
for (int i = start; i <= end; i++)
|
||||||
|
{
|
||||||
|
_masks[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
385
src/Ryujinx.Graphics.Metal/BufferHolder.cs
Normal file
385
src/Ryujinx.Graphics.Metal/BufferHolder.cs
Normal file
@@ -0,0 +1,385 @@
|
|||||||
|
using Ryujinx.Graphics.GAL;
|
||||||
|
using SharpMetal.Metal;
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Runtime.Versioning;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Metal
|
||||||
|
{
|
||||||
|
[SupportedOSPlatform("macos")]
|
||||||
|
class BufferHolder : IDisposable
|
||||||
|
{
|
||||||
|
private CacheByRange<BufferHolder> _cachedConvertedBuffers;
|
||||||
|
|
||||||
|
public int Size { get; }
|
||||||
|
|
||||||
|
private readonly IntPtr _map;
|
||||||
|
private readonly MetalRenderer _renderer;
|
||||||
|
private readonly Pipeline _pipeline;
|
||||||
|
|
||||||
|
private readonly MultiFenceHolder _waitable;
|
||||||
|
private readonly Auto<DisposableBuffer> _buffer;
|
||||||
|
|
||||||
|
private readonly ReaderWriterLockSlim _flushLock;
|
||||||
|
private FenceHolder _flushFence;
|
||||||
|
private int _flushWaiting;
|
||||||
|
|
||||||
|
public BufferHolder(MetalRenderer renderer, Pipeline pipeline, MTLBuffer buffer, int size)
|
||||||
|
{
|
||||||
|
_renderer = renderer;
|
||||||
|
_pipeline = pipeline;
|
||||||
|
_map = buffer.Contents;
|
||||||
|
_waitable = new MultiFenceHolder(size);
|
||||||
|
_buffer = new Auto<DisposableBuffer>(new(buffer), _waitable);
|
||||||
|
|
||||||
|
_flushLock = new ReaderWriterLockSlim();
|
||||||
|
|
||||||
|
Size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Auto<DisposableBuffer> GetBuffer()
|
||||||
|
{
|
||||||
|
return _buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Auto<DisposableBuffer> GetBuffer(bool isWrite)
|
||||||
|
{
|
||||||
|
if (isWrite)
|
||||||
|
{
|
||||||
|
SignalWrite(0, Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Auto<DisposableBuffer> GetBuffer(int offset, int size, bool isWrite)
|
||||||
|
{
|
||||||
|
if (isWrite)
|
||||||
|
{
|
||||||
|
SignalWrite(offset, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SignalWrite(int offset, int size)
|
||||||
|
{
|
||||||
|
if (offset == 0 && size == Size)
|
||||||
|
{
|
||||||
|
_cachedConvertedBuffers.Clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_cachedConvertedBuffers.ClearRange(offset, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClearFlushFence()
|
||||||
|
{
|
||||||
|
// Assumes _flushLock is held as writer.
|
||||||
|
|
||||||
|
if (_flushFence != null)
|
||||||
|
{
|
||||||
|
if (_flushWaiting == 0)
|
||||||
|
{
|
||||||
|
_flushFence.Put();
|
||||||
|
}
|
||||||
|
|
||||||
|
_flushFence = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WaitForFlushFence()
|
||||||
|
{
|
||||||
|
if (_flushFence == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If storage has changed, make sure the fence has been reached so that the data is in place.
|
||||||
|
_flushLock.ExitReadLock();
|
||||||
|
_flushLock.EnterWriteLock();
|
||||||
|
|
||||||
|
if (_flushFence != null)
|
||||||
|
{
|
||||||
|
var fence = _flushFence;
|
||||||
|
Interlocked.Increment(ref _flushWaiting);
|
||||||
|
|
||||||
|
// Don't wait in the lock.
|
||||||
|
|
||||||
|
_flushLock.ExitWriteLock();
|
||||||
|
|
||||||
|
fence.Wait();
|
||||||
|
|
||||||
|
_flushLock.EnterWriteLock();
|
||||||
|
|
||||||
|
if (Interlocked.Decrement(ref _flushWaiting) == 0)
|
||||||
|
{
|
||||||
|
fence.Put();
|
||||||
|
}
|
||||||
|
|
||||||
|
_flushFence = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assumes the _flushLock is held as reader, returns in same state.
|
||||||
|
_flushLock.ExitWriteLock();
|
||||||
|
_flushLock.EnterReadLock();
|
||||||
|
}
|
||||||
|
|
||||||
|
public PinnedSpan<byte> GetData(int offset, int size)
|
||||||
|
{
|
||||||
|
_flushLock.EnterReadLock();
|
||||||
|
|
||||||
|
WaitForFlushFence();
|
||||||
|
|
||||||
|
Span<byte> result;
|
||||||
|
|
||||||
|
if (_map != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
result = GetDataStorage(offset, size);
|
||||||
|
|
||||||
|
// Need to be careful here, the buffer can't be unmapped while the data is being used.
|
||||||
|
_buffer.IncrementReferenceCount();
|
||||||
|
|
||||||
|
_flushLock.ExitReadLock();
|
||||||
|
|
||||||
|
return PinnedSpan<byte>.UnsafeFromSpan(result, _buffer.DecrementReferenceCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new InvalidOperationException("The buffer is not mapped");
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe Span<byte> GetDataStorage(int offset, int size)
|
||||||
|
{
|
||||||
|
int mappingSize = Math.Min(size, Size - offset);
|
||||||
|
|
||||||
|
if (_map != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
return new Span<byte>((void*)(_map + offset), mappingSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new InvalidOperationException("The buffer is not mapped.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe void SetData(int offset, ReadOnlySpan<byte> data, CommandBufferScoped? cbs = null, bool allowCbsWait = true)
|
||||||
|
{
|
||||||
|
int dataSize = Math.Min(data.Length, Size - offset);
|
||||||
|
if (dataSize == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_map != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
// If persistently mapped, set the data directly if the buffer is not currently in use.
|
||||||
|
bool isRented = _buffer.HasRentedCommandBufferDependency(_renderer.CommandBufferPool);
|
||||||
|
|
||||||
|
// If the buffer is rented, take a little more time and check if the use overlaps this handle.
|
||||||
|
bool needsFlush = isRented && _waitable.IsBufferRangeInUse(offset, dataSize, false);
|
||||||
|
|
||||||
|
if (!needsFlush)
|
||||||
|
{
|
||||||
|
WaitForFences(offset, dataSize);
|
||||||
|
|
||||||
|
data[..dataSize].CopyTo(new Span<byte>((void*)(_map + offset), dataSize));
|
||||||
|
|
||||||
|
SignalWrite(offset, dataSize);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cbs != null &&
|
||||||
|
cbs.Value.Encoders.CurrentEncoderType == EncoderType.Render &&
|
||||||
|
!(_buffer.HasCommandBufferDependency(cbs.Value) &&
|
||||||
|
_waitable.IsBufferRangeInUse(cbs.Value.CommandBufferIndex, offset, dataSize)))
|
||||||
|
{
|
||||||
|
// If the buffer hasn't been used on the command buffer yet, try to preload the data.
|
||||||
|
// This avoids ending and beginning render passes on each buffer data upload.
|
||||||
|
|
||||||
|
cbs = _pipeline.GetPreloadCommandBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allowCbsWait)
|
||||||
|
{
|
||||||
|
_renderer.BufferManager.StagingBuffer.PushData(_renderer.CommandBufferPool, cbs, this, offset, data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool rentCbs = cbs == null;
|
||||||
|
if (rentCbs)
|
||||||
|
{
|
||||||
|
cbs = _renderer.CommandBufferPool.Rent();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_renderer.BufferManager.StagingBuffer.TryPushData(cbs.Value, this, offset, data))
|
||||||
|
{
|
||||||
|
// Need to do a slow upload.
|
||||||
|
BufferHolder srcHolder = _renderer.BufferManager.Create(dataSize);
|
||||||
|
srcHolder.SetDataUnchecked(0, data);
|
||||||
|
|
||||||
|
var srcBuffer = srcHolder.GetBuffer();
|
||||||
|
var dstBuffer = this.GetBuffer(true);
|
||||||
|
|
||||||
|
Copy(cbs.Value, srcBuffer, dstBuffer, 0, offset, dataSize);
|
||||||
|
|
||||||
|
srcHolder.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rentCbs)
|
||||||
|
{
|
||||||
|
cbs.Value.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe void SetDataUnchecked(int offset, ReadOnlySpan<byte> data)
|
||||||
|
{
|
||||||
|
int dataSize = Math.Min(data.Length, Size - offset);
|
||||||
|
if (dataSize == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_map != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
data[..dataSize].CopyTo(new Span<byte>((void*)(_map + offset), dataSize));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetDataUnchecked<T>(int offset, ReadOnlySpan<T> data) where T : unmanaged
|
||||||
|
{
|
||||||
|
SetDataUnchecked(offset, MemoryMarshal.AsBytes(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Copy(
|
||||||
|
CommandBufferScoped cbs,
|
||||||
|
Auto<DisposableBuffer> src,
|
||||||
|
Auto<DisposableBuffer> dst,
|
||||||
|
int srcOffset,
|
||||||
|
int dstOffset,
|
||||||
|
int size,
|
||||||
|
bool registerSrcUsage = true)
|
||||||
|
{
|
||||||
|
var srcBuffer = registerSrcUsage ? src.Get(cbs, srcOffset, size).Value : src.GetUnsafe().Value;
|
||||||
|
var dstbuffer = dst.Get(cbs, dstOffset, size, true).Value;
|
||||||
|
|
||||||
|
cbs.Encoders.EnsureBlitEncoder().CopyFromBuffer(
|
||||||
|
srcBuffer,
|
||||||
|
(ulong)srcOffset,
|
||||||
|
dstbuffer,
|
||||||
|
(ulong)dstOffset,
|
||||||
|
(ulong)size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WaitForFences()
|
||||||
|
{
|
||||||
|
_waitable.WaitForFences();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WaitForFences(int offset, int size)
|
||||||
|
{
|
||||||
|
_waitable.WaitForFences(offset, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool BoundToRange(int offset, ref int size)
|
||||||
|
{
|
||||||
|
if (offset >= Size)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = Math.Min(Size - offset, size);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Auto<DisposableBuffer> GetBufferI8ToI16(CommandBufferScoped cbs, int offset, int size)
|
||||||
|
{
|
||||||
|
if (!BoundToRange(offset, ref size))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var key = new I8ToI16CacheKey(_renderer);
|
||||||
|
|
||||||
|
if (!_cachedConvertedBuffers.TryGetValue(offset, size, key, out var holder))
|
||||||
|
{
|
||||||
|
holder = _renderer.BufferManager.Create((size * 2 + 3) & ~3);
|
||||||
|
|
||||||
|
_renderer.HelperShader.ConvertI8ToI16(cbs, this, holder, offset, size);
|
||||||
|
|
||||||
|
key.SetBuffer(holder.GetBuffer());
|
||||||
|
|
||||||
|
_cachedConvertedBuffers.Add(offset, size, key, holder);
|
||||||
|
}
|
||||||
|
|
||||||
|
return holder.GetBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Auto<DisposableBuffer> GetBufferTopologyConversion(CommandBufferScoped cbs, int offset, int size, IndexBufferPattern pattern, int indexSize)
|
||||||
|
{
|
||||||
|
if (!BoundToRange(offset, ref size))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var key = new TopologyConversionCacheKey(_renderer, pattern, indexSize);
|
||||||
|
|
||||||
|
if (!_cachedConvertedBuffers.TryGetValue(offset, size, key, out var holder))
|
||||||
|
{
|
||||||
|
// The destination index size is always I32.
|
||||||
|
|
||||||
|
int indexCount = size / indexSize;
|
||||||
|
|
||||||
|
int convertedCount = pattern.GetConvertedCount(indexCount);
|
||||||
|
|
||||||
|
holder = _renderer.BufferManager.Create(convertedCount * 4);
|
||||||
|
|
||||||
|
_renderer.HelperShader.ConvertIndexBuffer(cbs, this, holder, pattern, indexSize, offset, indexCount);
|
||||||
|
|
||||||
|
key.SetBuffer(holder.GetBuffer());
|
||||||
|
|
||||||
|
_cachedConvertedBuffers.Add(offset, size, key, holder);
|
||||||
|
}
|
||||||
|
|
||||||
|
return holder.GetBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetCachedConvertedBuffer(int offset, int size, ICacheKey key, out BufferHolder holder)
|
||||||
|
{
|
||||||
|
return _cachedConvertedBuffers.TryGetValue(offset, size, key, out holder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddCachedConvertedBuffer(int offset, int size, ICacheKey key, BufferHolder holder)
|
||||||
|
{
|
||||||
|
_cachedConvertedBuffers.Add(offset, size, key, holder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddCachedConvertedBufferDependency(int offset, int size, ICacheKey key, Dependency dependency)
|
||||||
|
{
|
||||||
|
_cachedConvertedBuffers.AddDependency(offset, size, key, dependency);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveCachedConvertedBuffer(int offset, int size, ICacheKey key)
|
||||||
|
{
|
||||||
|
_cachedConvertedBuffers.Remove(offset, size, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_pipeline.FlushCommandsIfWeightExceeding(_buffer, (ulong)Size);
|
||||||
|
|
||||||
|
_buffer.Dispose();
|
||||||
|
_cachedConvertedBuffers.Dispose();
|
||||||
|
|
||||||
|
_flushLock.EnterWriteLock();
|
||||||
|
|
||||||
|
ClearFlushFence();
|
||||||
|
|
||||||
|
_flushLock.ExitWriteLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
237
src/Ryujinx.Graphics.Metal/BufferManager.cs
Normal file
237
src/Ryujinx.Graphics.Metal/BufferManager.cs
Normal file
@@ -0,0 +1,237 @@
|
|||||||
|
using Ryujinx.Common.Logging;
|
||||||
|
using Ryujinx.Graphics.GAL;
|
||||||
|
using SharpMetal.Metal;
|
||||||
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Metal
|
||||||
|
{
|
||||||
|
[SupportedOSPlatform("macos")]
|
||||||
|
readonly struct ScopedTemporaryBuffer : IDisposable
|
||||||
|
{
|
||||||
|
private readonly BufferManager _bufferManager;
|
||||||
|
private readonly bool _isReserved;
|
||||||
|
|
||||||
|
public readonly BufferRange Range;
|
||||||
|
public readonly BufferHolder Holder;
|
||||||
|
|
||||||
|
public BufferHandle Handle => Range.Handle;
|
||||||
|
public int Offset => Range.Offset;
|
||||||
|
|
||||||
|
public ScopedTemporaryBuffer(BufferManager bufferManager, BufferHolder holder, BufferHandle handle, int offset, int size, bool isReserved)
|
||||||
|
{
|
||||||
|
_bufferManager = bufferManager;
|
||||||
|
|
||||||
|
Range = new BufferRange(handle, offset, size);
|
||||||
|
Holder = holder;
|
||||||
|
|
||||||
|
_isReserved = isReserved;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (!_isReserved)
|
||||||
|
{
|
||||||
|
_bufferManager.Delete(Range.Handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[SupportedOSPlatform("macos")]
|
||||||
|
class BufferManager : IDisposable
|
||||||
|
{
|
||||||
|
private readonly IdList<BufferHolder> _buffers;
|
||||||
|
|
||||||
|
private readonly MTLDevice _device;
|
||||||
|
private readonly MetalRenderer _renderer;
|
||||||
|
private readonly Pipeline _pipeline;
|
||||||
|
|
||||||
|
public int BufferCount { get; private set; }
|
||||||
|
|
||||||
|
public StagingBuffer StagingBuffer { get; }
|
||||||
|
|
||||||
|
public BufferManager(MTLDevice device, MetalRenderer renderer, Pipeline pipeline)
|
||||||
|
{
|
||||||
|
_device = device;
|
||||||
|
_renderer = renderer;
|
||||||
|
_pipeline = pipeline;
|
||||||
|
_buffers = new IdList<BufferHolder>();
|
||||||
|
|
||||||
|
StagingBuffer = new StagingBuffer(_renderer, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BufferHandle Create(nint pointer, int size)
|
||||||
|
{
|
||||||
|
// TODO: This is the wrong Metal method, we need no-copy which SharpMetal isn't giving us.
|
||||||
|
var buffer = _device.NewBuffer(pointer, (ulong)size, MTLResourceOptions.ResourceStorageModeShared);
|
||||||
|
|
||||||
|
if (buffer == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
Logger.Error?.PrintMsg(LogClass.Gpu, $"Failed to create buffer with size 0x{size:X}, and pointer 0x{pointer:X}.");
|
||||||
|
|
||||||
|
return BufferHandle.Null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var holder = new BufferHolder(_renderer, _pipeline, buffer, size);
|
||||||
|
|
||||||
|
BufferCount++;
|
||||||
|
|
||||||
|
ulong handle64 = (uint)_buffers.Add(holder);
|
||||||
|
|
||||||
|
return Unsafe.As<ulong, BufferHandle>(ref handle64);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BufferHandle CreateWithHandle(int size)
|
||||||
|
{
|
||||||
|
return CreateWithHandle(size, out _);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BufferHandle CreateWithHandle(int size, out BufferHolder holder)
|
||||||
|
{
|
||||||
|
holder = Create(size);
|
||||||
|
|
||||||
|
if (holder == null)
|
||||||
|
{
|
||||||
|
return BufferHandle.Null;
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferCount++;
|
||||||
|
|
||||||
|
ulong handle64 = (uint)_buffers.Add(holder);
|
||||||
|
|
||||||
|
return Unsafe.As<ulong, BufferHandle>(ref handle64);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScopedTemporaryBuffer ReserveOrCreate(CommandBufferScoped cbs, int size)
|
||||||
|
{
|
||||||
|
StagingBufferReserved? result = StagingBuffer.TryReserveData(cbs, size);
|
||||||
|
|
||||||
|
if (result.HasValue)
|
||||||
|
{
|
||||||
|
return new ScopedTemporaryBuffer(this, result.Value.Buffer, StagingBuffer.Handle, result.Value.Offset, result.Value.Size, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Create a temporary buffer.
|
||||||
|
BufferHandle handle = CreateWithHandle(size, out BufferHolder holder);
|
||||||
|
|
||||||
|
return new ScopedTemporaryBuffer(this, holder, handle, 0, size, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public BufferHolder Create(int size)
|
||||||
|
{
|
||||||
|
var buffer = _device.NewBuffer((ulong)size, MTLResourceOptions.ResourceStorageModeShared);
|
||||||
|
|
||||||
|
if (buffer != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
return new BufferHolder(_renderer, _pipeline, buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.Error?.PrintMsg(LogClass.Gpu, $"Failed to create buffer with size 0x{size:X}.");
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Auto<DisposableBuffer> GetBuffer(BufferHandle handle, bool isWrite, out int size)
|
||||||
|
{
|
||||||
|
if (TryGetBuffer(handle, out var holder))
|
||||||
|
{
|
||||||
|
size = holder.Size;
|
||||||
|
return holder.GetBuffer(isWrite);
|
||||||
|
}
|
||||||
|
|
||||||
|
size = 0;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Auto<DisposableBuffer> GetBuffer(BufferHandle handle, int offset, int size, bool isWrite)
|
||||||
|
{
|
||||||
|
if (TryGetBuffer(handle, out var holder))
|
||||||
|
{
|
||||||
|
return holder.GetBuffer(offset, size, isWrite);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Auto<DisposableBuffer> GetBuffer(BufferHandle handle, bool isWrite)
|
||||||
|
{
|
||||||
|
if (TryGetBuffer(handle, out var holder))
|
||||||
|
{
|
||||||
|
return holder.GetBuffer(isWrite);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Auto<DisposableBuffer> GetBufferI8ToI16(CommandBufferScoped cbs, BufferHandle handle, int offset, int size)
|
||||||
|
{
|
||||||
|
if (TryGetBuffer(handle, out var holder))
|
||||||
|
{
|
||||||
|
return holder.GetBufferI8ToI16(cbs, offset, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Auto<DisposableBuffer> GetBufferTopologyConversion(CommandBufferScoped cbs, BufferHandle handle, int offset, int size, IndexBufferPattern pattern, int indexSize)
|
||||||
|
{
|
||||||
|
if (TryGetBuffer(handle, out var holder))
|
||||||
|
{
|
||||||
|
return holder.GetBufferTopologyConversion(cbs, offset, size, pattern, indexSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PinnedSpan<byte> GetData(BufferHandle handle, int offset, int size)
|
||||||
|
{
|
||||||
|
if (TryGetBuffer(handle, out var holder))
|
||||||
|
{
|
||||||
|
return holder.GetData(offset, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PinnedSpan<byte>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetData<T>(BufferHandle handle, int offset, ReadOnlySpan<T> data) where T : unmanaged
|
||||||
|
{
|
||||||
|
SetData(handle, offset, MemoryMarshal.Cast<T, byte>(data), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetData(BufferHandle handle, int offset, ReadOnlySpan<byte> data, CommandBufferScoped? cbs)
|
||||||
|
{
|
||||||
|
if (TryGetBuffer(handle, out var holder))
|
||||||
|
{
|
||||||
|
holder.SetData(offset, data, cbs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Delete(BufferHandle handle)
|
||||||
|
{
|
||||||
|
if (TryGetBuffer(handle, out var holder))
|
||||||
|
{
|
||||||
|
holder.Dispose();
|
||||||
|
_buffers.Remove((int)Unsafe.As<BufferHandle, ulong>(ref handle));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TryGetBuffer(BufferHandle handle, out BufferHolder holder)
|
||||||
|
{
|
||||||
|
return _buffers.TryGetValue((int)Unsafe.As<BufferHandle, ulong>(ref handle), out holder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
StagingBuffer.Dispose();
|
||||||
|
|
||||||
|
foreach (var buffer in _buffers)
|
||||||
|
{
|
||||||
|
buffer.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
85
src/Ryujinx.Graphics.Metal/BufferUsageBitmap.cs
Normal file
85
src/Ryujinx.Graphics.Metal/BufferUsageBitmap.cs
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Metal
|
||||||
|
{
|
||||||
|
[SupportedOSPlatform("macos")]
|
||||||
|
internal class BufferUsageBitmap
|
||||||
|
{
|
||||||
|
private readonly BitMap _bitmap;
|
||||||
|
private readonly int _size;
|
||||||
|
private readonly int _granularity;
|
||||||
|
private readonly int _bits;
|
||||||
|
private readonly int _writeBitOffset;
|
||||||
|
|
||||||
|
private readonly int _intsPerCb;
|
||||||
|
private readonly int _bitsPerCb;
|
||||||
|
|
||||||
|
public BufferUsageBitmap(int size, int granularity)
|
||||||
|
{
|
||||||
|
_size = size;
|
||||||
|
_granularity = granularity;
|
||||||
|
|
||||||
|
// There are two sets of bits - one for read tracking, and the other for write.
|
||||||
|
int bits = (size + (granularity - 1)) / granularity;
|
||||||
|
_writeBitOffset = bits;
|
||||||
|
_bits = bits << 1;
|
||||||
|
|
||||||
|
_intsPerCb = (_bits + (BitMap.IntSize - 1)) / BitMap.IntSize;
|
||||||
|
_bitsPerCb = _intsPerCb * BitMap.IntSize;
|
||||||
|
|
||||||
|
_bitmap = new BitMap(_bitsPerCb * CommandBufferPool.MaxCommandBuffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(int cbIndex, int offset, int size, bool write)
|
||||||
|
{
|
||||||
|
if (size == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some usages can be out of bounds (vertex buffer on amd), so bound if necessary.
|
||||||
|
if (offset + size > _size)
|
||||||
|
{
|
||||||
|
size = _size - offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cbBase = cbIndex * _bitsPerCb + (write ? _writeBitOffset : 0);
|
||||||
|
int start = cbBase + offset / _granularity;
|
||||||
|
int end = cbBase + (offset + size - 1) / _granularity;
|
||||||
|
|
||||||
|
_bitmap.SetRange(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool OverlapsWith(int cbIndex, int offset, int size, bool write = false)
|
||||||
|
{
|
||||||
|
if (size == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cbBase = cbIndex * _bitsPerCb + (write ? _writeBitOffset : 0);
|
||||||
|
int start = cbBase + offset / _granularity;
|
||||||
|
int end = cbBase + (offset + size - 1) / _granularity;
|
||||||
|
|
||||||
|
return _bitmap.IsSet(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool OverlapsWith(int offset, int size, bool write)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < CommandBufferPool.MaxCommandBuffers; i++)
|
||||||
|
{
|
||||||
|
if (OverlapsWith(i, offset, size, write))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear(int cbIndex)
|
||||||
|
{
|
||||||
|
_bitmap.ClearInt(cbIndex * _intsPerCb, (cbIndex + 1) * _intsPerCb - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
294
src/Ryujinx.Graphics.Metal/CacheByRange.cs
Normal file
294
src/Ryujinx.Graphics.Metal/CacheByRange.cs
Normal file
@@ -0,0 +1,294 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Metal
|
||||||
|
{
|
||||||
|
interface ICacheKey : IDisposable
|
||||||
|
{
|
||||||
|
bool KeyEqual(ICacheKey other);
|
||||||
|
}
|
||||||
|
|
||||||
|
[SupportedOSPlatform("macos")]
|
||||||
|
struct I8ToI16CacheKey : ICacheKey
|
||||||
|
{
|
||||||
|
// Used to notify the pipeline that bindings have invalidated on dispose.
|
||||||
|
// private readonly MetalRenderer _renderer;
|
||||||
|
// private Auto<DisposableBuffer> _buffer;
|
||||||
|
|
||||||
|
public I8ToI16CacheKey(MetalRenderer renderer)
|
||||||
|
{
|
||||||
|
// _renderer = renderer;
|
||||||
|
// _buffer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly bool KeyEqual(ICacheKey other)
|
||||||
|
{
|
||||||
|
return other is I8ToI16CacheKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly void SetBuffer(Auto<DisposableBuffer> buffer)
|
||||||
|
{
|
||||||
|
// _buffer = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly void Dispose()
|
||||||
|
{
|
||||||
|
// TODO: Tell pipeline buffer is dirty!
|
||||||
|
// _renderer.PipelineInternal.DirtyIndexBuffer(_buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[SupportedOSPlatform("macos")]
|
||||||
|
readonly struct TopologyConversionCacheKey : ICacheKey
|
||||||
|
{
|
||||||
|
private readonly IndexBufferPattern _pattern;
|
||||||
|
private readonly int _indexSize;
|
||||||
|
|
||||||
|
// Used to notify the pipeline that bindings have invalidated on dispose.
|
||||||
|
// private readonly MetalRenderer _renderer;
|
||||||
|
// private Auto<DisposableBuffer> _buffer;
|
||||||
|
|
||||||
|
public TopologyConversionCacheKey(MetalRenderer renderer, IndexBufferPattern pattern, int indexSize)
|
||||||
|
{
|
||||||
|
// _renderer = renderer;
|
||||||
|
// _buffer = null;
|
||||||
|
_pattern = pattern;
|
||||||
|
_indexSize = indexSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly bool KeyEqual(ICacheKey other)
|
||||||
|
{
|
||||||
|
return other is TopologyConversionCacheKey entry &&
|
||||||
|
entry._pattern == _pattern &&
|
||||||
|
entry._indexSize == _indexSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetBuffer(Auto<DisposableBuffer> buffer)
|
||||||
|
{
|
||||||
|
// _buffer = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly void Dispose()
|
||||||
|
{
|
||||||
|
// TODO: Tell pipeline buffer is dirty!
|
||||||
|
// _renderer.PipelineInternal.DirtyVertexBuffer(_buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[SupportedOSPlatform("macos")]
|
||||||
|
readonly struct Dependency
|
||||||
|
{
|
||||||
|
private readonly BufferHolder _buffer;
|
||||||
|
private readonly int _offset;
|
||||||
|
private readonly int _size;
|
||||||
|
private readonly ICacheKey _key;
|
||||||
|
|
||||||
|
public Dependency(BufferHolder buffer, int offset, int size, ICacheKey key)
|
||||||
|
{
|
||||||
|
_buffer = buffer;
|
||||||
|
_offset = offset;
|
||||||
|
_size = size;
|
||||||
|
_key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveFromOwner()
|
||||||
|
{
|
||||||
|
_buffer.RemoveCachedConvertedBuffer(_offset, _size, _key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[SupportedOSPlatform("macos")]
|
||||||
|
struct CacheByRange<T> where T : IDisposable
|
||||||
|
{
|
||||||
|
private struct Entry
|
||||||
|
{
|
||||||
|
public readonly ICacheKey Key;
|
||||||
|
public readonly T Value;
|
||||||
|
public List<Dependency> DependencyList;
|
||||||
|
|
||||||
|
public Entry(ICacheKey key, T value)
|
||||||
|
{
|
||||||
|
Key = key;
|
||||||
|
Value = value;
|
||||||
|
DependencyList = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly void InvalidateDependencies()
|
||||||
|
{
|
||||||
|
if (DependencyList != null)
|
||||||
|
{
|
||||||
|
foreach (Dependency dependency in DependencyList)
|
||||||
|
{
|
||||||
|
dependency.RemoveFromOwner();
|
||||||
|
}
|
||||||
|
|
||||||
|
DependencyList.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dictionary<ulong, List<Entry>> _ranges;
|
||||||
|
|
||||||
|
public void Add(int offset, int size, ICacheKey key, T value)
|
||||||
|
{
|
||||||
|
List<Entry> entries = GetEntries(offset, size);
|
||||||
|
|
||||||
|
entries.Add(new Entry(key, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddDependency(int offset, int size, ICacheKey key, Dependency dependency)
|
||||||
|
{
|
||||||
|
List<Entry> entries = GetEntries(offset, size);
|
||||||
|
|
||||||
|
for (int i = 0; i < entries.Count; i++)
|
||||||
|
{
|
||||||
|
Entry entry = entries[i];
|
||||||
|
|
||||||
|
if (entry.Key.KeyEqual(key))
|
||||||
|
{
|
||||||
|
if (entry.DependencyList == null)
|
||||||
|
{
|
||||||
|
entry.DependencyList = new List<Dependency>();
|
||||||
|
entries[i] = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.DependencyList.Add(dependency);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Remove(int offset, int size, ICacheKey key)
|
||||||
|
{
|
||||||
|
List<Entry> entries = GetEntries(offset, size);
|
||||||
|
|
||||||
|
for (int i = 0; i < entries.Count; i++)
|
||||||
|
{
|
||||||
|
Entry entry = entries[i];
|
||||||
|
|
||||||
|
if (entry.Key.KeyEqual(key))
|
||||||
|
{
|
||||||
|
entries.RemoveAt(i--);
|
||||||
|
|
||||||
|
DestroyEntry(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entries.Count == 0)
|
||||||
|
{
|
||||||
|
_ranges.Remove(PackRange(offset, size));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetValue(int offset, int size, ICacheKey key, out T value)
|
||||||
|
{
|
||||||
|
List<Entry> entries = GetEntries(offset, size);
|
||||||
|
|
||||||
|
foreach (Entry entry in entries)
|
||||||
|
{
|
||||||
|
if (entry.Key.KeyEqual(key))
|
||||||
|
{
|
||||||
|
value = entry.Value;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
value = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
if (_ranges != null)
|
||||||
|
{
|
||||||
|
foreach (List<Entry> entries in _ranges.Values)
|
||||||
|
{
|
||||||
|
foreach (Entry entry in entries)
|
||||||
|
{
|
||||||
|
DestroyEntry(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_ranges.Clear();
|
||||||
|
_ranges = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly void ClearRange(int offset, int size)
|
||||||
|
{
|
||||||
|
if (_ranges != null && _ranges.Count > 0)
|
||||||
|
{
|
||||||
|
int end = offset + size;
|
||||||
|
|
||||||
|
List<ulong> toRemove = null;
|
||||||
|
|
||||||
|
foreach (KeyValuePair<ulong, List<Entry>> range in _ranges)
|
||||||
|
{
|
||||||
|
(int rOffset, int rSize) = UnpackRange(range.Key);
|
||||||
|
|
||||||
|
int rEnd = rOffset + rSize;
|
||||||
|
|
||||||
|
if (rEnd > offset && rOffset < end)
|
||||||
|
{
|
||||||
|
List<Entry> entries = range.Value;
|
||||||
|
|
||||||
|
foreach (Entry entry in entries)
|
||||||
|
{
|
||||||
|
DestroyEntry(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
(toRemove ??= new List<ulong>()).Add(range.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toRemove != null)
|
||||||
|
{
|
||||||
|
foreach (ulong range in toRemove)
|
||||||
|
{
|
||||||
|
_ranges.Remove(range);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Entry> GetEntries(int offset, int size)
|
||||||
|
{
|
||||||
|
_ranges ??= new Dictionary<ulong, List<Entry>>();
|
||||||
|
|
||||||
|
ulong key = PackRange(offset, size);
|
||||||
|
|
||||||
|
if (!_ranges.TryGetValue(key, out List<Entry> value))
|
||||||
|
{
|
||||||
|
value = new List<Entry>();
|
||||||
|
_ranges.Add(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DestroyEntry(Entry entry)
|
||||||
|
{
|
||||||
|
entry.Key.Dispose();
|
||||||
|
entry.Value?.Dispose();
|
||||||
|
entry.InvalidateDependencies();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ulong PackRange(int offset, int size)
|
||||||
|
{
|
||||||
|
return (uint)offset | ((ulong)size << 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static (int offset, int size) UnpackRange(ulong range)
|
||||||
|
{
|
||||||
|
return ((int)range, (int)(range >> 32));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
170
src/Ryujinx.Graphics.Metal/CommandBufferEncoder.cs
Normal file
170
src/Ryujinx.Graphics.Metal/CommandBufferEncoder.cs
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
using Ryujinx.Graphics.Metal;
|
||||||
|
using SharpMetal.Metal;
|
||||||
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
|
interface IEncoderFactory
|
||||||
|
{
|
||||||
|
MTLRenderCommandEncoder CreateRenderCommandEncoder();
|
||||||
|
MTLComputeCommandEncoder CreateComputeCommandEncoder();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tracks active encoder object for a command buffer.
|
||||||
|
/// </summary>
|
||||||
|
[SupportedOSPlatform("macos")]
|
||||||
|
class CommandBufferEncoder
|
||||||
|
{
|
||||||
|
public EncoderType CurrentEncoderType { get; private set; } = EncoderType.None;
|
||||||
|
|
||||||
|
public MTLBlitCommandEncoder BlitEncoder => new(CurrentEncoder.Value);
|
||||||
|
|
||||||
|
public MTLComputeCommandEncoder ComputeEncoder => new(CurrentEncoder.Value);
|
||||||
|
|
||||||
|
public MTLRenderCommandEncoder RenderEncoder => new(CurrentEncoder.Value);
|
||||||
|
|
||||||
|
internal MTLCommandEncoder? CurrentEncoder { get; private set; }
|
||||||
|
|
||||||
|
private MTLCommandBuffer _commandBuffer;
|
||||||
|
private IEncoderFactory _encoderFactory;
|
||||||
|
|
||||||
|
public void Initialize(MTLCommandBuffer commandBuffer, IEncoderFactory encoderFactory)
|
||||||
|
{
|
||||||
|
_commandBuffer = commandBuffer;
|
||||||
|
_encoderFactory = encoderFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public MTLRenderCommandEncoder EnsureRenderEncoder()
|
||||||
|
{
|
||||||
|
if (CurrentEncoderType != EncoderType.Render)
|
||||||
|
{
|
||||||
|
return BeginRenderPass();
|
||||||
|
}
|
||||||
|
|
||||||
|
return RenderEncoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public MTLBlitCommandEncoder EnsureBlitEncoder()
|
||||||
|
{
|
||||||
|
if (CurrentEncoderType != EncoderType.Blit)
|
||||||
|
{
|
||||||
|
return BeginBlitPass();
|
||||||
|
}
|
||||||
|
|
||||||
|
return BlitEncoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public MTLComputeCommandEncoder EnsureComputeEncoder()
|
||||||
|
{
|
||||||
|
if (CurrentEncoderType != EncoderType.Compute)
|
||||||
|
{
|
||||||
|
return BeginComputePass();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ComputeEncoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool TryGetRenderEncoder(out MTLRenderCommandEncoder encoder)
|
||||||
|
{
|
||||||
|
if (CurrentEncoderType != EncoderType.Render)
|
||||||
|
{
|
||||||
|
encoder = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
encoder = RenderEncoder;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool TryGetBlitEncoder(out MTLBlitCommandEncoder encoder)
|
||||||
|
{
|
||||||
|
if (CurrentEncoderType != EncoderType.Blit)
|
||||||
|
{
|
||||||
|
encoder = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
encoder = BlitEncoder;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool TryGetComputeEncoder(out MTLComputeCommandEncoder encoder)
|
||||||
|
{
|
||||||
|
if (CurrentEncoderType != EncoderType.Compute)
|
||||||
|
{
|
||||||
|
encoder = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
encoder = ComputeEncoder;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void EndCurrentPass()
|
||||||
|
{
|
||||||
|
if (CurrentEncoder != null)
|
||||||
|
{
|
||||||
|
switch (CurrentEncoderType)
|
||||||
|
{
|
||||||
|
case EncoderType.Blit:
|
||||||
|
BlitEncoder.EndEncoding();
|
||||||
|
CurrentEncoder = null;
|
||||||
|
break;
|
||||||
|
case EncoderType.Compute:
|
||||||
|
ComputeEncoder.EndEncoding();
|
||||||
|
CurrentEncoder = null;
|
||||||
|
break;
|
||||||
|
case EncoderType.Render:
|
||||||
|
RenderEncoder.EndEncoding();
|
||||||
|
CurrentEncoder = null;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
CurrentEncoderType = EncoderType.None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private MTLRenderCommandEncoder BeginRenderPass()
|
||||||
|
{
|
||||||
|
EndCurrentPass();
|
||||||
|
|
||||||
|
var renderCommandEncoder = _encoderFactory.CreateRenderCommandEncoder();
|
||||||
|
|
||||||
|
CurrentEncoder = renderCommandEncoder;
|
||||||
|
CurrentEncoderType = EncoderType.Render;
|
||||||
|
|
||||||
|
return renderCommandEncoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
private MTLBlitCommandEncoder BeginBlitPass()
|
||||||
|
{
|
||||||
|
EndCurrentPass();
|
||||||
|
|
||||||
|
using var descriptor = new MTLBlitPassDescriptor();
|
||||||
|
var blitCommandEncoder = _commandBuffer.BlitCommandEncoder(descriptor);
|
||||||
|
|
||||||
|
CurrentEncoder = blitCommandEncoder;
|
||||||
|
CurrentEncoderType = EncoderType.Blit;
|
||||||
|
return blitCommandEncoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
private MTLComputeCommandEncoder BeginComputePass()
|
||||||
|
{
|
||||||
|
EndCurrentPass();
|
||||||
|
|
||||||
|
var computeCommandEncoder = _encoderFactory.CreateComputeCommandEncoder();
|
||||||
|
|
||||||
|
CurrentEncoder = computeCommandEncoder;
|
||||||
|
CurrentEncoderType = EncoderType.Compute;
|
||||||
|
return computeCommandEncoder;
|
||||||
|
}
|
||||||
|
}
|
289
src/Ryujinx.Graphics.Metal/CommandBufferPool.cs
Normal file
289
src/Ryujinx.Graphics.Metal/CommandBufferPool.cs
Normal file
@@ -0,0 +1,289 @@
|
|||||||
|
using SharpMetal.Metal;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Runtime.Versioning;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Metal
|
||||||
|
{
|
||||||
|
[SupportedOSPlatform("macos")]
|
||||||
|
class CommandBufferPool : IDisposable
|
||||||
|
{
|
||||||
|
public const int MaxCommandBuffers = 16;
|
||||||
|
|
||||||
|
private readonly int _totalCommandBuffers;
|
||||||
|
private readonly int _totalCommandBuffersMask;
|
||||||
|
private readonly MTLCommandQueue _queue;
|
||||||
|
private readonly Thread _owner;
|
||||||
|
private IEncoderFactory _defaultEncoderFactory;
|
||||||
|
|
||||||
|
public bool OwnedByCurrentThread => _owner == Thread.CurrentThread;
|
||||||
|
|
||||||
|
[SupportedOSPlatform("macos")]
|
||||||
|
private struct ReservedCommandBuffer
|
||||||
|
{
|
||||||
|
public bool InUse;
|
||||||
|
public bool InConsumption;
|
||||||
|
public int SubmissionCount;
|
||||||
|
public MTLCommandBuffer CommandBuffer;
|
||||||
|
public CommandBufferEncoder Encoders;
|
||||||
|
public FenceHolder Fence;
|
||||||
|
|
||||||
|
public List<IAuto> Dependants;
|
||||||
|
public List<MultiFenceHolder> Waitables;
|
||||||
|
|
||||||
|
public void Use(MTLCommandQueue queue, IEncoderFactory stateManager)
|
||||||
|
{
|
||||||
|
MTLCommandBufferDescriptor descriptor = new();
|
||||||
|
#if DEBUG
|
||||||
|
descriptor.ErrorOptions = MTLCommandBufferErrorOption.EncoderExecutionStatus;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CommandBuffer = queue.CommandBuffer(descriptor);
|
||||||
|
Fence = new FenceHolder(CommandBuffer);
|
||||||
|
|
||||||
|
Encoders.Initialize(CommandBuffer, stateManager);
|
||||||
|
|
||||||
|
InUse = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Initialize()
|
||||||
|
{
|
||||||
|
Dependants = new List<IAuto>();
|
||||||
|
Waitables = new List<MultiFenceHolder>();
|
||||||
|
Encoders = new CommandBufferEncoder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly ReservedCommandBuffer[] _commandBuffers;
|
||||||
|
|
||||||
|
private readonly int[] _queuedIndexes;
|
||||||
|
private int _queuedIndexesPtr;
|
||||||
|
private int _queuedCount;
|
||||||
|
private int _inUseCount;
|
||||||
|
|
||||||
|
public CommandBufferPool(MTLCommandQueue queue, bool isLight = false)
|
||||||
|
{
|
||||||
|
_queue = queue;
|
||||||
|
_owner = Thread.CurrentThread;
|
||||||
|
|
||||||
|
_totalCommandBuffers = isLight ? 2 : MaxCommandBuffers;
|
||||||
|
_totalCommandBuffersMask = _totalCommandBuffers - 1;
|
||||||
|
|
||||||
|
_commandBuffers = new ReservedCommandBuffer[_totalCommandBuffers];
|
||||||
|
|
||||||
|
_queuedIndexes = new int[_totalCommandBuffers];
|
||||||
|
_queuedIndexesPtr = 0;
|
||||||
|
_queuedCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Initialize(IEncoderFactory encoderFactory)
|
||||||
|
{
|
||||||
|
_defaultEncoderFactory = encoderFactory;
|
||||||
|
|
||||||
|
for (int i = 0; i < _totalCommandBuffers; i++)
|
||||||
|
{
|
||||||
|
_commandBuffers[i].Initialize();
|
||||||
|
WaitAndDecrementRef(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddDependant(int cbIndex, IAuto dependant)
|
||||||
|
{
|
||||||
|
dependant.IncrementReferenceCount();
|
||||||
|
_commandBuffers[cbIndex].Dependants.Add(dependant);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddWaitable(MultiFenceHolder waitable)
|
||||||
|
{
|
||||||
|
lock (_commandBuffers)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _totalCommandBuffers; i++)
|
||||||
|
{
|
||||||
|
ref var entry = ref _commandBuffers[i];
|
||||||
|
|
||||||
|
if (entry.InConsumption)
|
||||||
|
{
|
||||||
|
AddWaitable(i, waitable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddInUseWaitable(MultiFenceHolder waitable)
|
||||||
|
{
|
||||||
|
lock (_commandBuffers)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _totalCommandBuffers; i++)
|
||||||
|
{
|
||||||
|
ref var entry = ref _commandBuffers[i];
|
||||||
|
|
||||||
|
if (entry.InUse)
|
||||||
|
{
|
||||||
|
AddWaitable(i, waitable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddWaitable(int cbIndex, MultiFenceHolder waitable)
|
||||||
|
{
|
||||||
|
ref var entry = ref _commandBuffers[cbIndex];
|
||||||
|
if (waitable.AddFence(cbIndex, entry.Fence))
|
||||||
|
{
|
||||||
|
entry.Waitables.Add(waitable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsFenceOnRentedCommandBuffer(FenceHolder fence)
|
||||||
|
{
|
||||||
|
lock (_commandBuffers)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _totalCommandBuffers; i++)
|
||||||
|
{
|
||||||
|
ref var entry = ref _commandBuffers[i];
|
||||||
|
|
||||||
|
if (entry.InUse && entry.Fence == fence)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FenceHolder GetFence(int cbIndex)
|
||||||
|
{
|
||||||
|
return _commandBuffers[cbIndex].Fence;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetSubmissionCount(int cbIndex)
|
||||||
|
{
|
||||||
|
return _commandBuffers[cbIndex].SubmissionCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int FreeConsumed(bool wait)
|
||||||
|
{
|
||||||
|
int freeEntry = 0;
|
||||||
|
|
||||||
|
while (_queuedCount > 0)
|
||||||
|
{
|
||||||
|
int index = _queuedIndexes[_queuedIndexesPtr];
|
||||||
|
|
||||||
|
ref var entry = ref _commandBuffers[index];
|
||||||
|
|
||||||
|
if (wait || !entry.InConsumption || entry.Fence.IsSignaled())
|
||||||
|
{
|
||||||
|
WaitAndDecrementRef(index);
|
||||||
|
|
||||||
|
wait = false;
|
||||||
|
freeEntry = index;
|
||||||
|
|
||||||
|
_queuedCount--;
|
||||||
|
_queuedIndexesPtr = (_queuedIndexesPtr + 1) % _totalCommandBuffers;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return freeEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandBufferScoped ReturnAndRent(CommandBufferScoped cbs)
|
||||||
|
{
|
||||||
|
Return(cbs);
|
||||||
|
return Rent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandBufferScoped Rent()
|
||||||
|
{
|
||||||
|
lock (_commandBuffers)
|
||||||
|
{
|
||||||
|
int cursor = FreeConsumed(_inUseCount + _queuedCount == _totalCommandBuffers);
|
||||||
|
|
||||||
|
for (int i = 0; i < _totalCommandBuffers; i++)
|
||||||
|
{
|
||||||
|
ref var entry = ref _commandBuffers[cursor];
|
||||||
|
|
||||||
|
if (!entry.InUse && !entry.InConsumption)
|
||||||
|
{
|
||||||
|
entry.Use(_queue, _defaultEncoderFactory);
|
||||||
|
|
||||||
|
_inUseCount++;
|
||||||
|
|
||||||
|
return new CommandBufferScoped(this, entry.CommandBuffer, entry.Encoders, cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor = (cursor + 1) & _totalCommandBuffersMask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new InvalidOperationException($"Out of command buffers (In use: {_inUseCount}, queued: {_queuedCount}, total: {_totalCommandBuffers})");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Return(CommandBufferScoped cbs)
|
||||||
|
{
|
||||||
|
// Ensure the encoder is committed.
|
||||||
|
cbs.Encoders.EndCurrentPass();
|
||||||
|
|
||||||
|
lock (_commandBuffers)
|
||||||
|
{
|
||||||
|
int cbIndex = cbs.CommandBufferIndex;
|
||||||
|
|
||||||
|
ref var entry = ref _commandBuffers[cbIndex];
|
||||||
|
|
||||||
|
Debug.Assert(entry.InUse);
|
||||||
|
Debug.Assert(entry.CommandBuffer.NativePtr == cbs.CommandBuffer.NativePtr);
|
||||||
|
entry.InUse = false;
|
||||||
|
entry.InConsumption = true;
|
||||||
|
entry.SubmissionCount++;
|
||||||
|
_inUseCount--;
|
||||||
|
|
||||||
|
var commandBuffer = entry.CommandBuffer;
|
||||||
|
commandBuffer.Commit();
|
||||||
|
|
||||||
|
int ptr = (_queuedIndexesPtr + _queuedCount) % _totalCommandBuffers;
|
||||||
|
_queuedIndexes[ptr] = cbIndex;
|
||||||
|
_queuedCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WaitAndDecrementRef(int cbIndex)
|
||||||
|
{
|
||||||
|
ref var entry = ref _commandBuffers[cbIndex];
|
||||||
|
|
||||||
|
if (entry.InConsumption)
|
||||||
|
{
|
||||||
|
entry.Fence.Wait();
|
||||||
|
entry.InConsumption = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var dependant in entry.Dependants)
|
||||||
|
{
|
||||||
|
dependant.DecrementReferenceCount(cbIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var waitable in entry.Waitables)
|
||||||
|
{
|
||||||
|
waitable.RemoveFence(cbIndex);
|
||||||
|
waitable.RemoveBufferUses(cbIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.Dependants.Clear();
|
||||||
|
entry.Waitables.Clear();
|
||||||
|
entry.Fence?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _totalCommandBuffers; i++)
|
||||||
|
{
|
||||||
|
WaitAndDecrementRef(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
43
src/Ryujinx.Graphics.Metal/CommandBufferScoped.cs
Normal file
43
src/Ryujinx.Graphics.Metal/CommandBufferScoped.cs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
using SharpMetal.Metal;
|
||||||
|
using System;
|
||||||
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Metal
|
||||||
|
{
|
||||||
|
[SupportedOSPlatform("macos")]
|
||||||
|
readonly struct CommandBufferScoped : IDisposable
|
||||||
|
{
|
||||||
|
private readonly CommandBufferPool _pool;
|
||||||
|
public MTLCommandBuffer CommandBuffer { get; }
|
||||||
|
public CommandBufferEncoder Encoders { get; }
|
||||||
|
public int CommandBufferIndex { get; }
|
||||||
|
|
||||||
|
public CommandBufferScoped(CommandBufferPool pool, MTLCommandBuffer commandBuffer, CommandBufferEncoder encoders, int commandBufferIndex)
|
||||||
|
{
|
||||||
|
_pool = pool;
|
||||||
|
CommandBuffer = commandBuffer;
|
||||||
|
Encoders = encoders;
|
||||||
|
CommandBufferIndex = commandBufferIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddDependant(IAuto dependant)
|
||||||
|
{
|
||||||
|
_pool.AddDependant(CommandBufferIndex, dependant);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddWaitable(MultiFenceHolder waitable)
|
||||||
|
{
|
||||||
|
_pool.AddWaitable(CommandBufferIndex, waitable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FenceHolder GetFence()
|
||||||
|
{
|
||||||
|
return _pool.GetFence(CommandBufferIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_pool?.Return(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
41
src/Ryujinx.Graphics.Metal/Constants.cs
Normal file
41
src/Ryujinx.Graphics.Metal/Constants.cs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
namespace Ryujinx.Graphics.Metal
|
||||||
|
{
|
||||||
|
static class Constants
|
||||||
|
{
|
||||||
|
public const int MaxShaderStages = 5;
|
||||||
|
public const int MaxVertexBuffers = 16;
|
||||||
|
public const int MaxUniformBuffersPerStage = 18;
|
||||||
|
public const int MaxStorageBuffersPerStage = 16;
|
||||||
|
public const int MaxTexturesPerStage = 64;
|
||||||
|
public const int MaxImagesPerStage = 16;
|
||||||
|
|
||||||
|
public const int MaxUniformBufferBindings = MaxUniformBuffersPerStage * MaxShaderStages;
|
||||||
|
public const int MaxStorageBufferBindings = MaxStorageBuffersPerStage * MaxShaderStages;
|
||||||
|
public const int MaxTextureBindings = MaxTexturesPerStage * MaxShaderStages;
|
||||||
|
public const int MaxImageBindings = MaxImagesPerStage * MaxShaderStages;
|
||||||
|
public const int MaxColorAttachments = 8;
|
||||||
|
public const int MaxViewports = 16;
|
||||||
|
// TODO: Check this value
|
||||||
|
public const int MaxVertexAttributes = 31;
|
||||||
|
|
||||||
|
public const int MinResourceAlignment = 16;
|
||||||
|
|
||||||
|
// Must match constants set in shader generation
|
||||||
|
public const uint ZeroBufferIndex = MaxVertexBuffers;
|
||||||
|
public const uint BaseSetIndex = MaxVertexBuffers + 1;
|
||||||
|
|
||||||
|
public const uint ConstantBuffersIndex = BaseSetIndex;
|
||||||
|
public const uint StorageBuffersIndex = BaseSetIndex + 1;
|
||||||
|
public const uint TexturesIndex = BaseSetIndex + 2;
|
||||||
|
public const uint ImagesIndex = BaseSetIndex + 3;
|
||||||
|
|
||||||
|
public const uint ConstantBuffersSetIndex = 0;
|
||||||
|
public const uint StorageBuffersSetIndex = 1;
|
||||||
|
public const uint TexturesSetIndex = 2;
|
||||||
|
public const uint ImagesSetIndex = 3;
|
||||||
|
|
||||||
|
public const uint MaximumBufferArgumentTableEntries = 31;
|
||||||
|
|
||||||
|
public const uint MaximumExtraSets = MaximumBufferArgumentTableEntries - ImagesIndex;
|
||||||
|
}
|
||||||
|
}
|
22
src/Ryujinx.Graphics.Metal/CounterEvent.cs
Normal file
22
src/Ryujinx.Graphics.Metal/CounterEvent.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
using Ryujinx.Graphics.GAL;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Metal
|
||||||
|
{
|
||||||
|
class CounterEvent : ICounterEvent
|
||||||
|
{
|
||||||
|
public CounterEvent()
|
||||||
|
{
|
||||||
|
Invalid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Invalid { get; set; }
|
||||||
|
public bool ReserveForHostAccess()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Flush() { }
|
||||||
|
|
||||||
|
public void Dispose() { }
|
||||||
|
}
|
||||||
|
}
|
68
src/Ryujinx.Graphics.Metal/DepthStencilCache.cs
Normal file
68
src/Ryujinx.Graphics.Metal/DepthStencilCache.cs
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
using Ryujinx.Graphics.Metal.State;
|
||||||
|
using SharpMetal.Metal;
|
||||||
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Metal
|
||||||
|
{
|
||||||
|
[SupportedOSPlatform("macos")]
|
||||||
|
class DepthStencilCache : StateCache<MTLDepthStencilState, DepthStencilUid, DepthStencilUid>
|
||||||
|
{
|
||||||
|
private readonly MTLDevice _device;
|
||||||
|
|
||||||
|
public DepthStencilCache(MTLDevice device)
|
||||||
|
{
|
||||||
|
_device = device;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override DepthStencilUid GetHash(DepthStencilUid descriptor)
|
||||||
|
{
|
||||||
|
return descriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override MTLDepthStencilState CreateValue(DepthStencilUid descriptor)
|
||||||
|
{
|
||||||
|
// Create descriptors
|
||||||
|
|
||||||
|
ref StencilUid frontUid = ref descriptor.FrontFace;
|
||||||
|
|
||||||
|
using var frontFaceStencil = new MTLStencilDescriptor
|
||||||
|
{
|
||||||
|
StencilFailureOperation = frontUid.StencilFailureOperation,
|
||||||
|
DepthFailureOperation = frontUid.DepthFailureOperation,
|
||||||
|
DepthStencilPassOperation = frontUid.DepthStencilPassOperation,
|
||||||
|
StencilCompareFunction = frontUid.StencilCompareFunction,
|
||||||
|
ReadMask = frontUid.ReadMask,
|
||||||
|
WriteMask = frontUid.WriteMask
|
||||||
|
};
|
||||||
|
|
||||||
|
ref StencilUid backUid = ref descriptor.BackFace;
|
||||||
|
|
||||||
|
using var backFaceStencil = new MTLStencilDescriptor
|
||||||
|
{
|
||||||
|
StencilFailureOperation = backUid.StencilFailureOperation,
|
||||||
|
DepthFailureOperation = backUid.DepthFailureOperation,
|
||||||
|
DepthStencilPassOperation = backUid.DepthStencilPassOperation,
|
||||||
|
StencilCompareFunction = backUid.StencilCompareFunction,
|
||||||
|
ReadMask = backUid.ReadMask,
|
||||||
|
WriteMask = backUid.WriteMask
|
||||||
|
};
|
||||||
|
|
||||||
|
var mtlDescriptor = new MTLDepthStencilDescriptor
|
||||||
|
{
|
||||||
|
DepthCompareFunction = descriptor.DepthCompareFunction,
|
||||||
|
DepthWriteEnabled = descriptor.DepthWriteEnabled
|
||||||
|
};
|
||||||
|
|
||||||
|
if (descriptor.StencilTestEnabled)
|
||||||
|
{
|
||||||
|
mtlDescriptor.BackFaceStencil = backFaceStencil;
|
||||||
|
mtlDescriptor.FrontFaceStencil = frontFaceStencil;
|
||||||
|
}
|
||||||
|
|
||||||
|
using (mtlDescriptor)
|
||||||
|
{
|
||||||
|
return _device.NewDepthStencilState(mtlDescriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
26
src/Ryujinx.Graphics.Metal/DisposableBuffer.cs
Normal file
26
src/Ryujinx.Graphics.Metal/DisposableBuffer.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using SharpMetal.Metal;
|
||||||
|
using System;
|
||||||
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Metal
|
||||||
|
{
|
||||||
|
[SupportedOSPlatform("macos")]
|
||||||
|
readonly struct DisposableBuffer : IDisposable
|
||||||
|
{
|
||||||
|
public MTLBuffer Value { get; }
|
||||||
|
|
||||||
|
public DisposableBuffer(MTLBuffer buffer)
|
||||||
|
{
|
||||||
|
Value = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (Value != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
Value.SetPurgeableState(MTLPurgeableState.Empty);
|
||||||
|
Value.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
src/Ryujinx.Graphics.Metal/DisposableSampler.cs
Normal file
22
src/Ryujinx.Graphics.Metal/DisposableSampler.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
using SharpMetal.Metal;
|
||||||
|
using System;
|
||||||
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Metal
|
||||||
|
{
|
||||||
|
[SupportedOSPlatform("macos")]
|
||||||
|
readonly struct DisposableSampler : IDisposable
|
||||||
|
{
|
||||||
|
public MTLSamplerState Value { get; }
|
||||||
|
|
||||||
|
public DisposableSampler(MTLSamplerState sampler)
|
||||||
|
{
|
||||||
|
Value = sampler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Value.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
src/Ryujinx.Graphics.Metal/Effects/IPostProcessingEffect.cs
Normal file
10
src/Ryujinx.Graphics.Metal/Effects/IPostProcessingEffect.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Metal.Effects
|
||||||
|
{
|
||||||
|
internal interface IPostProcessingEffect : IDisposable
|
||||||
|
{
|
||||||
|
const int LocalGroupSize = 64;
|
||||||
|
Texture Run(Texture view, int width, int height);
|
||||||
|
}
|
||||||
|
}
|
18
src/Ryujinx.Graphics.Metal/Effects/IScalingFilter.cs
Normal file
18
src/Ryujinx.Graphics.Metal/Effects/IScalingFilter.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using Ryujinx.Graphics.GAL;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Metal.Effects
|
||||||
|
{
|
||||||
|
internal interface IScalingFilter : IDisposable
|
||||||
|
{
|
||||||
|
float Level { get; set; }
|
||||||
|
void Run(
|
||||||
|
Texture view,
|
||||||
|
Texture destinationTexture,
|
||||||
|
Format format,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
Extents2D source,
|
||||||
|
Extents2D destination);
|
||||||
|
}
|
||||||
|
}
|
63
src/Ryujinx.Graphics.Metal/EncoderResources.cs
Normal file
63
src/Ryujinx.Graphics.Metal/EncoderResources.cs
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
using SharpMetal.Metal;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Metal
|
||||||
|
{
|
||||||
|
public struct RenderEncoderBindings
|
||||||
|
{
|
||||||
|
public List<Resource> Resources = new();
|
||||||
|
public List<BufferResource> VertexBuffers = new();
|
||||||
|
public List<BufferResource> FragmentBuffers = new();
|
||||||
|
|
||||||
|
public RenderEncoderBindings() { }
|
||||||
|
|
||||||
|
public readonly void Clear()
|
||||||
|
{
|
||||||
|
Resources.Clear();
|
||||||
|
VertexBuffers.Clear();
|
||||||
|
FragmentBuffers.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct ComputeEncoderBindings
|
||||||
|
{
|
||||||
|
public List<Resource> Resources = new();
|
||||||
|
public List<BufferResource> Buffers = new();
|
||||||
|
|
||||||
|
public ComputeEncoderBindings() { }
|
||||||
|
|
||||||
|
public readonly void Clear()
|
||||||
|
{
|
||||||
|
Resources.Clear();
|
||||||
|
Buffers.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct BufferResource
|
||||||
|
{
|
||||||
|
public MTLBuffer Buffer;
|
||||||
|
public ulong Offset;
|
||||||
|
public ulong Binding;
|
||||||
|
|
||||||
|
public BufferResource(MTLBuffer buffer, ulong offset, ulong binding)
|
||||||
|
{
|
||||||
|
Buffer = buffer;
|
||||||
|
Offset = offset;
|
||||||
|
Binding = binding;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct Resource
|
||||||
|
{
|
||||||
|
public MTLResource MtlResource;
|
||||||
|
public MTLResourceUsage ResourceUsage;
|
||||||
|
public MTLRenderStages Stages;
|
||||||
|
|
||||||
|
public Resource(MTLResource resource, MTLResourceUsage resourceUsage, MTLRenderStages stages)
|
||||||
|
{
|
||||||
|
MtlResource = resource;
|
||||||
|
ResourceUsage = resourceUsage;
|
||||||
|
Stages = stages;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
206
src/Ryujinx.Graphics.Metal/EncoderState.cs
Normal file
206
src/Ryujinx.Graphics.Metal/EncoderState.cs
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
using Ryujinx.Common.Memory;
|
||||||
|
using Ryujinx.Graphics.GAL;
|
||||||
|
using Ryujinx.Graphics.Metal.State;
|
||||||
|
using Ryujinx.Graphics.Shader;
|
||||||
|
using SharpMetal.Metal;
|
||||||
|
using System;
|
||||||
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Metal
|
||||||
|
{
|
||||||
|
[Flags]
|
||||||
|
enum DirtyFlags
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
RenderPipeline = 1 << 0,
|
||||||
|
ComputePipeline = 1 << 1,
|
||||||
|
DepthStencil = 1 << 2,
|
||||||
|
DepthClamp = 1 << 3,
|
||||||
|
DepthBias = 1 << 4,
|
||||||
|
CullMode = 1 << 5,
|
||||||
|
FrontFace = 1 << 6,
|
||||||
|
StencilRef = 1 << 7,
|
||||||
|
Viewports = 1 << 8,
|
||||||
|
Scissors = 1 << 9,
|
||||||
|
Uniforms = 1 << 10,
|
||||||
|
Storages = 1 << 11,
|
||||||
|
Textures = 1 << 12,
|
||||||
|
Images = 1 << 13,
|
||||||
|
|
||||||
|
ArgBuffers = Uniforms | Storages | Textures | Images,
|
||||||
|
|
||||||
|
RenderAll = RenderPipeline | DepthStencil | DepthClamp | DepthBias | CullMode | FrontFace | StencilRef | Viewports | Scissors | ArgBuffers,
|
||||||
|
ComputeAll = ComputePipeline | ArgBuffers,
|
||||||
|
All = RenderAll | ComputeAll,
|
||||||
|
}
|
||||||
|
|
||||||
|
record struct BufferRef
|
||||||
|
{
|
||||||
|
public Auto<DisposableBuffer> Buffer;
|
||||||
|
public BufferRange? Range;
|
||||||
|
|
||||||
|
public BufferRef(Auto<DisposableBuffer> buffer)
|
||||||
|
{
|
||||||
|
Buffer = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BufferRef(Auto<DisposableBuffer> buffer, ref BufferRange range)
|
||||||
|
{
|
||||||
|
Buffer = buffer;
|
||||||
|
Range = range;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
record struct TextureRef
|
||||||
|
{
|
||||||
|
public ShaderStage Stage;
|
||||||
|
public TextureBase Storage;
|
||||||
|
public Auto<DisposableSampler> Sampler;
|
||||||
|
public Format ImageFormat;
|
||||||
|
|
||||||
|
public TextureRef(ShaderStage stage, TextureBase storage, Auto<DisposableSampler> sampler)
|
||||||
|
{
|
||||||
|
Stage = stage;
|
||||||
|
Storage = storage;
|
||||||
|
Sampler = sampler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
record struct ImageRef
|
||||||
|
{
|
||||||
|
public ShaderStage Stage;
|
||||||
|
public Texture Storage;
|
||||||
|
|
||||||
|
public ImageRef(ShaderStage stage, Texture storage)
|
||||||
|
{
|
||||||
|
Stage = stage;
|
||||||
|
Storage = storage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PredrawState
|
||||||
|
{
|
||||||
|
public MTLCullMode CullMode;
|
||||||
|
public DepthStencilUid DepthStencilUid;
|
||||||
|
public PrimitiveTopology Topology;
|
||||||
|
public MTLViewport[] Viewports;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RenderTargetCopy
|
||||||
|
{
|
||||||
|
public MTLScissorRect[] Scissors;
|
||||||
|
public Texture DepthStencil;
|
||||||
|
public Texture[] RenderTargets;
|
||||||
|
}
|
||||||
|
|
||||||
|
[SupportedOSPlatform("macos")]
|
||||||
|
class EncoderState
|
||||||
|
{
|
||||||
|
public Program RenderProgram = null;
|
||||||
|
public Program ComputeProgram = null;
|
||||||
|
|
||||||
|
public PipelineState Pipeline;
|
||||||
|
public DepthStencilUid DepthStencilUid;
|
||||||
|
|
||||||
|
public readonly record struct ArrayRef<T>(ShaderStage Stage, T Array);
|
||||||
|
|
||||||
|
public readonly BufferRef[] UniformBufferRefs = new BufferRef[Constants.MaxUniformBufferBindings];
|
||||||
|
public readonly BufferRef[] StorageBufferRefs = new BufferRef[Constants.MaxStorageBufferBindings];
|
||||||
|
public readonly TextureRef[] TextureRefs = new TextureRef[Constants.MaxTextureBindings * 2];
|
||||||
|
public readonly ImageRef[] ImageRefs = new ImageRef[Constants.MaxImageBindings * 2];
|
||||||
|
|
||||||
|
public ArrayRef<TextureArray>[] TextureArrayRefs = [];
|
||||||
|
public ArrayRef<ImageArray>[] ImageArrayRefs = [];
|
||||||
|
|
||||||
|
public ArrayRef<TextureArray>[] TextureArrayExtraRefs = [];
|
||||||
|
public ArrayRef<ImageArray>[] ImageArrayExtraRefs = [];
|
||||||
|
|
||||||
|
public IndexBufferState IndexBuffer = default;
|
||||||
|
|
||||||
|
public MTLDepthClipMode DepthClipMode = MTLDepthClipMode.Clip;
|
||||||
|
|
||||||
|
public float DepthBias;
|
||||||
|
public float SlopeScale;
|
||||||
|
public float Clamp;
|
||||||
|
|
||||||
|
public int BackRefValue = 0;
|
||||||
|
public int FrontRefValue = 0;
|
||||||
|
|
||||||
|
public PrimitiveTopology Topology = PrimitiveTopology.Triangles;
|
||||||
|
public MTLCullMode CullMode = MTLCullMode.None;
|
||||||
|
public MTLWinding Winding = MTLWinding.CounterClockwise;
|
||||||
|
public bool CullBoth = false;
|
||||||
|
|
||||||
|
public MTLViewport[] Viewports = new MTLViewport[Constants.MaxViewports];
|
||||||
|
public MTLScissorRect[] Scissors = new MTLScissorRect[Constants.MaxViewports];
|
||||||
|
|
||||||
|
// Changes to attachments take recreation!
|
||||||
|
public Texture DepthStencil;
|
||||||
|
public Texture[] RenderTargets = new Texture[Constants.MaxColorAttachments];
|
||||||
|
public ITexture PreMaskDepthStencil = default;
|
||||||
|
public ITexture[] PreMaskRenderTargets;
|
||||||
|
public bool FramebufferUsingColorWriteMask;
|
||||||
|
|
||||||
|
public Array8<ColorBlendStateUid> StoredBlend;
|
||||||
|
public ColorF BlendColor = new();
|
||||||
|
|
||||||
|
public readonly VertexBufferState[] VertexBuffers = new VertexBufferState[Constants.MaxVertexBuffers];
|
||||||
|
public readonly VertexAttribDescriptor[] VertexAttribs = new VertexAttribDescriptor[Constants.MaxVertexAttributes];
|
||||||
|
// Dirty flags
|
||||||
|
public DirtyFlags Dirty = DirtyFlags.None;
|
||||||
|
|
||||||
|
// Only to be used for present
|
||||||
|
public bool ClearLoadAction = false;
|
||||||
|
|
||||||
|
public RenderEncoderBindings RenderEncoderBindings = new();
|
||||||
|
public ComputeEncoderBindings ComputeEncoderBindings = new();
|
||||||
|
|
||||||
|
public EncoderState()
|
||||||
|
{
|
||||||
|
Pipeline.Initialize();
|
||||||
|
DepthStencilUid.DepthCompareFunction = MTLCompareFunction.Always;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RenderTargetCopy InheritForClear(EncoderState other, bool depth, int singleIndex = -1)
|
||||||
|
{
|
||||||
|
// Inherit render target related information without causing a render encoder split.
|
||||||
|
|
||||||
|
var oldState = new RenderTargetCopy
|
||||||
|
{
|
||||||
|
Scissors = other.Scissors,
|
||||||
|
RenderTargets = other.RenderTargets,
|
||||||
|
DepthStencil = other.DepthStencil
|
||||||
|
};
|
||||||
|
|
||||||
|
Scissors = other.Scissors;
|
||||||
|
RenderTargets = other.RenderTargets;
|
||||||
|
DepthStencil = other.DepthStencil;
|
||||||
|
|
||||||
|
Pipeline.ColorBlendAttachmentStateCount = other.Pipeline.ColorBlendAttachmentStateCount;
|
||||||
|
Pipeline.Internal.ColorBlendState = other.Pipeline.Internal.ColorBlendState;
|
||||||
|
Pipeline.DepthStencilFormat = other.Pipeline.DepthStencilFormat;
|
||||||
|
|
||||||
|
ref var blendStates = ref Pipeline.Internal.ColorBlendState;
|
||||||
|
|
||||||
|
// Mask out irrelevant attachments.
|
||||||
|
for (int i = 0; i < blendStates.Length; i++)
|
||||||
|
{
|
||||||
|
if (depth || (singleIndex != -1 && singleIndex != i))
|
||||||
|
{
|
||||||
|
blendStates[i].WriteMask = MTLColorWriteMask.None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return oldState;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Restore(RenderTargetCopy copy)
|
||||||
|
{
|
||||||
|
Scissors = copy.Scissors;
|
||||||
|
RenderTargets = copy.RenderTargets;
|
||||||
|
DepthStencil = copy.DepthStencil;
|
||||||
|
|
||||||
|
Pipeline.Internal.ResetColorState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1789
src/Ryujinx.Graphics.Metal/EncoderStateManager.cs
Normal file
1789
src/Ryujinx.Graphics.Metal/EncoderStateManager.cs
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user