public unsafe void InitSurface(IntPtr sdlWindow) { SDL_version version; SDL_GetVersion(&version); SDL_SysWMinfo sysWmInfo; sysWmInfo.version = version; int result = SDL_GetWMWindowInfo(sdlWindow, &sysWmInfo); if (result == 0) { throw new InvalidOperationException("Couldn't retrieve SDL window info."); } VkResult err; if (sysWmInfo.subsystem == SysWMType.Windows) { Win32WindowInfo win32Info = Unsafe.Read <Win32WindowInfo>(&sysWmInfo.info); // Create the os-specific Surface VkWin32SurfaceCreateInfoKHR surfaceCreateInfo = VkWin32SurfaceCreateInfoKHR.New(); var processHandle = Process.GetCurrentProcess().SafeHandle.DangerousGetHandle(); surfaceCreateInfo.hinstance = processHandle; surfaceCreateInfo.hwnd = win32Info.Sdl2Window; VkSurfaceKHR surface; err = vkCreateWin32SurfaceKHR(Instance, &surfaceCreateInfo, null, &surface); Surface = surface; } else if (sysWmInfo.subsystem == SysWMType.X11) { X11WindowInfo x11Info = Unsafe.Read <X11WindowInfo>(&sysWmInfo.info); VkXlibSurfaceCreateInfoKHR surfaceCreateInfo = VkXlibSurfaceCreateInfoKHR.New(); surfaceCreateInfo.dpy = (Vulkan.Xlib.Display *)x11Info.display; surfaceCreateInfo.window = new Vulkan.Xlib.Window { Value = x11Info.Sdl2Window }; VkSurfaceKHR surface; err = vkCreateXlibSurfaceKHR(Instance, &surfaceCreateInfo, null, out surface); Surface = surface; } else { throw new NotImplementedException($"SDL backend not implemented: {sysWmInfo.subsystem}."); } // Get available queue family properties uint queueCount; vkGetPhysicalDeviceQueueFamilyProperties(PhysicalDevice, &queueCount, null); Debug.Assert(queueCount >= 1); using (NativeList <VkQueueFamilyProperties> queueProps = new NativeList <VkQueueFamilyProperties>(queueCount)) { vkGetPhysicalDeviceQueueFamilyProperties(PhysicalDevice, &queueCount, (VkQueueFamilyProperties *)queueProps.Data.ToPointer()); queueProps.Count = queueCount; // Iterate over each queue to learn whether it supports presenting: // Find a queue with present support // Will be used to present the swap chain Images to the windowing system VkBool32 *supportsPresent = stackalloc VkBool32[(int)queueCount]; for (uint i = 0; i < queueCount; i++) { vkGetPhysicalDeviceSurfaceSupportKHR(PhysicalDevice, i, Surface, &supportsPresent[i]); Console.WriteLine("supports: " + supportsPresent[i].ToString()); } // Search for a graphics and a present queue in the array of queue // families, try to find one that supports both uint graphicsQueueNodeIndex = uint.MaxValue; uint presentQueueNodeIndex = uint.MaxValue; for (uint i = 0; i < queueCount; i++) { if ((queueProps[i].queueFlags & VkQueueFlags.Graphics) != 0) { if (graphicsQueueNodeIndex == uint.MaxValue) { graphicsQueueNodeIndex = i; } if (supportsPresent[i] == True) { graphicsQueueNodeIndex = i; presentQueueNodeIndex = i; break; } } } if (presentQueueNodeIndex == uint.MaxValue) { // If there's no queue that supports both present and graphics // try to find a separate present queue for (uint i = 0; i < queueCount; ++i) { if (supportsPresent[i] == True) { presentQueueNodeIndex = i; break; } } } // Exit if either a graphics or a presenting queue hasn't been found if (graphicsQueueNodeIndex == uint.MaxValue || presentQueueNodeIndex == uint.MaxValue) { throw new InvalidOperationException("Could not find a graphics and/or presenting queue!"); } // todo : Add support for separate graphics and presenting queue if (graphicsQueueNodeIndex != presentQueueNodeIndex) { throw new InvalidOperationException("Separate graphics and presenting queues are not supported yet!"); } QueueNodeIndex = graphicsQueueNodeIndex; // Get list of supported Surface formats uint formatCount; err = vkGetPhysicalDeviceSurfaceFormatsKHR(PhysicalDevice, Surface, &formatCount, null); Debug.Assert(err == VkResult.Success); Debug.Assert(formatCount > 0); using (NativeList <VkSurfaceFormatKHR> surfaceFormats = new NativeList <VkSurfaceFormatKHR>(formatCount)) { err = vkGetPhysicalDeviceSurfaceFormatsKHR(PhysicalDevice, Surface, &formatCount, (VkSurfaceFormatKHR *)surfaceFormats.Data.ToPointer()); surfaceFormats.Count = formatCount; Debug.Assert(err == VkResult.Success); // If the Surface format list only includes one entry with VK_FORMAT_UNDEFINED, // there is no preferered format, so we assume VK_FORMAT_B8G8R8A8_UNORM if ((formatCount == 1) && (surfaceFormats[0].format == VkFormat.Undefined)) { ColorFormat = VkFormat.B8g8r8a8Unorm; ColorSpace = surfaceFormats[0].colorSpace; } else { // iterate over the list of available Surface format and // check for the presence of VK_FORMAT_B8G8R8A8_UNORM bool found_B8G8R8A8_UNORM = false; foreach (var surfaceFormat in surfaceFormats) { if (surfaceFormat.format == VkFormat.B8g8r8a8Unorm) { ColorFormat = surfaceFormat.format; ColorSpace = surfaceFormat.colorSpace; found_B8G8R8A8_UNORM = true; break; } } // in case VK_FORMAT_B8G8R8A8_UNORM is not available // select the first available color format if (!found_B8G8R8A8_UNORM) { ColorFormat = surfaceFormats[0].format; ColorSpace = surfaceFormats[0].colorSpace; } } } } }
public static IntPtr CreateWindowSurface(IntPtr vulkanInstance, NativeWindowBase window) { EnsureInit(); if (OperatingSystem.IsWindows() && IsExtensionPresent("VK_KHR_win32_surface")) { vkCreateWin32SurfaceKHRDelegate vkCreateWin32SurfaceKHR = Marshal.GetDelegateForFunctionPointer <vkCreateWin32SurfaceKHRDelegate>(_vkGetInstanceProcAddr(vulkanInstance, "vkCreateWin32SurfaceKHR")); VkWin32SurfaceCreateInfoKHR creationInfo = new VkWin32SurfaceCreateInfoKHR { StructType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, Next = IntPtr.Zero, Flags = 0, // Broken warning here there is no platform issues here... #pragma warning disable CA1416 HInstance = Win32.GetWindowLong(window.WindowHandle.RawHandle, Win32.GetWindowLongIndex.GWL_HINSTANCE), #pragma warning restore CA1416 Hwnd = window.WindowHandle.RawHandle }; int res = vkCreateWin32SurfaceKHR(vulkanInstance, ref creationInfo, IntPtr.Zero, out IntPtr surface); if (res != 0) { throw new PlatformException($"vkCreateWin32SurfaceKHR failed: {res}"); } return(surface); } if (OperatingSystem.IsLinux()) { if (IsExtensionPresent("VK_KHR_xcb_surface")) { vkCreateXcbSurfaceKHRDelegate vkCreateXcbSurfaceKHR = Marshal.GetDelegateForFunctionPointer <vkCreateXcbSurfaceKHRDelegate>(_vkGetInstanceProcAddr(vulkanInstance, "vkCreateXcbSurfaceKHR")); VkXcbSurfaceCreateInfoKHR creationInfo = new VkXcbSurfaceCreateInfoKHR { StructType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR, Next = IntPtr.Zero, Flags = 0, Connection = X11.GetXCBConnection(window.DisplayHandle.RawHandle), Window = window.WindowHandle.RawHandle }; int res = vkCreateXcbSurfaceKHR(vulkanInstance, ref creationInfo, IntPtr.Zero, out IntPtr surface); if (res != 0) { throw new PlatformException($"vkCreateXcbSurfaceKHR failed: {res}"); } return(surface); } else { vkCreateXlibSurfaceKHRDelegate vkCreateXlibSurfaceKHR = Marshal.GetDelegateForFunctionPointer <vkCreateXlibSurfaceKHRDelegate>(_vkGetInstanceProcAddr(vulkanInstance, "vkCreateXlibSurfaceKHR")); VkXlibSurfaceCreateInfoKHR creationInfo = new VkXlibSurfaceCreateInfoKHR { StructType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, Next = IntPtr.Zero, Flags = 0, Display = window.DisplayHandle.RawHandle, Window = window.WindowHandle.RawHandle }; int res = vkCreateXlibSurfaceKHR(vulkanInstance, ref creationInfo, IntPtr.Zero, out IntPtr surface); if (res != 0) { throw new PlatformException($"vkCreateXlibSurfaceKHR failed: {res}"); } return(surface); } } throw new NotImplementedException(); }
public void InitSurface(IntPtr platformHandle, IntPtr platformWindow) { VkResult err; // Create the os-specific Surface VkWin32SurfaceCreateInfoKHR surfaceCreateInfo = VkWin32SurfaceCreateInfoKHR.New(); surfaceCreateInfo.hinstance = platformHandle; surfaceCreateInfo.hwnd = platformWindow; VkSurfaceKHR surface; err = vkCreateWin32SurfaceKHR(Instance, &surfaceCreateInfo, null, &surface); Surface = surface; // Get available queue family properties uint queueCount; vkGetPhysicalDeviceQueueFamilyProperties(PhysicalDevice, &queueCount, null); Debug.Assert(queueCount >= 1); using (NativeList <VkQueueFamilyProperties> queueProps = new NativeList <VkQueueFamilyProperties>(queueCount)) { vkGetPhysicalDeviceQueueFamilyProperties(PhysicalDevice, &queueCount, (VkQueueFamilyProperties *)queueProps.Data.ToPointer()); queueProps.Count = queueCount; // Iterate over each queue to learn whether it supports presenting: // Find a queue with present support // Will be used to present the swap chain Images to the windowing system uint *supportsPresent = stackalloc uint[(int)queueCount]; for (uint i = 0; i < queueCount; i++) { vkGetPhysicalDeviceSurfaceSupportKHR(PhysicalDevice, i, Surface, &supportsPresent[i]); } // Search for a graphics and a present queue in the array of queue // families, try to find one that supports both uint graphicsQueueNodeIndex = uint.MaxValue; uint presentQueueNodeIndex = uint.MaxValue; for (uint i = 0; i < queueCount; i++) { if ((queueProps[i].queueFlags & VkQueueFlags.Graphics) != 0) { if (graphicsQueueNodeIndex == uint.MaxValue) { graphicsQueueNodeIndex = i; } if (supportsPresent[i] == True) { graphicsQueueNodeIndex = i; presentQueueNodeIndex = i; break; } } } if (presentQueueNodeIndex == uint.MaxValue) { // If there's no queue that supports both present and graphics // try to find a separate present queue for (uint i = 0; i < queueCount; ++i) { if (supportsPresent[i] == True) { presentQueueNodeIndex = i; break; } } } // Exit if either a graphics or a presenting queue hasn't been found if (graphicsQueueNodeIndex == uint.MaxValue || presentQueueNodeIndex == uint.MaxValue) { throw new InvalidOperationException("Could not find a graphics and/or presenting queue!"); } // todo : Add support for separate graphics and presenting queue if (graphicsQueueNodeIndex != presentQueueNodeIndex) { throw new InvalidOperationException("Separate graphics and presenting queues are not supported yet!"); } QueueNodeIndex = graphicsQueueNodeIndex; // Get list of supported Surface formats uint formatCount; err = vkGetPhysicalDeviceSurfaceFormatsKHR(PhysicalDevice, Surface, &formatCount, null); Debug.Assert(err == VkResult.Success); Debug.Assert(formatCount > 0); using (NativeList <VkSurfaceFormatKHR> surfaceFormats = new NativeList <VkSurfaceFormatKHR>(formatCount)) { err = vkGetPhysicalDeviceSurfaceFormatsKHR(PhysicalDevice, Surface, &formatCount, (VkSurfaceFormatKHR *)surfaceFormats.Data.ToPointer()); surfaceFormats.Count = formatCount; Debug.Assert(err == VkResult.Success); // If the Surface format list only includes one entry with VK_FORMAT_UNDEFINED, // there is no preferered format, so we assume VK_FORMAT_B8G8R8A8_UNORM if ((formatCount == 1) && (surfaceFormats[0].format == VkFormat.Undefined)) { ColorFormat = VkFormat.B8g8r8a8Unorm; ColorSpace = surfaceFormats[0].colorSpace; } else { // iterate over the list of available Surface format and // check for the presence of VK_FORMAT_B8G8R8A8_UNORM bool found_B8G8R8A8_UNORM = false; foreach (var surfaceFormat in surfaceFormats) { if (surfaceFormat.format == VkFormat.B8g8r8a8Unorm) { ColorFormat = surfaceFormat.format; ColorSpace = surfaceFormat.colorSpace; found_B8G8R8A8_UNORM = true; break; } } // in case VK_FORMAT_B8G8R8A8_UNORM is not available // select the first available color format if (!found_B8G8R8A8_UNORM) { ColorFormat = surfaceFormats[0].format; ColorSpace = surfaceFormats[0].colorSpace; } } } } }
private ulong CreateSurface() { ulong surface; VkResult result; var graphicsProvider = (GraphicsProvider)_graphicsAdapter.GraphicsProvider; switch (_graphicsSurface.Kind) { case GraphicsSurfaceKind.Win32: { var surfaceCreateInfo = new VkWin32SurfaceCreateInfoKHR { sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, pNext = null, flags = 0, hinstance = _graphicsSurface.DisplayHandle, hwnd = _graphicsSurface.WindowHandle, }; result = vkCreateWin32SurfaceKHR(graphicsProvider.Instance, &surfaceCreateInfo, pAllocator: null, &surface); if (result != VK_SUCCESS) { ThrowExternalException(nameof(vkCreateWin32SurfaceKHR), (int)result); } break; } case GraphicsSurfaceKind.Xlib: { var surfaceCreateInfo = new VkXlibSurfaceCreateInfoKHR { sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, pNext = null, flags = 0, dpy = (UIntPtr)(void *)_graphicsSurface.DisplayHandle, window = (UIntPtr)(void *)_graphicsSurface.WindowHandle, }; result = vkCreateXlibSurfaceKHR(graphicsProvider.Instance, &surfaceCreateInfo, pAllocator: null, &surface); if (result != VK_SUCCESS) { ThrowExternalException(nameof(vkCreateXlibSurfaceKHR), (int)result); } break; } default: { ThrowArgumentOutOfRangeException(nameof(_graphicsSurface), _graphicsSurface); surface = VK_NULL_HANDLE; break; } } uint supported; result = vkGetPhysicalDeviceSurfaceSupportKHR(_graphicsAdapter.PhysicalDevice, GraphicsQueueFamilyIndex, surface, &supported); if (supported == VK_FALSE) { ThrowArgumentOutOfRangeException(nameof(_graphicsSurface), _graphicsSurface); } return(surface); }
public VkResult CreateWin32SurfaceKHR(VkWin32SurfaceCreateInfoKHR pCreateInfo, out VkSurfaceKHR pSurface) { return(SoftwareSurfaceFactory.Create(this, pCreateInfo, out pSurface)); }
public static VkResult Create(SoftwareInstance instance, VkWin32SurfaceCreateInfoKHR createInfo, out VkSurfaceKHR pSurface) { pSurface = new SoftwareFormSurface(instance, createInfo); return(VkResult.VK_SUCCESS); }
protected override void Initialize() { var result = vkInitialize(); result.CheckResult(); var version = vkEnumerateInstanceVersion(); var queryExtensions = vkEnumerateInstanceExtensionProperties(); var queryLayers = vkEnumerateInstanceLayerProperties(); VkString name = "01-ClearScreen"; 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 = VkVersion.Version_1_0, }; var instanceExtensions = new List <string> { KHRSurfaceExtensionName, KHRWin32SurfaceExtensionName }; var instanceLayers = new List <string>(); if (EnableValidationLayers) { 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; } result = vkCreateInstance(&instanceCreateInfo, null, out instance); vkLoadInstance(instance); if (instanceLayers.Count > 0) { _debugMessengerCallbackFunc = DebugMessengerCallback; var debugCreateInfo = new VkDebugUtilsMessengerCreateInfoEXT { sType = VkStructureType.DebugUtilsMessengerCreateInfoEXT, messageSeverity = /*VkDebugUtilsMessageSeverityFlagsEXT.VerboseEXT | */ VkDebugUtilsMessageSeverityFlagsEXT.ErrorEXT | VkDebugUtilsMessageSeverityFlagsEXT.WarningEXT, messageType = VkDebugUtilsMessageTypeFlagsEXT.GeneralEXT | VkDebugUtilsMessageTypeFlagsEXT.ValidationEXT | VkDebugUtilsMessageTypeFlagsEXT.PerformanceEXT, pfnUserCallback = Marshal.GetFunctionPointerForDelegate(_debugMessengerCallbackFunc) }; vkCreateDebugUtilsMessengerEXT(instance, &debugCreateInfo, null, out debugMessenger).CheckResult(); } var surfaceCreateInfo = new VkWin32SurfaceCreateInfoKHR { sType = VkStructureType.Win32SurfaceCreateInfoKHR, hinstance = HInstance, hwnd = MainWindow.Handle }; result = vkCreateWin32SurfaceKHR(instance, &surfaceCreateInfo, null, out surface); var physicalDevices = vkEnumeratePhysicalDevices(instance); foreach (var physicalDevice in physicalDevices) { vkGetPhysicalDeviceProperties(physicalDevice, out var properties); var deviceName = properties.GetDeviceName(); } physicalDevice = physicalDevices[0]; var queueFamilies = FindQueueFamilies(physicalDevice, surface); 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 }; var deviceCreateInfo = new VkDeviceCreateInfo { sType = VkStructureType.DeviceCreateInfo, pQueueCreateInfos = &queueCreateInfo, queueCreateInfoCount = 1, pEnabledFeatures = null, }; using var deviceExtensionNames = new VkStringArray(deviceExtensions); deviceCreateInfo.enabledExtensionCount = deviceExtensionNames.Length; deviceCreateInfo.ppEnabledExtensionNames = deviceExtensionNames; result = vkCreateDevice(physicalDevice, &deviceCreateInfo, null, out device); if (result != VkResult.Success) { throw new Exception($"Failed to create Vulkan Logical Device, {result}"); } vkGetDeviceQueue(device, queueFamilies.graphicsFamily, 0, out graphicsQueue); vkGetDeviceQueue(device, queueFamilies.presentFamily, 0, out presentQueue); CreateSwapchain(); CreateSyncPrimitives(); }