public static VkQueueFamilyProperties Create(int queueCount, VkQueueFlagBits queueFlags)
 {
     return(new VkQueueFamilyProperties()
     {
         queueCount = queueCount, queueFlags = queueFlags, minImageTransferGranularity = VkExtent3D.Create(1, 1, 1)
     });
 }
        private uint GetQueueFamilyIndex(VkQueueFlagBits queueFlags)
        {
            // Dedicated queue for compute
            // Try to find a queue family index that supports compute but not graphics
            if ((queueFlags & VkQueueFlagBits.Compute) != 0)
            {
                for (uint i = 0; i < QueueFamilyProperties.Length; i++)
                {
                    if (((QueueFamilyProperties[i].queueFlags & queueFlags) != 0) &&
                        (QueueFamilyProperties[i].queueFlags & VkQueueFlagBits.Graphics) == 0)
                    {
                        return(i);
                    }
                }
            }

            // Dedicated queue for transfer
            // Try to find a queue family index that supports transfer but not graphics and compute
            if ((queueFlags & VkQueueFlagBits.Transfer) != 0)
            {
                for (uint i = 0; i < QueueFamilyProperties.Length; i++)
                {
                    if (((QueueFamilyProperties[i].queueFlags & queueFlags) != 0) &&
                        (QueueFamilyProperties[i].queueFlags & VkQueueFlagBits.Graphics) == 0 &&
                        (QueueFamilyProperties[i].queueFlags & VkQueueFlagBits.Compute) == 0)
                    {
                        return(i);
                    }
                }
            }

            // For other queue types or if no separate compute queue is present, return the first one to support the requested flags
            for (uint i = 0; i < QueueFamilyProperties.Length; i++)
            {
                if ((QueueFamilyProperties[i].queueFlags & queueFlags) != 0)
                {
                    return(i);
                }
            }

            throw new InvalidOperationException("Could not find a matching queue family index");
        }
        public VkResult CreateLogicalDevice(
            VkPhysicalDeviceFeatures enabledFeatures,
            string[] enabledExtensions,
            bool useSwapChain = true,
            VkQueueFlagBits requestedQueueTypes = VkQueueFlagBits.Graphics | VkQueueFlagBits.Compute)
        {
            // Desired queues need to be requested upon logical device creation
            // Due to differing queue family configurations of Vulkan implementations this can be a bit tricky, especially if the application
            // requests different queue types

            var   queueCreateInfos     = new List <VkDeviceQueueCreateInfo>();
            float defaultQueuePriority = 0.0f;

            // Graphics queue
            if ((requestedQueueTypes & VkQueueFlagBits.Graphics) != 0)
            {
                QFIndices.Graphics = GetQueueFamilyIndex(VkQueueFlagBits.Graphics);
                VkDeviceQueueCreateInfo queueInfo = new VkDeviceQueueCreateInfo();
                queueInfo.sType            = DeviceQueueCreateInfo;
                queueInfo.queueFamilyIndex = QFIndices.Graphics;
                queueInfo.queuePriorities  = defaultQueuePriority;
                queueCreateInfos.Add(queueInfo);
            }
            else
            {
                QFIndices.Graphics = 0;
            }

            // Dedicated compute queue
            if ((requestedQueueTypes & VkQueueFlagBits.Compute) != 0)
            {
                QFIndices.Compute = GetQueueFamilyIndex(VkQueueFlagBits.Compute);
                if (QFIndices.Compute != QFIndices.Graphics)
                {
                    // If compute family index differs, we need an additional queue create info for the compute queue
                    VkDeviceQueueCreateInfo queueInfo = new VkDeviceQueueCreateInfo();
                    queueInfo.sType            = DeviceQueueCreateInfo;
                    queueInfo.queueFamilyIndex = QFIndices.Compute;
                    queueInfo.queuePriorities  = defaultQueuePriority;
                    queueCreateInfos.Add(queueInfo);
                }
            }
            else
            {
                // Else we use the same queue
                QFIndices.Compute = QFIndices.Graphics;
            }

            // Dedicated transfer queue
            if ((requestedQueueTypes & VkQueueFlagBits.Transfer) != 0)
            {
                QFIndices.Transfer = GetQueueFamilyIndex(VkQueueFlagBits.Transfer);
                if (QFIndices.Transfer != QFIndices.Graphics && QFIndices.Transfer != QFIndices.Compute)
                {
                    // If compute family index differs, we need an additional queue create info for the transfer queue
                    VkDeviceQueueCreateInfo queueInfo = new VkDeviceQueueCreateInfo();
                    queueInfo.sType            = DeviceQueueCreateInfo;
                    queueInfo.queueFamilyIndex = QFIndices.Transfer;
                    queueInfo.queuePriorities  = defaultQueuePriority;
                    queueCreateInfos.Add(queueInfo);
                }
            }
            else
            {
                // Else we use the same queue
                QFIndices.Transfer = QFIndices.Graphics;
            }

            // Create the logical device representation
            //using (NativeList<IntPtr> deviceExtensions = new NativeList<IntPtr>(enabledExtensions)) {
            var deviceExtensions = new List <string>();

            if (useSwapChain)
            {
                // If the device will be used for presenting to a display via a swapchain we need to request the swapchain extension
                deviceExtensions.Add(Strings.VK_KHR_SWAPCHAIN_EXTENSION_NAME);
            }

            var deviceCreateInfo = VkDeviceCreateInfo.Alloc();

            deviceCreateInfo->queueCreateInfos = queueCreateInfos.ToArray();
            deviceCreateInfo->pEnabledFeatures = &enabledFeatures;

            if (deviceExtensions.Count > 0)
            {
                string[] array = deviceExtensions.ToArray();
                deviceCreateInfo[0].EnabledExtensions = array;
            }

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

            this._logicalDevice = device;
            if (result == VkResult.Success)
            {
                // Create a default command pool for graphics command buffers
                CommandPool = CreateCommandPool(QFIndices.Graphics);
            }

            return(result);
        }