Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
c525d7d9a9 | |||
1a0a351a15 | |||
bd3335c143 | |||
a94445b23e | |||
0c3421973c | |||
0afa8f2c14 |
@ -20,7 +20,7 @@
|
|||||||
<PackageVersion Include="LibHac" Version="0.19.0" />
|
<PackageVersion Include="LibHac" Version="0.19.0" />
|
||||||
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
|
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
|
||||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2" />
|
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2" />
|
||||||
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="7.6.0" />
|
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="7.6.2" />
|
||||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||||
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.1" />
|
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.1" />
|
||||||
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
|
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
|
||||||
|
@ -251,7 +251,20 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int selectedReg = GetHighestValueIndex(freePositions);
|
// If this is a copy destination variable, we prefer the register used for the copy source.
|
||||||
|
// If the register is available, then the copy can be eliminated later as both source
|
||||||
|
// and destination will use the same register.
|
||||||
|
int selectedReg;
|
||||||
|
|
||||||
|
if (current.TryGetCopySourceRegister(out int preferredReg) && freePositions[preferredReg] >= current.GetEnd())
|
||||||
|
{
|
||||||
|
selectedReg = preferredReg;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
selectedReg = GetHighestValueIndex(freePositions);
|
||||||
|
}
|
||||||
|
|
||||||
int selectedNextUse = freePositions[selectedReg];
|
int selectedNextUse = freePositions[selectedReg];
|
||||||
|
|
||||||
// Intervals starts and ends at odd positions, unless they span an entire
|
// Intervals starts and ends at odd positions, unless they span an entire
|
||||||
@ -431,7 +444,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int GetHighestValueIndex(Span<int> span)
|
private static int GetHighestValueIndex(ReadOnlySpan<int> span)
|
||||||
{
|
{
|
||||||
int highest = int.MinValue;
|
int highest = int.MinValue;
|
||||||
|
|
||||||
@ -798,12 +811,12 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
// The "visited" state is stored in the MSB of the local's value.
|
// The "visited" state is stored in the MSB of the local's value.
|
||||||
const ulong VisitedMask = 1ul << 63;
|
const ulong VisitedMask = 1ul << 63;
|
||||||
|
|
||||||
bool IsVisited(Operand local)
|
static bool IsVisited(Operand local)
|
||||||
{
|
{
|
||||||
return (local.GetValueUnsafe() & VisitedMask) != 0;
|
return (local.GetValueUnsafe() & VisitedMask) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetVisited(Operand local)
|
static void SetVisited(Operand local)
|
||||||
{
|
{
|
||||||
local.GetValueUnsafe() |= VisitedMask;
|
local.GetValueUnsafe() |= VisitedMask;
|
||||||
}
|
}
|
||||||
@ -826,9 +839,25 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
{
|
{
|
||||||
dest.NumberLocal(_intervals.Count);
|
dest.NumberLocal(_intervals.Count);
|
||||||
|
|
||||||
_intervals.Add(new LiveInterval(dest));
|
LiveInterval interval = new LiveInterval(dest);
|
||||||
|
_intervals.Add(interval);
|
||||||
|
|
||||||
SetVisited(dest);
|
SetVisited(dest);
|
||||||
|
|
||||||
|
// If this is a copy (or copy-like operation), set the copy source interval as well.
|
||||||
|
// This is used for register preferencing later on, which allows the copy to be eliminated
|
||||||
|
// in some cases.
|
||||||
|
if (node.Instruction == Instruction.Copy || node.Instruction == Instruction.ZeroExtend32)
|
||||||
|
{
|
||||||
|
Operand source = node.GetSource(0);
|
||||||
|
|
||||||
|
if (source.Kind == OperandKind.LocalVariable &&
|
||||||
|
source.GetLocalNumber() > 0 &&
|
||||||
|
(node.Instruction == Instruction.Copy || source.Type == OperandType.I32))
|
||||||
|
{
|
||||||
|
interval.SetCopySource(_intervals[source.GetLocalNumber()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
public LiveRange CurrRange;
|
public LiveRange CurrRange;
|
||||||
|
|
||||||
public LiveInterval Parent;
|
public LiveInterval Parent;
|
||||||
|
public LiveInterval CopySource;
|
||||||
|
|
||||||
public UseList Uses;
|
public UseList Uses;
|
||||||
public LiveIntervalList Children;
|
public LiveIntervalList Children;
|
||||||
@ -37,6 +38,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
private ref LiveRange CurrRange => ref _data->CurrRange;
|
private ref LiveRange CurrRange => ref _data->CurrRange;
|
||||||
private ref LiveRange PrevRange => ref _data->PrevRange;
|
private ref LiveRange PrevRange => ref _data->PrevRange;
|
||||||
private ref LiveInterval Parent => ref _data->Parent;
|
private ref LiveInterval Parent => ref _data->Parent;
|
||||||
|
private ref LiveInterval CopySource => ref _data->CopySource;
|
||||||
private ref UseList Uses => ref _data->Uses;
|
private ref UseList Uses => ref _data->Uses;
|
||||||
private ref LiveIntervalList Children => ref _data->Children;
|
private ref LiveIntervalList Children => ref _data->Children;
|
||||||
|
|
||||||
@ -78,6 +80,25 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
Register = register;
|
Register = register;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetCopySource(LiveInterval copySource)
|
||||||
|
{
|
||||||
|
CopySource = copySource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetCopySourceRegister(out int copySourceRegIndex)
|
||||||
|
{
|
||||||
|
if (CopySource._data != null)
|
||||||
|
{
|
||||||
|
copySourceRegIndex = CopySource.Register.Index;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
copySourceRegIndex = 0;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public void Reset()
|
public void Reset()
|
||||||
{
|
{
|
||||||
PrevRange = default;
|
PrevRange = default;
|
||||||
|
@ -29,7 +29,7 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
private const string OuterHeaderMagicString = "PTCohd\0\0";
|
private const string OuterHeaderMagicString = "PTCohd\0\0";
|
||||||
private const string InnerHeaderMagicString = "PTCihd\0\0";
|
private const string InnerHeaderMagicString = "PTCihd\0\0";
|
||||||
|
|
||||||
private const uint InternalVersion = 6634; //! To be incremented manually for each change to the ARMeilleure project.
|
private const uint InternalVersion = 6950; //! To be incremented manually for each change to the ARMeilleure project.
|
||||||
|
|
||||||
private const string ActualDir = "0";
|
private const string ActualDir = "0";
|
||||||
private const string BackupDir = "1";
|
private const string BackupDir = "1";
|
||||||
|
@ -103,12 +103,19 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
usage |= BufferUsageFlags.IndirectBufferBit;
|
usage |= BufferUsageFlags.IndirectBufferBit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var externalMemoryBuffer = new ExternalMemoryBufferCreateInfo
|
||||||
|
{
|
||||||
|
SType = StructureType.ExternalMemoryBufferCreateInfo,
|
||||||
|
HandleTypes = ExternalMemoryHandleTypeFlags.HostAllocationBitExt,
|
||||||
|
};
|
||||||
|
|
||||||
var bufferCreateInfo = new BufferCreateInfo
|
var bufferCreateInfo = new BufferCreateInfo
|
||||||
{
|
{
|
||||||
SType = StructureType.BufferCreateInfo,
|
SType = StructureType.BufferCreateInfo,
|
||||||
Size = (ulong)size,
|
Size = (ulong)size,
|
||||||
Usage = usage,
|
Usage = usage,
|
||||||
SharingMode = SharingMode.Exclusive,
|
SharingMode = SharingMode.Exclusive,
|
||||||
|
PNext = &externalMemoryBuffer,
|
||||||
};
|
};
|
||||||
|
|
||||||
gd.Api.CreateBuffer(_device, in bufferCreateInfo, null, out var buffer).ThrowOnError();
|
gd.Api.CreateBuffer(_device, in bufferCreateInfo, null, out var buffer).ThrowOnError();
|
||||||
|
@ -80,7 +80,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
var usage = GetImageUsage(info.Format, info.Target, gd.Capabilities.SupportsShaderStorageImageMultisample);
|
var usage = GetImageUsage(info.Format, info.Target, gd.Capabilities.SupportsShaderStorageImageMultisample);
|
||||||
|
|
||||||
var flags = ImageCreateFlags.CreateMutableFormatBit;
|
var flags = ImageCreateFlags.CreateMutableFormatBit | ImageCreateFlags.CreateExtendedUsageBit;
|
||||||
|
|
||||||
// This flag causes mipmapped texture arrays to break on AMD GCN, so for that copy dependencies are forced for aliasing as cube.
|
// This flag causes mipmapped texture arrays to break on AMD GCN, so for that copy dependencies are forced for aliasing as cube.
|
||||||
bool isCube = info.Target == Target.Cubemap || info.Target == Target.CubemapArray;
|
bool isCube = info.Target == Target.Cubemap || info.Target == Target.CubemapArray;
|
||||||
|
@ -100,7 +100,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
unsafe Auto<DisposableImageView> CreateImageView(ComponentMapping cm, ImageSubresourceRange sr, ImageViewType viewType, ImageUsageFlags usageFlags)
|
unsafe Auto<DisposableImageView> CreateImageView(ComponentMapping cm, ImageSubresourceRange sr, ImageViewType viewType, ImageUsageFlags usageFlags)
|
||||||
{
|
{
|
||||||
var usage = new ImageViewUsageCreateInfo
|
var imageViewUsage = new ImageViewUsageCreateInfo
|
||||||
{
|
{
|
||||||
SType = StructureType.ImageViewUsageCreateInfo,
|
SType = StructureType.ImageViewUsageCreateInfo,
|
||||||
Usage = usageFlags,
|
Usage = usageFlags,
|
||||||
@ -114,7 +114,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
Format = format,
|
Format = format,
|
||||||
Components = cm,
|
Components = cm,
|
||||||
SubresourceRange = sr,
|
SubresourceRange = sr,
|
||||||
PNext = &usage,
|
PNext = &imageViewUsage,
|
||||||
};
|
};
|
||||||
|
|
||||||
gd.Api.CreateImageView(device, imageCreateInfo, null, out var imageView).ThrowOnError();
|
gd.Api.CreateImageView(device, imageCreateInfo, null, out var imageView).ThrowOnError();
|
||||||
@ -123,7 +123,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
ImageUsageFlags shaderUsage = ImageUsageFlags.SampledBit;
|
ImageUsageFlags shaderUsage = ImageUsageFlags.SampledBit;
|
||||||
|
|
||||||
if (info.Format.IsImageCompatible())
|
if (info.Format.IsImageCompatible() && (_gd.Capabilities.SupportsShaderStorageImageMultisample || !info.Target.IsMultisample()))
|
||||||
{
|
{
|
||||||
shaderUsage |= ImageUsageFlags.StorageBit;
|
shaderUsage |= ImageUsageFlags.StorageBit;
|
||||||
}
|
}
|
||||||
@ -154,7 +154,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
subresourceRange = new ImageSubresourceRange(aspectFlags, (uint)firstLevel, levels, (uint)firstLayer, (uint)info.Depth);
|
subresourceRange = new ImageSubresourceRange(aspectFlags, (uint)firstLevel, 1, (uint)firstLayer, (uint)info.Depth);
|
||||||
|
|
||||||
_imageView2dArray = CreateImageView(identityComponentMapping, subresourceRange, ImageViewType.Type2DArray, usage);
|
_imageView2dArray = CreateImageView(identityComponentMapping, subresourceRange, ImageViewType.Type2DArray, usage);
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
"VK_EXT_depth_clip_control",
|
"VK_EXT_depth_clip_control",
|
||||||
"VK_KHR_portability_subset", // As per spec, we should enable this if present.
|
"VK_KHR_portability_subset", // As per spec, we should enable this if present.
|
||||||
"VK_EXT_4444_formats",
|
"VK_EXT_4444_formats",
|
||||||
|
"VK_KHR_8bit_storage",
|
||||||
|
"VK_KHR_maintenance2",
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly string[] _requiredExtensions = {
|
private static readonly string[] _requiredExtensions = {
|
||||||
@ -355,6 +357,14 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
features2.PNext = &supportedFeaturesDepthClipControl;
|
features2.PNext = &supportedFeaturesDepthClipControl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PhysicalDeviceVulkan12Features supportedPhysicalDeviceVulkan12Features = new()
|
||||||
|
{
|
||||||
|
SType = StructureType.PhysicalDeviceVulkan12Features,
|
||||||
|
PNext = features2.PNext,
|
||||||
|
};
|
||||||
|
|
||||||
|
features2.PNext = &supportedPhysicalDeviceVulkan12Features;
|
||||||
|
|
||||||
api.GetPhysicalDeviceFeatures2(physicalDevice.PhysicalDevice, &features2);
|
api.GetPhysicalDeviceFeatures2(physicalDevice.PhysicalDevice, &features2);
|
||||||
|
|
||||||
var supportedFeatures = features2.Features;
|
var supportedFeatures = features2.Features;
|
||||||
@ -382,6 +392,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
TessellationShader = supportedFeatures.TessellationShader,
|
TessellationShader = supportedFeatures.TessellationShader,
|
||||||
VertexPipelineStoresAndAtomics = supportedFeatures.VertexPipelineStoresAndAtomics,
|
VertexPipelineStoresAndAtomics = supportedFeatures.VertexPipelineStoresAndAtomics,
|
||||||
RobustBufferAccess = useRobustBufferAccess,
|
RobustBufferAccess = useRobustBufferAccess,
|
||||||
|
SampleRateShading = supportedFeatures.SampleRateShading,
|
||||||
};
|
};
|
||||||
|
|
||||||
void* pExtendedFeatures = null;
|
void* pExtendedFeatures = null;
|
||||||
@ -451,9 +462,11 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
SType = StructureType.PhysicalDeviceVulkan12Features,
|
SType = StructureType.PhysicalDeviceVulkan12Features,
|
||||||
PNext = pExtendedFeatures,
|
PNext = pExtendedFeatures,
|
||||||
DescriptorIndexing = physicalDevice.IsDeviceExtensionPresent("VK_EXT_descriptor_indexing"),
|
DescriptorIndexing = supportedPhysicalDeviceVulkan12Features.DescriptorIndexing,
|
||||||
DrawIndirectCount = physicalDevice.IsDeviceExtensionPresent(KhrDrawIndirectCount.ExtensionName),
|
DrawIndirectCount = supportedPhysicalDeviceVulkan12Features.DrawIndirectCount,
|
||||||
UniformBufferStandardLayout = physicalDevice.IsDeviceExtensionPresent("VK_KHR_uniform_buffer_standard_layout"),
|
UniformBufferStandardLayout = supportedPhysicalDeviceVulkan12Features.UniformBufferStandardLayout,
|
||||||
|
UniformAndStorageBuffer8BitAccess = supportedPhysicalDeviceVulkan12Features.UniformAndStorageBuffer8BitAccess,
|
||||||
|
StorageBuffer8BitAccess = supportedPhysicalDeviceVulkan12Features.StorageBuffer8BitAccess,
|
||||||
};
|
};
|
||||||
|
|
||||||
pExtendedFeatures = &featuresVk12;
|
pExtendedFeatures = &featuresVk12;
|
||||||
|
@ -623,7 +623,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
public override void SetSize(int width, int height)
|
public override void SetSize(int width, int height)
|
||||||
{
|
{
|
||||||
// Not needed as we can get the size from the surface.
|
// We don't need to use width and height as we can get the size from the surface.
|
||||||
|
_swapchainIsDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ChangeVSyncMode(bool vsyncEnabled)
|
public override void ChangeVSyncMode(bool vsyncEnabled)
|
||||||
|
@ -1546,8 +1546,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||||||
#pragma warning disable CA1822 // Mark member as static
|
#pragma warning disable CA1822 // Mark member as static
|
||||||
public Result SetProcessMemoryPermission(
|
public Result SetProcessMemoryPermission(
|
||||||
int handle,
|
int handle,
|
||||||
[PointerSized] ulong src,
|
ulong src,
|
||||||
[PointerSized] ulong size,
|
ulong size,
|
||||||
KMemoryPermission permission)
|
KMemoryPermission permission)
|
||||||
{
|
{
|
||||||
if (!PageAligned(src))
|
if (!PageAligned(src))
|
||||||
|
@ -104,8 +104,13 @@ namespace Ryujinx.UI.Common
|
|||||||
// Find the length to trim the string to guarantee we have space for the trailing ellipsis.
|
// Find the length to trim the string to guarantee we have space for the trailing ellipsis.
|
||||||
int trimLimit = byteLimit - Encoding.UTF8.GetByteCount(Ellipsis);
|
int trimLimit = byteLimit - Encoding.UTF8.GetByteCount(Ellipsis);
|
||||||
|
|
||||||
// Basic trim to best case scenario of 1 byte characters.
|
// Make sure the string is long enough to perform the basic trim.
|
||||||
input = input[..trimLimit];
|
// Amount of bytes != Length of the string
|
||||||
|
if (input.Length > trimLimit)
|
||||||
|
{
|
||||||
|
// Basic trim to best case scenario of 1 byte characters.
|
||||||
|
input = input[..trimLimit];
|
||||||
|
}
|
||||||
|
|
||||||
while (Encoding.UTF8.GetByteCount(input) > trimLimit)
|
while (Encoding.UTF8.GetByteCount(input) > trimLimit)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user