private bool IsPhysicalDeviceSuitable(VkPhysicalDevice physicalDevice) { QueueFamilyIndices indices = this.FindQueueFamilies(physicalDevice); bool extensionsSupported = this.CheckPhysicalDeviceExtensionSupport(physicalDevice); // acquire Raytracing features VkPhysicalDeviceRayTracingFeaturesKHR rayTracingFeatures = new VkPhysicalDeviceRayTracingFeaturesKHR() { sType = VkStructureType.VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_FEATURES_KHR, pNext = null, }; VkPhysicalDeviceFeatures2 deviceFeatures2 = new VkPhysicalDeviceFeatures2() { sType = VkStructureType.VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, pNext = &rayTracingFeatures, }; VulkanNative.vkGetPhysicalDeviceFeatures2(physicalDevice, &deviceFeatures2); extensionsSupported = extensionsSupported && rayTracingFeatures.rayTracing; bool swapChainAdequate = false; if (extensionsSupported) { SwapChainSupportDetails swapChainSupport = this.QuerySwapChainSupport(physicalDevice); swapChainAdequate = (swapChainSupport.formats.Length != 0 && swapChainSupport.presentModes.Length != 0); } return(indices.IsComplete() && extensionsSupported && swapChainAdequate); }
public GraphicsDevice(string applicationName, bool enableValidation, Window?window) { VkString name = applicationName; var appInfo = new VkApplicationInfo { sType = VkStructureType.ApplicationInfo, pApplicationName = name, applicationVersion = new VkVersion(1, 0, 0), pEngineName = s_EngineName, engineVersion = new VkVersion(1, 0, 0), apiVersion = vkEnumerateInstanceVersion() }; List <string> instanceExtensions = new List <string> { KHRSurfaceExtensionName }; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { instanceExtensions.Add(KHRWin32SurfaceExtensionName); } List <string> instanceLayers = new List <string>(); if (enableValidation) { FindValidationLayers(instanceLayers); } if (instanceLayers.Count > 0) { instanceExtensions.Add(EXTDebugUtilsExtensionName); } using var vkInstanceExtensions = new VkStringArray(instanceExtensions); var instanceCreateInfo = new VkInstanceCreateInfo { sType = VkStructureType.InstanceCreateInfo, pApplicationInfo = &appInfo, enabledExtensionCount = vkInstanceExtensions.Length, ppEnabledExtensionNames = vkInstanceExtensions }; using var vkLayerNames = new VkStringArray(instanceLayers); if (instanceLayers.Count > 0) { instanceCreateInfo.enabledLayerCount = vkLayerNames.Length; instanceCreateInfo.ppEnabledLayerNames = vkLayerNames; } var debugUtilsCreateInfo = new VkDebugUtilsMessengerCreateInfoEXT { sType = VkStructureType.DebugUtilsMessengerCreateInfoEXT }; if (instanceLayers.Count > 0) { _debugMessengerCallbackFunc = DebugMessengerCallback; debugUtilsCreateInfo.messageSeverity = VkDebugUtilsMessageSeverityFlagsEXT.Error | VkDebugUtilsMessageSeverityFlagsEXT.Warning; debugUtilsCreateInfo.messageType = VkDebugUtilsMessageTypeFlagsEXT.Validation | VkDebugUtilsMessageTypeFlagsEXT.Performance; debugUtilsCreateInfo.pfnUserCallback = Marshal.GetFunctionPointerForDelegate(_debugMessengerCallbackFunc); instanceCreateInfo.pNext = &debugUtilsCreateInfo; } VkResult result = vkCreateInstance(&instanceCreateInfo, null, out VkInstance); if (result != VkResult.Success) { throw new InvalidOperationException($"Failed to create vulkan instance: {result}"); } vkLoadInstance(VkInstance); if (instanceLayers.Count > 0) { vkCreateDebugUtilsMessengerEXT(VkInstance, &debugUtilsCreateInfo, null, out _debugMessenger).CheckResult(); } Log.Info($"Created VkInstance with version: {appInfo.apiVersion.Major}.{appInfo.apiVersion.Minor}.{appInfo.apiVersion.Patch}"); if (instanceLayers.Count > 0) { foreach (var layer in instanceLayers) { Log.Info($"Instance layer '{layer}'"); } } foreach (string extension in instanceExtensions) { Log.Info($"Instance extension '{extension}'"); } _surface = CreateSurface(window); // Find physical device, setup queue's and create device. var physicalDevices = vkEnumeratePhysicalDevices(VkInstance); foreach (var physicalDevice in physicalDevices) { //vkGetPhysicalDeviceProperties(physicalDevice, out var properties); //var deviceName = properties.GetDeviceName(); } PhysicalDevice = physicalDevices[0]; vkGetPhysicalDeviceProperties(PhysicalDevice, out VkPhysicalDeviceProperties properties); var queueFamilies = FindQueueFamilies(PhysicalDevice, _surface); var availableDeviceExtensions = vkEnumerateDeviceExtensionProperties(PhysicalDevice); var priority = 1.0f; var queueCreateInfo = new VkDeviceQueueCreateInfo { sType = VkStructureType.DeviceQueueCreateInfo, queueFamilyIndex = queueFamilies.graphicsFamily, queueCount = 1, pQueuePriorities = &priority }; List <string> deviceExtensions = new List <string> { KHRSwapchainExtensionName }; if (CheckDeviceExtensionSupport(KHRSpirv14ExtensionName, availableDeviceExtensions)) { deviceExtensions.Add(KHRSpirv14ExtensionName); } if (CheckDeviceExtensionSupport(KHRFragmentShadingRateExtensionName, availableDeviceExtensions)) { deviceExtensions.Add(KHRFragmentShadingRateExtensionName); } if (CheckDeviceExtensionSupport(NVMeshShaderExtensionName, availableDeviceExtensions)) { deviceExtensions.Add(NVMeshShaderExtensionName); } VkPhysicalDeviceVulkan11Features features_1_1 = new VkPhysicalDeviceVulkan11Features { sType = VkStructureType.PhysicalDeviceVulkan11Features }; VkPhysicalDeviceVulkan12Features features_1_2 = new VkPhysicalDeviceVulkan12Features { sType = VkStructureType.PhysicalDeviceVulkan12Features }; VkPhysicalDeviceFeatures2 deviceFeatures2 = new VkPhysicalDeviceFeatures2 { sType = VkStructureType.PhysicalDeviceFeatures2 }; deviceFeatures2.pNext = &features_1_1; features_1_1.pNext = &features_1_2; void **features_chain = &features_1_2.pNext; VkPhysicalDevice8BitStorageFeatures storage_8bit_features = default; if (properties.apiVersion <= VkVersion.Version_1_2) { if (CheckDeviceExtensionSupport(KHR8bitStorageExtensionName, availableDeviceExtensions)) { deviceExtensions.Add(KHR8bitStorageExtensionName); storage_8bit_features.sType = VkStructureType.PhysicalDevice8bitStorageFeatures; *features_chain = &storage_8bit_features; features_chain = &storage_8bit_features.pNext; } } VkPhysicalDeviceAccelerationStructureFeaturesKHR acceleration_structure_features = default; if (CheckDeviceExtensionSupport(KHRAccelerationStructureExtensionName, availableDeviceExtensions)) { deviceExtensions.Add(KHRAccelerationStructureExtensionName); acceleration_structure_features.sType = VkStructureType.PhysicalDeviceAccelerationStructureFeaturesKHR; *features_chain = &acceleration_structure_features; features_chain = &acceleration_structure_features.pNext; } vkGetPhysicalDeviceFeatures2(PhysicalDevice, out deviceFeatures2); using var deviceExtensionNames = new VkStringArray(deviceExtensions); var deviceCreateInfo = new VkDeviceCreateInfo { sType = VkStructureType.DeviceCreateInfo, pNext = &deviceFeatures2, queueCreateInfoCount = 1, pQueueCreateInfos = &queueCreateInfo, enabledExtensionCount = deviceExtensionNames.Length, ppEnabledExtensionNames = deviceExtensionNames, pEnabledFeatures = null, }; result = vkCreateDevice(PhysicalDevice, &deviceCreateInfo, null, out VkDevice); if (result != VkResult.Success) { throw new Exception($"Failed to create Vulkan Logical Device, {result}"); } vkGetDeviceQueue(VkDevice, queueFamilies.graphicsFamily, 0, out GraphicsQueue); vkGetDeviceQueue(VkDevice, queueFamilies.presentFamily, 0, out PresentQueue); // Create swap chain Swapchain = new Swapchain(this, window); _perFrame = new PerFrame[Swapchain.ImageCount]; for (var i = 0; i < _perFrame.Length; i++) { VkFenceCreateInfo fenceCreateInfo = new VkFenceCreateInfo(VkFenceCreateFlags.Signaled); vkCreateFence(VkDevice, &fenceCreateInfo, null, out _perFrame[i].QueueSubmitFence).CheckResult(); VkCommandPoolCreateInfo poolCreateInfo = new VkCommandPoolCreateInfo { sType = VkStructureType.CommandPoolCreateInfo, flags = VkCommandPoolCreateFlags.Transient, queueFamilyIndex = queueFamilies.graphicsFamily, }; vkCreateCommandPool(VkDevice, &poolCreateInfo, null, out _perFrame[i].PrimaryCommandPool).CheckResult(); VkCommandBufferAllocateInfo commandBufferInfo = new VkCommandBufferAllocateInfo { sType = VkStructureType.CommandBufferAllocateInfo, commandPool = _perFrame[i].PrimaryCommandPool, level = VkCommandBufferLevel.Primary, commandBufferCount = 1 }; vkAllocateCommandBuffers(VkDevice, &commandBufferInfo, out _perFrame[i].PrimaryCommandBuffer).CheckResult(); } }