protected override void configureEnabledFeatures(ref VkPhysicalDeviceFeatures features) { base.configureEnabledFeatures(ref features); #if DEBUG features.pipelineStatisticsQuery = true; #endif }
void GetDeviceFeatures() { using (var feat = new Marshalled <VkPhysicalDeviceFeatures>()) { Instance.Commands.getFeatures(physicalDevice, feat.Address); features = feat.Value; } }
protected override void configureEnabledFeatures(VkPhysicalDeviceFeatures available_features, ref VkPhysicalDeviceFeatures features) { base.configureEnabledFeatures(available_features, ref features); #if PIPELINE_STATS features.pipelineStatisticsQuery = true; #endif features.samplerAnisotropy = true; }
private void createLogicalDevice() { QueueFamilyIndices indices = findQueueFamilies(physicalDevice); List <VkDeviceQueueCreateInfo> queueCreateInfos = new List <VkDeviceQueueCreateInfo>(); HashSet <int> uniqueQueueFamilies = new HashSet <int>() { indices.graphicsFamily, indices.presentFamily }; float[] queuePriorities = new float[] { 1.0f }; foreach (var queueFamily in uniqueQueueFamilies) { VkDeviceQueueCreateInfo queueCreateInfo = new VkDeviceQueueCreateInfo(); queueCreateInfo.sType = VkStructureType.VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queueCreateInfo.queueFamilyIndex = queueFamily; queueCreateInfo.queueCount = 1; queueCreateInfo.pQueuePriorities = queuePriorities; queueCreateInfos.Add(queueCreateInfo); } VkPhysicalDeviceFeatures deviceFeatures = new VkPhysicalDeviceFeatures(); VkDeviceCreateInfo createInfo = new VkDeviceCreateInfo(); createInfo.sType = VkStructureType.VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; createInfo.queueCreateInfoCount = queueCreateInfos.Count; createInfo.pQueueCreateInfos = queueCreateInfos.ToArray(); createInfo.pEnabledFeatures = new VkPhysicalDeviceFeatures[] { deviceFeatures }; createInfo.enabledExtensionCount = deviceExtensions.Length; createInfo.ppEnabledExtensionNames = deviceExtensions; if (enableValidationLayers) { createInfo.enabledLayerCount = validationLayers.Length; createInfo.ppEnabledLayerNames = validationLayers; } else { createInfo.enabledLayerCount = 0; } VkResult result = Vulkan.vkCreateDevice(physicalDevice, createInfo, null, out device); if (result != VkResult.VK_SUCCESS) { throw Program.Throw("failed to create logical device!", result); } Vulkan.vkGetDeviceQueue(device, indices.graphicsFamily, 0, out graphicsQueue); Vulkan.vkGetDeviceQueue(device, indices.presentFamily, 0, out presentQueue); }
private void CreateLogicalDevice() { var indices = new QueueFamilyIndices(vkPhysicalDevice, vkSurface); float priority = 1f; var queueCreateInfos = stackalloc VkDeviceQueueCreateInfo[] { new VkDeviceQueueCreateInfo() { sType = VkStructureType.VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, queueFamilyIndex = (uint)indices.GraphicsFamily, queueCount = 1, pQueuePriorities = &priority, } }; int extensionsCount = 1; IntPtr *extensionsToEnableArray = stackalloc IntPtr[extensionsCount]; for (int i = 0; i < extensionsCount; i++) { string extension = "VK_KHR_swapchain"; extensionsToEnableArray[i] = Marshal.StringToHGlobalAnsi(extension); } VkPhysicalDeviceFeatures deviceFeatures = new VkPhysicalDeviceFeatures(); var createInfo = new VkDeviceCreateInfo() { sType = VkStructureType.VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, ppEnabledExtensionNames = (byte **)extensionsToEnableArray, enabledExtensionCount = (uint)extensionsCount, pQueueCreateInfos = queueCreateInfos, queueCreateInfoCount = 1, pEnabledFeatures = &deviceFeatures, }; VkDevice newDevice; var result = VulkanNative.vkCreateDevice(this.vkPhysicalDevice, &createInfo, null, &newDevice); this.vkDevice = newDevice; Helpers.CheckErrors(result); for (int i = 0; i < extensionsCount; i++) { Marshal.FreeHGlobal(extensionsToEnableArray[i]); } VkQueue newGraphicsQueue; VulkanNative.vkGetDeviceQueue(vkDevice, (uint)indices.GraphicsFamily, 0, &newGraphicsQueue); this.vkGraphicsQueue = newGraphicsQueue; VkQueue newPresentQueue; VulkanNative.vkGetDeviceQueue(vkDevice, (uint)indices.PresentFamily, 0, &newPresentQueue); this.vkPresentQueue = newPresentQueue; }
protected override void configureEnabledFeatures(VkPhysicalDeviceFeatures available_features, ref VkPhysicalDeviceFeatures enabled_features) { base.configureEnabledFeatures(available_features, ref enabled_features); enabled_features.samplerAnisotropy = available_features.samplerAnisotropy; enabled_features.sampleRateShading = available_features.sampleRateShading; enabled_features.geometryShader = available_features.geometryShader; enabled_features.textureCompressionBC = available_features.textureCompressionBC; }
private void CreateLogicalDevice() { GetQueueFamilyIndices(); HashSet <uint> familyIndices = new HashSet <uint> { _graphicsQueueIndex, _presentQueueIndex }; RawList <VkDeviceQueueCreateInfo> queueCreateInfos = new RawList <VkDeviceQueueCreateInfo>(); foreach (uint index in familyIndices) { VkDeviceQueueCreateInfo queueCreateInfo = VkDeviceQueueCreateInfo.New(); queueCreateInfo.queueFamilyIndex = _graphicsQueueIndex; queueCreateInfo.queueCount = 1; float priority = 1f; queueCreateInfo.pQueuePriorities = &priority; queueCreateInfos.Add(queueCreateInfo); } VkPhysicalDeviceFeatures deviceFeatures = new VkPhysicalDeviceFeatures(); deviceFeatures.samplerAnisotropy = true; deviceFeatures.fillModeNonSolid = true; deviceFeatures.geometryShader = true; deviceFeatures.depthClamp = true; VkDeviceCreateInfo deviceCreateInfo = VkDeviceCreateInfo.New(); fixed(VkDeviceQueueCreateInfo *qciPtr = &queueCreateInfos.Items[0]) { deviceCreateInfo.pQueueCreateInfos = qciPtr; deviceCreateInfo.queueCreateInfoCount = queueCreateInfos.Count; deviceCreateInfo.pEnabledFeatures = &deviceFeatures; StackList <IntPtr> layerNames = new StackList <IntPtr>(); layerNames.Add(CommonStrings.StandardValidationLayerName); deviceCreateInfo.enabledLayerCount = layerNames.Count; deviceCreateInfo.ppEnabledLayerNames = (byte **)layerNames.Data; byte *extensionNames = CommonStrings.VK_KHR_SWAPCHAIN_EXTENSION_NAME; deviceCreateInfo.enabledExtensionCount = 1; deviceCreateInfo.ppEnabledExtensionNames = &extensionNames; vkCreateDevice(_physicalDevice, ref deviceCreateInfo, null, out _device); } vkGetDeviceQueue(_device, _graphicsQueueIndex, 0, out _graphicsQueue); vkGetDeviceQueue(_device, _presentQueueIndex, 0, out _presentQueue); }
/// <summary> /// Create the minimum vulkan objects to quickly start a new application. The folowing objects are created: /// - Vulkan Instance with extensions present in the `EnabledInstanceExtensions` property. /// - Vulkan Surface for the GLFW native window. /// - Vulkan device for the selected physical one with configured enabledFeatures and extensions present in `EnabledDeviceExtensions` list. Selection of the default physical device /// may be replaced by the `selectPhysicalDevice` method override. /// - Create a default Graphic Queue with presentable support. The default queue creation may be customized by overriding the `createQueues` method. /// - Default vulkan Swapchain creation. Some swapchain's parameters are controled through static fields of the `SwapChain` class (ex: `SwapChain.PREFERED_FORMAT`). /// - Create a default command pool for the `presentQueue` family index. /// - Create an empty command buffer collection (`cmds`). /// - Create one unsignaled vulkan semaphore (named `drawComplete` per swapchain image used to control presentation submission to the graphic queue. /// - Create a signaled vulkan fence (`drawFence`). (TODO: improve this. /// With all these objects, vulkan application programming startup is reduced to the minimal. /// </summary> protected virtual void initVulkan() { List <string> instExts = new List <string> (Glfw3.GetRequiredInstanceExtensions()); if (EnabledInstanceExtensions != null) { instExts.AddRange(EnabledInstanceExtensions); } instance = new Instance(instExts.ToArray()); hSurf = instance.CreateSurface(hWin); selectPhysicalDevice(); VkPhysicalDeviceFeatures enabledFeatures = default; configureEnabledFeatures(phy.Features, ref enabledFeatures); //First create the c# device class dev = new Device(phy); dev.debugUtilsEnabled = instance.debugUtilsEnabled; //store a boolean to prevent testing against the extension string presence. //create queue class createQueues(); //activate the device to have effective queues created accordingly to what's available dev.Activate(enabledFeatures, EnabledDeviceExtensions); swapChain = new SwapChain(presentQueue as PresentQueue, Width, Height, SwapChain.PREFERED_FORMAT, VSync ? VkPresentModeKHR.FifoKHR : VkPresentModeKHR.ImmediateKHR); swapChain.Activate(); Width = swapChain.Width; Height = swapChain.Height; cmdPool = new CommandPool(dev, presentQueue.qFamIndex, VkCommandPoolCreateFlags.ResetCommandBuffer); cmds = new PrimaryCommandBuffer[swapChain.ImageCount]; drawComplete = new VkSemaphore[swapChain.ImageCount]; drawFence = new Fence(dev, true, "draw fence"); for (int i = 0; i < swapChain.ImageCount; i++) { drawComplete[i] = dev.CreateSemaphore(); drawComplete[i].SetDebugMarkerName(dev, "Semaphore DrawComplete" + i); } cmdPool.SetName("main CmdPool"); }
/// <summary> /// Gets the version-aware features associated with the physical device. /// </summary> /// <param name="device">The device to get the features for.</param> /// <param name="props">The Vulkan 1.0 features.</param> /// <param name="props11">The Vulkan 1.1 features.</param> /// <param name="props12">The Vulkan 1.2 features.</param> public static void GetFeatures(VkPhysicalDevice device, out VkPhysicalDeviceFeatures feats, out VkPhysicalDeviceVulkan11Features feats11, out VkPhysicalDeviceVulkan12Features feats12) { if (!device) { throw new ArgumentNullException(nameof(device), "Cannot pass null device or device handle"); } VkPhysicalDeviceFeatures.New(out feats); VkPhysicalDeviceVulkan11Features.New(out feats11); VkPhysicalDeviceVulkan12Features.New(out feats12); var version = device.Parent.Functions.CoreVersion; // 1.0 if (version < VkVersion.VK_VERSION_1_1) { device.GetPhysicalDeviceFeatures(out feats); } // 1.1 else if (version < VkVersion.VK_VERSION_1_2) { VkPhysicalDeviceFeatures2.New(out var feats2); fixed(VkPhysicalDeviceVulkan11Features *ptr11 = &feats11) { feats2.pNext = ptr11; device.GetPhysicalDeviceFeatures2(&feats2); feats = feats2.Features; } } // 1.2 else { VkPhysicalDeviceFeatures2.New(out var feats2); fixed(VkPhysicalDeviceVulkan11Features *ptr11 = &feats11) fixed(VkPhysicalDeviceVulkan12Features * ptr12 = &feats12) { feats2.pNext = ptr11; ptr11->pNext = ptr12; device.GetPhysicalDeviceFeatures2(&feats2); feats = feats2.Features; ptr11->pNext = null; } } }
void initVulkan(bool vSync, bool debugMarkers) { instance = new Instance(); hSurf = instance.CreateSurface(hWin); phy = instance.GetAvailablePhysicalDevice().Where(p => p.HasSwapChainSupport).FirstOrDefault(); VkPhysicalDeviceFeatures enabledFeatures = default(VkPhysicalDeviceFeatures); configureEnabledFeatures(phy.Features, ref enabledFeatures); if (debugMarkers) { debugMarkers = phy.GetDeviceExtensionSupported(Ext.D.VK_EXT_debug_marker); } //First create the c# device class dev = new Device(phy, debugMarkers); //create queue class createQueues(); //activate the device to have effective queues created accordingly to what's available dev.Activate(enabledFeatures, EnabledExtensions); swapChain = new SwapChain(presentQueue as PresentQueue, width, height, VkFormat.B8g8r8a8Srgb, vSync ? VkPresentModeKHR.FifoKHR : VkPresentModeKHR.MailboxKHR); swapChain.Create(); cmdPool = new CommandPool(dev, presentQueue.qFamIndex); cmds = new CommandBuffer[swapChain.ImageCount]; drawComplete = new VkSemaphore[swapChain.ImageCount]; for (int i = 0; i < swapChain.ImageCount; i++) { drawComplete[i] = dev.CreateSemaphore(); } cmdPool.SetName("main CmdPool"); for (int i = 0; i < swapChain.ImageCount; i++) { drawComplete[i].SetDebugMarkerName(dev, "Semaphore DrawComplete" + i); } }
protected override void configureEnabledFeatures(VkPhysicalDeviceFeatures available_features, ref VkPhysicalDeviceFeatures features) { base.configureEnabledFeatures(available_features, ref features); features.samplerAnisotropy = available_features.samplerAnisotropy; features.sampleRateShading = available_features.sampleRateShading; features.geometryShader = available_features.geometryShader; features.pipelineStatisticsQuery = true; if (available_features.textureCompressionETC2) { features.textureCompressionETC2 = true; Image.DefaultTextureFormat = VkFormat.Etc2R8g8b8a8UnormBlock; } else if (available_features.textureCompressionBC) { //features.textureCompressionBC = true; //Image.DefaultTextureFormat = VkFormat.Bc3UnormBlock; } }
private void CreateLogicalDevice() { var queueFamilies = FindQueueFamilies(physicalDevice, surface).Value; var queueCreateInfos = queueFamilies.GraphicsFamily == queueFamilies.PresentFamily ? new[] { new VkDeviceQueueCreateInfo { QueueFamilyIndex = queueFamilies.GraphicsFamily, QueuePriorities = new [] { 1f } } } : new [] { new VkDeviceQueueCreateInfo { QueueFamilyIndex = queueFamilies.GraphicsFamily, QueuePriorities = new[] { 1f } }, new VkDeviceQueueCreateInfo { QueueFamilyIndex = queueFamilies.PresentFamily, QueuePriorities = new[] { 1f } } }; var deviceFeatures = new VkPhysicalDeviceFeatures { }; var createInfo = new VkDeviceCreateInfo { QueueCreateInfos = queueCreateInfos, EnabledFeatures = deviceFeatures, EnabledExtensionNames = DeviceExtensions, EnabledLayerNames = LayerNames }; device = physicalDevice.CreateDevice(createInfo, null).Object; graphicsQueue = device.GetDeviceQueue(queueFamilies.GraphicsFamily, 0); presentQueue = device.GetDeviceQueue(queueFamilies.PresentFamily, 0); }
/// <summary> /// Initializes the specified device. /// </summary> /// <param name="graphicsProfiles">The graphics profiles.</param> /// <param name="deviceCreationFlags">The device creation flags.</param> /// <param name="windowHandle">The window handle.</param> private unsafe void InitializePlatformDevice(GraphicsProfile[] graphicsProfiles, DeviceCreationFlags deviceCreationFlags, object windowHandle) { if (nativeDevice != VkDevice.Null) { // Destroy previous device ReleaseDevice(); } rendererName = Adapter.Description; vkGetPhysicalDeviceProperties(NativePhysicalDevice, out var physicalDeviceProperties); ConstantBufferDataPlacementAlignment = (int)physicalDeviceProperties.limits.minUniformBufferOffsetAlignment; TimestampFrequency = (long)(1.0e9 / physicalDeviceProperties.limits.timestampPeriod); // Resolution in nanoseconds RequestedProfile = graphicsProfiles.First(); var queueProperties = vkGetPhysicalDeviceQueueFamilyProperties(NativePhysicalDevice); //IsProfilingSupported = queueProperties[0].TimestampValidBits > 0; // Command lists are thread-safe and execute deferred IsDeferred = true; // TODO VULKAN // Create Vulkan device based on profile float queuePriorities = 0; var queueCreateInfo = new VkDeviceQueueCreateInfo { sType = VkStructureType.DeviceQueueCreateInfo, queueFamilyIndex = 0, queueCount = 1, pQueuePriorities = &queuePriorities, }; var enabledFeature = new VkPhysicalDeviceFeatures { fillModeNonSolid = true, shaderClipDistance = true, shaderCullDistance = true, samplerAnisotropy = true, depthClamp = true, }; var extensionProperties = vkEnumerateDeviceExtensionProperties(NativePhysicalDevice); var availableExtensionNames = new List <string>(); var desiredExtensionNames = new List <string>(); for (int index = 0; index < extensionProperties.Length; index++) { fixed(VkExtensionProperties *extensionPropertiesPtr = extensionProperties) { var namePointer = new IntPtr(extensionPropertiesPtr[index].extensionName); var name = Marshal.PtrToStringAnsi(namePointer); availableExtensionNames.Add(name); } } desiredExtensionNames.Add(KHRSwapchainExtensionName); if (!availableExtensionNames.Contains(KHRSwapchainExtensionName)) { throw new InvalidOperationException(); } if (availableExtensionNames.Contains(EXTDebugMarkerExtensionName) && IsDebugMode) { desiredExtensionNames.Add(EXTDebugMarkerExtensionName); IsProfilingSupported = true; } var enabledExtensionNames = desiredExtensionNames.Select(Marshal.StringToHGlobalAnsi).ToArray(); try { var deviceCreateInfo = new VkDeviceCreateInfo { sType = VkStructureType.DeviceCreateInfo, queueCreateInfoCount = 1, pQueueCreateInfos = &queueCreateInfo, enabledExtensionCount = (uint)enabledExtensionNames.Length, ppEnabledExtensionNames = enabledExtensionNames.Length > 0 ? (byte **)Core.Interop.Fixed(enabledExtensionNames) : null, pEnabledFeatures = &enabledFeature, }; vkCreateDevice(NativePhysicalDevice, &deviceCreateInfo, null, out nativeDevice); } finally { foreach (var enabledExtensionName in enabledExtensionNames) { Marshal.FreeHGlobal(enabledExtensionName); } } vkGetDeviceQueue(nativeDevice, 0, 0, out NativeCommandQueue); NativeCopyCommandPools = new ThreadLocal <VkCommandPool>(() => { //// Prepare copy command list (start it closed, so that every new use start with a Reset) var commandPoolCreateInfo = new VkCommandPoolCreateInfo { sType = VkStructureType.CommandPoolCreateInfo, queueFamilyIndex = 0, //device.NativeCommandQueue.FamilyIndex flags = VkCommandPoolCreateFlags.ResetCommandBuffer }; vkCreateCommandPool(NativeDevice, &commandPoolCreateInfo, null, out var result); return(result); }, true); DescriptorPools = new HeapPool(this); nativeResourceCollector = new NativeResourceCollector(this); graphicsResourceLinkCollector = new GraphicsResourceLinkCollector(this); EmptyTexelBufferInt = Buffer.Typed.New(this, 1, PixelFormat.R32G32B32A32_UInt); EmptyTexelBufferFloat = Buffer.Typed.New(this, 1, PixelFormat.R32G32B32A32_Float); EmptyTexture = Texture.New2D(this, 1, 1, PixelFormat.R8G8B8A8_UNorm_SRgb, TextureFlags.ShaderResource); }
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)); }
private void CreateLogicalDevice() { QueueFamilyIndices indices = this.FindQueueFamilies(physicalDevice); List <VkDeviceQueueCreateInfo> queueCreateInfos = new List <VkDeviceQueueCreateInfo>(); HashSet <uint> uniqueQueueFamilies = new HashSet <uint>() { indices.graphicsFamily.Value, indices.presentFamily.Value }; float queuePriority = 1.0f; foreach (uint queueFamily in uniqueQueueFamilies) { VkDeviceQueueCreateInfo queueCreateInfo = new VkDeviceQueueCreateInfo() { sType = VkStructureType.VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, queueFamilyIndex = queueFamily, queueCount = 1, pQueuePriorities = &queuePriority, }; queueCreateInfos.Add(queueCreateInfo); } VkPhysicalDeviceFeatures deviceFeatures = default; // Raytracing extensions VkPhysicalDeviceRayTracingFeaturesKHR deviceRayTracingFeatures = new VkPhysicalDeviceRayTracingFeaturesKHR() { sType = VkStructureType.VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_FEATURES_KHR, pNext = null, rayTracing = true, }; VkPhysicalDeviceVulkan12Features deviceVulkan12Features = new VkPhysicalDeviceVulkan12Features() { sType = VkStructureType.VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES, pNext = &deviceRayTracingFeatures, bufferDeviceAddress = true, }; int deviceExtensionsCount = deviceExtensions.Length; IntPtr *deviceExtensionsArray = stackalloc IntPtr[deviceExtensionsCount]; for (int i = 0; i < deviceExtensionsCount; i++) { string extension = deviceExtensions[i]; deviceExtensionsArray[i] = Marshal.StringToHGlobalAnsi(extension); } VkDeviceCreateInfo createInfo = new VkDeviceCreateInfo(); createInfo.sType = VkStructureType.VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; createInfo.pNext = &deviceVulkan12Features; VkDeviceQueueCreateInfo[] queueCreateInfosArray = queueCreateInfos.ToArray(); fixed(VkDeviceQueueCreateInfo *queueCreateInfosArrayPtr = &queueCreateInfosArray[0]) { createInfo.queueCreateInfoCount = (uint)queueCreateInfos.Count; createInfo.pQueueCreateInfos = queueCreateInfosArrayPtr; } createInfo.pEnabledFeatures = &deviceFeatures; createInfo.enabledExtensionCount = (uint)deviceExtensions.Length; createInfo.ppEnabledExtensionNames = (byte **)deviceExtensionsArray; fixed(VkDevice *devicePtr = &device) { Helpers.CheckErrors(VulkanNative.vkCreateDevice(physicalDevice, &createInfo, null, devicePtr)); } fixed(VkQueue *graphicsQueuePtr = &graphicsQueue) { VulkanNative.vkGetDeviceQueue(device, indices.graphicsFamily.Value, 0, graphicsQueuePtr); } fixed(VkQueue *presentQueuePtr = &presentQueue) { VulkanNative.vkGetDeviceQueue(device, indices.presentFamily.Value, 0, presentQueuePtr); // TODO queue index 0 ?¿?¿ } }
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); }
/// <summary> /// override this method to modify enabled features before device creation /// </summary> /// <param name="enabled_features">Features.</param> protected virtual void configureEnabledFeatures(VkPhysicalDeviceFeatures available_features, ref VkPhysicalDeviceFeatures enabled_features) { }
/// <summary> /// Creates a new device and queues /// </summary> /// <param name="physDevice">Physical device</param> /// <param name="requiredLayers"></param> /// <param name="preferredExtensions"></param> /// <param name="requiredExtensions"></param> /// <param name="preferredLayers"></param> /// <param name="queueOptions">Queue options</param> /// <param name="desiredFeatures">Desired physical device features</param> public Device(PhysicalDevice physDevice, ICollection <VkExtension> preferredExtensions, ICollection <VkExtension> requiredExtensions, ICollection <string> preferredLayers, ICollection <string> requiredLayers, QueueCreateInfo[] queueOptions, VkPhysicalDeviceFeatures desiredFeatures) { PhysicalDevice = physDevice; foreach (var ext in preferredExtensions.Union(requiredExtensions).Select(VkExtensionDatabase.Extension)) { Debug.Assert(ext.Type == ExtensionType.Device || ext.Type == ExtensionType.Unknown, $"Ext {ext.Extension} type {ext.Type} doesn't conform"); } var supportedLayers = physDevice.Handle.EnumerateLayerProperties().Select(x => x.LayerNameString).ToHashSet(); Log.Info($"Supported device layers: {string.Join(", ", supportedLayers)}"); foreach (var requiredLayer in requiredLayers) { if (!supportedLayers.Contains(requiredLayer)) { throw new NotSupportedException($"Layer {requiredLayer} isn't supported"); } } var layersToUse = requiredLayers.Union(preferredLayers.Where(supportedLayers.Contains)).ToList(); var supportedExtensions = physDevice.Handle.EnumerateExtensionProperties(null).Union( layersToUse.SelectMany(physDevice.Handle.EnumerateExtensionProperties)) .Select(x => x.ExtensionNameString).ToHashSet(); Log.Info($"Supported device extensions: {string.Join(", ", supportedExtensions)}"); foreach (var requiredExtension in requiredExtensions) { if (!supportedExtensions.Contains(VkExtensionDatabase.Extension(requiredExtension).Extension)) { throw new NotSupportedException($"Extension {requiredExtension} isn't supported"); } } var extensionsToUse = requiredExtensions.Select(VkExtensionDatabase.Extension).Select(x => x.Extension) .Union( preferredExtensions.Select(VkExtensionDatabase.Extension).Select(x => x.Extension) .Where(supportedExtensions.Contains)).ToList(); _enabledExtensions = extensionsToUse.Select(VkExtensionDatabase.Extension).Where(y => y != null).Select(x => x.ExtensionId) .ToHashSet(); _enableExtensionsByName = extensionsToUse.ToHashSet(); Log.Info($"Using device layers: {string.Join(", ", layersToUse)}"); Log.Info($"Using device extensions: {string.Join(", ", extensionsToUse)}"); var pins = new List <GCHandle>(); var queueOptionsRedirect = new int[queueOptions.Length]; try { VkDeviceQueueCreateInfo[] queueCreateInfo; { var queueOptionsRewrite = new Dictionary <uint, List <float> >(); for (var queueId = 0; queueId < queueOptions.Length; queueId++) { var opti = queueOptions[queueId]; if (opti.Priorities.Count == 0) { continue; } if (!queueOptionsRewrite.TryGetValue(opti.Family, out var list)) { list = queueOptionsRewrite[opti.Family] = new List <float>(); } queueOptionsRedirect[queueId] = list.Count; list.AddRange(opti.Priorities); } queueCreateInfo = new VkDeviceQueueCreateInfo[queueOptionsRewrite.Count]; var family = 0; foreach (var kv in queueOptionsRewrite) { unsafe { var block = kv.Value.ToArray(); pins.Add(GCHandle.Alloc(block, GCHandleType.Pinned)); queueCreateInfo[family++] = new VkDeviceQueueCreateInfo() { SType = VkStructureType.DeviceQueueCreateInfo, Flags = 0, PNext = IntPtr.Zero, QueueFamilyIndex = kv.Key, QueueCount = (uint)block.Length, PQueuePriorities = (float *)Marshal.UnsafeAddrOfPinnedArrayElement(block, 0).ToPointer() }; } } } unsafe { var layersToUseAnsi = new IntPtr[layersToUse.Count]; for (var i = 0; i < layersToUse.Count; i++) { layersToUseAnsi[i] = Marshal.StringToHGlobalAnsi(layersToUse[i]); } var extensionsToUseAnsi = new IntPtr[extensionsToUse.Count]; for (var i = 0; i < extensionsToUse.Count; i++) { extensionsToUseAnsi[i] = Marshal.StringToHGlobalAnsi(extensionsToUse[i]); } try { fixed(VkDeviceQueueCreateInfo *queueOptionsPtr = queueCreateInfo) { Features = desiredFeatures; var deviceCreateInfo = new VkDeviceCreateInfo() { SType = VkStructureType.DeviceCreateInfo, QueueCreateInfoCount = (uint)queueOptions.Length, PQueueCreateInfos = queueOptionsPtr, PEnabledFeatures = &desiredFeatures, EnabledExtensionCount = (uint)extensionsToUse.Count, PpEnabledExtensionNames = extensionsToUse.Count > 0 ? (byte **)Marshal.UnsafeAddrOfPinnedArrayElement(extensionsToUseAnsi, 0) .ToPointer() : (byte **)0, EnabledLayerCount = (uint)layersToUse.Count, PpEnabledLayerNames = layersToUse.Count > 0 ? (byte **)Marshal.UnsafeAddrOfPinnedArrayElement(layersToUseAnsi, 0).ToPointer() : (byte **)0, }; Handle = PhysicalDevice.Handle.CreateDevice(&deviceCreateInfo, Instance.AllocationCallbacks); } } finally { foreach (var ptr in layersToUseAnsi) { Marshal.FreeHGlobal(ptr); } foreach (var ptr in extensionsToUseAnsi) { Marshal.FreeHGlobal(ptr); } } } } finally { foreach (var pin in pins) { pin.Free(); } pins.Clear(); } _queues = new Queue[queueOptions.Length][]; var queuesAll = new List <Queue>(); for (var i = 0; i < queueOptions.Length; i++) { _queues[i] = new Queue[queueOptions[i].Priorities.Count]; for (var j = 0; j < _queues[i].Length; j++) { queuesAll.Add(_queues[i][j] = new Queue(this, queueOptions[i].Family, (uint)(queueOptionsRedirect[i] + j))); } } Queues = queuesAll; MemoryPool = new DeviceMemoryPools(this); BufferPools = new BufferPools(this); }
public void Activate(VkPhysicalDeviceFeatures enabledFeatures, params string[] extensions) { List <VkDeviceQueueCreateInfo> qInfos = new List <VkDeviceQueueCreateInfo> (); List <List <float> > prioritiesLists = new List <List <float> > ();//store pinned lists for later unpin foreach (IGrouping <uint, Queue> qfams in queues.GroupBy(q => q.qFamIndex)) { int qTot = qfams.Count(); uint qIndex = 0; List <float> priorities = new List <float> (); bool qCountReached = false; //true when queue count of that family is reached foreach (Queue q in qfams) { if (!qCountReached) { priorities.Add(q.priority); } q.index = qIndex++; if (qIndex == phy.QueueFamilies[qfams.Key].queueCount) { qIndex = 0; qCountReached = true; } } qInfos.Add(new VkDeviceQueueCreateInfo { sType = VkStructureType.DeviceQueueCreateInfo, queueCount = qCountReached ? phy.QueueFamilies[qfams.Key].queueCount : qIndex, queueFamilyIndex = qfams.Key, pQueuePriorities = priorities.Pin() }); prioritiesLists.Add(priorities); //add for unpined } //enable only supported exceptions List <IntPtr> deviceExtensions = new List <IntPtr> (); for (int i = 0; i < extensions.Length; i++) { if (phy.GetDeviceExtensionSupported(extensions[i])) { deviceExtensions.Add(new FixedUtf8String(extensions[i])); } } VkDeviceCreateInfo deviceCreateInfo = VkDeviceCreateInfo.New(); deviceCreateInfo.queueCreateInfoCount = (uint)qInfos.Count; deviceCreateInfo.pQueueCreateInfos = qInfos.Pin(); deviceCreateInfo.pEnabledFeatures = enabledFeatures.Pin(); if (deviceExtensions.Count > 0) { deviceCreateInfo.enabledExtensionCount = (uint)deviceExtensions.Count; deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions.Pin(); } Utils.CheckResult(vkCreateDevice(phy.Handle, ref deviceCreateInfo, IntPtr.Zero, out dev)); qInfos.Unpin(); enabledFeatures.Unpin(); foreach (List <float> fa in prioritiesLists) { fa.Unpin(); } deviceExtensions.Unpin(); //Vk.LoadDeviceFunctionPointers (dev); foreach (Queue q in queues) { q.updateHandle(); } #if MEMORY_POOLS resourceManager = new ResourceManager(this); #endif }
private IntPtr CreateDevice() { IntPtr device; var queuePriority = 1.0f; var deviceQueueCreateInfo = new VkDeviceQueueCreateInfo { sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, pNext = null, flags = 0, queueFamilyIndex = GraphicsQueueFamilyIndex, queueCount = 1, pQueuePriorities = &queuePriority, }; var enabledExtensionCount = 1u; var enabledExtensionNames = stackalloc sbyte *[(int)enabledExtensionCount]; enabledExtensionNames[0] = (sbyte *)Unsafe.AsPointer(ref MemoryMarshal.GetReference(VK_KHR_SWAPCHAIN_EXTENSION_NAME)); var physicalDeviceFeatures = new VkPhysicalDeviceFeatures { robustBufferAccess = VK_FALSE, fullDrawIndexUint32 = VK_FALSE, imageCubeArray = VK_FALSE, independentBlend = VK_FALSE, geometryShader = VK_FALSE, tessellationShader = VK_FALSE, sampleRateShading = VK_FALSE, dualSrcBlend = VK_FALSE, logicOp = VK_FALSE, multiDrawIndirect = VK_FALSE, drawIndirectFirstInstance = VK_FALSE, depthClamp = VK_FALSE, depthBiasClamp = VK_FALSE, fillModeNonSolid = VK_FALSE, depthBounds = VK_FALSE, wideLines = VK_FALSE, largePoints = VK_FALSE, alphaToOne = VK_FALSE, multiViewport = VK_FALSE, samplerAnisotropy = VK_FALSE, textureCompressionETC2 = VK_FALSE, textureCompressionASTC_LDR = VK_FALSE, textureCompressionBC = VK_FALSE, occlusionQueryPrecise = VK_FALSE, pipelineStatisticsQuery = VK_FALSE, vertexPipelineStoresAndAtomics = VK_FALSE, fragmentStoresAndAtomics = VK_FALSE, shaderTessellationAndGeometryPointSize = VK_FALSE, shaderImageGatherExtended = VK_FALSE, shaderStorageImageExtendedFormats = VK_FALSE, shaderStorageImageMultisample = VK_FALSE, shaderStorageImageReadWithoutFormat = VK_FALSE, shaderStorageImageWriteWithoutFormat = VK_FALSE, shaderUniformBufferArrayDynamicIndexing = VK_FALSE, shaderSampledImageArrayDynamicIndexing = VK_FALSE, shaderStorageBufferArrayDynamicIndexing = VK_FALSE, shaderStorageImageArrayDynamicIndexing = VK_FALSE, shaderClipDistance = VK_FALSE, shaderCullDistance = VK_FALSE, shaderFloat64 = VK_FALSE, shaderInt64 = VK_FALSE, shaderInt16 = VK_FALSE, shaderResourceResidency = VK_FALSE, shaderResourceMinLod = VK_FALSE, sparseBinding = VK_FALSE, sparseResidencyBuffer = VK_FALSE, sparseResidencyImage2D = VK_FALSE, sparseResidencyImage3D = VK_FALSE, sparseResidency2Samples = VK_FALSE, sparseResidency4Samples = VK_FALSE, sparseResidency8Samples = VK_FALSE, sparseResidency16Samples = VK_FALSE, sparseResidencyAliased = VK_FALSE, variableMultisampleRate = VK_FALSE, inheritedQueries = VK_FALSE, }; var deviceCreateInfo = new VkDeviceCreateInfo { sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, pNext = null, flags = 0, queueCreateInfoCount = 1, pQueueCreateInfos = &deviceQueueCreateInfo, enabledLayerCount = 0, ppEnabledLayerNames = null, enabledExtensionCount = 1, ppEnabledExtensionNames = enabledExtensionNames, pEnabledFeatures = &physicalDeviceFeatures, }; var result = vkCreateDevice(_graphicsAdapter.PhysicalDevice, &deviceCreateInfo, pAllocator: null, &device); if (result != VK_SUCCESS) { ThrowExternalException(nameof(vkCreateDevice), (int)result); } return(device); }
public DeviceCreateInfo(List <String> extensions, List <DeviceQueueCreateInfo> queueCreateInfos, VkPhysicalDeviceFeatures features) { this.extensions = extensions; this.queueCreateInfos = queueCreateInfos; this.features = features; }
//protected InputSnapshot snapshot; public void InitVulkan() { VkResult err; err = CreateInstance(false); if (err != VkResult.Success) { throw new InvalidOperationException("Could not create Vulkan instance. Error: " + err); } if (Settings.Validation) { } // Physical Device uint gpuCount = 0; vkEnumeratePhysicalDevices(Instance, &gpuCount, null); Debug.Assert(gpuCount > 0); // Enumerate devices IntPtr *physicalDevices = stackalloc IntPtr[(int)gpuCount]; err = vkEnumeratePhysicalDevices(Instance, &gpuCount, (VkPhysicalDevice *)physicalDevices); if (err != VkResult.Success) { throw new InvalidOperationException("Could not enumerate physical devices."); } // GPU selection // Select physical Device to be used for the Vulkan example // Defaults to the first Device unless specified by command line uint selectedDevice = 0; // TODO: Implement arg parsing, etc. physicalDevice = ((VkPhysicalDevice *)physicalDevices)[selectedDevice]; // Store properties (including limits) and features of the phyiscal Device // So examples can check against them and see if a feature is actually supported VkPhysicalDeviceProperties deviceProperties; vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties); DeviceProperties = deviceProperties; VkPhysicalDeviceFeatures deviceFeatures; vkGetPhysicalDeviceFeatures(physicalDevice, &deviceFeatures); DeviceFeatures = deviceFeatures; // Gather physical Device memory properties VkPhysicalDeviceMemoryProperties deviceMemoryProperties; vkGetPhysicalDeviceMemoryProperties(physicalDevice, &deviceMemoryProperties); DeviceMemoryProperties = deviceMemoryProperties; // Derived examples can override this to set actual features (based on above readings) to enable for logical device creation getEnabledFeatures(); // Vulkan Device creation // This is handled by a separate class that gets a logical Device representation // and encapsulates functions related to a Device vulkanDevice = new vksVulkanDevice(physicalDevice); VkResult res = vulkanDevice.CreateLogicalDevice(enabledFeatures, EnabledExtensions); if (res != VkResult.Success) { throw new InvalidOperationException("Could not create Vulkan Device."); } device = vulkanDevice.LogicalDevice; // Get a graphics queue from the Device VkQueue queue; vkGetDeviceQueue(device, vulkanDevice.QFIndices.Graphics, 0, &queue); this.queue = queue; // Find a suitable depth format VkFormat depthFormat; uint validDepthFormat = Tools.getSupportedDepthFormat(physicalDevice, &depthFormat); Debug.Assert(validDepthFormat == True); DepthFormat = depthFormat; Swapchain.Connect(Instance, physicalDevice, device); // Create synchronization objects VkSemaphoreCreateInfo semaphoreCreateInfo = new VkSemaphoreCreateInfo(); semaphoreCreateInfo.sType = SemaphoreCreateInfo; // Create a semaphore used to synchronize image presentation // Ensures that the image is displayed before we start submitting new commands to the queu vkCreateSemaphore(device, &semaphoreCreateInfo, null, &GetSemaphoresPtr()->PresentComplete); // Create a semaphore used to synchronize command submission // Ensures that the image is not presented until all commands have been sumbitted and executed vkCreateSemaphore(device, &semaphoreCreateInfo, null, &GetSemaphoresPtr()->RenderComplete); // Create a semaphore used to synchronize command submission // Ensures that the image is not presented until all commands for the text overlay have been sumbitted and executed // Will be inserted after the render complete semaphore if the text overlay is enabled vkCreateSemaphore(device, &semaphoreCreateInfo, null, &GetSemaphoresPtr()->TextOverlayComplete); // Set up submit info structure // Semaphores will stay the same during application lifetime // Command buffer submission info is set by each example submitInfo = VkSubmitInfo.Alloc(); submitInfo->waitSemaphoresDstStageMasks.Set(submitPipelineStages); submitInfo->waitSemaphoresDstStageMasks.Set(GetSemaphoresPtr()->PresentComplete); submitInfo->signalSemaphores = GetSemaphoresPtr()->RenderComplete; }
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); }
internal DeviceBuilder(PhysicalDevice dev) { _physicalDevice = dev; _features = default; }
public DeviceBuilder WithFeatures(VkPhysicalDeviceFeatures f) { _features = f; return(this); }
public unsafe Device(VkPhysicalDevice physicalDevice) { _physicalDevice = physicalDevice; //get physical device information VulkanNative.vkGetPhysicalDeviceProperties( _physicalDevice, out _properties ); VulkanNative.vkGetPhysicalDeviceMemoryProperties( _physicalDevice, out _memoryProperties ); VulkanNative.vkGetPhysicalDeviceFeatures( _physicalDevice, out _features ); //get family queue properties uint familyQueuePropertiesCount; VulkanNative.vkGetPhysicalDeviceQueueFamilyProperties( _physicalDevice, &familyQueuePropertiesCount, null ); var familyQueueProperties = new NativeList <VkQueueFamilyProperties>( familyQueuePropertiesCount ); familyQueueProperties.Count = familyQueuePropertiesCount; VulkanNative.vkGetPhysicalDeviceQueueFamilyProperties( _physicalDevice, &familyQueuePropertiesCount, (VkQueueFamilyProperties *)familyQueueProperties.Data.ToPointer() ); //setup queue families _queueFamilies = new List <QueueFamily>(); for (uint i = 0; i < familyQueuePropertiesCount; i++) { var familyQueueProperty = familyQueueProperties[i]; _queueFamilies.Add(new QueueFamily( i, familyQueueProperty.queueCount, (QueueFamilyType)familyQueueProperty.queueFlags )); } //get queue create infos var queueCreateInfos = new NativeList <VkDeviceQueueCreateInfo>( familyQueuePropertiesCount ); queueCreateInfos.Count = familyQueuePropertiesCount; for (int i = 0; i < familyQueuePropertiesCount; i++) { queueCreateInfos[i] = _queueFamilies[i].QueueCreateInfo; } //enable extra device features var enabledFeatures = new VkPhysicalDeviceFeatures() { samplerAnisotropy = true, dualSrcBlend = true }; //enable swapchain extension for window support var enabledExtensions = new NativeList <IntPtr>(); enabledExtensions.Add(GraphicsApiConstants.VK_KHR_SWAPCHAIN_EXTENSION_NAME); var deviceInfo = new VkDeviceCreateInfo { sType = VkStructureType.DeviceCreateInfo, pEnabledFeatures = &enabledFeatures, enabledExtensionCount = enabledExtensions.Count, ppEnabledExtensionNames = (byte **)enabledExtensions.Data, enabledLayerCount = 0, ppEnabledLayerNames = null, queueCreateInfoCount = queueCreateInfos.Count, pQueueCreateInfos = (VkDeviceQueueCreateInfo *)queueCreateInfos.Data.ToPointer() }; //setup device VkDevice device; if (VulkanNative.vkCreateDevice( _physicalDevice, &deviceInfo, null, &device ) != VkResult.Success) { throw new Exception("failed to initialize device"); } _handle = device; //setup device queues foreach (var queueFamily in _queueFamilies) { queueFamily.GetQueuesFromDevice(this); } //calculate device score _score = 0; if (_properties.deviceType == VkPhysicalDeviceType.DiscreteGpu) { _score += 10; } else if (_properties.deviceType == VkPhysicalDeviceType.IntegratedGpu) { _score += 5; } else if (_properties.deviceType == VkPhysicalDeviceType.VirtualGpu) { _score += 3; } else if (_properties.deviceType == VkPhysicalDeviceType.Cpu) { _score += 1; } _score += ( //1073741824 = 1024 * 1024 * 1024 _properties.limits.maxMemoryAllocationCount / 1073741824.0f ); }
protected override void configureEnabledFeatures(VkPhysicalDeviceFeatures available_features, ref VkPhysicalDeviceFeatures enabled_features) { base.configureEnabledFeatures(available_features, ref enabled_features); enabled_features.textureCompressionBC = available_features.textureCompressionBC; enabled_features.textureCompressionASTC_LDR = available_features.textureCompressionASTC_LDR; }
private void CreateLogicalDevice() { GetQueueFamilyIndices(); HashSet <uint> familyIndices = new HashSet <uint> { _graphicsQueueIndex, _presentQueueIndex }; RawList <VkDeviceQueueCreateInfo> queueCreateInfos = new RawList <VkDeviceQueueCreateInfo>(); foreach (uint index in familyIndices) { VkDeviceQueueCreateInfo queueCreateInfo = VkDeviceQueueCreateInfo.New(); queueCreateInfo.queueFamilyIndex = _graphicsQueueIndex; queueCreateInfo.queueCount = 1; float priority = 1f; queueCreateInfo.pQueuePriorities = &priority; queueCreateInfos.Add(queueCreateInfo); } VkPhysicalDeviceFeatures deviceFeatures = new VkPhysicalDeviceFeatures(); deviceFeatures.samplerAnisotropy = true; deviceFeatures.fillModeNonSolid = true; deviceFeatures.geometryShader = true; deviceFeatures.depthClamp = true; bool debugMarkerSupported = false; uint propertyCount = 0; VkResult result = vkEnumerateDeviceExtensionProperties(_physicalDevice, (byte *)null, &propertyCount, null); CheckResult(result); VkExtensionProperties *properties = stackalloc VkExtensionProperties[(int)propertyCount]; result = vkEnumerateDeviceExtensionProperties(_physicalDevice, (byte *)null, &propertyCount, properties); CheckResult(result); for (int i = 0; i < propertyCount; i++) { if (Util.GetString(properties[i].extensionName) == "VK_EXT_debug_marker") { Console.WriteLine("VK_EXT_debug_marker is available."); debugMarkerSupported = true; break; } } VkDeviceCreateInfo deviceCreateInfo = VkDeviceCreateInfo.New(); fixed(VkDeviceQueueCreateInfo *qciPtr = &queueCreateInfos.Items[0]) { deviceCreateInfo.pQueueCreateInfos = qciPtr; deviceCreateInfo.queueCreateInfoCount = queueCreateInfos.Count; deviceCreateInfo.pEnabledFeatures = &deviceFeatures; StackList <IntPtr> layerNames = new StackList <IntPtr>(); layerNames.Add(CommonStrings.StandardValidationLayerName); deviceCreateInfo.enabledLayerCount = layerNames.Count; deviceCreateInfo.ppEnabledLayerNames = (byte **)layerNames.Data; StackList <IntPtr> extensionNames = new StackList <IntPtr>(); extensionNames.Add(CommonStrings.VK_KHR_SWAPCHAIN_EXTENSION_NAME); if (debugMarkerSupported) { extensionNames.Add(CommonStrings.VK_EXT_DEBUG_MARKER_EXTENSION_NAME); _debugMarkerEnabled = true; } deviceCreateInfo.enabledExtensionCount = extensionNames.Count; deviceCreateInfo.ppEnabledExtensionNames = (byte **)extensionNames.Data; result = vkCreateDevice(_physicalDevice, ref deviceCreateInfo, null, out _device); CheckResult(result); } vkGetDeviceQueue(_device, _graphicsQueueIndex, 0, out _graphicsQueue); vkGetDeviceQueue(_device, _presentQueueIndex, 0, out _presentQueue); if (debugMarkerSupported) { IntPtr setObjectNamePtr; using (FixedUtf8String debugExtFnName = "vkDebugMarkerSetObjectNameEXT") { setObjectNamePtr = vkGetInstanceProcAddr(_instance, debugExtFnName); } _setObjectNameDelegate = Marshal.GetDelegateForFunctionPointer <vkDebugMarkerSetObjectNameEXT_d>(setObjectNamePtr); } }
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); } } }
protected override void configureEnabledFeatures(VkPhysicalDeviceFeatures available_features, ref VkPhysicalDeviceFeatures features) { base.configureEnabledFeatures(available_features, ref features); features.textureCompressionBC = available_features.textureCompressionBC; }