Exemplo n.º 1
0
        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;
                        }
                    }
                }
            }
        }
Exemplo n.º 2
0
        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();
        }
Exemplo n.º 3
0
        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;
                        }
                    }
                }
            }
        }
Exemplo n.º 4
0
        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);
        }
Exemplo n.º 5
0
 public VkResult CreateWin32SurfaceKHR(VkWin32SurfaceCreateInfoKHR pCreateInfo, out VkSurfaceKHR pSurface)
 {
     return(SoftwareSurfaceFactory.Create(this, pCreateInfo, out pSurface));
 }
Exemplo n.º 6
0
 public static VkResult Create(SoftwareInstance instance, VkWin32SurfaceCreateInfoKHR createInfo, out VkSurfaceKHR pSurface)
 {
     pSurface = new SoftwareFormSurface(instance, createInfo);
     return(VkResult.VK_SUCCESS);
 }
Exemplo n.º 7
0
            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();
            }