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,14 +318,17 @@ 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
{
if (parent != null)
{ {
parent.Right = newNode; parent.Right = newNode;
} }
}
PropagateIncrease(newNode); PropagateIncrease(newNode);
Count++; Count++;

View file

@ -279,14 +279,17 @@ 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
{
if (parent != null)
{ {
parent.Right = newNode; 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,6 +258,8 @@ 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];
if (page != null)
{
ref TEntry* nextPage = ref page[level.GetValue(address)]; ref TEntry* nextPage = ref page[level.GetValue(address)];
if (nextPage == null || nextPage == _fillBottomLevelPtr) if (nextPage == null || nextPage == _fillBottomLevelPtr)
@ -276,6 +278,7 @@ namespace ARMeilleure.Common
page = (TEntry**)nextPage; page = (TEntry**)nextPage;
} }
}
return (TEntry*)page; return (TEntry*)page;
} }

View file

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

View file

@ -135,8 +135,11 @@ namespace Ryujinx.Cpu.Jit
offset += (int)copySize; offset += (int)copySize;
} }
if (last != null)
{
return new ReadOnlySequence<byte>(first, 0, last, (int)(size - last.RunningIndex)); return new ReadOnlySequence<byte>(first, 0, last, (int)(size - last.RunningIndex));
} }
}
catch (InvalidMemoryRegionException) catch (InvalidMemoryRegionException)
{ {
if (_invalidAccessHandler == null || !_invalidAccessHandler(va)) if (_invalidAccessHandler == null || !_invalidAccessHandler(va))
@ -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

@ -172,6 +172,8 @@ namespace Ryujinx.Graphics.Gpu.Image
/// Removes the least used texture from the cache. /// Removes the least used texture from the cache.
/// </summary> /// </summary>
private void RemoveLeastUsedTexture() private void RemoveLeastUsedTexture()
{
if (_textures.First != null)
{ {
Texture oldestTexture = _textures.First.Value; Texture oldestTexture = _textures.First.Value;
@ -192,6 +194,7 @@ namespace Ryujinx.Graphics.Gpu.Image
oldestTexture.DecrementReferenceCount(); oldestTexture.DecrementReferenceCount();
oldestTexture.CacheNode = null; oldestTexture.CacheNode = null;
} }
}
/// <summary> /// <summary>
/// Removes a texture from the cache. /// Removes a texture from the cache.

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

@ -990,10 +990,13 @@ namespace Ryujinx.Graphics.Gpu.Shader
dataWriter.Write(ref hasPipelineState); dataWriter.Write(ref hasPipelineState);
if (hasPipelineState) if (hasPipelineState)
{
if (PipelineState != null)
{ {
ProgramPipelineState pipelineState = PipelineState.Value; ProgramPipelineState pipelineState = PipelineState.Value;
dataWriter.WriteWithMagicAndSize(ref pipelineState, PgpsMagic); 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,7 +125,10 @@ 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;
@ -156,17 +159,19 @@ namespace Ryujinx.Graphics.OpenGL.Effects
// 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,
SizedInternalFormat.Rgba8);
textureView.Bind(0); textureView.Bind(0);
GL.Uniform1(_inputUniform, 0); GL.Uniform1(_inputUniform, 0);
GL.Uniform1(_outputUniform, 0); GL.Uniform1(_outputUniform, 0);
GL.Uniform1(_sharpeningUniform, 1.5f - (Level * 0.01f * 1.5f)); GL.Uniform1(_sharpeningUniform, 1.5f - (Level * 0.01f * 1.5f));
GL.DispatchCompute(dispatchX, dispatchY, 1); 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

@ -64,9 +64,12 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
INode lastOp = GetLastOp(); INode lastOp = GetLastOp();
if (lastOp is Operation operation && IsControlFlowInst(operation.Inst)) if (lastOp is Operation operation && IsControlFlowInst(operation.Inst))
{
if (Operations.Last != null)
{ {
Operations.AddBefore(Operations.Last, node); Operations.AddBefore(Operations.Last, node);
} }
}
else else
{ {
Operations.AddLast(node); Operations.AddLast(node);

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)
@ -444,9 +444,12 @@ namespace Ryujinx.Graphics.Shader.Translation
Operation copyOp = new(Instruction.Copy, OperandHelper.Argument(argIndex++), OperandHelper.Register(register)); Operation copyOp = new(Instruction.Copy, OperandHelper.Argument(argIndex++), OperandHelper.Register(register));
if (node == null) if (node == null)
{
if (block.Operations.Last != null)
{ {
node = block.Operations.AddBefore(block.Operations.Last, copyOp); node = block.Operations.AddBefore(block.Operations.Last, copyOp);
} }
}
else else
{ {
node = block.Operations.AddAfter(node, copyOp); node = block.Operations.AddAfter(node, copyOp);

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
} }
} }
if (bytes != null)
{
writer.Write(bytes); writer.Write(bytes);
writer.Seek((int)maxSize - bytes.Length, SeekOrigin.Current); 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

@ -61,8 +61,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
KernelContext.CriticalSection.Enter(); KernelContext.CriticalSection.Enter();
if (list.Count != 0) if (list.Count != 0)
{
if (list.First != null)
{ {
session = list.First.Value; session = list.First.Value;
}
list.RemoveFirst(); list.RemoveFirst();
} }

View file

@ -1369,6 +1369,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
LinkedListNode<KPageNode> pageListNode = pageList.Nodes.First; LinkedListNode<KPageNode> pageListNode = pageList.Nodes.First;
if (pageListNode != null)
{
KPageNode pageNode = pageListNode.Value; KPageNode pageNode = pageListNode.Value;
ulong srcPa = pageNode.Address; ulong srcPa = pageNode.Address;
@ -1391,9 +1393,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
{ {
if (srcPaPages == 0) if (srcPaPages == 0)
{ {
pageListNode = pageListNode.Next; pageListNode = pageListNode?.Next;
if (pageListNode != null)
{
pageNode = pageListNode.Value; pageNode = pageListNode.Value;
}
srcPa = pageNode.Address; srcPa = pageNode.Address;
srcPaPages = pageNode.PagesCount; srcPaPages = pageNode.PagesCount;
@ -1409,6 +1414,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
dstVaPages -= currentPagesCount; dstVaPages -= currentPagesCount;
} }
} }
}
PhysicalMemoryUsage += remainingSize; PhysicalMemoryUsage += remainingSize;

View file

@ -33,10 +33,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
public ref T GetRef<T>(ulong offset) where T : unmanaged public ref T GetRef<T>(ulong offset) where T : unmanaged
{ {
if (_pageList.Nodes.Count == 1) if (_pageList.Nodes.Count == 1)
{
if (_pageList.Nodes.First != null)
{ {
ulong address = _pageList.Nodes.First.Value.Address - DramMemoryMap.DramBase; ulong address = _pageList.Nodes.First.Value.Address - DramMemoryMap.DramBase;
return ref _context.Memory.GetRef<T>(address + offset); 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,6 +61,8 @@ namespace Ryujinx.Horizon.Generators.Hipc
{ {
HipcSyntaxReceiver syntaxReceiver = (HipcSyntaxReceiver)context.SyntaxReceiver; HipcSyntaxReceiver syntaxReceiver = (HipcSyntaxReceiver)context.SyntaxReceiver;
if (syntaxReceiver?.CommandInterfaces != null)
{
foreach (var commandInterface in syntaxReceiver.CommandInterfaces) foreach (var commandInterface in syntaxReceiver.CommandInterfaces)
{ {
if (!NeedsIServiceObjectImplementation(context.Compilation, commandInterface.ClassDeclarationSyntax)) if (!NeedsIServiceObjectImplementation(context.Compilation, commandInterface.ClassDeclarationSyntax))
@ -99,6 +101,7 @@ namespace Ryujinx.Horizon.Generators.Hipc
context.AddSource($"{GetNamespaceName(commandInterface.ClassDeclarationSyntax)}.{className}.g.cs", generator.ToString()); context.AddSource($"{GetNamespaceName(commandInterface.ClassDeclarationSyntax)}.{className}.g.cs", generator.ToString());
} }
} }
}
private static string GetNamespaceName(SyntaxNode syntaxNode) private static string GetNamespaceName(SyntaxNode syntaxNode)
{ {
@ -191,14 +194,18 @@ namespace Ryujinx.Horizon.Generators.Hipc
{ {
ISymbol symbol = compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetDeclaredSymbol(syntaxNode); ISymbol symbol = compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetDeclaredSymbol(syntaxNode);
if (symbol != null)
{
foreach (var attribute in symbol.GetAttributes()) foreach (var attribute in symbol.GetAttributes())
{ {
if (attribute.AttributeClass.ToDisplayString() == attributeName && (uint)argIndex < (uint)attribute.ConstructorArguments.Length) if (attribute.AttributeClass?.ToDisplayString() == attributeName &&
(uint)argIndex < (uint)attribute.ConstructorArguments.Length)
{ {
yield return attribute.ConstructorArguments[argIndex].ToCSharpString(); yield return attribute.ConstructorArguments[argIndex].ToCSharpString();
} }
} }
} }
}
private static string GetFirstAttributeArgument(Compilation compilation, SyntaxNode syntaxNode, string attributeName, int argIndex) private static string GetFirstAttributeArgument(Compilation compilation, SyntaxNode syntaxNode, string attributeName, int argIndex)
{ {
@ -507,19 +514,22 @@ 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();
if (typeName != null)
{
int genericArgsStartIndex = typeName.IndexOf('<'); int genericArgsStartIndex = typeName.IndexOf('<');
if (genericArgsStartIndex >= 0) if (genericArgsStartIndex >= 0)
{ {
return typeName.Substring(0, genericArgsStartIndex); 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;
if (symbol != null)
{
foreach (var attribute in symbol.GetAttributes()) foreach (var attribute in symbol.GetAttributes())
{ {
if (attribute.AttributeClass.ToDisplayString() == attributeName) if (attribute.AttributeClass?.ToDisplayString() == attributeName)
{ {
foreach (var kv in attribute.NamedArguments) foreach (var kv in attribute.NamedArguments.Where(kv => kv.Key == argName))
{
if (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,6 +147,8 @@ namespace Ryujinx.Horizon.Kernel.Generators
List<SyscallIdAndName> syscalls = []; List<SyscallIdAndName> syscalls = [];
if (syntaxReceiver != null)
{
foreach (var method in syntaxReceiver.SvcImplementations) foreach (var method in syntaxReceiver.SvcImplementations)
{ {
GenerateMethod32(generator, context.Compilation, method); GenerateMethod32(generator, context.Compilation, method);
@ -155,6 +157,8 @@ namespace Ryujinx.Horizon.Kernel.Generators
foreach (AttributeSyntax attribute in method.AttributeLists.SelectMany(attributeList => foreach (AttributeSyntax attribute in method.AttributeLists.SelectMany(attributeList =>
attributeList.Attributes.Where(attribute => attributeList.Attributes.Where(attribute =>
GetCanonicalTypeName(context.Compilation, attribute) == TypeSvcAttribute))) GetCanonicalTypeName(context.Compilation, attribute) == TypeSvcAttribute)))
{
if (attribute.ArgumentList != null)
{ {
syscalls.AddRange(from attributeArg in attribute.ArgumentList.Arguments syscalls.AddRange(from attributeArg in attribute.ArgumentList.Arguments
where attributeArg.Expression.Kind() == SyntaxKind.NumericLiteralExpression where attributeArg.Expression.Kind() == SyntaxKind.NumericLiteralExpression
@ -163,6 +167,8 @@ namespace Ryujinx.Horizon.Kernel.Generators
select new SyscallIdAndName((int)numericLiteral.Token.Value, method.Identifier.Text)); select new SyscallIdAndName((int)numericLiteral.Token.Value, method.Identifier.Text));
} }
} }
}
}
syscalls.Sort(); syscalls.Sort();

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,10 +304,13 @@ namespace Ryujinx.Input.HLE
buttons |= 1 << 4; buttons |= 1 << 4;
} }
if (mouse != null)
{
var position = IMouse.GetScreenPosition(mouseInput.Position, mouse.ClientSize, aspectRatio); 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
{ {
_device.Hid.Mouse.Update(0, 0); _device.Hid.Mouse.Update(0, 0);

View file

@ -88,6 +88,8 @@ 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);
if (resourceStream != null)
{
byte[] resourceByteArray = new byte[resourceStream.Length]; byte[] resourceByteArray = new byte[resourceStream.Length];
resourceStream.ReadExactly(resourceByteArray); resourceStream.ReadExactly(resourceByteArray);
@ -95,6 +97,9 @@ namespace Ryujinx.UI.App.Common
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>
/// <exception cref="NotImplementedException">The FsAccessHeader.ContentOwnerId section is not implemented.</exception> /// <exception cref="NotImplementedException">The FsAccessHeader.ContentOwnerId section is not implemented.</exception>
/// <exception cref="ArgumentException">An error occured while reading bytes from the stream.</exception> /// <exception cref="ArgumentException">An error occured while reading bytes from the stream.</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,8 +192,11 @@ namespace Ryujinx.Modules
HttpResponseMessage message = await buildSizeClient.GetAsync(new Uri(_buildUrl), HttpCompletionOption.ResponseHeadersRead); HttpResponseMessage message = await buildSizeClient.GetAsync(new Uri(_buildUrl), HttpCompletionOption.ResponseHeadersRead);
if (message.Content.Headers.ContentRange?.Length != null)
{
_buildSize = message.Content.Headers.ContentRange.Length.Value; _buildSize = message.Content.Headers.ContentRange.Length.Value;
} }
}
catch (Exception ex) catch (Exception ex)
{ {
Logger.Warning?.Print(LogClass.Application, ex.Message); Logger.Warning?.Print(LogClass.Application, ex.Message);
@ -375,17 +378,23 @@ namespace Ryujinx.Modules
} }
client.DownloadProgressChanged += (_, args) => client.DownloadProgressChanged += (_, args) =>
{
if (args.UserState != null)
{ {
int index = (int)args.UserState; int index = (int)args.UserState;
Interlocked.Add(ref totalProgressPercentage, -1 * progressPercentage[index]); Interlocked.Add(ref totalProgressPercentage, -1 * progressPercentage[index]);
Interlocked.Exchange(ref progressPercentage[index], args.ProgressPercentage); 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);
}; };
client.DownloadDataCompleted += (_, args) => client.DownloadDataCompleted += (_, args) =>
{
if (args.UserState != null)
{ {
int index = (int)args.UserState; int index = (int)args.UserState;
@ -399,6 +408,8 @@ namespace Ryujinx.Modules
} }
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,6 +476,8 @@ 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);
if (response.Content.Headers.ContentLength != null)
{
long totalBytes = response.Content.Headers.ContentLength.Value; long totalBytes = response.Content.Headers.ContentLength.Value;
long byteWritten = 0; long byteWritten = 0;
@ -485,6 +498,7 @@ namespace Ryujinx.Modules
updateFileStream.Write(buffer, 0, readSize); 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,11 +396,14 @@ 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");
if (iconFile != null)
{
await using var fileStream = await iconFile.OpenWriteAsync(); await using var fileStream = await iconFile.OpenWriteAsync();
fileStream.Write(selectedApp.Icon); fileStream.Write(selectedApp.Icon);
} }
} }
}
public void CreateApplicationShortcut_Click(object sender, RoutedEventArgs args) public void CreateApplicationShortcut_Click(object sender, RoutedEventArgs args)
{ {

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;
} }
if (X11Window != null)
{
WindowHandle = X11Window.WindowHandle.RawHandle; WindowHandle = X11Window.WindowHandle.RawHandle;
X11Display = X11Window.DisplayHandle.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);
if (_mainWindow != null)
{
_mainWindow.InputManager.GamepadDriver.OnGamepadConnected += HandleOnGamepadConnected; _mainWindow.InputManager.GamepadDriver.OnGamepadConnected += HandleOnGamepadConnected;
_mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected; _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();
} }
if (config != null)
{
config.ControllerType = Controllers[_controller].Type; 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:
if (x != null && y != null)
{
result = x.PotentialSavingsB.CompareTo(y.PotentialSavingsB); result = x.PotentialSavingsB.CompareTo(y.PotentialSavingsB);
}
break; break;
} }

View file

@ -70,7 +70,11 @@ namespace Ryujinx.Ava.UI.Views.Input
{ {
var viewModel = (DataContext as ControllerInputViewModel); var viewModel = (DataContext as ControllerInputViewModel);
if (viewModel != null)
{
viewModel.ParentModel.IsModified = true; viewModel.ParentModel.IsModified = true;
}
_changeSlider = (float)check.Value; _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)
var viewModel = (DataContext as ControllerInputViewModel); {
viewModel.ParentModel.IsModified = true; 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,10 +72,13 @@ namespace Ryujinx.Ava.UI.Views.Input
{ {
ViewModel.IsModified = true; ViewModel.IsModified = true;
var player = (PlayerModel)e.AddedItems[0]; var player = (PlayerModel)e.AddedItems[0];
if (player != null)
{
ViewModel.PlayerId = player.Id; 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,6 +60,8 @@ namespace Ryujinx.Ava.UI.Views.Input
var viewModel = (DataContext as KeyboardInputViewModel); var viewModel = (DataContext as KeyboardInputViewModel);
if (viewModel != null)
{
IKeyboard keyboard = (IKeyboard)viewModel.ParentModel.AvaloniaKeyboardDriver.GetGamepad("0"); // Open Avalonia keyboard for cancel operations. IKeyboard keyboard = (IKeyboard)viewModel.ParentModel.AvaloniaKeyboardDriver.GetGamepad("0"); // Open Avalonia keyboard for cancel operations.
IButtonAssigner assigner = CreateButtonAssigner(); IButtonAssigner assigner = CreateButtonAssigner();
@ -162,6 +164,7 @@ namespace Ryujinx.Ava.UI.Views.Input
_currentAssigner.GetInputAndAssign(assigner, keyboard); _currentAssigner.GetInputAndAssign(assigner, keyboard);
} }
}
else else
{ {
if (_currentAssigner != null) if (_currentAssigner != null)
@ -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,6 +69,8 @@ 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;
if (viewModel != null)
{
switch (button.Name) switch (button.Name)
{ {
case "ToggleVSyncMode": case "ToggleVSyncMode":
@ -106,6 +108,7 @@ namespace Ryujinx.Ava.UI.Views.Settings
break; break;
} }
} }
}
}; };
_currentAssigner.GetInputAndAssign(assigner, keyboard); _currentAssigner.GetInputAndAssign(assigner, keyboard);

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>
if (PlatformSettings != null)
{
PlatformSettings.ColorValuesChanged += OnPlatformColorValuesChanged; 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()