Compare commits

..

12 Commits

Author SHA1 Message Date
Mary
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
gdkchan
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
Mary
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
gdkchan
7bfb5f79b8 When copying linear textures, DMA should ignore region X/Y (#3121) 2022-02-16 11:13:45 +01:00
skrek
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
Berkan Diler
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
merry
ce71f9144e InstEmitMemory32: Literal loads always have word-aligned PC (#3104) 2022-02-11 17:51:03 -03:00
gdkchan
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
edisionnano
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
gdkchan
c3c3914ed3 Add a limit on the number of uses a constant may have (#3097) 2022-02-09 17:42:47 -03:00
Mary
6dffe0fad4 misc: Make PID unsigned long instead of long (#3043) 2022-02-09 17:18:07 -03:00
merry
86b37d0ff7 ARMeilleure: A32: Implement SHSUB8 and UHSUB8 (#3089)
* ARMeilleure: A32: Implement UHSUB8

* ARMeilleure: A32: Implement SHSUB8
2022-02-08 10:46:42 +01:00
91 changed files with 463 additions and 287 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

@@ -734,6 +734,7 @@ namespace ARMeilleure.Decoders
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("<<<<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);
@@ -782,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

@@ -392,6 +392,11 @@ namespace ARMeilleure.Instructions
EmitHadd8(context, false); 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;
@@ -482,6 +487,11 @@ namespace ARMeilleure.Instructions
EmitHadd8(context, true); EmitHadd8(context, true);
} }
public static void Uhsub8(ArmEmitterContext context)
{
EmitHsub8(context, true);
}
public static void Usat(ArmEmitterContext context) public static void Usat(ArmEmitterContext context)
{ {
OpCode32Sat op = (OpCode32Sat)context.CurrOp; OpCode32Sat op = (OpCode32Sat)context.CurrOp;
@@ -681,6 +691,41 @@ namespace ARMeilleure.Instructions
SetIntA32(context, op.Rd, res); 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,
@@ -546,6 +547,7 @@ namespace ARMeilleure.Instructions
Tst, Tst,
Ubfx, Ubfx,
Uhadd8, Uhadd8,
Uhsub8,
Umaal, Umaal,
Umlal, Umlal,
Umull, Umull,

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

@@ -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

@@ -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

@@ -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

@@ -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

@@ -5,32 +5,35 @@ namespace Ryujinx.Graphics.Shader
{ {
public class ShaderProgramInfo public class ShaderProgramInfo
{ {
public ReadOnlyCollection<BufferDescriptor> CBuffers { get; } public ReadOnlyCollection<BufferDescriptor> CBuffers { get; }
public ReadOnlyCollection<BufferDescriptor> SBuffers { get; } public ReadOnlyCollection<BufferDescriptor> SBuffers { get; }
public ReadOnlyCollection<TextureDescriptor> Textures { get; } public ReadOnlyCollection<TextureDescriptor> Textures { get; }
public ReadOnlyCollection<TextureDescriptor> Images { get; } public ReadOnlyCollection<TextureDescriptor> Images { get; }
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,
BufferDescriptor[] sBuffers, BufferDescriptor[] sBuffers,
TextureDescriptor[] textures, TextureDescriptor[] textures,
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);
Textures = Array.AsReadOnly(textures); Textures = Array.AsReadOnly(textures);
Images = Array.AsReadOnly(images); Images = Array.AsReadOnly(images);
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,9 +25,9 @@ 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; }
public IGpuAccessor GpuAccessor { get; } public IGpuAccessor GpuAccessor { 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; }
@@ -85,7 +54,7 @@ namespace Ryujinx.Graphics.Shader.Translation
public bool GpPassthrough { get; } public bool GpPassthrough { get; }
public bool DoesLoadOrStore { get; } public bool DoesLoadOrStore { get; }
public bool DoesFp64 { get; } public bool DoesFp64 { get; }
public int StreamOutMask { get; } public int StreamOutMask { get; }
@@ -104,13 +73,13 @@ namespace Ryujinx.Graphics.Shader.Translation
public int MaxOutputVertexCount { get; } public int MaxOutputVertexCount { get; }
public int StoreReqStart { get; } public int StoreReqStart { get; }
public int StoreReqEnd { get; } public int StoreReqEnd { get; }
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; }
public ShaderHeader(IGpuAccessor gpuAccessor, ulong address) public ShaderHeader(IGpuAccessor gpuAccessor, ulong address)
{ {
@@ -144,7 +113,7 @@ namespace Ryujinx.Graphics.Shader.Translation
GpPassthrough = commonWord0.Extract(24); GpPassthrough = commonWord0.Extract(24);
DoesLoadOrStore = commonWord0.Extract(26); DoesLoadOrStore = commonWord0.Extract(26);
DoesFp64 = commonWord0.Extract(27); DoesFp64 = commonWord0.Extract(27);
StreamOutMask = commonWord0.Extract(28, 4); StreamOutMask = commonWord0.Extract(28, 4);
@@ -163,7 +132,7 @@ namespace Ryujinx.Graphics.Shader.Translation
MaxOutputVertexCount = commonWord4.Extract(0, 12); MaxOutputVertexCount = commonWord4.Extract(0, 12);
StoreReqStart = commonWord4.Extract(12, 8); StoreReqStart = commonWord4.Extract(12, 8);
StoreReqEnd = commonWord4.Extract(24, 8); StoreReqEnd = commonWord4.Extract(24, 8);
ImapTypes = new ImapPixelType[32]; ImapTypes = new ImapPixelType[32];
@@ -179,21 +148,11 @@ 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];
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));
}
OmapTargets = type2OmapTarget;
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

@@ -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

@@ -96,6 +96,25 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); 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,
@@ -149,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>();

View File

@@ -1209,7 +1209,7 @@ namespace Ryujinx.Ui
{ {
AspectRatio aspectRatio = ConfigurationState.Instance.Graphics.AspectRatio.Value; AspectRatio aspectRatio = ConfigurationState.Instance.Graphics.AspectRatio.Value;
ConfigurationState.Instance.Graphics.AspectRatio.Value = ((int)aspectRatio + 1) > Enum.GetNames(typeof(AspectRatio)).Length - 1 ? AspectRatio.Fixed4x3 : aspectRatio + 1; ConfigurationState.Instance.Graphics.AspectRatio.Value = ((int)aspectRatio + 1) > Enum.GetNames<AspectRatio>().Length - 1 ? AspectRatio.Fixed4x3 : aspectRatio + 1;
} }
private void Row_Clicked(object sender, ButtonReleaseEventArgs args) private void Row_Clicked(object sender, ButtonReleaseEventArgs args)

View File

@@ -181,7 +181,7 @@ namespace Ryujinx.Ui.Windows
_fsAccessLogToggle.Click(); _fsAccessLogToggle.Click();
} }
foreach (GraphicsDebugLevel level in Enum.GetValues(typeof(GraphicsDebugLevel))) foreach (GraphicsDebugLevel level in Enum.GetValues<GraphicsDebugLevel>())
{ {
_graphicsDebugLevel.Append(level.ToString(), level.ToString()); _graphicsDebugLevel.Append(level.ToString(), level.ToString());
} }