public Queue(Device _dev, VkQueueFlags requestedFlags, float _priority = 0.0f) { dev = _dev; priority = _priority; qFamIndex = searchQFamily(requestedFlags); dev.queues.Add(this); }
public PresentQueue(Device _dev, VkQueueFlags requestedFlags, VkSurfaceKHR _surface, float _priority = 0.0f) { dev = _dev; priority = _priority; Surface = _surface; qFamIndex = searchQFamily(requestedFlags); dev.queues.Add(this); }
/// <summary> /// Searches the available queue familities for one matching the passed flags. /// </summary> /// <param name="req">The queue flags required for the family.</param> /// <param name="reqNot">The queue flags required to be not present for the family.</param> /// <returns>The queue family index, or <c>null</c> if a matching family was not found.</returns> public uint?FindQueueFamily(VkQueueFlags req, VkQueueFlags reqNot = VkQueueFlags.NoFlags) { for (uint fi = 0; fi < QueueFamilyCount; ++fi) { var yesPass = (_queueFamilies[fi].QueueFlags & req) == req; var noPass = (_queueFamilies[fi].QueueFlags & reqNot) == 0; if (yesPass && noPass) { return(fi); } } return(null); }
internal uint GetQueueFamilyIndex(VkQueueFlags queueFlags, List <VkQueueFamilyProperties> queueFamilyProperties) { // Dedicated queue for compute // Try to find a queue family index that supports compute but not graphics if ((queueFlags & VkQueueFlags.Compute) != 0) { for (uint i = 0; i < queueFamilyProperties.Count(); i++) { if (((queueFamilyProperties[(int)i].queueFlags & queueFlags) != 0) && (queueFamilyProperties[(int)i].queueFlags & VkQueueFlags.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 & VkQueueFlags.Transfer) != 0) { for (uint i = 0; i < queueFamilyProperties.Count(); i++) { if (((queueFamilyProperties[(int)i].queueFlags & queueFlags) != 0) && (queueFamilyProperties[(int)i].queueFlags & VkQueueFlags.Graphics) == 0 && (queueFamilyProperties[(int)i].queueFlags & VkQueueFlags.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.Count(); i++) { if ((queueFamilyProperties[(int)i].queueFlags & queueFlags) != 0) { return(i); } } throw new InvalidOperationException("Could not find a matching queue family index"); }
uint searchQFamily(VkQueueFlags requestedFlags) { //search for dedicated Q for (uint i = 0; i < dev.phy.QueueFamilies.Length; i++) { if (dev.phy.QueueFamilies[i].queueFlags == requestedFlags && dev.phy.GetPresentIsSupported(i, Surface)) { return(i); } } //search Q having flags for (uint i = 0; i < dev.phy.QueueFamilies.Length; i++) { if ((dev.phy.QueueFamilies[i].queueFlags & requestedFlags) == requestedFlags && dev.phy.GetPresentIsSupported(i, Surface)) { return(i); } } throw new Exception(string.Format("No Queue with flags {0} found", requestedFlags)); }
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); }
public VkResult CreateLogicalDevice( VkPhysicalDeviceFeatures enabledFeatures, NativeList <IntPtr> enabledExtensions, bool useSwapChain = true, VkQueueFlags requestedQueueTypes = VkQueueFlags.Graphics | VkQueueFlags.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 using (NativeList <VkDeviceQueueCreateInfo> queueCreateInfos = new NativeList <VkDeviceQueueCreateInfo>()) { float defaultQueuePriority = 0.0f; // Graphics queue if ((requestedQueueTypes & VkQueueFlags.Graphics) != 0) { QFIndices.Graphics = GetQueueFamilyIndex(VkQueueFlags.Graphics); VkDeviceQueueCreateInfo queueInfo = new VkDeviceQueueCreateInfo(); queueInfo.sType = VkStructureType.DeviceQueueCreateInfo; queueInfo.queueFamilyIndex = QFIndices.Graphics; queueInfo.queueCount = 1; queueInfo.pQueuePriorities = &defaultQueuePriority; queueCreateInfos.Add(queueInfo); } else { QFIndices.Graphics = (uint)NullHandle; } // Dedicated compute queue if ((requestedQueueTypes & VkQueueFlags.Compute) != 0) { QFIndices.Compute = GetQueueFamilyIndex(VkQueueFlags.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 = VkStructureType.DeviceQueueCreateInfo; queueInfo.queueFamilyIndex = QFIndices.Compute; queueInfo.queueCount = 1; queueInfo.pQueuePriorities = &defaultQueuePriority; queueCreateInfos.Add(queueInfo); } } else { // Else we use the same queue QFIndices.Compute = QFIndices.Graphics; } // Dedicated transfer queue if ((requestedQueueTypes & VkQueueFlags.Transfer) != 0) { QFIndices.Transfer = GetQueueFamilyIndex(VkQueueFlags.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 = VkStructureType.DeviceQueueCreateInfo; queueInfo.queueFamilyIndex = QFIndices.Transfer; queueInfo.queueCount = 1; queueInfo.pQueuePriorities = &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)) { 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); } VkDeviceCreateInfo deviceCreateInfo = VkDeviceCreateInfo.New(); deviceCreateInfo.queueCreateInfoCount = queueCreateInfos.Count; deviceCreateInfo.pQueueCreateInfos = (VkDeviceQueueCreateInfo *)queueCreateInfos.Data.ToPointer(); deviceCreateInfo.pEnabledFeatures = &enabledFeatures; if (deviceExtensions.Count > 0) { deviceCreateInfo.enabledExtensionCount = deviceExtensions.Count; deviceCreateInfo.ppEnabledExtensionNames = (byte **)deviceExtensions.Data.ToPointer(); } VkResult result = vkCreateDevice(PhysicalDevice, &deviceCreateInfo, null, out _logicalDevice); if (result == VkResult.Success) { // Create a default command pool for graphics command buffers CommandPool = CreateCommandPool(QFIndices.Graphics); } return(result); } } }
public static VkDevice Create(Settings settings, VkPhysicalDeviceFeatures enabledFeatures, CStringList enabledExtensions, VkQueueFlags requestedQueueTypes = VkQueueFlags.Graphics | VkQueueFlags.Compute | VkQueueFlags.Transfer) { instanceExtensions.Add(Vulkan.KHRSurfaceExtensionName); instanceExtensions.Add(Vulkan.KHRGetPhysicalDeviceProperties2ExtensionName); enabledExtensions.Add(Vulkan.KHRMaintenance1ExtensionName); enabledExtensions.Add(Vulkan.EXTInlineUniformBlockExtensionName); //enabledExtensions.Add(Strings.VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT); CreateInstance(settings); // Physical Device var physicalDevices = Vulkan.vkEnumeratePhysicalDevices(VkInstance); // TODO: Implement arg parsing, etc. int selectedDevice = 0; PhysicalDevice = physicalDevices[selectedDevice]; Debug.Assert(PhysicalDevice.Handle != IntPtr.Zero); vkGetPhysicalDeviceProperties(PhysicalDevice, out VkPhysicalDeviceProperties properties); Properties = properties; vkGetPhysicalDeviceFeatures(PhysicalDevice, out VkPhysicalDeviceFeatures features); Features = features; if (features.tessellationShader) { enabledFeatures.tessellationShader = true; } if (features.multiDrawIndirect) { enabledFeatures.multiDrawIndirect = true; } // Enable anisotropic filtering if supported if (features.samplerAnisotropy) { enabledFeatures.samplerAnisotropy = true; } // Enable texture compression if (features.textureCompressionBC) { enabledFeatures.textureCompressionBC = true; } else if (features.textureCompressionASTC_LDR) { enabledFeatures.textureCompressionASTC_LDR = true; } else if (features.textureCompressionETC2) { enabledFeatures.textureCompressionETC2 = true; } if (features.sparseBinding && features.sparseResidencyImage2D) { enabledFeatures.shaderResourceResidency = true; enabledFeatures.shaderResourceMinLod = true; enabledFeatures.sparseBinding = true; enabledFeatures.sparseResidencyImage2D = true; } else { Log.Warn("Sparse binding not supported"); } // Memory properties are used regularly for creating all kinds of buffers VkPhysicalDeviceMemoryProperties memoryProperties; vkGetPhysicalDeviceMemoryProperties(PhysicalDevice, out memoryProperties); MemoryProperties = memoryProperties; var qf = Vulkan.vkGetPhysicalDeviceQueueFamilyProperties(PhysicalDevice); QueueFamilyProperties.Add(qf); var extensions = Vulkan.vkEnumerateDeviceExtensionProperties(PhysicalDevice); foreach (var ext in extensions) { string strExt = UTF8String.FromPointer(ext.extensionName); //enabledExtensions.Add((IntPtr)ext.extensionName); supportedExtensions.Add(strExt); } device = CreateLogicalDevice(Features, enabledExtensions, true, requestedQueueTypes); if (device != VkDevice.Null) { VkPipelineCacheCreateInfo pipelineCacheCreateInfo = new VkPipelineCacheCreateInfo() { sType = VkStructureType.PipelineCacheCreateInfo }; VulkanUtil.CheckResult(vkCreatePipelineCache(device, &pipelineCacheCreateInfo, null, out pipelineCache)); } return(device); }
static VkDevice CreateLogicalDevice(VkPhysicalDeviceFeatures enabledFeatures, CStringList enabledExtensions, bool useSwapChain = true, VkQueueFlags requestedQueueTypes = VkQueueFlags.Graphics | VkQueueFlags.Compute | VkQueueFlags.Transfer) { using Vector <VkDeviceQueueCreateInfo> queueCreateInfos = new Vector <VkDeviceQueueCreateInfo>(); float defaultQueuePriority = 0.0f; // Graphics queue if ((requestedQueueTypes & VkQueueFlags.Graphics) != 0) { QFGraphics = GetQueueFamilyIndex(VkQueueFlags.Graphics); var queueInfo = new VkDeviceQueueCreateInfo { sType = VkStructureType.DeviceQueueCreateInfo, queueFamilyIndex = QFGraphics, queueCount = 1, pQueuePriorities = &defaultQueuePriority }; queueCreateInfos.Add(queueInfo); } else { QFGraphics = (uint)IntPtr.Zero; } // Dedicated compute queue if ((requestedQueueTypes & VkQueueFlags.Compute) != 0) { QFCompute = GetQueueFamilyIndex(VkQueueFlags.Compute); if (QFCompute != QFGraphics) { // If compute family index differs, we need an additional queue create info for the compute queue var queueInfo = new VkDeviceQueueCreateInfo { sType = VkStructureType.DeviceQueueCreateInfo, queueFamilyIndex = QFCompute, queueCount = 1, pQueuePriorities = &defaultQueuePriority }; queueCreateInfos.Add(queueInfo); } } else { // Else we use the same queue QFCompute = QFGraphics; } // Dedicated transfer queue if ((requestedQueueTypes & VkQueueFlags.Transfer) != 0) { QFTransfer = GetQueueFamilyIndex(VkQueueFlags.Transfer); if (QFTransfer != QFGraphics && QFTransfer != QFCompute) { // If compute family index differs, we need an additional queue create info for the transfer queue var queueInfo = new VkDeviceQueueCreateInfo { sType = VkStructureType.DeviceQueueCreateInfo, queueFamilyIndex = QFTransfer, queueCount = 1, pQueuePriorities = &defaultQueuePriority }; queueCreateInfos.Add(queueInfo); } } else { // Else we use the same queue QFTransfer = QFGraphics; } // Create the logical device representation using CStringList deviceExtensions = new CStringList(enabledExtensions); 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(Vulkan.KHRSwapchainExtensionName); } var deviceCreateInfo = new VkDeviceCreateInfo { sType = VkStructureType.DeviceCreateInfo, queueCreateInfoCount = queueCreateInfos.Count, pQueueCreateInfos = queueCreateInfos.DataPtr, pEnabledFeatures = &enabledFeatures }; if (deviceExtensions.Count > 0) { deviceCreateInfo.enabledExtensionCount = deviceExtensions.Count; deviceCreateInfo.ppEnabledExtensionNames = (byte **)deviceExtensions.Data; } return(Vulkan.CreateDevice(PhysicalDevice, &deviceCreateInfo)); }
internal void CreateDevice() { VkDeviceQueueCreateInfo *queueCreateInfos = stackalloc VkDeviceQueueCreateInfo[3]; float defaultQueuePriority = 0.0f; VkQueueFlags requestedQueueTypes = VkQueueFlags.Graphics | VkQueueFlags.Compute | VkQueueFlags.Transfer; // Graphics queue if ((requestedQueueTypes & VkQueueFlags.Graphics) != 0) { GraphicsFamily = GetQueueFamilyIndex(VkQueueFlags.Graphics, QueueFamilyProperties); VkDeviceQueueCreateInfo queueInfo = new VkDeviceQueueCreateInfo { sType = VkStructureType.DeviceQueueCreateInfo, queueFamilyIndex = GraphicsFamily, queueCount = 1, pQueuePriorities = &defaultQueuePriority }; queueCreateInfos[0] = (queueInfo); } else { GraphicsFamily = (uint)NullHandle; } // Dedicated compute queue if ((requestedQueueTypes & VkQueueFlags.Compute) != 0) { ComputeFamily = GetQueueFamilyIndex(VkQueueFlags.Compute, QueueFamilyProperties); if (ComputeFamily != GraphicsFamily) { // If compute family index differs, we need an additional queue create info for the compute queue VkDeviceQueueCreateInfo queueInfo = new VkDeviceQueueCreateInfo { sType = VkStructureType.DeviceQueueCreateInfo, queueFamilyIndex = ComputeFamily, queueCount = 1, pQueuePriorities = &defaultQueuePriority }; queueCreateInfos[1] = (queueInfo); } } else { // Else we use the same queue ComputeFamily = GraphicsFamily; } // Dedicated transfer queue if ((requestedQueueTypes & VkQueueFlags.Transfer) != 0) { TransferFamily = GetQueueFamilyIndex(VkQueueFlags.Transfer, QueueFamilyProperties); if (TransferFamily != GraphicsFamily && TransferFamily != ComputeFamily) { // If compute family index differs, we need an additional queue create info for the transfer queue VkDeviceQueueCreateInfo queueInfo = new VkDeviceQueueCreateInfo { sType = VkStructureType.DeviceQueueCreateInfo, queueFamilyIndex = TransferFamily, queueCount = 1, pQueuePriorities = &defaultQueuePriority }; queueCreateInfos[2] = (queueInfo); } } else { // Else we use the same queue TransferFamily = GraphicsFamily; } // Create the logical device representation List <string> deviceExtensions = new List <string>(); // If the device will be used for presenting to a display via a swapchain we need to request the swapchain extension deviceExtensions.Add("VK_KHR_swapchain"); var oldFeatures = Features; VkDeviceCreateInfo deviceCreateInfo = VkDeviceCreateInfo.New(); deviceCreateInfo.queueCreateInfoCount = 3; deviceCreateInfo.pQueueCreateInfos = queueCreateInfos; deviceCreateInfo.pEnabledFeatures = &oldFeatures; if (deviceExtensions.Count > 0) { deviceCreateInfo.enabledExtensionCount = (uint)deviceExtensions.Count; deviceCreateInfo.ppEnabledExtensionNames = Interop.String.AllocToPointers(deviceExtensions.ToArray()); } vkCreateDevice(NativeAdapter.NativePhysicalDevice, &deviceCreateInfo, null, out var device); Device = device; }