diff --git a/Directory.Packages.props b/Directory.Packages.props
index e45ffccae..3fa3bfe2c 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -17,12 +17,11 @@
-
-
+
@@ -33,7 +32,7 @@
-
+
@@ -51,4 +50,4 @@
-
\ No newline at end of file
+
diff --git a/src/Ryujinx.Ava/Ryujinx.Ava.csproj b/src/Ryujinx.Ava/Ryujinx.Ava.csproj
index b6d37a2f1..7f5224cfb 100644
--- a/src/Ryujinx.Ava/Ryujinx.Ava.csproj
+++ b/src/Ryujinx.Ava/Ryujinx.Ava.csproj
@@ -43,7 +43,6 @@
-
diff --git a/src/Ryujinx.Ava/UI/Controls/ApplicationGridView.axaml b/src/Ryujinx.Ava/UI/Controls/ApplicationGridView.axaml
index bbdb4c4a7..2dc95662a 100644
--- a/src/Ryujinx.Ava/UI/Controls/ApplicationGridView.axaml
+++ b/src/Ryujinx.Ava/UI/Controls/ApplicationGridView.axaml
@@ -4,7 +4,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:flex="clr-namespace:Avalonia.Flexbox;assembly=Avalonia.Flexbox"
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
@@ -33,11 +32,10 @@
SelectionChanged="GameList_SelectionChanged">
-
+ VerticalAlignment="Top"
+ Orientation="Horizontal" />
diff --git a/src/Ryujinx.Ava/UI/Views/User/UserSelectorView.axaml b/src/Ryujinx.Ava/UI/Views/User/UserSelectorView.axaml
index 818a21d69..3a9de3039 100644
--- a/src/Ryujinx.Ava/UI/Views/User/UserSelectorView.axaml
+++ b/src/Ryujinx.Ava/UI/Views/User/UserSelectorView.axaml
@@ -4,7 +4,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:flex="clr-namespace:Avalonia.Flexbox;assembly=Avalonia.Flexbox"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
xmlns:models="clr-namespace:Ryujinx.Ava.UI.Models"
@@ -40,11 +39,10 @@
ItemsSource="{Binding Profiles}">
-
+
@@ -161,4 +159,4 @@
Content="{locale:Locale UserProfilesClose}" />
-
\ No newline at end of file
+
diff --git a/src/Ryujinx.Ava/UI/Windows/AboutWindow.axaml b/src/Ryujinx.Ava/UI/Windows/AboutWindow.axaml
index a0fd2a1ac..ace1094e4 100644
--- a/src/Ryujinx.Ava/UI/Windows/AboutWindow.axaml
+++ b/src/Ryujinx.Ava/UI/Windows/AboutWindow.axaml
@@ -3,7 +3,6 @@
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:flex="clr-namespace:Avalonia.Flexbox;assembly=Avalonia.Flexbox"
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
@@ -49,13 +48,11 @@
Grid.Column="0"
Height="80"
Source="resm:Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png?assembly=Ryujinx.Ui.Common" />
-
+ HorizontalAlignment="Right"
+ VerticalAlignment="Center"
+ Orientation="Vertical">
-
+
Instructions;
public readonly bool EndsWithBranch;
public readonly bool HasHostCall;
+ public readonly bool HasHostCallSkipContext;
public readonly bool IsTruncated;
public readonly bool IsLoopEnd;
public readonly bool IsThumb;
@@ -20,6 +21,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
List instructions,
bool endsWithBranch,
bool hasHostCall,
+ bool hasHostCallSkipContext,
bool isTruncated,
bool isLoopEnd,
bool isThumb)
@@ -31,6 +33,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
Instructions = instructions;
EndsWithBranch = endsWithBranch;
HasHostCall = hasHostCall;
+ HasHostCallSkipContext = hasHostCallSkipContext;
IsTruncated = isTruncated;
IsLoopEnd = isLoopEnd;
IsThumb = isThumb;
@@ -57,6 +60,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
Instructions.GetRange(0, splitIndex),
false,
HasHostCall,
+ HasHostCallSkipContext,
false,
false,
IsThumb);
@@ -67,6 +71,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
Instructions.GetRange(splitIndex, splitCount),
EndsWithBranch,
HasHostCall,
+ HasHostCallSkipContext,
IsTruncated,
IsLoopEnd,
IsThumb);
diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Decoder.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Decoder.cs
index e0a18e666..8a2b389ad 100644
--- a/src/Ryujinx.Cpu/LightningJit/Arm32/Decoder.cs
+++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Decoder.cs
@@ -208,6 +208,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
InstMeta meta;
InstFlags extraFlags = InstFlags.None;
bool hasHostCall = false;
+ bool hasHostCallSkipContext = false;
bool isTruncated = false;
do
@@ -246,9 +247,17 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
meta = InstTableA32.GetMeta(encoding, cpuPreset.Version, cpuPreset.Features);
}
- if (meta.Name.IsSystemOrCall() && !hasHostCall)
+ if (meta.Name.IsSystemOrCall())
{
- hasHostCall = meta.Name.IsCall() || InstEmitSystem.NeedsCall(meta.Name);
+ if (!hasHostCall)
+ {
+ hasHostCall = InstEmitSystem.NeedsCall(meta.Name);
+ }
+
+ if (!hasHostCallSkipContext)
+ {
+ hasHostCallSkipContext = meta.Name.IsCall() || InstEmitSystem.NeedsCallSkipContext(meta.Name);
+ }
}
insts.Add(new(encoding, meta.Name, meta.EmitFunc, meta.Flags | extraFlags));
@@ -259,8 +268,8 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
if (!isTruncated && IsBackwardsBranch(meta.Name, encoding))
{
- hasHostCall = true;
isLoopEnd = true;
+ hasHostCallSkipContext = true;
}
return new(
@@ -269,6 +278,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
insts,
!isTruncated,
hasHostCall,
+ hasHostCallSkipContext,
isTruncated,
isLoopEnd,
isThumb);
diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/MultiBlock.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/MultiBlock.cs
index a213c222c..ca25057fe 100644
--- a/src/Ryujinx.Cpu/LightningJit/Arm32/MultiBlock.cs
+++ b/src/Ryujinx.Cpu/LightningJit/Arm32/MultiBlock.cs
@@ -6,6 +6,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
{
public readonly List Blocks;
public readonly bool HasHostCall;
+ public readonly bool HasHostCallSkipContext;
public readonly bool IsTruncated;
public MultiBlock(List blocks)
@@ -15,12 +16,14 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
Block block = blocks[0];
HasHostCall = block.HasHostCall;
+ HasHostCallSkipContext = block.HasHostCallSkipContext;
for (int index = 1; index < blocks.Count; index++)
{
block = blocks[index];
HasHostCall |= block.HasHostCall;
+ HasHostCallSkipContext |= block.HasHostCallSkipContext;
}
block = blocks[^1];
diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/RegisterAllocator.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/RegisterAllocator.cs
index 6c7057229..4a3f03b8a 100644
--- a/src/Ryujinx.Cpu/LightningJit/Arm32/RegisterAllocator.cs
+++ b/src/Ryujinx.Cpu/LightningJit/Arm32/RegisterAllocator.cs
@@ -106,6 +106,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
if ((regMask & AbiConstants.ReservedRegsMask) == 0)
{
_gprMask |= regMask;
+ UsedGprsMask |= regMask;
return firstCalleeSaved;
}
diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/Compiler.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/Compiler.cs
index 1e8a89157..a668b5777 100644
--- a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/Compiler.cs
+++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/Compiler.cs
@@ -305,12 +305,23 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
ForceConditionalEnd(cgContext, ref lastCondition, lastConditionIp);
}
+ int reservedStackSize = 0;
+
+ if (multiBlock.HasHostCall)
+ {
+ reservedStackSize = CalculateStackSizeForCallSpill(regAlloc.UsedGprsMask, regAlloc.UsedFpSimdMask, UsablePStateMask);
+ }
+ else if (multiBlock.HasHostCallSkipContext)
+ {
+ reservedStackSize = 2 * sizeof(ulong); // Context and page table pointers.
+ }
+
RegisterSaveRestore rsr = new(
regAlloc.UsedGprsMask & AbiConstants.GprCalleeSavedRegsMask,
regAlloc.UsedFpSimdMask & AbiConstants.FpSimdCalleeSavedRegsMask,
OperandType.FP64,
- multiBlock.HasHostCall,
- multiBlock.HasHostCall ? CalculateStackSizeForCallSpill(regAlloc.UsedGprsMask, regAlloc.UsedFpSimdMask, UsablePStateMask) : 0);
+ multiBlock.HasHostCall || multiBlock.HasHostCallSkipContext,
+ reservedStackSize);
TailMerger tailMerger = new();
@@ -596,7 +607,8 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
name == InstName.Ldm ||
name == InstName.Ldmda ||
name == InstName.Ldmdb ||
- name == InstName.Ldmib)
+ name == InstName.Ldmib ||
+ name == InstName.Pop)
{
// Arm32 does not have a return instruction, instead returns are implemented
// either using BX LR (for leaf functions), or POP { ... PC }.
@@ -711,7 +723,14 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
switch (type)
{
case BranchType.SyncPoint:
- InstEmitSystem.WriteSyncPoint(context.Writer, context.RegisterAllocator, context.TailMerger, context.GetReservedStackOffset());
+ InstEmitSystem.WriteSyncPoint(
+ context.Writer,
+ ref asm,
+ context.RegisterAllocator,
+ context.TailMerger,
+ context.GetReservedStackOffset(),
+ context.StoreToContext,
+ context.LoadFromContext);
break;
case BranchType.SoftwareInterrupt:
context.StoreToContext();
diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitFlow.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitFlow.cs
index 81e44ba00..3b1ff5a2a 100644
--- a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitFlow.cs
+++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitFlow.cs
@@ -199,12 +199,12 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
}
}
- private static void WriteSpillSkipContext(ref Assembler asm, RegisterAllocator regAlloc, int spillOffset)
+ public static void WriteSpillSkipContext(ref Assembler asm, RegisterAllocator regAlloc, int spillOffset)
{
WriteSpillOrFillSkipContext(ref asm, regAlloc, spillOffset, spill: true);
}
- private static void WriteFillSkipContext(ref Assembler asm, RegisterAllocator regAlloc, int spillOffset)
+ public static void WriteFillSkipContext(ref Assembler asm, RegisterAllocator regAlloc, int spillOffset)
{
WriteSpillOrFillSkipContext(ref asm, regAlloc, spillOffset, spill: false);
}
diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitSystem.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitSystem.cs
index be0976fd3..07f9f86a8 100644
--- a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitSystem.cs
+++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitSystem.cs
@@ -354,11 +354,18 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
// All instructions that might do a host call should be included here.
// That is required to reserve space on the stack for caller saved registers.
+ return name == InstName.Mrrc;
+ }
+
+ public static bool NeedsCallSkipContext(InstName name)
+ {
+ // All instructions that might do a host call should be included here.
+ // That is required to reserve space on the stack for caller saved registers.
+
switch (name)
{
case InstName.Mcr:
case InstName.Mrc:
- case InstName.Mrrc:
case InstName.Svc:
case InstName.Udf:
return true;
@@ -372,7 +379,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
Assembler asm = new(writer);
WriteCall(ref asm, regAlloc, GetBkptHandlerPtr(), skipContext: true, spillBaseOffset, null, pc, imm);
- WriteSyncPoint(writer, ref asm, regAlloc, tailMerger, skipContext: true, spillBaseOffset);
+ WriteSyncPoint(writer, ref asm, regAlloc, tailMerger, spillBaseOffset);
}
public static void WriteSvc(CodeWriter writer, RegisterAllocator regAlloc, TailMerger tailMerger, int spillBaseOffset, uint pc, uint svcId)
@@ -380,7 +387,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
Assembler asm = new(writer);
WriteCall(ref asm, regAlloc, GetSvcHandlerPtr(), skipContext: true, spillBaseOffset, null, pc, svcId);
- WriteSyncPoint(writer, ref asm, regAlloc, tailMerger, skipContext: true, spillBaseOffset);
+ WriteSyncPoint(writer, ref asm, regAlloc, tailMerger, spillBaseOffset);
}
public static void WriteUdf(CodeWriter writer, RegisterAllocator regAlloc, TailMerger tailMerger, int spillBaseOffset, uint pc, uint imm)
@@ -388,7 +395,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
Assembler asm = new(writer);
WriteCall(ref asm, regAlloc, GetUdfHandlerPtr(), skipContext: true, spillBaseOffset, null, pc, imm);
- WriteSyncPoint(writer, ref asm, regAlloc, tailMerger, skipContext: true, spillBaseOffset);
+ WriteSyncPoint(writer, ref asm, regAlloc, tailMerger, spillBaseOffset);
}
public static void WriteReadCntpct(CodeWriter writer, RegisterAllocator regAlloc, int spillBaseOffset, int rt, int rt2)
@@ -422,14 +429,14 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
WriteFill(ref asm, regAlloc, resultMask, skipContext: false, spillBaseOffset, tempRegister);
}
- public static void WriteSyncPoint(CodeWriter writer, RegisterAllocator regAlloc, TailMerger tailMerger, int spillBaseOffset)
- {
- Assembler asm = new(writer);
-
- WriteSyncPoint(writer, ref asm, regAlloc, tailMerger, skipContext: false, spillBaseOffset);
- }
-
- private static void WriteSyncPoint(CodeWriter writer, ref Assembler asm, RegisterAllocator regAlloc, TailMerger tailMerger, bool skipContext, int spillBaseOffset)
+ public static void WriteSyncPoint(
+ CodeWriter writer,
+ ref Assembler asm,
+ RegisterAllocator regAlloc,
+ TailMerger tailMerger,
+ int spillBaseOffset,
+ Action storeToContext = null,
+ Action loadFromContext = null)
{
int tempRegister = regAlloc.AllocateTempGprRegister();
@@ -440,7 +447,8 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
int branchIndex = writer.InstructionPointer;
asm.Cbnz(rt, 0);
- WriteSpill(ref asm, regAlloc, 1u << tempRegister, skipContext, spillBaseOffset, tempRegister);
+ storeToContext?.Invoke();
+ WriteSpill(ref asm, regAlloc, 1u << tempRegister, skipContext: true, spillBaseOffset, tempRegister);
Operand rn = Register(tempRegister == 0 ? 1 : 0);
@@ -449,7 +457,8 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
tailMerger.AddConditionalZeroReturn(writer, asm, Register(0, OperandType.I32));
- WriteFill(ref asm, regAlloc, 1u << tempRegister, skipContext, spillBaseOffset, tempRegister);
+ WriteFill(ref asm, regAlloc, 1u << tempRegister, skipContext: true, spillBaseOffset, tempRegister);
+ loadFromContext?.Invoke();
asm.LdrRiUn(rt, Register(regAlloc.FixedContextRegister), NativeContextOffsets.CounterOffset);
@@ -514,18 +523,31 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
private static void WriteSpill(ref Assembler asm, RegisterAllocator regAlloc, uint exceptMask, bool skipContext, int spillOffset, int tempRegister)
{
- WriteSpillOrFill(ref asm, regAlloc, skipContext, exceptMask, spillOffset, tempRegister, spill: true);
+ if (skipContext)
+ {
+ InstEmitFlow.WriteSpillSkipContext(ref asm, regAlloc, spillOffset);
+ }
+ else
+ {
+ WriteSpillOrFill(ref asm, regAlloc, exceptMask, spillOffset, tempRegister, spill: true);
+ }
}
private static void WriteFill(ref Assembler asm, RegisterAllocator regAlloc, uint exceptMask, bool skipContext, int spillOffset, int tempRegister)
{
- WriteSpillOrFill(ref asm, regAlloc, skipContext, exceptMask, spillOffset, tempRegister, spill: false);
+ if (skipContext)
+ {
+ InstEmitFlow.WriteFillSkipContext(ref asm, regAlloc, spillOffset);
+ }
+ else
+ {
+ WriteSpillOrFill(ref asm, regAlloc, exceptMask, spillOffset, tempRegister, spill: false);
+ }
}
private static void WriteSpillOrFill(
ref Assembler asm,
RegisterAllocator regAlloc,
- bool skipContext,
uint exceptMask,
int spillOffset,
int tempRegister,
@@ -533,11 +555,6 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
{
uint gprMask = regAlloc.UsedGprsMask & ~(AbiConstants.GprCalleeSavedRegsMask | exceptMask);
- if (skipContext)
- {
- gprMask &= ~Compiler.UsableGprsMask;
- }
-
if (!spill)
{
// We must reload the status register before reloading the GPRs,
@@ -600,11 +617,6 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
uint fpSimdMask = regAlloc.UsedFpSimdMask;
- if (skipContext)
- {
- fpSimdMask &= ~Compiler.UsableFpSimdMask;
- }
-
while (fpSimdMask != 0)
{
int reg = BitOperations.TrailingZeroCount(fpSimdMask);
diff --git a/src/Ryujinx.Graphics.GAL/Format.cs b/src/Ryujinx.Graphics.GAL/Format.cs
index 99c89dcec..035543560 100644
--- a/src/Ryujinx.Graphics.GAL/Format.cs
+++ b/src/Ryujinx.Graphics.GAL/Format.cs
@@ -147,6 +147,7 @@ namespace Ryujinx.Graphics.GAL
A1B5G5R5Unorm,
B8G8R8A8Unorm,
B8G8R8A8Srgb,
+ B10G10R10A2Unorm,
}
public static class FormatExtensions
@@ -260,6 +261,7 @@ namespace Ryujinx.Graphics.GAL
case Format.R10G10B10A2Sint:
case Format.R10G10B10A2Uscaled:
case Format.R10G10B10A2Sscaled:
+ case Format.B10G10R10A2Unorm:
return 4;
case Format.S8Uint:
@@ -451,6 +453,7 @@ namespace Ryujinx.Graphics.GAL
case Format.R32G32Uint:
case Format.B8G8R8A8Unorm:
case Format.B8G8R8A8Srgb:
+ case Format.B10G10R10A2Unorm:
case Format.R10G10B10A2Unorm:
case Format.R10G10B10A2Uint:
case Format.R8G8B8A8Unorm:
@@ -611,6 +614,7 @@ namespace Ryujinx.Graphics.GAL
case Format.B5G5R5A1Unorm:
case Format.B8G8R8A8Unorm:
case Format.B8G8R8A8Srgb:
+ case Format.B10G10R10A2Unorm:
return true;
}
diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs
index 2b65b4560..6b4ea89f3 100644
--- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs
+++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs
@@ -26,6 +26,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
public const int PrimitiveRestartStateIndex = 12;
public const int RenderTargetStateIndex = 27;
+ // Vertex buffers larger than this size will be clamped to the mapped size.
+ private const ulong VertexBufferSizeToMappedSizeThreshold = 256 * 1024 * 1024; // 256 MB
+
private readonly GpuContext _context;
private readonly GpuChannel _channel;
private readonly DeviceStateWithShadow _state;
@@ -1144,6 +1147,14 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
size = Math.Min(size, maxVertexBufferSize);
}
+ else if (size > VertexBufferSizeToMappedSizeThreshold)
+ {
+ // Make sure we have a sane vertex buffer size, since in some cases applications
+ // might set the "end address" of the vertex buffer to the end of the GPU address space,
+ // which would result in a several GBs large buffer.
+
+ size = _channel.MemoryManager.GetMappedSize(address, size);
+ }
}
else
{
diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Types/ColorFormat.cs b/src/Ryujinx.Graphics.Gpu/Engine/Types/ColorFormat.cs
index c798384f0..273438a67 100644
--- a/src/Ryujinx.Graphics.Gpu/Engine/Types/ColorFormat.cs
+++ b/src/Ryujinx.Graphics.Gpu/Engine/Types/ColorFormat.cs
@@ -37,6 +37,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Types
R16G16Sint = 0xdc,
R16G16Uint = 0xdd,
R16G16Float = 0xde,
+ B10G10R10A2Unorm = 0xdf,
R11G11B10Float = 0xe0,
R32Sint = 0xe3,
R32Uint = 0xe4,
@@ -104,6 +105,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Types
ColorFormat.R16G16Sint => new FormatInfo(Format.R16G16Sint, 1, 1, 4, 2),
ColorFormat.R16G16Uint => new FormatInfo(Format.R16G16Uint, 1, 1, 4, 2),
ColorFormat.R16G16Float => new FormatInfo(Format.R16G16Float, 1, 1, 4, 2),
+ ColorFormat.B10G10R10A2Unorm => new FormatInfo(Format.B10G10R10A2Unorm, 1, 1, 4, 4),
ColorFormat.R11G11B10Float => new FormatInfo(Format.R11G11B10Float, 1, 1, 4, 3),
ColorFormat.R32Sint => new FormatInfo(Format.R32Sint, 1, 1, 4, 1),
ColorFormat.R32Uint => new FormatInfo(Format.R32Uint, 1, 1, 4, 1),
diff --git a/src/Ryujinx.Graphics.OpenGL/FormatTable.cs b/src/Ryujinx.Graphics.OpenGL/FormatTable.cs
index 3dac33b94..c7e3e4e28 100644
--- a/src/Ryujinx.Graphics.OpenGL/FormatTable.cs
+++ b/src/Ryujinx.Graphics.OpenGL/FormatTable.cs
@@ -161,6 +161,7 @@ namespace Ryujinx.Graphics.OpenGL
Add(Format.A1B5G5R5Unorm, new FormatInfo(4, true, false, All.Rgb5A1, PixelFormat.Rgba, PixelType.UnsignedShort5551));
Add(Format.B8G8R8A8Unorm, new FormatInfo(4, true, false, All.Rgba8, PixelFormat.Rgba, PixelType.UnsignedByte));
Add(Format.B8G8R8A8Srgb, new FormatInfo(4, false, false, All.Srgb8Alpha8, PixelFormat.Rgba, PixelType.UnsignedByte));
+ Add(Format.B10G10R10A2Unorm, new FormatInfo(4, false, false, All.Rgb10A2, PixelFormat.Rgba, PixelType.UnsignedInt2101010Reversed));
Add(Format.R8Unorm, SizedInternalFormat.R8);
Add(Format.R8Uint, SizedInternalFormat.R8ui);
diff --git a/src/Ryujinx.Graphics.Vic/Ryujinx.Graphics.Vic.csproj b/src/Ryujinx.Graphics.Vic/Ryujinx.Graphics.Vic.csproj
index b3f39f2ef..a6c4fb2bb 100644
--- a/src/Ryujinx.Graphics.Vic/Ryujinx.Graphics.Vic.csproj
+++ b/src/Ryujinx.Graphics.Vic/Ryujinx.Graphics.Vic.csproj
@@ -8,7 +8,6 @@
-
diff --git a/src/Ryujinx.Graphics.Vulkan/FormatTable.cs b/src/Ryujinx.Graphics.Vulkan/FormatTable.cs
index a12e3efd0..596a665fc 100644
--- a/src/Ryujinx.Graphics.Vulkan/FormatTable.cs
+++ b/src/Ryujinx.Graphics.Vulkan/FormatTable.cs
@@ -161,6 +161,7 @@ namespace Ryujinx.Graphics.Vulkan
Add(Format.A1B5G5R5Unorm, VkFormat.R5G5B5A1UnormPack16);
Add(Format.B8G8R8A8Unorm, VkFormat.B8G8R8A8Unorm);
Add(Format.B8G8R8A8Srgb, VkFormat.B8G8R8A8Srgb);
+ Add(Format.B10G10R10A2Unorm, VkFormat.A2R10G10B10UnormPack32);
#pragma warning restore IDE0055
}
diff --git a/src/Ryujinx.Ui.Common/Helper/ShortcutHelper.cs b/src/Ryujinx.Ui.Common/Helper/ShortcutHelper.cs
index 60b928985..3d27d3ffb 100644
--- a/src/Ryujinx.Ui.Common/Helper/ShortcutHelper.cs
+++ b/src/Ryujinx.Ui.Common/Helper/ShortcutHelper.cs
@@ -2,15 +2,13 @@ using Ryujinx.Common;
using Ryujinx.Common.Configuration;
using ShellLink;
using SixLabors.ImageSharp;
+using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.PixelFormats;
+using SixLabors.ImageSharp.Processing;
using System;
using System.Collections.Generic;
-using System.Drawing;
-using System.Drawing.Drawing2D;
-using System.Drawing.Imaging;
using System.IO;
using System.Runtime.Versioning;
-using Image = System.Drawing.Image;
namespace Ryujinx.Ui.Common.Helper
{
@@ -23,12 +21,9 @@ namespace Ryujinx.Ui.Common.Helper
iconPath += ".ico";
MemoryStream iconDataStream = new(iconData);
- using Image image = Image.FromStream(iconDataStream);
- using Bitmap bitmap = new(128, 128);
- using System.Drawing.Graphics graphic = System.Drawing.Graphics.FromImage(bitmap);
- graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
- graphic.DrawImage(image, 0, 0, 128, 128);
- SaveBitmapAsIcon(bitmap, iconPath);
+ var image = Image.Load(iconDataStream);
+ image.Mutate(x => x.Resize(128, 128));
+ SaveBitmapAsIcon(image, iconPath);
var shortcut = Shortcut.CreateShortcut(basePath, GetArgsString(applicationFilePath), iconPath, 0);
shortcut.StringData.NameString = cleanedAppName;
@@ -42,7 +37,7 @@ namespace Ryujinx.Ui.Common.Helper
var desktopFile = EmbeddedResources.ReadAllText("Ryujinx.Ui.Common/shortcut-template.desktop");
iconPath += ".png";
- var image = SixLabors.ImageSharp.Image.Load(iconData);
+ var image = Image.Load(iconData);
image.SaveAsPng(iconPath);
using StreamWriter outputFile = new(Path.Combine(desktopPath, cleanedAppName + ".desktop"));
@@ -83,7 +78,7 @@ namespace Ryujinx.Ui.Common.Helper
}
const string IconName = "icon.png";
- var image = SixLabors.ImageSharp.Image.Load(iconData);
+ var image = Image.Load(iconData);
image.SaveAsPng(Path.Combine(resourceFolderPath, IconName));
// plist file
@@ -147,7 +142,7 @@ namespace Ryujinx.Ui.Common.Helper
/// The source bitmap image that will be saved as an .ico file
/// The location that the new .ico file will be saved too (Make sure to include '.ico' in the path).
[SupportedOSPlatform("windows")]
- private static void SaveBitmapAsIcon(Bitmap source, string filePath)
+ private static void SaveBitmapAsIcon(Image source, string filePath)
{
// Code Modified From https://stackoverflow.com/a/11448060/368354 by Benlitz
byte[] header = { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 32, 0, 0, 0, 0, 0, 22, 0, 0, 0 };
@@ -155,7 +150,7 @@ namespace Ryujinx.Ui.Common.Helper
fs.Write(header);
// Writing actual data
- source.Save(fs, ImageFormat.Png);
+ source.Save(fs, PngFormat.Instance);
// Getting data length (file length minus header)
long dataLength = fs.Length - header.Length;
// Write it in the correct place
diff --git a/src/Ryujinx.Ui.Common/Ryujinx.Ui.Common.csproj b/src/Ryujinx.Ui.Common/Ryujinx.Ui.Common.csproj
index 1a8c216aa..24f26a3f5 100644
--- a/src/Ryujinx.Ui.Common/Ryujinx.Ui.Common.csproj
+++ b/src/Ryujinx.Ui.Common/Ryujinx.Ui.Common.csproj
@@ -57,7 +57,6 @@
-