Пример #1
0
        private HostDevice FindSuitableDevice(
            SurfaceKhr surface,
            HostDeviceRequirements deviceRequirements,
            bool preferDiscreteDevice = true)
        {
            ThrowIfDisposed();
            List <HostDevice> supportedDevices = new List <HostDevice>();

            //Find all devices that support the given surface
            for (int i = 0; i < hostDevices.Length; i++)
            {
                if (hostDevices[i].IsSurfaceSupported(surface) &&
                    hostDevices[i].AreRequirementsMet(deviceRequirements))
                {
                    supportedDevices.Add(hostDevices[i]);
                }
            }

            if (supportedDevices.IsEmpty())
            {
                throw new Exception($"[{nameof(Host)}] Unable to find a supported device");
            }

            //If we have a supported discreate gpu and we prefer a discrete one then we pick that
            for (int i = 0; i < supportedDevices.Count; i++)
            {
                if (supportedDevices[i].IsDiscreteGPU == preferDiscreteDevice)
                {
                    return(supportedDevices[i]);
                }
            }

            return(supportedDevices[0]);
        }
Пример #2
0
        internal Window(
            string title,
            INativeWindow nativeWindow,
            SurfaceKhr surface,
            HostDevice hostDevice,
            HostDeviceRequirements deviceRequirements,
            Logger logger = null)
        {
            if (nativeWindow == null)
            {
                throw new ArgumentNullException(nameof(nativeWindow));
            }
            if (surface == null)
            {
                throw new ArgumentNullException(nameof(surface));
            }
            if (hostDevice == null)
            {
                throw new ArgumentNullException(nameof(hostDevice));
            }
            this.title        = title;
            this.nativeWindow = nativeWindow;
            this.surface      = surface;
            this.hostDevice   = hostDevice;
            this.logger       = logger;

            //Subscribe to callbacks for the native window
            nativeWindow.CloseRequested += OnNativeWindowCloseRequested;
            nativeWindow.Resized        += OnNativeWindowResized;

            //Create a logical device (and queues on the device)
            IList <string> enabledExtensions;

            (logicalDevice, graphicsQueue, presentQueue, enabledExtensions) = hostDevice.CreateLogicalDevice(
                surface: surface,
                deviceRequirements: deviceRequirements);
            hasDebugMarkerExtension = enabledExtensions.Contains("VK_EXT_debug_marker");
            if (hasDebugMarkerExtension)
            {
                logger?.Log(nameof(Window), "Enabled debug-markers");
            }

            //Get a presentmode to use
            presentMode = hostDevice.GetPresentMode(surface);
            //Get the surfaceformat to use
            (surfaceFormat, surfaceColorspace) = hostDevice.GetSurfaceFormat(surface);
            //Gets how many swapchain images we should use
            swapchainCount = hostDevice.GetSwapchainCount(surface);

            //Create a command-pool attached to this device
            commandPool = logicalDevice.CreateCommandPool(new CommandPoolCreateInfo(
                                                              queueFamilyIndex: graphicsQueue.FamilyIndex,
                                                              flags: CommandPoolCreateFlags.None
                                                              ));

            //Create the swapchain (images to present to the screen)
            CreateSwapchain(swapchainCount);
            //Synchronization objects are used to sync the rendering and presenting
            CreateSynchronizationObjects();
        }
Пример #3
0
        public Window CreateWindow(
            Int2 windowSize,
            HostDeviceRequirements deviceRequirements,
            bool preferDiscreteDevice = true)
        {
            ThrowIfDisposed();
            INativeWindow nativeWindow = nativeApp.CreateWindow(
                size: windowSize,
                minSize: (x: 150, y: 150),
                title: string.Empty);
            SurfaceKhr surface        = CreateSurface(nativeWindow);
            HostDevice graphicsDevice = FindSuitableDevice(
                surface,
                deviceRequirements,
                preferDiscreteDevice);

            return(new Window(
                       title: $"{appName} - {appVersion}",
                       nativeWindow, surface, graphicsDevice, deviceRequirements, logger));
        }
 internal bool AreRequirementsMet(HostDeviceRequirements requirements)
 => requirements.DoesSupportRequirements(supportedFeatures);
        internal (Device logicalDevice, Queue graphicsQueue, Queue presentQueue, IList <string>) CreateLogicalDevice(
            SurfaceKhr surface, HostDeviceRequirements deviceRequirements)
        {
            if (!AreRequirementsMet(deviceRequirements))
            {
                throw new Exception(
                          $"[{nameof(HostDevice)}] Device '{Name}' does not support all device-requirements");
            }

            string[] requiredExtensions = GetRequiredExtensions(surfaceType);
            if (!AreExtensionsAvailable(requiredExtensions))
            {
                throw new Exception(
                          $"[{nameof(HostDevice)}] Device '{Name}' does not support required extensions");
            }
            var extensionsToEnable = new List <string>(requiredExtensions);

            //Add any optional extensions IF its supported by this host
            string[] optionalExtensions = GetOptionalExtensions(surfaceType);
            for (int i = 0; i < optionalExtensions.Length; i++)
            {
                if (IsExtensionAvailable(optionalExtensions[i]))
                {
                    extensionsToEnable.Add(optionalExtensions[i]);
                }
            }

            int?graphicsQueueFamilyIndex = GetGraphicsQueueFamilyIndex();

            if (graphicsQueueFamilyIndex == null)
            {
                throw new Exception(
                          $"[{nameof(HostDevice)}] Device '{Name}' does not support graphics");
            }

            int?presentQueueFamilyIndex = GetPresentQueueFamilyIndex(surface);

            if (presentQueueFamilyIndex == null)
            {
                throw new Exception(
                          $"[{nameof(HostDevice)}] Device '{Name}' does not support presenting to the given surface");
            }

            List <VulkanCore.DeviceQueueCreateInfo> queueCreateInfos = new List <DeviceQueueCreateInfo>();

            queueCreateInfos.Add(new VulkanCore.DeviceQueueCreateInfo(
                                     graphicsQueueFamilyIndex.Value, queueCount: 1, queuePriorities: 1f));
            //If the present queue and graphics queues are not the same we also need to create a present queue
            if (graphicsQueueFamilyIndex.Value != presentQueueFamilyIndex.Value)
            {
                queueCreateInfos.Add(new VulkanCore.DeviceQueueCreateInfo(
                                         presentQueueFamilyIndex.Value, queueCount: 1, queuePriorities: 1f));
            }

            VulkanCore.DeviceCreateInfo createInfo = new VulkanCore.DeviceCreateInfo(
                queueCreateInfos: queueCreateInfos.ToArray(),
                enabledExtensionNames: extensionsToEnable.ToArray(),
                enabledFeatures: deviceRequirements.GetRequiredFeatures()
                );
            Device logicalDevice = physicalDevice.CreateDevice(createInfo);
            Queue  graphicsQueue = logicalDevice.GetQueue(graphicsQueueFamilyIndex.Value, queueIndex: 0);
            Queue  presentQueue  = logicalDevice.GetQueue(presentQueueFamilyIndex.Value, queueIndex: 0);

            logger?.Log(nameof(HostDevice), $"Created logical-device ({Name})");
            logger?.LogList(nameof(HostDevice), $"Enabled extensions for logical-device:", extensionsToEnable);

            //Note: If we are running on molten-vk then we can set some specific mvk device config
            if (extensionsToEnable.Contains("VK_MVK_moltenvk"))
            {
                var deviceConfig = logicalDevice.GetMVKDeviceConfiguration();
                deviceConfig.DebugMode                    = DebugUtils.IS_DEBUG;
                deviceConfig.PerformanceTracking          = DebugUtils.IS_DEBUG;
                deviceConfig.PerformanceLoggingFrameCount = DebugUtils.IS_DEBUG ? 300 : 0;
                logicalDevice.SetMVKDeviceConfiguration(deviceConfig);
            }

            return(logicalDevice, graphicsQueue, presentQueue, extensionsToEnable);
        }