misc: chore: Fix numerous NullReferenceExceptions, InvalidOperationExceptions

This commit is contained in:
KeatonTheBot 2025-06-17 17:17:31 -05:00
parent a90db3464d
commit d2a532f971
90 changed files with 667 additions and 533 deletions

View file

@ -59,7 +59,11 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
for (int y = 0; y < context.SampleCount; y++) for (int y = 0; y < context.SampleCount; y++)
{ {
context.MemoryManager.Write(targetOffset + (ulong)y * TargetChannelCount, PcmHelper.Saturate(inputBuffer[y])); if (inputBuffer != null)
{
context.MemoryManager.Write(targetOffset + (ulong)y * TargetChannelCount,
PcmHelper.Saturate(inputBuffer[y]));
}
} }
currentOffset += context.SampleCount * TargetChannelCount; currentOffset += context.SampleCount * TargetChannelCount;

View file

@ -318,13 +318,16 @@ namespace Ryujinx.Common.Collections
{ {
Root = newNode; Root = newNode;
} }
else if (start.CompareTo(parent.Start) < 0) else if (parent != null && start.CompareTo(parent.Start) < 0)
{ {
parent.Left = newNode; parent.Left = newNode;
} }
else else
{ {
parent.Right = newNode; if (parent != null)
{
parent.Right = newNode;
}
} }
PropagateIncrease(newNode); PropagateIncrease(newNode);

View file

@ -279,13 +279,16 @@ namespace Ryujinx.Common.Collections
{ {
Root = newNode; Root = newNode;
} }
else if (key.CompareTo(parent.Key) < 0) else if (parent != null && key.CompareTo(parent.Key) < 0)
{ {
parent.Left = newNode; parent.Left = newNode;
} }
else else
{ {
parent.Right = newNode; if (parent != null)
{
parent.Right = newNode;
}
} }
Count++; Count++;
return newNode; return newNode;

View file

@ -273,7 +273,7 @@ namespace Ryujinx.Common.Configuration
{ {
FileSystemInfo resolvedDirectoryInfo = FileSystemInfo resolvedDirectoryInfo =
Directory.ResolveLinkTarget(correctApplicationDataDirectoryPath, true); Directory.ResolveLinkTarget(correctApplicationDataDirectoryPath, true);
string resolvedPath = resolvedDirectoryInfo.FullName; string resolvedPath = resolvedDirectoryInfo?.FullName;
Logger.Error?.Print(LogClass.Application, $"Please manually move your Ryujinx data from {resolvedPath} to {correctApplicationDataDirectoryPath}, and remove the symlink."); Logger.Error?.Print(LogClass.Application, $"Please manually move your Ryujinx data from {resolvedPath} to {correctApplicationDataDirectoryPath}, and remove the symlink.");
} }
catch (Exception symlinkException) catch (Exception symlinkException)
@ -297,7 +297,7 @@ namespace Ryujinx.Common.Configuration
{ {
FileSystemInfo resolvedDirectoryInfo = FileSystemInfo resolvedDirectoryInfo =
Directory.ResolveLinkTarget(correctApplicationDataDirectoryPath, true); Directory.ResolveLinkTarget(correctApplicationDataDirectoryPath, true);
string resolvedPath = resolvedDirectoryInfo.FullName; string resolvedPath = resolvedDirectoryInfo?.FullName;
Logger.Error?.Print(LogClass.Application, $"Please manually move your Ryujinx data from {resolvedPath} to {correctApplicationDataDirectoryPath}, and remove the symlink."); Logger.Error?.Print(LogClass.Application, $"Please manually move your Ryujinx data from {resolvedPath} to {correctApplicationDataDirectoryPath}, and remove the symlink.");
} }
catch (Exception symlinkException) catch (Exception symlinkException)

View file

@ -25,7 +25,7 @@ namespace Ryujinx.Common.Configuration.Hid.Controller.Motion
{ {
string propertyName = tempReader.GetString(); string propertyName = tempReader.GetString();
if (propertyName.Equals("motion_backend")) if (propertyName is "motion_backend")
{ {
tempReader.Read(); tempReader.Read();

View file

@ -27,7 +27,7 @@ namespace Ryujinx.Common.Configuration.Hid
{ {
string propertyName = tempReader.GetString(); string propertyName = tempReader.GetString();
if (propertyName.Equals("backend")) if (propertyName is "backend")
{ {
tempReader.Read(); tempReader.Read();

View file

@ -24,7 +24,7 @@ namespace Ryujinx.Common.Logging
public readonly struct Log public readonly struct Log
{ {
private static readonly string _homeDir = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); private static readonly string _homeDir = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
private static readonly string _homeDirRedacted = Path.Combine(Directory.GetParent(_homeDir).FullName, "[redacted]"); private static readonly string _homeDirRedacted = Path.Combine(Directory.GetParent(_homeDir)?.FullName ?? string.Empty, "[redacted]");
internal readonly LogLevel Level; internal readonly LogLevel Level;

View file

@ -258,23 +258,26 @@ namespace ARMeilleure.Common
for (int i = 0; i < Levels.Length - 1; i++) for (int i = 0; i < Levels.Length - 1; i++)
{ {
ref AddressTableLevel level = ref Levels[i]; ref AddressTableLevel level = ref Levels[i];
ref TEntry* nextPage = ref page[level.GetValue(address)]; if (page != null)
if (nextPage == null || nextPage == _fillBottomLevelPtr)
{ {
ref AddressTableLevel nextLevel = ref Levels[i + 1]; ref TEntry* nextPage = ref page[level.GetValue(address)];
if (i == Levels.Length - 2) if (nextPage == null || nextPage == _fillBottomLevelPtr)
{ {
nextPage = (TEntry*)Allocate(1 << nextLevel.Length, Fill, leaf: true); ref AddressTableLevel nextLevel = ref Levels[i + 1];
}
else if (i == Levels.Length - 2)
{ {
nextPage = (TEntry*)Allocate(1 << nextLevel.Length, GetFillValue(i), leaf: false); nextPage = (TEntry*)Allocate(1 << nextLevel.Length, Fill, leaf: true);
}
else
{
nextPage = (TEntry*)Allocate(1 << nextLevel.Length, GetFillValue(i), leaf: false);
}
} }
page = (TEntry**)nextPage;
} }
page = (TEntry**)nextPage;
} }
return (TEntry*)page; return (TEntry*)page;

View file

@ -388,7 +388,12 @@ namespace Ryujinx.Cpu.Jit.HostTracked
_treeLock.ExitReadLock(); _treeLock.ExitReadLock();
} }
return (_backingMemory, _firstPagePa.Value); if (_firstPagePa != null)
{
return (_backingMemory, _firstPagePa.Value);
}
return (null, 0);
} }
public PrivateRange GetPrivateAllocation(ulong va) public PrivateRange GetPrivateAllocation(ulong va)

View file

@ -135,7 +135,10 @@ namespace Ryujinx.Cpu.Jit
offset += (int)copySize; offset += (int)copySize;
} }
return new ReadOnlySequence<byte>(first, 0, last, (int)(size - last.RunningIndex)); if (last != null)
{
return new ReadOnlySequence<byte>(first, 0, last, (int)(size - last.RunningIndex));
}
} }
catch (InvalidMemoryRegionException) catch (InvalidMemoryRegionException)
{ {
@ -146,6 +149,8 @@ namespace Ryujinx.Cpu.Jit
return ReadOnlySequence<byte>.Empty; return ReadOnlySequence<byte>.Empty;
} }
return default;
} }
/// <inheritdoc/> /// <inheritdoc/>

View file

@ -872,7 +872,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
if (unscaled) if (unscaled)
{ {
writeInstUnscaled(rt, tempRegister.Operand, offs); writeInstUnscaled?.Invoke(rt, tempRegister.Operand, offs);
} }
else else
{ {

View file

@ -126,7 +126,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
if (Volatile.Read(ref _interruptAction) != null) if (Volatile.Read(ref _interruptAction) != null)
{ {
_interruptAction(); _interruptAction?.Invoke();
_interruptRun.Set(); _interruptRun.Set();
Interlocked.Exchange(ref _interruptAction, null); Interlocked.Exchange(ref _interruptAction, null);

View file

@ -297,7 +297,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
EmitLoadGprA(opCode); EmitLoadGprA(opCode);
EmitLoadImm(opCode); EmitLoadImm(opCode);
_ilGen.Emit(OpCodes.Add); _ilGen.Emit(OpCodes.Add);
_ilGen.Emit(OpCodes.Call, typeof(MacroJitContext).GetMethod(nameof(MacroJitContext.Read))); _ilGen.Emit(OpCodes.Call, typeof(MacroJitContext).GetMethod(nameof(MacroJitContext.Read))!);
break; break;
default: default:
@ -457,7 +457,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
private void EmitFetchParam() private void EmitFetchParam()
{ {
_ilGen.Emit(OpCodes.Ldarg_0); _ilGen.Emit(OpCodes.Ldarg_0);
_ilGen.Emit(OpCodes.Call, typeof(MacroJitContext).GetMethod(nameof(MacroJitContext.FetchParam))); _ilGen.Emit(OpCodes.Call, typeof(MacroJitContext).GetMethod(nameof(MacroJitContext.FetchParam))!);
} }
/// <summary> /// <summary>
@ -508,7 +508,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
{ {
_ilGen.Emit(OpCodes.Ldarg_1); _ilGen.Emit(OpCodes.Ldarg_1);
_ilGen.Emit(OpCodes.Ldloc_S, _methAddr); _ilGen.Emit(OpCodes.Ldloc_S, _methAddr);
_ilGen.Emit(OpCodes.Call, typeof(MacroJitContext).GetMethod(nameof(MacroJitContext.Send))); _ilGen.Emit(OpCodes.Call, typeof(MacroJitContext).GetMethod(nameof(MacroJitContext.Send))!);
_ilGen.Emit(OpCodes.Ldloc_S, _methAddr); _ilGen.Emit(OpCodes.Ldloc_S, _methAddr);
_ilGen.Emit(OpCodes.Ldloc_S, _methIncr); _ilGen.Emit(OpCodes.Ldloc_S, _methIncr);
_ilGen.Emit(OpCodes.Add); _ilGen.Emit(OpCodes.Add);

View file

@ -173,24 +173,27 @@ namespace Ryujinx.Graphics.Gpu.Image
/// </summary> /// </summary>
private void RemoveLeastUsedTexture() private void RemoveLeastUsedTexture()
{ {
Texture oldestTexture = _textures.First.Value; if (_textures.First != null)
_totalSize -= oldestTexture.Size;
if (!oldestTexture.CheckModified(false))
{ {
// The texture must be flushed if it falls out of the auto delete cache. Texture oldestTexture = _textures.First.Value;
// Flushes out of the auto delete cache do not trigger write tracking,
// as it is expected that other overlapping textures exist that have more up-to-date contents.
oldestTexture.Group.SynchronizeDependents(oldestTexture); _totalSize -= oldestTexture.Size;
oldestTexture.FlushModified(false);
if (!oldestTexture.CheckModified(false))
{
// The texture must be flushed if it falls out of the auto delete cache.
// Flushes out of the auto delete cache do not trigger write tracking,
// as it is expected that other overlapping textures exist that have more up-to-date contents.
oldestTexture.Group.SynchronizeDependents(oldestTexture);
oldestTexture.FlushModified(false);
}
_textures.RemoveFirst();
oldestTexture.DecrementReferenceCount();
oldestTexture.CacheNode = null;
} }
_textures.RemoveFirst();
oldestTexture.DecrementReferenceCount();
oldestTexture.CacheNode = null;
} }
/// <summary> /// <summary>

View file

@ -67,7 +67,8 @@ namespace Ryujinx.Graphics.Gpu.Image
public T FindOrCreate(GpuChannel channel, ulong address, int maximumId, TextureBindingsArrayCache bindingsArrayCache) public T FindOrCreate(GpuChannel channel, ulong address, int maximumId, TextureBindingsArrayCache bindingsArrayCache)
{ {
// Remove old entries from the cache, if possible. // Remove old entries from the cache, if possible.
while (_pools.Count > MaxCapacity && (_currentTimestamp - _pools.First.Value.CacheTimestamp) >= MinDeltaForRemoval) while (_pools.Count > MaxCapacity && _pools.First != null &&
(_currentTimestamp - _pools.First.Value.CacheTimestamp) >= MinDeltaForRemoval)
{ {
T oldestPool = _pools.First.Value; T oldestPool = _pools.First.Value;

View file

@ -372,7 +372,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
if (rangeCount == -1) if (rangeCount == -1)
{ {
_migrationTarget.WaitForAndFlushRanges(address, size); _migrationTarget?.WaitForAndFlushRanges(address, size);
return; return;
} }

View file

@ -481,7 +481,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
} }
int offset = Unsafe.SizeOf<TocHeader>() + programIndex * Unsafe.SizeOf<OffsetAndSize>(); int offset = Unsafe.SizeOf<TocHeader>() + programIndex * Unsafe.SizeOf<OffsetAndSize>();
if (offset + Unsafe.SizeOf<OffsetAndSize>() > tocFileStream.Length) if (tocFileStream != null && offset + Unsafe.SizeOf<OffsetAndSize>() > tocFileStream.Length)
{ {
return (null, null); return (null, null);
} }
@ -491,7 +491,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
throw new DiskCacheLoadException(DiskCacheLoadResult.FileCorruptedGeneric); throw new DiskCacheLoadException(DiskCacheLoadResult.FileCorruptedGeneric);
} }
tocFileStream.Seek(offset, SeekOrigin.Begin); tocFileStream?.Seek(offset, SeekOrigin.Begin);
BinarySerializer tocReader = new(tocFileStream); BinarySerializer tocReader = new(tocFileStream);

View file

@ -991,8 +991,11 @@ namespace Ryujinx.Graphics.Gpu.Shader
if (hasPipelineState) if (hasPipelineState)
{ {
ProgramPipelineState pipelineState = PipelineState.Value; if (PipelineState != null)
dataWriter.WriteWithMagicAndSize(ref pipelineState, PgpsMagic); {
ProgramPipelineState pipelineState = PipelineState.Value;
dataWriter.WriteWithMagicAndSize(ref pipelineState, PgpsMagic);
}
} }
if (_queriedState.HasFlag(QueriedStateFlags.TransformFeedback)) if (_queriedState.HasFlag(QueriedStateFlags.TransformFeedback))

View file

@ -91,7 +91,7 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg
FFmpegApi.av_log_format_line(ptr, level, format, vl, lineBuffer, lineSize, &printPrefix); FFmpegApi.av_log_format_line(ptr, level, format, vl, lineBuffer, lineSize, &printPrefix);
string line = Marshal.PtrToStringAnsi((IntPtr)lineBuffer).Trim(); string line = Marshal.PtrToStringAnsi((IntPtr)lineBuffer)?.Trim();
switch (level) switch (level)
{ {

View file

@ -59,7 +59,7 @@ namespace Ryujinx.Graphics.OpenGL
IntPtr message, IntPtr message,
IntPtr userParam) IntPtr userParam)
{ {
string msg = Marshal.PtrToStringUTF8(message).Replace('\n', ' '); string msg = Marshal.PtrToStringUTF8(message)?.Replace('\n', ' ');
switch (type) switch (type)
{ {

View file

@ -94,7 +94,7 @@ namespace Ryujinx.Graphics.OpenGL.Effects
GL.UseProgram(previousProgram); GL.UseProgram(previousProgram);
GL.MemoryBarrier(MemoryBarrierFlags.ShaderImageAccessBarrierBit); GL.MemoryBarrier(MemoryBarrierFlags.ShaderImageAccessBarrierBit);
(_renderer.Pipeline as Pipeline).RestoreImages1And2(); (_renderer.Pipeline as Pipeline)?.RestoreImages1And2();
GL.ActiveTexture(TextureUnit.Texture0); GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, previousTextureBinding); GL.BindTexture(TextureTarget.Texture2D, previousTextureBinding);

View file

@ -125,48 +125,53 @@ namespace Ryujinx.Graphics.OpenGL.Effects
GL.ActiveTexture(TextureUnit.Texture0); GL.ActiveTexture(TextureUnit.Texture0);
int previousTextureBinding = GL.GetInteger(GetPName.TextureBinding2D); int previousTextureBinding = GL.GetInteger(GetPName.TextureBinding2D);
GL.BindImageTexture(0, textureView.Handle, 0, false, 0, TextureAccess.ReadWrite, SizedInternalFormat.Rgba8); if (textureView != null)
{
GL.BindImageTexture(0, textureView.Handle, 0, false, 0, TextureAccess.ReadWrite,
SizedInternalFormat.Rgba8);
int threadGroupWorkRegionDim = 16; int threadGroupWorkRegionDim = 16;
int dispatchX = (width + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; int dispatchX = (width + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
int dispatchY = (height + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; int dispatchY = (height + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
// Scaling pass // Scaling pass
float srcWidth = Math.Abs(source.X2 - source.X1); float srcWidth = Math.Abs(source.X2 - source.X1);
float srcHeight = Math.Abs(source.Y2 - source.Y1); float srcHeight = Math.Abs(source.Y2 - source.Y1);
float scaleX = srcWidth / view.Width; float scaleX = srcWidth / view.Width;
float scaleY = srcHeight / view.Height; float scaleY = srcHeight / view.Height;
GL.UseProgram(_scalingShaderProgram); GL.UseProgram(_scalingShaderProgram);
view.Bind(0); view.Bind(0);
GL.Uniform1(_inputUniform, 0); GL.Uniform1(_inputUniform, 0);
GL.Uniform1(_outputUniform, 0); GL.Uniform1(_outputUniform, 0);
GL.Uniform1(_srcX0Uniform, (float)source.X1); GL.Uniform1(_srcX0Uniform, (float)source.X1);
GL.Uniform1(_srcX1Uniform, (float)source.X2); GL.Uniform1(_srcX1Uniform, (float)source.X2);
GL.Uniform1(_srcY0Uniform, (float)source.Y1); GL.Uniform1(_srcY0Uniform, (float)source.Y1);
GL.Uniform1(_srcY1Uniform, (float)source.Y2); GL.Uniform1(_srcY1Uniform, (float)source.Y2);
GL.Uniform1(_dstX0Uniform, (float)destination.X1); GL.Uniform1(_dstX0Uniform, (float)destination.X1);
GL.Uniform1(_dstX1Uniform, (float)destination.X2); GL.Uniform1(_dstX1Uniform, (float)destination.X2);
GL.Uniform1(_dstY0Uniform, (float)destination.Y1); GL.Uniform1(_dstY0Uniform, (float)destination.Y1);
GL.Uniform1(_dstY1Uniform, (float)destination.Y2); GL.Uniform1(_dstY1Uniform, (float)destination.Y2);
GL.Uniform1(_scaleXUniform, scaleX); GL.Uniform1(_scaleXUniform, scaleX);
GL.Uniform1(_scaleYUniform, scaleY); GL.Uniform1(_scaleYUniform, scaleY);
GL.DispatchCompute(dispatchX, dispatchY, 1); GL.DispatchCompute(dispatchX, dispatchY, 1);
GL.MemoryBarrier(MemoryBarrierFlags.ShaderImageAccessBarrierBit); GL.MemoryBarrier(MemoryBarrierFlags.ShaderImageAccessBarrierBit);
// Sharpening Pass // Sharpening Pass
GL.UseProgram(_sharpeningShaderProgram); GL.UseProgram(_sharpeningShaderProgram);
GL.BindImageTexture(0, destinationTexture.Handle, 0, false, 0, TextureAccess.ReadWrite, SizedInternalFormat.Rgba8); GL.BindImageTexture(0, destinationTexture.Handle, 0, false, 0, TextureAccess.ReadWrite,
textureView.Bind(0); SizedInternalFormat.Rgba8);
GL.Uniform1(_inputUniform, 0); textureView.Bind(0);
GL.Uniform1(_outputUniform, 0); GL.Uniform1(_inputUniform, 0);
GL.Uniform1(_sharpeningUniform, 1.5f - (Level * 0.01f * 1.5f)); GL.Uniform1(_outputUniform, 0);
GL.DispatchCompute(dispatchX, dispatchY, 1); GL.Uniform1(_sharpeningUniform, 1.5f - (Level * 0.01f * 1.5f));
GL.DispatchCompute(dispatchX, dispatchY, 1);
}
GL.UseProgram(previousProgram); GL.UseProgram(previousProgram);
GL.MemoryBarrier(MemoryBarrierFlags.ShaderImageAccessBarrierBit); GL.MemoryBarrier(MemoryBarrierFlags.ShaderImageAccessBarrierBit);
(_renderer.Pipeline as Pipeline).RestoreImages1And2(); (_renderer.Pipeline as Pipeline)?.RestoreImages1And2();
GL.ActiveTexture(TextureUnit.Texture0); GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, previousTextureBinding); GL.BindTexture(TextureTarget.Texture2D, previousTextureBinding);

View file

@ -68,7 +68,7 @@ namespace Ryujinx.Graphics.OpenGL.Effects
GL.UseProgram(previousProgram); GL.UseProgram(previousProgram);
GL.MemoryBarrier(MemoryBarrierFlags.ShaderImageAccessBarrierBit); GL.MemoryBarrier(MemoryBarrierFlags.ShaderImageAccessBarrierBit);
(_renderer.Pipeline as Pipeline).RestoreImages1And2(); (_renderer.Pipeline as Pipeline)?.RestoreImages1And2();
GL.ActiveTexture(TextureUnit.Texture0); GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, previousTextureBinding); GL.BindTexture(TextureTarget.Texture2D, previousTextureBinding);

View file

@ -222,8 +222,8 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
GL.BindImageTexture(0, blendOutput.Handle, 0, false, 0, TextureAccess.ReadWrite, SizedInternalFormat.Rgba8); GL.BindImageTexture(0, blendOutput.Handle, 0, false, 0, TextureAccess.ReadWrite, SizedInternalFormat.Rgba8);
GL.UseProgram(_blendShaderPrograms[Quality]); GL.UseProgram(_blendShaderPrograms[Quality]);
edgeOutput.Bind(0); edgeOutput.Bind(0);
areaTexture.Bind(1); areaTexture?.Bind(1);
searchTexture.Bind(2); searchTexture?.Bind(2);
GL.Uniform1(_inputUniform, 0); GL.Uniform1(_inputUniform, 0);
GL.Uniform1(_outputUniform, 0); GL.Uniform1(_outputUniform, 0);
GL.Uniform1(_samplerAreaUniform, 1); GL.Uniform1(_samplerAreaUniform, 1);
@ -243,7 +243,7 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
GL.DispatchCompute(dispatchX, dispatchY, 1); GL.DispatchCompute(dispatchX, dispatchY, 1);
GL.MemoryBarrier(MemoryBarrierFlags.ShaderImageAccessBarrierBit); GL.MemoryBarrier(MemoryBarrierFlags.ShaderImageAccessBarrierBit);
(_renderer.Pipeline as Pipeline).RestoreImages1And2(); (_renderer.Pipeline as Pipeline)?.RestoreImages1And2();
GL.UseProgram(previousProgram); GL.UseProgram(previousProgram);

View file

@ -65,7 +65,10 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
if (lastOp is Operation operation && IsControlFlowInst(operation.Inst)) if (lastOp is Operation operation && IsControlFlowInst(operation.Inst))
{ {
Operations.AddBefore(Operations.Last, node); if (Operations.Last != null)
{
Operations.AddBefore(Operations.Last, node);
}
} }
else else
{ {

View file

@ -158,7 +158,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
} }
} }
if (handleAsgOp.Inst != Instruction.Load || if (handleAsgOp is not { Inst: Instruction.Load } ||
handleAsgOp.StorageKind != StorageKind.ConstantBuffer || handleAsgOp.StorageKind != StorageKind.ConstantBuffer ||
handleAsgOp.SourcesCount != 4) handleAsgOp.SourcesCount != 4)
{ {

View file

@ -34,7 +34,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
operation.Dest = null; operation.Dest = null;
LinkedListNode<INode> newNode = node.List.AddBefore(node, new Operation(Instruction.Call, 0, floatValue, callArgs)); LinkedListNode<INode> newNode = node.List?.AddBefore(node, new Operation(Instruction.Call, 0, floatValue, callArgs));
Utils.DeleteNode(node, operation); Utils.DeleteNode(node, operation);
@ -53,7 +53,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
Operand[] callArgs = [Const(functionId), operation.GetSource(0), resultLow, resultHigh]; Operand[] callArgs = [Const(functionId), operation.GetSource(0), resultLow, resultHigh];
LinkedListNode<INode> newNode = node.List.AddBefore(node, new Operation(Instruction.Call, 0, (Operand)null, callArgs)); LinkedListNode<INode> newNode = node.List?.AddBefore(node, new Operation(Instruction.Call, 0, (Operand)null, callArgs));
Utils.DeleteNode(node, operation); Utils.DeleteNode(node, operation);

View file

@ -305,7 +305,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
LinkedListNode<INode> node) LinkedListNode<INode> node)
{ {
Operation operation = node.Value as Operation; Operation operation = node.Value as Operation;
Operand globalAddress = operation.GetSource(0); Operand globalAddress = operation?.GetSource(0);
SearchResult result = FindUniqueBaseAddressCb(gtsContext, block, globalAddress, needsOffset: true); SearchResult result = FindUniqueBaseAddressCb(gtsContext, block, globalAddress, needsOffset: true);
if (result.Found) if (result.Found)
@ -331,8 +331,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
Operation maskOp = new(Instruction.BitwiseAnd, baseAddressMasked, baseAddress, Const(-alignment)); Operation maskOp = new(Instruction.BitwiseAnd, baseAddressMasked, baseAddress, Const(-alignment));
Operation subOp = new(Instruction.Subtract, hostOffset, globalAddress, baseAddressMasked); Operation subOp = new(Instruction.Subtract, hostOffset, globalAddress, baseAddressMasked);
node.List.AddBefore(node, maskOp); node.List?.AddBefore(node, maskOp);
node.List.AddBefore(node, subOp); node.List?.AddBefore(node, subOp);
offset = hostOffset; offset = hostOffset;
} }
@ -342,7 +342,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
Operation addOp = new(Instruction.Add, newOffset, offset, Const(result.ConstOffset)); Operation addOp = new(Instruction.Add, newOffset, offset, Const(result.ConstOffset));
node.List.AddBefore(node, addOp); node.List?.AddBefore(node, addOp);
offset = newOffset; offset = newOffset;
} }
@ -441,8 +441,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
Operation shiftOp = new(Instruction.ShiftRightU32, wordOffset, offset, Const(2)); Operation shiftOp = new(Instruction.ShiftRightU32, wordOffset, offset, Const(2));
Operation storageOp = new(operation.Inst, StorageKind.StorageBuffer, operation.Dest, sources); Operation storageOp = new(operation.Inst, StorageKind.StorageBuffer, operation.Dest, sources);
node.List.AddBefore(node, shiftOp); node.List?.AddBefore(node, shiftOp);
LinkedListNode<INode> newNode = node.List.AddBefore(node, storageOp); LinkedListNode<INode> newNode = node.List?.AddBefore(node, storageOp);
Utils.DeleteNode(node, operation); Utils.DeleteNode(node, operation);
@ -483,7 +483,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
Operation callOp = new(Instruction.Call, returnValue, sources); Operation callOp = new(Instruction.Call, returnValue, sources);
LinkedListNode<INode> newNode = node.List.AddBefore(node, callOp); LinkedListNode<INode> newNode = node.List?.AddBefore(node, callOp);
if (returnsValue) if (returnsValue)
{ {

View file

@ -189,7 +189,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
public static void DeleteNode(LinkedListNode<INode> node, Operation operation) public static void DeleteNode(LinkedListNode<INode> node, Operation operation)
{ {
node.List.Remove(node); node.List?.Remove(node);
for (int srcIndex = 0; srcIndex < operation.SourcesCount; srcIndex++) for (int srcIndex = 0; srcIndex < operation.SourcesCount; srcIndex++)
{ {

View file

@ -141,7 +141,7 @@ namespace Ryujinx.Graphics.Shader.Translation
{ {
Operation operation = node.Value as Operation; Operation operation = node.Value as Operation;
for (int srcIndex = 0; srcIndex < operation.SourcesCount; srcIndex++) for (int srcIndex = 0; srcIndex < operation?.SourcesCount; srcIndex++)
{ {
Operand source = operation.GetSource(srcIndex); Operand source = operation.GetSource(srcIndex);
@ -155,7 +155,7 @@ namespace Ryujinx.Graphics.Shader.Translation
localInputs[block.Index] |= GetMask(register) & ~localOutputs[block.Index]; localInputs[block.Index] |= GetMask(register) & ~localOutputs[block.Index];
} }
for (int dstIndex = 0; dstIndex < operation.DestsCount; dstIndex++) for (int dstIndex = 0; dstIndex < operation?.DestsCount; dstIndex++)
{ {
Operand dest = operation.GetDest(dstIndex); Operand dest = operation.GetDest(dstIndex);
@ -296,7 +296,7 @@ namespace Ryujinx.Graphics.Shader.Translation
{ {
Operation operation = node.Value as Operation; Operation operation = node.Value as Operation;
if (operation.Inst == Instruction.Call) if (operation?.Inst == Instruction.Call)
{ {
Operand funcId = operation.GetSource(0); Operand funcId = operation.GetSource(0);
@ -333,7 +333,7 @@ namespace Ryujinx.Graphics.Shader.Translation
return false; return false;
} }
return block.Operations.First.Value is Operation operation && operation.Inst == inst; return block.Operations.First?.Value is Operation operation && operation.Inst == inst;
} }
private static bool EndsWith(BasicBlock block, Instruction inst) private static bool EndsWith(BasicBlock block, Instruction inst)
@ -343,7 +343,7 @@ namespace Ryujinx.Graphics.Shader.Translation
return false; return false;
} }
return block.Operations.Last.Value is Operation operation && operation.Inst == inst; return block.Operations.Last?.Value is Operation operation && operation.Inst == inst;
} }
private static RegisterMask GetMask(Register register) private static RegisterMask GetMask(Register register)
@ -445,7 +445,10 @@ namespace Ryujinx.Graphics.Shader.Translation
if (node == null) if (node == null)
{ {
node = block.Operations.AddBefore(block.Operations.Last, copyOp); if (block.Operations.Last != null)
{
node = block.Operations.AddBefore(block.Operations.Last, copyOp);
}
} }
else else
{ {

View file

@ -36,7 +36,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
Operand GenerateLoad(IoVariable ioVariable) Operand GenerateLoad(IoVariable ioVariable)
{ {
Operand value = Local(); Operand value = Local();
node.List.AddBefore(node, new Operation(Instruction.Load, StorageKind.Input, value, Const((int)ioVariable))); node.List?.AddBefore(node, new Operation(Instruction.Load, StorageKind.Input, value, Const((int)ioVariable)));
return value; return value;
} }

View file

@ -45,7 +45,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
Operand vertexElemOffset = GenerateVertexOffset(context.ResourceManager, node, inputOffset, primVertex); Operand vertexElemOffset = GenerateVertexOffset(context.ResourceManager, node, inputOffset, primVertex);
newNode = node.List.AddBefore(node, new Operation( newNode = node.List?.AddBefore(node, new Operation(
Instruction.Load, Instruction.Load,
StorageKind.StorageBuffer, StorageKind.StorageBuffer,
operation.Dest, operation.Dest,
@ -80,7 +80,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
{ {
if (TryGetOffset(context.ResourceManager, operation, StorageKind.Output, out int outputOffset)) if (TryGetOffset(context.ResourceManager, operation, StorageKind.Output, out int outputOffset))
{ {
newNode = node.List.AddBefore(node, new Operation( newNode = node.List?.AddBefore(node, new Operation(
Instruction.Load, Instruction.Load,
StorageKind.LocalMemory, StorageKind.LocalMemory,
operation.Dest, operation.Dest,
@ -99,7 +99,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
{ {
Operand value = operation.GetSource(operation.SourcesCount - 1); Operand value = operation.GetSource(operation.SourcesCount - 1);
newNode = node.List.AddBefore(node, new Operation( newNode = node.List?.AddBefore(node, new Operation(
Instruction.Store, Instruction.Store,
StorageKind.LocalMemory, StorageKind.LocalMemory,
(Operand)null, (Operand)null,
@ -134,7 +134,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
definitions.MaxOutputVertices * definitions.ThreadsPerInputPrimitive, definitions.MaxOutputVertices * definitions.ThreadsPerInputPrimitive,
definitions.ThreadsPerInputPrimitive); definitions.ThreadsPerInputPrimitive);
Operand outputBaseVertex = Local(); Operand outputBaseVertex = Local();
node.List.AddBefore(node, new Operation(Instruction.Add, outputBaseVertex, new[] { baseVertexOffset, outputPrimVertex })); node.List?.AddBefore(node, new Operation(Instruction.Add, outputBaseVertex, new[] { baseVertexOffset, outputPrimVertex }));
Operand outputPrimIndex = IncrementLocalMemory(node, resourceManager.LocalGeometryOutputIndexCountMemoryId); Operand outputPrimIndex = IncrementLocalMemory(node, resourceManager.LocalGeometryOutputIndexCountMemoryId);
Operand baseIndexOffset = GenerateBaseOffset( Operand baseIndexOffset = GenerateBaseOffset(
@ -143,16 +143,16 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
definitions.GetGeometryOutputIndexBufferStride(), definitions.GetGeometryOutputIndexBufferStride(),
definitions.ThreadsPerInputPrimitive); definitions.ThreadsPerInputPrimitive);
Operand outputBaseIndex = Local(); Operand outputBaseIndex = Local();
node.List.AddBefore(node, new Operation(Instruction.Add, outputBaseIndex, new[] { baseIndexOffset, outputPrimIndex })); node.List?.AddBefore(node, new Operation(Instruction.Add, outputBaseIndex, new[] { baseIndexOffset, outputPrimIndex }));
node.List.AddBefore(node, new Operation( node.List?.AddBefore(node, new Operation(
Instruction.Store, Instruction.Store,
StorageKind.StorageBuffer, StorageKind.StorageBuffer,
null, null,
new[] { Const(ibOutputBinding), Const(0), outputBaseIndex, outputBaseVertex })); new[] { Const(ibOutputBinding), Const(0), outputBaseIndex, outputBaseVertex }));
Operand baseOffset = Local(); Operand baseOffset = Local();
node.List.AddBefore(node, new Operation(Instruction.Multiply, baseOffset, new[] { outputBaseVertex, Const(stride) })); node.List?.AddBefore(node, new Operation(Instruction.Multiply, baseOffset, new[] { outputBaseVertex, Const(stride) }));
LinkedListNode<INode> newNode = node; LinkedListNode<INode> newNode = node;
@ -163,7 +163,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
if (offset > 0) if (offset > 0)
{ {
vertexOffset = Local(); vertexOffset = Local();
node.List.AddBefore(node, new Operation(Instruction.Add, vertexOffset, new[] { baseOffset, Const(offset) })); node.List?.AddBefore(node, new Operation(Instruction.Add, vertexOffset, new[] { baseOffset, Const(offset) }));
} }
else else
{ {
@ -171,13 +171,13 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
} }
Operand value = Local(); Operand value = Local();
node.List.AddBefore(node, new Operation( node.List?.AddBefore(node, new Operation(
Instruction.Load, Instruction.Load,
StorageKind.LocalMemory, StorageKind.LocalMemory,
value, value,
new[] { Const(resourceManager.LocalVertexDataMemoryId), Const(offset) })); new[] { Const(resourceManager.LocalVertexDataMemoryId), Const(offset) }));
newNode = node.List.AddBefore(node, new Operation( newNode = node.List?.AddBefore(node, new Operation(
Instruction.Store, Instruction.Store,
StorageKind.StorageBuffer, StorageKind.StorageBuffer,
null, null,
@ -198,9 +198,9 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
definitions.GetGeometryOutputIndexBufferStride(), definitions.GetGeometryOutputIndexBufferStride(),
definitions.ThreadsPerInputPrimitive); definitions.ThreadsPerInputPrimitive);
Operand outputBaseIndex = Local(); Operand outputBaseIndex = Local();
node.List.AddBefore(node, new Operation(Instruction.Add, outputBaseIndex, new[] { baseIndexOffset, outputPrimIndex })); node.List?.AddBefore(node, new Operation(Instruction.Add, outputBaseIndex, new[] { baseIndexOffset, outputPrimIndex }));
return node.List.AddBefore(node, new Operation( return node.List?.AddBefore(node, new Operation(
Instruction.Store, Instruction.Store,
StorageKind.StorageBuffer, StorageKind.StorageBuffer,
null, null,
@ -213,16 +213,16 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
GeneratePrimitiveId(resourceManager, node, primitiveId); GeneratePrimitiveId(resourceManager, node, primitiveId);
Operand baseOffset = Local(); Operand baseOffset = Local();
node.List.AddBefore(node, new Operation(Instruction.Multiply, baseOffset, new[] { primitiveId, Const(stride) })); node.List?.AddBefore(node, new Operation(Instruction.Multiply, baseOffset, new[] { primitiveId, Const(stride) }));
Operand invocationId = Local(); Operand invocationId = Local();
GenerateInvocationId(node, invocationId); GenerateInvocationId(node, invocationId);
Operand invocationOffset = Local(); Operand invocationOffset = Local();
node.List.AddBefore(node, new Operation(Instruction.Multiply, invocationOffset, new[] { invocationId, Const(stride / threadsPerInputPrimitive) })); node.List?.AddBefore(node, new Operation(Instruction.Multiply, invocationOffset, new[] { invocationId, Const(stride / threadsPerInputPrimitive) }));
Operand combinedOffset = Local(); Operand combinedOffset = Local();
node.List.AddBefore(node, new Operation(Instruction.Add, combinedOffset, new[] { baseOffset, invocationOffset })); node.List?.AddBefore(node, new Operation(Instruction.Add, combinedOffset, new[] { baseOffset, invocationOffset }));
return combinedOffset; return combinedOffset;
} }
@ -230,16 +230,16 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
private static Operand IncrementLocalMemory(LinkedListNode<INode> node, int memoryId) private static Operand IncrementLocalMemory(LinkedListNode<INode> node, int memoryId)
{ {
Operand oldValue = Local(); Operand oldValue = Local();
node.List.AddBefore(node, new Operation( node.List?.AddBefore(node, new Operation(
Instruction.Load, Instruction.Load,
StorageKind.LocalMemory, StorageKind.LocalMemory,
oldValue, oldValue,
new[] { Const(memoryId) })); new[] { Const(memoryId) }));
Operand newValue = Local(); Operand newValue = Local();
node.List.AddBefore(node, new Operation(Instruction.Add, newValue, new[] { oldValue, Const(1) })); node.List?.AddBefore(node, new Operation(Instruction.Add, newValue, new[] { oldValue, Const(1) }));
node.List.AddBefore(node, new Operation(Instruction.Store, StorageKind.LocalMemory, null, new[] { Const(memoryId), newValue })); node.List?.AddBefore(node, new Operation(Instruction.Store, StorageKind.LocalMemory, null, new[] { Const(memoryId), newValue }));
return oldValue; return oldValue;
} }
@ -253,34 +253,34 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
int vertexInfoCbBinding = resourceManager.Reservations.VertexInfoConstantBufferBinding; int vertexInfoCbBinding = resourceManager.Reservations.VertexInfoConstantBufferBinding;
Operand vertexCount = Local(); Operand vertexCount = Local();
node.List.AddBefore(node, new Operation( node.List?.AddBefore(node, new Operation(
Instruction.Load, Instruction.Load,
StorageKind.ConstantBuffer, StorageKind.ConstantBuffer,
vertexCount, vertexCount,
new[] { Const(vertexInfoCbBinding), Const((int)VertexInfoBufferField.VertexCounts), Const(0) })); new[] { Const(vertexInfoCbBinding), Const((int)VertexInfoBufferField.VertexCounts), Const(0) }));
Operand primInputVertex = Local(); Operand primInputVertex = Local();
node.List.AddBefore(node, new Operation( node.List?.AddBefore(node, new Operation(
Instruction.Load, Instruction.Load,
StorageKind.LocalMemory, StorageKind.LocalMemory,
primInputVertex, primInputVertex,
new[] { Const(resourceManager.LocalTopologyRemapMemoryId), primVertex })); new[] { Const(resourceManager.LocalTopologyRemapMemoryId), primVertex }));
Operand instanceIndex = Local(); Operand instanceIndex = Local();
node.List.AddBefore(node, new Operation( node.List?.AddBefore(node, new Operation(
Instruction.Load, Instruction.Load,
StorageKind.Input, StorageKind.Input,
instanceIndex, instanceIndex,
new[] { Const((int)IoVariable.GlobalId), Const(1) })); new[] { Const((int)IoVariable.GlobalId), Const(1) }));
Operand baseVertex = Local(); Operand baseVertex = Local();
node.List.AddBefore(node, new Operation(Instruction.Multiply, baseVertex, new[] { instanceIndex, vertexCount })); node.List?.AddBefore(node, new Operation(Instruction.Multiply, baseVertex, new[] { instanceIndex, vertexCount }));
Operand vertexIndex = Local(); Operand vertexIndex = Local();
node.List.AddBefore(node, new Operation(Instruction.Add, vertexIndex, new[] { baseVertex, primInputVertex })); node.List?.AddBefore(node, new Operation(Instruction.Add, vertexIndex, new[] { baseVertex, primInputVertex }));
Operand vertexBaseOffset = Local(); Operand vertexBaseOffset = Local();
node.List.AddBefore(node, new Operation( node.List?.AddBefore(node, new Operation(
Instruction.Multiply, Instruction.Multiply,
vertexBaseOffset, vertexBaseOffset,
new[] { vertexIndex, Const(resourceManager.Reservations.InputSizePerInvocation) })); new[] { vertexIndex, Const(resourceManager.Reservations.InputSizePerInvocation) }));
@ -291,7 +291,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
{ {
vertexElemOffset = Local(); vertexElemOffset = Local();
node.List.AddBefore(node, new Operation(Instruction.Add, vertexElemOffset, new[] { vertexBaseOffset, Const(elementOffset) })); node.List?.AddBefore(node, new Operation(Instruction.Add, vertexElemOffset, new[] { vertexBaseOffset, Const(elementOffset) }));
} }
else else
{ {
@ -306,35 +306,35 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
int vertexInfoCbBinding = resourceManager.Reservations.VertexInfoConstantBufferBinding; int vertexInfoCbBinding = resourceManager.Reservations.VertexInfoConstantBufferBinding;
Operand vertexCount = Local(); Operand vertexCount = Local();
node.List.AddBefore(node, new Operation( node.List?.AddBefore(node, new Operation(
Instruction.Load, Instruction.Load,
StorageKind.ConstantBuffer, StorageKind.ConstantBuffer,
vertexCount, vertexCount,
new[] { Const(vertexInfoCbBinding), Const((int)VertexInfoBufferField.VertexCounts), Const(0) })); new[] { Const(vertexInfoCbBinding), Const((int)VertexInfoBufferField.VertexCounts), Const(0) }));
Operand vertexIndex = Local(); Operand vertexIndex = Local();
node.List.AddBefore(node, new Operation( node.List?.AddBefore(node, new Operation(
Instruction.Load, Instruction.Load,
StorageKind.Input, StorageKind.Input,
vertexIndex, vertexIndex,
new[] { Const((int)IoVariable.GlobalId), Const(0) })); new[] { Const((int)IoVariable.GlobalId), Const(0) }));
Operand instanceIndex = Local(); Operand instanceIndex = Local();
node.List.AddBefore(node, new Operation( node.List?.AddBefore(node, new Operation(
Instruction.Load, Instruction.Load,
StorageKind.Input, StorageKind.Input,
instanceIndex, instanceIndex,
new[] { Const((int)IoVariable.GlobalId), Const(1) })); new[] { Const((int)IoVariable.GlobalId), Const(1) }));
Operand baseVertex = Local(); Operand baseVertex = Local();
node.List.AddBefore(node, new Operation(Instruction.Multiply, baseVertex, new[] { instanceIndex, vertexCount })); node.List?.AddBefore(node, new Operation(Instruction.Multiply, baseVertex, new[] { instanceIndex, vertexCount }));
return node.List.AddBefore(node, new Operation(Instruction.Add, dest, new[] { baseVertex, vertexIndex })); return node.List?.AddBefore(node, new Operation(Instruction.Add, dest, new[] { baseVertex, vertexIndex }));
} }
private static LinkedListNode<INode> GenerateInvocationId(LinkedListNode<INode> node, Operand dest) private static LinkedListNode<INode> GenerateInvocationId(LinkedListNode<INode> node, Operand dest)
{ {
return node.List.AddBefore(node, new Operation( return node.List?.AddBefore(node, new Operation(
Instruction.Load, Instruction.Load,
StorageKind.Input, StorageKind.Input,
dest, dest,

View file

@ -48,7 +48,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
Operand[] callArgs = [Const(functionId), byteOffset, value]; Operand[] callArgs = [Const(functionId), byteOffset, value];
LinkedListNode<INode> newNode = node.List.AddBefore(node, new Operation(Instruction.Call, 0, result, callArgs)); LinkedListNode<INode> newNode = node.List?.AddBefore(node, new Operation(Instruction.Call, 0, result, callArgs));
Utils.DeleteNode(node, operation); Utils.DeleteNode(node, operation);

View file

@ -47,7 +47,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
Operand[] callArgs = [Const(functionId), byteOffset, value]; Operand[] callArgs = [Const(functionId), byteOffset, value];
LinkedListNode<INode> newNode = node.List.AddBefore(node, new Operation(Instruction.Call, 0, (Operand)null, callArgs)); LinkedListNode<INode> newNode = node.List?.AddBefore(node, new Operation(Instruction.Call, 0, (Operand)null, callArgs));
Utils.DeleteNode(node, operation); Utils.DeleteNode(node, operation);

View file

@ -42,7 +42,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
Operand[] callArgs = [Const(functionId), value, index, mask, valid]; Operand[] callArgs = [Const(functionId), value, index, mask, valid];
LinkedListNode<INode> newNode = node.List.AddBefore(node, new Operation(Instruction.Call, 0, result, callArgs)); LinkedListNode<INode> newNode = node.List?.AddBefore(node, new Operation(Instruction.Call, 0, result, callArgs));
Utils.DeleteNode(node, operation); Utils.DeleteNode(node, operation);

View file

@ -79,7 +79,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
callArgs = [Const(functionId), texOp.GetSource(coordsIndex + index), Const(samplerIndex)]; callArgs = [Const(functionId), texOp.GetSource(coordsIndex + index), Const(samplerIndex)];
} }
node.List.AddBefore(node, new Operation(Instruction.Call, 0, scaledCoord, callArgs)); node.List?.AddBefore(node, new Operation(Instruction.Call, 0, scaledCoord, callArgs));
texOp.SetSource(coordsIndex + index, scaledCoord); texOp.SetSource(coordsIndex + index, scaledCoord);
} }
@ -130,7 +130,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
Operand[] callArgs = [Const(functionId), dest, Const(samplerIndex)]; Operand[] callArgs = [Const(functionId), dest, Const(samplerIndex)];
node.List.AddAfter(node, new Operation(Instruction.Call, 0, unscaledSize, callArgs)); node.List?.AddAfter(node, new Operation(Instruction.Call, 0, unscaledSize, callArgs));
} }
} }
@ -178,7 +178,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
Operand[] texSizeSources = [Const(0)]; Operand[] texSizeSources = [Const(0)];
LinkedListNode<INode> textureSizeNode = node.List.AddBefore(node, new TextureOperation( LinkedListNode<INode> textureSizeNode = node.List?.AddBefore(node, new TextureOperation(
Instruction.TextureQuerySize, Instruction.TextureQuerySize,
texOp.Type, texOp.Type,
texOp.Format, texOp.Format,
@ -195,7 +195,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
Operand coordNormalized = Local(); Operand coordNormalized = Local();
node.List.AddBefore(node, new Operation(Instruction.FP32 | Instruction.Divide, coordNormalized, source, GenerateI2f(node, coordSize))); node.List?.AddBefore(node, new Operation(Instruction.FP32 | Instruction.Divide, coordNormalized, source, GenerateI2f(node, coordSize)));
texOp.SetSource(index, coordNormalized); texOp.SetSource(index, coordNormalized);
@ -248,7 +248,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
texSizeSources = [Const(0)]; texSizeSources = [Const(0)];
} }
node.List.AddBefore(node, new TextureOperation( node.List?.AddBefore(node, new TextureOperation(
Instruction.TextureQuerySize, Instruction.TextureQuerySize,
texOp.Type, texOp.Type,
texOp.Format, texOp.Format,
@ -259,18 +259,18 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
[coordSize], [coordSize],
texSizeSources)); texSizeSources));
node.List.AddBefore(node, new Operation( node.List?.AddBefore(node, new Operation(
Instruction.FP32 | Instruction.Multiply, Instruction.FP32 | Instruction.Multiply,
scaledSize, scaledSize,
GenerateI2f(node, coordSize), GenerateI2f(node, coordSize),
ConstF((float)(1 << (gatherBiasPrecision + 1))))); ConstF((float)(1 << (gatherBiasPrecision + 1)))));
node.List.AddBefore(node, new Operation(Instruction.FP32 | Instruction.Divide, bias, ConstF(1f), scaledSize)); node.List?.AddBefore(node, new Operation(Instruction.FP32 | Instruction.Divide, bias, ConstF(1f), scaledSize));
Operand source = texOp.GetSource(coordsIndex + index); Operand source = texOp.GetSource(coordsIndex + index);
Operand coordBiased = Local(); Operand coordBiased = Local();
node.List.AddBefore(node, new Operation(Instruction.FP32 | Instruction.Add, coordBiased, source, bias)); node.List?.AddBefore(node, new Operation(Instruction.FP32 | Instruction.Add, coordBiased, source, bias));
texOp.SetSource(coordsIndex + index, coordBiased); texOp.SetSource(coordsIndex + index, coordBiased);
} }
@ -573,7 +573,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
texSizeSources = [Const(0)]; texSizeSources = [Const(0)];
} }
node.List.AddBefore(node, new TextureOperation( node.List?.AddBefore(node, new TextureOperation(
Instruction.TextureQuerySize, Instruction.TextureQuerySize,
texOp.Type, texOp.Type,
texOp.Format, texOp.Format,
@ -604,7 +604,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
{ {
lod = Local(); lod = Local();
node.List.AddBefore(node, new TextureOperation( node.List?.AddBefore(node, new TextureOperation(
Instruction.Lod, Instruction.Lod,
texOp.Type, texOp.Type,
texOp.Format, texOp.Format,
@ -635,7 +635,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
texSizeSources = [GenerateF2i(node, lod)]; texSizeSources = [GenerateF2i(node, lod)];
} }
node.List.AddBefore(node, new TextureOperation( node.List?.AddBefore(node, new TextureOperation(
Instruction.TextureQuerySize, Instruction.TextureQuerySize,
texOp.Type, texOp.Type,
texOp.Format, texOp.Format,
@ -692,8 +692,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
Operation convOp = new(Instruction.ConvertS32ToFP32, Local(), dest); Operation convOp = new(Instruction.ConvertS32ToFP32, Local(), dest);
Operation normOp = new(Instruction.FP32 | Instruction.Multiply, Local(), convOp.Dest, ConstF(1f / maxPositive)); Operation normOp = new(Instruction.FP32 | Instruction.Multiply, Local(), convOp.Dest, ConstF(1f / maxPositive));
node = node.List.AddAfter(node, convOp); node = node?.List?.AddAfter(node, convOp);
node = node.List.AddAfter(node, normOp); node = node?.List?.AddAfter(node, normOp);
foreach (INode useOp in uses) foreach (INode useOp in uses)
{ {
@ -720,7 +720,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
{ {
Operand res = Local(); Operand res = Local();
node.List.AddBefore(node, new Operation(Instruction.ConvertS32ToFP32, res, value)); node.List?.AddBefore(node, new Operation(Instruction.ConvertS32ToFP32, res, value));
return res; return res;
} }
@ -729,7 +729,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
{ {
Operand res = Local(); Operand res = Local();
node.List.AddBefore(node, new Operation(Instruction.ConvertFP32ToS32, res, value)); node.List?.AddBefore(node, new Operation(Instruction.ConvertFP32ToS32, res, value));
return res; return res;
} }

View file

@ -67,7 +67,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
Operation loadOp = new(Instruction.Load, StorageKind.ConstantBuffer, value, inputs); Operation loadOp = new(Instruction.Load, StorageKind.ConstantBuffer, value, inputs);
node.List.AddBefore(node, loadOp); node.List?.AddBefore(node, loadOp);
if (i == 0) if (i == 0)
{ {
@ -81,8 +81,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
Operation compareOp = new(Instruction.CompareEqual, isCurrentIndex, new Operand[] { elemIndex, Const(i) }); Operation compareOp = new(Instruction.CompareEqual, isCurrentIndex, new Operand[] { elemIndex, Const(i) });
Operation selectOp = new(Instruction.ConditionalSelect, selection, new Operand[] { isCurrentIndex, value, result }); Operation selectOp = new(Instruction.ConditionalSelect, selection, new Operand[] { isCurrentIndex, value, result });
node.List.AddBefore(node, compareOp); node.List?.AddBefore(node, compareOp);
node.List.AddBefore(node, selectOp); node.List?.AddBefore(node, selectOp);
result = selection; result = selection;
} }

View file

@ -58,7 +58,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
Operand temp = needsSextNorm ? Local() : dest; Operand temp = needsSextNorm ? Local() : dest;
Operand vertexElemOffset = GenerateVertexOffset(context.ResourceManager, node, location, 0); Operand vertexElemOffset = GenerateVertexOffset(context.ResourceManager, node, location, 0);
newNode = node.List.AddBefore(node, new TextureOperation( newNode = node.List?.AddBefore(node, new TextureOperation(
Instruction.TextureSample, Instruction.TextureSample,
SamplerType.TextureBuffer, SamplerType.TextureBuffer,
TextureFormat.Unknown, TextureFormat.Unknown,
@ -81,7 +81,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
Operand temp = component > 0 ? Local() : dest; Operand temp = component > 0 ? Local() : dest;
Operand vertexElemOffset = GenerateVertexOffset(context.ResourceManager, node, location, component); Operand vertexElemOffset = GenerateVertexOffset(context.ResourceManager, node, location, component);
newNode = node.List.AddBefore(node, new TextureOperation( newNode = node.List?.AddBefore(node, new TextureOperation(
Instruction.TextureSample, Instruction.TextureSample,
SamplerType.TextureBuffer, SamplerType.TextureBuffer,
TextureFormat.Unknown, TextureFormat.Unknown,
@ -116,7 +116,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
{ {
if (TryGetOutputOffset(context.ResourceManager, operation, out int outputOffset)) if (TryGetOutputOffset(context.ResourceManager, operation, out int outputOffset))
{ {
newNode = node.List.AddBefore(node, new Operation( newNode = node.List?.AddBefore(node, new Operation(
Instruction.Load, Instruction.Load,
StorageKind.LocalMemory, StorageKind.LocalMemory,
operation.Dest, operation.Dest,
@ -133,7 +133,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
{ {
Operand value = operation.GetSource(operation.SourcesCount - 1); Operand value = operation.GetSource(operation.SourcesCount - 1);
newNode = node.List.AddBefore(node, new Operation( newNode = node.List?.AddBefore(node, new Operation(
Instruction.Store, Instruction.Store,
StorageKind.LocalMemory, StorageKind.LocalMemory,
(Operand)null, (Operand)null,
@ -164,37 +164,37 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
GenerateVertexIdInstanceRateLoad(resourceManager, node, vertexIdIr); GenerateVertexIdInstanceRateLoad(resourceManager, node, vertexIdIr);
Operand attributeOffset = Local(); Operand attributeOffset = Local();
node.List.AddBefore(node, new Operation( node.List?.AddBefore(node, new Operation(
Instruction.Load, Instruction.Load,
StorageKind.ConstantBuffer, StorageKind.ConstantBuffer,
attributeOffset, attributeOffset,
new[] { Const(vertexInfoCbBinding), Const((int)VertexInfoBufferField.VertexOffsets), Const(location), Const(0) })); new[] { Const(vertexInfoCbBinding), Const((int)VertexInfoBufferField.VertexOffsets), Const(location), Const(0) }));
Operand isInstanceRate = Local(); Operand isInstanceRate = Local();
node.List.AddBefore(node, new Operation( node.List?.AddBefore(node, new Operation(
Instruction.Load, Instruction.Load,
StorageKind.ConstantBuffer, StorageKind.ConstantBuffer,
isInstanceRate, isInstanceRate,
new[] { Const(vertexInfoCbBinding), Const((int)VertexInfoBufferField.VertexOffsets), Const(location), Const(1) })); new[] { Const(vertexInfoCbBinding), Const((int)VertexInfoBufferField.VertexOffsets), Const(location), Const(1) }));
Operand vertexId = Local(); Operand vertexId = Local();
node.List.AddBefore(node, new Operation( node.List?.AddBefore(node, new Operation(
Instruction.ConditionalSelect, Instruction.ConditionalSelect,
vertexId, vertexId,
new[] { isInstanceRate, vertexIdIr, vertexIdVr })); new[] { isInstanceRate, vertexIdIr, vertexIdVr }));
Operand vertexStride = Local(); Operand vertexStride = Local();
node.List.AddBefore(node, new Operation( node.List?.AddBefore(node, new Operation(
Instruction.Load, Instruction.Load,
StorageKind.ConstantBuffer, StorageKind.ConstantBuffer,
vertexStride, vertexStride,
new[] { Const(vertexInfoCbBinding), Const((int)VertexInfoBufferField.VertexStrides), Const(location), Const(0) })); new[] { Const(vertexInfoCbBinding), Const((int)VertexInfoBufferField.VertexStrides), Const(location), Const(0) }));
Operand vertexBaseOffset = Local(); Operand vertexBaseOffset = Local();
node.List.AddBefore(node, new Operation(Instruction.Multiply, vertexBaseOffset, new[] { vertexId, vertexStride })); node.List?.AddBefore(node, new Operation(Instruction.Multiply, vertexBaseOffset, new[] { vertexId, vertexStride }));
Operand vertexOffset = Local(); Operand vertexOffset = Local();
node.List.AddBefore(node, new Operation(Instruction.Add, vertexOffset, new[] { attributeOffset, vertexBaseOffset })); node.List?.AddBefore(node, new Operation(Instruction.Add, vertexOffset, new[] { attributeOffset, vertexBaseOffset }));
Operand vertexElemOffset; Operand vertexElemOffset;
@ -202,7 +202,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
{ {
vertexElemOffset = Local(); vertexElemOffset = Local();
node.List.AddBefore(node, new Operation(Instruction.Add, vertexElemOffset, new[] { vertexOffset, Const(component) })); node.List?.AddBefore(node, new Operation(Instruction.Add, vertexElemOffset, new[] { vertexOffset, Const(component) }));
} }
else else
{ {
@ -215,13 +215,13 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
private static LinkedListNode<INode> CopySignExtendedNormalized(LinkedListNode<INode> node, int bits, bool normalize, Operand dest, Operand src) private static LinkedListNode<INode> CopySignExtendedNormalized(LinkedListNode<INode> node, int bits, bool normalize, Operand dest, Operand src)
{ {
Operand leftShifted = Local(); Operand leftShifted = Local();
node = node.List.AddAfter(node, new Operation( node = node.List?.AddAfter(node, new Operation(
Instruction.ShiftLeft, Instruction.ShiftLeft,
leftShifted, leftShifted,
new[] { src, Const(32 - bits) })); new[] { src, Const(32 - bits) }));
Operand rightShifted = normalize ? Local() : dest; Operand rightShifted = normalize ? Local() : dest;
node = node.List.AddAfter(node, new Operation( node = node?.List?.AddAfter(node, new Operation(
Instruction.ShiftRightS32, Instruction.ShiftRightS32,
rightShifted, rightShifted,
new[] { leftShifted, Const(32 - bits) })); new[] { leftShifted, Const(32 - bits) }));
@ -229,8 +229,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
if (normalize) if (normalize)
{ {
Operand asFloat = Local(); Operand asFloat = Local();
node = node.List.AddAfter(node, new Operation(Instruction.ConvertS32ToFP32, asFloat, new[] { rightShifted })); node = node?.List?.AddAfter(node, new Operation(Instruction.ConvertS32ToFP32, asFloat, new[] { rightShifted }));
node = node.List.AddAfter(node, new Operation( node = node?.List?.AddAfter(node, new Operation(
Instruction.FP32 | Instruction.Multiply, Instruction.FP32 | Instruction.Multiply,
dest, dest,
new[] { asFloat, ConstF(1f / (1 << (bits - 1))) })); new[] { asFloat, ConstF(1f / (1 << (bits - 1))) }));
@ -249,13 +249,13 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
{ {
Operand componentExists = Local(); Operand componentExists = Local();
int vertexInfoCbBinding = resourceManager.Reservations.VertexInfoConstantBufferBinding; int vertexInfoCbBinding = resourceManager.Reservations.VertexInfoConstantBufferBinding;
node = node.List.AddAfter(node, new Operation( node = node.List?.AddAfter(node, new Operation(
Instruction.Load, Instruction.Load,
StorageKind.ConstantBuffer, StorageKind.ConstantBuffer,
componentExists, componentExists,
new[] { Const(vertexInfoCbBinding), Const((int)VertexInfoBufferField.VertexStrides), Const(location), Const(component) })); new[] { Const(vertexInfoCbBinding), Const((int)VertexInfoBufferField.VertexStrides), Const(location), Const(component) }));
return node.List.AddAfter(node, new Operation( return node?.List?.AddAfter(node, new Operation(
Instruction.ConditionalSelect, Instruction.ConditionalSelect,
dest, dest,
new[] { componentExists, src, ConstF(component == 3 ? 1f : 0f) })); new[] { componentExists, src, ConstF(component == 3 ? 1f : 0f) }));
@ -265,7 +265,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
{ {
int vertexInfoCbBinding = resourceManager.Reservations.VertexInfoConstantBufferBinding; int vertexInfoCbBinding = resourceManager.Reservations.VertexInfoConstantBufferBinding;
return node.List.AddBefore(node, new Operation( return node.List?.AddBefore(node, new Operation(
Instruction.Load, Instruction.Load,
StorageKind.ConstantBuffer, StorageKind.ConstantBuffer,
dest, dest,
@ -276,7 +276,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
{ {
int vertexInfoCbBinding = resourceManager.Reservations.VertexInfoConstantBufferBinding; int vertexInfoCbBinding = resourceManager.Reservations.VertexInfoConstantBufferBinding;
return node.List.AddBefore(node, new Operation( return node.List?.AddBefore(node, new Operation(
Instruction.Load, Instruction.Load,
StorageKind.ConstantBuffer, StorageKind.ConstantBuffer,
dest, dest,
@ -291,7 +291,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
GenerateBaseVertexLoad(resourceManager, node, baseVertex); GenerateBaseVertexLoad(resourceManager, node, baseVertex);
GenerateVertexIdVertexRateLoad(resourceManager, node, vertexId); GenerateVertexIdVertexRateLoad(resourceManager, node, vertexId);
return node.List.AddBefore(node, new Operation(Instruction.Add, dest, new[] { baseVertex, vertexId })); return node.List?.AddBefore(node, new Operation(Instruction.Add, dest, new[] { baseVertex, vertexId }));
} }
private static LinkedListNode<INode> GenerateInstanceIndexLoad(ResourceManager resourceManager, LinkedListNode<INode> node, Operand dest) private static LinkedListNode<INode> GenerateInstanceIndexLoad(ResourceManager resourceManager, LinkedListNode<INode> node, Operand dest)
@ -301,34 +301,34 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
GenerateBaseInstanceLoad(resourceManager, node, baseInstance); GenerateBaseInstanceLoad(resourceManager, node, baseInstance);
node.List.AddBefore(node, new Operation( node.List?.AddBefore(node, new Operation(
Instruction.Load, Instruction.Load,
StorageKind.Input, StorageKind.Input,
instanceId, instanceId,
new[] { Const((int)IoVariable.GlobalId), Const(1) })); new[] { Const((int)IoVariable.GlobalId), Const(1) }));
return node.List.AddBefore(node, new Operation(Instruction.Add, dest, new[] { baseInstance, instanceId })); return node.List?.AddBefore(node, new Operation(Instruction.Add, dest, new[] { baseInstance, instanceId }));
} }
private static LinkedListNode<INode> GenerateVertexIdVertexRateLoad(ResourceManager resourceManager, LinkedListNode<INode> node, Operand dest) private static LinkedListNode<INode> GenerateVertexIdVertexRateLoad(ResourceManager resourceManager, LinkedListNode<INode> node, Operand dest)
{ {
Operand[] sources = [Const(resourceManager.LocalVertexIndexVertexRateMemoryId)]; Operand[] sources = [Const(resourceManager.LocalVertexIndexVertexRateMemoryId)];
return node.List.AddBefore(node, new Operation(Instruction.Load, StorageKind.LocalMemory, dest, sources)); return node.List?.AddBefore(node, new Operation(Instruction.Load, StorageKind.LocalMemory, dest, sources));
} }
private static LinkedListNode<INode> GenerateVertexIdInstanceRateLoad(ResourceManager resourceManager, LinkedListNode<INode> node, Operand dest) private static LinkedListNode<INode> GenerateVertexIdInstanceRateLoad(ResourceManager resourceManager, LinkedListNode<INode> node, Operand dest)
{ {
Operand[] sources = [Const(resourceManager.LocalVertexIndexInstanceRateMemoryId)]; Operand[] sources = [Const(resourceManager.LocalVertexIndexInstanceRateMemoryId)];
return node.List.AddBefore(node, new Operation(Instruction.Load, StorageKind.LocalMemory, dest, sources)); return node.List?.AddBefore(node, new Operation(Instruction.Load, StorageKind.LocalMemory, dest, sources));
} }
private static LinkedListNode<INode> GenerateInstanceIdLoad(LinkedListNode<INode> node, Operand dest) private static LinkedListNode<INode> GenerateInstanceIdLoad(LinkedListNode<INode> node, Operand dest)
{ {
Operand[] sources = [Const((int)IoVariable.GlobalId), Const(1)]; Operand[] sources = [Const((int)IoVariable.GlobalId), Const(1)];
return node.List.AddBefore(node, new Operation(Instruction.Load, StorageKind.Input, dest, sources)); return node.List?.AddBefore(node, new Operation(Instruction.Load, StorageKind.Input, dest, sources));
} }
private static bool TryGetOutputOffset(ResourceManager resourceManager, Operation operation, out int outputOffset) private static bool TryGetOutputOffset(ResourceManager resourceManager, Operation operation, out int outputOffset)

View file

@ -152,7 +152,7 @@ namespace Ryujinx.Graphics.Vulkan.Effects
int dispatchY = (height + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; int dispatchY = (height + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
_pipeline.SetUniformBuffers([new BufferAssignment(2, buffer.Range)]); _pipeline.SetUniformBuffers([new BufferAssignment(2, buffer.Range)]);
_pipeline.SetImage(ShaderStage.Compute, 0, _intermediaryTexture.GetView(FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format))); _pipeline.SetImage(ShaderStage.Compute, 0, _intermediaryTexture?.GetView(FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format)));
_pipeline.DispatchCompute(dispatchX, dispatchY, 1); _pipeline.DispatchCompute(dispatchX, dispatchY, 1);
_pipeline.ComputeBarrier(); _pipeline.ComputeBarrier();

View file

@ -74,7 +74,7 @@ namespace Ryujinx.Graphics.Vulkan.Effects
var dispatchX = BitUtils.DivRoundUp(view.Width, IPostProcessingEffect.LocalGroupSize); var dispatchX = BitUtils.DivRoundUp(view.Width, IPostProcessingEffect.LocalGroupSize);
var dispatchY = BitUtils.DivRoundUp(view.Height, IPostProcessingEffect.LocalGroupSize); var dispatchY = BitUtils.DivRoundUp(view.Height, IPostProcessingEffect.LocalGroupSize);
_pipeline.SetImage(ShaderStage.Compute, 0, _texture.GetView(FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format))); _pipeline.SetImage(ShaderStage.Compute, 0, _texture?.GetView(FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format)));
_pipeline.DispatchCompute(dispatchX, dispatchY, 1); _pipeline.DispatchCompute(dispatchX, dispatchY, 1);
_pipeline.ComputeBarrier(); _pipeline.ComputeBarrier();

View file

@ -177,8 +177,8 @@ namespace Ryujinx.Graphics.Vulkan.Effects
_areaTexture = _renderer.CreateTexture(areaInfo) as TextureView; _areaTexture = _renderer.CreateTexture(areaInfo) as TextureView;
_searchTexture = _renderer.CreateTexture(searchInfo) as TextureView; _searchTexture = _renderer.CreateTexture(searchInfo) as TextureView;
_areaTexture.SetData(areaTexture); _areaTexture?.SetData(areaTexture);
_searchTexture.SetData(searchTexture); _searchTexture?.SetData(searchTexture);
} }
public TextureView Run(TextureView view, CommandBufferScoped cbs, int width, int height) public TextureView Run(TextureView view, CommandBufferScoped cbs, int width, int height)
@ -216,7 +216,7 @@ namespace Ryujinx.Graphics.Vulkan.Effects
buffer.Holder.SetDataUnchecked(buffer.Offset, resolutionBuffer); buffer.Holder.SetDataUnchecked(buffer.Offset, resolutionBuffer);
_pipeline.SetUniformBuffers([new BufferAssignment(2, buffer.Range)]); _pipeline.SetUniformBuffers([new BufferAssignment(2, buffer.Range)]);
_pipeline.SetImage(ShaderStage.Compute, 0, _edgeOutputTexture.GetView(FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format))); _pipeline.SetImage(ShaderStage.Compute, 0, _edgeOutputTexture?.GetView(FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format)));
_pipeline.DispatchCompute(dispatchX, dispatchY, 1); _pipeline.DispatchCompute(dispatchX, dispatchY, 1);
_pipeline.ComputeBarrier(); _pipeline.ComputeBarrier();
@ -226,7 +226,7 @@ namespace Ryujinx.Graphics.Vulkan.Effects
_pipeline.SetTextureAndSampler(ShaderStage.Compute, 1, _edgeOutputTexture, _samplerLinear); _pipeline.SetTextureAndSampler(ShaderStage.Compute, 1, _edgeOutputTexture, _samplerLinear);
_pipeline.SetTextureAndSampler(ShaderStage.Compute, 3, _areaTexture, _samplerLinear); _pipeline.SetTextureAndSampler(ShaderStage.Compute, 3, _areaTexture, _samplerLinear);
_pipeline.SetTextureAndSampler(ShaderStage.Compute, 4, _searchTexture, _samplerLinear); _pipeline.SetTextureAndSampler(ShaderStage.Compute, 4, _searchTexture, _samplerLinear);
_pipeline.SetImage(ShaderStage.Compute, 0, _blendOutputTexture.GetView(FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format))); _pipeline.SetImage(ShaderStage.Compute, 0, _blendOutputTexture?.GetView(FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format)));
_pipeline.DispatchCompute(dispatchX, dispatchY, 1); _pipeline.DispatchCompute(dispatchX, dispatchY, 1);
_pipeline.ComputeBarrier(); _pipeline.ComputeBarrier();
@ -235,7 +235,7 @@ namespace Ryujinx.Graphics.Vulkan.Effects
_pipeline.Specialize(_specConstants); _pipeline.Specialize(_specConstants);
_pipeline.SetTextureAndSampler(ShaderStage.Compute, 3, _blendOutputTexture, _samplerLinear); _pipeline.SetTextureAndSampler(ShaderStage.Compute, 3, _blendOutputTexture, _samplerLinear);
_pipeline.SetTextureAndSampler(ShaderStage.Compute, 1, view, _samplerLinear); _pipeline.SetTextureAndSampler(ShaderStage.Compute, 1, view, _samplerLinear);
_pipeline.SetImage(ShaderStage.Compute, 0, _outputTexture.GetView(FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format))); _pipeline.SetImage(ShaderStage.Compute, 0, _outputTexture?.GetView(FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format)));
_pipeline.DispatchCompute(dispatchX, dispatchY, 1); _pipeline.DispatchCompute(dispatchX, dispatchY, 1);
_pipeline.ComputeBarrier(); _pipeline.ComputeBarrier();

View file

@ -28,15 +28,15 @@ namespace Ryujinx.HLE.Generators
continue; continue;
var constructors = className.ChildNodes().Where(x => x.IsKind(SyntaxKind.ConstructorDeclaration)).Select(y => y as ConstructorDeclarationSyntax); var constructors = className.ChildNodes().Where(x => x.IsKind(SyntaxKind.ConstructorDeclaration)).Select(y => y as ConstructorDeclarationSyntax);
if (!constructors.Any(x => x.ParameterList.Parameters.Count >= 1)) if (!constructors.Any(x => x != null && x.ParameterList.Parameters.Count >= 1))
continue; continue;
if (constructors.Where(x => x.ParameterList.Parameters.Count >= 1).FirstOrDefault().ParameterList.Parameters[0].Type.ToString() == "ServiceCtx") if (constructors.FirstOrDefault(x => x != null && x.ParameterList.Parameters.Count >= 1).ParameterList.Parameters[0].Type.ToString() == "ServiceCtx")
{ {
generator.EnterScope($"if (type == typeof({GetFullName(className, context)}))"); generator.EnterScope($"if (type == typeof({GetFullName(className, context)}))");
if (constructors.Any(x => x.ParameterList.Parameters.Count == 2)) if (constructors.Any(x => x != null && x.ParameterList.Parameters.Count == 2))
{ {
var type = constructors.Where(x => x.ParameterList.Parameters.Count == 2).FirstOrDefault().ParameterList.Parameters[1].Type; var type = constructors.FirstOrDefault(x => x != null && x.ParameterList.Parameters.Count == 2).ParameterList.Parameters[1].Type;
var model = context.Compilation.GetSemanticModel(type.SyntaxTree); var model = context.Compilation.GetSemanticModel(type.SyntaxTree);
var typeSymbol = model.GetSymbolInfo(type).Symbol as INamedTypeSymbol; var typeSymbol = model.GetSymbolInfo(type).Symbol as INamedTypeSymbol;
var fullName = typeSymbol?.ToString(); var fullName = typeSymbol?.ToString();
@ -45,7 +45,7 @@ namespace Ryujinx.HLE.Generators
generator.LeaveScope(); generator.LeaveScope();
} }
if (constructors.Any(x => x.ParameterList.Parameters.Count == 1)) if (constructors.Any(x => x != null && x.ParameterList.Parameters.Count == 1))
{ {
generator.AppendLine($"return new {GetFullName(className, context)}(context);"); generator.AppendLine($"return new {GetFullName(className, context)}(context);");
} }

View file

@ -147,7 +147,7 @@ namespace Ryujinx.HLE.Exceptions
while ((frame = trace.GetFrame(i++)) != null) while ((frame = trace.GetFrame(i++)) != null)
{ {
var method = frame.GetMethod(); var method = frame.GetMethod();
var declType = method.DeclaringType; var declType = method?.DeclaringType;
if (typeof(IpcService).IsAssignableFrom(declType)) if (typeof(IpcService).IsAssignableFrom(declType))
{ {

View file

@ -551,7 +551,7 @@ namespace Ryujinx.HLE.FileSystem
new DirectoryInfo(registeredDirectory).Delete(true); new DirectoryInfo(registeredDirectory).Delete(true);
} }
Directory.Move(temporaryDirectory, registeredDirectory); Directory.Move(temporaryDirectory, registeredDirectory ?? string.Empty);
LoadEntries(); LoadEntries();
} }

View file

@ -31,8 +31,12 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
} }
} }
writer.Write(bytes); if (bytes != null)
writer.Seek((int)maxSize - bytes.Length, SeekOrigin.Current); {
writer.Write(bytes);
writer.Seek((int)maxSize - bytes.Length, SeekOrigin.Current);
}
writer.Write((uint)text.Length); // String size writer.Write((uint)text.Length); // String size
return (uint)text.Length; // Return the cursor position at the end of the text return (uint)text.Length; // Return the cursor position at the end of the text

View file

@ -62,7 +62,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
if (list.Count != 0) if (list.Count != 0)
{ {
session = list.First.Value; if (list.First != null)
{
session = list.First.Value;
}
list.RemoveFirst(); list.RemoveFirst();
} }

View file

@ -1369,44 +1369,50 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
LinkedListNode<KPageNode> pageListNode = pageList.Nodes.First; LinkedListNode<KPageNode> pageListNode = pageList.Nodes.First;
KPageNode pageNode = pageListNode.Value; if (pageListNode != null)
ulong srcPa = pageNode.Address;
ulong srcPaPages = pageNode.PagesCount;
foreach (KMemoryInfo info in IterateOverRange(address, endAddr))
{ {
if (info.State != MemoryState.Unmapped) KPageNode pageNode = pageListNode.Value;
ulong srcPa = pageNode.Address;
ulong srcPaPages = pageNode.PagesCount;
foreach (KMemoryInfo info in IterateOverRange(address, endAddr))
{ {
continue; if (info.State != MemoryState.Unmapped)
}
ulong blockSize = GetSizeInRange(info, address, endAddr);
ulong dstVaPages = blockSize / PageSize;
ulong dstVa = GetAddrInRange(info, address);
while (dstVaPages > 0)
{
if (srcPaPages == 0)
{ {
pageListNode = pageListNode.Next; continue;
pageNode = pageListNode.Value;
srcPa = pageNode.Address;
srcPaPages = pageNode.PagesCount;
} }
ulong currentPagesCount = Math.Min(srcPaPages, dstVaPages); ulong blockSize = GetSizeInRange(info, address, endAddr);
MapPages(dstVa, currentPagesCount, srcPa, KMemoryPermission.ReadAndWrite, MemoryMapFlags.Private); ulong dstVaPages = blockSize / PageSize;
dstVa += currentPagesCount * PageSize; ulong dstVa = GetAddrInRange(info, address);
srcPa += currentPagesCount * PageSize;
srcPaPages -= currentPagesCount; while (dstVaPages > 0)
dstVaPages -= currentPagesCount; {
if (srcPaPages == 0)
{
pageListNode = pageListNode?.Next;
if (pageListNode != null)
{
pageNode = pageListNode.Value;
}
srcPa = pageNode.Address;
srcPaPages = pageNode.PagesCount;
}
ulong currentPagesCount = Math.Min(srcPaPages, dstVaPages);
MapPages(dstVa, currentPagesCount, srcPa, KMemoryPermission.ReadAndWrite, MemoryMapFlags.Private);
dstVa += currentPagesCount * PageSize;
srcPa += currentPagesCount * PageSize;
srcPaPages -= currentPagesCount;
dstVaPages -= currentPagesCount;
}
} }
} }

View file

@ -34,8 +34,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
{ {
if (_pageList.Nodes.Count == 1) if (_pageList.Nodes.Count == 1)
{ {
ulong address = _pageList.Nodes.First.Value.Address - DramMemoryMap.DramBase; if (_pageList.Nodes.First != null)
return ref _context.Memory.GetRef<T>(address + offset); {
ulong address = _pageList.Nodes.First.Value.Address - DramMemoryMap.DramBase;
return ref _context.Memory.GetRef<T>(address + offset);
}
} }
throw new NotImplementedException("Non-contiguous shared memory is not yet supported."); throw new NotImplementedException("Non-contiguous shared memory is not yet supported.");

View file

@ -253,7 +253,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
thread.SiblingsPerCore[core] = queue.AddLast(thread); thread.SiblingsPerCore[core] = queue.AddLast(thread);
return queue.First.Value; return queue.First?.Value;
} }
public void Unschedule(int prio, int core, KThread thread) public void Unschedule(int prio, int core, KThread thread)

View file

@ -1302,7 +1302,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
{ {
Owner?.RemoveThread(this); Owner?.RemoveThread(this);
if (_tlsAddress != 0 && Owner.FreeThreadLocalStorage(_tlsAddress) != Result.Success) if (_tlsAddress != 0 && Owner?.FreeThreadLocalStorage(_tlsAddress) != Result.Success)
{ {
throw new InvalidOperationException("Unexpected failure freeing thread local storage."); throw new InvalidOperationException("Unexpected failure freeing thread local storage.");
} }

View file

@ -61,42 +61,45 @@ namespace Ryujinx.Horizon.Generators.Hipc
{ {
HipcSyntaxReceiver syntaxReceiver = (HipcSyntaxReceiver)context.SyntaxReceiver; HipcSyntaxReceiver syntaxReceiver = (HipcSyntaxReceiver)context.SyntaxReceiver;
foreach (var commandInterface in syntaxReceiver.CommandInterfaces) if (syntaxReceiver?.CommandInterfaces != null)
{ {
if (!NeedsIServiceObjectImplementation(context.Compilation, commandInterface.ClassDeclarationSyntax)) foreach (var commandInterface in syntaxReceiver.CommandInterfaces)
{ {
continue; if (!NeedsIServiceObjectImplementation(context.Compilation, commandInterface.ClassDeclarationSyntax))
} {
continue;
}
CodeGenerator generator = new CodeGenerator(); CodeGenerator generator = new CodeGenerator();
string className = commandInterface.ClassDeclarationSyntax.Identifier.ToString(); string className = commandInterface.ClassDeclarationSyntax.Identifier.ToString();
generator.AppendLine("using Ryujinx.Horizon.Common;"); generator.AppendLine("using Ryujinx.Horizon.Common;");
generator.AppendLine("using Ryujinx.Horizon.Sdk.Sf;"); generator.AppendLine("using Ryujinx.Horizon.Sdk.Sf;");
generator.AppendLine("using Ryujinx.Horizon.Sdk.Sf.Cmif;"); generator.AppendLine("using Ryujinx.Horizon.Sdk.Sf.Cmif;");
generator.AppendLine("using Ryujinx.Horizon.Sdk.Sf.Hipc;"); generator.AppendLine("using Ryujinx.Horizon.Sdk.Sf.Hipc;");
generator.AppendLine("using System;"); generator.AppendLine("using System;");
generator.AppendLine("using System.Collections.Frozen;"); generator.AppendLine("using System.Collections.Frozen;");
generator.AppendLine("using System.Collections.Generic;"); generator.AppendLine("using System.Collections.Generic;");
generator.AppendLine("using System.Runtime.CompilerServices;"); generator.AppendLine("using System.Runtime.CompilerServices;");
generator.AppendLine("using System.Runtime.InteropServices;"); generator.AppendLine("using System.Runtime.InteropServices;");
generator.AppendLine();
generator.EnterScope($"namespace {GetNamespaceName(commandInterface.ClassDeclarationSyntax)}");
generator.EnterScope($"partial class {className}");
GenerateMethodTable(generator, context.Compilation, commandInterface);
foreach (var method in commandInterface.CommandImplementations)
{
generator.AppendLine(); generator.AppendLine();
generator.EnterScope($"namespace {GetNamespaceName(commandInterface.ClassDeclarationSyntax)}");
generator.EnterScope($"partial class {className}");
GenerateMethod(generator, context.Compilation, method); GenerateMethodTable(generator, context.Compilation, commandInterface);
foreach (var method in commandInterface.CommandImplementations)
{
generator.AppendLine();
GenerateMethod(generator, context.Compilation, method);
}
generator.LeaveScope();
generator.LeaveScope();
context.AddSource($"{GetNamespaceName(commandInterface.ClassDeclarationSyntax)}.{className}.g.cs", generator.ToString());
} }
generator.LeaveScope();
generator.LeaveScope();
context.AddSource($"{GetNamespaceName(commandInterface.ClassDeclarationSyntax)}.{className}.g.cs", generator.ToString());
} }
} }
@ -191,11 +194,15 @@ namespace Ryujinx.Horizon.Generators.Hipc
{ {
ISymbol symbol = compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetDeclaredSymbol(syntaxNode); ISymbol symbol = compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetDeclaredSymbol(syntaxNode);
foreach (var attribute in symbol.GetAttributes()) if (symbol != null)
{ {
if (attribute.AttributeClass.ToDisplayString() == attributeName && (uint)argIndex < (uint)attribute.ConstructorArguments.Length) foreach (var attribute in symbol.GetAttributes())
{ {
yield return attribute.ConstructorArguments[argIndex].ToCSharpString(); if (attribute.AttributeClass?.ToDisplayString() == attributeName &&
(uint)argIndex < (uint)attribute.ConstructorArguments.Length)
{
yield return attribute.ConstructorArguments[argIndex].ToCSharpString();
}
} }
} }
} }
@ -507,18 +514,21 @@ namespace Ryujinx.Horizon.Generators.Hipc
{ {
TypeInfo typeInfo = compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetTypeInfo(syntaxNode); TypeInfo typeInfo = compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetTypeInfo(syntaxNode);
return typeInfo.Type.ToDisplayString(); return typeInfo.Type?.ToDisplayString();
} }
private static string GetCanonicalTypeName(Compilation compilation, SyntaxNode syntaxNode) private static string GetCanonicalTypeName(Compilation compilation, SyntaxNode syntaxNode)
{ {
TypeInfo typeInfo = compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetTypeInfo(syntaxNode); TypeInfo typeInfo = compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetTypeInfo(syntaxNode);
string typeName = typeInfo.Type.ToDisplayString(); string typeName = typeInfo.Type?.ToDisplayString();
int genericArgsStartIndex = typeName.IndexOf('<'); if (typeName != null)
if (genericArgsStartIndex >= 0)
{ {
return typeName.Substring(0, genericArgsStartIndex); int genericArgsStartIndex = typeName.IndexOf('<');
if (genericArgsStartIndex >= 0)
{
return typeName.Substring(0, genericArgsStartIndex);
}
} }
return typeName; return typeName;
@ -528,7 +538,7 @@ namespace Ryujinx.Horizon.Generators.Hipc
{ {
TypeInfo typeInfo = compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetTypeInfo(syntaxNode); TypeInfo typeInfo = compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetTypeInfo(syntaxNode);
return typeInfo.Type.SpecialType; return typeInfo.Type?.SpecialType ?? SpecialType.None;
} }
private static string GetTypeAlignmentExpression(Compilation compilation, SyntaxNode syntaxNode) private static string GetTypeAlignmentExpression(Compilation compilation, SyntaxNode syntaxNode)
@ -539,7 +549,7 @@ namespace Ryujinx.Horizon.Generators.Hipc
// "special" types are primitive types aligned to their own length. // "special" types are primitive types aligned to their own length.
// Otherwise, assume that the type is a custom struct, that either defines an explicit alignment // Otherwise, assume that the type is a custom struct, that either defines an explicit alignment
// or has an alignment of 1 which is the lowest possible value. // or has an alignment of 1 which is the lowest possible value.
if (typeInfo.Type.SpecialType == SpecialType.None) if (typeInfo.Type is { SpecialType: SpecialType.None })
{ {
string pack = GetTypeFirstNamedAttributeAgument(compilation, syntaxNode, TypeStructLayoutAttribute, "Pack"); string pack = GetTypeFirstNamedAttributeAgument(compilation, syntaxNode, TypeStructLayoutAttribute, "Pack");
@ -547,7 +557,7 @@ namespace Ryujinx.Horizon.Generators.Hipc
} }
else else
{ {
return $"Unsafe.SizeOf<{typeInfo.Type.ToDisplayString()}>()"; return $"Unsafe.SizeOf<{typeInfo.Type?.ToDisplayString()}>()";
} }
} }
@ -555,13 +565,13 @@ namespace Ryujinx.Horizon.Generators.Hipc
{ {
ISymbol symbol = compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetTypeInfo(syntaxNode).Type; ISymbol symbol = compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetTypeInfo(syntaxNode).Type;
foreach (var attribute in symbol.GetAttributes()) if (symbol != null)
{ {
if (attribute.AttributeClass.ToDisplayString() == attributeName) foreach (var attribute in symbol.GetAttributes())
{ {
foreach (var kv in attribute.NamedArguments) if (attribute.AttributeClass?.ToDisplayString() == attributeName)
{ {
if (kv.Key == argName) foreach (var kv in attribute.NamedArguments.Where(kv => kv.Key == argName))
{ {
return kv.Value.ToCSharpString(); return kv.Value.ToCSharpString();
} }
@ -664,7 +674,7 @@ namespace Ryujinx.Horizon.Generators.Hipc
{ {
TypeInfo typeInfo = compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetTypeInfo(syntaxNode); TypeInfo typeInfo = compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetTypeInfo(syntaxNode);
return typeInfo.Type.IsUnmanagedType; return typeInfo.Type is { IsUnmanagedType: true };
} }
private static bool IsMemory(Compilation compilation, ParameterSyntax parameter) private static bool IsMemory(Compilation compilation, ParameterSyntax parameter)
@ -707,10 +717,11 @@ namespace Ryujinx.Horizon.Generators.Hipc
private static bool IsObject(Compilation compilation, ParameterSyntax parameter) private static bool IsObject(Compilation compilation, ParameterSyntax parameter)
{ {
SyntaxNode syntaxNode = parameter.Type; SyntaxNode syntaxNode = parameter.Type;
TypeInfo typeInfo = compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetTypeInfo(syntaxNode); TypeInfo typeInfo = compilation.GetSemanticModel(syntaxNode!.SyntaxTree).GetTypeInfo(syntaxNode);
return typeInfo.Type.ToDisplayString() == TypeIServiceObject || return typeInfo.Type != null &&
typeInfo.Type.AllInterfaces.Any(x => x.ToDisplayString() == TypeIServiceObject); (typeInfo.Type.ToDisplayString() == TypeIServiceObject ||
typeInfo.Type.AllInterfaces.Any(x => x.ToDisplayString() == TypeIServiceObject));
} }
private static bool IsProcessId(Compilation compilation, ParameterSyntax parameter) private static bool IsProcessId(Compilation compilation, ParameterSyntax parameter)
@ -781,7 +792,7 @@ namespace Ryujinx.Horizon.Generators.Hipc
private static bool NeedsIServiceObjectImplementation(Compilation compilation, ClassDeclarationSyntax classDeclarationSyntax) private static bool NeedsIServiceObjectImplementation(Compilation compilation, ClassDeclarationSyntax classDeclarationSyntax)
{ {
ITypeSymbol type = compilation.GetSemanticModel(classDeclarationSyntax.SyntaxTree).GetDeclaredSymbol(classDeclarationSyntax); ITypeSymbol type = compilation.GetSemanticModel(classDeclarationSyntax.SyntaxTree).GetDeclaredSymbol(classDeclarationSyntax);
var serviceObjectInterface = type.AllInterfaces.FirstOrDefault(x => x.ToDisplayString() == TypeIServiceObject); var serviceObjectInterface = type?.AllInterfaces.FirstOrDefault(x => x.ToDisplayString() == TypeIServiceObject);
var interfaceMember = serviceObjectInterface?.GetMembers().FirstOrDefault(x => x.Name == "GetCommandHandlers"); var interfaceMember = serviceObjectInterface?.GetMembers().FirstOrDefault(x => x.Name == "GetCommandHandlers");
// Return true only if the class implements IServiceObject but does not actually implement the method // Return true only if the class implements IServiceObject but does not actually implement the method

View file

@ -147,20 +147,26 @@ namespace Ryujinx.Horizon.Kernel.Generators
List<SyscallIdAndName> syscalls = []; List<SyscallIdAndName> syscalls = [];
foreach (var method in syntaxReceiver.SvcImplementations) if (syntaxReceiver != null)
{ {
GenerateMethod32(generator, context.Compilation, method); foreach (var method in syntaxReceiver.SvcImplementations)
GenerateMethod64(generator, context.Compilation, method);
foreach (AttributeSyntax attribute in method.AttributeLists.SelectMany(attributeList =>
attributeList.Attributes.Where(attribute =>
GetCanonicalTypeName(context.Compilation, attribute) == TypeSvcAttribute)))
{ {
syscalls.AddRange(from attributeArg in attribute.ArgumentList.Arguments GenerateMethod32(generator, context.Compilation, method);
where attributeArg.Expression.Kind() == SyntaxKind.NumericLiteralExpression GenerateMethod64(generator, context.Compilation, method);
select (LiteralExpressionSyntax)attributeArg.Expression
into numericLiteral foreach (AttributeSyntax attribute in method.AttributeLists.SelectMany(attributeList =>
select new SyscallIdAndName((int)numericLiteral.Token.Value, method.Identifier.Text)); attributeList.Attributes.Where(attribute =>
GetCanonicalTypeName(context.Compilation, attribute) == TypeSvcAttribute)))
{
if (attribute.ArgumentList != null)
{
syscalls.AddRange(from attributeArg in attribute.ArgumentList.Arguments
where attributeArg.Expression.Kind() == SyntaxKind.NumericLiteralExpression
select (LiteralExpressionSyntax)attributeArg.Expression
into numericLiteral
select new SyscallIdAndName((int)numericLiteral.Token.Value, method.Identifier.Text));
}
}
} }
} }

View file

@ -127,7 +127,11 @@ namespace Ryujinx.Horizon.Arp.Ipc
return ArpResult.InvalidInstanceId; return ArpResult.InvalidInstanceId;
} }
applicationCertificate = _applicationInstanceManager.Entries[applicationInstanceId].Certificate.Value; ApplicationCertificate? certificate = _applicationInstanceManager.Entries[applicationInstanceId].Certificate;
if (certificate != null)
{
applicationCertificate = certificate.Value;
}
return Result.Success; return Result.Success;
} }

View file

@ -510,7 +510,7 @@ namespace Ryujinx.Input.HLE
{ {
var keyboard = KeyboardDriver.GetGamepad("0") as IKeyboard; var keyboard = KeyboardDriver.GetGamepad("0") as IKeyboard;
KeyboardStateSnapshot keyboardState = keyboard.GetKeyboardStateSnapshot(); KeyboardStateSnapshot keyboardState = keyboard?.GetKeyboardStateSnapshot();
KeyboardInput hidKeyboard = new() KeyboardInput hidKeyboard = new()
{ {
@ -520,14 +520,14 @@ namespace Ryujinx.Input.HLE
foreach (HLEKeyboardMappingEntry entry in _keyMapping) foreach (HLEKeyboardMappingEntry entry in _keyMapping)
{ {
ulong value = keyboardState.IsPressed(entry.TargetKey) ? 1UL : 0UL; ulong value = keyboardState != null && keyboardState.IsPressed(entry.TargetKey) ? 1UL : 0UL;
hidKeyboard.Keys[entry.Target / 0x40] |= (value << (entry.Target % 0x40)); hidKeyboard.Keys[entry.Target / 0x40] |= (value << (entry.Target % 0x40));
} }
foreach (HLEKeyboardMappingEntry entry in _keyModifierMapping) foreach (HLEKeyboardMappingEntry entry in _keyModifierMapping)
{ {
int value = keyboardState.IsPressed(entry.TargetKey) ? 1 : 0; int value = keyboardState != null && keyboardState.IsPressed(entry.TargetKey) ? 1 : 0;
hidKeyboard.Modifier |= value << entry.Target; hidKeyboard.Modifier |= value << entry.Target;
} }

View file

@ -304,9 +304,12 @@ namespace Ryujinx.Input.HLE
buttons |= 1 << 4; buttons |= 1 << 4;
} }
var position = IMouse.GetScreenPosition(mouseInput.Position, mouse.ClientSize, aspectRatio); if (mouse != null)
{
var position = IMouse.GetScreenPosition(mouseInput.Position, mouse.ClientSize, aspectRatio);
_device.Hid.Mouse.Update((int)position.X, (int)position.Y, buttons, (int)mouseInput.Scroll.X, (int)mouseInput.Scroll.Y, true); _device.Hid.Mouse.Update((int)position.X, (int)position.Y, buttons, (int)mouseInput.Scroll.X, (int)mouseInput.Scroll.Y, true);
}
} }
else else
{ {

View file

@ -88,11 +88,16 @@ namespace Ryujinx.UI.App.Common
private static byte[] GetResourceBytes(string resourceName) private static byte[] GetResourceBytes(string resourceName)
{ {
Stream resourceStream = Assembly.GetCallingAssembly().GetManifestResourceStream(resourceName); Stream resourceStream = Assembly.GetCallingAssembly().GetManifestResourceStream(resourceName);
byte[] resourceByteArray = new byte[resourceStream.Length]; if (resourceStream != null)
{
byte[] resourceByteArray = new byte[resourceStream.Length];
resourceStream.ReadExactly(resourceByteArray); resourceStream.ReadExactly(resourceByteArray);
return resourceByteArray; return resourceByteArray;
}
return [];
} }
/// <exception cref="Ryujinx.HLE.Exceptions.InvalidNpdmException">The npdm file doesn't contain valid data.</exception> /// <exception cref="Ryujinx.HLE.Exceptions.InvalidNpdmException">The npdm file doesn't contain valid data.</exception>
@ -1178,7 +1183,7 @@ namespace Ryujinx.UI.App.Common
{ {
string extension = Path.GetExtension(applicationPath)?.ToLower(); string extension = Path.GetExtension(applicationPath)?.ToLower();
using FileStream file = new(applicationPath, FileMode.Open, FileAccess.Read); using FileStream file = new(applicationPath ?? string.Empty, FileMode.Open, FileAccess.Read);
if (extension == ".nsp" || extension == ".pfs0" || extension == ".xci") if (extension == ".nsp" || extension == ".pfs0" || extension == ".xci")
{ {

View file

@ -152,7 +152,7 @@ namespace Ryujinx.UI.Common.Helper
Logger.Debug?.Print(LogClass.Application, $"Adding type association {ext}"); Logger.Debug?.Print(LogClass.Application, $"Adding type association {ext}");
using var openCmd = key.CreateSubKey(@"shell\open\command"); using var openCmd = key.CreateSubKey(@"shell\open\command");
openCmd.SetValue("", $"\"{Environment.ProcessPath}\" \"%1\""); openCmd?.SetValue("", $"\"{Environment.ProcessPath}\" \"%1\"");
Logger.Debug?.Print(LogClass.Application, $"Added type association {ext}"); Logger.Debug?.Print(LogClass.Application, $"Added type association {ext}");
} }

View file

@ -36,11 +36,11 @@ namespace Ryujinx.UI.Common.SystemInfo
{ {
foreach (var cpuObj in cpuObjs) foreach (var cpuObj in cpuObjs)
{ {
return cpuObj["Name"].ToString().Trim(); return cpuObj["Name"].ToString()?.Trim();
} }
} }
return Environment.GetEnvironmentVariable("PROCESSOR_IDENTIFIER").Trim(); return Environment.GetEnvironmentVariable("PROCESSOR_IDENTIFIER")?.Trim();
} }
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]

View file

@ -84,7 +84,7 @@ namespace Ryujinx.Ava
if (result == UserResult.Yes) if (result == UserResult.Yes)
{ {
var path = Environment.ProcessPath; var path = Environment.ProcessPath;
var proc = Process.Start(path, CommandLineState.Arguments); var proc = Process.Start(path ?? string.Empty, CommandLineState.Arguments);
desktop.Shutdown(); desktop.Shutdown();
Environment.Exit(0); Environment.Exit(0);
} }
@ -144,7 +144,7 @@ namespace Ryujinx.Ava
public static ThemeVariant DetectSystemTheme() public static ThemeVariant DetectSystemTheme()
{ {
if (Current is App app) if (Current is App { PlatformSettings: not null } app)
{ {
var colorValues = app.PlatformSettings.GetColorValues(); var colorValues = app.PlatformSettings.GetColorValues();

View file

@ -192,7 +192,10 @@ namespace Ryujinx.Modules
HttpResponseMessage message = await buildSizeClient.GetAsync(new Uri(_buildUrl), HttpCompletionOption.ResponseHeadersRead); HttpResponseMessage message = await buildSizeClient.GetAsync(new Uri(_buildUrl), HttpCompletionOption.ResponseHeadersRead);
_buildSize = message.Content.Headers.ContentRange.Length.Value; if (message.Content.Headers.ContentRange?.Length != null)
{
_buildSize = message.Content.Headers.ContentRange.Length.Value;
}
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -376,10 +379,14 @@ namespace Ryujinx.Modules
client.DownloadProgressChanged += (_, args) => client.DownloadProgressChanged += (_, args) =>
{ {
int index = (int)args.UserState; if (args.UserState != null)
{
int index = (int)args.UserState;
Interlocked.Add(ref totalProgressPercentage, -1 * progressPercentage[index]);
Interlocked.Exchange(ref progressPercentage[index], args.ProgressPercentage);
}
Interlocked.Add(ref totalProgressPercentage, -1 * progressPercentage[index]);
Interlocked.Exchange(ref progressPercentage[index], args.ProgressPercentage);
Interlocked.Add(ref totalProgressPercentage, args.ProgressPercentage); Interlocked.Add(ref totalProgressPercentage, args.ProgressPercentage);
taskDialog.SetProgressBarState(totalProgressPercentage / ConnectionCount, TaskDialogProgressState.Normal); taskDialog.SetProgressBarState(totalProgressPercentage / ConnectionCount, TaskDialogProgressState.Normal);
@ -387,18 +394,22 @@ namespace Ryujinx.Modules
client.DownloadDataCompleted += (_, args) => client.DownloadDataCompleted += (_, args) =>
{ {
int index = (int)args.UserState; if (args.UserState != null)
if (args.Cancelled)
{ {
webClients[index].Dispose(); int index = (int)args.UserState;
taskDialog.Hide(); if (args.Cancelled)
{
webClients[index].Dispose();
return; taskDialog.Hide();
return;
}
list[index] = args.Result;
} }
list[index] = args.Result;
Interlocked.Increment(ref completedRequests); Interlocked.Increment(ref completedRequests);
if (Equals(completedRequests, ConnectionCount)) if (Equals(completedRequests, ConnectionCount))
@ -465,25 +476,28 @@ namespace Ryujinx.Modules
using Stream remoteFileStream = response.Content.ReadAsStreamAsync().Result; using Stream remoteFileStream = response.Content.ReadAsStreamAsync().Result;
using Stream updateFileStream = File.Open(updateFile, FileMode.Create); using Stream updateFileStream = File.Open(updateFile, FileMode.Create);
long totalBytes = response.Content.Headers.ContentLength.Value; if (response.Content.Headers.ContentLength != null)
long byteWritten = 0;
byte[] buffer = new byte[32 * 1024];
while (true)
{ {
int readSize = remoteFileStream.Read(buffer); long totalBytes = response.Content.Headers.ContentLength.Value;
long byteWritten = 0;
if (readSize == 0) byte[] buffer = new byte[32 * 1024];
while (true)
{ {
break; int readSize = remoteFileStream.Read(buffer);
if (readSize == 0)
{
break;
}
byteWritten += readSize;
taskDialog.SetProgressBarState(GetPercentage(byteWritten, totalBytes), TaskDialogProgressState.Normal);
updateFileStream.Write(buffer, 0, readSize);
} }
byteWritten += readSize;
taskDialog.SetProgressBarState(GetPercentage(byteWritten, totalBytes), TaskDialogProgressState.Normal);
updateFileStream.Write(buffer, 0, readSize);
} }
InstallUpdate(taskDialog, updateFile); InstallUpdate(taskDialog, updateFile);
@ -524,7 +538,7 @@ namespace Ryujinx.Modules
string outPath = Path.Combine(outputDirectoryPath, tarEntry.Name); string outPath = Path.Combine(outputDirectoryPath, tarEntry.Name);
Directory.CreateDirectory(Path.GetDirectoryName(outPath)); Directory.CreateDirectory(Path.GetDirectoryName(outPath) ?? string.Empty);
using FileStream outStream = File.OpenWrite(outPath); using FileStream outStream = File.OpenWrite(outPath);
tarStream.CopyEntryContents(outStream); tarStream.CopyEntryContents(outStream);
@ -560,7 +574,7 @@ namespace Ryujinx.Modules
string outPath = Path.Combine(outputDirectoryPath, zipEntry.Name); string outPath = Path.Combine(outputDirectoryPath, zipEntry.Name);
Directory.CreateDirectory(Path.GetDirectoryName(outPath)); Directory.CreateDirectory(Path.GetDirectoryName(outPath) ?? string.Empty);
using Stream zipStream = zipFile.GetInputStream(zipEntry); using Stream zipStream = zipFile.GetInputStream(zipEntry);
using FileStream outStream = File.OpenWrite(outPath); using FileStream outStream = File.OpenWrite(outPath);

View file

@ -25,9 +25,9 @@ namespace Ryujinx.Ava.UI.Applet
{ {
_parent = parent; _parent = parent;
(_parent.InputManager.KeyboardDriver as AvaloniaKeyboardDriver).KeyPressed += AvaloniaDynamicTextInputHandler_KeyPressed; ((AvaloniaKeyboardDriver)_parent.InputManager.KeyboardDriver).KeyPressed += AvaloniaDynamicTextInputHandler_KeyPressed;
(_parent.InputManager.KeyboardDriver as AvaloniaKeyboardDriver).KeyRelease += AvaloniaDynamicTextInputHandler_KeyRelease; ((AvaloniaKeyboardDriver)_parent.InputManager.KeyboardDriver).KeyRelease += AvaloniaDynamicTextInputHandler_KeyRelease;
(_parent.InputManager.KeyboardDriver as AvaloniaKeyboardDriver).TextInput += AvaloniaDynamicTextInputHandler_TextInput; ((AvaloniaKeyboardDriver)_parent.InputManager.KeyboardDriver).TextInput += AvaloniaDynamicTextInputHandler_TextInput;
_hiddenTextBox = _parent.HiddenTextBox; _hiddenTextBox = _parent.HiddenTextBox;
@ -118,9 +118,9 @@ namespace Ryujinx.Ava.UI.Applet
public void Dispose() public void Dispose()
{ {
(_parent.InputManager.KeyboardDriver as AvaloniaKeyboardDriver).KeyPressed -= AvaloniaDynamicTextInputHandler_KeyPressed; ((AvaloniaKeyboardDriver)_parent.InputManager.KeyboardDriver).KeyPressed -= AvaloniaDynamicTextInputHandler_KeyPressed;
(_parent.InputManager.KeyboardDriver as AvaloniaKeyboardDriver).KeyRelease -= AvaloniaDynamicTextInputHandler_KeyRelease; ((AvaloniaKeyboardDriver)_parent.InputManager.KeyboardDriver).KeyRelease -= AvaloniaDynamicTextInputHandler_KeyRelease;
(_parent.InputManager.KeyboardDriver as AvaloniaKeyboardDriver).TextInput -= AvaloniaDynamicTextInputHandler_TextInput; ((AvaloniaKeyboardDriver)_parent.InputManager.KeyboardDriver).TextInput -= AvaloniaDynamicTextInputHandler_TextInput;
_textChangedSubscription?.Dispose(); _textChangedSubscription?.Dispose();
_selectionStartChangedSubscription?.Dispose(); _selectionStartChangedSubscription?.Dispose();

View file

@ -111,7 +111,7 @@ namespace Ryujinx.Ava.UI.Controls
viewModel.VirtualFileSystem, viewModel.VirtualFileSystem,
viewModel.SelectedApplication.IdString, viewModel.SelectedApplication.IdString,
viewModel.SelectedApplication.Name, viewModel.SelectedApplication.Name,
viewModel.SelectedApplication.Path).ShowDialog(viewModel.TopLevel as Window); viewModel.SelectedApplication.Path).ShowDialog((Window)viewModel.TopLevel);
} }
} }
@ -396,9 +396,12 @@ namespace Ryujinx.Ava.UI.Controls
viewModel.SelectedApplication.Name); viewModel.SelectedApplication.Name);
var iconFile = await result[0].CreateFileAsync(selectedApp.IdString + ".png"); var iconFile = await result[0].CreateFileAsync(selectedApp.IdString + ".png");
await using var fileStream = await iconFile.OpenWriteAsync(); if (iconFile != null)
{
await using var fileStream = await iconFile.OpenWriteAsync();
fileStream.Write(selectedApp.Icon); fileStream.Write(selectedApp.Icon);
}
} }
} }

View file

@ -37,7 +37,7 @@ namespace Ryujinx.Ava.UI.Controls
private void SearchBox_OnKeyUp(object sender, KeyEventArgs args) private void SearchBox_OnKeyUp(object sender, KeyEventArgs args)
{ {
(DataContext as MainWindowViewModel).SearchText = (sender as TextBox).Text; (DataContext as MainWindowViewModel).SearchText = (sender as TextBox)?.Text;
} }
} }
} }

View file

@ -38,7 +38,7 @@ namespace Ryujinx.Ava.UI.Controls
private void SearchBox_OnKeyUp(object sender, KeyEventArgs args) private void SearchBox_OnKeyUp(object sender, KeyEventArgs args)
{ {
(DataContext as MainWindowViewModel).SearchText = (sender as TextBox).Text; (DataContext as MainWindowViewModel).SearchText = (sender as TextBox)?.Text;
} }
private async void IdString_OnClick(object sender, RoutedEventArgs e) private async void IdString_OnClick(object sender, RoutedEventArgs e)

View file

@ -52,8 +52,8 @@ namespace Ryujinx.Ava.UI.Models
if (InGameList) if (InGameList)
{ {
Icon = appData.Icon; Icon = appData?.Icon;
Title = appData.Name; Title = appData?.Name;
} }
else else
{ {

View file

@ -88,7 +88,7 @@ namespace Ryujinx.Ava.UI.Models
private void UpdateBackground() private void UpdateBackground()
{ {
var currentApplication = Avalonia.Application.Current; var currentApplication = Avalonia.Application.Current;
currentApplication.Styles.TryGetResource("ControlFillColorSecondary", currentApplication.ActualThemeVariant, out object color); currentApplication!.Styles.TryGetResource("ControlFillColorSecondary", currentApplication.ActualThemeVariant, out object color);
if (color is not null) if (color is not null)
{ {

View file

@ -127,8 +127,11 @@ namespace Ryujinx.Ava.UI.Renderer
X11Window = PlatformHelper.CreateOpenGLWindow(new FramebufferFormat(new ColorFormat(8, 8, 8, 0), 16, 0, ColorFormat.Zero, 0, 2, false), 0, 0, 100, 100) as GLXWindow; X11Window = PlatformHelper.CreateOpenGLWindow(new FramebufferFormat(new ColorFormat(8, 8, 8, 0), 16, 0, ColorFormat.Zero, 0, 2, false), 0, 0, 100, 100) as GLXWindow;
} }
WindowHandle = X11Window.WindowHandle.RawHandle; if (X11Window != null)
X11Display = X11Window.DisplayHandle.RawHandle; {
WindowHandle = X11Window.WindowHandle.RawHandle;
X11Display = X11Window.DisplayHandle.RawHandle;
}
return new PlatformHandle(WindowHandle, "X11"); return new PlatformHandle(WindowHandle, "X11");
} }

View file

@ -37,7 +37,7 @@ namespace Ryujinx.Ava.UI.ViewModels
return app.Favorite ? -1 : 1; return app.Favorite ? -1 : 1;
} }
throw new InvalidCastException($"Cannot cast {o.GetType()} to {nameof(AppListFavoriteComparable)}"); throw new InvalidCastException($"Cannot cast {o?.GetType()} to {nameof(AppListFavoriteComparable)}");
} }
} }
} }

View file

@ -92,9 +92,9 @@ namespace Ryujinx.Ava.UI.ViewModels
_applicationData = applicationData; _applicationData = applicationData;
if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{ {
_storageProvider = desktop.MainWindow.StorageProvider; _storageProvider = desktop.MainWindow?.StorageProvider;
} }
LoadDownloadableContents(); LoadDownloadableContents();

View file

@ -254,10 +254,13 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
AvaloniaKeyboardDriver = new AvaloniaKeyboardDriver(owner); AvaloniaKeyboardDriver = new AvaloniaKeyboardDriver(owner);
_mainWindow.InputManager.GamepadDriver.OnGamepadConnected += HandleOnGamepadConnected; if (_mainWindow != null)
_mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected; {
_mainWindow.InputManager.GamepadDriver.OnGamepadConnected += HandleOnGamepadConnected;
_mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected;
_mainWindow.ViewModel.AppHost?.NpadManager.BlockInputUpdates(); _mainWindow.ViewModel.AppHost?.NpadManager.BlockInputUpdates();
}
_isLoaded = false; _isLoaded = false;
@ -783,11 +786,14 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
config = (ConfigViewModel as ControllerInputViewModel)?.Config.GetConfig(); config = (ConfigViewModel as ControllerInputViewModel)?.Config.GetConfig();
} }
config.ControllerType = Controllers[_controller].Type; if (config != null)
{
config.ControllerType = Controllers[_controller].Type;
string jsonString = JsonHelper.Serialize(config, _serializerContext.InputConfig); string jsonString = JsonHelper.Serialize(config, _serializerContext.InputConfig);
await File.WriteAllTextAsync(path, jsonString); await File.WriteAllTextAsync(path, jsonString);
}
LoadProfiles(); LoadProfiles();
} }

View file

@ -1332,7 +1332,7 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
catch (MissingKeyException ex) catch (MissingKeyException ex)
{ {
if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{ {
Logger.Error?.Print(LogClass.Application, ex.ToString()); Logger.Error?.Print(LogClass.Application, ex.ToString());
@ -1553,7 +1553,7 @@ namespace Ryujinx.Ava.UI.ViewModels
{ {
Dispatcher.UIThread.InvokeAsync(() => Dispatcher.UIThread.InvokeAsync(() =>
{ {
Application.Current.Styles.TryGetResource(args.VSyncMode, Application.Current!.Styles.TryGetResource(args.VSyncMode,
Application.Current.ActualThemeVariant, Application.Current.ActualThemeVariant,
out object color); out object color);

View file

@ -279,7 +279,7 @@ namespace Ryujinx.Ava.UI.ViewModels
foreach (var dir in directories) foreach (var dir in directories)
{ {
string dirToCreate = dir.Replace(directory.Parent.ToString(), destinationDir); string dirToCreate = dir.Replace(directory.Parent?.ToString() ?? string.Empty, destinationDir);
// Mod already exists // Mod already exists
if (Directory.Exists(dirToCreate)) if (Directory.Exists(dirToCreate))
@ -302,7 +302,7 @@ namespace Ryujinx.Ava.UI.ViewModels
foreach (var file in files) foreach (var file in files)
{ {
File.Copy(file, file.Replace(directory.Parent.ToString(), destinationDir), true); File.Copy(file, file.Replace(directory.Parent?.ToString() ?? string.Empty, destinationDir), true);
} }
LoadMods(_applicationId, _installedDlcIds); LoadMods(_applicationId, _installedDlcIds);

View file

@ -75,9 +75,9 @@ namespace Ryujinx.Ava.UI.ViewModels
ApplicationData = applicationData; ApplicationData = applicationData;
if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{ {
StorageProvider = desktop.MainWindow.StorageProvider; StorageProvider = desktop.MainWindow?.StorageProvider;
} }
LoadUpdates(); LoadUpdates();

View file

@ -268,7 +268,11 @@ namespace Ryujinx.Ava.UI.ViewModels
result = String.Compare(x?.Name, y?.Name, StringComparison.Ordinal); result = String.Compare(x?.Name, y?.Name, StringComparison.Ordinal);
break; break;
case SortField.Saved: case SortField.Saved:
result = x.PotentialSavingsB.CompareTo(y.PotentialSavingsB); if (x != null && y != null)
{
result = x.PotentialSavingsB.CompareTo(y.PotentialSavingsB);
}
break; break;
} }

View file

@ -70,8 +70,12 @@ namespace Ryujinx.Ava.UI.Views.Input
{ {
var viewModel = (DataContext as ControllerInputViewModel); var viewModel = (DataContext as ControllerInputViewModel);
viewModel.ParentModel.IsModified = true; if (viewModel != null)
_changeSlider = (float)check.Value; {
viewModel.ParentModel.IsModified = true;
}
_changeSlider = (float)check.Value;
} }
} }
} }
@ -82,9 +86,11 @@ namespace Ryujinx.Ava.UI.Views.Input
{ {
if ((bool)check.IsPointerOver) if ((bool)check.IsPointerOver)
{ {
if (DataContext is ControllerInputViewModel viewModel)
{
viewModel.ParentModel.IsModified = true;
}
var viewModel = (DataContext as ControllerInputViewModel);
viewModel.ParentModel.IsModified = true;
_currentAssigner?.Cancel(); _currentAssigner?.Cancel();
_currentAssigner = null; _currentAssigner = null;
} }
@ -96,7 +102,7 @@ namespace Ryujinx.Ava.UI.Views.Input
{ {
if (sender is ToggleButton button ) if (sender is ToggleButton button )
{ {
if ((bool)button.IsChecked) if (button.IsChecked != null && (bool)button.IsChecked)
{ {
if (_currentAssigner != null && button == _currentAssigner.ToggledButton) if (_currentAssigner != null && button == _currentAssigner.ToggledButton)
{ {
@ -233,7 +239,7 @@ namespace Ryujinx.Ava.UI.Views.Input
var controllerInputViewModel = DataContext as ControllerInputViewModel; var controllerInputViewModel = DataContext as ControllerInputViewModel;
assigner = new GamepadButtonAssigner( assigner = new GamepadButtonAssigner(
controllerInputViewModel.ParentModel.SelectedGamepad, controllerInputViewModel?.ParentModel.SelectedGamepad,
(controllerInputViewModel.ParentModel.Config as StandardControllerInputConfig).TriggerThreshold, (controllerInputViewModel.ParentModel.Config as StandardControllerInputConfig).TriggerThreshold,
forStick); forStick);

View file

@ -72,7 +72,10 @@ namespace Ryujinx.Ava.UI.Views.Input
{ {
ViewModel.IsModified = true; ViewModel.IsModified = true;
var player = (PlayerModel)e.AddedItems[0]; var player = (PlayerModel)e.AddedItems[0];
ViewModel.PlayerId = player.Id; if (player != null)
{
ViewModel.PlayerId = player.Id;
}
} }
} }
} }

View file

@ -43,7 +43,7 @@ namespace Ryujinx.Ava.UI.Views.Input
{ {
if (sender is ToggleButton button) if (sender is ToggleButton button)
{ {
if ((bool)button.IsChecked) if (button.IsChecked != null && (bool)button.IsChecked)
{ {
if (_currentAssigner != null && button == _currentAssigner.ToggledButton) if (_currentAssigner != null && button == _currentAssigner.ToggledButton)
{ {
@ -60,107 +60,110 @@ namespace Ryujinx.Ava.UI.Views.Input
var viewModel = (DataContext as KeyboardInputViewModel); var viewModel = (DataContext as KeyboardInputViewModel);
IKeyboard keyboard = (IKeyboard)viewModel.ParentModel.AvaloniaKeyboardDriver.GetGamepad("0"); // Open Avalonia keyboard for cancel operations. if (viewModel != null)
IButtonAssigner assigner = CreateButtonAssigner();
_currentAssigner.ButtonAssigned += (sender, e) =>
{ {
if (e.ButtonValue.HasValue) IKeyboard keyboard = (IKeyboard)viewModel.ParentModel.AvaloniaKeyboardDriver.GetGamepad("0"); // Open Avalonia keyboard for cancel operations.
IButtonAssigner assigner = CreateButtonAssigner();
_currentAssigner.ButtonAssigned += (sender, e) =>
{ {
var buttonValue = e.ButtonValue.Value; if (e.ButtonValue.HasValue)
viewModel.ParentModel.IsModified = true;
switch (button.Name)
{ {
case "ButtonZl": var buttonValue = e.ButtonValue.Value;
viewModel.Config.ButtonZl = buttonValue.AsHidType<Key>(); viewModel.ParentModel.IsModified = true;
break;
case "ButtonL":
viewModel.Config.ButtonL = buttonValue.AsHidType<Key>();
break;
case "ButtonMinus":
viewModel.Config.ButtonMinus = buttonValue.AsHidType<Key>();
break;
case "LeftStickButton":
viewModel.Config.LeftStickButton = buttonValue.AsHidType<Key>();
break;
case "LeftStickUp":
viewModel.Config.LeftStickUp = buttonValue.AsHidType<Key>();
break;
case "LeftStickDown":
viewModel.Config.LeftStickDown = buttonValue.AsHidType<Key>();
break;
case "LeftStickRight":
viewModel.Config.LeftStickRight = buttonValue.AsHidType<Key>();
break;
case "LeftStickLeft":
viewModel.Config.LeftStickLeft = buttonValue.AsHidType<Key>();
break;
case "DpadUp":
viewModel.Config.DpadUp = buttonValue.AsHidType<Key>();
break;
case "DpadDown":
viewModel.Config.DpadDown = buttonValue.AsHidType<Key>();
break;
case "DpadLeft":
viewModel.Config.DpadLeft = buttonValue.AsHidType<Key>();
break;
case "DpadRight":
viewModel.Config.DpadRight = buttonValue.AsHidType<Key>();
break;
case "LeftButtonSr":
viewModel.Config.LeftButtonSr = buttonValue.AsHidType<Key>();
break;
case "LeftButtonSl":
viewModel.Config.LeftButtonSl = buttonValue.AsHidType<Key>();
break;
case "RightButtonSr":
viewModel.Config.RightButtonSr = buttonValue.AsHidType<Key>();
break;
case "RightButtonSl":
viewModel.Config.RightButtonSl = buttonValue.AsHidType<Key>();
break;
case "ButtonZr":
viewModel.Config.ButtonZr = buttonValue.AsHidType<Key>();
break;
case "ButtonR":
viewModel.Config.ButtonR = buttonValue.AsHidType<Key>();
break;
case "ButtonPlus":
viewModel.Config.ButtonPlus = buttonValue.AsHidType<Key>();
break;
case "ButtonA":
viewModel.Config.ButtonA = buttonValue.AsHidType<Key>();
break;
case "ButtonB":
viewModel.Config.ButtonB = buttonValue.AsHidType<Key>();
break;
case "ButtonX":
viewModel.Config.ButtonX = buttonValue.AsHidType<Key>();
break;
case "ButtonY":
viewModel.Config.ButtonY = buttonValue.AsHidType<Key>();
break;
case "RightStickButton":
viewModel.Config.RightStickButton = buttonValue.AsHidType<Key>();
break;
case "RightStickUp":
viewModel.Config.RightStickUp = buttonValue.AsHidType<Key>();
break;
case "RightStickDown":
viewModel.Config.RightStickDown = buttonValue.AsHidType<Key>();
break;
case "RightStickRight":
viewModel.Config.RightStickRight = buttonValue.AsHidType<Key>();
break;
case "RightStickLeft":
viewModel.Config.RightStickLeft = buttonValue.AsHidType<Key>();
break;
}
}
};
_currentAssigner.GetInputAndAssign(assigner, keyboard); switch (button.Name)
{
case "ButtonZl":
viewModel.Config.ButtonZl = buttonValue.AsHidType<Key>();
break;
case "ButtonL":
viewModel.Config.ButtonL = buttonValue.AsHidType<Key>();
break;
case "ButtonMinus":
viewModel.Config.ButtonMinus = buttonValue.AsHidType<Key>();
break;
case "LeftStickButton":
viewModel.Config.LeftStickButton = buttonValue.AsHidType<Key>();
break;
case "LeftStickUp":
viewModel.Config.LeftStickUp = buttonValue.AsHidType<Key>();
break;
case "LeftStickDown":
viewModel.Config.LeftStickDown = buttonValue.AsHidType<Key>();
break;
case "LeftStickRight":
viewModel.Config.LeftStickRight = buttonValue.AsHidType<Key>();
break;
case "LeftStickLeft":
viewModel.Config.LeftStickLeft = buttonValue.AsHidType<Key>();
break;
case "DpadUp":
viewModel.Config.DpadUp = buttonValue.AsHidType<Key>();
break;
case "DpadDown":
viewModel.Config.DpadDown = buttonValue.AsHidType<Key>();
break;
case "DpadLeft":
viewModel.Config.DpadLeft = buttonValue.AsHidType<Key>();
break;
case "DpadRight":
viewModel.Config.DpadRight = buttonValue.AsHidType<Key>();
break;
case "LeftButtonSr":
viewModel.Config.LeftButtonSr = buttonValue.AsHidType<Key>();
break;
case "LeftButtonSl":
viewModel.Config.LeftButtonSl = buttonValue.AsHidType<Key>();
break;
case "RightButtonSr":
viewModel.Config.RightButtonSr = buttonValue.AsHidType<Key>();
break;
case "RightButtonSl":
viewModel.Config.RightButtonSl = buttonValue.AsHidType<Key>();
break;
case "ButtonZr":
viewModel.Config.ButtonZr = buttonValue.AsHidType<Key>();
break;
case "ButtonR":
viewModel.Config.ButtonR = buttonValue.AsHidType<Key>();
break;
case "ButtonPlus":
viewModel.Config.ButtonPlus = buttonValue.AsHidType<Key>();
break;
case "ButtonA":
viewModel.Config.ButtonA = buttonValue.AsHidType<Key>();
break;
case "ButtonB":
viewModel.Config.ButtonB = buttonValue.AsHidType<Key>();
break;
case "ButtonX":
viewModel.Config.ButtonX = buttonValue.AsHidType<Key>();
break;
case "ButtonY":
viewModel.Config.ButtonY = buttonValue.AsHidType<Key>();
break;
case "RightStickButton":
viewModel.Config.RightStickButton = buttonValue.AsHidType<Key>();
break;
case "RightStickUp":
viewModel.Config.RightStickUp = buttonValue.AsHidType<Key>();
break;
case "RightStickDown":
viewModel.Config.RightStickDown = buttonValue.AsHidType<Key>();
break;
case "RightStickRight":
viewModel.Config.RightStickRight = buttonValue.AsHidType<Key>();
break;
case "RightStickLeft":
viewModel.Config.RightStickLeft = buttonValue.AsHidType<Key>();
break;
}
}
};
_currentAssigner.GetInputAndAssign(assigner, keyboard);
}
} }
else else
{ {
@ -193,7 +196,7 @@ namespace Ryujinx.Ava.UI.Views.Input
{ {
IButtonAssigner assigner; IButtonAssigner assigner;
assigner = new KeyboardKeyAssigner((IKeyboard)(DataContext as KeyboardInputViewModel).ParentModel.SelectedGamepad); assigner = new KeyboardKeyAssigner((IKeyboard)(DataContext as KeyboardInputViewModel)?.ParentModel.SelectedGamepad);
return assigner; return assigner;
} }

View file

@ -34,7 +34,7 @@ namespace Ryujinx.Ava.UI.Views.Main
{ {
if (sender is RadioButton button) if (sender is RadioButton button)
{ {
ViewModel.Sort(Enum.Parse<ApplicationSort>(button.Tag.ToString())); ViewModel.Sort(Enum.Parse<ApplicationSort>(button.Tag?.ToString() ?? string.Empty));
} }
} }
@ -42,7 +42,7 @@ namespace Ryujinx.Ava.UI.Views.Main
{ {
if (sender is RadioButton button) if (sender is RadioButton button)
{ {
ViewModel.Sort(button.Tag.ToString() != "Descending"); ViewModel.Sort(button.Tag?.ToString() != "Descending");
} }
} }

View file

@ -46,7 +46,7 @@ namespace Ryujinx.Ava.UI.Views.Settings
{ {
if (sender is ToggleButton button) if (sender is ToggleButton button)
{ {
if ((bool)button.IsChecked) if (button.IsChecked != null && (bool)button.IsChecked)
{ {
if (_currentAssigner != null && button == _currentAssigner.ToggledButton) if (_currentAssigner != null && button == _currentAssigner.ToggledButton)
{ {
@ -69,41 +69,44 @@ namespace Ryujinx.Ava.UI.Views.Settings
var viewModel = (DataContext) as SettingsViewModel; var viewModel = (DataContext) as SettingsViewModel;
var buttonValue = e.ButtonValue.Value; var buttonValue = e.ButtonValue.Value;
switch (button.Name) if (viewModel != null)
{ {
case "ToggleVSyncMode": switch (button.Name)
viewModel.KeyboardHotkey.ToggleVSyncMode = buttonValue.AsHidType<Key>(); {
break; case "ToggleVSyncMode":
case "Screenshot": viewModel.KeyboardHotkey.ToggleVSyncMode = buttonValue.AsHidType<Key>();
viewModel.KeyboardHotkey.Screenshot = buttonValue.AsHidType<Key>(); break;
break; case "Screenshot":
case "ShowUI": viewModel.KeyboardHotkey.Screenshot = buttonValue.AsHidType<Key>();
viewModel.KeyboardHotkey.ShowUI = buttonValue.AsHidType<Key>(); break;
break; case "ShowUI":
case "Pause": viewModel.KeyboardHotkey.ShowUI = buttonValue.AsHidType<Key>();
viewModel.KeyboardHotkey.Pause = buttonValue.AsHidType<Key>(); break;
break; case "Pause":
case "ToggleMute": viewModel.KeyboardHotkey.Pause = buttonValue.AsHidType<Key>();
viewModel.KeyboardHotkey.ToggleMute = buttonValue.AsHidType<Key>(); break;
break; case "ToggleMute":
case "ResScaleUp": viewModel.KeyboardHotkey.ToggleMute = buttonValue.AsHidType<Key>();
viewModel.KeyboardHotkey.ResScaleUp = buttonValue.AsHidType<Key>(); break;
break; case "ResScaleUp":
case "ResScaleDown": viewModel.KeyboardHotkey.ResScaleUp = buttonValue.AsHidType<Key>();
viewModel.KeyboardHotkey.ResScaleDown = buttonValue.AsHidType<Key>(); break;
break; case "ResScaleDown":
case "VolumeUp": viewModel.KeyboardHotkey.ResScaleDown = buttonValue.AsHidType<Key>();
viewModel.KeyboardHotkey.VolumeUp = buttonValue.AsHidType<Key>(); break;
break; case "VolumeUp":
case "VolumeDown": viewModel.KeyboardHotkey.VolumeUp = buttonValue.AsHidType<Key>();
viewModel.KeyboardHotkey.VolumeDown = buttonValue.AsHidType<Key>(); break;
break; case "VolumeDown":
case "CustomVSyncIntervalIncrement": viewModel.KeyboardHotkey.VolumeDown = buttonValue.AsHidType<Key>();
viewModel.KeyboardHotkey.CustomVSyncIntervalIncrement = buttonValue.AsHidType<Key>(); break;
break; case "CustomVSyncIntervalIncrement":
case "CustomVSyncIntervalDecrement": viewModel.KeyboardHotkey.CustomVSyncIntervalIncrement = buttonValue.AsHidType<Key>();
viewModel.KeyboardHotkey.CustomVSyncIntervalDecrement = buttonValue.AsHidType<Key>(); break;
break; case "CustomVSyncIntervalDecrement":
viewModel.KeyboardHotkey.CustomVSyncIntervalDecrement = buttonValue.AsHidType<Key>();
break;
}
} }
} }
}; };

View file

@ -64,7 +64,7 @@ namespace Ryujinx.Ava.UI.Views.User
private async void Import_OnClick(object sender, RoutedEventArgs e) private async void Import_OnClick(object sender, RoutedEventArgs e)
{ {
var window = this.GetVisualRoot() as Window; var window = this.GetVisualRoot() as Window;
var result = await window.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions var result = await window?.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
{ {
AllowMultiple = false, AllowMultiple = false,
FileTypeFilter = new List<FilePickerFileType> FileTypeFilter = new List<FilePickerFileType>

View file

@ -123,7 +123,7 @@ namespace Ryujinx.Ava.UI.Views.User
private void Close(object sender, RoutedEventArgs e) private void Close(object sender, RoutedEventArgs e)
{ {
((ContentDialog)_parent.Parent).Hide(); ((ContentDialog)_parent.Parent)?.Hide();
} }
} }
} }

View file

@ -120,7 +120,7 @@ namespace Ryujinx.Ava.UI.Windows
} }
} }
Directory.CreateDirectory(Path.GetDirectoryName(_enabledCheatsPath)); Directory.CreateDirectory(Path.GetDirectoryName(_enabledCheatsPath) ?? string.Empty);
File.WriteAllLines(_enabledCheatsPath, enabledCheats); File.WriteAllLines(_enabledCheatsPath, enabledCheats);

View file

@ -53,12 +53,12 @@ namespace Ryujinx.Ava.UI.Windows
private void SaveAndClose(object sender, RoutedEventArgs routedEventArgs) private void SaveAndClose(object sender, RoutedEventArgs routedEventArgs)
{ {
ViewModel.Save(); ViewModel.Save();
((ContentDialog)Parent).Hide(); ((ContentDialog)Parent)?.Hide();
} }
private void Close(object sender, RoutedEventArgs e) private void Close(object sender, RoutedEventArgs e)
{ {
((ContentDialog)Parent).Hide(); ((ContentDialog)Parent)?.Hide();
} }
private void RemoveDLC(object sender, RoutedEventArgs e) private void RemoveDLC(object sender, RoutedEventArgs e)

View file

@ -494,7 +494,10 @@ namespace Ryujinx.Ava.UI.Windows
/// <summary> /// <summary>
/// Subscribe to the ColorValuesChanged event /// Subscribe to the ColorValuesChanged event
/// </summary> /// </summary>
PlatformSettings.ColorValuesChanged += OnPlatformColorValuesChanged; if (PlatformSettings != null)
{
PlatformSettings.ColorValuesChanged += OnPlatformColorValuesChanged;
}
ViewModel.Initialize( ViewModel.Initialize(
ContentManager, ContentManager,
@ -578,7 +581,7 @@ namespace Ryujinx.Ava.UI.Windows
var volumeSplitButton = sender as ToggleSplitButton; var volumeSplitButton = sender as ToggleSplitButton;
if (ViewModel.IsGameRunning) if (ViewModel.IsGameRunning)
{ {
if (!volumeSplitButton.IsChecked) if (volumeSplitButton is not { IsChecked: true })
{ {
ViewModel.AppHost.Device.SetVolume(ViewModel.VolumeBeforeMute); ViewModel.AppHost.Device.SetVolume(ViewModel.VolumeBeforeMute);
} }

View file

@ -53,12 +53,12 @@ namespace Ryujinx.Ava.UI.Windows
private void SaveAndClose(object sender, RoutedEventArgs e) private void SaveAndClose(object sender, RoutedEventArgs e)
{ {
ViewModel.Save(); ViewModel.Save();
((ContentDialog)Parent).Hide(); ((ContentDialog)Parent)?.Hide();
} }
private void Close(object sender, RoutedEventArgs e) private void Close(object sender, RoutedEventArgs e)
{ {
((ContentDialog)Parent).Hide(); ((ContentDialog)Parent)?.Hide();
} }
private async void DeleteMod(object sender, RoutedEventArgs e) private async void DeleteMod(object sender, RoutedEventArgs e)

View file

@ -50,14 +50,14 @@ namespace Ryujinx.Ava.UI.Windows
private void Close(object sender, RoutedEventArgs e) private void Close(object sender, RoutedEventArgs e)
{ {
((ContentDialog)Parent).Hide(); ((ContentDialog)Parent)?.Hide();
} }
public void Save(object sender, RoutedEventArgs e) public void Save(object sender, RoutedEventArgs e)
{ {
ViewModel.Save(); ViewModel.Save();
((ContentDialog)Parent).Hide(); ((ContentDialog)Parent)?.Hide();
} }
private void OpenLocation(object sender, RoutedEventArgs e) private void OpenLocation(object sender, RoutedEventArgs e)

View file

@ -59,7 +59,7 @@ namespace Ryujinx.Ava.UI.Windows
private void Close(object sender, RoutedEventArgs e) private void Close(object sender, RoutedEventArgs e)
{ {
((ContentDialog)Parent).Hide(); ((ContentDialog)Parent)?.Hide();
} }
private void Cancel(Object sender, RoutedEventArgs e) private void Cancel(Object sender, RoutedEventArgs e)

View file

@ -162,7 +162,7 @@ namespace Spv.Generator
public bool Equals(Instruction cmpObj) public bool Equals(Instruction cmpObj)
{ {
bool result = Type == cmpObj.Type && Id == cmpObj.Id; bool result = cmpObj != null && Type == cmpObj.Type && Id == cmpObj.Id;
if (result) if (result)
{ {

View file

@ -87,7 +87,7 @@ namespace Spv.Generator
public bool Equals(LiteralInteger cmpObj) public bool Equals(LiteralInteger cmpObj)
{ {
return Type == cmpObj.Type && _integerType == cmpObj._integerType && _data == cmpObj._data; return cmpObj != null && Type == cmpObj.Type && _integerType == cmpObj._integerType && _data == cmpObj._data;
} }
public override int GetHashCode() public override int GetHashCode()

View file

@ -36,7 +36,7 @@ namespace Spv.Generator
public bool Equals(LiteralString cmpObj) public bool Equals(LiteralString cmpObj)
{ {
return Type == cmpObj.Type && _value.Equals(cmpObj._value); return cmpObj != null && Type == cmpObj.Type && _value.Equals(cmpObj._value);
} }
public override int GetHashCode() public override int GetHashCode()