internal static void SelectAvailableDevices(VulkanInstance instance, VulkanSurface surface, bool preferDiscreteGpu, string preferredDevice) { uint physicalDeviceCount; instance.Api.EnumeratePhysicalDevices(instance.InternalHandle, &physicalDeviceCount, null).ThrowOnError(); var physicalDevices = new PhysicalDevice[physicalDeviceCount]; fixed(PhysicalDevice *pPhysicalDevices = physicalDevices) { instance.Api.EnumeratePhysicalDevices(instance.InternalHandle, &physicalDeviceCount, pPhysicalDevices) .ThrowOnError(); } PhysicalDevices = new Dictionary <PhysicalDevice, PhysicalDeviceProperties>(); foreach (var physicalDevice in physicalDevices) { instance.Api.GetPhysicalDeviceProperties(physicalDevice, out var properties); PhysicalDevices.Add(physicalDevice, properties); } SuitableDevices = PhysicalDevices.Where(x => IsSuitableDevice( instance.Api, x.Key, x.Value, surface.ApiHandle, out _, out _)); }
internal static VulkanPhysicalDevice FindSuitablePhysicalDevice(VulkanInstance instance, VulkanSurface surface, bool preferDiscreteGpu, string preferredDevice) { SelectAvailableDevices(instance, surface, preferDiscreteGpu, preferredDevice); uint queueFamilyIndex = 0; uint queueCount = 0; if (!string.IsNullOrWhiteSpace(preferredDevice)) { var physicalDevice = SuitableDevices.FirstOrDefault(x => VulkanInitialization.StringFromIdPair(x.Value.VendorID, x.Value.DeviceID) == preferredDevice); queueFamilyIndex = FindSuitableQueueFamily(instance.Api, physicalDevice.Key, surface.ApiHandle, out queueCount); if (queueFamilyIndex != int.MaxValue) { return(new VulkanPhysicalDevice(physicalDevice.Key, instance.Api, queueCount, queueFamilyIndex)); } } if (preferDiscreteGpu) { var discreteGpus = SuitableDevices.Where(p => p.Value.DeviceType == PhysicalDeviceType.DiscreteGpu); foreach (var gpu in discreteGpus) { queueFamilyIndex = FindSuitableQueueFamily(instance.Api, gpu.Key, surface.ApiHandle, out queueCount); if (queueFamilyIndex != int.MaxValue) { return(new VulkanPhysicalDevice(gpu.Key, instance.Api, queueCount, queueFamilyIndex)); } } } foreach (var physicalDevice in SuitableDevices) { queueFamilyIndex = FindSuitableQueueFamily(instance.Api, physicalDevice.Key, surface.ApiHandle, out queueCount); if (queueFamilyIndex != int.MaxValue) { return(new VulkanPhysicalDevice(physicalDevice.Key, instance.Api, queueCount, queueFamilyIndex)); } } throw new Exception("No suitable physical device found"); }
private VulkanDisplay(VulkanInstance instance, VulkanDevice device, VulkanPhysicalDevice physicalDevice, VulkanSurface surface, SwapchainKHR swapchain, Extent2D swapchainExtent) { _instance = instance; _device = device; _physicalDevice = physicalDevice; _swapchain = swapchain; _swapchainExtent = swapchainExtent; _surface = surface; CreateSwapchainImages(); _semaphorePair = new VulkanSemaphorePair(_device); CommandBufferPool = new VulkanCommandBufferPool(device, physicalDevice); }
public VulkanSurfaceRenderTarget CreateRenderTarget(IVulkanPlatformSurface platformSurface) { var surface = VulkanSurface.CreateSurface(Instance, platformSurface); if (PhysicalDevice == null) { PhysicalDevice = VulkanPhysicalDevice.FindSuitablePhysicalDevice(Instance, surface, _options.PreferDiscreteGpu, _options.PreferredDevice); } var renderTarget = new VulkanSurfaceRenderTarget(this, surface); if (MainSurface == null && surface != null) { MainSurface = renderTarget; } return(renderTarget); }
private static unsafe Extent2D GetSwapchainExtent(VulkanSurface surface, SurfaceCapabilitiesKHR capabilities) { Extent2D swapchainExtent; if (capabilities.CurrentExtent.Width != uint.MaxValue) { swapchainExtent = capabilities.CurrentExtent; } else { var surfaceSize = surface.SurfaceSize; var width = Math.Clamp((uint)surfaceSize.Width, capabilities.MinImageExtent.Width, capabilities.MaxImageExtent.Width); var height = Math.Clamp((uint)surfaceSize.Height, capabilities.MinImageExtent.Height, capabilities.MaxImageExtent.Height); swapchainExtent = new Extent2D(width, height); } return(swapchainExtent); }
private static unsafe SwapchainKHR CreateSwapchain(VulkanInstance instance, VulkanDevice device, VulkanPhysicalDevice physicalDevice, VulkanSurface surface, out Extent2D swapchainExtent, SwapchainKHR?oldswapchain = null, bool vsyncEnabled = true) { if (_swapchainExtension == null) { instance.Api.TryGetDeviceExtension(instance.InternalHandle, device.InternalHandle, out _swapchainExtension); } while (!surface.CanSurfacePresent(physicalDevice)) { Thread.Sleep(16); } VulkanSurface.SurfaceExtension.GetPhysicalDeviceSurfaceCapabilities(physicalDevice.InternalHandle, surface.ApiHandle, out var capabilities); var imageCount = capabilities.MinImageCount + 1; if (capabilities.MaxImageCount > 0 && imageCount > capabilities.MaxImageCount) { imageCount = capabilities.MaxImageCount; } var surfaceFormat = surface.GetSurfaceFormat(physicalDevice); bool supportsIdentityTransform = capabilities.SupportedTransforms.HasFlag(SurfaceTransformFlagsKHR.SurfaceTransformIdentityBitKhr); bool isRotated = capabilities.CurrentTransform.HasFlag(SurfaceTransformFlagsKHR.SurfaceTransformRotate90BitKhr) || capabilities.CurrentTransform.HasFlag(SurfaceTransformFlagsKHR.SurfaceTransformRotate270BitKhr); swapchainExtent = GetSwapchainExtent(surface, capabilities); CompositeAlphaFlagsKHR compositeAlphaFlags = GetSuitableCompositeAlphaFlags(capabilities); PresentModeKHR presentMode = GetSuitablePresentMode(physicalDevice, surface, vsyncEnabled); var swapchainCreateInfo = new SwapchainCreateInfoKHR { SType = StructureType.SwapchainCreateInfoKhr, Surface = surface.ApiHandle, MinImageCount = imageCount, ImageFormat = surfaceFormat.Format, ImageColorSpace = surfaceFormat.ColorSpace, ImageExtent = swapchainExtent, ImageUsage = ImageUsageFlags.ImageUsageColorAttachmentBit | ImageUsageFlags.ImageUsageTransferDstBit, ImageSharingMode = SharingMode.Exclusive, ImageArrayLayers = 1, PreTransform = supportsIdentityTransform && isRotated ? SurfaceTransformFlagsKHR.SurfaceTransformIdentityBitKhr : capabilities.CurrentTransform, CompositeAlpha = compositeAlphaFlags, PresentMode = presentMode, Clipped = true, OldSwapchain = oldswapchain ?? new SwapchainKHR() }; _swapchainExtension.CreateSwapchain(device.InternalHandle, swapchainCreateInfo, null, out var swapchain) .ThrowOnError(); if (oldswapchain != null) { _swapchainExtension.DestroySwapchain(device.InternalHandle, oldswapchain.Value, null); } return(swapchain); }
internal static VulkanDisplay CreateDisplay(VulkanInstance instance, VulkanDevice device, VulkanPhysicalDevice physicalDevice, VulkanSurface surface) { var swapchain = CreateSwapchain(instance, device, physicalDevice, surface, out var extent, null, true); return(new VulkanDisplay(instance, device, physicalDevice, surface, swapchain, extent)); }
private static unsafe PresentModeKHR GetSuitablePresentMode(VulkanPhysicalDevice physicalDevice, VulkanSurface surface, bool vsyncEnabled) { uint presentModesCount; VulkanSurface.SurfaceExtension.GetPhysicalDeviceSurfacePresentModes(physicalDevice.InternalHandle, surface.ApiHandle, &presentModesCount, null); var presentModes = new PresentModeKHR[presentModesCount]; fixed(PresentModeKHR *pPresentModes = presentModes) { VulkanSurface.SurfaceExtension.GetPhysicalDeviceSurfacePresentModes(physicalDevice.InternalHandle, surface.ApiHandle, &presentModesCount, pPresentModes); } var modes = presentModes.ToList(); if (!vsyncEnabled && modes.Contains(PresentModeKHR.PresentModeImmediateKhr)) { return(PresentModeKHR.PresentModeImmediateKhr); } else if (modes.Contains(PresentModeKHR.PresentModeMailboxKhr)) { return(PresentModeKHR.PresentModeMailboxKhr); } else if (modes.Contains(PresentModeKHR.PresentModeFifoKhr)) { return(PresentModeKHR.PresentModeFifoKhr); } else { return(PresentModeKHR.PresentModeImmediateKhr); } }