Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Beryl.RHI/Beryl.RHI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

<ItemGroup>
<PackageReference Include="Silk.NET.Windowing" Version="2.23.0" />
<PackageReference Include="Veldrith" Version="1.2.18" />
<PackageReference Include="Vortice.Direct3D12" Version="3.8.3" />
<PackageReference Include="Vortice.Vulkan" Version="3.3.0" />
<PackageReference Include="WebGPUSharp" Version="0.5.8" />
</ItemGroup>

<ItemGroup>
Expand Down
115 changes: 115 additions & 0 deletions Beryl.RHI/GraphicsBackendSupport.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// This file is part of the Beryl Game Engine.
// Licensed under the MIT license. (https://github.com/Beryl-Engine/Beryl/blob/main/LICENSE)

using Vortice.Direct3D;
using Vortice.Direct3D12;
using Vortice.DXGI;
using Vortice.Vulkan;

namespace Beryl.RHI;

internal static class GraphicsBackendSupport
{
public static bool IsDirect3D12Supported()
{
if (DXGI.CreateDXGIFactory1<IDXGIFactory1>(out var factory).Failure || factory == null)
return false;

using (factory)
{
for (uint index = 0; factory.EnumAdapters1(index, out var adapter).Success; index++)
{
using (adapter)
{
if ((adapter.Description1.Flags & AdapterFlags.Software) == 0 && D3D12.IsSupported(adapter, FeatureLevel.Level_11_0))
return true;
}
}
}

return false;
}

public static unsafe bool IsVulkanSupported()
{
if (Vulkan.vkInitialize() != VkResult.Success || Vulkan.vkEnumerateInstanceVersion() < VkVersion.Version_1_1)
return false;

if (Vulkan.vkEnumerateInstanceExtensionProperties(out uint extensionCount) != VkResult.Success || extensionCount == 0)
return false;

VkExtensionProperties[] extensions = new VkExtensionProperties[extensionCount];
if (Vulkan.vkEnumerateInstanceExtensionProperties(extensions) != VkResult.Success ||
!HasExtension(extensions, "VK_KHR_surface\0"u8) ||
!(OperatingSystem.IsWindows()
? HasExtension(extensions, "VK_KHR_win32_surface\0"u8)
: HasExtension(extensions, "VK_KHR_xlib_surface\0"u8) || HasExtension(extensions, "VK_KHR_wayland_surface\0"u8)))
{
return false;
}

VkApplicationInfo application = new() { apiVersion = VkVersion.Version_1_1 };
VkInstanceCreateInfo description = new() { pApplicationInfo = &application };
if (Vulkan.vkCreateInstance(in description, out VkInstance instance) != VkResult.Success)
return false;

var api = new VkInstanceApi(in instance);
try
{
if (api.vkEnumeratePhysicalDevices(out uint deviceCount) != VkResult.Success || deviceCount == 0)
return false;

VkPhysicalDevice[] devices = new VkPhysicalDevice[deviceCount];
if (api.vkEnumeratePhysicalDevices(devices) != VkResult.Success)
return false;

foreach (var device in devices)
{
if (device.IsNotNull && api.vkGetPhysicalDeviceProperties(device).apiVersion >= VkVersion.Version_1_1 && HasRequiredQueue(api, device) && HasSwapchainSupport(api, device))
return true;
}
return false;
}
finally
{
api.vkDestroyInstance();
}
}

private static bool HasRequiredQueue(VkInstanceApi api, VkPhysicalDevice device)
{
api.vkGetPhysicalDeviceQueueFamilyProperties(device, out uint count);
VkQueueFamilyProperties[] queues = new VkQueueFamilyProperties[count];

api.vkGetPhysicalDeviceQueueFamilyProperties(device, queues);

const VkQueueFlags required = VkQueueFlags.Graphics | VkQueueFlags.Compute;
foreach (var queue in queues)
{
if (queue.queueCount > 0 && (queue.queueFlags & required) == required)
return true;
}

return false;
}

private static bool HasSwapchainSupport(VkInstanceApi api, VkPhysicalDevice device)
{
if (api.vkEnumerateDeviceExtensionProperties(device, out uint count) != VkResult.Success || count == 0)
return false;

VkExtensionProperties[] extensions = new VkExtensionProperties[count];
return api.vkEnumerateDeviceExtensionProperties(device, extensions) == VkResult.Success && HasExtension(extensions, "VK_KHR_swapchain\0"u8);
}

private static unsafe bool HasExtension(ReadOnlySpan<VkExtensionProperties> extensions, ReadOnlySpan<byte> name)
{
foreach (var extension in extensions)
{
if (new ReadOnlySpan<byte>(extension.extensionName, 256).StartsWith(name))
return true;
}

return false;
}
}
24 changes: 17 additions & 7 deletions Beryl.RHI/GraphicsDeviceFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,24 @@ namespace Beryl.RHI;
/// </summary>
public static class GraphicsDeviceFactory
{
/// <summary> Determines whether <paramref name="backend"/> is supported. </summary>
public static bool IsBackendSupported(RendererBackend backend) => backend switch
/// <summary> Checks platform, runtime and driver support for <paramref name="backend"/>. Window presentation is validated during device initialization. </summary>
public static bool IsBackendSupported(RendererBackend backend)
{
RendererBackend.Vulkan => Veldrith.GraphicsDevice.IsBackendSupported(Veldrith.GraphicsBackend.Vulkan),
RendererBackend.Direct3D12 => Veldrith.GraphicsDevice.IsBackendSupported(Veldrith.GraphicsBackend.Direct3D12),
_ => false
};
try
{
return backend switch
{
RendererBackend.Vulkan => (OperatingSystem.IsWindows() || OperatingSystem.IsLinux()) && GraphicsBackendSupport.IsVulkanSupported(),
RendererBackend.Direct3D12 => OperatingSystem.IsWindowsVersionAtLeast(10) && GraphicsBackendSupport.IsDirect3D12Supported(),
_ => false
};
}
catch (Exception exception) when (exception is DllNotFoundException or EntryPointNotFoundException or BadImageFormatException or TypeInitializationException or SharpGen.Runtime.SharpGenException)
{
return false;
}
}

/// <summary> Creates a graphics device for <paramref name="backend"/>. </summary>
public static IGraphicsDevice Create(RendererBackend backend) => new VeldrithBackend.VeldrithDevice(backend);
public static IGraphicsDevice Create(RendererBackend backend) => new WebGPUBackend.WebGPUDevice(backend);
}
73 changes: 0 additions & 73 deletions Beryl.RHI/VeldrithBackend/VeldrithCommandBuffer.cs

This file was deleted.

Loading
Loading