Compare commits

...

23 Commits

Author SHA1 Message Date
Mary
6f28c4abad test: Make tests runnable on system without 4KiB page size (#5184)
* ARMeilleure: Do not hardcode 4KiB page size in JitCache

* test: Do not hardcode page size to 4KiB for Ryujinx.Tests.Memory.Tests

Fix running tests on Asahi Linux with 16KiB pages.

* test: Do not hardcode page size to 4KiB for Ryujinx.Tests.Cpu

Fix running tests on Asahi Linux.

Test runner still crash when trying to run all test suite.

* test: Do not hardcode page size to 4KiB for Ryujinx.Tests.Cpu

Fix somecrashes on Asahi Linux.

* test: Ignore Vshl test on ARM64 due to unicorn crashes

* test: Workaround hardcoded size on some tests

Change mapping of code and data in case of non 4KiB configuration.

* test: Make CpuTestT32Flow depends on code address

Fix failure with different page size.

* test: Disable CpuTestThumb.TestRandomTestCases when page size isn't 4KiB

The test data needs to be reevaluated to take different page size into account.

* Address gdkchan's comments
2023-06-14 18:02:41 +02:00
gdkchan
105c9712c1 Fix Arm32 double to int/uint conversion on Arm64 (#5292)
* Fix Arm32 double to int/uint conversion on Arm64

* PPTC version bump
2023-06-14 00:57:02 -03:00
Kurochi51
4d804ed45e Mod Loader: Stop loading mods from folders that don't exactly match titleId (#5298)
* Stop loading mods from folders that don't exactly match titleId

* What the worst that can happen?
2023-06-13 20:47:33 +02:00
Mary
4a27d29412 infra: Sync paths-ignore with release job and attempt to fix review assign 2023-06-13 11:51:22 +02:00
mmdurrant
5bd2c58ad6 UI: Correctly set 'shell/open/command; registry key for file associations (#5244)
* Correctly set 'shell/open/command; registry key for file associations

* File association fixes
* 'using' statements instead of blocks
* Idempotent unregistration
* Single "hey shell, we changed file associations" notification at the
  end instead of 1 for every operation, speeds things up greatly.

* Adapt and fix Linux specific function as well

---------

Co-authored-by: TSR Berry <20988865+TSRBerry@users.noreply.github.com>
2023-06-13 00:36:40 +00:00
gdkchan
cf4c78b9c8 Make LM skip instead of crashing for invalid messages (#5290) 2023-06-13 00:12:06 +00:00
TSRBerry
52aa4b6c22 Fix action version (#5299) 2023-06-12 21:57:07 +02:00
TSRBerry
5a02433080 infra: Fix PR triage workflow glob patterns (#5297)
* Use glob patterns to match file paths

* Update ignored paths for releases

* Adjust build.yml as well

* Add names to auto-assign steps

* Fix developer team name

* Allow build workflows to run if workflows changed
2023-06-12 18:42:27 +00:00
Steveice10
915a0f7173 hle: Stub IHidbusServer.GetBusHandle (#5284) 2023-06-12 17:33:13 +02:00
Mary
0cc266ff19 infra: Add PR triage action (#5293)
This is a bare minimal triage action that handle big categories.

In the future we could also label all services correctly but
I didn't felt this was required for a first iteration.
2023-06-12 12:29:41 +02:00
TSRBerry
9a1b74799d Ava: Fix OpenGL on Linux again (#5216)
* ava: Fix OpenGL on Linux again

This shouldn't be working like that, but for some reason it does.

* Apply the correct fix

* gtk: Add warning messages for caught exceptions

* ava: Handle disposing the same way as GTK does

* Address review feedback
2023-06-11 18:31:22 +02:00
Patrick Hovsepian
638f3761f3 Show/Hide UI Hotkey fix on Avalonia (#5133)
* fix show/hide ui for ava

* revert style

* unbound by default

* revert
2023-06-11 15:34:56 +02:00
gdkchan
193ca3c9a2 Implement fast path for AES crypto instructions on Arm64 (#5281)
* Implement fast path for AES crypto instructions on Arm64

* PPTC version bump

* Use AES HW feature check
2023-06-11 00:51:35 +00:00
gdkchan
eb0bb36bbf Implement transform feedback emulation for hardware without native support (#5080)
* Implement transform feedback emulation for hardware without native support

* Stop doing some useless buffer updates and account for non-zero base instance

* Reduce redundant updates even more

* Update descriptor init logic to account for ResourceLayout

* Fix transform feedback and storage buffers not being updated in some cases

* Shader cache version bump

* PR feedback

* SetInstancedDrawVertexCount must be always called after UpdateState

* Minor typo
2023-06-10 18:31:38 -03:00
Marco Carvalho
0e95a8271a Non-flags enums should not be used in bitwise operations (#5214) 2023-06-09 19:44:22 +02:00
Marco Carvalho
76b474e97b Update ShaderConfig.cs (#5226) 2023-06-09 14:53:20 +00:00
siegmund-heiss-ich
27ee86f33b Exclude macOS from checking for changed files (#5270) 2023-06-09 15:35:24 +02:00
siegmund-heiss-ich
f7ec310231 Check if existing oldConfigPath is a Symlink (#5271) 2023-06-09 15:31:19 +02:00
Marco Carvalho
e94d24f508 Prefer a 'TryGetValue' call over a Dictionary indexer access guarded by a 'ContainsKey' (#5231)
* Prefer a 'TryGetValue' call over a Dictionary indexer access guarded by a 'ContainsKey' check to avoid double lookup

* fix
2023-06-09 13:05:32 +02:00
Isaac Marovitz
2bf4555591 Swkbd Applet Fixes (#5236)
* Swkbd Applet Fixes

* Forgot a full stop

* Update src/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update src/Ryujinx/Ui/Applet/SwkbdAppletDialog.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

---------

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-06-09 12:11:53 +02:00
Marco Carvalho
86de288142 Removing shift by 0 (#5249)
* Integral numbers should not be shifted by zero or more than their number of bits-1

* more
2023-06-09 11:23:44 +02:00
dependabot[bot]
f35aa8e9d6 nuget: bump Microsoft.NET.Test.Sdk from 17.6.1 to 17.6.2 (#5250)
Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.6.1 to 17.6.2.
- [Release notes](https://github.com/microsoft/vstest/releases)
- [Changelog](https://github.com/microsoft/vstest/blob/main/docs/releases.md)
- [Commits](https://github.com/microsoft/vstest/compare/v17.6.1...v17.6.2)

---
updated-dependencies:
- dependency-name: Microsoft.NET.Test.Sdk
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-09 11:02:56 +02:00
dependabot[bot]
0e8e735a6d nuget: bump System.IdentityModel.Tokens.Jwt from 6.30.1 to 6.31.0 (#5265)
Bumps [System.IdentityModel.Tokens.Jwt](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) from 6.30.1 to 6.31.0.
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/compare/6.30.1...6.31.0)

---
updated-dependencies:
- dependency-name: System.IdentityModel.Tokens.Jwt
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-09 10:40:25 +02:00
88 changed files with 1406 additions and 652 deletions

8
.github/assign/audio.yml vendored Normal file
View File

@@ -0,0 +1,8 @@
addReviewers: true
reviewers:
- marysaka
filterLabels:
include:
- audio

11
.github/assign/cpu.yml vendored Normal file
View File

@@ -0,0 +1,11 @@
addReviewers: true
reviewers:
- gdkchan
- riperiperi
- marysaka
- LDj3SNuD
filterLabels:
include:
- cpu

4
.github/assign/global.yml vendored Normal file
View File

@@ -0,0 +1,4 @@
addReviewers: true
reviewers:
- Ryujinx/developers

10
.github/assign/gpu.yml vendored Normal file
View File

@@ -0,0 +1,10 @@
addReviewers: true
reviewers:
- gdkchan
- riperiperi
- marysaka
filterLabels:
include:
- gpu

11
.github/assign/gui.yml vendored Normal file
View File

@@ -0,0 +1,11 @@
addReviewers: true
reviewers:
- Ack77
- emmauss
- TSRBerry
- marysaka
filterLabels:
include:
- gui

11
.github/assign/horizon.yml vendored Normal file
View File

@@ -0,0 +1,11 @@
addReviewers: true
reviewers:
- gdkchan
- Ack77
- marysaka
- TSRBerry
filterLabels:
include:
- horizon

9
.github/assign/infra.yml vendored Normal file
View File

@@ -0,0 +1,9 @@
addReviewers: true
reviewers:
- marysaka
- TSRBerry
filterLabels:
include:
- infra

33
.github/labeler.yml vendored Normal file
View File

@@ -0,0 +1,33 @@
audio: 'src/Ryujinx.Audio*/**'
cpu:
- 'src/ARMeilleure/**'
- 'src/Ryujinx.Cpu/**'
- 'src/Ryujinx.Memory/**'
gpu:
- 'src/Ryujinx.Graphics.*/**'
- 'src/Spv.Generator/**'
- 'src/Ryujinx.ShaderTools/**'
'graphics-backend:opengl': 'src/Ryujinx.Graphics.OpenGL/**'
'graphics-backend:vulkan':
- 'src/Ryujinx.Graphics.Vulkan/**'
- 'src/Spv.Generator/**'
gui:
- 'src/Ryujinx/**'
- 'src/Ryujinx.Ui.Common/**'
- 'src/Ryujinx.Ui.LocaleGenerator/**'
- 'src/Ryujinx.Ava/**'
horizon:
- 'src/Ryujinx.HLE/**'
- 'src/Ryujinx.Horizon*/**'
kernel: 'src/Ryujinx.HLE/HOS/Kernel/**'
infra:
- '.github/**'
- 'distribution/**'
- 'Directory.Packages.props'

View File

@@ -3,19 +3,13 @@ name: Build job
on: on:
workflow_dispatch: workflow_dispatch:
inputs: {} inputs: {}
#push:
# branches: [ master ]
# paths-ignore:
# - '.github/*'
# - '.github/ISSUE_TEMPLATE/**'
# - '*.yml'
# - 'README.md'
pull_request: pull_request:
branches: [ master ] branches: [ master ]
paths-ignore: paths-ignore:
- '.github/*' - '.github/**'
- '.github/ISSUE_TEMPLATE/**'
- '*.yml' - '*.yml'
- '*.json'
- '*.config'
- 'README.md' - 'README.md'
concurrency: concurrency:

54
.github/workflows/pr_triage.yml vendored Normal file
View File

@@ -0,0 +1,54 @@
name: "Pull Request Triage"
on:
pull_request_target:
types: [opened, ready_for_review]
jobs:
triage:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- name: Update labels based on changes
uses: actions/labeler@v4
with:
sync-labels: true
dot: true
- name: Auto Assign [Audio]
uses: kentaro-m/auto-assign-action@v1.2.5
with:
configuration-path: '.github/assign/audio.yml'
- name: Auto Assign [CPU]
uses: kentaro-m/auto-assign-action@v1.2.5
with:
configuration-path: '.github/assign/cpu.yml'
- name: Auto Assign [GPU]
uses: kentaro-m/auto-assign-action@v1.2.5
with:
configuration-path: '.github/assign/gpu.yml'
- name: Auto Assign [GUI]
uses: kentaro-m/auto-assign-action@v1.2.5
with:
configuration-path: '.github/assign/gui.yml'
- name: Auto Assign [Horizon]
uses: kentaro-m/auto-assign-action@v1.2.5
with:
configuration-path: '.github/assign/horizon.yml'
- name: Auto Assign [Infra]
uses: kentaro-m/auto-assign-action@v1.2.5
with:
configuration-path: '.github/assign/infra.yml'
- name: Auto Assign [Global]
uses: kentaro-m/auto-assign-action@v1.2.5
with:
configuration-path: '.github/assign/global.yml'

View File

@@ -6,9 +6,10 @@ on:
push: push:
branches: [ master ] branches: [ master ]
paths-ignore: paths-ignore:
- '.github/*' - '.github/**'
- '.github/ISSUE_TEMPLATE/**'
- '*.yml' - '*.yml'
- '*.json'
- '*.config'
- 'README.md' - 'README.md'
concurrency: release concurrency: release

View File

@@ -21,7 +21,7 @@
<PackageVersion Include="LibHac" Version="0.18.0" /> <PackageVersion Include="LibHac" Version="0.18.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.5.0" /> <PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.6.1" /> <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.6.2" />
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="2.3.2" /> <PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="2.3.2" />
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" /> <PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
<PackageVersion Include="NUnit" Version="3.13.3" /> <PackageVersion Include="NUnit" Version="3.13.3" />
@@ -44,7 +44,7 @@
<PackageVersion Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta11" /> <PackageVersion Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta11" />
<PackageVersion Include="SPB" Version="0.0.4-build28" /> <PackageVersion Include="SPB" Version="0.0.4-build28" />
<PackageVersion Include="System.Drawing.Common" Version="7.0.0" /> <PackageVersion Include="System.Drawing.Common" Version="7.0.0" />
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="6.30.1" /> <PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="6.31.0" />
<PackageVersion Include="System.IO.Hashing" Version="7.0.0" /> <PackageVersion Include="System.IO.Hashing" Version="7.0.0" />
<PackageVersion Include="System.Management" Version="7.0.1" /> <PackageVersion Include="System.Management" Version="7.0.1" />
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" /> <PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />

View File

@@ -168,8 +168,6 @@ namespace ARMeilleure.CodeGen.Arm64
Logger.StartPass(PassName.CodeGeneration); Logger.StartPass(PassName.CodeGeneration);
//Console.Error.WriteLine(IRDumper.GetDump(cfg));
bool relocatable = (cctx.Options & CompilerOptions.Relocatable) != 0; bool relocatable = (cctx.Options & CompilerOptions.Relocatable) != 0;
CodeGenContext context = new(allocResult, maxCallArgs, cfg.Blocks.Count, relocatable); CodeGenContext context = new(allocResult, maxCallArgs, cfg.Blocks.Count, relocatable);

View File

@@ -179,6 +179,35 @@ namespace ARMeilleure.CodeGen.Arm64
(uint)operation.GetSource(2).AsInt32()); (uint)operation.GetSource(2).AsInt32());
break; break;
case IntrinsicType.Vector128Unary:
GenerateVectorUnary(
context,
1,
0,
info.Inst,
operation.Destination,
operation.GetSource(0));
break;
case IntrinsicType.Vector128Binary:
GenerateVectorBinary(
context,
1,
0,
info.Inst,
operation.Destination,
operation.GetSource(0),
operation.GetSource(1));
break;
case IntrinsicType.Vector128BinaryRd:
GenerateVectorUnary(
context,
1,
0,
info.Inst,
operation.Destination,
operation.GetSource(1));
break;
case IntrinsicType.VectorUnary: case IntrinsicType.VectorUnary:
GenerateVectorUnary( GenerateVectorUnary(
context, context,

View File

@@ -19,8 +19,8 @@ namespace ARMeilleure.CodeGen.Arm64
Add(Intrinsic.Arm64AddvV, new IntrinsicInfo(0x0e31b800u, IntrinsicType.VectorUnary)); Add(Intrinsic.Arm64AddvV, new IntrinsicInfo(0x0e31b800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64AddS, new IntrinsicInfo(0x5e208400u, IntrinsicType.ScalarBinary)); Add(Intrinsic.Arm64AddS, new IntrinsicInfo(0x5e208400u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64AddV, new IntrinsicInfo(0x0e208400u, IntrinsicType.VectorBinary)); Add(Intrinsic.Arm64AddV, new IntrinsicInfo(0x0e208400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64AesdV, new IntrinsicInfo(0x4e285800u, IntrinsicType.Vector128Unary)); Add(Intrinsic.Arm64AesdV, new IntrinsicInfo(0x4e285800u, IntrinsicType.Vector128BinaryRd));
Add(Intrinsic.Arm64AeseV, new IntrinsicInfo(0x4e284800u, IntrinsicType.Vector128Unary)); Add(Intrinsic.Arm64AeseV, new IntrinsicInfo(0x4e284800u, IntrinsicType.Vector128BinaryRd));
Add(Intrinsic.Arm64AesimcV, new IntrinsicInfo(0x4e287800u, IntrinsicType.Vector128Unary)); Add(Intrinsic.Arm64AesimcV, new IntrinsicInfo(0x4e287800u, IntrinsicType.Vector128Unary));
Add(Intrinsic.Arm64AesmcV, new IntrinsicInfo(0x4e286800u, IntrinsicType.Vector128Unary)); Add(Intrinsic.Arm64AesmcV, new IntrinsicInfo(0x4e286800u, IntrinsicType.Vector128Unary));
Add(Intrinsic.Arm64AndV, new IntrinsicInfo(0x0e201c00u, IntrinsicType.VectorBinaryBitwise)); Add(Intrinsic.Arm64AndV, new IntrinsicInfo(0x0e201c00u, IntrinsicType.VectorBinaryBitwise));

View File

@@ -23,6 +23,10 @@ namespace ARMeilleure.CodeGen.Arm64
ScalarTernaryShlRd, ScalarTernaryShlRd,
ScalarTernaryShrRd, ScalarTernaryShrRd,
Vector128Unary,
Vector128Binary,
Vector128BinaryRd,
VectorUnary, VectorUnary,
VectorUnaryBitwise, VectorUnaryBitwise,
VectorUnaryByElem, VectorUnaryByElem,
@@ -50,9 +54,6 @@ namespace ARMeilleure.CodeGen.Arm64
VectorTernaryShlRd, VectorTernaryShlRd,
VectorTernaryShrRd, VectorTernaryShrRd,
Vector128Unary,
Vector128Binary,
GetRegister, GetRegister,
SetRegister SetRegister
} }

View File

@@ -746,6 +746,7 @@ namespace ARMeilleure.CodeGen.Arm64
info.Type == IntrinsicType.ScalarTernaryFPRdByElem || info.Type == IntrinsicType.ScalarTernaryFPRdByElem ||
info.Type == IntrinsicType.ScalarTernaryShlRd || info.Type == IntrinsicType.ScalarTernaryShlRd ||
info.Type == IntrinsicType.ScalarTernaryShrRd || info.Type == IntrinsicType.ScalarTernaryShrRd ||
info.Type == IntrinsicType.Vector128BinaryRd ||
info.Type == IntrinsicType.VectorBinaryRd || info.Type == IntrinsicType.VectorBinaryRd ||
info.Type == IntrinsicType.VectorInsertByElem || info.Type == IntrinsicType.VectorInsertByElem ||
info.Type == IntrinsicType.VectorTernaryRd || info.Type == IntrinsicType.VectorTernaryRd ||

View File

@@ -17,7 +17,11 @@ namespace ARMeilleure.Instructions
Operand res; Operand res;
if (Optimizations.UseAesni) if (Optimizations.UseArm64Aes)
{
res = context.AddIntrinsic(Intrinsic.Arm64AesdV, d, n);
}
else if (Optimizations.UseAesni)
{ {
res = context.AddIntrinsic(Intrinsic.X86Aesdeclast, context.AddIntrinsic(Intrinsic.X86Xorpd, d, n), context.VectorZero()); res = context.AddIntrinsic(Intrinsic.X86Aesdeclast, context.AddIntrinsic(Intrinsic.X86Xorpd, d, n), context.VectorZero());
} }
@@ -38,7 +42,11 @@ namespace ARMeilleure.Instructions
Operand res; Operand res;
if (Optimizations.UseAesni) if (Optimizations.UseArm64Aes)
{
res = context.AddIntrinsic(Intrinsic.Arm64AeseV, d, n);
}
else if (Optimizations.UseAesni)
{ {
res = context.AddIntrinsic(Intrinsic.X86Aesenclast, context.AddIntrinsic(Intrinsic.X86Xorpd, d, n), context.VectorZero()); res = context.AddIntrinsic(Intrinsic.X86Aesenclast, context.AddIntrinsic(Intrinsic.X86Xorpd, d, n), context.VectorZero());
} }
@@ -58,7 +66,11 @@ namespace ARMeilleure.Instructions
Operand res; Operand res;
if (Optimizations.UseAesni) if (Optimizations.UseArm64Aes)
{
res = context.AddIntrinsic(Intrinsic.Arm64AesimcV, n);
}
else if (Optimizations.UseAesni)
{ {
res = context.AddIntrinsic(Intrinsic.X86Aesimc, n); res = context.AddIntrinsic(Intrinsic.X86Aesimc, n);
} }
@@ -78,7 +90,11 @@ namespace ARMeilleure.Instructions
Operand res; Operand res;
if (Optimizations.UseAesni) if (Optimizations.UseArm64Aes)
{
res = context.AddIntrinsic(Intrinsic.Arm64AesmcV, n);
}
else if (Optimizations.UseAesni)
{ {
Operand roundKey = context.VectorZero(); Operand roundKey = context.VectorZero();

View File

@@ -17,7 +17,11 @@ namespace ARMeilleure.Instructions
Operand res; Operand res;
if (Optimizations.UseAesni) if (Optimizations.UseArm64Aes)
{
res = context.AddIntrinsic(Intrinsic.Arm64AesdV, d, n);
}
else if (Optimizations.UseAesni)
{ {
res = context.AddIntrinsic(Intrinsic.X86Aesdeclast, context.AddIntrinsic(Intrinsic.X86Xorpd, d, n), context.VectorZero()); res = context.AddIntrinsic(Intrinsic.X86Aesdeclast, context.AddIntrinsic(Intrinsic.X86Xorpd, d, n), context.VectorZero());
} }
@@ -38,7 +42,11 @@ namespace ARMeilleure.Instructions
Operand res; Operand res;
if (Optimizations.UseAesni) if (Optimizations.UseArm64Aes)
{
res = context.AddIntrinsic(Intrinsic.Arm64AeseV, d, n);
}
else if (Optimizations.UseAesni)
{ {
res = context.AddIntrinsic(Intrinsic.X86Aesenclast, context.AddIntrinsic(Intrinsic.X86Xorpd, d, n), context.VectorZero()); res = context.AddIntrinsic(Intrinsic.X86Aesenclast, context.AddIntrinsic(Intrinsic.X86Xorpd, d, n), context.VectorZero());
} }
@@ -58,7 +66,11 @@ namespace ARMeilleure.Instructions
Operand res; Operand res;
if (Optimizations.UseAesni) if (Optimizations.UseArm64Aes)
{
res = context.AddIntrinsic(Intrinsic.Arm64AesimcV, n);
}
else if (Optimizations.UseAesni)
{ {
res = context.AddIntrinsic(Intrinsic.X86Aesimc, n); res = context.AddIntrinsic(Intrinsic.X86Aesimc, n);
} }
@@ -78,7 +90,11 @@ namespace ARMeilleure.Instructions
Operand res; Operand res;
if (Optimizations.UseAesni) if (Optimizations.UseArm64Aes)
{
res = context.AddIntrinsic(Intrinsic.Arm64AesmcV, n);
}
else if (Optimizations.UseAesni)
{ {
Operand roundKey = context.VectorZero(); Operand roundKey = context.VectorZero();

View File

@@ -165,7 +165,7 @@ namespace ARMeilleure.Instructions
{ {
Operand m = GetVecA32(op.Vm >> 1); Operand m = GetVecA32(op.Vm >> 1);
Operand toConvert = InstEmitSimdHelper32Arm64.EmitExtractScalar(context, m, op.Vm, doubleSize); Operand toConvert = InstEmitSimdHelper32Arm64.EmitExtractScalar(context, m, op.Vm, true);
Intrinsic inst = (unsigned ? Intrinsic.Arm64FcvtzuGp : Intrinsic.Arm64FcvtzsGp) | Intrinsic.Arm64VDouble; Intrinsic inst = (unsigned ? Intrinsic.Arm64FcvtzuGp : Intrinsic.Arm64FcvtzsGp) | Intrinsic.Arm64VDouble;
@@ -175,7 +175,7 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
InstEmitSimdHelper32Arm64.EmitScalarUnaryOpF32(context, unsigned ? Intrinsic.Arm64FcvtzuS : Intrinsic.Arm64FcvtzsS); InstEmitSimdHelper32Arm64.EmitScalarUnaryOpF32(context, unsigned ? Intrinsic.Arm64FcvtzuS : Intrinsic.Arm64FcvtzsS, false);
} }
} }
else if (!roundWithFpscr && Optimizations.UseSse41) else if (!roundWithFpscr && Optimizations.UseSse41)
@@ -260,28 +260,64 @@ namespace ARMeilleure.Instructions
if (Optimizations.UseAdvSimd) if (Optimizations.UseAdvSimd)
{ {
if (unsigned) bool doubleSize = floatSize == OperandType.FP64;
if (doubleSize)
{ {
inst = rm switch { Operand m = GetVecA32(op.Vm >> 1);
0b00 => Intrinsic.Arm64FcvtauS,
0b01 => Intrinsic.Arm64FcvtnuS, Operand toConvert = InstEmitSimdHelper32Arm64.EmitExtractScalar(context, m, op.Vm, true);
0b10 => Intrinsic.Arm64FcvtpuS,
0b11 => Intrinsic.Arm64FcvtmuS, if (unsigned)
_ => throw new ArgumentOutOfRangeException(nameof(rm)) {
}; inst = rm switch {
0b00 => Intrinsic.Arm64FcvtauGp,
0b01 => Intrinsic.Arm64FcvtnuGp,
0b10 => Intrinsic.Arm64FcvtpuGp,
0b11 => Intrinsic.Arm64FcvtmuGp,
_ => throw new ArgumentOutOfRangeException(nameof(rm))
};
}
else
{
inst = rm switch {
0b00 => Intrinsic.Arm64FcvtasGp,
0b01 => Intrinsic.Arm64FcvtnsGp,
0b10 => Intrinsic.Arm64FcvtpsGp,
0b11 => Intrinsic.Arm64FcvtmsGp,
_ => throw new ArgumentOutOfRangeException(nameof(rm))
};
}
Operand asInteger = context.AddIntrinsicInt(inst | Intrinsic.Arm64VDouble, toConvert);
InsertScalar(context, op.Vd, asInteger);
} }
else else
{ {
inst = rm switch { if (unsigned)
0b00 => Intrinsic.Arm64FcvtasS, {
0b01 => Intrinsic.Arm64FcvtnsS, inst = rm switch {
0b10 => Intrinsic.Arm64FcvtpsS, 0b00 => Intrinsic.Arm64FcvtauS,
0b11 => Intrinsic.Arm64FcvtmsS, 0b01 => Intrinsic.Arm64FcvtnuS,
_ => throw new ArgumentOutOfRangeException(nameof(rm)) 0b10 => Intrinsic.Arm64FcvtpuS,
}; 0b11 => Intrinsic.Arm64FcvtmuS,
} _ => throw new ArgumentOutOfRangeException(nameof(rm))
};
}
else
{
inst = rm switch {
0b00 => Intrinsic.Arm64FcvtasS,
0b01 => Intrinsic.Arm64FcvtnsS,
0b10 => Intrinsic.Arm64FcvtpsS,
0b11 => Intrinsic.Arm64FcvtmsS,
_ => throw new ArgumentOutOfRangeException(nameof(rm))
};
}
InstEmitSimdHelper32Arm64.EmitScalarUnaryOpF32(context, inst); InstEmitSimdHelper32Arm64.EmitScalarUnaryOpF32(context, inst);
}
} }
else if (Optimizations.UseSse41) else if (Optimizations.UseSse41)
{ {

View File

@@ -192,11 +192,10 @@ namespace ARMeilleure.Instructions
EmitVectorTernaryOpSimd32(context, (d, n, m) => context.AddIntrinsic(inst, d, n, m)); EmitVectorTernaryOpSimd32(context, (d, n, m) => context.AddIntrinsic(inst, d, n, m));
} }
public static void EmitScalarUnaryOpSimd32(ArmEmitterContext context, Func1I scalarFunc) public static void EmitScalarUnaryOpSimd32(ArmEmitterContext context, Func1I scalarFunc, bool doubleSize)
{ {
OpCode32SimdS op = (OpCode32SimdS)context.CurrOp; OpCode32SimdS op = (OpCode32SimdS)context.CurrOp;
bool doubleSize = (op.Size & 1) != 0;
int shift = doubleSize ? 1 : 2; int shift = doubleSize ? 1 : 2;
Operand m = GetVecA32(op.Vm >> shift); Operand m = GetVecA32(op.Vm >> shift);
Operand d = GetVecA32(op.Vd >> shift); Operand d = GetVecA32(op.Vd >> shift);
@@ -215,8 +214,13 @@ namespace ARMeilleure.Instructions
{ {
OpCode32SimdS op = (OpCode32SimdS)context.CurrOp; OpCode32SimdS op = (OpCode32SimdS)context.CurrOp;
inst |= ((op.Size & 1) != 0 ? Intrinsic.Arm64VDouble : Intrinsic.Arm64VFloat) | Intrinsic.Arm64V128; EmitScalarUnaryOpF32(context, inst, (op.Size & 1) != 0);
EmitScalarUnaryOpSimd32(context, (m) => (inst == 0) ? m : context.AddIntrinsic(inst, m)); }
public static void EmitScalarUnaryOpF32(ArmEmitterContext context, Intrinsic inst, bool doubleSize)
{
inst |= (doubleSize ? Intrinsic.Arm64VDouble : Intrinsic.Arm64VFloat) | Intrinsic.Arm64V128;
EmitScalarUnaryOpSimd32(context, (m) => (inst == 0) ? m : context.AddIntrinsic(inst, m), doubleSize);
} }
public static void EmitScalarBinaryOpSimd32(ArmEmitterContext context, Func2I scalarFunc) public static void EmitScalarBinaryOpSimd32(ArmEmitterContext context, Func2I scalarFunc)

View File

@@ -1,5 +1,8 @@
using System;
namespace ARMeilleure.IntermediateRepresentation namespace ARMeilleure.IntermediateRepresentation
{ {
[Flags]
enum Intrinsic : ushort enum Intrinsic : ushort
{ {
// X86 (SSE and AVX) // X86 (SSE and AVX)

View File

@@ -13,6 +13,7 @@ namespace ARMeilleure
public static bool UseUnmanagedDispatchLoop { get; set; } = true; public static bool UseUnmanagedDispatchLoop { get; set; } = true;
public static bool UseAdvSimdIfAvailable { get; set; } = true; public static bool UseAdvSimdIfAvailable { get; set; } = true;
public static bool UseArm64AesIfAvailable { get; set; } = true;
public static bool UseArm64PmullIfAvailable { get; set; } = true; public static bool UseArm64PmullIfAvailable { get; set; } = true;
public static bool UseSseIfAvailable { get; set; } = true; public static bool UseSseIfAvailable { get; set; } = true;
@@ -41,6 +42,7 @@ namespace ARMeilleure
} }
internal static bool UseAdvSimd => UseAdvSimdIfAvailable && Arm64HardwareCapabilities.SupportsAdvSimd; internal static bool UseAdvSimd => UseAdvSimdIfAvailable && Arm64HardwareCapabilities.SupportsAdvSimd;
internal static bool UseArm64Aes => UseArm64AesIfAvailable && Arm64HardwareCapabilities.SupportsAes;
internal static bool UseArm64Pmull => UseArm64PmullIfAvailable && Arm64HardwareCapabilities.SupportsPmull; internal static bool UseArm64Pmull => UseArm64PmullIfAvailable && Arm64HardwareCapabilities.SupportsPmull;
internal static bool UseSse => UseSseIfAvailable && X86HardwareCapabilities.SupportsSse; internal static bool UseSse => UseSseIfAvailable && X86HardwareCapabilities.SupportsSse;

View File

@@ -2,6 +2,7 @@ using ARMeilleure.CodeGen;
using ARMeilleure.CodeGen.Unwinding; using ARMeilleure.CodeGen.Unwinding;
using ARMeilleure.Memory; using ARMeilleure.Memory;
using ARMeilleure.Native; using ARMeilleure.Native;
using Ryujinx.Memory;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
@@ -12,8 +13,8 @@ namespace ARMeilleure.Translation.Cache
{ {
static partial class JitCache static partial class JitCache
{ {
private const int PageSize = 4 * 1024; private static readonly int PageSize = (int)MemoryBlock.GetPageSize();
private const int PageMask = PageSize - 1; private static readonly int PageMask = PageSize - 1;
private const int CodeAlignment = 4; // Bytes. private const int CodeAlignment = 4; // Bytes.
private const int CacheSize = 2047 * 1024 * 1024; private const int CacheSize = 2047 * 1024 * 1024;

View File

@@ -30,7 +30,7 @@ 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 = 4661; //! To be incremented manually for each change to the ARMeilleure project. private const uint InternalVersion = 5292; //! 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";

View File

@@ -40,6 +40,7 @@ using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing;
using SPB.Graphics.Exceptions;
using SPB.Graphics.Vulkan; using SPB.Graphics.Vulkan;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@@ -475,11 +476,20 @@ namespace Ryujinx.Ava
_windowsMultimediaTimerResolution = null; _windowsMultimediaTimerResolution = null;
} }
(_rendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.MakeCurrent(); if (_rendererHost.EmbeddedWindow is EmbeddedWindowOpenGL openGlWindow)
{
// Try to bind the OpenGL context before calling the shutdown event.
openGlWindow.MakeCurrent(false, false);
Device.DisposeGpu(); Device.DisposeGpu();
(_rendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.MakeCurrent(null); // Unbind context and destroy everything.
openGlWindow.MakeCurrent(true, false);
}
else
{
Device.DisposeGpu();
}
} }
private void HideCursorState_Changed(object sender, ReactiveEventArgs<HideCursorMode> state) private void HideCursorState_Changed(object sender, ReactiveEventArgs<HideCursorMode> state)
@@ -930,7 +940,7 @@ namespace Ryujinx.Ava
_gpuDoneEvent.Set(); _gpuDoneEvent.Set();
}); });
(_rendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.MakeCurrent(null); (_rendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.MakeCurrent(true);
} }
public void UpdateStatus() public void UpdateStatus()
@@ -1044,7 +1054,7 @@ namespace Ryujinx.Ava
ScreenshotRequested = true; ScreenshotRequested = true;
break; break;
case KeyboardHotkeyState.ShowUi: case KeyboardHotkeyState.ShowUi:
_viewModel.ShowMenuAndStatusBar = true; _viewModel.ShowMenuAndStatusBar = !_viewModel.ShowMenuAndStatusBar;
break; break;
case KeyboardHotkeyState.Pause: case KeyboardHotkeyState.Pause:
if (_viewModel.IsPaused) if (_viewModel.IsPaused)

View File

@@ -545,7 +545,7 @@
"SwkbdMinRangeCharacters": "Must be {0}-{1} characters long", "SwkbdMinRangeCharacters": "Must be {0}-{1} characters long",
"SoftwareKeyboard": "Software Keyboard", "SoftwareKeyboard": "Software Keyboard",
"SoftwareKeyboardModeNumbersOnly": "Must be numbers only", "SoftwareKeyboardModeNumbersOnly": "Must be numbers only",
"SoftwareKeyboardModeAlphabet": "Must be alphabets only", "SoftwareKeyboardModeAlphabet": "Must be non CJK-characters only",
"SoftwareKeyboardModeASCII": "Must be ASCII text only", "SoftwareKeyboardModeASCII": "Must be ASCII text only",
"DialogControllerAppletMessagePlayerRange": "Application requests {0} player(s) with:\n\nTYPES: {1}\n\nPLAYERS: {2}\n\n{3}Please open Settings and reconfigure Input now or press Close.", "DialogControllerAppletMessagePlayerRange": "Application requests {0} player(s) with:\n\nTYPES: {1}\n\nPLAYERS: {2}\n\n{3}Please open Settings and reconfigure Input now or press Close.",
"DialogControllerAppletMessage": "Application requests exactly {0} player(s) with:\n\nTYPES: {1}\n\nPLAYERS: {2}\n\n{3}Please open Settings and reconfigure Input now or press Close.", "DialogControllerAppletMessage": "Application requests exactly {0} player(s) with:\n\nTYPES: {1}\n\nPLAYERS: {2}\n\n{3}Please open Settings and reconfigure Input now or press Close.",

View File

@@ -741,7 +741,7 @@ namespace Ryujinx.Modules
var files = Directory.EnumerateFiles(HomeDir); // All files directly in base dir. var files = Directory.EnumerateFiles(HomeDir); // All files directly in base dir.
// Determine and exclude user files only when the updater is running, not when cleaning old files // Determine and exclude user files only when the updater is running, not when cleaning old files
if (_running) if (_running && !OperatingSystem.IsMacOS())
{ {
// Compare the loose files in base directory against the loose files from the incoming update, and store foreign ones in a user list. // Compare the loose files in base directory against the loose files from the incoming update, and store foreign ones in a user list.
var oldFiles = Directory.EnumerateFiles(HomeDir, "*", SearchOption.TopDirectoryOnly).Select(Path.GetFileName); var oldFiles = Directory.EnumerateFiles(HomeDir, "*", SearchOption.TopDirectoryOnly).Select(Path.GetFileName);

View File

@@ -146,7 +146,7 @@ namespace Ryujinx.Ava.UI.Controls
case KeyboardMode.Alphabet: case KeyboardMode.Alphabet:
localeText = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SoftwareKeyboardModeAlphabet); localeText = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SoftwareKeyboardModeAlphabet);
validationInfoText = string.IsNullOrEmpty(validationInfoText) ? localeText : string.Join("\n", validationInfoText, localeText); validationInfoText = string.IsNullOrEmpty(validationInfoText) ? localeText : string.Join("\n", validationInfoText, localeText);
_checkInput = text => text.All(char.IsAsciiLetter); _checkInput = text => text.All(value => !CJKCharacterValidation.IsCJK(value));
break; break;
case KeyboardMode.ASCII: case KeyboardMode.ASCII:
localeText = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SoftwareKeyboardModeASCII); localeText = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SoftwareKeyboardModeASCII);

View File

@@ -123,7 +123,7 @@ namespace Ryujinx.Ava.UI.Renderer
} }
else else
{ {
X11Window = PlatformHelper.CreateOpenGLWindow(FramebufferFormat.Default, 0, 0, 100, 100) as GLXWindow; X11Window = PlatformHelper.CreateOpenGLWindow(new FramebufferFormat(new ColorFormat(8, 8, 8, 0), 16, 0, ColorFormat.Zero, 0, 2, false), 0, 0, 100, 100) as GLXWindow;
} }
WindowHandle = X11Window.WindowHandle.RawHandle; WindowHandle = X11Window.WindowHandle.RawHandle;

View File

@@ -1,9 +1,11 @@
using OpenTK.Graphics.OpenGL; using OpenTK.Graphics.OpenGL;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.OpenGL; using Ryujinx.Graphics.OpenGL;
using Ryujinx.Ui.Common.Configuration; using Ryujinx.Ui.Common.Configuration;
using SPB.Graphics; using SPB.Graphics;
using SPB.Graphics.Exceptions;
using SPB.Graphics.OpenGL; using SPB.Graphics.OpenGL;
using SPB.Platform; using SPB.Platform;
using SPB.Platform.WGL; using SPB.Platform.WGL;
@@ -18,8 +20,6 @@ namespace Ryujinx.Ava.UI.Renderer
public OpenGLContextBase Context { get; set; } public OpenGLContextBase Context { get; set; }
public EmbeddedWindowOpenGL() { }
protected override void OnWindowDestroying() protected override void OnWindowDestroying()
{ {
Context.Dispose(); Context.Dispose();
@@ -62,14 +62,21 @@ namespace Ryujinx.Ava.UI.Renderer
Context.MakeCurrent(null); Context.MakeCurrent(null);
} }
public void MakeCurrent() public void MakeCurrent(bool unbind = false, bool shouldThrow = true)
{ {
Context?.MakeCurrent(_window); try
} {
Context?.MakeCurrent(!unbind ? _window : null);
}
catch (ContextException e)
{
if (shouldThrow)
{
throw;
}
public void MakeCurrent(NativeWindowBase window) Logger.Warning?.Print(LogClass.Ui, $"Failed to {(!unbind ? "bind" : "unbind")} OpenGL context: {e}");
{ }
Context?.MakeCurrent(window);
} }
public void SwapBuffers() public void SwapBuffers()

View File

@@ -96,7 +96,7 @@ namespace Ryujinx.Common.Configuration
if (OperatingSystem.IsMacOS() && Mode == LaunchMode.UserProfile) if (OperatingSystem.IsMacOS() && Mode == LaunchMode.UserProfile)
{ {
string oldConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), DefaultBaseDir); string oldConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), DefaultBaseDir);
if (Path.Exists(oldConfigPath) && !Path.Exists(BaseDirPath)) if (Path.Exists(oldConfigPath) && !IsPathSymlink(oldConfigPath) && !Path.Exists(BaseDirPath))
{ {
CopyDirectory(oldConfigPath, BaseDirPath); CopyDirectory(oldConfigPath, BaseDirPath);
Directory.Delete(oldConfigPath, true); Directory.Delete(oldConfigPath, true);
@@ -115,6 +115,14 @@ namespace Ryujinx.Common.Configuration
Directory.CreateDirectory(KeysDirPath = Path.Combine(BaseDirPath, KeysDir)); Directory.CreateDirectory(KeysDirPath = Path.Combine(BaseDirPath, KeysDir));
} }
// Check if existing old baseDirPath is a symlink, to prevent possible errors.
// Should be removed, when the existance of the old directory isn't checked anymore.
private static bool IsPathSymlink(string path)
{
FileAttributes attributes = File.GetAttributes(path);
return (attributes & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint;
}
private static void CopyDirectory(string sourceDir, string destinationDir) private static void CopyDirectory(string sourceDir, string destinationDir)
{ {
var dir = new DirectoryInfo(sourceDir); var dir = new DirectoryInfo(sourceDir);

View File

@@ -24,6 +24,24 @@ namespace Ryujinx.Common.Memory
return value; return value;
} }
public bool TryRead<T>(out T value) where T : unmanaged
{
int valueSize = Unsafe.SizeOf<T>();
if (valueSize > _input.Length)
{
value = default;
return false;
}
value = MemoryMarshal.Cast<byte, T>(_input)[0];
_input = _input.Slice(valueSize);
return true;
}
public ReadOnlySpan<byte> GetSpan(int size) public ReadOnlySpan<byte> GetSpan(int size)
{ {
ReadOnlySpan<byte> data = _input.Slice(0, size); ReadOnlySpan<byte> data = _input.Slice(0, size);

View File

@@ -28,6 +28,7 @@ namespace Ryujinx.Graphics.GAL
public readonly bool SupportsFragmentShaderOrderingIntel; public readonly bool SupportsFragmentShaderOrderingIntel;
public readonly bool SupportsGeometryShader; public readonly bool SupportsGeometryShader;
public readonly bool SupportsGeometryShaderPassthrough; public readonly bool SupportsGeometryShaderPassthrough;
public readonly bool SupportsTransformFeedback;
public readonly bool SupportsImageLoadFormatted; public readonly bool SupportsImageLoadFormatted;
public readonly bool SupportsLayerVertexTessellation; public readonly bool SupportsLayerVertexTessellation;
public readonly bool SupportsMismatchingViewFormat; public readonly bool SupportsMismatchingViewFormat;
@@ -77,6 +78,7 @@ namespace Ryujinx.Graphics.GAL
bool supportsFragmentShaderOrderingIntel, bool supportsFragmentShaderOrderingIntel,
bool supportsGeometryShader, bool supportsGeometryShader,
bool supportsGeometryShaderPassthrough, bool supportsGeometryShaderPassthrough,
bool supportsTransformFeedback,
bool supportsImageLoadFormatted, bool supportsImageLoadFormatted,
bool supportsLayerVertexTessellation, bool supportsLayerVertexTessellation,
bool supportsMismatchingViewFormat, bool supportsMismatchingViewFormat,
@@ -122,6 +124,7 @@ namespace Ryujinx.Graphics.GAL
SupportsFragmentShaderOrderingIntel = supportsFragmentShaderOrderingIntel; SupportsFragmentShaderOrderingIntel = supportsFragmentShaderOrderingIntel;
SupportsGeometryShader = supportsGeometryShader; SupportsGeometryShader = supportsGeometryShader;
SupportsGeometryShaderPassthrough = supportsGeometryShaderPassthrough; SupportsGeometryShaderPassthrough = supportsGeometryShaderPassthrough;
SupportsTransformFeedback = supportsTransformFeedback;
SupportsImageLoadFormatted = supportsImageLoadFormatted; SupportsImageLoadFormatted = supportsImageLoadFormatted;
SupportsLayerVertexTessellation = supportsLayerVertexTessellation; SupportsLayerVertexTessellation = supportsLayerVertexTessellation;
SupportsMismatchingViewFormat = supportsMismatchingViewFormat; SupportsMismatchingViewFormat = supportsMismatchingViewFormat;

View File

@@ -100,22 +100,22 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
{ {
#pragma warning disable CS0649 #pragma warning disable CS0649
public uint SetObject; public uint SetObject;
public int SetObjectClassId => (int)((SetObject >> 0) & 0xFFFF); public int SetObjectClassId => (int)(SetObject & 0xFFFF);
public int SetObjectEngineId => (int)((SetObject >> 16) & 0x1F); public int SetObjectEngineId => (int)((SetObject >> 16) & 0x1F);
public fixed uint Reserved04[63]; public fixed uint Reserved04[63];
public uint NoOperation; public uint NoOperation;
public uint SetNotifyA; public uint SetNotifyA;
public int SetNotifyAAddressUpper => (int)((SetNotifyA >> 0) & 0xFF); public int SetNotifyAAddressUpper => (int)(SetNotifyA & 0xFF);
public uint SetNotifyB; public uint SetNotifyB;
public uint Notify; public uint Notify;
public NotifyType NotifyType => (NotifyType)(Notify); public NotifyType NotifyType => (NotifyType)(Notify);
public uint WaitForIdle; public uint WaitForIdle;
public fixed uint Reserved114[7]; public fixed uint Reserved114[7];
public uint SetGlobalRenderEnableA; public uint SetGlobalRenderEnableA;
public int SetGlobalRenderEnableAOffsetUpper => (int)((SetGlobalRenderEnableA >> 0) & 0xFF); public int SetGlobalRenderEnableAOffsetUpper => (int)(SetGlobalRenderEnableA & 0xFF);
public uint SetGlobalRenderEnableB; public uint SetGlobalRenderEnableB;
public uint SetGlobalRenderEnableC; public uint SetGlobalRenderEnableC;
public int SetGlobalRenderEnableCMode => (int)((SetGlobalRenderEnableC >> 0) & 0x7); public int SetGlobalRenderEnableCMode => (int)(SetGlobalRenderEnableC & 0x7);
public uint SendGoIdle; public uint SendGoIdle;
public uint PmTrigger; public uint PmTrigger;
public uint PmTriggerWfi; public uint PmTriggerWfi;
@@ -126,11 +126,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
public uint LineLengthIn; public uint LineLengthIn;
public uint LineCount; public uint LineCount;
public uint OffsetOutUpper; public uint OffsetOutUpper;
public int OffsetOutUpperValue => (int)((OffsetOutUpper >> 0) & 0xFF); public int OffsetOutUpperValue => (int)(OffsetOutUpper & 0xFF);
public uint OffsetOut; public uint OffsetOut;
public uint PitchOut; public uint PitchOut;
public uint SetDstBlockSize; public uint SetDstBlockSize;
public SetDstBlockSizeWidth SetDstBlockSizeWidth => (SetDstBlockSizeWidth)((SetDstBlockSize >> 0) & 0xF); public SetDstBlockSizeWidth SetDstBlockSizeWidth => (SetDstBlockSizeWidth)(SetDstBlockSize & 0xF);
public SetDstBlockSizeHeight SetDstBlockSizeHeight => (SetDstBlockSizeHeight)((SetDstBlockSize >> 4) & 0xF); public SetDstBlockSizeHeight SetDstBlockSizeHeight => (SetDstBlockSizeHeight)((SetDstBlockSize >> 4) & 0xF);
public SetDstBlockSizeDepth SetDstBlockSizeDepth => (SetDstBlockSizeDepth)((SetDstBlockSize >> 8) & 0xF); public SetDstBlockSizeDepth SetDstBlockSizeDepth => (SetDstBlockSizeDepth)((SetDstBlockSize >> 8) & 0xF);
public uint SetDstWidth; public uint SetDstWidth;
@@ -138,11 +138,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
public uint SetDstDepth; public uint SetDstDepth;
public uint SetDstLayer; public uint SetDstLayer;
public uint SetDstOriginBytesX; public uint SetDstOriginBytesX;
public int SetDstOriginBytesXV => (int)((SetDstOriginBytesX >> 0) & 0xFFFFF); public int SetDstOriginBytesXV => (int)(SetDstOriginBytesX & 0xFFFFF);
public uint SetDstOriginSamplesY; public uint SetDstOriginSamplesY;
public int SetDstOriginSamplesYV => (int)((SetDstOriginSamplesY >> 0) & 0xFFFF); public int SetDstOriginSamplesYV => (int)(SetDstOriginSamplesY & 0xFFFF);
public uint LaunchDma; public uint LaunchDma;
public LaunchDmaDstMemoryLayout LaunchDmaDstMemoryLayout => (LaunchDmaDstMemoryLayout)((LaunchDma >> 0) & 0x1); public LaunchDmaDstMemoryLayout LaunchDmaDstMemoryLayout => (LaunchDmaDstMemoryLayout)(LaunchDma & 0x1);
public LaunchDmaCompletionType LaunchDmaCompletionType => (LaunchDmaCompletionType)((LaunchDma >> 4) & 0x3); public LaunchDmaCompletionType LaunchDmaCompletionType => (LaunchDmaCompletionType)((LaunchDma >> 4) & 0x3);
public LaunchDmaInterruptType LaunchDmaInterruptType => (LaunchDmaInterruptType)((LaunchDma >> 8) & 0x3); public LaunchDmaInterruptType LaunchDmaInterruptType => (LaunchDmaInterruptType)((LaunchDma >> 8) & 0x3);
public LaunchDmaSemaphoreStructSize LaunchDmaSemaphoreStructSize => (LaunchDmaSemaphoreStructSize)((LaunchDma >> 12) & 0x1); public LaunchDmaSemaphoreStructSize LaunchDmaSemaphoreStructSize => (LaunchDmaSemaphoreStructSize)((LaunchDma >> 12) & 0x1);
@@ -153,7 +153,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
public uint LoadInlineData; public uint LoadInlineData;
public fixed uint Reserved1B8[9]; public fixed uint Reserved1B8[9];
public uint SetI2mSemaphoreA; public uint SetI2mSemaphoreA;
public int SetI2mSemaphoreAOffsetUpper => (int)((SetI2mSemaphoreA >> 0) & 0xFF); public int SetI2mSemaphoreAOffsetUpper => (int)(SetI2mSemaphoreA & 0xFF);
public uint SetI2mSemaphoreB; public uint SetI2mSemaphoreB;
public uint SetI2mSemaphoreC; public uint SetI2mSemaphoreC;
public fixed uint Reserved1E8[2]; public fixed uint Reserved1E8[2];
@@ -162,7 +162,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
public uint SetI2mSpareNoop02; public uint SetI2mSpareNoop02;
public uint SetI2mSpareNoop03; public uint SetI2mSpareNoop03;
public uint SetValidSpanOverflowAreaA; public uint SetValidSpanOverflowAreaA;
public int SetValidSpanOverflowAreaAAddressUpper => (int)((SetValidSpanOverflowAreaA >> 0) & 0xFF); public int SetValidSpanOverflowAreaAAddressUpper => (int)(SetValidSpanOverflowAreaA & 0xFF);
public uint SetValidSpanOverflowAreaB; public uint SetValidSpanOverflowAreaB;
public uint SetValidSpanOverflowAreaC; public uint SetValidSpanOverflowAreaC;
public uint SetCoalesceWaitingPeriodUnit; public uint SetCoalesceWaitingPeriodUnit;
@@ -185,12 +185,12 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
public uint SetReservedSwMethod06; public uint SetReservedSwMethod06;
public uint SetReservedSwMethod07; public uint SetReservedSwMethod07;
public uint SetCwdControl; public uint SetCwdControl;
public SetCwdControlSmSelection SetCwdControlSmSelection => (SetCwdControlSmSelection)((SetCwdControl >> 0) & 0x1); public SetCwdControlSmSelection SetCwdControlSmSelection => (SetCwdControlSmSelection)(SetCwdControl & 0x1);
public uint InvalidateTextureHeaderCacheNoWfi; public uint InvalidateTextureHeaderCacheNoWfi;
public InvalidateCacheLines InvalidateTextureHeaderCacheNoWfiLines => (InvalidateCacheLines)((InvalidateTextureHeaderCacheNoWfi >> 0) & 0x1); public InvalidateCacheLines InvalidateTextureHeaderCacheNoWfiLines => (InvalidateCacheLines)(InvalidateTextureHeaderCacheNoWfi & 0x1);
public int InvalidateTextureHeaderCacheNoWfiTag => (int)((InvalidateTextureHeaderCacheNoWfi >> 4) & 0x3FFFFF); public int InvalidateTextureHeaderCacheNoWfiTag => (int)((InvalidateTextureHeaderCacheNoWfi >> 4) & 0x3FFFFF);
public uint SetCwdRefCounter; public uint SetCwdRefCounter;
public int SetCwdRefCounterSelect => (int)((SetCwdRefCounter >> 0) & 0x3F); public int SetCwdRefCounterSelect => (int)(SetCwdRefCounter & 0x3F);
public int SetCwdRefCounterValue => (int)((SetCwdRefCounter >> 8) & 0xFFFF); public int SetCwdRefCounterValue => (int)((SetCwdRefCounter >> 8) & 0xFFFF);
public uint SetReservedSwMethod08; public uint SetReservedSwMethod08;
public uint SetReservedSwMethod09; public uint SetReservedSwMethod09;
@@ -201,28 +201,28 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
public uint SetReservedSwMethod14; public uint SetReservedSwMethod14;
public uint SetReservedSwMethod15; public uint SetReservedSwMethod15;
public uint SetGwcScgType; public uint SetGwcScgType;
public SetGwcScgTypeScgType SetGwcScgTypeScgType => (SetGwcScgTypeScgType)((SetGwcScgType >> 0) & 0x1); public SetGwcScgTypeScgType SetGwcScgTypeScgType => (SetGwcScgTypeScgType)(SetGwcScgType & 0x1);
public uint SetScgControl; public uint SetScgControl;
public int SetScgControlCompute1MaxSmCount => (int)((SetScgControl >> 0) & 0x1FF); public int SetScgControlCompute1MaxSmCount => (int)(SetScgControl & 0x1FF);
public uint InvalidateConstantBufferCacheA; public uint InvalidateConstantBufferCacheA;
public int InvalidateConstantBufferCacheAAddressUpper => (int)((InvalidateConstantBufferCacheA >> 0) & 0xFF); public int InvalidateConstantBufferCacheAAddressUpper => (int)(InvalidateConstantBufferCacheA & 0xFF);
public uint InvalidateConstantBufferCacheB; public uint InvalidateConstantBufferCacheB;
public uint InvalidateConstantBufferCacheC; public uint InvalidateConstantBufferCacheC;
public int InvalidateConstantBufferCacheCByteCount => (int)((InvalidateConstantBufferCacheC >> 0) & 0x1FFFF); public int InvalidateConstantBufferCacheCByteCount => (int)(InvalidateConstantBufferCacheC & 0x1FFFF);
public bool InvalidateConstantBufferCacheCThruL2 => (InvalidateConstantBufferCacheC & 0x80000000) != 0; public bool InvalidateConstantBufferCacheCThruL2 => (InvalidateConstantBufferCacheC & 0x80000000) != 0;
public uint SetComputeClassVersion; public uint SetComputeClassVersion;
public int SetComputeClassVersionCurrent => (int)((SetComputeClassVersion >> 0) & 0xFFFF); public int SetComputeClassVersionCurrent => (int)(SetComputeClassVersion & 0xFFFF);
public int SetComputeClassVersionOldestSupported => (int)((SetComputeClassVersion >> 16) & 0xFFFF); public int SetComputeClassVersionOldestSupported => (int)((SetComputeClassVersion >> 16) & 0xFFFF);
public uint CheckComputeClassVersion; public uint CheckComputeClassVersion;
public int CheckComputeClassVersionCurrent => (int)((CheckComputeClassVersion >> 0) & 0xFFFF); public int CheckComputeClassVersionCurrent => (int)(CheckComputeClassVersion & 0xFFFF);
public int CheckComputeClassVersionOldestSupported => (int)((CheckComputeClassVersion >> 16) & 0xFFFF); public int CheckComputeClassVersionOldestSupported => (int)((CheckComputeClassVersion >> 16) & 0xFFFF);
public uint SetQmdVersion; public uint SetQmdVersion;
public int SetQmdVersionCurrent => (int)((SetQmdVersion >> 0) & 0xFFFF); public int SetQmdVersionCurrent => (int)(SetQmdVersion & 0xFFFF);
public int SetQmdVersionOldestSupported => (int)((SetQmdVersion >> 16) & 0xFFFF); public int SetQmdVersionOldestSupported => (int)((SetQmdVersion >> 16) & 0xFFFF);
public uint SetWfiConfig; public uint SetWfiConfig;
public bool SetWfiConfigEnableScgTypeWfi => (SetWfiConfig & 0x1) != 0; public bool SetWfiConfigEnableScgTypeWfi => (SetWfiConfig & 0x1) != 0;
public uint CheckQmdVersion; public uint CheckQmdVersion;
public int CheckQmdVersionCurrent => (int)((CheckQmdVersion >> 0) & 0xFFFF); public int CheckQmdVersionCurrent => (int)(CheckQmdVersion & 0xFFFF);
public int CheckQmdVersionOldestSupported => (int)((CheckQmdVersion >> 16) & 0xFFFF); public int CheckQmdVersionOldestSupported => (int)((CheckQmdVersion >> 16) & 0xFFFF);
public uint WaitForIdleScgType; public uint WaitForIdleScgType;
public uint InvalidateSkedCaches; public uint InvalidateSkedCaches;
@@ -231,28 +231,28 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
public bool SetScgRenderEnableControlCompute1UsesRenderEnable => (SetScgRenderEnableControl & 0x1) != 0; public bool SetScgRenderEnableControlCompute1UsesRenderEnable => (SetScgRenderEnableControl & 0x1) != 0;
public fixed uint Reserved2A0[4]; public fixed uint Reserved2A0[4];
public uint SetCwdSlotCount; public uint SetCwdSlotCount;
public int SetCwdSlotCountV => (int)((SetCwdSlotCount >> 0) & 0xFF); public int SetCwdSlotCountV => (int)(SetCwdSlotCount & 0xFF);
public uint SendPcasA; public uint SendPcasA;
public uint SendPcasB; public uint SendPcasB;
public int SendPcasBFrom => (int)((SendPcasB >> 0) & 0xFFFFFF); public int SendPcasBFrom => (int)(SendPcasB & 0xFFFFFF);
public int SendPcasBDelta => (int)((SendPcasB >> 24) & 0xFF); public int SendPcasBDelta => (int)((SendPcasB >> 24) & 0xFF);
public uint SendSignalingPcasB; public uint SendSignalingPcasB;
public bool SendSignalingPcasBInvalidate => (SendSignalingPcasB & 0x1) != 0; public bool SendSignalingPcasBInvalidate => (SendSignalingPcasB & 0x1) != 0;
public bool SendSignalingPcasBSchedule => (SendSignalingPcasB & 0x2) != 0; public bool SendSignalingPcasBSchedule => (SendSignalingPcasB & 0x2) != 0;
public fixed uint Reserved2C0[9]; public fixed uint Reserved2C0[9];
public uint SetShaderLocalMemoryNonThrottledA; public uint SetShaderLocalMemoryNonThrottledA;
public int SetShaderLocalMemoryNonThrottledASizeUpper => (int)((SetShaderLocalMemoryNonThrottledA >> 0) & 0xFF); public int SetShaderLocalMemoryNonThrottledASizeUpper => (int)(SetShaderLocalMemoryNonThrottledA & 0xFF);
public uint SetShaderLocalMemoryNonThrottledB; public uint SetShaderLocalMemoryNonThrottledB;
public uint SetShaderLocalMemoryNonThrottledC; public uint SetShaderLocalMemoryNonThrottledC;
public int SetShaderLocalMemoryNonThrottledCMaxSmCount => (int)((SetShaderLocalMemoryNonThrottledC >> 0) & 0x1FF); public int SetShaderLocalMemoryNonThrottledCMaxSmCount => (int)(SetShaderLocalMemoryNonThrottledC & 0x1FF);
public uint SetShaderLocalMemoryThrottledA; public uint SetShaderLocalMemoryThrottledA;
public int SetShaderLocalMemoryThrottledASizeUpper => (int)((SetShaderLocalMemoryThrottledA >> 0) & 0xFF); public int SetShaderLocalMemoryThrottledASizeUpper => (int)(SetShaderLocalMemoryThrottledA & 0xFF);
public uint SetShaderLocalMemoryThrottledB; public uint SetShaderLocalMemoryThrottledB;
public uint SetShaderLocalMemoryThrottledC; public uint SetShaderLocalMemoryThrottledC;
public int SetShaderLocalMemoryThrottledCMaxSmCount => (int)((SetShaderLocalMemoryThrottledC >> 0) & 0x1FF); public int SetShaderLocalMemoryThrottledCMaxSmCount => (int)(SetShaderLocalMemoryThrottledC & 0x1FF);
public fixed uint Reserved2FC[5]; public fixed uint Reserved2FC[5];
public uint SetSpaVersion; public uint SetSpaVersion;
public int SetSpaVersionMinor => (int)((SetSpaVersion >> 0) & 0xFF); public int SetSpaVersionMinor => (int)(SetSpaVersion & 0xFF);
public int SetSpaVersionMajor => (int)((SetSpaVersion >> 8) & 0xFF); public int SetSpaVersionMajor => (int)((SetSpaVersion >> 8) & 0xFF);
public fixed uint Reserved314[123]; public fixed uint Reserved314[123];
public uint SetFalcon00; public uint SetFalcon00;
@@ -291,14 +291,14 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
public uint SetShaderLocalMemoryWindow; public uint SetShaderLocalMemoryWindow;
public fixed uint Reserved780[4]; public fixed uint Reserved780[4];
public uint SetShaderLocalMemoryA; public uint SetShaderLocalMemoryA;
public int SetShaderLocalMemoryAAddressUpper => (int)((SetShaderLocalMemoryA >> 0) & 0xFF); public int SetShaderLocalMemoryAAddressUpper => (int)(SetShaderLocalMemoryA & 0xFF);
public uint SetShaderLocalMemoryB; public uint SetShaderLocalMemoryB;
public fixed uint Reserved798[383]; public fixed uint Reserved798[383];
public uint SetShaderCacheControl; public uint SetShaderCacheControl;
public bool SetShaderCacheControlIcachePrefetchEnable => (SetShaderCacheControl & 0x1) != 0; public bool SetShaderCacheControlIcachePrefetchEnable => (SetShaderCacheControl & 0x1) != 0;
public fixed uint ReservedD98[19]; public fixed uint ReservedD98[19];
public uint SetSmTimeoutInterval; public uint SetSmTimeoutInterval;
public int SetSmTimeoutIntervalCounterBit => (int)((SetSmTimeoutInterval >> 0) & 0x3F); public int SetSmTimeoutIntervalCounterBit => (int)(SetSmTimeoutInterval & 0x3F);
public fixed uint ReservedDE8[87]; public fixed uint ReservedDE8[87];
public uint SetSpareNoop12; public uint SetSpareNoop12;
public uint SetSpareNoop13; public uint SetSpareNoop13;
@@ -324,48 +324,48 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
public bool InvalidateTextureHeaderCacheAllV => (InvalidateTextureHeaderCacheAll & 0x1) != 0; public bool InvalidateTextureHeaderCacheAllV => (InvalidateTextureHeaderCacheAll & 0x1) != 0;
public fixed uint Reserved1214[29]; public fixed uint Reserved1214[29];
public uint InvalidateTextureDataCacheNoWfi; public uint InvalidateTextureDataCacheNoWfi;
public InvalidateCacheLines InvalidateTextureDataCacheNoWfiLines => (InvalidateCacheLines)((InvalidateTextureDataCacheNoWfi >> 0) & 0x1); public InvalidateCacheLines InvalidateTextureDataCacheNoWfiLines => (InvalidateCacheLines)(InvalidateTextureDataCacheNoWfi & 0x1);
public int InvalidateTextureDataCacheNoWfiTag => (int)((InvalidateTextureDataCacheNoWfi >> 4) & 0x3FFFFF); public int InvalidateTextureDataCacheNoWfiTag => (int)((InvalidateTextureDataCacheNoWfi >> 4) & 0x3FFFFF);
public fixed uint Reserved128C[7]; public fixed uint Reserved128C[7];
public uint ActivatePerfSettingsForComputeContext; public uint ActivatePerfSettingsForComputeContext;
public bool ActivatePerfSettingsForComputeContextAll => (ActivatePerfSettingsForComputeContext & 0x1) != 0; public bool ActivatePerfSettingsForComputeContextAll => (ActivatePerfSettingsForComputeContext & 0x1) != 0;
public fixed uint Reserved12AC[33]; public fixed uint Reserved12AC[33];
public uint InvalidateSamplerCache; public uint InvalidateSamplerCache;
public InvalidateCacheLines InvalidateSamplerCacheLines => (InvalidateCacheLines)((InvalidateSamplerCache >> 0) & 0x1); public InvalidateCacheLines InvalidateSamplerCacheLines => (InvalidateCacheLines)(InvalidateSamplerCache & 0x1);
public int InvalidateSamplerCacheTag => (int)((InvalidateSamplerCache >> 4) & 0x3FFFFF); public int InvalidateSamplerCacheTag => (int)((InvalidateSamplerCache >> 4) & 0x3FFFFF);
public uint InvalidateTextureHeaderCache; public uint InvalidateTextureHeaderCache;
public InvalidateCacheLines InvalidateTextureHeaderCacheLines => (InvalidateCacheLines)((InvalidateTextureHeaderCache >> 0) & 0x1); public InvalidateCacheLines InvalidateTextureHeaderCacheLines => (InvalidateCacheLines)(InvalidateTextureHeaderCache & 0x1);
public int InvalidateTextureHeaderCacheTag => (int)((InvalidateTextureHeaderCache >> 4) & 0x3FFFFF); public int InvalidateTextureHeaderCacheTag => (int)((InvalidateTextureHeaderCache >> 4) & 0x3FFFFF);
public uint InvalidateTextureDataCache; public uint InvalidateTextureDataCache;
public InvalidateCacheLines InvalidateTextureDataCacheLines => (InvalidateCacheLines)((InvalidateTextureDataCache >> 0) & 0x1); public InvalidateCacheLines InvalidateTextureDataCacheLines => (InvalidateCacheLines)(InvalidateTextureDataCache & 0x1);
public int InvalidateTextureDataCacheTag => (int)((InvalidateTextureDataCache >> 4) & 0x3FFFFF); public int InvalidateTextureDataCacheTag => (int)((InvalidateTextureDataCache >> 4) & 0x3FFFFF);
public fixed uint Reserved133C[58]; public fixed uint Reserved133C[58];
public uint InvalidateSamplerCacheNoWfi; public uint InvalidateSamplerCacheNoWfi;
public InvalidateCacheLines InvalidateSamplerCacheNoWfiLines => (InvalidateCacheLines)((InvalidateSamplerCacheNoWfi >> 0) & 0x1); public InvalidateCacheLines InvalidateSamplerCacheNoWfiLines => (InvalidateCacheLines)(InvalidateSamplerCacheNoWfi & 0x1);
public int InvalidateSamplerCacheNoWfiTag => (int)((InvalidateSamplerCacheNoWfi >> 4) & 0x3FFFFF); public int InvalidateSamplerCacheNoWfiTag => (int)((InvalidateSamplerCacheNoWfi >> 4) & 0x3FFFFF);
public fixed uint Reserved1428[64]; public fixed uint Reserved1428[64];
public uint SetShaderExceptions; public uint SetShaderExceptions;
public bool SetShaderExceptionsEnable => (SetShaderExceptions & 0x1) != 0; public bool SetShaderExceptionsEnable => (SetShaderExceptions & 0x1) != 0;
public fixed uint Reserved152C[9]; public fixed uint Reserved152C[9];
public uint SetRenderEnableA; public uint SetRenderEnableA;
public int SetRenderEnableAOffsetUpper => (int)((SetRenderEnableA >> 0) & 0xFF); public int SetRenderEnableAOffsetUpper => (int)(SetRenderEnableA & 0xFF);
public uint SetRenderEnableB; public uint SetRenderEnableB;
public uint SetRenderEnableC; public uint SetRenderEnableC;
public int SetRenderEnableCMode => (int)((SetRenderEnableC >> 0) & 0x7); public int SetRenderEnableCMode => (int)(SetRenderEnableC & 0x7);
public uint SetTexSamplerPoolA; public uint SetTexSamplerPoolA;
public int SetTexSamplerPoolAOffsetUpper => (int)((SetTexSamplerPoolA >> 0) & 0xFF); public int SetTexSamplerPoolAOffsetUpper => (int)(SetTexSamplerPoolA & 0xFF);
public uint SetTexSamplerPoolB; public uint SetTexSamplerPoolB;
public uint SetTexSamplerPoolC; public uint SetTexSamplerPoolC;
public int SetTexSamplerPoolCMaximumIndex => (int)((SetTexSamplerPoolC >> 0) & 0xFFFFF); public int SetTexSamplerPoolCMaximumIndex => (int)(SetTexSamplerPoolC & 0xFFFFF);
public fixed uint Reserved1568[3]; public fixed uint Reserved1568[3];
public uint SetTexHeaderPoolA; public uint SetTexHeaderPoolA;
public int SetTexHeaderPoolAOffsetUpper => (int)((SetTexHeaderPoolA >> 0) & 0xFF); public int SetTexHeaderPoolAOffsetUpper => (int)(SetTexHeaderPoolA & 0xFF);
public uint SetTexHeaderPoolB; public uint SetTexHeaderPoolB;
public uint SetTexHeaderPoolC; public uint SetTexHeaderPoolC;
public int SetTexHeaderPoolCMaximumIndex => (int)((SetTexHeaderPoolC >> 0) & 0x3FFFFF); public int SetTexHeaderPoolCMaximumIndex => (int)(SetTexHeaderPoolC & 0x3FFFFF);
public fixed uint Reserved1580[34]; public fixed uint Reserved1580[34];
public uint SetProgramRegionA; public uint SetProgramRegionA;
public int SetProgramRegionAAddressUpper => (int)((SetProgramRegionA >> 0) & 0xFF); public int SetProgramRegionAAddressUpper => (int)(SetProgramRegionA & 0xFF);
public uint SetProgramRegionB; public uint SetProgramRegionB;
public fixed uint Reserved1610[34]; public fixed uint Reserved1610[34];
public uint InvalidateShaderCachesNoWfi; public uint InvalidateShaderCachesNoWfi;
@@ -374,7 +374,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
public bool InvalidateShaderCachesNoWfiConstant => (InvalidateShaderCachesNoWfi & 0x1000) != 0; public bool InvalidateShaderCachesNoWfiConstant => (InvalidateShaderCachesNoWfi & 0x1000) != 0;
public fixed uint Reserved169C[170]; public fixed uint Reserved169C[170];
public uint SetRenderEnableOverride; public uint SetRenderEnableOverride;
public SetRenderEnableOverrideMode SetRenderEnableOverrideMode => (SetRenderEnableOverrideMode)((SetRenderEnableOverride >> 0) & 0x3); public SetRenderEnableOverrideMode SetRenderEnableOverrideMode => (SetRenderEnableOverrideMode)(SetRenderEnableOverride & 0x3);
public fixed uint Reserved1948[57]; public fixed uint Reserved1948[57];
public uint PipeNop; public uint PipeNop;
public uint SetSpare00; public uint SetSpare00;
@@ -383,11 +383,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
public uint SetSpare03; public uint SetSpare03;
public fixed uint Reserved1A40[48]; public fixed uint Reserved1A40[48];
public uint SetReportSemaphoreA; public uint SetReportSemaphoreA;
public int SetReportSemaphoreAOffsetUpper => (int)((SetReportSemaphoreA >> 0) & 0xFF); public int SetReportSemaphoreAOffsetUpper => (int)(SetReportSemaphoreA & 0xFF);
public uint SetReportSemaphoreB; public uint SetReportSemaphoreB;
public uint SetReportSemaphoreC; public uint SetReportSemaphoreC;
public uint SetReportSemaphoreD; public uint SetReportSemaphoreD;
public SetReportSemaphoreDOperation SetReportSemaphoreDOperation => (SetReportSemaphoreDOperation)((SetReportSemaphoreD >> 0) & 0x3); public SetReportSemaphoreDOperation SetReportSemaphoreDOperation => (SetReportSemaphoreDOperation)(SetReportSemaphoreD & 0x3);
public bool SetReportSemaphoreDAwakenEnable => (SetReportSemaphoreD & 0x100000) != 0; public bool SetReportSemaphoreDAwakenEnable => (SetReportSemaphoreD & 0x100000) != 0;
public SetReportSemaphoreDStructureSize SetReportSemaphoreDStructureSize => (SetReportSemaphoreDStructureSize)((SetReportSemaphoreD >> 28) & 0x1); public SetReportSemaphoreDStructureSize SetReportSemaphoreDStructureSize => (SetReportSemaphoreDStructureSize)((SetReportSemaphoreD >> 28) & 0x1);
public bool SetReportSemaphoreDFlushDisable => (SetReportSemaphoreD & 0x4) != 0; public bool SetReportSemaphoreDFlushDisable => (SetReportSemaphoreD & 0x4) != 0;
@@ -396,7 +396,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
public SetReportSemaphoreDReductionFormat SetReportSemaphoreDReductionFormat => (SetReportSemaphoreDReductionFormat)((SetReportSemaphoreD >> 17) & 0x3); public SetReportSemaphoreDReductionFormat SetReportSemaphoreDReductionFormat => (SetReportSemaphoreDReductionFormat)((SetReportSemaphoreD >> 17) & 0x3);
public fixed uint Reserved1B10[702]; public fixed uint Reserved1B10[702];
public uint SetBindlessTexture; public uint SetBindlessTexture;
public int SetBindlessTextureConstantBufferSlotSelect => (int)((SetBindlessTexture >> 0) & 0x7); public int SetBindlessTextureConstantBufferSlotSelect => (int)(SetBindlessTexture & 0x7);
public uint SetTrapHandler; public uint SetTrapHandler;
public fixed uint Reserved2610[843]; public fixed uint Reserved2610[843];
public Array8<uint> SetShaderPerformanceCounterValueUpper; public Array8<uint> SetShaderPerformanceCounterValueUpper;
@@ -423,11 +423,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
public bool SetShaderPerformanceCounterControlBWindowed(int i) => (SetShaderPerformanceCounterControlB[i] & 0x8) != 0; public bool SetShaderPerformanceCounterControlBWindowed(int i) => (SetShaderPerformanceCounterControlB[i] & 0x8) != 0;
public int SetShaderPerformanceCounterControlBFunc(int i) => (int)((SetShaderPerformanceCounterControlB[i] >> 4) & 0xFFFF); public int SetShaderPerformanceCounterControlBFunc(int i) => (int)((SetShaderPerformanceCounterControlB[i] >> 4) & 0xFFFF);
public uint SetShaderPerformanceCounterTrapControl; public uint SetShaderPerformanceCounterTrapControl;
public int SetShaderPerformanceCounterTrapControlMask => (int)((SetShaderPerformanceCounterTrapControl >> 0) & 0xFF); public int SetShaderPerformanceCounterTrapControlMask => (int)(SetShaderPerformanceCounterTrapControl & 0xFF);
public uint StartShaderPerformanceCounter; public uint StartShaderPerformanceCounter;
public int StartShaderPerformanceCounterCounterMask => (int)((StartShaderPerformanceCounter >> 0) & 0xFF); public int StartShaderPerformanceCounterCounterMask => (int)(StartShaderPerformanceCounter & 0xFF);
public uint StopShaderPerformanceCounter; public uint StopShaderPerformanceCounter;
public int StopShaderPerformanceCounterCounterMask => (int)((StopShaderPerformanceCounter >> 0) & 0xFF); public int StopShaderPerformanceCounterCounterMask => (int)(StopShaderPerformanceCounter & 0xFF);
public fixed uint Reserved33E8[6]; public fixed uint Reserved33E8[6];
public MmeShadowScratch SetMmeShadowScratch; public MmeShadowScratch SetMmeShadowScratch;
#pragma warning restore CS0649 #pragma warning restore CS0649

View File

@@ -186,22 +186,22 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
public uint PmTrigger; public uint PmTrigger;
public fixed uint Reserved144[63]; public fixed uint Reserved144[63];
public uint SetSemaphoreA; public uint SetSemaphoreA;
public int SetSemaphoreAUpper => (int)((SetSemaphoreA >> 0) & 0xFF); public int SetSemaphoreAUpper => (int)(SetSemaphoreA & 0xFF);
public uint SetSemaphoreB; public uint SetSemaphoreB;
public uint SetSemaphorePayload; public uint SetSemaphorePayload;
public fixed uint Reserved24C[2]; public fixed uint Reserved24C[2];
public uint SetRenderEnableA; public uint SetRenderEnableA;
public int SetRenderEnableAUpper => (int)((SetRenderEnableA >> 0) & 0xFF); public int SetRenderEnableAUpper => (int)(SetRenderEnableA & 0xFF);
public uint SetRenderEnableB; public uint SetRenderEnableB;
public uint SetRenderEnableC; public uint SetRenderEnableC;
public int SetRenderEnableCMode => (int)((SetRenderEnableC >> 0) & 0x7); public int SetRenderEnableCMode => (int)(SetRenderEnableC & 0x7);
public uint SetSrcPhysMode; public uint SetSrcPhysMode;
public SetPhysModeTarget SetSrcPhysModeTarget => (SetPhysModeTarget)((SetSrcPhysMode >> 0) & 0x3); public SetPhysModeTarget SetSrcPhysModeTarget => (SetPhysModeTarget)(SetSrcPhysMode & 0x3);
public uint SetDstPhysMode; public uint SetDstPhysMode;
public SetPhysModeTarget SetDstPhysModeTarget => (SetPhysModeTarget)((SetDstPhysMode >> 0) & 0x3); public SetPhysModeTarget SetDstPhysModeTarget => (SetPhysModeTarget)(SetDstPhysMode & 0x3);
public fixed uint Reserved268[38]; public fixed uint Reserved268[38];
public uint LaunchDma; public uint LaunchDma;
public LaunchDmaDataTransferType LaunchDmaDataTransferType => (LaunchDmaDataTransferType)((LaunchDma >> 0) & 0x3); public LaunchDmaDataTransferType LaunchDmaDataTransferType => (LaunchDmaDataTransferType)(LaunchDma & 0x3);
public bool LaunchDmaFlushEnable => (LaunchDma & 0x4) != 0; public bool LaunchDmaFlushEnable => (LaunchDma & 0x4) != 0;
public LaunchDmaSemaphoreType LaunchDmaSemaphoreType => (LaunchDmaSemaphoreType)((LaunchDma >> 3) & 0x3); public LaunchDmaSemaphoreType LaunchDmaSemaphoreType => (LaunchDmaSemaphoreType)((LaunchDma >> 3) & 0x3);
public LaunchDmaInterruptType LaunchDmaInterruptType => (LaunchDmaInterruptType)((LaunchDma >> 5) & 0x3); public LaunchDmaInterruptType LaunchDmaInterruptType => (LaunchDmaInterruptType)((LaunchDma >> 5) & 0x3);
@@ -218,10 +218,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
public LaunchDmaBypassL2 LaunchDmaBypassL2 => (LaunchDmaBypassL2)((LaunchDma >> 20) & 0x1); public LaunchDmaBypassL2 LaunchDmaBypassL2 => (LaunchDmaBypassL2)((LaunchDma >> 20) & 0x1);
public fixed uint Reserved304[63]; public fixed uint Reserved304[63];
public uint OffsetInUpper; public uint OffsetInUpper;
public int OffsetInUpperUpper => (int)((OffsetInUpper >> 0) & 0xFF); public int OffsetInUpperUpper => (int)(OffsetInUpper & 0xFF);
public uint OffsetInLower; public uint OffsetInLower;
public uint OffsetOutUpper; public uint OffsetOutUpper;
public int OffsetOutUpperUpper => (int)((OffsetOutUpper >> 0) & 0xFF); public int OffsetOutUpperUpper => (int)(OffsetOutUpper & 0xFF);
public uint OffsetOutLower; public uint OffsetOutLower;
public uint PitchIn; public uint PitchIn;
public uint PitchOut; public uint PitchOut;
@@ -231,7 +231,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
public uint SetRemapConstA; public uint SetRemapConstA;
public uint SetRemapConstB; public uint SetRemapConstB;
public uint SetRemapComponents; public uint SetRemapComponents;
public SetRemapComponentsDst SetRemapComponentsDstX => (SetRemapComponentsDst)((SetRemapComponents >> 0) & 0x7); public SetRemapComponentsDst SetRemapComponentsDstX => (SetRemapComponentsDst)(SetRemapComponents & 0x7);
public SetRemapComponentsDst SetRemapComponentsDstY => (SetRemapComponentsDst)((SetRemapComponents >> 4) & 0x7); public SetRemapComponentsDst SetRemapComponentsDstY => (SetRemapComponentsDst)((SetRemapComponents >> 4) & 0x7);
public SetRemapComponentsDst SetRemapComponentsDstZ => (SetRemapComponentsDst)((SetRemapComponents >> 8) & 0x7); public SetRemapComponentsDst SetRemapComponentsDstZ => (SetRemapComponentsDst)((SetRemapComponents >> 8) & 0x7);
public SetRemapComponentsDst SetRemapComponentsDstW => (SetRemapComponentsDst)((SetRemapComponents >> 12) & 0x7); public SetRemapComponentsDst SetRemapComponentsDstW => (SetRemapComponentsDst)((SetRemapComponents >> 12) & 0x7);
@@ -239,7 +239,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
public SetRemapComponentsNumComponents SetRemapComponentsNumSrcComponents => (SetRemapComponentsNumComponents)((SetRemapComponents >> 20) & 0x3); public SetRemapComponentsNumComponents SetRemapComponentsNumSrcComponents => (SetRemapComponentsNumComponents)((SetRemapComponents >> 20) & 0x3);
public SetRemapComponentsNumComponents SetRemapComponentsNumDstComponents => (SetRemapComponentsNumComponents)((SetRemapComponents >> 24) & 0x3); public SetRemapComponentsNumComponents SetRemapComponentsNumDstComponents => (SetRemapComponentsNumComponents)((SetRemapComponents >> 24) & 0x3);
public uint SetDstBlockSize; public uint SetDstBlockSize;
public SetBlockSizeWidth SetDstBlockSizeWidth => (SetBlockSizeWidth)((SetDstBlockSize >> 0) & 0xF); public SetBlockSizeWidth SetDstBlockSizeWidth => (SetBlockSizeWidth)(SetDstBlockSize & 0xF);
public SetBlockSizeHeight SetDstBlockSizeHeight => (SetBlockSizeHeight)((SetDstBlockSize >> 4) & 0xF); public SetBlockSizeHeight SetDstBlockSizeHeight => (SetBlockSizeHeight)((SetDstBlockSize >> 4) & 0xF);
public SetBlockSizeDepth SetDstBlockSizeDepth => (SetBlockSizeDepth)((SetDstBlockSize >> 8) & 0xF); public SetBlockSizeDepth SetDstBlockSizeDepth => (SetBlockSizeDepth)((SetDstBlockSize >> 8) & 0xF);
public SetBlockSizeGobHeight SetDstBlockSizeGobHeight => (SetBlockSizeGobHeight)((SetDstBlockSize >> 12) & 0xF); public SetBlockSizeGobHeight SetDstBlockSizeGobHeight => (SetBlockSizeGobHeight)((SetDstBlockSize >> 12) & 0xF);
@@ -248,11 +248,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
public uint SetDstDepth; public uint SetDstDepth;
public uint SetDstLayer; public uint SetDstLayer;
public uint SetDstOrigin; public uint SetDstOrigin;
public int SetDstOriginX => (int)((SetDstOrigin >> 0) & 0xFFFF); public int SetDstOriginX => (int)(SetDstOrigin & 0xFFFF);
public int SetDstOriginY => (int)((SetDstOrigin >> 16) & 0xFFFF); public int SetDstOriginY => (int)((SetDstOrigin >> 16) & 0xFFFF);
public uint Reserved724; public uint Reserved724;
public uint SetSrcBlockSize; public uint SetSrcBlockSize;
public SetBlockSizeWidth SetSrcBlockSizeWidth => (SetBlockSizeWidth)((SetSrcBlockSize >> 0) & 0xF); public SetBlockSizeWidth SetSrcBlockSizeWidth => (SetBlockSizeWidth)(SetSrcBlockSize & 0xF);
public SetBlockSizeHeight SetSrcBlockSizeHeight => (SetBlockSizeHeight)((SetSrcBlockSize >> 4) & 0xF); public SetBlockSizeHeight SetSrcBlockSizeHeight => (SetBlockSizeHeight)((SetSrcBlockSize >> 4) & 0xF);
public SetBlockSizeDepth SetSrcBlockSizeDepth => (SetBlockSizeDepth)((SetSrcBlockSize >> 8) & 0xF); public SetBlockSizeDepth SetSrcBlockSizeDepth => (SetBlockSizeDepth)((SetSrcBlockSize >> 8) & 0xF);
public SetBlockSizeGobHeight SetSrcBlockSizeGobHeight => (SetBlockSizeGobHeight)((SetSrcBlockSize >> 12) & 0xF); public SetBlockSizeGobHeight SetSrcBlockSizeGobHeight => (SetBlockSizeGobHeight)((SetSrcBlockSize >> 12) & 0xF);
@@ -261,7 +261,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
public uint SetSrcDepth; public uint SetSrcDepth;
public uint SetSrcLayer; public uint SetSrcLayer;
public uint SetSrcOrigin; public uint SetSrcOrigin;
public int SetSrcOriginX => (int)((SetSrcOrigin >> 0) & 0xFFFF); public int SetSrcOriginX => (int)(SetSrcOrigin & 0xFFFF);
public int SetSrcOriginY => (int)((SetSrcOrigin >> 16) & 0xFFFF); public int SetSrcOriginY => (int)((SetSrcOrigin >> 16) & 0xFFFF);
public fixed uint Reserved740[629]; public fixed uint Reserved740[629];
public uint PmTriggerEnd; public uint PmTriggerEnd;

View File

@@ -29,7 +29,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
public uint Method; public uint Method;
#pragma warning restore CS0649 #pragma warning restore CS0649
public int MethodAddressOld => (int)((Method >> 2) & 0x7FF); public int MethodAddressOld => (int)((Method >> 2) & 0x7FF);
public int MethodAddress => (int)((Method >> 0) & 0xFFF); public int MethodAddress => (int)(Method & 0xFFF);
public int SubdeviceMask => (int)((Method >> 4) & 0xFFF); public int SubdeviceMask => (int)((Method >> 4) & 0xFFF);
public int MethodSubchannel => (int)((Method >> 13) & 0x7); public int MethodSubchannel => (int)((Method >> 13) & 0x7);
public TertOp TertOp => (TertOp)((Method >> 16) & 0x3); public TertOp TertOp => (TertOp)((Method >> 16) & 0x3);

View File

@@ -39,17 +39,17 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
#pragma warning disable CS0649 #pragma warning disable CS0649
public uint Entry0; public uint Entry0;
#pragma warning restore CS0649 #pragma warning restore CS0649
public Entry0Fetch Entry0Fetch => (Entry0Fetch)((Entry0 >> 0) & 0x1); public Entry0Fetch Entry0Fetch => (Entry0Fetch)(Entry0 & 0x1);
public int Entry0Get => (int)((Entry0 >> 2) & 0x3FFFFFFF); public int Entry0Get => (int)((Entry0 >> 2) & 0x3FFFFFFF);
public int Entry0Operand => (int)(Entry0); public int Entry0Operand => (int)(Entry0);
#pragma warning disable CS0649 #pragma warning disable CS0649
public uint Entry1; public uint Entry1;
#pragma warning restore CS0649 #pragma warning restore CS0649
public int Entry1GetHi => (int)((Entry1 >> 0) & 0xFF); public int Entry1GetHi => (int)(Entry1 & 0xFF);
public Entry1Priv Entry1Priv => (Entry1Priv)((Entry1 >> 8) & 0x1); public Entry1Priv Entry1Priv => (Entry1Priv)((Entry1 >> 8) & 0x1);
public Entry1Level Entry1Level => (Entry1Level)((Entry1 >> 9) & 0x1); public Entry1Level Entry1Level => (Entry1Level)((Entry1 >> 9) & 0x1);
public int Entry1Length => (int)((Entry1 >> 10) & 0x1FFFFF); public int Entry1Length => (int)((Entry1 >> 10) & 0x1FFFFF);
public Entry1Sync Entry1Sync => (Entry1Sync)((Entry1 >> 31) & 0x1); public Entry1Sync Entry1Sync => (Entry1Sync)((Entry1 >> 31) & 0x1);
public Entry1Opcode Entry1Opcode => (Entry1Opcode)((Entry1 >> 0) & 0xFF); public Entry1Opcode Entry1Opcode => (Entry1Opcode)(Entry1 & 0xFF);
} }
} }

View File

@@ -153,7 +153,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
{ {
#pragma warning disable CS0649 #pragma warning disable CS0649
public uint SetObject; public uint SetObject;
public int SetObjectNvclass => (int)((SetObject >> 0) & 0xFFFF); public int SetObjectNvclass => (int)(SetObject & 0xFFFF);
public int SetObjectEngine => (int)((SetObject >> 16) & 0x1F); public int SetObjectEngine => (int)((SetObject >> 16) & 0x1F);
public uint Illegal; public uint Illegal;
public int IllegalHandle => (int)(Illegal); public int IllegalHandle => (int)(Illegal);
@@ -161,13 +161,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
public int NopHandle => (int)(Nop); public int NopHandle => (int)(Nop);
public uint Reserved0C; public uint Reserved0C;
public uint Semaphorea; public uint Semaphorea;
public int SemaphoreaOffsetUpper => (int)((Semaphorea >> 0) & 0xFF); public int SemaphoreaOffsetUpper => (int)(Semaphorea & 0xFF);
public uint Semaphoreb; public uint Semaphoreb;
public int SemaphorebOffsetLower => (int)((Semaphoreb >> 2) & 0x3FFFFFFF); public int SemaphorebOffsetLower => (int)((Semaphoreb >> 2) & 0x3FFFFFFF);
public uint Semaphorec; public uint Semaphorec;
public int SemaphorecPayload => (int)(Semaphorec); public int SemaphorecPayload => (int)(Semaphorec);
public uint Semaphored; public uint Semaphored;
public SemaphoredOperation SemaphoredOperation => (SemaphoredOperation)((Semaphored >> 0) & 0x1F); public SemaphoredOperation SemaphoredOperation => (SemaphoredOperation)(Semaphored & 0x1F);
public SemaphoredAcquireSwitch SemaphoredAcquireSwitch => (SemaphoredAcquireSwitch)((Semaphored >> 12) & 0x1); public SemaphoredAcquireSwitch SemaphoredAcquireSwitch => (SemaphoredAcquireSwitch)((Semaphored >> 12) & 0x1);
public SemaphoredReleaseWfi SemaphoredReleaseWfi => (SemaphoredReleaseWfi)((Semaphored >> 20) & 0x1); public SemaphoredReleaseWfi SemaphoredReleaseWfi => (SemaphoredReleaseWfi)((Semaphored >> 20) & 0x1);
public SemaphoredReleaseSize SemaphoredReleaseSize => (SemaphoredReleaseSize)((Semaphored >> 24) & 0x1); public SemaphoredReleaseSize SemaphoredReleaseSize => (SemaphoredReleaseSize)((Semaphored >> 24) & 0x1);
@@ -181,14 +181,14 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
public uint Reserved2C; public uint Reserved2C;
public uint MemOpC; public uint MemOpC;
public int MemOpCOperandLow => (int)((MemOpC >> 2) & 0x3FFFFFFF); public int MemOpCOperandLow => (int)((MemOpC >> 2) & 0x3FFFFFFF);
public MemOpCTlbInvalidatePdb MemOpCTlbInvalidatePdb => (MemOpCTlbInvalidatePdb)((MemOpC >> 0) & 0x1); public MemOpCTlbInvalidatePdb MemOpCTlbInvalidatePdb => (MemOpCTlbInvalidatePdb)(MemOpC & 0x1);
public MemOpCTlbInvalidateGpc MemOpCTlbInvalidateGpc => (MemOpCTlbInvalidateGpc)((MemOpC >> 1) & 0x1); public MemOpCTlbInvalidateGpc MemOpCTlbInvalidateGpc => (MemOpCTlbInvalidateGpc)((MemOpC >> 1) & 0x1);
public MemOpCTlbInvalidateTarget MemOpCTlbInvalidateTarget => (MemOpCTlbInvalidateTarget)((MemOpC >> 10) & 0x3); public MemOpCTlbInvalidateTarget MemOpCTlbInvalidateTarget => (MemOpCTlbInvalidateTarget)((MemOpC >> 10) & 0x3);
public int MemOpCTlbInvalidateAddrLo => (int)((MemOpC >> 12) & 0xFFFFF); public int MemOpCTlbInvalidateAddrLo => (int)((MemOpC >> 12) & 0xFFFFF);
public uint MemOpD; public uint MemOpD;
public int MemOpDOperandHigh => (int)((MemOpD >> 0) & 0xFF); public int MemOpDOperandHigh => (int)(MemOpD & 0xFF);
public MemOpDOperation MemOpDOperation => (MemOpDOperation)((MemOpD >> 27) & 0x1F); public MemOpDOperation MemOpDOperation => (MemOpDOperation)((MemOpD >> 27) & 0x1F);
public int MemOpDTlbInvalidateAddrHi => (int)((MemOpD >> 0) & 0xFF); public int MemOpDTlbInvalidateAddrHi => (int)(MemOpD & 0xFF);
public uint Reserved38; public uint Reserved38;
public uint Reserved3C; public uint Reserved3C;
public uint Reserved40; public uint Reserved40;
@@ -207,15 +207,15 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
public uint Syncpointa; public uint Syncpointa;
public int SyncpointaPayload => (int)(Syncpointa); public int SyncpointaPayload => (int)(Syncpointa);
public uint Syncpointb; public uint Syncpointb;
public SyncpointbOperation SyncpointbOperation => (SyncpointbOperation)((Syncpointb >> 0) & 0x1); public SyncpointbOperation SyncpointbOperation => (SyncpointbOperation)(Syncpointb & 0x1);
public SyncpointbWaitSwitch SyncpointbWaitSwitch => (SyncpointbWaitSwitch)((Syncpointb >> 4) & 0x1); public SyncpointbWaitSwitch SyncpointbWaitSwitch => (SyncpointbWaitSwitch)((Syncpointb >> 4) & 0x1);
public int SyncpointbSyncptIndex => (int)((Syncpointb >> 8) & 0xFFF); public int SyncpointbSyncptIndex => (int)((Syncpointb >> 8) & 0xFFF);
public uint Wfi; public uint Wfi;
public WfiScope WfiScope => (WfiScope)((Wfi >> 0) & 0x1); public WfiScope WfiScope => (WfiScope)(Wfi & 0x1);
public uint CrcCheck; public uint CrcCheck;
public int CrcCheckValue => (int)(CrcCheck); public int CrcCheckValue => (int)(CrcCheck);
public uint Yield; public uint Yield;
public YieldOp YieldOp => (YieldOp)((Yield >> 0) & 0x3); public YieldOp YieldOp => (YieldOp)(Yield & 0x3);
// TODO: Eventually move this to per-engine state. // TODO: Eventually move this to per-engine state.
public Array31<uint> Reserved84; public Array31<uint> Reserved84;
public uint NoOperation; public uint NoOperation;

View File

@@ -113,22 +113,22 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory
{ {
#pragma warning disable CS0649 #pragma warning disable CS0649
public uint SetObject; public uint SetObject;
public int SetObjectClassId => (int)((SetObject >> 0) & 0xFFFF); public int SetObjectClassId => (int)(SetObject & 0xFFFF);
public int SetObjectEngineId => (int)((SetObject >> 16) & 0x1F); public int SetObjectEngineId => (int)((SetObject >> 16) & 0x1F);
public fixed uint Reserved04[63]; public fixed uint Reserved04[63];
public uint NoOperation; public uint NoOperation;
public uint SetNotifyA; public uint SetNotifyA;
public int SetNotifyAAddressUpper => (int)((SetNotifyA >> 0) & 0xFF); public int SetNotifyAAddressUpper => (int)(SetNotifyA & 0xFF);
public uint SetNotifyB; public uint SetNotifyB;
public uint Notify; public uint Notify;
public NotifyType NotifyType => (NotifyType)(Notify); public NotifyType NotifyType => (NotifyType)(Notify);
public uint WaitForIdle; public uint WaitForIdle;
public fixed uint Reserved114[7]; public fixed uint Reserved114[7];
public uint SetGlobalRenderEnableA; public uint SetGlobalRenderEnableA;
public int SetGlobalRenderEnableAOffsetUpper => (int)((SetGlobalRenderEnableA >> 0) & 0xFF); public int SetGlobalRenderEnableAOffsetUpper => (int)(SetGlobalRenderEnableA & 0xFF);
public uint SetGlobalRenderEnableB; public uint SetGlobalRenderEnableB;
public uint SetGlobalRenderEnableC; public uint SetGlobalRenderEnableC;
public int SetGlobalRenderEnableCMode => (int)((SetGlobalRenderEnableC >> 0) & 0x7); public int SetGlobalRenderEnableCMode => (int)(SetGlobalRenderEnableC & 0x7);
public uint SendGoIdle; public uint SendGoIdle;
public uint PmTrigger; public uint PmTrigger;
public uint PmTriggerWfi; public uint PmTriggerWfi;
@@ -139,11 +139,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory
public uint LineLengthIn; public uint LineLengthIn;
public uint LineCount; public uint LineCount;
public uint OffsetOutUpper; public uint OffsetOutUpper;
public int OffsetOutUpperValue => (int)((OffsetOutUpper >> 0) & 0xFF); public int OffsetOutUpperValue => (int)(OffsetOutUpper & 0xFF);
public uint OffsetOut; public uint OffsetOut;
public uint PitchOut; public uint PitchOut;
public uint SetDstBlockSize; public uint SetDstBlockSize;
public SetDstBlockSizeWidth SetDstBlockSizeWidth => (SetDstBlockSizeWidth)((SetDstBlockSize >> 0) & 0xF); public SetDstBlockSizeWidth SetDstBlockSizeWidth => (SetDstBlockSizeWidth)(SetDstBlockSize & 0xF);
public SetDstBlockSizeHeight SetDstBlockSizeHeight => (SetDstBlockSizeHeight)((SetDstBlockSize >> 4) & 0xF); public SetDstBlockSizeHeight SetDstBlockSizeHeight => (SetDstBlockSizeHeight)((SetDstBlockSize >> 4) & 0xF);
public SetDstBlockSizeDepth SetDstBlockSizeDepth => (SetDstBlockSizeDepth)((SetDstBlockSize >> 8) & 0xF); public SetDstBlockSizeDepth SetDstBlockSizeDepth => (SetDstBlockSizeDepth)((SetDstBlockSize >> 8) & 0xF);
public uint SetDstWidth; public uint SetDstWidth;
@@ -151,11 +151,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory
public uint SetDstDepth; public uint SetDstDepth;
public uint SetDstLayer; public uint SetDstLayer;
public uint SetDstOriginBytesX; public uint SetDstOriginBytesX;
public int SetDstOriginBytesXV => (int)((SetDstOriginBytesX >> 0) & 0xFFFFF); public int SetDstOriginBytesXV => (int)(SetDstOriginBytesX & 0xFFFFF);
public uint SetDstOriginSamplesY; public uint SetDstOriginSamplesY;
public int SetDstOriginSamplesYV => (int)((SetDstOriginSamplesY >> 0) & 0xFFFF); public int SetDstOriginSamplesYV => (int)(SetDstOriginSamplesY & 0xFFFF);
public uint LaunchDma; public uint LaunchDma;
public LaunchDmaDstMemoryLayout LaunchDmaDstMemoryLayout => (LaunchDmaDstMemoryLayout)((LaunchDma >> 0) & 0x1); public LaunchDmaDstMemoryLayout LaunchDmaDstMemoryLayout => (LaunchDmaDstMemoryLayout)(LaunchDma & 0x1);
public LaunchDmaCompletionType LaunchDmaCompletionType => (LaunchDmaCompletionType)((LaunchDma >> 4) & 0x3); public LaunchDmaCompletionType LaunchDmaCompletionType => (LaunchDmaCompletionType)((LaunchDma >> 4) & 0x3);
public LaunchDmaInterruptType LaunchDmaInterruptType => (LaunchDmaInterruptType)((LaunchDma >> 8) & 0x3); public LaunchDmaInterruptType LaunchDmaInterruptType => (LaunchDmaInterruptType)((LaunchDma >> 8) & 0x3);
public LaunchDmaSemaphoreStructSize LaunchDmaSemaphoreStructSize => (LaunchDmaSemaphoreStructSize)((LaunchDma >> 12) & 0x1); public LaunchDmaSemaphoreStructSize LaunchDmaSemaphoreStructSize => (LaunchDmaSemaphoreStructSize)((LaunchDma >> 12) & 0x1);
@@ -166,7 +166,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory
public uint LoadInlineData; public uint LoadInlineData;
public fixed uint Reserved1B8[9]; public fixed uint Reserved1B8[9];
public uint SetI2mSemaphoreA; public uint SetI2mSemaphoreA;
public int SetI2mSemaphoreAOffsetUpper => (int)((SetI2mSemaphoreA >> 0) & 0xFF); public int SetI2mSemaphoreAOffsetUpper => (int)(SetI2mSemaphoreA & 0xFF);
public uint SetI2mSemaphoreB; public uint SetI2mSemaphoreB;
public uint SetI2mSemaphoreC; public uint SetI2mSemaphoreC;
public fixed uint Reserved1E8[2]; public fixed uint Reserved1E8[2];

View File

@@ -539,6 +539,14 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
engine.UpdateState(); engine.UpdateState();
if (instanceCount > 1)
{
// Must be called after UpdateState as it assumes the shader state
// has already been set, and that bindings have been updated already.
_channel.BufferManager.SetInstancedDrawVertexCount(count);
}
if (indexed) if (indexed)
{ {
_context.Renderer.Pipeline.DrawIndexed(count, instanceCount, firstIndex, firstVertex, firstInstance); _context.Renderer.Pipeline.DrawIndexed(count, instanceCount, firstIndex, firstVertex, firstInstance);
@@ -676,6 +684,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
_channel.BufferManager.SetIndexBuffer(br, IndexType.UInt); _channel.BufferManager.SetIndexBuffer(br, IndexType.UInt);
} }
_channel.BufferManager.SetInstancedDrawVertexCount(_instancedIndexCount);
_context.Renderer.Pipeline.DrawIndexed( _context.Renderer.Pipeline.DrawIndexed(
_instancedIndexCount, _instancedIndexCount,
_instanceIndex + 1, _instanceIndex + 1,
@@ -685,6 +695,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
} }
else else
{ {
_channel.BufferManager.SetInstancedDrawVertexCount(_instancedDrawStateCount);
_context.Renderer.Pipeline.Draw( _context.Renderer.Pipeline.Draw(
_instancedDrawStateCount, _instancedDrawStateCount,
_instanceIndex + 1, _instanceIndex + 1,

View File

@@ -269,7 +269,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
_prevFirstVertex = _state.State.FirstVertex; _prevFirstVertex = _state.State.FirstVertex;
} }
bool tfEnable = _state.State.TfEnable; bool tfEnable = _state.State.TfEnable && _context.Capabilities.SupportsTransformFeedback;
if (!tfEnable && _prevTfEnable) if (!tfEnable && _prevTfEnable)
{ {
@@ -1367,6 +1367,22 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
_vsUsesDrawParameters = gs.Shaders[1]?.Info.UsesDrawParameters ?? false; _vsUsesDrawParameters = gs.Shaders[1]?.Info.UsesDrawParameters ?? false;
_vsClipDistancesWritten = gs.Shaders[1]?.Info.ClipDistancesWritten ?? 0; _vsClipDistancesWritten = gs.Shaders[1]?.Info.ClipDistancesWritten ?? 0;
bool hasTransformFeedback = gs.SpecializationState.TransformFeedbackDescriptors != null;
if (hasTransformFeedback != _channel.BufferManager.HasTransformFeedbackOutputs)
{
if (!_context.Capabilities.SupportsTransformFeedback)
{
// If host does not support transform feedback, and the shader changed,
// we might need to update bindings as transform feedback emulation
// uses storage buffer bindings that might have been used for something
// else in a previous draw.
_channel.BufferManager.ForceTransformFeedbackAndStorageBuffersDirty();
}
_channel.BufferManager.HasTransformFeedbackOutputs = hasTransformFeedback;
}
if (oldVsClipDistancesWritten != _vsClipDistancesWritten) if (oldVsClipDistancesWritten != _vsClipDistancesWritten)
{ {
UpdateUserClipState(); UpdateUserClipState();

View File

@@ -746,12 +746,12 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
{ {
#pragma warning disable CS0649 #pragma warning disable CS0649
public uint SetObject; public uint SetObject;
public int SetObjectClassId => (int)((SetObject >> 0) & 0xFFFF); public int SetObjectClassId => (int)(SetObject & 0xFFFF);
public int SetObjectEngineId => (int)((SetObject >> 16) & 0x1F); public int SetObjectEngineId => (int)((SetObject >> 16) & 0x1F);
public fixed uint Reserved04[63]; public fixed uint Reserved04[63];
public uint NoOperation; public uint NoOperation;
public uint SetNotifyA; public uint SetNotifyA;
public int SetNotifyAAddressUpper => (int)((SetNotifyA >> 0) & 0xFF); public int SetNotifyAAddressUpper => (int)(SetNotifyA & 0xFF);
public uint SetNotifyB; public uint SetNotifyB;
public uint Notify; public uint Notify;
public NotifyType NotifyType => (NotifyType)(Notify); public NotifyType NotifyType => (NotifyType)(Notify);
@@ -761,13 +761,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
public uint LoadMmeStartAddressRamPointer; public uint LoadMmeStartAddressRamPointer;
public uint LoadMmeStartAddressRam; public uint LoadMmeStartAddressRam;
public uint SetMmeShadowRamControl; public uint SetMmeShadowRamControl;
public SetMmeShadowRamControlMode SetMmeShadowRamControlMode => (SetMmeShadowRamControlMode)((SetMmeShadowRamControl >> 0) & 0x3); public SetMmeShadowRamControlMode SetMmeShadowRamControlMode => (SetMmeShadowRamControlMode)(SetMmeShadowRamControl & 0x3);
public fixed uint Reserved128[2]; public fixed uint Reserved128[2];
public uint SetGlobalRenderEnableA; public uint SetGlobalRenderEnableA;
public int SetGlobalRenderEnableAOffsetUpper => (int)((SetGlobalRenderEnableA >> 0) & 0xFF); public int SetGlobalRenderEnableAOffsetUpper => (int)(SetGlobalRenderEnableA & 0xFF);
public uint SetGlobalRenderEnableB; public uint SetGlobalRenderEnableB;
public uint SetGlobalRenderEnableC; public uint SetGlobalRenderEnableC;
public int SetGlobalRenderEnableCMode => (int)((SetGlobalRenderEnableC >> 0) & 0x7); public int SetGlobalRenderEnableCMode => (int)(SetGlobalRenderEnableC & 0x7);
public uint SendGoIdle; public uint SendGoIdle;
public uint PmTrigger; public uint PmTrigger;
public uint PmTriggerWfi; public uint PmTriggerWfi;
@@ -778,11 +778,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
public uint LineLengthIn; public uint LineLengthIn;
public uint LineCount; public uint LineCount;
public uint OffsetOutUpper; public uint OffsetOutUpper;
public int OffsetOutUpperValue => (int)((OffsetOutUpper >> 0) & 0xFF); public int OffsetOutUpperValue => (int)(OffsetOutUpper & 0xFF);
public uint OffsetOut; public uint OffsetOut;
public uint PitchOut; public uint PitchOut;
public uint SetDstBlockSize; public uint SetDstBlockSize;
public SetDstBlockSizeWidth SetDstBlockSizeWidth => (SetDstBlockSizeWidth)((SetDstBlockSize >> 0) & 0xF); public SetDstBlockSizeWidth SetDstBlockSizeWidth => (SetDstBlockSizeWidth)(SetDstBlockSize & 0xF);
public SetDstBlockSizeHeight SetDstBlockSizeHeight => (SetDstBlockSizeHeight)((SetDstBlockSize >> 4) & 0xF); public SetDstBlockSizeHeight SetDstBlockSizeHeight => (SetDstBlockSizeHeight)((SetDstBlockSize >> 4) & 0xF);
public SetDstBlockSizeDepth SetDstBlockSizeDepth => (SetDstBlockSizeDepth)((SetDstBlockSize >> 8) & 0xF); public SetDstBlockSizeDepth SetDstBlockSizeDepth => (SetDstBlockSizeDepth)((SetDstBlockSize >> 8) & 0xF);
public uint SetDstWidth; public uint SetDstWidth;
@@ -790,11 +790,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
public uint SetDstDepth; public uint SetDstDepth;
public uint SetDstLayer; public uint SetDstLayer;
public uint SetDstOriginBytesX; public uint SetDstOriginBytesX;
public int SetDstOriginBytesXV => (int)((SetDstOriginBytesX >> 0) & 0xFFFFF); public int SetDstOriginBytesXV => (int)(SetDstOriginBytesX & 0xFFFFF);
public uint SetDstOriginSamplesY; public uint SetDstOriginSamplesY;
public int SetDstOriginSamplesYV => (int)((SetDstOriginSamplesY >> 0) & 0xFFFF); public int SetDstOriginSamplesYV => (int)(SetDstOriginSamplesY & 0xFFFF);
public uint LaunchDma; public uint LaunchDma;
public LaunchDmaDstMemoryLayout LaunchDmaDstMemoryLayout => (LaunchDmaDstMemoryLayout)((LaunchDma >> 0) & 0x1); public LaunchDmaDstMemoryLayout LaunchDmaDstMemoryLayout => (LaunchDmaDstMemoryLayout)(LaunchDma & 0x1);
public LaunchDmaCompletionType LaunchDmaCompletionType => (LaunchDmaCompletionType)((LaunchDma >> 4) & 0x3); public LaunchDmaCompletionType LaunchDmaCompletionType => (LaunchDmaCompletionType)((LaunchDma >> 4) & 0x3);
public LaunchDmaInterruptType LaunchDmaInterruptType => (LaunchDmaInterruptType)((LaunchDma >> 8) & 0x3); public LaunchDmaInterruptType LaunchDmaInterruptType => (LaunchDmaInterruptType)((LaunchDma >> 8) & 0x3);
public LaunchDmaSemaphoreStructSize LaunchDmaSemaphoreStructSize => (LaunchDmaSemaphoreStructSize)((LaunchDma >> 12) & 0x1); public LaunchDmaSemaphoreStructSize LaunchDmaSemaphoreStructSize => (LaunchDmaSemaphoreStructSize)((LaunchDma >> 12) & 0x1);

View File

@@ -499,12 +499,12 @@ namespace Ryujinx.Graphics.Gpu.Engine.Twod
{ {
#pragma warning disable CS0649 #pragma warning disable CS0649
public uint SetObject; public uint SetObject;
public int SetObjectClassId => (int)((SetObject >> 0) & 0xFFFF); public int SetObjectClassId => (int)(SetObject & 0xFFFF);
public int SetObjectEngineId => (int)((SetObject >> 16) & 0x1F); public int SetObjectEngineId => (int)((SetObject >> 16) & 0x1F);
public fixed uint Reserved04[63]; public fixed uint Reserved04[63];
public uint NoOperation; public uint NoOperation;
public uint SetNotifyA; public uint SetNotifyA;
public int SetNotifyAAddressUpper => (int)((SetNotifyA >> 0) & 0x1FFFFFF); public int SetNotifyAAddressUpper => (int)(SetNotifyA & 0x1FFFFFF);
public uint SetNotifyB; public uint SetNotifyB;
public uint Notify; public uint Notify;
public NotifyType NotifyType => (NotifyType)(Notify); public NotifyType NotifyType => (NotifyType)(Notify);
@@ -514,13 +514,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.Twod
public uint LoadMmeStartAddressRamPointer; public uint LoadMmeStartAddressRamPointer;
public uint LoadMmeStartAddressRam; public uint LoadMmeStartAddressRam;
public uint SetMmeShadowRamControl; public uint SetMmeShadowRamControl;
public SetMmeShadowRamControlMode SetMmeShadowRamControlMode => (SetMmeShadowRamControlMode)((SetMmeShadowRamControl >> 0) & 0x3); public SetMmeShadowRamControlMode SetMmeShadowRamControlMode => (SetMmeShadowRamControlMode)(SetMmeShadowRamControl & 0x3);
public fixed uint Reserved128[2]; public fixed uint Reserved128[2];
public uint SetGlobalRenderEnableA; public uint SetGlobalRenderEnableA;
public int SetGlobalRenderEnableAOffsetUpper => (int)((SetGlobalRenderEnableA >> 0) & 0xFF); public int SetGlobalRenderEnableAOffsetUpper => (int)(SetGlobalRenderEnableA & 0xFF);
public uint SetGlobalRenderEnableB; public uint SetGlobalRenderEnableB;
public uint SetGlobalRenderEnableC; public uint SetGlobalRenderEnableC;
public int SetGlobalRenderEnableCMode => (int)((SetGlobalRenderEnableC >> 0) & 0x7); public int SetGlobalRenderEnableCMode => (int)(SetGlobalRenderEnableC & 0x7);
public uint SendGoIdle; public uint SendGoIdle;
public uint PmTrigger; public uint PmTrigger;
public fixed uint Reserved144[3]; public fixed uint Reserved144[3];
@@ -533,9 +533,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Twod
public int SetMmeSwitchStateRestoreMacro => (int)((SetMmeSwitchState >> 12) & 0xFF); public int SetMmeSwitchStateRestoreMacro => (int)((SetMmeSwitchState >> 12) & 0xFF);
public fixed uint Reserved1F0[4]; public fixed uint Reserved1F0[4];
public uint SetDstFormat; public uint SetDstFormat;
public SetDstFormatV SetDstFormatV => (SetDstFormatV)((SetDstFormat >> 0) & 0xFF); public SetDstFormatV SetDstFormatV => (SetDstFormatV)(SetDstFormat & 0xFF);
public uint SetDstMemoryLayout; public uint SetDstMemoryLayout;
public SetDstMemoryLayoutV SetDstMemoryLayoutV => (SetDstMemoryLayoutV)((SetDstMemoryLayout >> 0) & 0x1); public SetDstMemoryLayoutV SetDstMemoryLayoutV => (SetDstMemoryLayoutV)(SetDstMemoryLayout & 0x1);
public uint SetDstBlockSize; public uint SetDstBlockSize;
public SetDstBlockSizeHeight SetDstBlockSizeHeight => (SetDstBlockSizeHeight)((SetDstBlockSize >> 4) & 0x7); public SetDstBlockSizeHeight SetDstBlockSizeHeight => (SetDstBlockSizeHeight)((SetDstBlockSize >> 4) & 0x7);
public SetDstBlockSizeDepth SetDstBlockSizeDepth => (SetDstBlockSizeDepth)((SetDstBlockSize >> 8) & 0x7); public SetDstBlockSizeDepth SetDstBlockSizeDepth => (SetDstBlockSizeDepth)((SetDstBlockSize >> 8) & 0x7);
@@ -545,37 +545,37 @@ namespace Ryujinx.Graphics.Gpu.Engine.Twod
public uint SetDstWidth; public uint SetDstWidth;
public uint SetDstHeight; public uint SetDstHeight;
public uint SetDstOffsetUpper; public uint SetDstOffsetUpper;
public int SetDstOffsetUpperV => (int)((SetDstOffsetUpper >> 0) & 0xFF); public int SetDstOffsetUpperV => (int)(SetDstOffsetUpper & 0xFF);
public uint SetDstOffsetLower; public uint SetDstOffsetLower;
public uint FlushAndInvalidateRopMiniCache; public uint FlushAndInvalidateRopMiniCache;
public bool FlushAndInvalidateRopMiniCacheV => (FlushAndInvalidateRopMiniCache & 0x1) != 0; public bool FlushAndInvalidateRopMiniCacheV => (FlushAndInvalidateRopMiniCache & 0x1) != 0;
public uint SetSpareNoop06; public uint SetSpareNoop06;
public uint SetSrcFormat; public uint SetSrcFormat;
public SetSrcFormatV SetSrcFormatV => (SetSrcFormatV)((SetSrcFormat >> 0) & 0xFF); public SetSrcFormatV SetSrcFormatV => (SetSrcFormatV)(SetSrcFormat & 0xFF);
public uint SetSrcMemoryLayout; public uint SetSrcMemoryLayout;
public SetSrcMemoryLayoutV SetSrcMemoryLayoutV => (SetSrcMemoryLayoutV)((SetSrcMemoryLayout >> 0) & 0x1); public SetSrcMemoryLayoutV SetSrcMemoryLayoutV => (SetSrcMemoryLayoutV)(SetSrcMemoryLayout & 0x1);
public uint SetSrcBlockSize; public uint SetSrcBlockSize;
public SetSrcBlockSizeHeight SetSrcBlockSizeHeight => (SetSrcBlockSizeHeight)((SetSrcBlockSize >> 4) & 0x7); public SetSrcBlockSizeHeight SetSrcBlockSizeHeight => (SetSrcBlockSizeHeight)((SetSrcBlockSize >> 4) & 0x7);
public SetSrcBlockSizeDepth SetSrcBlockSizeDepth => (SetSrcBlockSizeDepth)((SetSrcBlockSize >> 8) & 0x7); public SetSrcBlockSizeDepth SetSrcBlockSizeDepth => (SetSrcBlockSizeDepth)((SetSrcBlockSize >> 8) & 0x7);
public uint SetSrcDepth; public uint SetSrcDepth;
public uint TwodInvalidateTextureDataCache; public uint TwodInvalidateTextureDataCache;
public TwodInvalidateTextureDataCacheV TwodInvalidateTextureDataCacheV => (TwodInvalidateTextureDataCacheV)((TwodInvalidateTextureDataCache >> 0) & 0x3); public TwodInvalidateTextureDataCacheV TwodInvalidateTextureDataCacheV => (TwodInvalidateTextureDataCacheV)(TwodInvalidateTextureDataCache & 0x3);
public uint SetSrcPitch; public uint SetSrcPitch;
public uint SetSrcWidth; public uint SetSrcWidth;
public uint SetSrcHeight; public uint SetSrcHeight;
public uint SetSrcOffsetUpper; public uint SetSrcOffsetUpper;
public int SetSrcOffsetUpperV => (int)((SetSrcOffsetUpper >> 0) & 0xFF); public int SetSrcOffsetUpperV => (int)(SetSrcOffsetUpper & 0xFF);
public uint SetSrcOffsetLower; public uint SetSrcOffsetLower;
public uint SetPixelsFromMemorySectorPromotion; public uint SetPixelsFromMemorySectorPromotion;
public SetPixelsFromMemorySectorPromotionV SetPixelsFromMemorySectorPromotionV => (SetPixelsFromMemorySectorPromotionV)((SetPixelsFromMemorySectorPromotion >> 0) & 0x3); public SetPixelsFromMemorySectorPromotionV SetPixelsFromMemorySectorPromotionV => (SetPixelsFromMemorySectorPromotionV)(SetPixelsFromMemorySectorPromotion & 0x3);
public uint SetSpareNoop12; public uint SetSpareNoop12;
public uint SetNumProcessingClusters; public uint SetNumProcessingClusters;
public SetNumProcessingClustersV SetNumProcessingClustersV => (SetNumProcessingClustersV)((SetNumProcessingClusters >> 0) & 0x1); public SetNumProcessingClustersV SetNumProcessingClustersV => (SetNumProcessingClustersV)(SetNumProcessingClusters & 0x1);
public uint SetRenderEnableA; public uint SetRenderEnableA;
public int SetRenderEnableAOffsetUpper => (int)((SetRenderEnableA >> 0) & 0xFF); public int SetRenderEnableAOffsetUpper => (int)(SetRenderEnableA & 0xFF);
public uint SetRenderEnableB; public uint SetRenderEnableB;
public uint SetRenderEnableC; public uint SetRenderEnableC;
public int SetRenderEnableCMode => (int)((SetRenderEnableC >> 0) & 0x7); public int SetRenderEnableCMode => (int)(SetRenderEnableC & 0x7);
public uint SetSpareNoop08; public uint SetSpareNoop08;
public uint SetSpareNoop01; public uint SetSpareNoop01;
public uint SetSpareNoop11; public uint SetSpareNoop11;
@@ -587,25 +587,25 @@ namespace Ryujinx.Graphics.Gpu.Engine.Twod
public uint SetClipEnable; public uint SetClipEnable;
public bool SetClipEnableV => (SetClipEnable & 0x1) != 0; public bool SetClipEnableV => (SetClipEnable & 0x1) != 0;
public uint SetColorKeyFormat; public uint SetColorKeyFormat;
public SetColorKeyFormatV SetColorKeyFormatV => (SetColorKeyFormatV)((SetColorKeyFormat >> 0) & 0x7); public SetColorKeyFormatV SetColorKeyFormatV => (SetColorKeyFormatV)(SetColorKeyFormat & 0x7);
public uint SetColorKey; public uint SetColorKey;
public uint SetColorKeyEnable; public uint SetColorKeyEnable;
public bool SetColorKeyEnableV => (SetColorKeyEnable & 0x1) != 0; public bool SetColorKeyEnableV => (SetColorKeyEnable & 0x1) != 0;
public uint SetRop; public uint SetRop;
public int SetRopV => (int)((SetRop >> 0) & 0xFF); public int SetRopV => (int)(SetRop & 0xFF);
public uint SetBeta1; public uint SetBeta1;
public uint SetBeta4; public uint SetBeta4;
public int SetBeta4B => (int)((SetBeta4 >> 0) & 0xFF); public int SetBeta4B => (int)(SetBeta4 & 0xFF);
public int SetBeta4G => (int)((SetBeta4 >> 8) & 0xFF); public int SetBeta4G => (int)((SetBeta4 >> 8) & 0xFF);
public int SetBeta4R => (int)((SetBeta4 >> 16) & 0xFF); public int SetBeta4R => (int)((SetBeta4 >> 16) & 0xFF);
public int SetBeta4A => (int)((SetBeta4 >> 24) & 0xFF); public int SetBeta4A => (int)((SetBeta4 >> 24) & 0xFF);
public uint SetOperation; public uint SetOperation;
public SetOperationV SetOperationV => (SetOperationV)((SetOperation >> 0) & 0x7); public SetOperationV SetOperationV => (SetOperationV)(SetOperation & 0x7);
public uint SetPatternOffset; public uint SetPatternOffset;
public int SetPatternOffsetX => (int)((SetPatternOffset >> 0) & 0x3F); public int SetPatternOffsetX => (int)(SetPatternOffset & 0x3F);
public int SetPatternOffsetY => (int)((SetPatternOffset >> 8) & 0x3F); public int SetPatternOffsetY => (int)((SetPatternOffset >> 8) & 0x3F);
public uint SetPatternSelect; public uint SetPatternSelect;
public SetPatternSelectV SetPatternSelectV => (SetPatternSelectV)((SetPatternSelect >> 0) & 0x3); public SetPatternSelectV SetPatternSelectV => (SetPatternSelectV)(SetPatternSelect & 0x3);
public uint SetDstColorRenderToZetaSurface; public uint SetDstColorRenderToZetaSurface;
public bool SetDstColorRenderToZetaSurfaceV => (SetDstColorRenderToZetaSurface & 0x1) != 0; public bool SetDstColorRenderToZetaSurfaceV => (SetDstColorRenderToZetaSurface & 0x1) != 0;
public uint SetSpareNoop04; public uint SetSpareNoop04;
@@ -618,15 +618,15 @@ namespace Ryujinx.Graphics.Gpu.Engine.Twod
public bool SetCompressionEnable => (SetCompression & 0x1) != 0; public bool SetCompressionEnable => (SetCompression & 0x1) != 0;
public uint SetSpareNoop09; public uint SetSpareNoop09;
public uint SetRenderEnableOverride; public uint SetRenderEnableOverride;
public SetRenderEnableOverrideMode SetRenderEnableOverrideMode => (SetRenderEnableOverrideMode)((SetRenderEnableOverride >> 0) & 0x3); public SetRenderEnableOverrideMode SetRenderEnableOverrideMode => (SetRenderEnableOverrideMode)(SetRenderEnableOverride & 0x3);
public uint SetPixelsFromMemoryDirection; public uint SetPixelsFromMemoryDirection;
public SetPixelsFromMemoryDirectionHorizontal SetPixelsFromMemoryDirectionHorizontal => (SetPixelsFromMemoryDirectionHorizontal)((SetPixelsFromMemoryDirection >> 0) & 0x3); public SetPixelsFromMemoryDirectionHorizontal SetPixelsFromMemoryDirectionHorizontal => (SetPixelsFromMemoryDirectionHorizontal)(SetPixelsFromMemoryDirection & 0x3);
public SetPixelsFromMemoryDirectionVertical SetPixelsFromMemoryDirectionVertical => (SetPixelsFromMemoryDirectionVertical)((SetPixelsFromMemoryDirection >> 4) & 0x3); public SetPixelsFromMemoryDirectionVertical SetPixelsFromMemoryDirectionVertical => (SetPixelsFromMemoryDirectionVertical)((SetPixelsFromMemoryDirection >> 4) & 0x3);
public uint SetSpareNoop10; public uint SetSpareNoop10;
public uint SetMonochromePatternColorFormat; public uint SetMonochromePatternColorFormat;
public SetMonochromePatternColorFormatV SetMonochromePatternColorFormatV => (SetMonochromePatternColorFormatV)((SetMonochromePatternColorFormat >> 0) & 0x7); public SetMonochromePatternColorFormatV SetMonochromePatternColorFormatV => (SetMonochromePatternColorFormatV)(SetMonochromePatternColorFormat & 0x7);
public uint SetMonochromePatternFormat; public uint SetMonochromePatternFormat;
public SetMonochromePatternFormatV SetMonochromePatternFormatV => (SetMonochromePatternFormatV)((SetMonochromePatternFormat >> 0) & 0x1); public SetMonochromePatternFormatV SetMonochromePatternFormatV => (SetMonochromePatternFormatV)(SetMonochromePatternFormat & 0x1);
public uint SetMonochromePatternColor0; public uint SetMonochromePatternColor0;
public uint SetMonochromePatternColor1; public uint SetMonochromePatternColor1;
public uint SetMonochromePattern0; public uint SetMonochromePattern0;
@@ -662,26 +662,26 @@ namespace Ryujinx.Graphics.Gpu.Engine.Twod
public uint SetRenderSolidPrimColor2; public uint SetRenderSolidPrimColor2;
public uint SetRenderSolidPrimColor3; public uint SetRenderSolidPrimColor3;
public uint SetMmeMemAddressA; public uint SetMmeMemAddressA;
public int SetMmeMemAddressAUpper => (int)((SetMmeMemAddressA >> 0) & 0x1FFFFFF); public int SetMmeMemAddressAUpper => (int)(SetMmeMemAddressA & 0x1FFFFFF);
public uint SetMmeMemAddressB; public uint SetMmeMemAddressB;
public uint SetMmeDataRamAddress; public uint SetMmeDataRamAddress;
public uint MmeDmaRead; public uint MmeDmaRead;
public uint MmeDmaReadFifoed; public uint MmeDmaReadFifoed;
public uint MmeDmaWrite; public uint MmeDmaWrite;
public uint MmeDmaReduction; public uint MmeDmaReduction;
public MmeDmaReductionReductionOp MmeDmaReductionReductionOp => (MmeDmaReductionReductionOp)((MmeDmaReduction >> 0) & 0x7); public MmeDmaReductionReductionOp MmeDmaReductionReductionOp => (MmeDmaReductionReductionOp)(MmeDmaReduction & 0x7);
public MmeDmaReductionReductionFormat MmeDmaReductionReductionFormat => (MmeDmaReductionReductionFormat)((MmeDmaReduction >> 4) & 0x3); public MmeDmaReductionReductionFormat MmeDmaReductionReductionFormat => (MmeDmaReductionReductionFormat)((MmeDmaReduction >> 4) & 0x3);
public MmeDmaReductionReductionSize MmeDmaReductionReductionSize => (MmeDmaReductionReductionSize)((MmeDmaReduction >> 8) & 0x1); public MmeDmaReductionReductionSize MmeDmaReductionReductionSize => (MmeDmaReductionReductionSize)((MmeDmaReduction >> 8) & 0x1);
public uint MmeDmaSysmembar; public uint MmeDmaSysmembar;
public bool MmeDmaSysmembarV => (MmeDmaSysmembar & 0x1) != 0; public bool MmeDmaSysmembarV => (MmeDmaSysmembar & 0x1) != 0;
public uint MmeDmaSync; public uint MmeDmaSync;
public uint SetMmeDataFifoConfig; public uint SetMmeDataFifoConfig;
public SetMmeDataFifoConfigFifoSize SetMmeDataFifoConfigFifoSize => (SetMmeDataFifoConfigFifoSize)((SetMmeDataFifoConfig >> 0) & 0x7); public SetMmeDataFifoConfigFifoSize SetMmeDataFifoConfigFifoSize => (SetMmeDataFifoConfigFifoSize)(SetMmeDataFifoConfig & 0x7);
public fixed uint Reserved578[2]; public fixed uint Reserved578[2];
public uint RenderSolidPrimMode; public uint RenderSolidPrimMode;
public RenderSolidPrimModeV RenderSolidPrimModeV => (RenderSolidPrimModeV)((RenderSolidPrimMode >> 0) & 0x7); public RenderSolidPrimModeV RenderSolidPrimModeV => (RenderSolidPrimModeV)(RenderSolidPrimMode & 0x7);
public uint SetRenderSolidPrimColorFormat; public uint SetRenderSolidPrimColorFormat;
public SetRenderSolidPrimColorFormatV SetRenderSolidPrimColorFormatV => (SetRenderSolidPrimColorFormatV)((SetRenderSolidPrimColorFormat >> 0) & 0xFF); public SetRenderSolidPrimColorFormatV SetRenderSolidPrimColorFormatV => (SetRenderSolidPrimColorFormatV)(SetRenderSolidPrimColorFormat & 0xFF);
public uint SetRenderSolidPrimColor; public uint SetRenderSolidPrimColor;
public uint SetRenderSolidLineTieBreakBits; public uint SetRenderSolidLineTieBreakBits;
public bool SetRenderSolidLineTieBreakBitsXmajXincYinc => (SetRenderSolidLineTieBreakBits & 0x1) != 0; public bool SetRenderSolidLineTieBreakBitsXmajXincYinc => (SetRenderSolidLineTieBreakBits & 0x1) != 0;
@@ -690,24 +690,24 @@ namespace Ryujinx.Graphics.Gpu.Engine.Twod
public bool SetRenderSolidLineTieBreakBitsYmajXdecYinc => (SetRenderSolidLineTieBreakBits & 0x1000) != 0; public bool SetRenderSolidLineTieBreakBitsYmajXdecYinc => (SetRenderSolidLineTieBreakBits & 0x1000) != 0;
public fixed uint Reserved590[20]; public fixed uint Reserved590[20];
public uint RenderSolidPrimPointXY; public uint RenderSolidPrimPointXY;
public int RenderSolidPrimPointXYX => (int)((RenderSolidPrimPointXY >> 0) & 0xFFFF); public int RenderSolidPrimPointXYX => (int)(RenderSolidPrimPointXY & 0xFFFF);
public int RenderSolidPrimPointXYY => (int)((RenderSolidPrimPointXY >> 16) & 0xFFFF); public int RenderSolidPrimPointXYY => (int)((RenderSolidPrimPointXY >> 16) & 0xFFFF);
public fixed uint Reserved5E4[7]; public fixed uint Reserved5E4[7];
public Array64<RenderSolidPrimPoint> RenderSolidPrimPoint; public Array64<RenderSolidPrimPoint> RenderSolidPrimPoint;
public uint SetPixelsFromCpuDataType; public uint SetPixelsFromCpuDataType;
public SetPixelsFromCpuDataTypeV SetPixelsFromCpuDataTypeV => (SetPixelsFromCpuDataTypeV)((SetPixelsFromCpuDataType >> 0) & 0x1); public SetPixelsFromCpuDataTypeV SetPixelsFromCpuDataTypeV => (SetPixelsFromCpuDataTypeV)(SetPixelsFromCpuDataType & 0x1);
public uint SetPixelsFromCpuColorFormat; public uint SetPixelsFromCpuColorFormat;
public SetPixelsFromCpuColorFormatV SetPixelsFromCpuColorFormatV => (SetPixelsFromCpuColorFormatV)((SetPixelsFromCpuColorFormat >> 0) & 0xFF); public SetPixelsFromCpuColorFormatV SetPixelsFromCpuColorFormatV => (SetPixelsFromCpuColorFormatV)(SetPixelsFromCpuColorFormat & 0xFF);
public uint SetPixelsFromCpuIndexFormat; public uint SetPixelsFromCpuIndexFormat;
public SetPixelsFromCpuIndexFormatV SetPixelsFromCpuIndexFormatV => (SetPixelsFromCpuIndexFormatV)((SetPixelsFromCpuIndexFormat >> 0) & 0x3); public SetPixelsFromCpuIndexFormatV SetPixelsFromCpuIndexFormatV => (SetPixelsFromCpuIndexFormatV)(SetPixelsFromCpuIndexFormat & 0x3);
public uint SetPixelsFromCpuMonoFormat; public uint SetPixelsFromCpuMonoFormat;
public SetPixelsFromCpuMonoFormatV SetPixelsFromCpuMonoFormatV => (SetPixelsFromCpuMonoFormatV)((SetPixelsFromCpuMonoFormat >> 0) & 0x1); public SetPixelsFromCpuMonoFormatV SetPixelsFromCpuMonoFormatV => (SetPixelsFromCpuMonoFormatV)(SetPixelsFromCpuMonoFormat & 0x1);
public uint SetPixelsFromCpuWrap; public uint SetPixelsFromCpuWrap;
public SetPixelsFromCpuWrapV SetPixelsFromCpuWrapV => (SetPixelsFromCpuWrapV)((SetPixelsFromCpuWrap >> 0) & 0x3); public SetPixelsFromCpuWrapV SetPixelsFromCpuWrapV => (SetPixelsFromCpuWrapV)(SetPixelsFromCpuWrap & 0x3);
public uint SetPixelsFromCpuColor0; public uint SetPixelsFromCpuColor0;
public uint SetPixelsFromCpuColor1; public uint SetPixelsFromCpuColor1;
public uint SetPixelsFromCpuMonoOpacity; public uint SetPixelsFromCpuMonoOpacity;
public SetPixelsFromCpuMonoOpacityV SetPixelsFromCpuMonoOpacityV => (SetPixelsFromCpuMonoOpacityV)((SetPixelsFromCpuMonoOpacity >> 0) & 0x1); public SetPixelsFromCpuMonoOpacityV SetPixelsFromCpuMonoOpacityV => (SetPixelsFromCpuMonoOpacityV)(SetPixelsFromCpuMonoOpacity & 0x1);
public fixed uint Reserved820[6]; public fixed uint Reserved820[6];
public uint SetPixelsFromCpuSrcWidth; public uint SetPixelsFromCpuSrcWidth;
public uint SetPixelsFromCpuSrcHeight; public uint SetPixelsFromCpuSrcHeight;
@@ -753,13 +753,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.Twod
public bool SetBigEndianControlOverride => (SetBigEndianControl & 0x10000000) != 0; public bool SetBigEndianControlOverride => (SetBigEndianControl & 0x10000000) != 0;
public fixed uint Reserved874[3]; public fixed uint Reserved874[3];
public uint SetPixelsFromMemoryBlockShape; public uint SetPixelsFromMemoryBlockShape;
public SetPixelsFromMemoryBlockShapeV SetPixelsFromMemoryBlockShapeV => (SetPixelsFromMemoryBlockShapeV)((SetPixelsFromMemoryBlockShape >> 0) & 0x7); public SetPixelsFromMemoryBlockShapeV SetPixelsFromMemoryBlockShapeV => (SetPixelsFromMemoryBlockShapeV)(SetPixelsFromMemoryBlockShape & 0x7);
public uint SetPixelsFromMemoryCorralSize; public uint SetPixelsFromMemoryCorralSize;
public int SetPixelsFromMemoryCorralSizeV => (int)((SetPixelsFromMemoryCorralSize >> 0) & 0x3FF); public int SetPixelsFromMemoryCorralSizeV => (int)(SetPixelsFromMemoryCorralSize & 0x3FF);
public uint SetPixelsFromMemorySafeOverlap; public uint SetPixelsFromMemorySafeOverlap;
public bool SetPixelsFromMemorySafeOverlapV => (SetPixelsFromMemorySafeOverlap & 0x1) != 0; public bool SetPixelsFromMemorySafeOverlapV => (SetPixelsFromMemorySafeOverlap & 0x1) != 0;
public uint SetPixelsFromMemorySampleMode; public uint SetPixelsFromMemorySampleMode;
public SetPixelsFromMemorySampleModeOrigin SetPixelsFromMemorySampleModeOrigin => (SetPixelsFromMemorySampleModeOrigin)((SetPixelsFromMemorySampleMode >> 0) & 0x1); public SetPixelsFromMemorySampleModeOrigin SetPixelsFromMemorySampleModeOrigin => (SetPixelsFromMemorySampleModeOrigin)(SetPixelsFromMemorySampleMode & 0x1);
public SetPixelsFromMemorySampleModeFilter SetPixelsFromMemorySampleModeFilter => (SetPixelsFromMemorySampleModeFilter)((SetPixelsFromMemorySampleMode >> 4) & 0x1); public SetPixelsFromMemorySampleModeFilter SetPixelsFromMemorySampleModeFilter => (SetPixelsFromMemorySampleModeFilter)((SetPixelsFromMemorySampleMode >> 4) & 0x1);
public fixed uint Reserved890[8]; public fixed uint Reserved890[8];
public uint SetPixelsFromMemoryDstX0; public uint SetPixelsFromMemoryDstX0;

View File

@@ -6,6 +6,7 @@ using Ryujinx.Graphics.Shader;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Ryujinx.Graphics.Gpu.Memory namespace Ryujinx.Graphics.Gpu.Memory
{ {
@@ -14,12 +15,17 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// </summary> /// </summary>
class BufferManager class BufferManager
{ {
private const int TfInfoVertexCountOffset = Constants.TotalTransformFeedbackBuffers * sizeof(int);
private const int TfInfoBufferSize = TfInfoVertexCountOffset + sizeof(int);
private readonly GpuContext _context; private readonly GpuContext _context;
private readonly GpuChannel _channel; private readonly GpuChannel _channel;
private int _unalignedStorageBuffers; private int _unalignedStorageBuffers;
public bool HasUnalignedStorageBuffers => _unalignedStorageBuffers > 0; public bool HasUnalignedStorageBuffers => _unalignedStorageBuffers > 0;
public bool HasTransformFeedbackOutputs { get; set; }
private IndexBuffer _indexBuffer; private IndexBuffer _indexBuffer;
private readonly VertexBuffer[] _vertexBuffers; private readonly VertexBuffer[] _vertexBuffers;
private readonly BufferBounds[] _transformFeedbackBuffers; private readonly BufferBounds[] _transformFeedbackBuffers;
@@ -98,6 +104,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
private readonly BuffersPerStage[] _gpStorageBuffers; private readonly BuffersPerStage[] _gpStorageBuffers;
private readonly BuffersPerStage[] _gpUniformBuffers; private readonly BuffersPerStage[] _gpUniformBuffers;
private BufferHandle _tfInfoBuffer;
private int[] _tfInfoData;
private bool _gpStorageBuffersDirty; private bool _gpStorageBuffersDirty;
private bool _gpUniformBuffersDirty; private bool _gpUniformBuffersDirty;
@@ -137,6 +146,11 @@ namespace Ryujinx.Graphics.Gpu.Memory
_bufferTextures = new List<BufferTextureBinding>(); _bufferTextures = new List<BufferTextureBinding>();
_ranges = new BufferAssignment[Constants.TotalGpUniformBuffers * Constants.ShaderStages]; _ranges = new BufferAssignment[Constants.TotalGpUniformBuffers * Constants.ShaderStages];
if (!context.Capabilities.SupportsTransformFeedback)
{
_tfInfoData = new int[Constants.TotalTransformFeedbackBuffers];
}
} }
@@ -319,6 +333,31 @@ namespace Ryujinx.Graphics.Gpu.Memory
_gpUniformBuffersDirty = true; _gpUniformBuffersDirty = true;
} }
/// <summary>
/// Sets the number of vertices per instance on a instanced draw. Used for transform feedback emulation.
/// </summary>
/// <param name="vertexCount">Vertex count per instance</param>
public void SetInstancedDrawVertexCount(int vertexCount)
{
if (!_context.Capabilities.SupportsTransformFeedback &&
HasTransformFeedbackOutputs &&
_tfInfoBuffer != BufferHandle.Null)
{
Span<byte> data = stackalloc byte[sizeof(int)];
MemoryMarshal.Cast<byte, int>(data)[0] = vertexCount;
_context.Renderer.SetBufferData(_tfInfoBuffer, TfInfoVertexCountOffset, data);
}
}
/// <summary>
/// Forces transform feedback and storage buffers to be updated on the next draw.
/// </summary>
public void ForceTransformFeedbackAndStorageBuffersDirty()
{
_transformFeedbackBuffersDirty = true;
_gpStorageBuffersDirty = true;
}
/// <summary> /// <summary>
/// Sets the binding points for the storage buffers bound on the compute pipeline. /// Sets the binding points for the storage buffers bound on the compute pipeline.
/// </summary> /// </summary>
@@ -537,22 +576,75 @@ namespace Ryujinx.Graphics.Gpu.Memory
{ {
_transformFeedbackBuffersDirty = false; _transformFeedbackBuffersDirty = false;
Span<BufferRange> tfbs = stackalloc BufferRange[Constants.TotalTransformFeedbackBuffers]; if (_context.Capabilities.SupportsTransformFeedback)
for (int index = 0; index < Constants.TotalTransformFeedbackBuffers; index++)
{ {
BufferBounds tfb = _transformFeedbackBuffers[index]; Span<BufferRange> tfbs = stackalloc BufferRange[Constants.TotalTransformFeedbackBuffers];
if (tfb.Address == 0) for (int index = 0; index < Constants.TotalTransformFeedbackBuffers; index++)
{ {
tfbs[index] = BufferRange.Empty; BufferBounds tfb = _transformFeedbackBuffers[index];
continue;
if (tfb.Address == 0)
{
tfbs[index] = BufferRange.Empty;
continue;
}
tfbs[index] = bufferCache.GetBufferRange(tfb.Address, tfb.Size, write: true);
} }
tfbs[index] = bufferCache.GetBufferRange(tfb.Address, tfb.Size, write: true); _context.Renderer.Pipeline.SetTransformFeedbackBuffers(tfbs);
} }
else if (HasTransformFeedbackOutputs)
{
Span<int> info = _tfInfoData.AsSpan();
Span<BufferAssignment> buffers = stackalloc BufferAssignment[Constants.TotalTransformFeedbackBuffers + 1];
_context.Renderer.Pipeline.SetTransformFeedbackBuffers(tfbs); bool needsDataUpdate = false;
if (_tfInfoBuffer == BufferHandle.Null)
{
_tfInfoBuffer = _context.Renderer.CreateBuffer(TfInfoBufferSize);
}
buffers[0] = new BufferAssignment(0, new BufferRange(_tfInfoBuffer, 0, TfInfoBufferSize));
int alignment = _context.Capabilities.StorageBufferOffsetAlignment;
for (int index = 0; index < Constants.TotalTransformFeedbackBuffers; index++)
{
BufferBounds tfb = _transformFeedbackBuffers[index];
if (tfb.Address == 0)
{
buffers[1 + index] = new BufferAssignment(1 + index, BufferRange.Empty);
}
else
{
ulong endAddress = tfb.Address + tfb.Size;
ulong address = BitUtils.AlignDown(tfb.Address, (ulong)alignment);
ulong size = endAddress - address;
int tfeOffset = ((int)tfb.Address & (alignment - 1)) / 4;
if (info[index] != tfeOffset)
{
info[index] = tfeOffset;
needsDataUpdate = true;
}
buffers[1 + index] = new BufferAssignment(1 + index, bufferCache.GetBufferRange(address, size, write: true));
}
}
if (needsDataUpdate)
{
Span<byte> infoData = MemoryMarshal.Cast<int, byte>(info);
_context.Renderer.SetBufferData(_tfInfoBuffer, 0, infoData);
}
_context.Renderer.Pipeline.SetStorageBuffers(buffers);
}
} }
else else
{ {

View File

@@ -37,7 +37,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
ShaderSpecializationState oldSpecState, ShaderSpecializationState oldSpecState,
ShaderSpecializationState newSpecState, ShaderSpecializationState newSpecState,
ResourceCounts counts, ResourceCounts counts,
int stageIndex) : base(context, counts, stageIndex) int stageIndex) : base(context, counts, stageIndex, oldSpecState.TransformFeedbackDescriptors != null)
{ {
_data = data; _data = data;
_cb1Data = cb1Data; _cb1Data = cb1Data;

View File

@@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
private const ushort FileFormatVersionMajor = 1; private const ushort FileFormatVersionMajor = 1;
private const ushort FileFormatVersionMinor = 2; private const ushort FileFormatVersionMinor = 2;
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor; private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
private const uint CodeGenVersion = 5044; private const uint CodeGenVersion = 5080;
private const string SharedTocFileName = "shared.toc"; private const string SharedTocFileName = "shared.toc";
private const string SharedDataFileName = "shared.data"; private const string SharedDataFileName = "shared.data";
@@ -368,7 +368,11 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
if (hostCode != null) if (hostCode != null)
{ {
ShaderInfo shaderInfo = ShaderInfoBuilder.BuildForCache(context, shaders, specState.PipelineState); ShaderInfo shaderInfo = ShaderInfoBuilder.BuildForCache(
context,
shaders,
specState.PipelineState,
specState.TransformFeedbackDescriptors != null);
IProgram hostProgram; IProgram hostProgram;

View File

@@ -491,7 +491,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
{ {
ShaderSource[] shaderSources = new ShaderSource[compilation.TranslatedStages.Length]; ShaderSource[] shaderSources = new ShaderSource[compilation.TranslatedStages.Length];
ShaderInfoBuilder shaderInfoBuilder = new ShaderInfoBuilder(_context); ShaderInfoBuilder shaderInfoBuilder = new ShaderInfoBuilder(_context, compilation.SpecializationState.TransformFeedbackDescriptors != null);
for (int index = 0; index < compilation.TranslatedStages.Length; index++) for (int index = 0; index < compilation.TranslatedStages.Length; index++)
{ {

View File

@@ -30,7 +30,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
GpuContext context, GpuContext context,
GpuChannel channel, GpuChannel channel,
GpuAccessorState state, GpuAccessorState state,
int stageIndex) : base(context, state.ResourceCounts, stageIndex) int stageIndex) : base(context, state.ResourceCounts, stageIndex, state.TransformFeedbackDescriptors != null)
{ {
_isVulkan = context.Capabilities.Api == TargetApi.Vulkan; _isVulkan = context.Capabilities.Api == TargetApi.Vulkan;
_channel = channel; _channel = channel;
@@ -44,7 +44,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// <param name="context">GPU context</param> /// <param name="context">GPU context</param>
/// <param name="channel">GPU channel</param> /// <param name="channel">GPU channel</param>
/// <param name="state">Current GPU state</param> /// <param name="state">Current GPU state</param>
public GpuAccessor(GpuContext context, GpuChannel channel, GpuAccessorState state) : base(context, state.ResourceCounts, 0) public GpuAccessor(GpuContext context, GpuChannel channel, GpuAccessorState state) : base(context, state.ResourceCounts, 0, false)
{ {
_channel = channel; _channel = channel;
_state = state; _state = state;

View File

@@ -17,40 +17,56 @@ namespace Ryujinx.Graphics.Gpu.Shader
private readonly ResourceCounts _resourceCounts; private readonly ResourceCounts _resourceCounts;
private readonly int _stageIndex; private readonly int _stageIndex;
private readonly int _reservedConstantBuffers;
private readonly int _reservedStorageBuffers;
/// <summary> /// <summary>
/// Creates a new GPU accessor. /// Creates a new GPU accessor.
/// </summary> /// </summary>
/// <param name="context">GPU context</param> /// <param name="context">GPU context</param>
public GpuAccessorBase(GpuContext context, ResourceCounts resourceCounts, int stageIndex) /// <param name="resourceCounts">Counter of GPU resources used by the shader</param>
/// <param name="stageIndex">Index of the shader stage, 0 for compute</param>
/// <param name="tfEnabled">Indicates if the current graphics shader is used with transform feedback enabled</param>
public GpuAccessorBase(GpuContext context, ResourceCounts resourceCounts, int stageIndex, bool tfEnabled)
{ {
_context = context; _context = context;
_resourceCounts = resourceCounts; _resourceCounts = resourceCounts;
_stageIndex = stageIndex; _stageIndex = stageIndex;
_reservedConstantBuffers = 1; // For the support buffer.
_reservedStorageBuffers = !context.Capabilities.SupportsTransformFeedback && tfEnabled ? 5 : 0;
} }
public int QueryBindingConstantBuffer(int index) public int QueryBindingConstantBuffer(int index)
{ {
int binding;
if (_context.Capabilities.Api == TargetApi.Vulkan) if (_context.Capabilities.Api == TargetApi.Vulkan)
{ {
// We need to start counting from 1 since binding 0 is reserved for the support uniform buffer. binding = GetBindingFromIndex(index, _context.Capabilities.MaximumUniformBuffersPerStage, "Uniform buffer");
return GetBindingFromIndex(index, _context.Capabilities.MaximumUniformBuffersPerStage, "Uniform buffer") + 1;
} }
else else
{ {
return _resourceCounts.UniformBuffersCount++; binding = _resourceCounts.UniformBuffersCount++;
} }
return binding + _reservedConstantBuffers;
} }
public int QueryBindingStorageBuffer(int index) public int QueryBindingStorageBuffer(int index)
{ {
int binding;
if (_context.Capabilities.Api == TargetApi.Vulkan) if (_context.Capabilities.Api == TargetApi.Vulkan)
{ {
return GetBindingFromIndex(index, _context.Capabilities.MaximumStorageBuffersPerStage, "Storage buffer"); binding = GetBindingFromIndex(index, _context.Capabilities.MaximumStorageBuffersPerStage, "Storage buffer");
} }
else else
{ {
return _resourceCounts.StorageBuffersCount++; binding = _resourceCounts.StorageBuffersCount++;
} }
return binding + _reservedStorageBuffers;
} }
public int QueryBindingTexture(int index, bool isBuffer) public int QueryBindingTexture(int index, bool isBuffer)
@@ -149,6 +165,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
public bool QueryHostSupportsTextureShadowLod() => _context.Capabilities.SupportsTextureShadowLod; public bool QueryHostSupportsTextureShadowLod() => _context.Capabilities.SupportsTextureShadowLod;
public bool QueryHostSupportsTransformFeedback() => _context.Capabilities.SupportsTransformFeedback;
public bool QueryHostSupportsViewportIndexVertexTessellation() => _context.Capabilities.SupportsViewportIndexVertexTessellation; public bool QueryHostSupportsViewportIndexVertexTessellation() => _context.Capabilities.SupportsViewportIndexVertexTessellation;
public bool QueryHostSupportsViewportMask() => _context.Capabilities.SupportsViewportMask; public bool QueryHostSupportsViewportMask() => _context.Capabilities.SupportsViewportMask;

View File

@@ -24,13 +24,5 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// Total of images used by the shaders. /// Total of images used by the shaders.
/// </summary> /// </summary>
public int ImagesCount; public int ImagesCount;
/// <summary>
/// Creates a new instance of the shader resource counts class.
/// </summary>
public ResourceCounts()
{
UniformBuffersCount = 1; // The first binding is reserved for the support buffer.
}
} }
} }

View File

@@ -362,7 +362,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
TranslatorContext previousStage = null; TranslatorContext previousStage = null;
ShaderInfoBuilder infoBuilder = new ShaderInfoBuilder(_context); ShaderInfoBuilder infoBuilder = new ShaderInfoBuilder(_context, transformFeedbackDescriptors != null);
for (int stageIndex = 0; stageIndex < Constants.ShaderStages; stageIndex++) for (int stageIndex = 0; stageIndex < Constants.ShaderStages; stageIndex++)
{ {

View File

@@ -16,15 +16,24 @@ namespace Ryujinx.Graphics.Gpu.Shader
private const int TextureSetIndex = 2; private const int TextureSetIndex = 2;
private const int ImageSetIndex = 3; private const int ImageSetIndex = 3;
private const ResourceStages SupportBufferStags = private const ResourceStages SupportBufferStages =
ResourceStages.Compute | ResourceStages.Compute |
ResourceStages.Vertex | ResourceStages.Vertex |
ResourceStages.Fragment; ResourceStages.Fragment;
private const ResourceStages VtgStages =
ResourceStages.Vertex |
ResourceStages.TessellationControl |
ResourceStages.TessellationEvaluation |
ResourceStages.Geometry;
private readonly GpuContext _context; private readonly GpuContext _context;
private int _fragmentOutputMap; private int _fragmentOutputMap;
private readonly int _reservedConstantBuffers;
private readonly int _reservedStorageBuffers;
private readonly List<ResourceDescriptor>[] _resourceDescriptors; private readonly List<ResourceDescriptor>[] _resourceDescriptors;
private readonly List<ResourceUsage>[] _resourceUsages; private readonly List<ResourceUsage>[] _resourceUsages;
@@ -32,7 +41,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// Creates a new shader info builder. /// Creates a new shader info builder.
/// </summary> /// </summary>
/// <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>
public ShaderInfoBuilder(GpuContext context) /// <param name="tfEnabled">Indicates if the graphics shader is used with transform feedback enabled</param>
public ShaderInfoBuilder(GpuContext context, bool tfEnabled)
{ {
_context = context; _context = context;
@@ -47,7 +57,22 @@ namespace Ryujinx.Graphics.Gpu.Shader
_resourceUsages[index] = new(); _resourceUsages[index] = new();
} }
AddDescriptor(SupportBufferStags, ResourceType.UniformBuffer, UniformSetIndex, 0, 1); AddDescriptor(SupportBufferStages, ResourceType.UniformBuffer, UniformSetIndex, 0, 1);
_reservedConstantBuffers = 1; // For the support buffer.
if (!context.Capabilities.SupportsTransformFeedback && tfEnabled)
{
_reservedStorageBuffers = 5;
AddDescriptor(VtgStages, ResourceType.StorageBuffer, StorageSetIndex, 0, 5);
AddUsage(VtgStages, ResourceType.StorageBuffer, ResourceAccess.Read, StorageSetIndex, 0, 1);
AddUsage(VtgStages, ResourceType.StorageBuffer, ResourceAccess.Write, StorageSetIndex, 1, 4);
}
else
{
_reservedStorageBuffers = 0;
}
} }
/// <summary> /// <summary>
@@ -86,8 +111,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
int texturesPerStage = (int)_context.Capabilities.MaximumTexturesPerStage; int texturesPerStage = (int)_context.Capabilities.MaximumTexturesPerStage;
int imagesPerStage = (int)_context.Capabilities.MaximumImagesPerStage; int imagesPerStage = (int)_context.Capabilities.MaximumImagesPerStage;
int uniformBinding = 1 + stageIndex * uniformsPerStage; int uniformBinding = _reservedConstantBuffers + stageIndex * uniformsPerStage;
int storageBinding = stageIndex * storagesPerStage; int storageBinding = _reservedStorageBuffers + stageIndex * storagesPerStage;
int textureBinding = stageIndex * texturesPerStage * 2; int textureBinding = stageIndex * texturesPerStage * 2;
int imageBinding = stageIndex * imagesPerStage * 2; int imageBinding = stageIndex * imagesPerStage * 2;
@@ -133,6 +158,23 @@ namespace Ryujinx.Graphics.Gpu.Shader
AddDescriptor(stages, type2, setIndex, binding + count, count); AddDescriptor(stages, type2, setIndex, binding + count, count);
} }
/// <summary>
/// Adds buffer usage information to the list of usages.
/// </summary>
/// <param name="stages">Shader stages where the resource is used</param>
/// <param name="type">Type of the resource</param>
/// <param name="access">How the resource is accessed by the shader stages where it is used</param>
/// <param name="setIndex">Descriptor set number where the resource will be bound</param>
/// <param name="binding">Binding number where the resource will be bound</param>
/// <param name="count">Number of resources bound at the binding location</param>
private void AddUsage(ResourceStages stages, ResourceType type, ResourceAccess access, int setIndex, int binding, int count)
{
for (int index = 0; index < count; index++)
{
_resourceUsages[setIndex].Add(new ResourceUsage(binding + index, type, stages, access));
}
}
/// <summary> /// <summary>
/// Adds buffer usage information to the list of usages. /// Adds buffer usage information to the list of usages.
/// </summary> /// </summary>
@@ -212,10 +254,15 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// <param name="context">GPU context that owns the shaders</param> /// <param name="context">GPU context that owns the shaders</param>
/// <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>
/// <returns>Shader information</returns> /// <returns>Shader information</returns>
public static ShaderInfo BuildForCache(GpuContext context, IEnumerable<CachedShaderStage> programs, ProgramPipelineState? pipeline) public static ShaderInfo BuildForCache(
GpuContext context,
IEnumerable<CachedShaderStage> programs,
ProgramPipelineState? pipeline,
bool tfEnabled)
{ {
ShaderInfoBuilder builder = new ShaderInfoBuilder(context); ShaderInfoBuilder builder = new ShaderInfoBuilder(context, tfEnabled);
foreach (CachedShaderStage program in programs) foreach (CachedShaderStage program in programs)
{ {
@@ -237,7 +284,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// <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, bool fromCache = false)
{ {
ShaderInfoBuilder builder = new ShaderInfoBuilder(context); ShaderInfoBuilder builder = new ShaderInfoBuilder(context, tfEnabled: false);
builder.AddStageInfo(info); builder.AddStageInfo(info);

View File

@@ -153,6 +153,7 @@ namespace Ryujinx.Graphics.OpenGL
supportsFragmentShaderOrderingIntel: HwCapabilities.SupportsFragmentShaderOrdering, supportsFragmentShaderOrderingIntel: HwCapabilities.SupportsFragmentShaderOrdering,
supportsGeometryShader: true, supportsGeometryShader: true,
supportsGeometryShaderPassthrough: HwCapabilities.SupportsGeometryShaderPassthrough, supportsGeometryShaderPassthrough: HwCapabilities.SupportsGeometryShaderPassthrough,
supportsTransformFeedback: true,
supportsImageLoadFormatted: HwCapabilities.SupportsImageLoadFormatted, supportsImageLoadFormatted: HwCapabilities.SupportsImageLoadFormatted,
supportsLayerVertexTessellation: HwCapabilities.SupportsShaderViewportLayerArray, supportsLayerVertexTessellation: HwCapabilities.SupportsShaderViewportLayerArray,
supportsMismatchingViewFormat: HwCapabilities.SupportsMismatchingViewFormat, supportsMismatchingViewFormat: HwCapabilities.SupportsMismatchingViewFormat,

View File

@@ -10,5 +10,11 @@ namespace Ryujinx.Graphics.Shader
public const int NvnBaseVertexByteOffset = 0x640; public const int NvnBaseVertexByteOffset = 0x640;
public const int NvnBaseInstanceByteOffset = 0x644; public const int NvnBaseInstanceByteOffset = 0x644;
public const int NvnDrawIndexByteOffset = 0x648; public const int NvnDrawIndexByteOffset = 0x648;
// Transform Feedback emulation.
public const int TfeInfoBinding = 0;
public const int TfeBufferBaseBinding = 1;
public const int TfeBuffersCount = 4;
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,8 @@
using System;
namespace Ryujinx.Graphics.Shader.Decoders namespace Ryujinx.Graphics.Shader.Decoders
{ {
[Flags]
enum InstProps : ushort enum InstProps : ushort
{ {
None = 0, None = 0,

View File

@@ -367,6 +367,15 @@ namespace Ryujinx.Graphics.Shader
return true; return true;
} }
/// <summary>
/// Queries host GPU transform feedback support.
/// </summary>
/// <returns>True if the GPU and driver supports transform feedback, false otherwise</returns>
bool QueryHostSupportsTransformFeedback()
{
return true;
}
/// <summary> /// <summary>
/// Queries host support for writes to the viewport index from vertex or tessellation shader stages. /// Queries host support for writes to the viewport index from vertex or tessellation shader stages.
/// </summary> /// </summary>

View File

@@ -61,7 +61,7 @@ namespace Ryujinx.Graphics.Shader
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int UnpackTextureId(int packedId) public static int UnpackTextureId(int packedId)
{ {
return (packedId >> 0) & 0xfffff; return packedId & 0xfffff;
} }
/// <summary> /// <summary>

View File

@@ -1,5 +1,8 @@
namespace Ryujinx.Graphics.Shader.Translation using System;
namespace Ryujinx.Graphics.Shader.Translation
{ {
[Flags]
enum AggregateType enum AggregateType
{ {
Invalid, Invalid,

View File

@@ -234,6 +234,45 @@ namespace Ryujinx.Graphics.Shader.Translation
public void PrepareForVertexReturn() public void PrepareForVertexReturn()
{ {
if (!Config.GpuAccessor.QueryHostSupportsTransformFeedback() && Config.GpuAccessor.QueryTransformFeedbackEnabled())
{
Operand vertexCount = this.Load(StorageKind.StorageBuffer, Constants.TfeInfoBinding, Const(1));
for (int tfbIndex = 0; tfbIndex < Constants.TfeBuffersCount; tfbIndex++)
{
var locations = Config.GpuAccessor.QueryTransformFeedbackVaryingLocations(tfbIndex);
var stride = Config.GpuAccessor.QueryTransformFeedbackStride(tfbIndex);
Operand baseOffset = this.Load(StorageKind.StorageBuffer, Constants.TfeInfoBinding, Const(0), Const(tfbIndex));
Operand baseVertex = this.Load(StorageKind.Input, IoVariable.BaseVertex);
Operand baseInstance = this.Load(StorageKind.Input, IoVariable.BaseInstance);
Operand vertexIndex = this.Load(StorageKind.Input, IoVariable.VertexIndex);
Operand instanceIndex = this.Load(StorageKind.Input, IoVariable.InstanceIndex);
Operand outputVertexOffset = this.ISubtract(vertexIndex, baseVertex);
Operand outputInstanceOffset = this.ISubtract(instanceIndex, baseInstance);
Operand outputBaseVertex = this.IMultiply(outputInstanceOffset, vertexCount);
Operand vertexOffset = this.IMultiply(this.IAdd(outputBaseVertex, outputVertexOffset), Const(stride / 4));
baseOffset = this.IAdd(baseOffset, vertexOffset);
for (int j = 0; j < locations.Length; j++)
{
byte location = locations[j];
if (location == 0xff)
{
continue;
}
Operand offset = this.IAdd(baseOffset, Const(j));
Operand value = Instructions.AttributeMap.GenerateAttributeLoad(this, null, location * 4, isOutput: true, isPerPatch: false);
this.Store(StorageKind.StorageBuffer, Constants.TfeBufferBaseBinding + tfbIndex, Const(0), offset, value);
}
}
}
if (Config.GpuAccessor.QueryViewportTransformDisable()) if (Config.GpuAccessor.QueryViewportTransformDisable())
{ {
Operand x = this.Load(StorageKind.Output, IoVariable.Position, null, Const(0)); Operand x = this.Load(StorageKind.Output, IoVariable.Position, null, Const(0));

View File

@@ -132,6 +132,11 @@ namespace Ryujinx.Graphics.Shader.Translation
_transformFeedbackDefinitions = new Dictionary<TransformFeedbackVariable, TransformFeedbackOutput>(); _transformFeedbackDefinitions = new Dictionary<TransformFeedbackVariable, TransformFeedbackOutput>();
TransformFeedbackEnabled =
stage != ShaderStage.Compute &&
gpuAccessor.QueryTransformFeedbackEnabled() &&
gpuAccessor.QueryHostSupportsTransformFeedback();
UsedInputAttributesPerPatch = new HashSet<int>(); UsedInputAttributesPerPatch = new HashSet<int>();
UsedOutputAttributesPerPatch = new HashSet<int>(); UsedOutputAttributesPerPatch = new HashSet<int>();
@@ -139,6 +144,31 @@ namespace Ryujinx.Graphics.Shader.Translation
_usedImages = new Dictionary<TextureInfo, TextureMeta>(); _usedImages = new Dictionary<TextureInfo, TextureMeta>();
ResourceManager = new ResourceManager(stage, gpuAccessor, new ShaderProperties()); ResourceManager = new ResourceManager(stage, gpuAccessor, new ShaderProperties());
if (!gpuAccessor.QueryHostSupportsTransformFeedback() && gpuAccessor.QueryTransformFeedbackEnabled())
{
StructureType tfeInfoStruct = new StructureType(new StructureField[]
{
new StructureField(AggregateType.Array | AggregateType.U32, "base_offset", 4),
new StructureField(AggregateType.U32, "vertex_count")
});
BufferDefinition tfeInfoBuffer = new BufferDefinition(BufferLayout.Std430, 1, Constants.TfeInfoBinding, "tfe_info", tfeInfoStruct);
Properties.AddStorageBuffer(Constants.TfeInfoBinding, tfeInfoBuffer);
StructureType tfeDataStruct = new StructureType(new StructureField[]
{
new StructureField(AggregateType.Array | AggregateType.U32, "data", 0)
});
for (int i = 0; i < Constants.TfeBuffersCount; i++)
{
int binding = Constants.TfeBufferBaseBinding + i;
BufferDefinition tfeDataBuffer = new BufferDefinition(BufferLayout.Std430, 1, binding, $"tfe_data{i}", tfeDataStruct);
Properties.AddStorageBuffer(binding, tfeDataBuffer);
}
}
} }
public ShaderConfig( public ShaderConfig(
@@ -151,7 +181,6 @@ namespace Ryujinx.Graphics.Shader.Translation
ThreadsPerInputPrimitive = 1; ThreadsPerInputPrimitive = 1;
OutputTopology = outputTopology; OutputTopology = outputTopology;
MaxOutputVertices = maxOutputVertices; MaxOutputVertices = maxOutputVertices;
TransformFeedbackEnabled = gpuAccessor.QueryTransformFeedbackEnabled();
} }
public ShaderConfig(ShaderHeader header, IGpuAccessor gpuAccessor, TranslationOptions options) : this(header.Stage, gpuAccessor, options) public ShaderConfig(ShaderHeader header, IGpuAccessor gpuAccessor, TranslationOptions options) : this(header.Stage, gpuAccessor, options)
@@ -165,7 +194,6 @@ namespace Ryujinx.Graphics.Shader.Translation
OmapTargets = header.OmapTargets; OmapTargets = header.OmapTargets;
OmapSampleMask = header.OmapSampleMask; OmapSampleMask = header.OmapSampleMask;
OmapDepth = header.OmapDepth; OmapDepth = header.OmapDepth;
TransformFeedbackEnabled = gpuAccessor.QueryTransformFeedbackEnabled();
LastInVertexPipeline = header.Stage < ShaderStage.Fragment; LastInVertexPipeline = header.Stage < ShaderStage.Fragment;
} }
@@ -726,7 +754,7 @@ namespace Ryujinx.Graphics.Shader.Translation
var descriptors = new TextureDescriptor[dict.Count]; var descriptors = new TextureDescriptor[dict.Count];
int i = 0; int i = 0;
foreach (var kv in dict.OrderBy(x => x.Key.Indexed).OrderBy(x => x.Key.Handle)) foreach (var kv in dict.OrderBy(x => x.Key.Indexed).ThenBy(x => x.Key.Handle))
{ {
var info = kv.Key; var info = kv.Key;
var meta = kv.Value; var meta = kv.Value;
@@ -824,4 +852,4 @@ namespace Ryujinx.Graphics.Shader.Translation
OmapTargets); OmapTargets);
} }
} }
} }

View File

@@ -16,9 +16,9 @@ namespace Ryujinx.Graphics.Vulkan
_descriptorSets = descriptorSets; _descriptorSets = descriptorSets;
} }
public void InitializeBuffers(int setIndex, int baseBinding, int countPerUnit, DescriptorType type, VkBuffer dummyBuffer) public void InitializeBuffers(int setIndex, int baseBinding, int count, DescriptorType type, VkBuffer dummyBuffer)
{ {
Span<DescriptorBufferInfo> infos = stackalloc DescriptorBufferInfo[countPerUnit]; Span<DescriptorBufferInfo> infos = stackalloc DescriptorBufferInfo[count];
infos.Fill(new DescriptorBufferInfo() infos.Fill(new DescriptorBufferInfo()
{ {

View File

@@ -596,36 +596,19 @@ namespace Ryujinx.Graphics.Vulkan
} }
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void Initialize(CommandBufferScoped cbs, int setIndex, DescriptorSetCollection dsc) private void Initialize(CommandBufferScoped cbs, int setIndex, DescriptorSetCollection dsc)
{ {
// We don't support clearing texture descriptors currently.
if (setIndex != PipelineBase.UniformSetIndex && setIndex != PipelineBase.StorageSetIndex)
{
return;
}
var dummyBuffer = _dummyBuffer?.GetBuffer().Get(cbs).Value ?? default; var dummyBuffer = _dummyBuffer?.GetBuffer().Get(cbs).Value ?? default;
uint stages = _program.Stages; foreach (ResourceBindingSegment segment in _program.ClearSegments[setIndex])
while (stages != 0)
{ {
int stage = BitOperations.TrailingZeroCount(stages); dsc.InitializeBuffers(0, segment.Binding, segment.Count, segment.Type.Convert(), dummyBuffer);
stages &= ~(1u << stage);
if (setIndex == PipelineBase.UniformSetIndex)
{
dsc.InitializeBuffers(
0,
1 + stage * Constants.MaxUniformBuffersPerStage,
Constants.MaxUniformBuffersPerStage,
DescriptorType.UniformBuffer,
dummyBuffer);
}
else if (setIndex == PipelineBase.StorageSetIndex)
{
dsc.InitializeBuffers(
0,
stage * Constants.MaxStorageBuffersPerStage,
Constants.MaxStorageBuffersPerStage,
DescriptorType.StorageBuffer,
dummyBuffer);
}
} }
} }

View File

@@ -25,7 +25,7 @@ namespace Ryujinx.Graphics.Vulkan
private uint VertexAttributeDescriptionsCount => (byte)((Id6 >> 38) & 0xFF); private uint VertexAttributeDescriptionsCount => (byte)((Id6 >> 38) & 0xFF);
private uint VertexBindingDescriptionsCount => (byte)((Id6 >> 46) & 0xFF); private uint VertexBindingDescriptionsCount => (byte)((Id6 >> 46) & 0xFF);
private uint ViewportsCount => (byte)((Id6 >> 54) & 0xFF); private uint ViewportsCount => (byte)((Id6 >> 54) & 0xFF);
private uint ScissorsCount => (byte)((Id7 >> 0) & 0xFF); private uint ScissorsCount => (byte)(Id7 & 0xFF);
private uint ColorBlendAttachmentStateCount => (byte)((Id7 >> 8) & 0xFF); private uint ColorBlendAttachmentStateCount => (byte)((Id7 >> 8) & 0xFF);
private bool HasDepthStencil => ((Id7 >> 63) & 0x1) != 0UL; private bool HasDepthStencil => ((Id7 >> 63) & 0x1) != 0UL;

View File

@@ -24,6 +24,7 @@ namespace Ryujinx.Graphics.Vulkan
public uint Stages { get; } public uint Stages { get; }
public ResourceBindingSegment[][] ClearSegments { get; }
public ResourceBindingSegment[][] BindingSegments { get; } public ResourceBindingSegment[][] BindingSegments { get; }
public ProgramLinkStatus LinkStatus { get; private set; } public ProgramLinkStatus LinkStatus { get; private set; }
@@ -115,6 +116,7 @@ namespace Ryujinx.Graphics.Vulkan
Stages = stages; Stages = stages;
ClearSegments = BuildClearSegments(resourceLayout.Sets);
BindingSegments = BuildBindingSegments(resourceLayout.SetUsages); BindingSegments = BuildBindingSegments(resourceLayout.SetUsages);
_compileTask = Task.CompletedTask; _compileTask = Task.CompletedTask;
@@ -135,6 +137,60 @@ namespace Ryujinx.Graphics.Vulkan
_firstBackgroundUse = !fromCache; _firstBackgroundUse = !fromCache;
} }
private static ResourceBindingSegment[][] BuildClearSegments(ReadOnlyCollection<ResourceDescriptorCollection> sets)
{
ResourceBindingSegment[][] segments = new ResourceBindingSegment[sets.Count][];
for (int setIndex = 0; setIndex < sets.Count; setIndex++)
{
List<ResourceBindingSegment> currentSegments = new List<ResourceBindingSegment>();
ResourceDescriptor currentDescriptor = default;
int currentCount = 0;
for (int index = 0; index < sets[setIndex].Descriptors.Count; index++)
{
ResourceDescriptor descriptor = sets[setIndex].Descriptors[index];
if (currentDescriptor.Binding + currentCount != descriptor.Binding ||
currentDescriptor.Type != descriptor.Type ||
currentDescriptor.Stages != descriptor.Stages)
{
if (currentCount != 0)
{
currentSegments.Add(new ResourceBindingSegment(
currentDescriptor.Binding,
currentCount,
currentDescriptor.Type,
currentDescriptor.Stages,
ResourceAccess.ReadWrite));
}
currentDescriptor = descriptor;
currentCount = descriptor.Count;
}
else
{
currentCount += descriptor.Count;
}
}
if (currentCount != 0)
{
currentSegments.Add(new ResourceBindingSegment(
currentDescriptor.Binding,
currentCount,
currentDescriptor.Type,
currentDescriptor.Stages,
ResourceAccess.ReadWrite));
}
segments[setIndex] = currentSegments.ToArray();
}
return segments;
}
private static ResourceBindingSegment[][] BuildBindingSegments(ReadOnlyCollection<ResourceUsageCollection> setUsages) private static ResourceBindingSegment[][] BuildBindingSegments(ReadOnlyCollection<ResourceUsageCollection> setUsages)
{ {
ResourceBindingSegment[][] segments = new ResourceBindingSegment[setUsages.Count][]; ResourceBindingSegment[][] segments = new ResourceBindingSegment[setUsages.Count][];

View File

@@ -589,6 +589,7 @@ namespace Ryujinx.Graphics.Vulkan
supportsFragmentShaderOrderingIntel: false, supportsFragmentShaderOrderingIntel: false,
supportsGeometryShader: Capabilities.SupportsGeometryShader, supportsGeometryShader: Capabilities.SupportsGeometryShader,
supportsGeometryShaderPassthrough: Capabilities.SupportsGeometryShaderPassthrough, supportsGeometryShaderPassthrough: Capabilities.SupportsGeometryShaderPassthrough,
supportsTransformFeedback: Capabilities.SupportsTransformFeedback,
supportsImageLoadFormatted: features2.Features.ShaderStorageImageReadWithoutFormat, supportsImageLoadFormatted: features2.Features.ShaderStorageImageReadWithoutFormat,
supportsLayerVertexTessellation: featuresVk12.ShaderOutputLayer, supportsLayerVertexTessellation: featuresVk12.ShaderOutputLayer,
supportsMismatchingViewFormat: true, supportsMismatchingViewFormat: true,

View File

@@ -181,7 +181,7 @@ namespace Ryujinx.HLE.FileSystem
} }
} }
if (_locationEntries.ContainsKey(storageId) && _locationEntries[storageId]?.Count == 0) if (_locationEntries.TryGetValue(storageId, out var locationEntriesItem) && locationEntriesItem?.Count == 0)
{ {
_locationEntries.Remove(storageId); _locationEntries.Remove(storageId);
} }
@@ -347,9 +347,9 @@ namespace Ryujinx.HLE.FileSystem
{ {
lock (_lock) lock (_lock)
{ {
if (_contentDictionary.ContainsKey((titleId, contentType))) if (_contentDictionary.TryGetValue((titleId, contentType), out var contentDictionaryItem))
{ {
return UInt128Utils.FromHex(_contentDictionary[(titleId, contentType)]); return UInt128Utils.FromHex(contentDictionaryItem);
} }
} }
@@ -719,9 +719,9 @@ namespace Ryujinx.HLE.FileSystem
Nca nca = new Nca(_virtualFileSystem.KeySet, storage); Nca nca = new Nca(_virtualFileSystem.KeySet, storage);
if (updateNcas.ContainsKey(nca.Header.TitleId)) if (updateNcas.TryGetValue(nca.Header.TitleId, out var updateNcasItem))
{ {
updateNcas[nca.Header.TitleId].Add((nca.Header.ContentType, entry.FullName)); updateNcasItem.Add((nca.Header.ContentType, entry.FullName));
} }
else else
{ {
@@ -732,10 +732,8 @@ namespace Ryujinx.HLE.FileSystem
} }
} }
if (updateNcas.ContainsKey(SystemUpdateTitleId)) if (updateNcas.TryGetValue(SystemUpdateTitleId, out var ncaEntry))
{ {
var ncaEntry = updateNcas[SystemUpdateTitleId];
string metaPath = ncaEntry.Find(x => x.type == NcaContentType.Meta).path; string metaPath = ncaEntry.Find(x => x.type == NcaContentType.Meta).path;
CnmtContentMetaEntry[] metaEntries = null; CnmtContentMetaEntry[] metaEntries = null;
@@ -770,9 +768,9 @@ namespace Ryujinx.HLE.FileSystem
throw new FileNotFoundException("System update title was not found in the firmware package."); throw new FileNotFoundException("System update title was not found in the firmware package.");
} }
if (updateNcas.ContainsKey(SystemVersionTitleId)) if (updateNcas.TryGetValue(SystemVersionTitleId, out var updateNcasItem))
{ {
string versionEntry = updateNcas[SystemVersionTitleId].Find(x => x.type != NcaContentType.Meta).path; string versionEntry = updateNcasItem.Find(x => x.type != NcaContentType.Meta).path;
using (Stream ncaStream = GetZipStream(archive.GetEntry(versionEntry))) using (Stream ncaStream = GetZipStream(archive.GetEntry(versionEntry)))
{ {
@@ -916,9 +914,9 @@ namespace Ryujinx.HLE.FileSystem
} }
} }
if (updateNcas.ContainsKey(nca.Header.TitleId)) if (updateNcas.TryGetValue(nca.Header.TitleId, out var updateNcasItem))
{ {
updateNcas[nca.Header.TitleId].Add((nca.Header.ContentType, entry.FullPath)); updateNcasItem.Add((nca.Header.ContentType, entry.FullPath));
} }
else else
{ {

View File

@@ -0,0 +1,17 @@
using System.Text.RegularExpressions;
namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
{
public static partial class CJKCharacterValidation
{
public static bool IsCJK(char value)
{
Regex regex = CJKRegex();
return regex.IsMatch(value.ToString());
}
[GeneratedRegex("\\p{IsHangulJamo}|\\p{IsCJKRadicalsSupplement}|\\p{IsCJKSymbolsandPunctuation}|\\p{IsEnclosedCJKLettersandMonths}|\\p{IsCJKCompatibility}|\\p{IsCJKUnifiedIdeographsExtensionA}|\\p{IsCJKUnifiedIdeographs}|\\p{IsHangulSyllables}|\\p{IsCJKCompatibilityForms}")]
private static partial Regex CJKRegex();
}
}

View File

@@ -6,22 +6,30 @@
public enum KeyboardMode : uint public enum KeyboardMode : uint
{ {
/// <summary> /// <summary>
/// A full alpha-numeric keyboard. /// All UTF-16 characters allowed.
/// </summary> /// </summary>
Default = 0, Default = 0,
/// <summary> /// <summary>
/// Number pad. /// Only numbers allowed.
/// </summary> /// </summary>
NumbersOnly = 1, NumbersOnly = 1,
/// <summary> /// <summary>
/// ASCII characters keyboard. /// Only ASCII characters allowed.
/// </summary> /// </summary>
ASCII = 2, ASCII = 2,
FullLatin = 3, /// <summary>
Alphabet = 4, /// Synonymous with default.
/// </summary>
FullLatin = 3,
/// <summary>
/// All UTF-16 characters except CJK characters allowed.
/// </summary>
Alphabet = 4,
SimplifiedChinese = 5, SimplifiedChinese = 5,
TraditionalChinese = 6, TraditionalChinese = 6,
Korean = 7, Korean = 7,

View File

@@ -137,7 +137,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
public void CancelHandleReservation(int handle) public void CancelHandleReservation(int handle)
{ {
int index = (handle >> 0) & 0x7fff; int index = handle & 0x7fff;
lock (_table) lock (_table)
{ {

View File

@@ -1,5 +1,8 @@
using System;
namespace Ryujinx.HLE.HOS.Kernel.Threading namespace Ryujinx.HLE.HOS.Kernel.Threading
{ {
[Flags]
enum ThreadSchedState : ushort enum ThreadSchedState : ushort
{ {
LowMask = 0xf, LowMask = 0xf,

View File

@@ -154,7 +154,7 @@ namespace Ryujinx.HLE.HOS
} }
private static DirectoryInfo FindTitleDir(DirectoryInfo contentsDir, string titleId) private static DirectoryInfo FindTitleDir(DirectoryInfo contentsDir, string titleId)
=> contentsDir.EnumerateDirectories($"{titleId}*", DirEnumOptions).FirstOrDefault(); => contentsDir.EnumerateDirectories(titleId, DirEnumOptions).FirstOrDefault();
private static void AddModsFromDirectory(ModCache mods, DirectoryInfo dir, string titleId) private static void AddModsFromDirectory(ModCache mods, DirectoryInfo dir, string titleId)
{ {

View File

@@ -1,8 +1,29 @@
namespace Ryujinx.HLE.HOS.Services.Hid using Ryujinx.Common;
using Ryujinx.Common.Logging;
namespace Ryujinx.HLE.HOS.Services.Hid
{ {
[Service("hidbus")] [Service("hidbus")]
class IHidbusServer : IpcService class IHidbusServer : IpcService
{ {
public IHidbusServer(ServiceCtx context) { } public IHidbusServer(ServiceCtx context) { }
[CommandCmif(1)]
// GetBusHandle(nn::hid::NpadIdType, nn::hidbus::BusType, nn::applet::AppletResourceUserId) -> (bool HasHandle, nn::hidbus::BusHandle)
public ResultCode GetBusHandle(ServiceCtx context)
{
NpadIdType npadIdType = (NpadIdType)context.RequestData.ReadInt32();
context.RequestData.BaseStream.Position += 4; // Padding
BusType busType = (BusType)context.RequestData.ReadInt64();
long appletResourceUserId = context.RequestData.ReadInt64();
context.ResponseData.Write(false);
context.ResponseData.BaseStream.Position += 7; // Padding
context.ResponseData.WriteStruct(new BusHandle());
Logger.Stub?.PrintStub(LogClass.ServiceHid, new { npadIdType, busType, appletResourceUserId });
return ResultCode.Success;
}
} }
} }

View File

@@ -0,0 +1,14 @@
using System.Runtime.InteropServices;
namespace Ryujinx.HLE.HOS.Services.Hid
{
[StructLayout(LayoutKind.Sequential)]
struct BusHandle
{
public int AbstractedPadId;
public byte InternalIndex;
public byte PlayerNumber;
public byte BusTypeId;
public byte IsValid;
}
}

View File

@@ -0,0 +1,9 @@
namespace Ryujinx.HLE.HOS.Services.Hid
{
public enum BusType : long
{
LeftJoyRail = 0,
RightJoyRail = 1,
InternalBus = 2
}
}

View File

@@ -17,7 +17,7 @@ namespace Ryujinx.Horizon.LogManager.Ipc
private const int MessageLengthLimit = 5000; private const int MessageLengthLimit = 5000;
private readonly LogService _log; private readonly LogService _log;
private readonly ulong _pid; private readonly ulong _pid;
private LogPacket _logPacket; private LogPacket _logPacket;
@@ -74,8 +74,12 @@ namespace Ryujinx.Horizon.LogManager.Ipc
private bool LogImpl(ReadOnlySpan<byte> message) private bool LogImpl(ReadOnlySpan<byte> message)
{ {
SpanReader reader = new(message); SpanReader reader = new(message);
LogPacketHeader header = reader.Read<LogPacketHeader>();
if (!reader.TryRead(out LogPacketHeader header))
{
return true;
}
bool isHeadPacket = (header.Flags & LogPacketFlags.IsHead) != 0; bool isHeadPacket = (header.Flags & LogPacketFlags.IsHead) != 0;
bool isTailPacket = (header.Flags & LogPacketFlags.IsTail) != 0; bool isTailPacket = (header.Flags & LogPacketFlags.IsTail) != 0;
@@ -84,8 +88,10 @@ namespace Ryujinx.Horizon.LogManager.Ipc
while (reader.Length > 0) while (reader.Length > 0)
{ {
int type = ReadUleb128(ref reader); if (!TryReadUleb128(ref reader, out int type) || !TryReadUleb128(ref reader, out int size))
int size = ReadUleb128(ref reader); {
return true;
}
LogDataChunkKey key = (LogDataChunkKey)type; LogDataChunkKey key = (LogDataChunkKey)type;
@@ -101,15 +107,24 @@ namespace Ryujinx.Horizon.LogManager.Ipc
} }
else if (key == LogDataChunkKey.Line) else if (key == LogDataChunkKey.Line)
{ {
_logPacket.Line = reader.Read<int>(); if (!reader.TryRead<int>(out _logPacket.Line))
{
return true;
}
} }
else if (key == LogDataChunkKey.DropCount) else if (key == LogDataChunkKey.DropCount)
{ {
_logPacket.DropCount = reader.Read<long>(); if (!reader.TryRead<long>(out _logPacket.DropCount))
{
return true;
}
} }
else if (key == LogDataChunkKey.Time) else if (key == LogDataChunkKey.Time)
{ {
_logPacket.Time = reader.Read<long>(); if (!reader.TryRead<long>(out _logPacket.Time))
{
return true;
}
} }
else if (key == LogDataChunkKey.Message) else if (key == LogDataChunkKey.Message)
{ {
@@ -154,23 +169,25 @@ namespace Ryujinx.Horizon.LogManager.Ipc
return isTailPacket; return isTailPacket;
} }
private static int ReadUleb128(ref SpanReader reader) private static bool TryReadUleb128(ref SpanReader reader, out int result)
{ {
int result = 0; result = 0;
int count = 0; int count = 0;
byte encoded; byte encoded;
do do
{ {
encoded = reader.Read<byte>(); if (!reader.TryRead<byte>(out encoded))
{
return false;
}
result += (encoded & 0x7F) << (7 * count); result += (encoded & 0x7F) << (7 * count);
count++; count++;
} while ((encoded & 0x80) != 0); } while ((encoded & 0x80) != 0);
return result; return true;
} }
} }
} }

View File

@@ -338,12 +338,10 @@ namespace Ryujinx.Input.Motion.CemuHook
{ {
int slot = inputData.Shared.Slot; int slot = inputData.Shared.Slot;
if (_motionData.ContainsKey(clientId)) if (_motionData.TryGetValue(clientId, out var motionDataItem))
{ {
if (_motionData[clientId].ContainsKey(slot)) if (motionDataItem.TryGetValue(slot, out var previousData))
{ {
MotionInput previousData = _motionData[clientId][slot];
previousData.Update(accelerometer, gyroscrope, timestamp, cemuHookConfig.Sensitivity, (float)cemuHookConfig.GyroDeadzone); previousData.Update(accelerometer, gyroscrope, timestamp, cemuHookConfig.Sensitivity, (float)cemuHookConfig.GyroDeadzone);
} }
else else
@@ -352,7 +350,7 @@ namespace Ryujinx.Input.Motion.CemuHook
input.Update(accelerometer, gyroscrope, timestamp, cemuHookConfig.Sensitivity, (float)cemuHookConfig.GyroDeadzone); input.Update(accelerometer, gyroscrope, timestamp, cemuHookConfig.Sensitivity, (float)cemuHookConfig.GyroDeadzone);
_motionData[clientId].Add(slot, input); motionDataItem.Add(slot, input);
} }
} }
else else

View File

@@ -7,7 +7,7 @@ namespace Ryujinx.Tests.Memory
{ {
public class Tests public class Tests
{ {
private const ulong MemorySize = 0x8000; private static readonly ulong MemorySize = MemoryBlock.GetPageSize() * 8;
private MemoryBlock _memoryBlock; private MemoryBlock _memoryBlock;
@@ -44,14 +44,17 @@ namespace Ryujinx.Tests.Memory
[Platform(Exclude = "MacOsX")] [Platform(Exclude = "MacOsX")]
public void Test_Alias() public void Test_Alias()
{ {
using MemoryBlock backing = new MemoryBlock(0x10000, MemoryAllocationFlags.Mirrorable); ulong pageSize = MemoryBlock.GetPageSize();
using MemoryBlock toAlias = new MemoryBlock(0x10000, MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible); ulong blockSize = MemoryBlock.GetPageSize() * 16;
toAlias.MapView(backing, 0x1000, 0, 0x4000); using MemoryBlock backing = new MemoryBlock(blockSize, MemoryAllocationFlags.Mirrorable);
toAlias.UnmapView(backing, 0x3000, 0x1000); using MemoryBlock toAlias = new MemoryBlock(blockSize, MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible);
toAlias.MapView(backing, pageSize, 0, pageSize * 4);
toAlias.UnmapView(backing, pageSize * 3, pageSize);
toAlias.Write(0, 0xbadc0de); toAlias.Write(0, 0xbadc0de);
Assert.AreEqual(Marshal.ReadInt32(backing.Pointer, 0x1000), 0xbadc0de); Assert.AreEqual(Marshal.ReadInt32(backing.Pointer, (int)pageSize), 0xbadc0de);
} }
[Test] [Test]
@@ -59,8 +62,12 @@ namespace Ryujinx.Tests.Memory
[Platform(Exclude = "MacOsX")] [Platform(Exclude = "MacOsX")]
public void Test_AliasRandom() public void Test_AliasRandom()
{ {
using MemoryBlock backing = new MemoryBlock(0x80000, MemoryAllocationFlags.Mirrorable); ulong pageSize = MemoryBlock.GetPageSize();
using MemoryBlock toAlias = new MemoryBlock(0x80000, MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible); int pageBits = (int)ulong.Log2(pageSize);
ulong blockSize = MemoryBlock.GetPageSize() * 128;
using MemoryBlock backing = new MemoryBlock(blockSize, MemoryAllocationFlags.Mirrorable);
using MemoryBlock toAlias = new MemoryBlock(blockSize, MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible);
Random rng = new Random(123); Random rng = new Random(123);
@@ -72,16 +79,16 @@ namespace Ryujinx.Tests.Memory
if ((rng.Next() & 1) != 0) if ((rng.Next() & 1) != 0)
{ {
toAlias.MapView(backing, (ulong)srcPage << 12, (ulong)dstPage << 12, (ulong)pages << 12); toAlias.MapView(backing, (ulong)srcPage << pageBits, (ulong)dstPage << pageBits, (ulong)pages << pageBits);
int offset = rng.Next(0, 0x1000 - sizeof(int)); int offset = rng.Next(0, (int)pageSize - sizeof(int));
toAlias.Write((ulong)((dstPage << 12) + offset), 0xbadc0de); toAlias.Write((ulong)((dstPage << pageBits) + offset), 0xbadc0de);
Assert.AreEqual(Marshal.ReadInt32(backing.Pointer, (srcPage << 12) + offset), 0xbadc0de); Assert.AreEqual(Marshal.ReadInt32(backing.Pointer, (srcPage << pageBits) + offset), 0xbadc0de);
} }
else else
{ {
toAlias.UnmapView(backing, (ulong)dstPage << 12, (ulong)pages << 12); toAlias.UnmapView(backing, (ulong)dstPage << pageBits, (ulong)pages << pageBits);
} }
} }
} }
@@ -91,7 +98,7 @@ namespace Ryujinx.Tests.Memory
[Platform(Exclude = "MacOsX")] [Platform(Exclude = "MacOsX")]
public void Test_AliasMapLeak() public void Test_AliasMapLeak()
{ {
ulong pageSize = 4096; ulong pageSize = MemoryBlock.GetPageSize();
ulong size = 100000 * pageSize; // The mappings limit on Linux is usually around 65K, so let's make sure we are above that. ulong size = 100000 * pageSize; // The mappings limit on Linux is usually around 65K, so let's make sure we are above that.
using MemoryBlock backing = new MemoryBlock(pageSize, MemoryAllocationFlags.Mirrorable); using MemoryBlock backing = new MemoryBlock(pageSize, MemoryAllocationFlags.Mirrorable);

View File

@@ -13,9 +13,9 @@ namespace Ryujinx.Tests.Cpu
[TestFixture] [TestFixture]
public class CpuTest public class CpuTest
{ {
protected const ulong Size = 0x1000; protected static readonly ulong Size = MemoryBlock.GetPageSize();
protected const ulong CodeBaseAddress = 0x1000; protected static ulong CodeBaseAddress = Size;
protected const ulong DataBaseAddress = CodeBaseAddress + Size; protected static ulong DataBaseAddress = CodeBaseAddress + Size;
private static bool Ignore_FpcrFz = false; private static bool Ignore_FpcrFz = false;
private static bool Ignore_FpcrDn = false; private static bool Ignore_FpcrDn = false;
@@ -39,12 +39,24 @@ namespace Ryujinx.Tests.Cpu
[SetUp] [SetUp]
public void Setup() public void Setup()
{ {
_currAddress = CodeBaseAddress; int pageBits = (int)ulong.Log2(Size);
_ram = new MemoryBlock(Size * 2); _ram = new MemoryBlock(Size * 2);
_memory = new MemoryManager(_ram, 1ul << 16); _memory = new MemoryManager(_ram, 1ul << (pageBits + 4));
_memory.IncrementReferenceCount(); _memory.IncrementReferenceCount();
_memory.Map(CodeBaseAddress, 0, Size * 2, MemoryMapFlags.Private);
// Some tests depends on hardcoded address that were computed for 4KiB.
// We change the layout on non 4KiB platforms to keep compat here.
if (Size > 0x1000)
{
DataBaseAddress = 0;
CodeBaseAddress = Size;
}
_currAddress = CodeBaseAddress;
_memory.Map(CodeBaseAddress, 0, Size, MemoryMapFlags.Private);
_memory.Map(DataBaseAddress, Size, Size, MemoryMapFlags.Private);
_context = CpuContext.CreateExecutionContext(); _context = CpuContext.CreateExecutionContext();
Translator.IsReadyForTranslation.Set(); Translator.IsReadyForTranslation.Set();

View File

@@ -13,9 +13,9 @@ namespace Ryujinx.Tests.Cpu
[TestFixture] [TestFixture]
public class CpuTest32 public class CpuTest32
{ {
protected const uint Size = 0x1000; protected static readonly uint Size = (uint)MemoryBlock.GetPageSize();
protected const uint CodeBaseAddress = 0x1000; protected static uint CodeBaseAddress = Size;
protected const uint DataBaseAddress = CodeBaseAddress + Size; protected static uint DataBaseAddress = CodeBaseAddress + Size;
private uint _currAddress; private uint _currAddress;
@@ -33,12 +33,24 @@ namespace Ryujinx.Tests.Cpu
[SetUp] [SetUp]
public void Setup() public void Setup()
{ {
_currAddress = CodeBaseAddress; int pageBits = (int)ulong.Log2(Size);
_ram = new MemoryBlock(Size * 2); _ram = new MemoryBlock(Size * 2);
_memory = new MemoryManager(_ram, 1ul << 16); _memory = new MemoryManager(_ram, 1ul << (pageBits + 4));
_memory.IncrementReferenceCount(); _memory.IncrementReferenceCount();
_memory.Map(CodeBaseAddress, 0, Size * 2, MemoryMapFlags.Private);
// Some tests depends on hardcoded address that were computed for 4KiB.
// We change the layout on non 4KiB platforms to keep compat here.
if (Size > 0x1000)
{
DataBaseAddress = 0;
CodeBaseAddress = Size;
}
_currAddress = CodeBaseAddress;
_memory.Map(CodeBaseAddress, 0, Size, MemoryMapFlags.Private);
_memory.Map(DataBaseAddress, Size, Size, MemoryMapFlags.Private);
_context = CpuContext.CreateExecutionContext(); _context = CpuContext.CreateExecutionContext();
_context.IsAarch32 = true; _context.IsAarch32 = true;

View File

@@ -1,6 +1,7 @@
#define SimdMemory32 #define SimdMemory32
using ARMeilleure.State; using ARMeilleure.State;
using Ryujinx.Memory;
using NUnit.Framework; using NUnit.Framework;
using System; using System;
@@ -9,6 +10,7 @@ namespace Ryujinx.Tests.Cpu
[Category("SimdMemory32")] [Category("SimdMemory32")]
public sealed class CpuTestSimdMemory32 : CpuTest32 public sealed class CpuTestSimdMemory32 : CpuTest32
{ {
private static readonly uint TestOffset = DataBaseAddress + 0x500;
#if SimdMemory32 #if SimdMemory32
private uint[] _ldStModes = private uint[] _ldStModes =
@@ -42,7 +44,7 @@ namespace Ryujinx.Tests.Cpu
[Range(0u, 3u)] uint n, [Range(0u, 3u)] uint n,
[Values(0x0u)] uint offset) [Values(0x0u)] uint offset)
{ {
var data = GenerateVectorSequence(0x1000); var data = GenerateVectorSequence((int)MemoryBlock.GetPageSize());
SetWorkingMemory(0, data); SetWorkingMemory(0, data);
uint opcode = 0xf4a00000u; // VLD1.8 {D0[0]}, [R0], R0 uint opcode = 0xf4a00000u; // VLD1.8 {D0[0]}, [R0], R0
@@ -58,7 +60,7 @@ namespace Ryujinx.Tests.Cpu
opcode |= (n & 3) << 8; // LD1 is 0, LD2 is 1 etc. opcode |= (n & 3) << 8; // LD1 is 0, LD2 is 1 etc.
SingleOpcode(opcode, r0: 0x2500, r1: offset, sp: 0x2500); SingleOpcode(opcode, r0: TestOffset, r1: offset, sp: TestOffset);
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@@ -72,7 +74,7 @@ namespace Ryujinx.Tests.Cpu
[Values] bool t, [Values] bool t,
[Values(0x0u)] uint offset) [Values(0x0u)] uint offset)
{ {
var data = GenerateVectorSequence(0x1000); var data = GenerateVectorSequence((int)MemoryBlock.GetPageSize());
SetWorkingMemory(0, data); SetWorkingMemory(0, data);
uint opcode = 0xf4a00c00u; // VLD1.8 {D0[0]}, [R0], R0 uint opcode = 0xf4a00c00u; // VLD1.8 {D0[0]}, [R0], R0
@@ -85,7 +87,7 @@ namespace Ryujinx.Tests.Cpu
opcode |= (n & 3) << 8; // LD1 is 0, LD2 is 1 etc. opcode |= (n & 3) << 8; // LD1 is 0, LD2 is 1 etc.
if (t) opcode |= 1 << 5; if (t) opcode |= 1 << 5;
SingleOpcode(opcode, r0: 0x2500, r1: offset, sp: 0x2500); SingleOpcode(opcode, r0: TestOffset, r1: offset, sp: TestOffset);
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@@ -98,7 +100,7 @@ namespace Ryujinx.Tests.Cpu
[Range(0u, 10u)] uint mode, [Range(0u, 10u)] uint mode,
[Values(0x0u)] uint offset) [Values(0x0u)] uint offset)
{ {
var data = GenerateVectorSequence(0x1000); var data = GenerateVectorSequence((int)MemoryBlock.GetPageSize());
SetWorkingMemory(0, data); SetWorkingMemory(0, data);
uint opcode = 0xf4200000u; // VLD4.8 {D0, D1, D2, D3}, [R0], R0 uint opcode = 0xf4200000u; // VLD4.8 {D0, D1, D2, D3}, [R0], R0
@@ -114,7 +116,7 @@ namespace Ryujinx.Tests.Cpu
opcode |= ((vd & 0x10) << 18); opcode |= ((vd & 0x10) << 18);
opcode |= ((vd & 0xf) << 12); opcode |= ((vd & 0xf) << 12);
SingleOpcode(opcode, r0: 0x2500, r1: offset, sp: 0x2500); SingleOpcode(opcode, r0: TestOffset, r1: offset, sp: TestOffset);
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@@ -128,7 +130,7 @@ namespace Ryujinx.Tests.Cpu
[Range(0u, 3u)] uint n, [Range(0u, 3u)] uint n,
[Values(0x0u)] uint offset) [Values(0x0u)] uint offset)
{ {
var data = GenerateVectorSequence(0x1000); var data = GenerateVectorSequence((int)MemoryBlock.GetPageSize());
SetWorkingMemory(0, data); SetWorkingMemory(0, data);
(V128 vec1, V128 vec2, V128 vec3, V128 vec4) = GenerateTestVectors(); (V128 vec1, V128 vec2, V128 vec3, V128 vec4) = GenerateTestVectors();
@@ -146,7 +148,7 @@ namespace Ryujinx.Tests.Cpu
opcode |= (n & 3) << 8; // ST1 is 0, ST2 is 1 etc. opcode |= (n & 3) << 8; // ST1 is 0, ST2 is 1 etc.
SingleOpcode(opcode, r0: 0x2500, r1: offset, v1: vec1, v2: vec2, v3: vec3, v4: vec4, sp: 0x2500); SingleOpcode(opcode, r0: TestOffset, r1: offset, v1: vec1, v2: vec2, v3: vec3, v4: vec4, sp: TestOffset);
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@@ -159,7 +161,7 @@ namespace Ryujinx.Tests.Cpu
[Range(0u, 10u)] uint mode, [Range(0u, 10u)] uint mode,
[Values(0x0u)] uint offset) [Values(0x0u)] uint offset)
{ {
var data = GenerateVectorSequence(0x1000); var data = GenerateVectorSequence((int)MemoryBlock.GetPageSize());
SetWorkingMemory(0, data); SetWorkingMemory(0, data);
(V128 vec1, V128 vec2, V128 vec3, V128 vec4) = GenerateTestVectors(); (V128 vec1, V128 vec2, V128 vec3, V128 vec4) = GenerateTestVectors();
@@ -177,7 +179,7 @@ namespace Ryujinx.Tests.Cpu
opcode |= ((vd & 0x10) << 18); opcode |= ((vd & 0x10) << 18);
opcode |= ((vd & 0xf) << 12); opcode |= ((vd & 0xf) << 12);
SingleOpcode(opcode, r0: 0x2500, r1: offset, v1: vec1, v2: vec2, v3: vec3, v4: vec4, sp: 0x2500); SingleOpcode(opcode, r0: TestOffset, r1: offset, v1: vec1, v2: vec2, v3: vec3, v4: vec4, sp: TestOffset);
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@@ -189,7 +191,7 @@ namespace Ryujinx.Tests.Cpu
[Values(0x1u, 0x32u)] uint regs, [Values(0x1u, 0x32u)] uint regs,
[Values] bool single) [Values] bool single)
{ {
var data = GenerateVectorSequence(0x1000); var data = GenerateVectorSequence((int)MemoryBlock.GetPageSize());
SetWorkingMemory(0, data); SetWorkingMemory(0, data);
uint opcode = 0xec100a00u; // VST4.8 {D0, D1, D2, D3}, [R0], R0 uint opcode = 0xec100a00u; // VST4.8 {D0, D1, D2, D3}, [R0], R0
@@ -225,7 +227,7 @@ namespace Ryujinx.Tests.Cpu
opcode |= regs & 0xff; opcode |= regs & 0xff;
SingleOpcode(opcode, r0: 0x2500, sp: 0x2500); SingleOpcode(opcode, r0: TestOffset, sp: TestOffset);
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@@ -237,7 +239,7 @@ namespace Ryujinx.Tests.Cpu
[Values(0x0u)] uint imm, [Values(0x0u)] uint imm,
[Values] bool sub) [Values] bool sub)
{ {
var data = GenerateVectorSequence(0x1000); var data = GenerateVectorSequence((int)MemoryBlock.GetPageSize());
SetWorkingMemory(0, data); SetWorkingMemory(0, data);
uint opcode = 0xed900a00u; // VLDR.32 S0, [R0, #0] uint opcode = 0xed900a00u; // VLDR.32 S0, [R0, #0]
@@ -260,7 +262,7 @@ namespace Ryujinx.Tests.Cpu
} }
opcode |= imm & 0xff; opcode |= imm & 0xff;
SingleOpcode(opcode, r0: 0x2500); SingleOpcode(opcode, r0: TestOffset);
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@@ -272,7 +274,7 @@ namespace Ryujinx.Tests.Cpu
[Values(0x0u)] uint imm, [Values(0x0u)] uint imm,
[Values] bool sub) [Values] bool sub)
{ {
var data = GenerateVectorSequence(0x1000); var data = GenerateVectorSequence((int)MemoryBlock.GetPageSize());
SetWorkingMemory(0, data); SetWorkingMemory(0, data);
uint opcode = 0xed800a00u; // VSTR.32 S0, [R0, #0] uint opcode = 0xed800a00u; // VSTR.32 S0, [R0, #0]
@@ -297,7 +299,7 @@ namespace Ryujinx.Tests.Cpu
(V128 vec1, V128 vec2, _, _) = GenerateTestVectors(); (V128 vec1, V128 vec2, _, _) = GenerateTestVectors();
SingleOpcode(opcode, r0: 0x2500, v0: vec1, v1: vec2); SingleOpcode(opcode, r0: TestOffset, v0: vec1, v1: vec2);
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }

View File

@@ -3,6 +3,7 @@
using ARMeilleure.State; using ARMeilleure.State;
using NUnit.Framework; using NUnit.Framework;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace Ryujinx.Tests.Cpu namespace Ryujinx.Tests.Cpu
{ {
@@ -703,6 +704,11 @@ namespace Ryujinx.Tests.Cpu
[Values] bool q, [Values] bool q,
[Values] bool u) [Values] bool u)
{ {
if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
{
Assert.Ignore("Unicorn on ARM64 crash while executing this test");
}
uint opcode = 0xf2000400u; // VSHL.S8 D0, D0, D0 uint opcode = 0xf2000400u; // VSHL.S8 D0, D0, D0
if (q) if (q)
{ {

View File

@@ -109,7 +109,7 @@ namespace Ryujinx.Tests.Cpu
ExecuteOpcodes(runUnicorn: false); ExecuteOpcodes(runUnicorn: false);
Assert.That(GetContext().GetX(0), Is.EqualTo(0x1005)); Assert.That(GetContext().GetX(0), Is.EqualTo(CodeBaseAddress + 0x5));
} }
[Test] [Test]
@@ -133,7 +133,7 @@ namespace Ryujinx.Tests.Cpu
ExecuteOpcodes(runUnicorn: false); ExecuteOpcodes(runUnicorn: false);
Assert.That(GetContext().GetX(0), Is.EqualTo(0x1005)); Assert.That(GetContext().GetX(0), Is.EqualTo(CodeBaseAddress + 0x5));
Assert.That(GetContext().GetPstateFlag(PState.TFlag), Is.EqualTo(false)); Assert.That(GetContext().GetPstateFlag(PState.TFlag), Is.EqualTo(false));
} }
@@ -160,7 +160,7 @@ namespace Ryujinx.Tests.Cpu
ExecuteOpcodes(runUnicorn: false); ExecuteOpcodes(runUnicorn: false);
Assert.That(GetContext().GetX(0), Is.EqualTo(0x1007)); Assert.That(GetContext().GetX(0), Is.EqualTo(CodeBaseAddress + 0x7));
Assert.That(GetContext().GetPstateFlag(PState.TFlag), Is.EqualTo(false)); Assert.That(GetContext().GetPstateFlag(PState.TFlag), Is.EqualTo(false));
} }
} }

View File

@@ -268,6 +268,12 @@ namespace Ryujinx.Tests.Cpu
[Test] [Test]
public void TestRandomTestCases([ValueSource(nameof(RandomTestCases))] PrecomputedThumbTestCase test) public void TestRandomTestCases([ValueSource(nameof(RandomTestCases))] PrecomputedThumbTestCase test)
{ {
if (Size != 0x1000)
{
// TODO: Change it to depend on DataBaseAddress instead.
Assert.Ignore("This test currently only support 4KiB page size");
}
RunPrecomputedTestCase(test); RunPrecomputedTestCase(test);
} }

View File

@@ -11,10 +11,10 @@ namespace Ryujinx.Ui.Common.Helper
{ {
public static partial class FileAssociationHelper public static partial class FileAssociationHelper
{ {
private static string[] _fileExtensions = new string[] { ".nca", ".nro", ".nso", ".nsp", ".xci" }; private static readonly string[] _fileExtensions = { ".nca", ".nro", ".nso", ".nsp", ".xci" };
[SupportedOSPlatform("linux")] [SupportedOSPlatform("linux")]
private static string _mimeDbPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share", "mime"); private static readonly string _mimeDbPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share", "mime");
private const int SHCNE_ASSOCCHANGED = 0x8000000; private const int SHCNE_ASSOCCHANGED = 0x8000000;
private const int SHCNF_FLUSH = 0x1000; private const int SHCNF_FLUSH = 0x1000;
@@ -32,7 +32,7 @@ namespace Ryujinx.Ui.Common.Helper
{ {
string installKeyword = uninstall ? "uninstall" : "install"; string installKeyword = uninstall ? "uninstall" : "install";
if (!AreMimeTypesRegisteredLinux()) if ((uninstall && AreMimeTypesRegisteredLinux()) || (!uninstall && !AreMimeTypesRegisteredLinux()))
{ {
string mimeTypesFile = Path.Combine(ReleaseInformation.GetBaseApplicationDirectory(), "mime", "Ryujinx.xml"); string mimeTypesFile = Path.Combine(ReleaseInformation.GetBaseApplicationDirectory(), "mime", "Ryujinx.xml");
string additionalArgs = !uninstall ? "--novendor" : ""; string additionalArgs = !uninstall ? "--novendor" : "";
@@ -81,9 +81,9 @@ namespace Ryujinx.Ui.Common.Helper
return false; return false;
} }
key.OpenSubKey(@"shell\open\command"); var openCmd = key.OpenSubKey(@"shell\open\command");
string keyValue = (string)key.GetValue(""); string keyValue = (string)openCmd.GetValue("");
return keyValue is not null && (keyValue.Contains("Ryujinx") || keyValue.Contains(AppDomain.CurrentDomain.FriendlyName)); return keyValue is not null && (keyValue.Contains("Ryujinx") || keyValue.Contains(AppDomain.CurrentDomain.FriendlyName));
} }
@@ -107,30 +107,31 @@ 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 (!AreMimeTypesRegisteredWindows()) if (!AreMimeTypesRegisteredWindows())
{ {
return false; return true;
} }
Logger.Debug?.Print(LogClass.Application, $"Removing type association {ext}");
Registry.CurrentUser.DeleteSubKeyTree(keyString); Registry.CurrentUser.DeleteSubKeyTree(keyString);
Logger.Debug?.Print(LogClass.Application, $"Removed type association {ext}");
} }
else else
{ {
RegistryKey key = Registry.CurrentUser.CreateSubKey(keyString); using var key = Registry.CurrentUser.CreateSubKey(keyString);
if (key is null) if (key is null)
{ {
return false; return false;
} }
key.CreateSubKey(@"shell\open\command"); Logger.Debug?.Print(LogClass.Application, $"Adding type association {ext}");
using var openCmd = key.CreateSubKey(@"shell\open\command");
openCmd.SetValue("", $"\"{Environment.ProcessPath}\" \"%1\"");
Logger.Debug?.Print(LogClass.Application, $"Added type association {ext}");
key.SetValue("", $"\"{Environment.ProcessPath}\" \"%1\"");
key.Close();
} }
// Notify Explorer the file association has been changed.
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSH, IntPtr.Zero, IntPtr.Zero);
return true; return true;
} }
@@ -141,6 +142,9 @@ namespace Ryujinx.Ui.Common.Helper
registered |= RegisterExtension(ext, uninstall); registered |= RegisterExtension(ext, uninstall);
} }
// Notify Explorer the file association has been changed.
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSH, IntPtr.Zero, IntPtr.Zero);
return registered; return registered;
} }

View File

@@ -93,8 +93,8 @@ namespace Ryujinx.Ui.Applet
_checkInput = text => text.All(char.IsDigit); _checkInput = text => text.All(char.IsDigit);
break; break;
case KeyboardMode.Alphabet: case KeyboardMode.Alphabet:
_validationInfoText += "<i>Must be alphabets only.</i>"; _validationInfoText += "<i>Must be non CJK-characters only.</i>";
_checkInput = text => text.All(char.IsAsciiLetter); _checkInput = text => text.All(value => !CJKCharacterValidation.IsCJK(value));
break; break;
case KeyboardMode.ASCII: case KeyboardMode.ASCII:
_validationInfoText += "<i>Must be ASCII text only.</i>"; _validationInfoText += "<i>Must be ASCII text only.</i>";

View File

@@ -1,8 +1,10 @@
using OpenTK.Graphics.OpenGL; using OpenTK.Graphics.OpenGL;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.OpenGL; using Ryujinx.Graphics.OpenGL;
using Ryujinx.Input.HLE; using Ryujinx.Input.HLE;
using SPB.Graphics; using SPB.Graphics;
using SPB.Graphics.Exceptions;
using SPB.Graphics.OpenGL; using SPB.Graphics.OpenGL;
using SPB.Platform; using SPB.Platform;
using SPB.Platform.GLX; using SPB.Platform.GLX;
@@ -112,24 +114,30 @@ namespace Ryujinx.Ui
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)
{ {
// Try to bind the OpenGL context before calling the shutdown event // Try to bind the OpenGL context before calling the shutdown event.
try try
{ {
_openGLContext?.MakeCurrent(_nativeWindow); _openGLContext?.MakeCurrent(_nativeWindow);
} }
catch (Exception) { } catch (ContextException e)
{
Logger.Warning?.Print(LogClass.Ui, $"Failed to bind OpenGL context: {e}");
}
Device?.DisposeGpu(); Device?.DisposeGpu();
NpadManager.Dispose(); NpadManager.Dispose();
// Unbind context and destroy everything // Unbind context and destroy everything.
try try
{ {
_openGLContext?.MakeCurrent(null); _openGLContext?.MakeCurrent(null);
} }
catch (Exception) { } catch (ContextException e)
{
Logger.Warning?.Print(LogClass.Ui, $"Failed to unbind OpenGL context: {e}");
}
_openGLContext?.Dispose(); _openGLContext?.Dispose();
} }
} }
} }