Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
17078ad929 | ||
|
32450d45de | ||
|
ed7a0474c6 | ||
|
fe9c49949a |
34
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
34
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -1,26 +1,27 @@
|
||||
name: Bug Report
|
||||
description: File a bug report
|
||||
title: "[Bug] <title>"
|
||||
title: "[Bug]"
|
||||
labels: bug
|
||||
body:
|
||||
- type: textarea
|
||||
id: issue
|
||||
attributes:
|
||||
label: Description of Issue
|
||||
label: Description of the issue
|
||||
description: What's the issue you encountered?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: repro
|
||||
attributes:
|
||||
label: Reproduction Steps
|
||||
label: Reproduction steps
|
||||
description: How can the issue be reproduced?
|
||||
placeholder: Describe each step as precisely as possible
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: log
|
||||
attributes:
|
||||
label: Log File
|
||||
label: Log file
|
||||
description: A log file will help our developers to better diagnose and fix the issue.
|
||||
placeholder: Logs files can be found under "Logs" folder in Ryujinx program folder. You can drag and drop the log on to the text area
|
||||
validations:
|
||||
@@ -29,55 +30,44 @@ body:
|
||||
id: os
|
||||
attributes:
|
||||
label: OS
|
||||
placeholder: "Example: Windows 10"
|
||||
placeholder: "e.g. Windows 10"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: ryujinx-version
|
||||
attributes:
|
||||
label: Ryujinx version
|
||||
placeholder: |
|
||||
- *(e.g. 1.0.470)*
|
||||
placeholder: "e.g. 1.0.470"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: game-version
|
||||
attributes:
|
||||
label: Game version
|
||||
placeholder: |
|
||||
- *(e.g. 1.1.1)*
|
||||
placeholder: "e.g. 1.1.1"
|
||||
validations:
|
||||
required: false
|
||||
- type: input
|
||||
id: cpu
|
||||
attributes:
|
||||
label: CPU
|
||||
placeholder: |
|
||||
- *(e.g. i7-6700)*
|
||||
placeholder: "e.g. i7-6700"
|
||||
validations:
|
||||
required: false
|
||||
- type: input
|
||||
id: gpu
|
||||
attributes:
|
||||
label: GPU
|
||||
placeholder: |
|
||||
- *(e.g. NVIDIA RTX 2070)*
|
||||
placeholder: "e.g. NVIDIA RTX 2070"
|
||||
validations:
|
||||
required: false
|
||||
- type: input
|
||||
id: ram
|
||||
attributes:
|
||||
label: RAM
|
||||
placeholder: |
|
||||
- *(e.g. 16GB)*
|
||||
placeholder: "e.g. 16GB"
|
||||
validations:
|
||||
required: false
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Applied Mods?
|
||||
options:
|
||||
- label: "Yes"
|
||||
required: false
|
||||
- type: textarea
|
||||
id: mods
|
||||
attributes:
|
||||
@@ -93,4 +83,4 @@ body:
|
||||
- Additional info about your environment:
|
||||
- Any other information relevant to your issue.
|
||||
validations:
|
||||
required: false
|
||||
required: false
|
6
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
6
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@@ -1,6 +1,6 @@
|
||||
name: Feature Request
|
||||
description: Suggest a new feature for Ryujinx.
|
||||
title: "[Feature Request] <title>"
|
||||
title: "[Feature Request]"
|
||||
body:
|
||||
- type: textarea
|
||||
id: overview
|
||||
@@ -12,14 +12,14 @@ body:
|
||||
- type: textarea
|
||||
id: details
|
||||
attributes:
|
||||
label: Smaller Details
|
||||
label: Smaller details
|
||||
description: These may include specific methods of implementation etc.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: request
|
||||
attributes:
|
||||
label: Nature of Request
|
||||
label: Nature of request
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
|
@@ -1,6 +1,6 @@
|
||||
name: Missing CPU Instruction
|
||||
description: CPU Instruction is missing in Ryujinx.
|
||||
title: "[CPU] <title>"
|
||||
title: "[CPU]"
|
||||
labels: [cpu, not-implemented]
|
||||
body:
|
||||
- type: textarea
|
||||
|
@@ -5,7 +5,7 @@ body:
|
||||
- type: textarea
|
||||
id: instruction
|
||||
attributes:
|
||||
label: Service Call
|
||||
label: Service call
|
||||
description: What service call is missing?
|
||||
validations:
|
||||
required: true
|
||||
|
@@ -39,7 +39,6 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
BufferUsageFlags.VertexBufferBit |
|
||||
BufferUsageFlags.TransformFeedbackBufferBitExt;
|
||||
|
||||
private readonly PhysicalDevice _physicalDevice;
|
||||
private readonly Device _device;
|
||||
|
||||
private readonly IdList<BufferHolder> _buffers;
|
||||
@@ -48,9 +47,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
public StagingBuffer StagingBuffer { get; }
|
||||
|
||||
public BufferManager(VulkanRenderer gd, PhysicalDevice physicalDevice, Device device)
|
||||
public BufferManager(VulkanRenderer gd, Device device)
|
||||
{
|
||||
_physicalDevice = physicalDevice;
|
||||
_device = device;
|
||||
_buffers = new IdList<BufferHolder>();
|
||||
StagingBuffer = new StagingBuffer(gd, this);
|
||||
@@ -114,7 +112,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
allocateFlagsAlt = DefaultBufferMemoryAltFlags;
|
||||
}
|
||||
|
||||
var allocation = gd.MemoryAllocator.AllocateDeviceMemory(_physicalDevice, requirements, allocateFlags, allocateFlagsAlt);
|
||||
var allocation = gd.MemoryAllocator.AllocateDeviceMemory(requirements, allocateFlags, allocateFlagsAlt);
|
||||
|
||||
if (allocation.Memory.Handle == 0UL)
|
||||
{
|
||||
|
@@ -8,11 +8,10 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
None = 0,
|
||||
|
||||
VertexBufferAlignment4B = 1,
|
||||
NoTriangleFans = 1 << 1,
|
||||
NoPointMode = 1 << 2,
|
||||
No3DImageView = 1 << 3,
|
||||
NoLodBias = 1 << 4
|
||||
NoTriangleFans = 1,
|
||||
NoPointMode = 1 << 1,
|
||||
No3DImageView = 1 << 2,
|
||||
NoLodBias = 1 << 3
|
||||
}
|
||||
|
||||
readonly struct HardwareCapabilities
|
||||
@@ -40,6 +39,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
public readonly ShaderStageFlags RequiredSubgroupSizeStages;
|
||||
public readonly SampleCountFlags SupportedSampleCounts;
|
||||
public readonly PortabilitySubsetFlags PortabilitySubset;
|
||||
public readonly uint VertexBufferAlignment;
|
||||
|
||||
public HardwareCapabilities(
|
||||
bool supportsIndexTypeUint8,
|
||||
@@ -64,7 +64,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
uint maxSubgroupSize,
|
||||
ShaderStageFlags requiredSubgroupSizeStages,
|
||||
SampleCountFlags supportedSampleCounts,
|
||||
PortabilitySubsetFlags portabilitySubset)
|
||||
PortabilitySubsetFlags portabilitySubset,
|
||||
uint vertexBufferAlignment)
|
||||
{
|
||||
SupportsIndexTypeUint8 = supportsIndexTypeUint8;
|
||||
SupportsCustomBorderColor = supportsCustomBorderColor;
|
||||
@@ -89,6 +90,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
RequiredSubgroupSizeStages = requiredSubgroupSizeStages;
|
||||
SupportedSampleCounts = supportedSampleCounts;
|
||||
PortabilitySubset = portabilitySubset;
|
||||
VertexBufferAlignment = vertexBufferAlignment;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -9,34 +9,36 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
private ulong MaxDeviceMemoryUsageEstimate = 16UL * 1024 * 1024 * 1024;
|
||||
|
||||
private readonly Vk _api;
|
||||
private readonly PhysicalDevice _physicalDevice;
|
||||
private readonly Device _device;
|
||||
private readonly List<MemoryAllocatorBlockList> _blockLists;
|
||||
private readonly int _blockAlignment;
|
||||
private readonly PhysicalDeviceMemoryProperties _physicalDeviceMemoryProperties;
|
||||
|
||||
private int _blockAlignment;
|
||||
|
||||
public MemoryAllocator(Vk api, Device device, uint maxMemoryAllocationCount)
|
||||
public MemoryAllocator(Vk api, PhysicalDevice physicalDevice, Device device, uint maxMemoryAllocationCount)
|
||||
{
|
||||
_api = api;
|
||||
_physicalDevice = physicalDevice;
|
||||
_device = device;
|
||||
_blockLists = new List<MemoryAllocatorBlockList>();
|
||||
_blockAlignment = (int)Math.Min(int.MaxValue, MaxDeviceMemoryUsageEstimate / (ulong)maxMemoryAllocationCount);
|
||||
|
||||
_api.GetPhysicalDeviceMemoryProperties(_physicalDevice, out _physicalDeviceMemoryProperties);
|
||||
}
|
||||
|
||||
public MemoryAllocation AllocateDeviceMemory(
|
||||
PhysicalDevice physicalDevice,
|
||||
MemoryRequirements requirements,
|
||||
MemoryPropertyFlags flags = 0)
|
||||
{
|
||||
return AllocateDeviceMemory(physicalDevice, requirements, flags, flags);
|
||||
return AllocateDeviceMemory(requirements, flags, flags);
|
||||
}
|
||||
|
||||
public MemoryAllocation AllocateDeviceMemory(
|
||||
PhysicalDevice physicalDevice,
|
||||
MemoryRequirements requirements,
|
||||
MemoryPropertyFlags flags,
|
||||
MemoryPropertyFlags alternativeFlags)
|
||||
{
|
||||
int memoryTypeIndex = FindSuitableMemoryTypeIndex(_api, physicalDevice, requirements.MemoryTypeBits, flags, alternativeFlags);
|
||||
int memoryTypeIndex = FindSuitableMemoryTypeIndex(requirements.MemoryTypeBits, flags, alternativeFlags);
|
||||
if (memoryTypeIndex < 0)
|
||||
{
|
||||
return default;
|
||||
@@ -65,20 +67,16 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
return newBl.Allocate(size, alignment, map);
|
||||
}
|
||||
|
||||
private static int FindSuitableMemoryTypeIndex(
|
||||
Vk api,
|
||||
PhysicalDevice physicalDevice,
|
||||
private int FindSuitableMemoryTypeIndex(
|
||||
uint memoryTypeBits,
|
||||
MemoryPropertyFlags flags,
|
||||
MemoryPropertyFlags alternativeFlags)
|
||||
{
|
||||
int bestCandidateIndex = -1;
|
||||
|
||||
api.GetPhysicalDeviceMemoryProperties(physicalDevice, out var properties);
|
||||
|
||||
for (int i = 0; i < properties.MemoryTypeCount; i++)
|
||||
for (int i = 0; i < _physicalDeviceMemoryProperties.MemoryTypeCount; i++)
|
||||
{
|
||||
var type = properties.MemoryTypes[i];
|
||||
var type = _physicalDeviceMemoryProperties.MemoryTypes[i];
|
||||
|
||||
if ((memoryTypeBits & (1 << i)) != 0)
|
||||
{
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Graphics.Shader;
|
||||
using Silk.NET.Vulkan;
|
||||
using System;
|
||||
@@ -1136,7 +1137,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
buffer.Dispose();
|
||||
|
||||
if (!Gd.Capabilities.PortabilitySubset.HasFlag(PortabilitySubsetFlags.VertexBufferAlignment4B) &&
|
||||
if (Gd.Capabilities.VertexBufferAlignment < 2 &&
|
||||
(vertexBuffer.Stride % FormatExtensions.MaxBufferFormatScalarSize) == 0)
|
||||
{
|
||||
buffer = new VertexBufferState(
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Silk.NET.Vulkan;
|
||||
using System;
|
||||
|
||||
@@ -253,7 +254,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
if (gd.NeedsVertexBufferAlignment(vbScalarSizes[i], out int alignment))
|
||||
{
|
||||
alignedStride = (vertexBuffer.Stride + (alignment - 1)) & -alignment;
|
||||
alignedStride = BitUtils.AlignUp(vertexBuffer.Stride, alignment);
|
||||
}
|
||||
|
||||
// TODO: Support divisor > 1
|
||||
|
@@ -55,7 +55,6 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
public unsafe TextureStorage(
|
||||
VulkanRenderer gd,
|
||||
PhysicalDevice physicalDevice,
|
||||
Device device,
|
||||
TextureCreateInfo info,
|
||||
float scaleFactor,
|
||||
@@ -118,7 +117,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
if (foreignAllocation == null)
|
||||
{
|
||||
gd.Api.GetImageMemoryRequirements(device, _image, out var requirements);
|
||||
var allocation = gd.MemoryAllocator.AllocateDeviceMemory(physicalDevice, requirements, DefaultImageMemoryFlags);
|
||||
var allocation = gd.MemoryAllocator.AllocateDeviceMemory(requirements, DefaultImageMemoryFlags);
|
||||
|
||||
if (allocation.Memory.Handle == 0UL)
|
||||
{
|
||||
@@ -173,7 +172,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
var info = NewCreateInfoWith(ref _info, format, _info.BytesPerPixel);
|
||||
|
||||
storage = new TextureStorage(_gd, default, _device, info, ScaleFactor, _allocationAuto);
|
||||
storage = new TextureStorage(_gd, _device, info, ScaleFactor, _allocationAuto);
|
||||
|
||||
_aliasedStorages.Add(format, storage);
|
||||
}
|
||||
|
@@ -14,6 +14,9 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
public unsafe static class VulkanInitialization
|
||||
{
|
||||
private const uint InvalidIndex = uint.MaxValue;
|
||||
private static uint MinimalVulkanVersion = Vk.Version11.Value;
|
||||
private static uint MinimalInstanceVulkanVersion = Vk.Version12.Value;
|
||||
private static uint MaximumVulkanVersion = Vk.Version12.Value;
|
||||
private const string AppName = "Ryujinx.Graphics.Vulkan";
|
||||
private const int QueuesCount = 2;
|
||||
|
||||
@@ -33,7 +36,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
"VK_KHR_shader_float16_int8",
|
||||
"VK_EXT_shader_subgroup_ballot",
|
||||
"VK_EXT_subgroup_size_control",
|
||||
"VK_NV_geometry_shader_passthrough"
|
||||
"VK_NV_geometry_shader_passthrough",
|
||||
"VK_KHR_portability_subset", // By spec, we should enable this if present.
|
||||
};
|
||||
|
||||
public static string[] RequiredExtensions { get; } = new string[]
|
||||
@@ -99,7 +103,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
ApplicationVersion = 1,
|
||||
PEngineName = (byte*)appName,
|
||||
EngineVersion = 1,
|
||||
ApiVersion = Vk.Version12.Value
|
||||
ApiVersion = MaximumVulkanVersion
|
||||
};
|
||||
|
||||
IntPtr* ppEnabledExtensions = stackalloc IntPtr[enabledExtensions.Length];
|
||||
@@ -224,7 +228,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
ApplicationVersion = 1,
|
||||
PEngineName = (byte*)appName,
|
||||
EngineVersion = 1,
|
||||
ApiVersion = Vk.Version12.Value
|
||||
ApiVersion = MaximumVulkanVersion
|
||||
};
|
||||
|
||||
var instanceCreateInfo = new InstanceCreateInfo
|
||||
@@ -239,6 +243,27 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
api.CreateInstance(in instanceCreateInfo, null, out var instance).ThrowOnError();
|
||||
|
||||
// We ensure that vkEnumerateInstanceVersion is present (added in 1.1).
|
||||
// If the instance doesn't support it, no device is going to be 1.1 compatible.
|
||||
if (api.GetInstanceProcAddr(instance, "vkEnumerateInstanceVersion") == IntPtr.Zero)
|
||||
{
|
||||
api.DestroyInstance(instance, null);
|
||||
|
||||
return Array.Empty<DeviceInfo>();
|
||||
}
|
||||
|
||||
// We currently assume that the instance is compatible with Vulkan 1.2
|
||||
// TODO: Remove this once we relax our initialization codepaths.
|
||||
uint instanceApiVerison = 0;
|
||||
api.EnumerateInstanceVersion(ref instanceApiVerison).ThrowOnError();
|
||||
|
||||
if (instanceApiVerison < MinimalInstanceVulkanVersion)
|
||||
{
|
||||
api.DestroyInstance(instance, null);
|
||||
|
||||
return Array.Empty<DeviceInfo>();
|
||||
}
|
||||
|
||||
Marshal.FreeHGlobal(appName);
|
||||
|
||||
uint physicalDeviceCount;
|
||||
@@ -259,6 +284,11 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
var physicalDevice = physicalDevices[i];
|
||||
api.GetPhysicalDeviceProperties(physicalDevice, out var properties);
|
||||
|
||||
if (properties.ApiVersion < MinimalVulkanVersion)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
devices[i] = new DeviceInfo(
|
||||
StringFromIdPair(properties.VendorID, properties.DeviceID),
|
||||
VendorUtils.GetNameFromId(properties.VendorID),
|
||||
|
@@ -234,10 +234,12 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
Api.GetPhysicalDeviceFeatures2(_physicalDevice, &features2);
|
||||
|
||||
var portabilityFlags = PortabilitySubsetFlags.None;
|
||||
uint vertexBufferAlignment = 1;
|
||||
|
||||
if (usePortability)
|
||||
{
|
||||
portabilityFlags |= propertiesPortabilitySubset.MinVertexInputBindingStrideAlignment > 1 ? PortabilitySubsetFlags.VertexBufferAlignment4B : 0;
|
||||
vertexBufferAlignment = propertiesPortabilitySubset.MinVertexInputBindingStrideAlignment;
|
||||
|
||||
portabilityFlags |= featuresPortabilitySubset.TriangleFans ? 0 : PortabilitySubsetFlags.NoTriangleFans;
|
||||
portabilityFlags |= featuresPortabilitySubset.PointPolygons ? 0 : PortabilitySubsetFlags.NoPointMode;
|
||||
portabilityFlags |= featuresPortabilitySubset.ImageView2DOn3DImage ? 0 : PortabilitySubsetFlags.No3DImageView;
|
||||
@@ -278,9 +280,10 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
propertiesSubgroupSizeControl.MaxSubgroupSize,
|
||||
propertiesSubgroupSizeControl.RequiredSubgroupSizeStages,
|
||||
supportedSampleCounts,
|
||||
portabilityFlags);
|
||||
portabilityFlags,
|
||||
vertexBufferAlignment);
|
||||
|
||||
MemoryAllocator = new MemoryAllocator(Api, _device, properties.Limits.MaxMemoryAllocationCount);
|
||||
MemoryAllocator = new MemoryAllocator(Api, _physicalDevice, _device, properties.Limits.MaxMemoryAllocationCount);
|
||||
|
||||
CommandBufferPool = VulkanInitialization.CreateCommandBufferPool(Api, _device, Queue, QueueLock, queueFamilyIndex);
|
||||
|
||||
@@ -290,7 +293,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
BackgroundResources = new BackgroundResources(this, _device);
|
||||
|
||||
BufferManager = new BufferManager(this, _physicalDevice, _device);
|
||||
BufferManager = new BufferManager(this, _device);
|
||||
|
||||
_syncManager = new SyncManager(this, _device);
|
||||
_pipeline = new PipelineFull(this, _device);
|
||||
@@ -388,7 +391,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
internal TextureStorage CreateTextureStorage(TextureCreateInfo info, float scale)
|
||||
{
|
||||
return new TextureStorage(this, _physicalDevice, _device, info, scale);
|
||||
return new TextureStorage(this, _device, info, scale);
|
||||
}
|
||||
|
||||
public void DeleteBuffer(BufferHandle buffer)
|
||||
@@ -636,11 +639,11 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
PrintGpuInformation();
|
||||
}
|
||||
|
||||
public bool NeedsVertexBufferAlignment(int attrScalarAlignment, out int alignment)
|
||||
internal bool NeedsVertexBufferAlignment(int attrScalarAlignment, out int alignment)
|
||||
{
|
||||
if (Capabilities.PortabilitySubset.HasFlag(PortabilitySubsetFlags.VertexBufferAlignment4B))
|
||||
if (Capabilities.VertexBufferAlignment > 1)
|
||||
{
|
||||
alignment = 4;
|
||||
alignment = (int)Capabilities.VertexBufferAlignment;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
Reference in New Issue
Block a user