Пример #1
0
        public unsafe QueueFamilyIndices(VkPhysicalDevice device, VkSurfaceKHR surface)
        {
            int graphicsIndex = -1;
            int presentIndex  = -1;

            uint queueFamilyCount = 0;

            VulkanNative.vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, null);
            VkQueueFamilyProperties *queueFamilies = stackalloc VkQueueFamilyProperties[(int)queueFamilyCount];

            VulkanNative.vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies);

            for (int i = 0; i < queueFamilyCount; i++)
            {
                var q = queueFamilies[i];

                if (q.queueCount > 0 && (q.queueFlags & VkQueueFlagBits.VK_QUEUE_GRAPHICS_BIT) != 0)
                {
                    graphicsIndex = i;
                }

                VkBool32 presentSupported = false;
                VkResult result           = VulkanNative.vkGetPhysicalDeviceSurfaceSupportKHR(device, (uint)i, surface, &presentSupported);
                Helpers.CheckErrors(result);
                if (presentIndex < 0 && q.queueCount > 0 && presentSupported)
                {
                    presentIndex = i;
                }
            }

            GraphicsFamily = graphicsIndex;
            PresentFamily  = presentIndex;
        }
Пример #2
0
        internal void CreateQueueFamilyProperties()
        {
            VkPhysicalDevice physicalDevice = NativeAdapter.NativePhysicalDevice;

            uint Count = 0;

            vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, ref Count, null);

            VkQueueFamilyProperties *queueFamilyProperties = stackalloc VkQueueFamilyProperties[(int)Count];

            vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &Count, queueFamilyProperties);

            for (int i = 0; i < Count; i++)
            {
                QueueFamilyProperties.Add(queueFamilyProperties[i]);
            }
        }
Пример #3
0
        private bool TryGetQueueFamilyIndex(VkPhysicalDevice device, VkQueueFlags flag, out uint index)
        {
            index = 0;

            uint queueFamilyCount = 0;

            VK.GetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, null);

            VkQueueFamilyProperties *queueFamilies = stackalloc VkQueueFamilyProperties[(int)queueFamilyCount];

            VK.GetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies);

            for (int i = 0; i < queueFamilyCount; i++)
            {
                if (queueFamilies[i].queueFlags.HasFlag(flag))
                {
                    index = (uint)i;
                    return(true);
                }
            }

            return(false);
        }
Пример #4
0
        private QueueFamilyIndices FindQueueFamilies(VkPhysicalDevice physicalDevice)
        {
            QueueFamilyIndices indices = default;

            uint queueFamilyCount = 0;

            VulkanNative.vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, null);

            VkQueueFamilyProperties *queueFamilies = stackalloc VkQueueFamilyProperties[(int)queueFamilyCount];

            VulkanNative.vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, queueFamilies);

            for (uint i = 0; i < queueFamilyCount; i++)
            {
                var queueFamily = queueFamilies[i];
                if ((queueFamily.queueFlags & VkQueueFlags.VK_QUEUE_GRAPHICS_BIT) != 0)
                {
                    indices.graphicsFamily = i;
                }

                VkBool32 presentSupport = false;
                Helpers.CheckErrors(VulkanNative.vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, i, this.surface, &presentSupport));

                if (presentSupport)
                {
                    indices.presentFamily = i;
                }

                if (indices.IsComplete())
                {
                    break;
                }
            }

            return(indices);
        }
Пример #5
0
 internal extern static unsafe void vkGetPhysicalDeviceQueueFamilyProperties(IntPtr physicalDevice, UInt32 *pQueueFamilyPropertyCount, VkQueueFamilyProperties *pQueueFamilyProperties);
Пример #6
0
        public VulkanContext(VkInstance instance, VkSurfaceKHR surface, Platform platform)
        {
            // Find graphics and presentation capable physical device(s) that support
            // the provided surface for platform.
            int graphicsQueueFamilyIndex = -1;
            int computeQueueFamilyIndex  = -1;
            int presentQueueFamilyIndex  = -1;

            var physicalDevices = vkEnumeratePhysicalDevices(instance);

            foreach (var physicalDevice in physicalDevices)
            {
                uint Count = 0;

                vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &Count, null);
                VkQueueFamilyProperties *queueFamilyPropertiesptr = stackalloc VkQueueFamilyProperties[(int)Count];

                vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &Count, queueFamilyPropertiesptr);

                for (int i = 0; i < Count; i++)
                {
                    if (queueFamilyPropertiesptr[i].queueFlags.HasFlag(VkQueueFlags.Graphics))
                    {
                        if (graphicsQueueFamilyIndex == -1)
                        {
                            graphicsQueueFamilyIndex = i;
                        }
                        if (computeQueueFamilyIndex == -1)
                        {
                            computeQueueFamilyIndex = i;
                        }

                        VkBool32 isSupported;
                        uint     queueFamilyIndex = (uint)i;
                        VkResult result           = vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface, out isSupported);
                        result.CheckResult();

                        if (isSupported == VkBool32.True)
                        {
                            bool presentationSupport = false;
                            if (platform == Platform.Win32)
                            {
                                presentationSupport = vkGetPhysicalDeviceWin32PresentationSupportKHR(physicalDevice, queueFamilyIndex);
                            }
                            else
                            {
                                presentationSupport = true;
                            }

                            if (presentationSupport)
                            {
                                presentQueueFamilyIndex = i;
                            }
                        }

                        if (graphicsQueueFamilyIndex != -1 &&
                            computeQueueFamilyIndex != -1 &&
                            presentQueueFamilyIndex != -1)
                        {
                            PhysicalDevice = physicalDevice;
                            break;
                        }
                    }
                }
                if (PhysicalDevice != null)
                {
                    break;
                }
            }

            if (PhysicalDevice == null)
            {
                throw new InvalidOperationException("No suitable physical device found.");
            }

            vkGetPhysicalDeviceMemoryProperties(PhysicalDevice, out VkPhysicalDeviceMemoryProperties memoryProperties);
            MemoryProperties = memoryProperties;
            vkGetPhysicalDeviceFeatures(PhysicalDevice, out VkPhysicalDeviceFeatures features);
            Features = features;
            vkGetPhysicalDeviceProperties(PhysicalDevice, out VkPhysicalDeviceProperties physicalDeviceProperties);
            Properties = physicalDeviceProperties;

            // Create a logical device.
            bool sameGraphicsAndPresent = graphicsQueueFamilyIndex == presentQueueFamilyIndex;
            VkDeviceQueueCreateInfo *queueCreateInfos = stackalloc VkDeviceQueueCreateInfo[sameGraphicsAndPresent ? 1 : 2];

            float defaultQueuePriority = 1.0f;

            VkDeviceQueueCreateInfo queueInfoGraphics = new VkDeviceQueueCreateInfo
            {
                sType            = VkStructureType.DeviceQueueCreateInfo,
                queueFamilyIndex = (uint)graphicsQueueFamilyIndex,
                queueCount       = 1,
                pQueuePriorities = &defaultQueuePriority
            };

            queueCreateInfos[0] = queueInfoGraphics;

            if (!sameGraphicsAndPresent)
            {
                queueCreateInfos[1] = new VkDeviceQueueCreateInfo
                {
                    sType            = VkStructureType.DeviceQueueCreateInfo,
                    queueFamilyIndex = (uint)presentQueueFamilyIndex,
                    queueCount       = 1,
                    pQueuePriorities = &defaultQueuePriority
                };
            }

            VkDeviceCreateInfo deviceCreateInfo = new VkDeviceCreateInfo
            {
                sType = VkStructureType.DeviceCreateInfo,
                pNext = null,
                flags = VkDeviceCreateFlags.None,
                queueCreateInfoCount = (uint)(sameGraphicsAndPresent ? 1 : 2),
                pQueueCreateInfos    = queueCreateInfos,
            };

            deviceCreateInfo.pEnabledFeatures = &features;

            string[] deviceExtensions = new[] {
                // If the device will be used for presenting to a display via a swapchain we need to request the swapchain extension
                "VK_KHR_swapchain"
            };

            deviceCreateInfo.enabledExtensionCount   = (uint)deviceExtensions.Length;
            deviceCreateInfo.ppEnabledExtensionNames = Interop.String.AllocToPointers(deviceExtensions);

            VkResult result2 = vkCreateDevice(PhysicalDevice, &deviceCreateInfo, null, out VkDevice device);

            result2.CheckResult();

            Device = device;

            // Get queue(s).
            GraphicsQueue = GetQueue((uint)graphicsQueueFamilyIndex);
            ComputeQueue  = computeQueueFamilyIndex == graphicsQueueFamilyIndex
                ? GraphicsQueue
                : GetQueue((uint)computeQueueFamilyIndex);
            PresentQueue = presentQueueFamilyIndex == graphicsQueueFamilyIndex
                ? GraphicsQueue
                : GetQueue((uint)presentQueueFamilyIndex);

            GraphicsQueueFamilyIndex = graphicsQueueFamilyIndex;
            PresentQueueFamilyIndex  = presentQueueFamilyIndex;
            ComputeQueueFamilyIndex  = presentQueueFamilyIndex;

            GraphicsCommandPool = CreateCommandPool((uint)graphicsQueueFamilyIndex);
            ComputeCommandPool  = CreateCommandPool((uint)computeQueueFamilyIndex);
        }
Пример #7
0
        public void CreateSwapChain()
        {
            var PhysicalDevice = NativeDevice.NativeAdapter.NativePhysicalDevice;

            var width = Parameters.BackBufferWidth;

            var height = Parameters.BackBufferHeight;

            var vsync = Parameters.Settings.VSync;


            // Get available queue family properties
            uint queueCount;

            vkGetPhysicalDeviceQueueFamilyProperties(PhysicalDevice, &queueCount, null);
            VkQueueFamilyProperties *queueProps = stackalloc VkQueueFamilyProperties[(int)queueCount];

            vkGetPhysicalDeviceQueueFamilyProperties(PhysicalDevice, &queueCount, queueProps);



            // 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]);
            }



            // 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] == 1)
                    {
                        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] == 1)
                    {
                        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!");
            }



            // Get list of supported Surface formats
            uint formatCount;

            vkGetPhysicalDeviceSurfaceFormatsKHR(PhysicalDevice, Surface, &formatCount, null);
            VkSurfaceFormatKHR *surfaceFormats = stackalloc VkSurfaceFormatKHR[(int)formatCount];

            vkGetPhysicalDeviceSurfaceFormatsKHR(PhysicalDevice, Surface, &formatCount, surfaceFormats);



            // 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))
            {
                VkColorFormat = 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;

                List <VkSurfaceFormatKHR> Formats = new List <VkSurfaceFormatKHR>();

                for (int i = 0; i < formatCount; i++)
                {
                    Formats.Add(surfaceFormats[i]);
                }



                foreach (var surfaceFormat in Formats)
                {
                    if (surfaceFormat.format == VkFormat.B8g8r8a8Unorm)
                    {
                        VkColorFormat        = 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)
                {
                    VkColorFormat = surfaceFormats[0].format;
                    ColorSpace    = surfaceFormats[0].colorSpace;
                }
            }


            // Get physical Device Surface properties and formats
            VkSurfaceCapabilitiesKHR surfCaps;

            vkGetPhysicalDeviceSurfaceCapabilitiesKHR(PhysicalDevice, Surface, &surfCaps);



            // Get available present modes
            uint presentModeCount;

            vkGetPhysicalDeviceSurfacePresentModesKHR(PhysicalDevice, Surface, &presentModeCount, null);
            VkPresentModeKHR *presentModes = stackalloc VkPresentModeKHR[(int)presentModeCount];

            vkGetPhysicalDeviceSurfacePresentModesKHR(PhysicalDevice, Surface, &presentModeCount, (VkPresentModeKHR *)presentModes);



            VkExtent2D swapchainExtent;

            // If width (and height) equals the special value 0xFFFFFFFF, the size of the Surface will be set by the swapchain
            if (surfCaps.currentExtent.width == unchecked ((uint)-1))
            {
                // If the Surface size is undefined, the size is set to
                // the size of the Images requested.
                swapchainExtent.width  = (uint)width;
                swapchainExtent.height = (uint)height;
            }
            else
            {
                // If the Surface size is defined, the swap chain size must match
                swapchainExtent = surfCaps.currentExtent;
                width           = (int)surfCaps.currentExtent.width;
                height          = (int)surfCaps.currentExtent.height;
            }


            // Select a present mode for the swapchain

            // The VK_PRESENT_MODE_FIFO_KHR mode must always be present as per spec
            // This mode waits for the vertical blank ("v-sync")
            VkPresentModeKHR swapchainPresentMode = VkPresentModeKHR.FifoKHR;

            // If v-sync is not requested, try to find a mailbox mode
            // It's the lowest latency non-tearing present mode available
            if (!vsync)
            {
                for (uint i = 0; i < presentModeCount; i++)
                {
                    if (presentModes[i] == VkPresentModeKHR.MailboxKHR)
                    {
                        swapchainPresentMode = VkPresentModeKHR.MailboxKHR;
                        break;
                    }
                    if ((swapchainPresentMode != VkPresentModeKHR.MailboxKHR) && (presentModes[i] == VkPresentModeKHR.ImmediateKHR))
                    {
                        swapchainPresentMode = VkPresentModeKHR.ImmediateKHR;
                    }
                }
            }

            // Determine the number of Images
            uint desiredNumberOfSwapchainImages = surfCaps.minImageCount + 1;

            if ((surfCaps.maxImageCount > 0) && (desiredNumberOfSwapchainImages > surfCaps.maxImageCount))
            {
                desiredNumberOfSwapchainImages = surfCaps.maxImageCount;
            }


            // Find the transformation of the Surface
            VkSurfaceTransformFlagsKHR preTransform;

            if ((surfCaps.supportedTransforms & VkSurfaceTransformFlagsKHR.IdentityKHR) != 0)
            {
                // We prefer a non-rotated transform
                preTransform = VkSurfaceTransformFlagsKHR.IdentityKHR;
            }

            else
            {
                preTransform = surfCaps.currentTransform;
            }


            VkSwapchainCreateInfoKHR swapchainCI = new VkSwapchainCreateInfoKHR()
            {
                sType           = VkStructureType.SwapchainCreateInfoKHR,
                pNext           = null,
                surface         = Surface,
                minImageCount   = desiredNumberOfSwapchainImages,
                imageFormat     = VkColorFormat,
                imageColorSpace = ColorSpace,
                imageExtent     = new VkExtent2D()
                {
                    width  = swapchainExtent.width,
                    height = swapchainExtent.height
                },
                imageUsage            = VkImageUsageFlags.ColorAttachment,
                preTransform          = preTransform,
                imageArrayLayers      = 1,
                imageSharingMode      = VkSharingMode.Exclusive,
                queueFamilyIndexCount = 0,
                pQueueFamilyIndices   = null,
                presentMode           = swapchainPresentMode,
                oldSwapchain          = SwapChain,

                // Setting clipped to VK_TRUE allows the implementation to discard rendering outside of the Surface area
                clipped        = True,
                compositeAlpha = VkCompositeAlphaFlagsKHR.OpaqueKHR,
            };


            // Set additional usage flag for blitting from the swapchain Images if supported
            VkFormatProperties formatProps;

            vkGetPhysicalDeviceFormatProperties(PhysicalDevice, VkColorFormat, out formatProps);
            if ((formatProps.optimalTilingFeatures & VkFormatFeatureFlags.BlitDst) != 0)
            {
                swapchainCI.imageUsage |= VkImageUsageFlags.TransferSrc;
            }


            VkSwapchainKHR swapChain;

            vkCreateSwapchainKHR(NativeDevice.Device, &swapchainCI, null, &swapChain);
            SwapChain = swapChain;


            //vkDestroySwapchainKHR(NativeDevice.Device, SwapChain, null);



            uint imageCount;

            vkGetSwapchainImagesKHR(NativeDevice.Device, SwapChain, &imageCount, null);
            VkImage *VkImages = stackalloc VkImage[(int)imageCount];

            vkGetSwapchainImagesKHR(NativeDevice.Device, swapChain, &imageCount, VkImages);



            Images = new List <VkImage>();

            for (int i = 0; i < imageCount; i++)
            {
                Images.Add(VkImages[i]);
            }
        }
Пример #8
0
        public void CreateSwapChain()
        {
            VkPhysicalDevice PhysicalDevice = NativeDevice.NativeAdapter.handle;

            int width = Parameters.Width;

            int height = Parameters.Height;

            bool vsync = false;


            // Get available queue family properties
            uint queueCount;

            vkGetPhysicalDeviceQueueFamilyProperties(PhysicalDevice, &queueCount, null);
            VkQueueFamilyProperties *queueProps = stackalloc VkQueueFamilyProperties[(int)queueCount];

            vkGetPhysicalDeviceQueueFamilyProperties(PhysicalDevice, &queueCount, queueProps);



            // 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, out 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 is uint.MaxValue)
                    {
                        graphicsQueueNodeIndex = i;
                    }

                    if (supportsPresent[i] == true)
                    {
                        graphicsQueueNodeIndex = i;
                        presentQueueNodeIndex  = i;
                        break;
                    }
                }
            }

            if (presentQueueNodeIndex is 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 is uint.MaxValue || presentQueueNodeIndex is 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!");
            }



            // Get list of supported Surface formats
            uint formatCount;

            vkGetPhysicalDeviceSurfaceFormatsKHR(PhysicalDevice, surface, &formatCount, null);
            VkSurfaceFormatKHR *surfaceFormats = stackalloc VkSurfaceFormatKHR[(int)formatCount];

            vkGetPhysicalDeviceSurfaceFormatsKHR(PhysicalDevice, surface, &formatCount, surfaceFormats);



            // 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 is 1) && (surfaceFormats[0].format is VkFormat.Undefined))
            {
                color_format = VkFormat.B8G8R8A8UNorm;
                color_space  = surfaceFormats[0].colorSpace;
            }