Compare commits

..

19 Commits

Author SHA1 Message Date
868919e101 misc: Update GtkSharp.Dependencies and speed up initial Windows build (#3128)
Update GtkSharp.Dependencies to fix between menu flickering and enable
the SkipInstallGtk in csproj to avoid downloading unused GTK3 install
locally.
2022-02-17 22:10:48 +01:00
9ca040c0ff Use ReadOnlySpan<byte> compiler optimization for static data (#3130) 2022-02-17 21:38:50 +01:00
7e9011673b Use a basic cubic interpolation for the audren upsampler (#3129)
Before, it was selecting nearest neighbour, which sounded terrible. This is likely temporary til the upsampling algorithm used by the switch is reversed.

Fixes bad audio in Skyward Sword HD.
2022-02-17 20:19:29 +01:00
741db8e43d amadeus: Fix PCMFloat datasource command v1 (#3127)
Really simple copy pasta error here.

Shouldn't affect anything as float support was added at the same REV as
datasource command v2.
2022-02-16 23:55:40 +01:00
3bd357045f Do not allow render targets not explicitly written by the fragment shader to be modified (#3063)
* Do not allow render targets not explicitly written by the fragment shader to be modified

* Shader cache version bump

* Remove blank lines

* Avoid redundant color mask updates

* HostShaderCacheEntry can be null

* Avoid more redundant glColorMask calls

* nit: Mask -> Masks

* Fix currentComponentMask

* More efficient way to update _currentComponentMasks
2022-02-16 23:15:39 +01:00
ab5d77c0c4 amadeus: Fix limiter correctness (#3126)
This fixes missing audio on Nintendo Switch Sports Online Play Test.
2022-02-16 21:38:45 +01:00
7bfb5f79b8 When copying linear textures, DMA should ignore region X/Y (#3121) 2022-02-16 11:13:45 +01:00
8cc2479825 Adjusting how deadzones are calculated (#3079)
* Making deadzones feel nice and smooth + adding rider files to .gitignore

* removing unnecessary parentheses and fixing possibility of divide by 0

* formatting :)

* fixing up ClampAxis

* fixing up ClampAxis
2022-02-16 11:06:52 +01:00
8f35345729 Use Enum and Delegate.CreateDelegate generic overloads (#3111)
* Use Enum generic overloads

* Remove EnumExtensions.cs

* Use Delegate.CreateDelegate generic overloads
2022-02-13 10:50:07 -03:00
ce71f9144e InstEmitMemory32: Literal loads always have word-aligned PC (#3104) 2022-02-11 17:51:03 -03:00
f861f0bca2 Fix missing geometry shader passthrough inputs (#3106)
* Fix missing geometry shader passthrough inputs

* Shader cache version bump
2022-02-11 19:52:20 +01:00
571496d243 Ship SoundIO library only for the specified runtime (#3103)
* Add RuntimeIdentifers properties

For Linux, Windows and OS X x86-64
This ensures that the SoundIO project gets this property when built as a subproject

* Address gdkchan's nit

Merge tags into one
2022-02-11 00:15:13 +01:00
c3c3914ed3 Add a limit on the number of uses a constant may have (#3097) 2022-02-09 17:42:47 -03:00
6dffe0fad4 misc: Make PID unsigned long instead of long (#3043) 2022-02-09 17:18:07 -03:00
86b37d0ff7 ARMeilleure: A32: Implement SHSUB8 and UHSUB8 (#3089)
* ARMeilleure: A32: Implement UHSUB8

* ARMeilleure: A32: Implement SHSUB8
2022-02-08 10:46:42 +01:00
863c581190 fix headless sdl2 option string (#3093) 2022-02-07 11:50:51 +01:00
5c3112aaeb Convert the bool to a lowercase string (#3080)
mesa_glthread doesn't accept PascalCase input
2022-02-06 12:52:39 -03:00
88d3ffb97c ARMeilleure: A32: Implement SHADD8 (#3086) 2022-02-06 12:25:45 -03:00
222b1ad7da ARMeilleure: OpCodeTable: Add CMN (RsReg) (#3087) 2022-02-06 02:01:05 +01:00
103 changed files with 579 additions and 330 deletions

3
.gitignore vendored
View File

@ -74,6 +74,9 @@ _TeamCity*
# DotCover is a Code Coverage Tool # DotCover is a Code Coverage Tool
*.dotCover *.dotCover
# Rider is a Visual Studio alternative
.idea/*
# NCrunch # NCrunch
*.ncrunch* *.ncrunch*
.*crunch*.local.xml .*crunch*.local.xml

View File

@ -9,13 +9,17 @@ namespace ARMeilleure.CodeGen.X86
{ {
static class X86Optimizer static class X86Optimizer
{ {
private const int MaxConstantUses = 10000;
public static void RunPass(ControlFlowGraph cfg) public static void RunPass(ControlFlowGraph cfg)
{ {
var constants = new Dictionary<ulong, Operand>(); var constants = new Dictionary<ulong, Operand>();
Operand GetConstantCopy(BasicBlock block, Operation operation, Operand source) Operand GetConstantCopy(BasicBlock block, Operation operation, Operand source)
{ {
if (!constants.TryGetValue(source.Value, out var constant)) // If the constant has many uses, we also force a new constant mov to be added, in order
// to avoid overflow of the counts field (that is limited to 16 bits).
if (!constants.TryGetValue(source.Value, out var constant) || constant.UsesCount > MaxConstantUses)
{ {
constant = Local(source.Type); constant = Local(source.Type);
@ -23,7 +27,7 @@ namespace ARMeilleure.CodeGen.X86
block.Operations.AddBefore(operation, copyOp); block.Operations.AddBefore(operation, copyOp);
constants.Add(source.Value, constant); constants[source.Value] = constant;
} }
return constant; return constant;

View File

@ -654,6 +654,7 @@ namespace ARMeilleure.Decoders
SetA32("<<<<000101101111xxxx11110001xxxx", InstName.Clz, InstEmit32.Clz, OpCode32AluReg.Create); SetA32("<<<<000101101111xxxx11110001xxxx", InstName.Clz, InstEmit32.Clz, OpCode32AluReg.Create);
SetA32("<<<<00110111xxxx0000xxxxxxxxxxxx", InstName.Cmn, InstEmit32.Cmn, OpCode32AluImm.Create); SetA32("<<<<00110111xxxx0000xxxxxxxxxxxx", InstName.Cmn, InstEmit32.Cmn, OpCode32AluImm.Create);
SetA32("<<<<00010111xxxx0000xxxxxxx0xxxx", InstName.Cmn, InstEmit32.Cmn, OpCode32AluRsImm.Create); SetA32("<<<<00010111xxxx0000xxxxxxx0xxxx", InstName.Cmn, InstEmit32.Cmn, OpCode32AluRsImm.Create);
SetA32("<<<<00010111xxxx0000xxxx0xx1xxxx", InstName.Cmn, InstEmit32.Cmn, OpCode32AluRsReg.Create);
SetA32("<<<<00110101xxxx0000xxxxxxxxxxxx", InstName.Cmp, InstEmit32.Cmp, OpCode32AluImm.Create); SetA32("<<<<00110101xxxx0000xxxxxxxxxxxx", InstName.Cmp, InstEmit32.Cmp, OpCode32AluImm.Create);
SetA32("<<<<00010101xxxx0000xxxxxxx0xxxx", InstName.Cmp, InstEmit32.Cmp, OpCode32AluRsImm.Create); SetA32("<<<<00010101xxxx0000xxxxxxx0xxxx", InstName.Cmp, InstEmit32.Cmp, OpCode32AluRsImm.Create);
SetA32("<<<<00010101xxxx0000xxxx0xx1xxxx", InstName.Cmp, InstEmit32.Cmp, OpCode32AluRsReg.Create); SetA32("<<<<00010101xxxx0000xxxx0xx1xxxx", InstName.Cmp, InstEmit32.Cmp, OpCode32AluRsReg.Create);
@ -732,6 +733,8 @@ namespace ARMeilleure.Decoders
SetA32("<<<<0000110xxxxxxxxxxxxx0xx1xxxx", InstName.Sbc, InstEmit32.Sbc, OpCode32AluRsReg.Create); SetA32("<<<<0000110xxxxxxxxxxxxx0xx1xxxx", InstName.Sbc, InstEmit32.Sbc, OpCode32AluRsReg.Create);
SetA32("<<<<0111101xxxxxxxxxxxxxx101xxxx", InstName.Sbfx, InstEmit32.Sbfx, OpCode32AluBf.Create); SetA32("<<<<0111101xxxxxxxxxxxxxx101xxxx", InstName.Sbfx, InstEmit32.Sbfx, OpCode32AluBf.Create);
SetA32("<<<<01110001xxxx1111xxxx0001xxxx", InstName.Sdiv, InstEmit32.Sdiv, OpCode32AluMla.Create); SetA32("<<<<01110001xxxx1111xxxx0001xxxx", InstName.Sdiv, InstEmit32.Sdiv, OpCode32AluMla.Create);
SetA32("<<<<01100011xxxxxxxx11111001xxxx", InstName.Shadd8, InstEmit32.Shadd8, OpCode32AluReg.Create);
SetA32("<<<<01100011xxxxxxxx11111111xxxx", InstName.Shsub8, InstEmit32.Shsub8, OpCode32AluReg.Create);
SetA32("<<<<00010000xxxxxxxxxxxx1xx0xxxx", InstName.Smla__, InstEmit32.Smla__, OpCode32AluMla.Create); SetA32("<<<<00010000xxxxxxxxxxxx1xx0xxxx", InstName.Smla__, InstEmit32.Smla__, OpCode32AluMla.Create);
SetA32("<<<<0000111xxxxxxxxxxxxx1001xxxx", InstName.Smlal, InstEmit32.Smlal, OpCode32AluUmull.Create); SetA32("<<<<0000111xxxxxxxxxxxxx1001xxxx", InstName.Smlal, InstEmit32.Smlal, OpCode32AluUmull.Create);
SetA32("<<<<00010100xxxxxxxxxxxx1xx0xxxx", InstName.Smlal__, InstEmit32.Smlal__, OpCode32AluUmull.Create); SetA32("<<<<00010100xxxxxxxxxxxx1xx0xxxx", InstName.Smlal__, InstEmit32.Smlal__, OpCode32AluUmull.Create);
@ -780,6 +783,7 @@ namespace ARMeilleure.Decoders
SetA32("<<<<0111111xxxxxxxxxxxxxx101xxxx", InstName.Ubfx, InstEmit32.Ubfx, OpCode32AluBf.Create); SetA32("<<<<0111111xxxxxxxxxxxxxx101xxxx", InstName.Ubfx, InstEmit32.Ubfx, OpCode32AluBf.Create);
SetA32("<<<<01110011xxxx1111xxxx0001xxxx", InstName.Udiv, InstEmit32.Udiv, OpCode32AluMla.Create); SetA32("<<<<01110011xxxx1111xxxx0001xxxx", InstName.Udiv, InstEmit32.Udiv, OpCode32AluMla.Create);
SetA32("<<<<01100111xxxxxxxx11111001xxxx", InstName.Uhadd8, InstEmit32.Uhadd8, OpCode32AluReg.Create); SetA32("<<<<01100111xxxxxxxx11111001xxxx", InstName.Uhadd8, InstEmit32.Uhadd8, OpCode32AluReg.Create);
SetA32("<<<<01100111xxxxxxxx11111111xxxx", InstName.Uhsub8, InstEmit32.Uhsub8, OpCode32AluReg.Create);
SetA32("<<<<00000100xxxxxxxxxxxx1001xxxx", InstName.Umaal, InstEmit32.Umaal, OpCode32AluUmull.Create); SetA32("<<<<00000100xxxxxxxxxxxx1001xxxx", InstName.Umaal, InstEmit32.Umaal, OpCode32AluUmull.Create);
SetA32("<<<<0000101xxxxxxxxxxxxx1001xxxx", InstName.Umlal, InstEmit32.Umlal, OpCode32AluUmull.Create); SetA32("<<<<0000101xxxxxxxxxxxxx1001xxxx", InstName.Umlal, InstEmit32.Umlal, OpCode32AluUmull.Create);
SetA32("<<<<0000100xxxxxxxxxxxxx1001xxxx", InstName.Umull, InstEmit32.Umull, OpCode32AluUmull.Create); SetA32("<<<<0000100xxxxxxxxxxxxx1001xxxx", InstName.Umull, InstEmit32.Umull, OpCode32AluUmull.Create);

View File

@ -1,13 +1,14 @@
// https://www.intel.com/content/dam/doc/white-paper/advanced-encryption-standard-new-instructions-set-paper.pdf // https://www.intel.com/content/dam/doc/white-paper/advanced-encryption-standard-new-instructions-set-paper.pdf
using ARMeilleure.State; using ARMeilleure.State;
using System;
namespace ARMeilleure.Instructions namespace ARMeilleure.Instructions
{ {
static class CryptoHelper static class CryptoHelper
{ {
#region "LookUp Tables" #region "LookUp Tables"
private static readonly byte[] _sBox = new byte[] private static ReadOnlySpan<byte> _sBox => new byte[]
{ {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
@ -27,7 +28,7 @@ namespace ARMeilleure.Instructions
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
}; };
private static readonly byte[] _invSBox = new byte[] private static ReadOnlySpan<byte> _invSBox => new byte[]
{ {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
@ -47,7 +48,7 @@ namespace ARMeilleure.Instructions
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
}; };
private static readonly byte[] _gfMul02 = new byte[] private static ReadOnlySpan<byte> _gfMul02 => new byte[]
{ {
0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e,
@ -67,7 +68,7 @@ namespace ARMeilleure.Instructions
0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5 0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5
}; };
private static readonly byte[] _gfMul03 = new byte[] private static ReadOnlySpan<byte> _gfMul03 => new byte[]
{ {
0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11, 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11,
0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21, 0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21,
@ -87,7 +88,7 @@ namespace ARMeilleure.Instructions
0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a 0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a
}; };
private static readonly byte[] _gfMul09 = new byte[] private static ReadOnlySpan<byte> _gfMul09 => new byte[]
{ {
0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77, 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7, 0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7,
@ -107,7 +108,7 @@ namespace ARMeilleure.Instructions
0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46 0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46
}; };
private static readonly byte[] _gfMul0B = new byte[] private static ReadOnlySpan<byte> _gfMul0B => new byte[]
{ {
0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69, 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69,
0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9, 0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9,
@ -127,7 +128,7 @@ namespace ARMeilleure.Instructions
0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3 0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3
}; };
private static readonly byte[] _gfMul0D = new byte[] private static ReadOnlySpan<byte> _gfMul0D => new byte[]
{ {
0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b, 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b,
0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b, 0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b,
@ -147,7 +148,7 @@ namespace ARMeilleure.Instructions
0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97 0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97
}; };
private static readonly byte[] _gfMul0E = new byte[] private static ReadOnlySpan<byte> _gfMul0E => new byte[]
{ {
0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a, 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a,
0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba, 0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba,
@ -167,12 +168,12 @@ namespace ARMeilleure.Instructions
0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d 0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d
}; };
private static readonly byte[] _srPerm = new byte[] private static ReadOnlySpan<byte> _srPerm => new byte[]
{ {
0, 13, 10, 7, 4, 1, 14, 11, 8, 5, 2, 15, 12, 9, 6, 3 0, 13, 10, 7, 4, 1, 14, 11, 8, 5, 2, 15, 12, 9, 6, 3
}; };
private static readonly byte[] _isrPerm = new byte[] private static ReadOnlySpan<byte> _isrPerm => new byte[]
{ {
0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11
}; };

View File

@ -387,6 +387,16 @@ namespace ARMeilleure.Instructions
EmitDiv(context, false); EmitDiv(context, false);
} }
public static void Shadd8(ArmEmitterContext context)
{
EmitHadd8(context, false);
}
public static void Shsub8(ArmEmitterContext context)
{
EmitHsub8(context, false);
}
public static void Ssat(ArmEmitterContext context) public static void Ssat(ArmEmitterContext context)
{ {
OpCode32Sat op = (OpCode32Sat)context.CurrOp; OpCode32Sat op = (OpCode32Sat)context.CurrOp;
@ -474,20 +484,12 @@ namespace ARMeilleure.Instructions
public static void Uhadd8(ArmEmitterContext context) public static void Uhadd8(ArmEmitterContext context)
{ {
OpCode32AluReg op = (OpCode32AluReg)context.CurrOp; EmitHadd8(context, true);
}
Operand m = GetIntA32(context, op.Rm); public static void Uhsub8(ArmEmitterContext context)
Operand n = GetIntA32(context, op.Rn); {
EmitHsub8(context, true);
Operand xor, res;
res = context.BitwiseAnd(m, n);
xor = context.BitwiseExclusiveOr(m, n);
xor = context.ShiftRightUI(xor, Const(1));
xor = context.BitwiseAnd(xor, Const(0x7F7F7F7Fu));
res = context.Add(res, xor);
SetIntA32(context, op.Rd, res);
} }
public static void Usat(ArmEmitterContext context) public static void Usat(ArmEmitterContext context)
@ -659,6 +661,71 @@ namespace ARMeilleure.Instructions
context.MarkLabel(lblEnd); context.MarkLabel(lblEnd);
} }
private static void EmitHadd8(ArmEmitterContext context, bool unsigned)
{
OpCode32AluReg op = (OpCode32AluReg)context.CurrOp;
Operand m = GetIntA32(context, op.Rm);
Operand n = GetIntA32(context, op.Rn);
Operand xor, res, carry;
// This relies on the equality x+y == ((x&y) << 1) + (x^y).
// Note that x^y always contains the LSB of the result.
// Since we want to calculate (x+y)/2, we can instead calculate (x&y) + ((x^y)>>1).
// We mask by 0x7F to remove the LSB so that it doesn't leak into the field below.
res = context.BitwiseAnd(m, n);
carry = context.BitwiseExclusiveOr(m, n);
xor = context.ShiftRightUI(carry, Const(1));
xor = context.BitwiseAnd(xor, Const(0x7F7F7F7Fu));
res = context.Add(res, xor);
if (!unsigned)
{
// Propagates the sign bit from (x^y)>>1 upwards by one.
carry = context.BitwiseAnd(carry, Const(0x80808080u));
res = context.BitwiseExclusiveOr(res, carry);
}
SetIntA32(context, op.Rd, res);
}
private static void EmitHsub8(ArmEmitterContext context, bool unsigned)
{
OpCode32AluReg op = (OpCode32AluReg)context.CurrOp;
Operand m = GetIntA32(context, op.Rm);
Operand n = GetIntA32(context, op.Rn);
Operand left, right, carry, res;
// This relies on the equality x-y == (x^y) - (((x^y)&y) << 1).
// Note that x^y always contains the LSB of the result.
// Since we want to calculate (x+y)/2, we can instead calculate ((x^y)>>1) - ((x^y)&y).
carry = context.BitwiseExclusiveOr(m, n);
left = context.ShiftRightUI(carry, Const(1));
right = context.BitwiseAnd(carry, m);
// We must now perform a partitioned subtraction.
// We can do this because minuend contains 7 bit fields.
// We use the extra bit in minuend as a bit to borrow from; we set this bit.
// We invert this bit at the end as this tells us if that bit was borrowed from.
res = context.BitwiseOr(left, Const(0x80808080));
res = context.Subtract(res, right);
res = context.BitwiseExclusiveOr(res, Const(0x80808080));
if (!unsigned)
{
// We then sign extend the result into this bit.
carry = context.BitwiseAnd(carry, Const(0x80808080));
res = context.BitwiseExclusiveOr(res, carry);
}
SetIntA32(context, op.Rd, res);
}
private static void EmitSat(ArmEmitterContext context, int intMin, int intMax) private static void EmitSat(ArmEmitterContext context, int intMin, int intMax)
{ {
OpCode32Sat op = (OpCode32Sat)context.CurrOp; OpCode32Sat op = (OpCode32Sat)context.CurrOp;

View File

@ -47,6 +47,20 @@ namespace ARMeilleure.Instructions
} }
} }
public static Operand GetIntA32AlignedPC(ArmEmitterContext context, int regIndex)
{
if (regIndex == RegisterAlias.Aarch32Pc)
{
OpCode32 op = (OpCode32)context.CurrOp;
return Const((int)(op.GetPc() & 0xfffffffc));
}
else
{
return Register(GetRegisterAlias(context.Mode, regIndex), RegisterType.Integer, OperandType.I32);
}
}
public static Operand GetVecA32(int regIndex) public static Operand GetVecA32(int regIndex)
{ {
return Register(regIndex, RegisterType.Vector, OperandType.V128); return Register(regIndex, RegisterType.Vector, OperandType.V128);

View File

@ -153,7 +153,7 @@ namespace ARMeilleure.Instructions
{ {
OpCode32Mem op = (OpCode32Mem)context.CurrOp; OpCode32Mem op = (OpCode32Mem)context.CurrOp;
Operand n = context.Copy(GetIntA32(context, op.Rn)); Operand n = context.Copy(GetIntA32AlignedPC(context, op.Rn));
Operand m = GetMemM(context, setCarry: false); Operand m = GetMemM(context, setCarry: false);
Operand temp = default; Operand temp = default;

View File

@ -80,6 +80,7 @@ namespace ARMeilleure.Instructions
Sbcs, Sbcs,
Sbfm, Sbfm,
Sdiv, Sdiv,
Shsub8,
Smaddl, Smaddl,
Smsubl, Smsubl,
Smulh, Smulh,
@ -516,6 +517,7 @@ namespace ARMeilleure.Instructions
Rsb, Rsb,
Rsc, Rsc,
Sbfx, Sbfx,
Shadd8,
Smla__, Smla__,
Smlal, Smlal,
Smlal__, Smlal__,
@ -545,6 +547,7 @@ namespace ARMeilleure.Instructions
Tst, Tst,
Ubfx, Ubfx,
Uhadd8, Uhadd8,
Uhsub8,
Umaal, Umaal,
Umlal, Umlal,
Umull, Umull,

View File

@ -824,7 +824,7 @@ namespace ARMeilleure.Instructions
return (ulong)(size - 1); return (ulong)(size - 1);
} }
private static readonly byte[] ClzNibbleTbl = { 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }; private static ReadOnlySpan<byte> ClzNibbleTbl => new byte[] { 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
public static ulong CountLeadingZeros(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.). public static ulong CountLeadingZeros(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
{ {

View File

@ -3,6 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -100,9 +100,11 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
for (int sampleIndex = 0; sampleIndex < context.SampleCount; sampleIndex++) for (int sampleIndex = 0; sampleIndex < context.SampleCount; sampleIndex++)
{ {
float inputSample = *((float*)inputBuffers[channelIndex] + sampleIndex); float rawInputSample = *((float*)inputBuffers[channelIndex] + sampleIndex);
float sampleInputMax = Math.Abs(inputSample * Parameter.InputGain); float inputSample = (rawInputSample / short.MaxValue) * Parameter.InputGain;
float sampleInputMax = Math.Abs(inputSample);
float inputCoefficient = Parameter.ReleaseCoefficient; float inputCoefficient = Parameter.ReleaseCoefficient;
@ -131,7 +133,9 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
ref float delayedSample = ref state.DelayedSampleBuffer[channelIndex * Parameter.DelayBufferSampleCountMax + state.DelayedSampleBufferPosition[channelIndex]]; ref float delayedSample = ref state.DelayedSampleBuffer[channelIndex * Parameter.DelayBufferSampleCountMax + state.DelayedSampleBufferPosition[channelIndex]];
*((float*)outputBuffers[channelIndex] + sampleIndex) = delayedSample * state.CompressionGain[channelIndex] * Parameter.OutputGain; float outputSample = delayedSample * state.CompressionGain[channelIndex] * Parameter.OutputGain;
*((float*)outputBuffers[channelIndex] + sampleIndex) = outputSample * short.MaxValue;
delayedSample = inputSample; delayedSample = inputSample;

View File

@ -111,9 +111,11 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
for (int sampleIndex = 0; sampleIndex < context.SampleCount; sampleIndex++) for (int sampleIndex = 0; sampleIndex < context.SampleCount; sampleIndex++)
{ {
float inputSample = *((float*)inputBuffers[channelIndex] + sampleIndex); float rawInputSample = *((float*)inputBuffers[channelIndex] + sampleIndex);
float sampleInputMax = Math.Abs(inputSample * Parameter.InputGain); float inputSample = (rawInputSample / short.MaxValue) * Parameter.InputGain;
float sampleInputMax = Math.Abs(inputSample);
float inputCoefficient = Parameter.ReleaseCoefficient; float inputCoefficient = Parameter.ReleaseCoefficient;
@ -142,7 +144,9 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
ref float delayedSample = ref state.DelayedSampleBuffer[channelIndex * Parameter.DelayBufferSampleCountMax + state.DelayedSampleBufferPosition[channelIndex]]; ref float delayedSample = ref state.DelayedSampleBuffer[channelIndex * Parameter.DelayBufferSampleCountMax + state.DelayedSampleBufferPosition[channelIndex]];
*((float*)outputBuffers[channelIndex] + sampleIndex) = delayedSample * state.CompressionGain[channelIndex] * Parameter.OutputGain; float outputSample = delayedSample * state.CompressionGain[channelIndex] * Parameter.OutputGain;
*((float*)outputBuffers[channelIndex] + sampleIndex) = outputSample * short.MaxValue;
delayedSample = inputSample; delayedSample = inputSample;

View File

@ -76,7 +76,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
DataSourceHelper.WaveBufferInformation info = new DataSourceHelper.WaveBufferInformation DataSourceHelper.WaveBufferInformation info = new DataSourceHelper.WaveBufferInformation
{ {
SourceSampleRate = SampleRate, SourceSampleRate = SampleRate,
SampleFormat = SampleFormat.PcmInt16, SampleFormat = SampleFormat.PcmFloat,
Pitch = Pitch, Pitch = Pitch,
DecodingBehaviour = DecodingBehaviour, DecodingBehaviour = DecodingBehaviour,
ExtraParameter = 0, ExtraParameter = 0,

View File

@ -600,19 +600,42 @@ namespace Ryujinx.Audio.Renderer.Dsp
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ResampleForUpsampler(Span<float> outputBuffer, ReadOnlySpan<float> inputBuffer, float ratio, ref float fraction, int sampleCount) public static void ResampleForUpsampler(Span<float> outputBuffer, ReadOnlySpan<float> inputBuffer, float ratio, ref float fraction, int sampleCount)
{ {
// TODO: use a bandwidth filter to have better resampling. // Currently a simple cubic interpolation, assuming duplicated values at edges.
// TODO: Discover and use algorithm that the switch uses.
int inputBufferIndex = 0; int inputBufferIndex = 0;
int maxIndex = inputBuffer.Length - 1;
int cubicEnd = inputBuffer.Length - 3;
for (int i = 0; i < sampleCount; i++) for (int i = 0; i < sampleCount; i++)
{ {
float outputData = inputBuffer[inputBufferIndex]; float s0, s1, s2, s3;
if (fraction > 1.0f) s1 = inputBuffer[inputBufferIndex];
if (inputBufferIndex == 0 || inputBufferIndex > cubicEnd)
{ {
outputData = inputBuffer[inputBufferIndex + 1]; // Clamp interplation values at the ends of the input buffer.
s0 = inputBuffer[Math.Max(0, inputBufferIndex - 1)];
s2 = inputBuffer[Math.Min(maxIndex, inputBufferIndex + 1)];
s3 = inputBuffer[Math.Min(maxIndex, inputBufferIndex + 2)];
}
else
{
s0 = inputBuffer[inputBufferIndex - 1];
s2 = inputBuffer[inputBufferIndex + 1];
s3 = inputBuffer[inputBufferIndex + 2];
} }
outputBuffer[i] = outputData; float a = s3 - s2 - s0 + s1;
float b = s0 - s1 - a;
float c = s2 - s0;
float d = s1;
float f2 = fraction * fraction;
float f3 = f2 * fraction;
outputBuffer[i] = a * f3 + b * f2 + c * fraction + d;
fraction += ratio; fraction += ratio;
inputBufferIndex += (int)MathF.Truncate(fraction); inputBufferIndex += (int)MathF.Truncate(fraction);

View File

@ -37,6 +37,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.State
DectectorAverage.AsSpan().Fill(0.0f); DectectorAverage.AsSpan().Fill(0.0f);
CompressionGain.AsSpan().Fill(1.0f); CompressionGain.AsSpan().Fill(1.0f);
DelayedSampleBufferPosition.AsSpan().Fill(0); DelayedSampleBufferPosition.AsSpan().Fill(0);
DelayedSampleBuffer.AsSpan().Fill(0.0f);
UpdateParameter(ref parameter); UpdateParameter(ref parameter);
} }

View File

@ -558,7 +558,16 @@ namespace Ryujinx.Audio.Renderer.Server
if (_rendererContext.BehaviourContext.IsEffectInfoVersion2Supported()) if (_rendererContext.BehaviourContext.IsEffectInfoVersion2Supported())
{ {
Memory<EffectResultState> dspResultState = _effectContext.GetDspStateMemory(effectId); Memory<EffectResultState> dspResultState;
if (effect.Parameter.StatisticsEnabled)
{
dspResultState = _effectContext.GetDspStateMemory(effectId);
}
else
{
dspResultState = Memory<EffectResultState>.Empty;
}
_commandBuffer.GenerateLimiterEffectVersion2(bufferOffset, effect.Parameter, effect.State, dspResultState, effect.IsEnabled, workBuffer, nodeId); _commandBuffer.GenerateLimiterEffectVersion2(bufferOffset, effect.Parameter, effect.State, dspResultState, effect.IsEnabled, workBuffer, nodeId);
} }

View File

@ -1,12 +0,0 @@
using System;
namespace Ryujinx.Common
{
public static class EnumExtensions
{
public static T[] GetValues<T>()
{
return (T[])Enum.GetValues(typeof(T));
}
}
}

View File

@ -6,7 +6,7 @@ namespace Ryujinx.Common.GraphicsDriver
{ {
public static void ToggleOGLThreading(bool enabled) public static void ToggleOGLThreading(bool enabled)
{ {
Environment.SetEnvironmentVariable("mesa_glthread", enabled.ToString()); Environment.SetEnvironmentVariable("mesa_glthread", enabled.ToString().ToLower());
Environment.SetEnvironmentVariable("__GL_THREADED_OPTIMIZATIONS", enabled ? "1" : "0"); Environment.SetEnvironmentVariable("__GL_THREADED_OPTIMIZATIONS", enabled ? "1" : "0");
try try

View File

@ -94,7 +94,7 @@ namespace Ryujinx.Common.Logging
static Logger() static Logger()
{ {
m_EnabledClasses = new bool[Enum.GetNames(typeof(LogClass)).Length]; m_EnabledClasses = new bool[Enum.GetNames<LogClass>().Length];
for (int index = 0; index < m_EnabledClasses.Length; index++) for (int index = 0; index < m_EnabledClasses.Length; index++)
{ {

View File

@ -1,8 +1,10 @@
using System;
namespace Ryujinx.Common namespace Ryujinx.Common
{ {
public static class BitUtils public static class BitUtils
{ {
private static readonly byte[] ClzNibbleTbl = { 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }; private static ReadOnlySpan<byte> ClzNibbleTbl => new byte[] { 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
public static uint AlignUp(uint value, int size) public static uint AlignUp(uint value, int size)
{ {

View File

@ -43,7 +43,7 @@ namespace Ryujinx.Common
Prime32_1 Prime32_1
}; };
private static readonly byte[] Xxh3KSecret = new byte[] private static ReadOnlySpan<byte> Xxh3KSecret => new byte[]
{ {
0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c, 0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c,
0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f, 0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f,

View File

@ -20,7 +20,7 @@ namespace Ryujinx.Graphics.GAL
BufferHandle CreateBuffer(int size); BufferHandle CreateBuffer(int size);
IProgram CreateProgram(IShader[] shaders); IProgram CreateProgram(IShader[] shaders, ShaderInfo info);
ISampler CreateSampler(SamplerCreateInfo info); ISampler CreateSampler(SamplerCreateInfo info);
ITexture CreateTexture(TextureCreateInfo info, float scale); ITexture CreateTexture(TextureCreateInfo info, float scale);
@ -33,7 +33,7 @@ namespace Ryujinx.Graphics.GAL
Capabilities GetCapabilities(); Capabilities GetCapabilities();
IProgram LoadProgramBinary(byte[] programBinary); IProgram LoadProgramBinary(byte[] programBinary, bool hasFragmentShader, ShaderInfo info);
void SetBufferData(BufferHandle buffer, int offset, ReadOnlySpan<byte> data); void SetBufferData(BufferHandle buffer, int offset, ReadOnlySpan<byte> data);

View File

@ -5,17 +5,21 @@
public ThreadedProgram Threaded { get; set; } public ThreadedProgram Threaded { get; set; }
private byte[] _data; private byte[] _data;
private bool _hasFragmentShader;
private ShaderInfo _info;
public BinaryProgramRequest(ThreadedProgram program, byte[] data) public BinaryProgramRequest(ThreadedProgram program, byte[] data, bool hasFragmentShader, ShaderInfo info)
{ {
Threaded = program; Threaded = program;
_data = data; _data = data;
_hasFragmentShader = hasFragmentShader;
_info = info;
} }
public IProgram Create(IRenderer renderer) public IProgram Create(IRenderer renderer)
{ {
return renderer.LoadProgramBinary(_data); return renderer.LoadProgramBinary(_data, _hasFragmentShader, _info);
} }
} }
} }

View File

@ -7,12 +7,14 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources.Programs
public ThreadedProgram Threaded { get; set; } public ThreadedProgram Threaded { get; set; }
private IShader[] _shaders; private IShader[] _shaders;
private ShaderInfo _info;
public SourceProgramRequest(ThreadedProgram program, IShader[] shaders) public SourceProgramRequest(ThreadedProgram program, IShader[] shaders, ShaderInfo info)
{ {
Threaded = program; Threaded = program;
_shaders = shaders; _shaders = shaders;
_info = info;
} }
public IProgram Create(IRenderer renderer) public IProgram Create(IRenderer renderer)
@ -24,7 +26,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources.Programs
return threaded?.Base; return threaded?.Base;
}).ToArray(); }).ToArray();
return renderer.CreateProgram(shaders); return renderer.CreateProgram(shaders, _info);
} }
} }
} }

View File

@ -268,10 +268,10 @@ namespace Ryujinx.Graphics.GAL.Multithreading
return handle; return handle;
} }
public IProgram CreateProgram(IShader[] shaders) public IProgram CreateProgram(IShader[] shaders, ShaderInfo info)
{ {
var program = new ThreadedProgram(this); var program = new ThreadedProgram(this);
SourceProgramRequest request = new SourceProgramRequest(program, shaders); SourceProgramRequest request = new SourceProgramRequest(program, shaders, info);
Programs.Add(request); Programs.Add(request);
New<CreateProgramCommand>().Set(Ref((IProgramRequest)request)); New<CreateProgramCommand>().Set(Ref((IProgramRequest)request));
@ -355,11 +355,11 @@ namespace Ryujinx.Graphics.GAL.Multithreading
_baseRenderer.Initialize(logLevel); _baseRenderer.Initialize(logLevel);
} }
public IProgram LoadProgramBinary(byte[] programBinary) public IProgram LoadProgramBinary(byte[] programBinary, bool hasFragmentShader, ShaderInfo info)
{ {
var program = new ThreadedProgram(this); var program = new ThreadedProgram(this);
BinaryProgramRequest request = new BinaryProgramRequest(program, programBinary); BinaryProgramRequest request = new BinaryProgramRequest(program, programBinary, hasFragmentShader, info);
Programs.Add(request); Programs.Add(request);
New<CreateProgramCommand>().Set(Ref((IProgramRequest)request)); New<CreateProgramCommand>().Set(Ref((IProgramRequest)request));

View File

@ -0,0 +1,12 @@
namespace Ryujinx.Graphics.GAL
{
public struct ShaderInfo
{
public int FragmentOutputMap { get; }
public ShaderInfo(int fragmentOutputMap)
{
FragmentOutputMap = fragmentOutputMap;
}
}
}

View File

@ -85,9 +85,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
} }
int alignWidth = Constants.StrideAlignment / bpp; int alignWidth = Constants.StrideAlignment / bpp;
return tex.RegionX == 0 && return stride / bpp == BitUtils.AlignUp(xCount, alignWidth);
tex.RegionY == 0 &&
stride / bpp == BitUtils.AlignUp(xCount, alignWidth);
} }
else else
{ {
@ -161,6 +159,20 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
var dst = Unsafe.As<uint, DmaTexture>(ref _state.State.SetDstBlockSize); var dst = Unsafe.As<uint, DmaTexture>(ref _state.State.SetDstBlockSize);
var src = Unsafe.As<uint, DmaTexture>(ref _state.State.SetSrcBlockSize); var src = Unsafe.As<uint, DmaTexture>(ref _state.State.SetSrcBlockSize);
int srcRegionX = 0, srcRegionY = 0, dstRegionX = 0, dstRegionY = 0;
if (!srcLinear)
{
srcRegionX = src.RegionX;
srcRegionY = src.RegionY;
}
if (!dstLinear)
{
dstRegionX = dst.RegionX;
dstRegionY = dst.RegionY;
}
int srcStride = (int)_state.State.PitchIn; int srcStride = (int)_state.State.PitchIn;
int dstStride = (int)_state.State.PitchOut; int dstStride = (int)_state.State.PitchOut;
@ -182,8 +194,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
dst.MemoryLayout.UnpackGobBlocksInZ(), dst.MemoryLayout.UnpackGobBlocksInZ(),
dstBpp); dstBpp);
(int srcBaseOffset, int srcSize) = srcCalculator.GetRectangleRange(src.RegionX, src.RegionY, xCount, yCount); (int srcBaseOffset, int srcSize) = srcCalculator.GetRectangleRange(srcRegionX, srcRegionY, xCount, yCount);
(int dstBaseOffset, int dstSize) = dstCalculator.GetRectangleRange(dst.RegionX, dst.RegionY, xCount, yCount); (int dstBaseOffset, int dstSize) = dstCalculator.GetRectangleRange(dstRegionX, dstRegionY, xCount, yCount);
if (srcLinear && srcStride < 0) if (srcLinear && srcStride < 0)
{ {
@ -272,13 +284,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
for (int y = 0; y < yCount; y++) for (int y = 0; y < yCount; y++)
{ {
srcCalculator.SetY(src.RegionY + y); srcCalculator.SetY(srcRegionY + y);
dstCalculator.SetY(dst.RegionY + y); dstCalculator.SetY(dstRegionY + y);
for (int x = 0; x < xCount; x++) for (int x = 0; x < xCount; x++)
{ {
int srcOffset = srcCalculator.GetOffset(src.RegionX + x); int srcOffset = srcCalculator.GetOffset(srcRegionX + x);
int dstOffset = dstCalculator.GetOffset(dst.RegionX + x); int dstOffset = dstCalculator.GetOffset(dstRegionX + x);
*(T*)(dstBase + dstOffset) = *(T*)(srcBase + srcOffset); *(T*)(dstBase + dstOffset) = *(T*)(srcBase + srcOffset);
} }

View File

@ -112,7 +112,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
_ilGen.Emit(OpCodes.Ret); _ilGen.Emit(OpCodes.Ret);
} }
return (MacroExecute)_meth.CreateDelegate(typeof(MacroExecute)); return _meth.CreateDelegate<MacroExecute>();
} }
/// <summary> /// <summary>

View File

@ -77,7 +77,7 @@ namespace Ryujinx.Graphics.Gpu
/// <summary> /// <summary>
/// Registry with physical memories that can be used with this GPU context, keyed by owner process ID. /// Registry with physical memories that can be used with this GPU context, keyed by owner process ID.
/// </summary> /// </summary>
internal ConcurrentDictionary<long, PhysicalMemory> PhysicalMemoryRegistry { get; } internal ConcurrentDictionary<ulong, PhysicalMemory> PhysicalMemoryRegistry { get; }
/// <summary> /// <summary>
/// Host hardware capabilities. /// Host hardware capabilities.
@ -126,7 +126,7 @@ namespace Ryujinx.Graphics.Gpu
DeferredActions = new Queue<Action>(); DeferredActions = new Queue<Action>();
PhysicalMemoryRegistry = new ConcurrentDictionary<long, PhysicalMemory>(); PhysicalMemoryRegistry = new ConcurrentDictionary<ulong, PhysicalMemory>();
} }
/// <summary> /// <summary>
@ -144,7 +144,7 @@ namespace Ryujinx.Graphics.Gpu
/// <param name="pid">ID of the process that owns the memory manager</param> /// <param name="pid">ID of the process that owns the memory manager</param>
/// <returns>The memory manager</returns> /// <returns>The memory manager</returns>
/// <exception cref="ArgumentException">Thrown when <paramref name="pid"/> is invalid</exception> /// <exception cref="ArgumentException">Thrown when <paramref name="pid"/> is invalid</exception>
public MemoryManager CreateMemoryManager(long pid) public MemoryManager CreateMemoryManager(ulong pid)
{ {
if (!PhysicalMemoryRegistry.TryGetValue(pid, out var physicalMemory)) if (!PhysicalMemoryRegistry.TryGetValue(pid, out var physicalMemory))
{ {
@ -160,7 +160,7 @@ namespace Ryujinx.Graphics.Gpu
/// <param name="pid">ID of the process that owns <paramref name="cpuMemory"/></param> /// <param name="pid">ID of the process that owns <paramref name="cpuMemory"/></param>
/// <param name="cpuMemory">Virtual memory owned by the process</param> /// <param name="cpuMemory">Virtual memory owned by the process</param>
/// <exception cref="ArgumentException">Thrown if <paramref name="pid"/> was already registered</exception> /// <exception cref="ArgumentException">Thrown if <paramref name="pid"/> was already registered</exception>
public void RegisterProcess(long pid, Cpu.IVirtualMemoryManagerTracked cpuMemory) public void RegisterProcess(ulong pid, Cpu.IVirtualMemoryManagerTracked cpuMemory)
{ {
var physicalMemory = new PhysicalMemory(this, cpuMemory); var physicalMemory = new PhysicalMemory(this, cpuMemory);
if (!PhysicalMemoryRegistry.TryAdd(pid, physicalMemory)) if (!PhysicalMemoryRegistry.TryAdd(pid, physicalMemory))
@ -175,7 +175,7 @@ namespace Ryujinx.Graphics.Gpu
/// Unregisters a process, indicating that its memory will no longer be used, and that caches can be freed. /// Unregisters a process, indicating that its memory will no longer be used, and that caches can be freed.
/// </summary> /// </summary>
/// <param name="pid">ID of the process</param> /// <param name="pid">ID of the process</param>
public void UnregisterProcess(long pid) public void UnregisterProcess(ulong pid)
{ {
if (PhysicalMemoryRegistry.TryRemove(pid, out var physicalMemory)) if (PhysicalMemoryRegistry.TryRemove(pid, out var physicalMemory))
{ {

View File

@ -77,7 +77,8 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition
programInfo.Images.Count, programInfo.Images.Count,
programInfo.UsesInstanceId, programInfo.UsesInstanceId,
programInfo.UsesRtLayer, programInfo.UsesRtLayer,
programInfo.ClipDistancesWritten); programInfo.ClipDistancesWritten,
programInfo.FragmentOutputMap);
CBuffers = programInfo.CBuffers.ToArray(); CBuffers = programInfo.CBuffers.ToArray();
SBuffers = programInfo.SBuffers.ToArray(); SBuffers = programInfo.SBuffers.ToArray();
Textures = programInfo.Textures.ToArray(); Textures = programInfo.Textures.ToArray();
@ -97,7 +98,8 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition
Images, Images,
Header.UseFlags.HasFlag(UseFlags.InstanceId), Header.UseFlags.HasFlag(UseFlags.InstanceId),
Header.UseFlags.HasFlag(UseFlags.RtLayer), Header.UseFlags.HasFlag(UseFlags.RtLayer),
Header.ClipDistancesWritten); Header.ClipDistancesWritten,
Header.FragmentOutputMap);
} }
/// <summary> /// <summary>

View File

@ -26,7 +26,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition
/// <summary> /// <summary>
/// Host shader entry header used for binding information. /// Host shader entry header used for binding information.
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1, Size = 0x14)] [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 0x18)]
struct HostShaderCacheEntryHeader struct HostShaderCacheEntryHeader
{ {
/// <summary> /// <summary>
@ -70,6 +70,11 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition
/// </summary> /// </summary>
public byte Reserved; public byte Reserved;
/// <summary>
/// Mask of components written by the fragment shader stage.
/// </summary>
public int FragmentOutputMap;
/// <summary> /// <summary>
/// Create a new host shader cache entry header. /// Create a new host shader cache entry header.
/// </summary> /// </summary>
@ -78,6 +83,8 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition
/// <param name="texturesCount">Count of texture descriptors</param> /// <param name="texturesCount">Count of texture descriptors</param>
/// <param name="imagesCount">Count of image descriptors</param> /// <param name="imagesCount">Count of image descriptors</param>
/// <param name="usesInstanceId">Set to true if the shader uses instance id</param> /// <param name="usesInstanceId">Set to true if the shader uses instance id</param>
/// <param name="clipDistancesWritten">Mask of clip distances that are written to on the shader</param>
/// <param name="fragmentOutputMap">Mask of components written by the fragment shader stage</param>
public HostShaderCacheEntryHeader( public HostShaderCacheEntryHeader(
int cBuffersCount, int cBuffersCount,
int sBuffersCount, int sBuffersCount,
@ -85,13 +92,15 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition
int imagesCount, int imagesCount,
bool usesInstanceId, bool usesInstanceId,
bool usesRtLayer, bool usesRtLayer,
byte clipDistancesWritten) : this() byte clipDistancesWritten,
int fragmentOutputMap) : this()
{ {
CBuffersCount = cBuffersCount; CBuffersCount = cBuffersCount;
SBuffersCount = sBuffersCount; SBuffersCount = sBuffersCount;
TexturesCount = texturesCount; TexturesCount = texturesCount;
ImagesCount = imagesCount; ImagesCount = imagesCount;
ClipDistancesWritten = clipDistancesWritten; ClipDistancesWritten = clipDistancesWritten;
FragmentOutputMap = fragmentOutputMap;
InUse = true; InUse = true;
UseFlags = usesInstanceId ? UseFlags.InstanceId : UseFlags.None; UseFlags = usesInstanceId ? UseFlags.InstanceId : UseFlags.None;

View File

@ -40,7 +40,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// <summary> /// <summary>
/// Version of the codegen (to be changed when codegen or guest format change). /// Version of the codegen (to be changed when codegen or guest format change).
/// </summary> /// </summary>
private const ulong ShaderCodeGenVersion = 3012; private const ulong ShaderCodeGenVersion = 3063;
// Progress reporting helpers // Progress reporting helpers
private volatile int _shaderCount; private volatile int _shaderCount;
@ -188,7 +188,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
{ {
hostShaderEntries = HostShaderCacheEntry.Parse(hostProgramBinary, out ReadOnlySpan<byte> hostProgramBinarySpan); hostShaderEntries = HostShaderCacheEntry.Parse(hostProgramBinary, out ReadOnlySpan<byte> hostProgramBinarySpan);
hostProgramBinary = hostProgramBinarySpan.ToArray(); hostProgramBinary = hostProgramBinarySpan.ToArray();
hostProgram = _context.Renderer.LoadProgramBinary(hostProgramBinary); hostProgram = _context.Renderer.LoadProgramBinary(hostProgramBinary, false, new ShaderInfo(-1));
} }
ShaderCompileTask task = new ShaderCompileTask(taskDoneEvent); ShaderCompileTask task = new ShaderCompileTask(taskDoneEvent);
@ -252,7 +252,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
// Compile shader and create program as the shader program binary got invalidated. // Compile shader and create program as the shader program binary got invalidated.
shader.HostShader = _context.Renderer.CompileShader(ShaderStage.Compute, program.Code); shader.HostShader = _context.Renderer.CompileShader(ShaderStage.Compute, program.Code);
hostProgram = _context.Renderer.CreateProgram(new IShader[] { shader.HostShader }); hostProgram = _context.Renderer.CreateProgram(new IShader[] { shader.HostShader }, new ShaderInfo(-1));
task.OnCompiled(hostProgram, (bool isNewProgramValid, ShaderCompileTask task) => task.OnCompiled(hostProgram, (bool isNewProgramValid, ShaderCompileTask task) =>
{ {
@ -303,7 +303,18 @@ namespace Ryujinx.Graphics.Gpu.Shader
{ {
hostShaderEntries = HostShaderCacheEntry.Parse(hostProgramBinary, out ReadOnlySpan<byte> hostProgramBinarySpan); hostShaderEntries = HostShaderCacheEntry.Parse(hostProgramBinary, out ReadOnlySpan<byte> hostProgramBinarySpan);
hostProgramBinary = hostProgramBinarySpan.ToArray(); hostProgramBinary = hostProgramBinarySpan.ToArray();
hostProgram = _context.Renderer.LoadProgramBinary(hostProgramBinary);
bool hasFragmentShader = false;
int fragmentOutputMap = -1;
int fragmentIndex = (int)ShaderStage.Fragment - 1;
if (hostShaderEntries[fragmentIndex] != null && hostShaderEntries[fragmentIndex].Header.InUse)
{
hasFragmentShader = true;
fragmentOutputMap = hostShaderEntries[fragmentIndex].Header.FragmentOutputMap;
}
hostProgram = _context.Renderer.LoadProgramBinary(hostProgramBinary, hasFragmentShader, new ShaderInfo(fragmentOutputMap));
} }
ShaderCompileTask task = new ShaderCompileTask(taskDoneEvent); ShaderCompileTask task = new ShaderCompileTask(taskDoneEvent);
@ -426,7 +437,15 @@ namespace Ryujinx.Graphics.Gpu.Shader
hostShaders.Add(hostShader); hostShaders.Add(hostShader);
} }
hostProgram = _context.Renderer.CreateProgram(hostShaders.ToArray()); int fragmentIndex = (int)ShaderStage.Fragment - 1;
int fragmentOutputMap = -1;
if (shaders[fragmentIndex] != null)
{
fragmentOutputMap = shaders[fragmentIndex].Info.FragmentOutputMap;
}
hostProgram = _context.Renderer.CreateProgram(hostShaders.ToArray(), new ShaderInfo(fragmentOutputMap));
task.OnCompiled(hostProgram, (bool isNewProgramValid, ShaderCompileTask task) => task.OnCompiled(hostProgram, (bool isNewProgramValid, ShaderCompileTask task) =>
{ {
@ -617,7 +636,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
shader.HostShader = _context.Renderer.CompileShader(ShaderStage.Compute, shader.Program.Code); shader.HostShader = _context.Renderer.CompileShader(ShaderStage.Compute, shader.Program.Code);
IProgram hostProgram = _context.Renderer.CreateProgram(new IShader[] { shader.HostShader }); IProgram hostProgram = _context.Renderer.CreateProgram(new IShader[] { shader.HostShader }, new ShaderInfo(-1));
cpShader = new ShaderBundle(hostProgram, shader); cpShader = new ShaderBundle(hostProgram, shader);
@ -755,7 +774,15 @@ namespace Ryujinx.Graphics.Gpu.Shader
hostShaders.Add(hostShader); hostShaders.Add(hostShader);
} }
IProgram hostProgram = _context.Renderer.CreateProgram(hostShaders.ToArray()); int fragmentIndex = (int)ShaderStage.Fragment - 1;
int fragmentOutputMap = -1;
if (shaders[fragmentIndex] != null)
{
fragmentOutputMap = shaders[fragmentIndex].Info.FragmentOutputMap;
}
IProgram hostProgram = _context.Renderer.CreateProgram(hostShaders.ToArray(), new ShaderInfo(fragmentOutputMap));
gpShaders = new ShaderBundle(hostProgram, shaders); gpShaders = new ShaderBundle(hostProgram, shaders);

View File

@ -122,7 +122,7 @@ namespace Ryujinx.Graphics.Gpu
/// <param name="userObj">User defined object passed to the release callback</param> /// <param name="userObj">User defined object passed to the release callback</param>
/// <exception cref="ArgumentException">Thrown when <paramref name="pid"/> is invalid</exception> /// <exception cref="ArgumentException">Thrown when <paramref name="pid"/> is invalid</exception>
public void EnqueueFrameThreadSafe( public void EnqueueFrameThreadSafe(
long pid, ulong pid,
ulong address, ulong address,
int width, int width,
int height, int height,

View File

@ -118,7 +118,7 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg.H264
} }
// ZigZag LUTs from libavcodec. // ZigZag LUTs from libavcodec.
private static readonly byte[] ZigZagDirect = new byte[] private static ReadOnlySpan<byte> ZigZagDirect => new byte[]
{ {
0, 1, 8, 16, 9, 2, 3, 10, 0, 1, 8, 16, 9, 2, 3, 10,
17, 24, 32, 25, 18, 11, 4, 5, 17, 24, 32, 25, 18, 11, 4, 5,
@ -130,7 +130,7 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg.H264
53, 60, 61, 54, 47, 55, 62, 63 53, 60, 61, 54, 47, 55, 62, 63
}; };
private static readonly byte[] ZigZagScan = new byte[] private static ReadOnlySpan<byte> ZigZagScan => new byte[]
{ {
0 + 0 * 4, 1 + 0 * 4, 0 + 1 * 4, 0 + 2 * 4, 0 + 0 * 4, 1 + 0 * 4, 0 + 1 * 4, 0 + 2 * 4,
1 + 1 * 4, 2 + 0 * 4, 3 + 0 * 4, 2 + 1 * 4, 1 + 1 * 4, 2 + 0 * 4, 3 + 0 * 4, 2 + 1 * 4,
@ -140,7 +140,7 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg.H264
private static void WriteScalingList(ref H264BitStreamWriter writer, IArray<byte> list) private static void WriteScalingList(ref H264BitStreamWriter writer, IArray<byte> list)
{ {
byte[] scan = list.Length == 16 ? ZigZagScan : ZigZagDirect; ReadOnlySpan<byte> scan = list.Length == 16 ? ZigZagScan : ZigZagDirect;
int lastScale = 8; int lastScale = 8;

View File

@ -15,7 +15,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
public ISurface CreateSurface(int width, int height) => new Surface(width, height); public ISurface CreateSurface(int width, int height) => new Surface(width, height);
private static readonly byte[] LiteralToFilter = new byte[] private static ReadOnlySpan<byte> LiteralToFilter => new byte[]
{ {
Constants.EightTapSmooth, Constants.EightTapSmooth,
Constants.EightTap, Constants.EightTap,

View File

@ -1,5 +1,6 @@
using Ryujinx.Graphics.Nvdec.Vp9.Common; using Ryujinx.Graphics.Nvdec.Vp9.Common;
using Ryujinx.Graphics.Nvdec.Vp9.Types; using Ryujinx.Graphics.Nvdec.Vp9.Types;
using System;
using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.IntraPred; using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.IntraPred;
namespace Ryujinx.Graphics.Nvdec.Vp9 namespace Ryujinx.Graphics.Nvdec.Vp9
@ -24,7 +25,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private const int NeedAbove = 1 << 2; private const int NeedAbove = 1 << 2;
private const int NeedAboveRight = 1 << 3; private const int NeedAboveRight = 1 << 3;
private static readonly byte[] ExtendModes = new byte[] private static ReadOnlySpan<byte> ExtendModes => new byte[]
{ {
NeedAbove | NeedLeft, // DC NeedAbove | NeedLeft, // DC
NeedAbove, // V NeedAbove, // V

View File

@ -10,7 +10,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public short Row; public short Row;
public short Col; public short Col;
private static readonly byte[] LogInBase2 = new byte[] private static ReadOnlySpan<byte> LogInBase2 => new byte[]
{ {
0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,

View File

@ -11,7 +11,7 @@ namespace Ryujinx.Graphics.OpenGL
static FormatTable() static FormatTable()
{ {
int tableSize = Enum.GetNames(typeof(Format)).Length; int tableSize = Enum.GetNames<Format>().Length;
Table = new FormatInfo[tableSize]; Table = new FormatInfo[tableSize];
TableImage = new SizedInternalFormat[tableSize]; TableImage = new SizedInternalFormat[tableSize];

View File

@ -53,7 +53,9 @@ namespace Ryujinx.Graphics.OpenGL
private ClipOrigin _clipOrigin; private ClipOrigin _clipOrigin;
private ClipDepthMode _clipDepthMode; private ClipDepthMode _clipDepthMode;
private readonly uint[] _componentMasks; private uint _fragmentOutputMap;
private uint _componentMasks;
private uint _currentComponentMasks;
private uint _scissorEnables; private uint _scissorEnables;
@ -73,12 +75,8 @@ namespace Ryujinx.Graphics.OpenGL
_clipOrigin = ClipOrigin.LowerLeft; _clipOrigin = ClipOrigin.LowerLeft;
_clipDepthMode = ClipDepthMode.NegativeOneToOne; _clipDepthMode = ClipDepthMode.NegativeOneToOne;
_componentMasks = new uint[Constants.MaxRenderTargets]; _fragmentOutputMap = uint.MaxValue;
_componentMasks = uint.MaxValue;
for (int index = 0; index < Constants.MaxRenderTargets; index++)
{
_componentMasks[index] = 0xf;
}
var defaultScale = new Vector4<float> { X = 1f, Y = 0f, Z = 0f, W = 0f }; var defaultScale = new Vector4<float> { X = 1f, Y = 0f, Z = 0f, W = 0f };
new Span<Vector4<float>>(_renderScale).Fill(defaultScale); new Span<Vector4<float>>(_renderScale).Fill(defaultScale);
@ -1001,18 +999,30 @@ namespace Ryujinx.Graphics.OpenGL
public void SetProgram(IProgram program) public void SetProgram(IProgram program)
{ {
_program = (Program)program; Program prg = (Program)program;
if (_tfEnabled) if (_tfEnabled)
{ {
GL.EndTransformFeedback(); GL.EndTransformFeedback();
_program.Bind(); prg.Bind();
GL.BeginTransformFeedback(_tfTopology); GL.BeginTransformFeedback(_tfTopology);
} }
else else
{ {
_program.Bind(); prg.Bind();
} }
if (prg.HasFragmentShader && _fragmentOutputMap != (uint)prg.FragmentOutputMap)
{
_fragmentOutputMap = (uint)prg.FragmentOutputMap;
for (int index = 0; index < Constants.MaxRenderTargets; index++)
{
RestoreComponentMask(index, force: false);
}
}
_program = prg;
} }
public void SetRasterizerDiscard(bool discard) public void SetRasterizerDiscard(bool discard)
@ -1037,11 +1047,13 @@ namespace Ryujinx.Graphics.OpenGL
public void SetRenderTargetColorMasks(ReadOnlySpan<uint> componentMasks) public void SetRenderTargetColorMasks(ReadOnlySpan<uint> componentMasks)
{ {
_componentMasks = 0;
for (int index = 0; index < componentMasks.Length; index++) for (int index = 0; index < componentMasks.Length; index++)
{ {
_componentMasks[index] = componentMasks[index]; _componentMasks |= componentMasks[index] << (index * 4);
RestoreComponentMask(index); RestoreComponentMask(index, force: false);
} }
} }
@ -1436,18 +1448,34 @@ namespace Ryujinx.Graphics.OpenGL
} }
} }
public void RestoreComponentMask(int index) public void RestoreComponentMask(int index, bool force = true)
{ {
// If the bound render target is bgra, swap the red and blue masks. // If the bound render target is bgra, swap the red and blue masks.
uint redMask = _fpIsBgra[index].X == 0 ? 1u : 4u; uint redMask = _fpIsBgra[index].X == 0 ? 1u : 4u;
uint blueMask = _fpIsBgra[index].X == 0 ? 4u : 1u; uint blueMask = _fpIsBgra[index].X == 0 ? 4u : 1u;
int shift = index * 4;
uint componentMask = _componentMasks & _fragmentOutputMap;
uint checkMask = 0xfu << shift;
uint componentMaskAtIndex = componentMask & checkMask;
if (!force && componentMaskAtIndex == (_currentComponentMasks & checkMask))
{
return;
}
componentMask >>= shift;
componentMask &= 0xfu;
GL.ColorMask( GL.ColorMask(
index, index,
(_componentMasks[index] & redMask) != 0, (componentMask & redMask) != 0,
(_componentMasks[index] & 2u) != 0, (componentMask & 2u) != 0,
(_componentMasks[index] & blueMask) != 0, (componentMask & blueMask) != 0,
(_componentMasks[index] & 8u) != 0); (componentMask & 8u) != 0);
_currentComponentMasks &= ~checkMask;
_currentComponentMasks |= componentMaskAtIndex;
} }
public void RestoreScissor0Enable() public void RestoreScissor0Enable()

View File

@ -1,11 +1,8 @@
using OpenTK.Graphics.OpenGL; using OpenTK.Graphics.OpenGL;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Shader.CodeGen.Glsl;
using System; using System;
using System.Buffers.Binary; using System.Buffers.Binary;
using System.Collections.Generic;
using System.Linq;
namespace Ryujinx.Graphics.OpenGL namespace Ryujinx.Graphics.OpenGL
{ {
@ -29,7 +26,10 @@ namespace Ryujinx.Graphics.OpenGL
private ProgramLinkStatus _status = ProgramLinkStatus.Incomplete; private ProgramLinkStatus _status = ProgramLinkStatus.Incomplete;
private IShader[] _shaders; private IShader[] _shaders;
public Program(IShader[] shaders) public bool HasFragmentShader;
public int FragmentOutputMap { get; }
public Program(IShader[] shaders, int fragmentOutputMap)
{ {
Handle = GL.CreateProgram(); Handle = GL.CreateProgram();
@ -37,17 +37,23 @@ namespace Ryujinx.Graphics.OpenGL
for (int index = 0; index < shaders.Length; index++) for (int index = 0; index < shaders.Length; index++)
{ {
int shaderHandle = ((Shader)shaders[index]).Handle; Shader shader = (Shader)shaders[index];
GL.AttachShader(Handle, shaderHandle); if (shader.IsFragment)
{
HasFragmentShader = true;
}
GL.AttachShader(Handle, shader.Handle);
} }
GL.LinkProgram(Handle); GL.LinkProgram(Handle);
_shaders = shaders; _shaders = shaders;
FragmentOutputMap = fragmentOutputMap;
} }
public Program(ReadOnlySpan<byte> code) public Program(ReadOnlySpan<byte> code, bool hasFragmentShader, int fragmentOutputMap)
{ {
BinaryFormat binaryFormat = (BinaryFormat)BinaryPrimitives.ReadInt32LittleEndian(code.Slice(code.Length - 4, 4)); BinaryFormat binaryFormat = (BinaryFormat)BinaryPrimitives.ReadInt32LittleEndian(code.Slice(code.Length - 4, 4));
@ -60,6 +66,9 @@ namespace Ryujinx.Graphics.OpenGL
GL.ProgramBinary(Handle, binaryFormat, (IntPtr)ptr, code.Length - 4); GL.ProgramBinary(Handle, binaryFormat, (IntPtr)ptr, code.Length - 4);
} }
} }
HasFragmentShader = hasFragmentShader;
FragmentOutputMap = fragmentOutputMap;
} }
public void Bind() public void Bind()

View File

@ -9,7 +9,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries
public Counters() public Counters()
{ {
int count = Enum.GetNames(typeof(CounterType)).Length; int count = Enum.GetNames<CounterType>().Length;
_counterQueues = new CounterQueue[count]; _counterQueues = new CounterQueue[count];
} }

View File

@ -66,9 +66,9 @@ namespace Ryujinx.Graphics.OpenGL
return Buffer.Create(size); return Buffer.Create(size);
} }
public IProgram CreateProgram(IShader[] shaders) public IProgram CreateProgram(IShader[] shaders, ShaderInfo info)
{ {
return new Program(shaders); return new Program(shaders, info.FragmentOutputMap);
} }
public ISampler CreateSampler(SamplerCreateInfo info) public ISampler CreateSampler(SamplerCreateInfo info)
@ -202,9 +202,9 @@ namespace Ryujinx.Graphics.OpenGL
_sync.Dispose(); _sync.Dispose();
} }
public IProgram LoadProgramBinary(byte[] programBinary) public IProgram LoadProgramBinary(byte[] programBinary, bool hasFragmentShader, ShaderInfo info)
{ {
return new Program(programBinary); return new Program(programBinary, hasFragmentShader, info.FragmentOutputMap);
} }
public void CreateSync(ulong id) public void CreateSync(ulong id)

View File

@ -7,6 +7,7 @@ namespace Ryujinx.Graphics.OpenGL
class Shader : IShader class Shader : IShader
{ {
public int Handle { get; private set; } public int Handle { get; private set; }
public bool IsFragment { get; }
public Shader(ShaderStage stage, string code) public Shader(ShaderStage stage, string code)
{ {
@ -22,6 +23,7 @@ namespace Ryujinx.Graphics.OpenGL
}; };
Handle = GL.CreateShader(type); Handle = GL.CreateShader(type);
IsFragment = stage == ShaderStage.Fragment;
GL.ShaderSource(Handle, code); GL.ShaderSource(Handle, code);
GL.CompileShader(Handle); GL.CompileShader(Handle);

View File

@ -490,7 +490,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
} }
else else
{ {
int usedAttributes = context.Config.UsedInputAttributes; int usedAttributes = context.Config.UsedInputAttributes | context.Config.PassthroughAttributes;
while (usedAttributes != 0) while (usedAttributes != 0)
{ {
int index = BitOperations.TrailingZeroCount(usedAttributes); int index = BitOperations.TrailingZeroCount(usedAttributes);

View File

@ -13,6 +13,7 @@ namespace Ryujinx.Graphics.Shader
public bool UsesInstanceId { get; } public bool UsesInstanceId { get; }
public bool UsesRtLayer { get; } public bool UsesRtLayer { get; }
public byte ClipDistancesWritten { get; } public byte ClipDistancesWritten { get; }
public int FragmentOutputMap { get; }
public ShaderProgramInfo( public ShaderProgramInfo(
BufferDescriptor[] cBuffers, BufferDescriptor[] cBuffers,
@ -21,7 +22,8 @@ namespace Ryujinx.Graphics.Shader
TextureDescriptor[] images, TextureDescriptor[] images,
bool usesInstanceId, bool usesInstanceId,
bool usesRtLayer, bool usesRtLayer,
byte clipDistancesWritten) byte clipDistancesWritten,
int fragmentOutputMap)
{ {
CBuffers = Array.AsReadOnly(cBuffers); CBuffers = Array.AsReadOnly(cBuffers);
SBuffers = Array.AsReadOnly(sBuffers); SBuffers = Array.AsReadOnly(sBuffers);
@ -31,6 +33,7 @@ namespace Ryujinx.Graphics.Shader
UsesInstanceId = usesInstanceId; UsesInstanceId = usesInstanceId;
UsesRtLayer = usesRtLayer; UsesRtLayer = usesRtLayer;
ClipDistancesWritten = clipDistancesWritten; ClipDistancesWritten = clipDistancesWritten;
FragmentOutputMap = fragmentOutputMap;
} }
} }
} }

View File

@ -172,11 +172,10 @@ namespace Ryujinx.Graphics.Shader.Translation
for (int rtIndex = 0; rtIndex < 8; rtIndex++) for (int rtIndex = 0; rtIndex < 8; rtIndex++)
{ {
OmapTarget target = Config.OmapTargets[rtIndex];
for (int component = 0; component < 4; component++) for (int component = 0; component < 4; component++)
{ {
if (!target.ComponentEnabled(component)) bool componentEnabled = (Config.OmapTargets & (1 << (rtIndex * 4 + component))) != 0;
if (!componentEnabled)
{ {
continue; continue;
} }
@ -210,7 +209,8 @@ namespace Ryujinx.Graphics.Shader.Translation
} }
} }
if (target.Enabled) bool targetEnabled = (Config.OmapTargets & (0xf << (rtIndex * 4))) != 0;
if (targetEnabled)
{ {
Config.SetOutputUserAttribute(rtIndex, perPatch: false); Config.SetOutputUserAttribute(rtIndex, perPatch: false);
regIndexBase += 4; regIndexBase += 4;

View File

@ -25,7 +25,7 @@ namespace Ryujinx.Graphics.Shader.Translation
public ImapPixelType[] ImapTypes { get; } public ImapPixelType[] ImapTypes { get; }
public OmapTarget[] OmapTargets { get; } public int OmapTargets { get; }
public bool OmapSampleMask { get; } public bool OmapSampleMask { get; }
public bool OmapDepth { get; } public bool OmapDepth { get; }
@ -135,21 +135,8 @@ namespace Ryujinx.Graphics.Shader.Translation
public int GetDepthRegister() public int GetDepthRegister()
{ {
int count = 0;
for (int index = 0; index < OmapTargets.Length; index++)
{
for (int component = 0; component < 4; component++)
{
if (OmapTargets[index].ComponentEnabled(component))
{
count++;
}
}
}
// The depth register is always two registers after the last color output. // The depth register is always two registers after the last color output.
return count + 1; return BitOperations.PopCount((uint)OmapTargets) + 1;
} }
public TextureFormat GetTextureFormat(int handle, int cbufSlot = -1) public TextureFormat GetTextureFormat(int handle, int cbufSlot = -1)

View File

@ -36,37 +36,6 @@ namespace Ryujinx.Graphics.Shader.Translation
} }
} }
struct OmapTarget
{
public bool Red { get; }
public bool Green { get; }
public bool Blue { get; }
public bool Alpha { get; }
public bool Enabled => Red || Green || Blue || Alpha;
public OmapTarget(bool red, bool green, bool blue, bool alpha)
{
Red = red;
Green = green;
Blue = blue;
Alpha = alpha;
}
public bool ComponentEnabled(int component)
{
switch (component)
{
case 0: return Red;
case 1: return Green;
case 2: return Blue;
case 3: return Alpha;
}
throw new ArgumentOutOfRangeException(nameof(component));
}
}
class ShaderHeader class ShaderHeader
{ {
public int SphType { get; } public int SphType { get; }
@ -108,7 +77,7 @@ namespace Ryujinx.Graphics.Shader.Translation
public ImapPixelType[] ImapTypes { get; } public ImapPixelType[] ImapTypes { get; }
public OmapTarget[] OmapTargets { get; } public int OmapTargets { get; }
public bool OmapSampleMask { get; } public bool OmapSampleMask { get; }
public bool OmapDepth { get; } public bool OmapDepth { get; }
@ -181,17 +150,7 @@ namespace Ryujinx.Graphics.Shader.Translation
int type2OmapTarget = header[18]; int type2OmapTarget = header[18];
int type2Omap = header[19]; int type2Omap = header[19];
OmapTargets = new OmapTarget[8]; OmapTargets = type2OmapTarget;
for (int offset = 0; offset < OmapTargets.Length * 4; offset += 4)
{
OmapTargets[offset >> 2] = new OmapTarget(
type2OmapTarget.Extract(offset + 0),
type2OmapTarget.Extract(offset + 1),
type2OmapTarget.Extract(offset + 2),
type2OmapTarget.Extract(offset + 3));
}
OmapSampleMask = type2Omap.Extract(0); OmapSampleMask = type2Omap.Extract(0);
OmapDepth = type2Omap.Extract(1); OmapDepth = type2Omap.Extract(1);
} }

View File

@ -105,7 +105,8 @@ namespace Ryujinx.Graphics.Shader.Translation
config.GetImageDescriptors(), config.GetImageDescriptors(),
config.UsedFeatures.HasFlag(FeatureFlags.InstanceId), config.UsedFeatures.HasFlag(FeatureFlags.InstanceId),
config.UsedFeatures.HasFlag(FeatureFlags.RtLayer), config.UsedFeatures.HasFlag(FeatureFlags.RtLayer),
config.ClipDistancesWritten); config.ClipDistancesWritten,
config.OmapTargets);
return program; return program;
} }

View File

@ -102,7 +102,7 @@ namespace Ryujinx.HLE.FileSystem.Content
_contentDictionary = new SortedDictionary<(ulong, NcaContentType), string>(); _contentDictionary = new SortedDictionary<(ulong, NcaContentType), string>();
_locationEntries = new Dictionary<StorageId, LinkedList<LocationEntry>>(); _locationEntries = new Dictionary<StorageId, LinkedList<LocationEntry>>();
foreach (StorageId storageId in Enum.GetValues(typeof(StorageId))) foreach (StorageId storageId in Enum.GetValues<StorageId>())
{ {
string contentDirectory = null; string contentDirectory = null;
string contentPathString = null; string contentPathString = null;

View File

@ -9,14 +9,14 @@ namespace Ryujinx.HLE.HOS
{ {
class ArmProcessContext<T> : IProcessContext where T : class, IVirtualMemoryManagerTracked, IMemoryManager class ArmProcessContext<T> : IProcessContext where T : class, IVirtualMemoryManagerTracked, IMemoryManager
{ {
private readonly long _pid; private readonly ulong _pid;
private readonly GpuContext _gpuContext; private readonly GpuContext _gpuContext;
private readonly CpuContext _cpuContext; private readonly CpuContext _cpuContext;
private T _memoryManager; private T _memoryManager;
public IVirtualMemoryManager AddressSpace => _memoryManager; public IVirtualMemoryManager AddressSpace => _memoryManager;
public ArmProcessContext(long pid, GpuContext gpuContext, T memoryManager, bool for64Bit) public ArmProcessContext(ulong pid, GpuContext gpuContext, T memoryManager, bool for64Bit)
{ {
if (memoryManager is IRefCounted rc) if (memoryManager is IRefCounted rc)
{ {

View File

@ -17,7 +17,7 @@ namespace Ryujinx.HLE.HOS
_gpu = gpu; _gpu = gpu;
} }
public IProcessContext Create(KernelContext context, long pid, ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler, bool for64Bit) public IProcessContext Create(KernelContext context, ulong pid, ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler, bool for64Bit)
{ {
MemoryManagerMode mode = context.Device.Configuration.MemoryManagerMode; MemoryManagerMode mode = context.Device.Configuration.MemoryManagerMode;

View File

@ -7,7 +7,7 @@ namespace Ryujinx.HLE.HOS.Ipc
{ {
public bool HasPId { get; private set; } public bool HasPId { get; private set; }
public long PId { get; private set; } public ulong PId { get; private set; }
public int[] ToCopy { get; private set; } public int[] ToCopy { get; private set; }
public int[] ToMove { get; private set; } public int[] ToMove { get; private set; }
@ -21,7 +21,7 @@ namespace Ryujinx.HLE.HOS.Ipc
ToCopy = new int[(word >> 1) & 0xf]; ToCopy = new int[(word >> 1) & 0xf];
ToMove = new int[(word >> 5) & 0xf]; ToMove = new int[(word >> 5) & 0xf];
PId = HasPId ? reader.ReadInt64() : 0; PId = HasPId ? reader.ReadUInt64() : 0;
for (int index = 0; index < ToCopy.Length; index++) for (int index = 0; index < ToCopy.Length; index++)
{ {
@ -40,7 +40,7 @@ namespace Ryujinx.HLE.HOS.Ipc
ToMove = move ?? throw new ArgumentNullException(nameof(move)); ToMove = move ?? throw new ArgumentNullException(nameof(move));
} }
public IpcHandleDesc(int[] copy, int[] move, long pId) : this(copy, move) public IpcHandleDesc(int[] copy, int[] move, ulong pId) : this(copy, move)
{ {
PId = pId; PId = pId;

View File

@ -42,14 +42,14 @@ namespace Ryujinx.HLE.HOS.Kernel
public KSynchronization Synchronization { get; } public KSynchronization Synchronization { get; }
public KContextIdManager ContextIdManager { get; } public KContextIdManager ContextIdManager { get; }
public ConcurrentDictionary<long, KProcess> Processes { get; } public ConcurrentDictionary<ulong, KProcess> Processes { get; }
public ConcurrentDictionary<string, KAutoObject> AutoObjectNames { get; } public ConcurrentDictionary<string, KAutoObject> AutoObjectNames { get; }
public bool ThreadReselectionRequested { get; set; } public bool ThreadReselectionRequested { get; set; }
private long _kipId; private ulong _kipId;
private long _processId; private ulong _processId;
private long _threadUid; private ulong _threadUid;
public KernelContext( public KernelContext(
Switch device, Switch device,
@ -98,7 +98,7 @@ namespace Ryujinx.HLE.HOS.Kernel
KernelInitialized = true; KernelInitialized = true;
Processes = new ConcurrentDictionary<long, KProcess>(); Processes = new ConcurrentDictionary<ulong, KProcess>();
AutoObjectNames = new ConcurrentDictionary<string, KAutoObject>(); AutoObjectNames = new ConcurrentDictionary<string, KAutoObject>();
_kipId = KernelConstants.InitialKipId; _kipId = KernelConstants.InitialKipId;
@ -115,17 +115,17 @@ namespace Ryujinx.HLE.HOS.Kernel
new Thread(PreemptionThreadStart) { Name = "HLE.PreemptionThread" }.Start(); new Thread(PreemptionThreadStart) { Name = "HLE.PreemptionThread" }.Start();
} }
public long NewThreadUid() public ulong NewThreadUid()
{ {
return Interlocked.Increment(ref _threadUid) - 1; return Interlocked.Increment(ref _threadUid) - 1;
} }
public long NewKipId() public ulong NewKipId()
{ {
return Interlocked.Increment(ref _kipId) - 1; return Interlocked.Increment(ref _kipId) - 1;
} }
public long NewProcessId() public ulong NewProcessId()
{ {
return Interlocked.Increment(ref _processId) - 1; return Interlocked.Increment(ref _processId) - 1;
} }

View File

@ -8,7 +8,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
{ {
private readonly SharedMemoryStorage _storage; private readonly SharedMemoryStorage _storage;
private readonly long _ownerPid; private readonly ulong _ownerPid;
private readonly KMemoryPermission _ownerPermission; private readonly KMemoryPermission _ownerPermission;
private readonly KMemoryPermission _userPermission; private readonly KMemoryPermission _userPermission;
@ -16,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
public KSharedMemory( public KSharedMemory(
KernelContext context, KernelContext context,
SharedMemoryStorage storage, SharedMemoryStorage storage,
long ownerPid, ulong ownerPid,
KMemoryPermission ownerPermission, KMemoryPermission ownerPermission,
KMemoryPermission userPermission) : base(context) KMemoryPermission userPermission) : base(context)
{ {

View File

@ -4,6 +4,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
{ {
interface IProcessContextFactory interface IProcessContextFactory
{ {
IProcessContext Create(KernelContext context, long pid, ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler, bool for64Bit); IProcessContext Create(KernelContext context, ulong pid, ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler, bool for64Bit);
} }
} }

View File

@ -62,7 +62,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
public ulong TitleId { get; private set; } public ulong TitleId { get; private set; }
public bool IsApplication { get; private set; } public bool IsApplication { get; private set; }
public long Pid { get; private set; } public ulong Pid { get; private set; }
private long _creationTimestamp; private long _creationTimestamp;
private ulong _entrypoint; private ulong _entrypoint;
@ -131,7 +131,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
Pid = KernelContext.NewKipId(); Pid = KernelContext.NewKipId();
if (Pid == 0 || (ulong)Pid >= KernelConstants.InitialProcessId) if (Pid == 0 || Pid >= KernelConstants.InitialProcessId)
{ {
throw new InvalidOperationException($"Invalid KIP Id {Pid}."); throw new InvalidOperationException($"Invalid KIP Id {Pid}.");
} }
@ -239,7 +239,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
Pid = KernelContext.NewProcessId(); Pid = KernelContext.NewProcessId();
if (Pid == -1 || (ulong)Pid < KernelConstants.InitialProcessId) if (Pid == ulong.MaxValue || Pid < KernelConstants.InitialProcessId)
{ {
throw new InvalidOperationException($"Invalid Process Id {Pid}."); throw new InvalidOperationException($"Invalid Process Id {Pid}.");
} }

View File

@ -4,7 +4,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
{ {
class ProcessContextFactory : IProcessContextFactory class ProcessContextFactory : IProcessContextFactory
{ {
public IProcessContext Create(KernelContext context, long pid, ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler, bool for64Bit) public IProcessContext Create(KernelContext context, ulong pid, ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler, bool for64Bit)
{ {
return new ProcessContext(new AddressSpaceManager(addressSpaceSize)); return new ProcessContext(new AddressSpaceManager(addressSpaceSize));
} }

View File

@ -24,7 +24,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
// Process // Process
public KernelResult GetProcessId(out long pid, int handle) public KernelResult GetProcessId(out ulong pid, int handle)
{ {
KProcess currentProcess = KernelStatic.GetCurrentProcess(); KProcess currentProcess = KernelStatic.GetCurrentProcess();
@ -2280,7 +2280,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return KernelStatic.GetCurrentThread().CurrentCore; return KernelStatic.GetCurrentThread().CurrentCore;
} }
public KernelResult GetThreadId(out long threadUid, int handle) public KernelResult GetThreadId(out ulong threadUid, int handle)
{ {
KProcess process = KernelStatic.GetCurrentProcess(); KProcess process = KernelStatic.GetCurrentProcess();

View File

@ -235,12 +235,12 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
resultHigh = (uint)(result >> 32); resultHigh = (uint)(result >> 32);
} }
public KernelResult GetProcessId32([R(1)] int handle, [R(1)] out int pidLow, [R(2)] out int pidHigh) public KernelResult GetProcessId32([R(1)] int handle, [R(1)] out uint pidLow, [R(2)] out uint pidHigh)
{ {
KernelResult result = _syscall.GetProcessId(out long pid, handle); KernelResult result = _syscall.GetProcessId(out ulong pid, handle);
pidLow = (int)(pid & uint.MaxValue); pidLow = (uint)(pid & uint.MaxValue);
pidHigh = (int)(pid >> 32); pidHigh = (uint)(pid >> 32);
return result; return result;
} }
@ -413,7 +413,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
public KernelResult GetThreadId32([R(1)] int handle, [R(1)] out uint threadUidLow, [R(2)] out uint threadUidHigh) public KernelResult GetThreadId32([R(1)] int handle, [R(1)] out uint threadUidLow, [R(2)] out uint threadUidHigh)
{ {
long threadUid; ulong threadUid;
KernelResult result = _syscall.GetThreadId(out threadUid, handle); KernelResult result = _syscall.GetThreadId(out threadUid, handle);

View File

@ -232,7 +232,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return _syscall.GetSystemTick(); return _syscall.GetSystemTick();
} }
public KernelResult GetProcessId64([R(1)] int handle, [R(1)] out long pid) public KernelResult GetProcessId64([R(1)] int handle, [R(1)] out ulong pid)
{ {
return _syscall.GetProcessId(out pid, handle); return _syscall.GetProcessId(out pid, handle);
} }
@ -345,7 +345,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return _syscall.GetCurrentProcessorNumber(); return _syscall.GetCurrentProcessorNumber();
} }
public KernelResult GetThreadId64([R(1)] int handle, [R(1)] out long threadUid) public KernelResult GetThreadId64([R(1)] int handle, [R(1)] out ulong threadUid)
{ {
return _syscall.GetThreadId(out threadUid, handle); return _syscall.GetThreadId(out threadUid, handle);
} }

View File

@ -433,7 +433,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
generator.Emit(OpCodes.Ret); generator.Emit(OpCodes.Ret);
return (Action<T, ExecutionContext>)method.CreateDelegate(typeof(Action<T, ExecutionContext>)); return method.CreateDelegate<Action<T, ExecutionContext>>();
} }
private static void CheckIfTypeIsSupported(Type type, string svcName) private static void CheckIfTypeIsSupported(Type type, string svcName)

View File

@ -30,7 +30,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
public int DynamicPriority { get; set; } public int DynamicPriority { get; set; }
public ulong AffinityMask { get; set; } public ulong AffinityMask { get; set; }
public long ThreadUid { get; private set; } public ulong ThreadUid { get; private set; }
private long _totalTimeRunning; private long _totalTimeRunning;

View File

@ -5,9 +5,9 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService
{ {
class ILibraryAppletProxy : IpcService class ILibraryAppletProxy : IpcService
{ {
private readonly long _pid; private readonly ulong _pid;
public ILibraryAppletProxy(long pid) public ILibraryAppletProxy(ulong pid)
{ {
_pid = pid; _pid = pid;
} }

View File

@ -4,9 +4,9 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService
{ {
class ISystemAppletProxy : IpcService class ISystemAppletProxy : IpcService
{ {
private readonly long _pid; private readonly ulong _pid;
public ISystemAppletProxy(long pid) public ISystemAppletProxy(ulong pid)
{ {
_pid = pid; _pid = pid;
} }

View File

@ -8,7 +8,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
{ {
class ISelfController : IpcService class ISelfController : IpcService
{ {
private readonly long _pid; private readonly ulong _pid;
private KEvent _libraryAppletLaunchableEvent; private KEvent _libraryAppletLaunchableEvent;
private int _libraryAppletLaunchableEventHandle; private int _libraryAppletLaunchableEventHandle;
@ -35,7 +35,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
private uint _screenShotImageOrientation = 0; private uint _screenShotImageOrientation = 0;
private uint _idleTimeDetectionExtension = 0; private uint _idleTimeDetectionExtension = 0;
public ISelfController(ServiceCtx context, long pid) public ISelfController(ServiceCtx context, ulong pid)
{ {
_libraryAppletLaunchableEvent = new KEvent(context.Device.System.KernelContext); _libraryAppletLaunchableEvent = new KEvent(context.Device.System.KernelContext);
_pid = pid; _pid = pid;

View File

@ -4,9 +4,9 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
{ {
class IWindowController : IpcService class IWindowController : IpcService
{ {
private readonly long _pid; private readonly ulong _pid;
public IWindowController(long pid) public IWindowController(ulong pid)
{ {
_pid = pid; _pid = pid;
} }

View File

@ -5,9 +5,9 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService
{ {
class IApplicationProxy : IpcService class IApplicationProxy : IpcService
{ {
private readonly long _pid; private readonly ulong _pid;
public IApplicationProxy(long pid) public IApplicationProxy(ulong pid)
{ {
_pid = pid; _pid = pid;
} }

View File

@ -318,7 +318,7 @@ namespace Ryujinx.HLE.HOS.Services.Friend.ServiceCreator
// Pid placeholder // Pid placeholder
context.RequestData.ReadInt64(); context.RequestData.ReadInt64();
long pid = context.Request.HandleDesc.PId; ulong pid = context.Request.HandleDesc.PId;
ulong playHistoryRegistrationKeyPosition = context.Request.PtrBuff[0].Position; ulong playHistoryRegistrationKeyPosition = context.Request.PtrBuff[0].Position;
ulong PlayHistoryRegistrationKeySize = context.Request.PtrBuff[0].Size; ulong PlayHistoryRegistrationKeySize = context.Request.PtrBuff[0].Size;

View File

@ -1021,7 +1021,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
HidVibrationDeviceType vibrationDeviceType = HidVibrationDeviceType.None; HidVibrationDeviceType vibrationDeviceType = HidVibrationDeviceType.None;
if (Enum.IsDefined(typeof(NpadStyleIndex), deviceType)) if (Enum.IsDefined<NpadStyleIndex>(deviceType))
{ {
vibrationDeviceType = HidVibrationDeviceType.LinearResonantActuator; vibrationDeviceType = HidVibrationDeviceType.LinearResonantActuator;
} }

View File

@ -44,7 +44,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns.Aoc
// CountAddOnContent(pid) -> u32 // CountAddOnContent(pid) -> u32
public ResultCode CountAddOnContent(ServiceCtx context) public ResultCode CountAddOnContent(ServiceCtx context)
{ {
long pid = context.Request.HandleDesc.PId; ulong pid = context.Request.HandleDesc.PId;
// NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId. // NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId.
@ -55,7 +55,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns.Aoc
// ListAddOnContent(u32 start_index, u32 buffer_size, pid) -> (u32 count, buffer<u32>) // ListAddOnContent(u32 start_index, u32 buffer_size, pid) -> (u32 count, buffer<u32>)
public ResultCode ListAddOnContent(ServiceCtx context) public ResultCode ListAddOnContent(ServiceCtx context)
{ {
long pid = context.Request.HandleDesc.PId; ulong pid = context.Request.HandleDesc.PId;
// NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId. // NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId.
@ -75,7 +75,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns.Aoc
// GetAddOnContentBaseId(pid) -> u64 // GetAddOnContentBaseId(pid) -> u64
public ResultCode GetAddOnContentBaseId(ServiceCtx context) public ResultCode GetAddOnContentBaseId(ServiceCtx context)
{ {
long pid = context.Request.HandleDesc.PId; ulong pid = context.Request.HandleDesc.PId;
// NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId. // NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId.
@ -95,7 +95,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns.Aoc
// PrepareAddOnContent(u32 index, pid) // PrepareAddOnContent(u32 index, pid)
public ResultCode PrepareAddOnContent(ServiceCtx context) public ResultCode PrepareAddOnContent(ServiceCtx context)
{ {
long pid = context.Request.HandleDesc.PId; ulong pid = context.Request.HandleDesc.PId;
// NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId. // NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId.
@ -123,7 +123,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns.Aoc
// GetAddOnContentListChangedEventWithProcessId(pid) -> handle<copy> // GetAddOnContentListChangedEventWithProcessId(pid) -> handle<copy>
public ResultCode GetAddOnContentListChangedEventWithProcessId(ServiceCtx context) public ResultCode GetAddOnContentListChangedEventWithProcessId(ServiceCtx context)
{ {
long pid = context.Request.HandleDesc.PId; ulong pid = context.Request.HandleDesc.PId;
// NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId. // NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId.
@ -142,7 +142,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns.Aoc
// NotifyMountAddOnContent(pid, u64 title_id) // NotifyMountAddOnContent(pid, u64 title_id)
public ResultCode NotifyMountAddOnContent(ServiceCtx context) public ResultCode NotifyMountAddOnContent(ServiceCtx context)
{ {
long pid = context.Request.HandleDesc.PId; ulong pid = context.Request.HandleDesc.PId;
// NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId. // NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId.
@ -160,7 +160,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns.Aoc
// NotifyUnmountAddOnContent(pid, u64 title_id) // NotifyUnmountAddOnContent(pid, u64 title_id)
public ResultCode NotifyUnmountAddOnContent(ServiceCtx context) public ResultCode NotifyUnmountAddOnContent(ServiceCtx context)
{ {
long pid = context.Request.HandleDesc.PId; ulong pid = context.Request.HandleDesc.PId;
// NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId. // NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId.
@ -175,7 +175,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns.Aoc
// CheckAddOnContentMountStatus(pid) // CheckAddOnContentMountStatus(pid)
public ResultCode CheckAddOnContentMountStatus(ServiceCtx context) public ResultCode CheckAddOnContentMountStatus(ServiceCtx context)
{ {
long pid = context.Request.HandleDesc.PId; ulong pid = context.Request.HandleDesc.PId;
// NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId. // NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId.
// Then it does some internal checks and returns InvalidBufferSize if they fail. // Then it does some internal checks and returns InvalidBufferSize if they fail.

View File

@ -13,7 +13,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv
public NvMemoryAllocator MemoryAllocator { get; } public NvMemoryAllocator MemoryAllocator { get; }
public Host1xDevice Host1x { get;} public Host1xDevice Host1x { get;}
public Host1xContext(GpuContext gpu, long pid) public Host1xContext(GpuContext gpu, ulong pid)
{ {
MemoryAllocator = new NvMemoryAllocator(); MemoryAllocator = new NvMemoryAllocator();
Host1x = new Host1xDevice(gpu.Synchronization); Host1x = new Host1xDevice(gpu.Synchronization);

View File

@ -40,7 +40,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv
public static IdDictionary DeviceFileIdRegistry = new IdDictionary(); public static IdDictionary DeviceFileIdRegistry = new IdDictionary();
private IVirtualMemoryManager _clientMemory; private IVirtualMemoryManager _clientMemory;
private long _owner; private ulong _owner;
private bool _transferMemInitialized = false; private bool _transferMemInitialized = false;
@ -53,7 +53,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv
{ {
if (_deviceFileRegistry.TryGetValue(path, out Type deviceFileClass)) if (_deviceFileRegistry.TryGetValue(path, out Type deviceFileClass))
{ {
ConstructorInfo constructor = deviceFileClass.GetConstructor(new Type[] { typeof(ServiceCtx), typeof(IVirtualMemoryManager), typeof(long) }); ConstructorInfo constructor = deviceFileClass.GetConstructor(new Type[] { typeof(ServiceCtx), typeof(IVirtualMemoryManager), typeof(ulong) });
NvDeviceFile deviceFile = (NvDeviceFile)constructor.Invoke(new object[] { context, _clientMemory, _owner }); NvDeviceFile deviceFile = (NvDeviceFile)constructor.Invoke(new object[] { context, _clientMemory, _owner });

View File

@ -11,11 +11,11 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices
abstract class NvDeviceFile abstract class NvDeviceFile
{ {
public readonly ServiceCtx Context; public readonly ServiceCtx Context;
public readonly long Owner; public readonly ulong Owner;
public string Path; public string Path;
public NvDeviceFile(ServiceCtx context, long owner) public NvDeviceFile(ServiceCtx context, ulong owner)
{ {
Context = context; Context = context;
Owner = owner; Owner = owner;

View File

@ -41,7 +41,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu
private readonly AddressSpaceContext _asContext; private readonly AddressSpaceContext _asContext;
private readonly NvMemoryAllocator _memoryAllocator; private readonly NvMemoryAllocator _memoryAllocator;
public NvHostAsGpuDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, long owner) : base(context, owner) public NvHostAsGpuDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, ulong owner) : base(context, owner)
{ {
_asContext = new AddressSpaceContext(context.Device.Gpu.CreateMemoryManager(owner)); _asContext = new AddressSpaceContext(context.Device.Gpu.CreateMemoryManager(owner));
_memoryAllocator = new NvMemoryAllocator(); _memoryAllocator = new NvMemoryAllocator();

View File

@ -15,7 +15,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel
{ {
class NvHostChannelDeviceFile : NvDeviceFile class NvHostChannelDeviceFile : NvDeviceFile
{ {
private static readonly ConcurrentDictionary<long, Host1xContext> _host1xContextRegistry = new(); private static readonly ConcurrentDictionary<ulong, Host1xContext> _host1xContextRegistry = new();
private const uint MaxModuleSyncpoint = 16; private const uint MaxModuleSyncpoint = 16;
@ -45,7 +45,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel
private NvFence _channelSyncpoint; private NvFence _channelSyncpoint;
public NvHostChannelDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, long owner) : base(context, owner) public NvHostChannelDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, ulong owner) : base(context, owner)
{ {
_device = context.Device; _device = context.Device;
_memory = memory; _memory = memory;
@ -556,9 +556,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel
_channelSyncpoint.Id = 0; _channelSyncpoint.Id = 0;
} }
private static Host1xContext GetHost1XContext(GpuContext gpu, long pid) private static Host1xContext GetHost1XContext(GpuContext gpu, ulong pid)
{ {
return _host1xContextRegistry.GetOrAdd(pid, (long key) => new Host1xContext(gpu, key)); return _host1xContextRegistry.GetOrAdd(pid, (ulong key) => new Host1xContext(gpu, key));
} }
public static void Destroy() public static void Destroy()

View File

@ -16,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel
private int _smExceptionBptPauseReportEventHandle; private int _smExceptionBptPauseReportEventHandle;
private int _errorNotifierEventHandle; private int _errorNotifierEventHandle;
public NvHostGpuDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, long owner) : base(context, memory, owner) public NvHostGpuDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, ulong owner) : base(context, memory, owner)
{ {
_smExceptionBptIntReportEvent = CreateEvent(context, out _smExceptionBptIntReportEventHandle); _smExceptionBptIntReportEvent = CreateEvent(context, out _smExceptionBptIntReportEventHandle);
_smExceptionBptPauseReportEvent = CreateEvent(context, out _smExceptionBptPauseReportEventHandle); _smExceptionBptPauseReportEvent = CreateEvent(context, out _smExceptionBptPauseReportEventHandle);

View File

@ -20,7 +20,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl
private Switch _device; private Switch _device;
private NvHostEvent[] _events; private NvHostEvent[] _events;
public NvHostCtrlDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, long owner) : base(context, owner) public NvHostCtrlDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, ulong owner) : base(context, owner)
{ {
if (NxSettings.Settings.TryGetValue("nv!rmos_set_production_mode", out object productionModeSetting)) if (NxSettings.Settings.TryGetValue("nv!rmos_set_production_mode", out object productionModeSetting))
{ {

View File

@ -16,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrlGpu
private KEvent _errorEvent; private KEvent _errorEvent;
private KEvent _unknownEvent; private KEvent _unknownEvent;
public NvHostCtrlGpuDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, long owner) : base(context, owner) public NvHostCtrlGpuDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, ulong owner) : base(context, owner)
{ {
_errorEvent = new KEvent(context.Device.System.KernelContext); _errorEvent = new KEvent(context.Device.System.KernelContext);
_unknownEvent = new KEvent(context.Device.System.KernelContext); _unknownEvent = new KEvent(context.Device.System.KernelContext);

View File

@ -11,9 +11,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
{ {
private const int FlagNotFreedYet = 1; private const int FlagNotFreedYet = 1;
private static ConcurrentDictionary<long, IdDictionary> _maps = new ConcurrentDictionary<long, IdDictionary>(); private static ConcurrentDictionary<ulong, IdDictionary> _maps = new ConcurrentDictionary<ulong, IdDictionary>();
public NvMapDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, long owner) : base(context, owner) public NvMapDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, ulong owner) : base(context, owner)
{ {
IdDictionary dict = _maps.GetOrAdd(Owner, (key) => new IdDictionary()); IdDictionary dict = _maps.GetOrAdd(Owner, (key) => new IdDictionary());
@ -237,7 +237,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
return dict.Add(map); return dict.Add(map);
} }
private static bool DeleteMapWithHandle(long pid, int handle) private static bool DeleteMapWithHandle(ulong pid, int handle)
{ {
if (_maps.TryGetValue(pid, out IdDictionary dict)) if (_maps.TryGetValue(pid, out IdDictionary dict))
{ {
@ -247,12 +247,12 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
return false; return false;
} }
public static void IncrementMapRefCount(long pid, int handle) public static void IncrementMapRefCount(ulong pid, int handle)
{ {
GetMapFromHandle(pid, handle)?.IncrementRefCount(); GetMapFromHandle(pid, handle)?.IncrementRefCount();
} }
public static bool DecrementMapRefCount(long pid, int handle) public static bool DecrementMapRefCount(ulong pid, int handle)
{ {
NvMapHandle map = GetMapFromHandle(pid, handle); NvMapHandle map = GetMapFromHandle(pid, handle);
@ -275,7 +275,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
} }
} }
public static NvMapHandle GetMapFromHandle(long pid, int handle) public static NvMapHandle GetMapFromHandle(ulong pid, int handle)
{ {
if (_maps.TryGetValue(pid, out IdDictionary dict)) if (_maps.TryGetValue(pid, out IdDictionary dict))
{ {

View File

@ -19,7 +19,7 @@ namespace Ryujinx.HLE.HOS.Services.Pctl
// CreateService(u64, pid) -> object<nn::pctl::detail::ipc::IParentalControlService> // CreateService(u64, pid) -> object<nn::pctl::detail::ipc::IParentalControlService>
public ResultCode CreateService(ServiceCtx context) public ResultCode CreateService(ServiceCtx context)
{ {
long pid = context.Request.HandleDesc.PId; ulong pid = context.Request.HandleDesc.PId;
MakeObject(context, new IParentalControlService(context, pid, true, _permissionFlag)); MakeObject(context, new IParentalControlService(context, pid, true, _permissionFlag));
@ -30,7 +30,7 @@ namespace Ryujinx.HLE.HOS.Services.Pctl
// CreateServiceWithoutInitialize(u64, pid) -> object<nn::pctl::detail::ipc::IParentalControlService> // CreateServiceWithoutInitialize(u64, pid) -> object<nn::pctl::detail::ipc::IParentalControlService>
public ResultCode CreateServiceWithoutInitialize(ServiceCtx context) public ResultCode CreateServiceWithoutInitialize(ServiceCtx context)
{ {
long pid = context.Request.HandleDesc.PId; ulong pid = context.Request.HandleDesc.PId;
MakeObject(context, new IParentalControlService(context, pid, false, _permissionFlag)); MakeObject(context, new IParentalControlService(context, pid, false, _permissionFlag));

View File

@ -7,7 +7,7 @@ namespace Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory
{ {
class IParentalControlService : IpcService class IParentalControlService : IpcService
{ {
private long _pid; private ulong _pid;
private int _permissionFlag; private int _permissionFlag;
private ulong _titleId; private ulong _titleId;
private ParentalControlFlagValue _parentalControlFlag; private ParentalControlFlagValue _parentalControlFlag;
@ -19,7 +19,7 @@ namespace Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory
private bool _stereoVisionRestrictionConfigurable = true; private bool _stereoVisionRestrictionConfigurable = true;
private bool _stereoVisionRestriction = false; private bool _stereoVisionRestriction = false;
public IParentalControlService(ServiceCtx context, long pid, bool withInitialize, int permissionFlag) public IParentalControlService(ServiceCtx context, ulong pid, bool withInitialize, int permissionFlag)
{ {
_pid = pid; _pid = pid;
_permissionFlag = permissionFlag; _permissionFlag = permissionFlag;

View File

@ -11,7 +11,7 @@
{ {
// FIXME: This is wrong but needed to make hb loader works // FIXME: This is wrong but needed to make hb loader works
// TODO: Change this when we will have a way to process via a PM like interface. // TODO: Change this when we will have a way to process via a PM like interface.
long pid = context.Process.Pid; ulong pid = context.Process.Pid;
context.ResponseData.Write(pid); context.ResponseData.Write(pid);

View File

@ -418,7 +418,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro
return (ResultCode)result; return (ResultCode)result;
} }
private ResultCode IsInitialized(long pid) private ResultCode IsInitialized(ulong pid)
{ {
if (_owner != null && _owner.Pid == pid) if (_owner != null && _owner.Pid == pid)
{ {

View File

@ -5,7 +5,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
{ {
class BsdContext class BsdContext
{ {
private static ConcurrentDictionary<long, BsdContext> _registry = new ConcurrentDictionary<long, BsdContext>(); private static ConcurrentDictionary<ulong, BsdContext> _registry = new ConcurrentDictionary<ulong, BsdContext>();
private readonly object _lock = new object(); private readonly object _lock = new object();
@ -123,7 +123,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
return LinuxError.SUCCESS; return LinuxError.SUCCESS;
} }
public static BsdContext GetOrRegister(long processId) public static BsdContext GetOrRegister(ulong processId)
{ {
BsdContext context = GetContext(processId); BsdContext context = GetContext(processId);
@ -137,7 +137,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
return context; return context;
} }
public static BsdContext GetContext(long processId) public static BsdContext GetContext(ulong processId)
{ {
if (!_registry.TryGetValue(processId, out BsdContext processContext)) if (!_registry.TryGetValue(processId, out BsdContext processContext))
{ {

View File

@ -23,11 +23,11 @@ namespace Ryujinx.HLE.HOS.Services.Ssl.SslService
private ISslConnectionBase _connection; private ISslConnectionBase _connection;
private BsdContext _bsdContext; private BsdContext _bsdContext;
private readonly long _processId; private readonly ulong _processId;
private byte[] _nextAplnProto; private byte[] _nextAplnProto;
public ISslConnection(long processId, SslVersion sslVersion) public ISslConnection(ulong processId, SslVersion sslVersion)
{ {
_processId = processId; _processId = processId;
_sslVersion = sslVersion; _sslVersion = sslVersion;

View File

@ -1,5 +1,4 @@
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.HLE.HOS.Services.Sockets.Bsd;
using Ryujinx.HLE.HOS.Services.Ssl.Types; using Ryujinx.HLE.HOS.Services.Ssl.Types;
using System.Text; using System.Text;
@ -9,12 +8,12 @@ namespace Ryujinx.HLE.HOS.Services.Ssl.SslService
{ {
private uint _connectionCount; private uint _connectionCount;
private readonly long _processId; private readonly ulong _processId;
private readonly SslVersion _sslVersion; private readonly SslVersion _sslVersion;
private ulong _serverCertificateId; private ulong _serverCertificateId;
private ulong _clientCertificateId; private ulong _clientCertificateId;
public ISslContext(long processId, SslVersion sslVersion) public ISslContext(ulong processId, SslVersion sslVersion)
{ {
_processId = processId; _processId = processId;
_sslVersion = sslVersion; _sslVersion = sslVersion;

View File

@ -2,7 +2,7 @@
{ {
static class BufferQueue static class BufferQueue
{ {
public static BufferQueueCore CreateBufferQueue(Switch device, long pid, out BufferQueueProducer producer, out BufferQueueConsumer consumer) public static BufferQueueCore CreateBufferQueue(Switch device, ulong pid, out BufferQueueProducer producer, out BufferQueueConsumer consumer)
{ {
BufferQueueCore core = new BufferQueueCore(device, pid); BufferQueueCore core = new BufferQueueCore(device, pid);

View File

@ -40,7 +40,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
private KEvent _waitBufferFreeEvent; private KEvent _waitBufferFreeEvent;
private KEvent _frameAvailableEvent; private KEvent _frameAvailableEvent;
public long Owner { get; } public ulong Owner { get; }
public bool Active { get; private set; } public bool Active { get; private set; }
@ -48,7 +48,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
public event Action BufferQueued; public event Action BufferQueued;
public BufferQueueCore(Switch device, long pid) public BufferQueueCore(Switch device, ulong pid)
{ {
Slots = new BufferSlotArray(); Slots = new BufferSlotArray();
IsAbandoned = false; IsAbandoned = false;

View File

@ -44,7 +44,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
public IGraphicBufferProducer Producer; public IGraphicBufferProducer Producer;
public BufferItemConsumer Consumer; public BufferItemConsumer Consumer;
public BufferQueueCore Core; public BufferQueueCore Core;
public long Owner; public ulong Owner;
} }
private class TextureCallbackInformation private class TextureCallbackInformation
@ -92,7 +92,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
} }
} }
public IGraphicBufferProducer OpenLayer(long pid, long layerId) public IGraphicBufferProducer OpenLayer(ulong pid, long layerId)
{ {
bool needCreate; bool needCreate;
@ -109,7 +109,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
return GetProducerByLayerId(layerId); return GetProducerByLayerId(layerId);
} }
public IGraphicBufferProducer CreateLayer(long pid, out long layerId) public IGraphicBufferProducer CreateLayer(ulong pid, out long layerId)
{ {
layerId = 1; layerId = 1;
@ -129,7 +129,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
return GetProducerByLayerId(layerId); return GetProducerByLayerId(layerId);
} }
private void CreateLayerFromId(long pid, long layerId) private void CreateLayerFromId(ulong pid, long layerId)
{ {
lock (Lock) lock (Lock)
{ {

View File

@ -42,7 +42,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
Buffer = parcel.ReadUnmanagedType<NvGraphicBuffer>(); Buffer = parcel.ReadUnmanagedType<NvGraphicBuffer>();
} }
public void IncrementNvMapHandleRefCount(long pid) public void IncrementNvMapHandleRefCount(ulong pid)
{ {
NvMapDeviceFile.IncrementMapRefCount(pid, Buffer.NvMapId); NvMapDeviceFile.IncrementMapRefCount(pid, Buffer.NvMapId);
@ -52,7 +52,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
} }
} }
public void DecrementNvMapHandleRefCount(long pid) public void DecrementNvMapHandleRefCount(ulong pid)
{ {
NvMapDeviceFile.DecrementMapRefCount(pid, Buffer.NvMapId); NvMapDeviceFile.DecrementMapRefCount(pid, Buffer.NvMapId);

View File

@ -33,7 +33,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService.ApplicationDisplayService
long displayId = context.RequestData.ReadInt64(); long displayId = context.RequestData.ReadInt64();
long appletResourceUserId = context.RequestData.ReadInt64(); long appletResourceUserId = context.RequestData.ReadInt64();
long pid = context.Device.System.AppletState.AppletResourceUserIds.GetData<long>((int)appletResourceUserId); ulong pid = context.Device.System.AppletState.AppletResourceUserIds.GetData<ulong>((int)appletResourceUserId);
context.Device.System.SurfaceFlinger.CreateLayer(pid, out long layerId); context.Device.System.SurfaceFlinger.CreateLayer(pid, out long layerId);
context.Device.System.SurfaceFlinger.SetRenderLayer(layerId); context.Device.System.SurfaceFlinger.SetRenderLayer(layerId);

View File

@ -60,7 +60,7 @@ namespace Ryujinx.HLE.HOS.SystemState
SystemLanguage.TraditionalChinese => TitleLanguage.Taiwanese, SystemLanguage.TraditionalChinese => TitleLanguage.Taiwanese,
SystemLanguage.Chinese or SystemLanguage.Chinese or
SystemLanguage.SimplifiedChinese => TitleLanguage.Chinese, SystemLanguage.SimplifiedChinese => TitleLanguage.Chinese,
_ => Enum.Parse<TitleLanguage>(Enum.GetName(typeof(SystemLanguage), language)), _ => Enum.Parse<TitleLanguage>(Enum.GetName<SystemLanguage>(language)),
}; };
} }

View File

@ -54,7 +54,7 @@ namespace Ryujinx.HLE.HOS
Activate(); Activate();
} }
private bool CanInstallOnPid(long pid) private bool CanInstallOnPid(ulong pid)
{ {
// Do not allow tampering of kernel processes. // Do not allow tampering of kernel processes.
if (pid < KernelConstants.InitialProcessId) if (pid < KernelConstants.InitialProcessId)

View File

@ -100,7 +100,7 @@ namespace Ryujinx.Headless.SDL2
[Option("system-language", Required = false, Default = SystemLanguage.AmericanEnglish, HelpText = "Change System Language.")] [Option("system-language", Required = false, Default = SystemLanguage.AmericanEnglish, HelpText = "Change System Language.")]
public SystemLanguage SystemLanguage { get; set; } public SystemLanguage SystemLanguage { get; set; }
[Option("system-language", Required = false, Default = RegionCode.USA, HelpText = "Change System Region.")] [Option("system-region", Required = false, Default = RegionCode.USA, HelpText = "Change System Region.")]
public RegionCode SystemRegion { get; set; } public RegionCode SystemRegion { get; set; }
[Option("system-timezone", Required = false, Default = "UTC", HelpText = "Change System TimeZone.")] [Option("system-timezone", Required = false, Default = "UTC", HelpText = "Change System TimeZone.")]
@ -132,7 +132,7 @@ namespace Ryujinx.Headless.SDL2
[Option("enable-warning-logs", Required = false, Default = true, HelpText = "Enables printing warning log messages.")] [Option("enable-warning-logs", Required = false, Default = true, HelpText = "Enables printing warning log messages.")]
public bool? LoggingEnableWarning { get; set; } public bool? LoggingEnableWarning { get; set; }
[Option("enable-warning-logs", Required = false, Default = true, HelpText = "Enables printing error log messages.")] [Option("enable-error-logs", Required = false, Default = true, HelpText = "Enables printing error log messages.")]
public bool? LoggingEnableError { get; set; } public bool? LoggingEnableError { get; set; }
[Option("enable-guest-logs", Required = false, Default = true, HelpText = "Enables printing guest log messages.")] [Option("enable-guest-logs", Required = false, Default = true, HelpText = "Enables printing guest log messages.")]

View File

@ -391,24 +391,29 @@ namespace Ryujinx.Input.HLE
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static JoystickPosition ApplyDeadzone(float x, float y, float deadzone) private static JoystickPosition ApplyDeadzone(float x, float y, float deadzone)
{ {
return new JoystickPosition float magnitudeClamped = Math.Min(MathF.Sqrt(x * x + y * y), 1f);
if (magnitudeClamped <= deadzone)
{ {
Dx = ClampAxis(MathF.Abs(x) > deadzone ? x : 0.0f), return new JoystickPosition() {Dx = 0, Dy = 0};
Dy = ClampAxis(MathF.Abs(y) > deadzone ? y : 0.0f) }
return new JoystickPosition()
{
Dx = ClampAxis((x / magnitudeClamped) * ((magnitudeClamped - deadzone) / (1 - deadzone))),
Dy = ClampAxis((y / magnitudeClamped) * ((magnitudeClamped - deadzone) / (1 - deadzone)))
}; };
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static short ClampAxis(float value) private static short ClampAxis(float value)
{ {
if (value <= -short.MaxValue) if (Math.Sign(value) < 0)
{ {
return -short.MaxValue; return (short)Math.Max(value * -short.MinValue, short.MinValue);
}
else
{
return (short)(value * short.MaxValue);
} }
return (short)Math.Min(value * short.MaxValue, short.MaxValue);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@ -27,8 +27,8 @@ namespace Ryujinx.Input.Motion.CemuHook
private readonly Dictionary<int, Dictionary<int, MotionInput>> _motionData; private readonly Dictionary<int, Dictionary<int, MotionInput>> _motionData;
private readonly Dictionary<int, UdpClient> _clients; private readonly Dictionary<int, UdpClient> _clients;
private readonly bool[] _clientErrorStatus = new bool[Enum.GetValues(typeof(PlayerIndex)).Length]; private readonly bool[] _clientErrorStatus = new bool[Enum.GetValues<PlayerIndex>().Length];
private readonly long[] _clientRetryTimer = new long[Enum.GetValues(typeof(PlayerIndex)).Length]; private readonly long[] _clientRetryTimer = new long[Enum.GetValues<PlayerIndex>().Length];
private NpadManager _npadManager; private NpadManager _npadManager;
public Client(NpadManager npadManager) public Client(NpadManager npadManager)

View File

@ -77,6 +77,44 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise]
public void Shadd8([Values(0u, 0xdu)] uint rd,
[Values(1u)] uint rm,
[Values(2u)] uint rn,
[Random(RndCnt)] uint w0,
[Random(RndCnt)] uint w1,
[Random(RndCnt)] uint w2)
{
uint opcode = 0xE6300F90u; // SHADD8 R0, R0, R0
opcode |= ((rm & 15) << 0) | ((rd & 15) << 12) | ((rn & 15) << 16);
uint sp = TestContext.CurrentContext.Random.NextUInt();
SingleOpcode(opcode, r0: w0, r1: w1, r2: w2, sp: sp);
CompareAgainstUnicorn();
}
[Test, Pairwise]
public void Shsub8([Values(0u, 0xdu)] uint rd,
[Values(1u)] uint rm,
[Values(2u)] uint rn,
[Random(RndCnt)] uint w0,
[Random(RndCnt)] uint w1,
[Random(RndCnt)] uint w2)
{
uint opcode = 0xE6300FF0u; // SHSUB8 R0, R0, R0
opcode |= ((rm & 15) << 0) | ((rd & 15) << 12) | ((rn & 15) << 16);
uint sp = TestContext.CurrentContext.Random.NextUInt();
SingleOpcode(opcode, r0: w0, r1: w1, r2: w2, sp: sp);
CompareAgainstUnicorn();
}
[Test, Pairwise] [Test, Pairwise]
public void Ssat_Usat([ValueSource("_Ssat_Usat_")] uint opcode, public void Ssat_Usat([ValueSource("_Ssat_Usat_")] uint opcode,
[Values(0u, 0xdu)] uint rd, [Values(0u, 0xdu)] uint rd,
@ -130,6 +168,25 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise]
public void Uhsub8([Values(0u, 0xdu)] uint rd,
[Values(1u)] uint rm,
[Values(2u)] uint rn,
[Random(RndCnt)] uint w0,
[Random(RndCnt)] uint w1,
[Random(RndCnt)] uint w2)
{
uint opcode = 0xE6700FF0u; // UHSUB8 R0, R0, R0
opcode |= ((rm & 15) << 0) | ((rd & 15) << 12) | ((rn & 15) << 16);
uint sp = TestContext.CurrentContext.Random.NextUInt();
SingleOpcode(opcode, r0: w0, r1: w1, r2: w2, sp: sp);
CompareAgainstUnicorn();
}
#endif #endif
} }
} }

View File

@ -58,7 +58,7 @@ namespace Ryujinx.Configuration
{ {
bool noFilter = e.NewValue.Length == 0; bool noFilter = e.NewValue.Length == 0;
foreach (var logClass in EnumExtensions.GetValues<LogClass>()) foreach (var logClass in Enum.GetValues<LogClass>())
{ {
Logger.SetEnable(logClass, noFilter); Logger.SetEnable(logClass, noFilter);
} }

View File

@ -150,7 +150,7 @@ namespace Ryujinx.Input.GTK3
static GTK3MappingHelper() static GTK3MappingHelper()
{ {
var inputKeys = Enum.GetValues(typeof(Key)); var inputKeys = Enum.GetValues<Key>();
// GtkKey is not contiguous and quite large, so use a dictionary instead of an array. // GtkKey is not contiguous and quite large, so use a dictionary instead of an array.
_gtkKeyMapping = new Dictionary<GtkKey, Key>(); _gtkKeyMapping = new Dictionary<GtkKey, Key>();

Some files were not shown because too many files have changed in this diff Show More