Example #1
0
        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;
     }
 }
Example #3
0
        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;
        }
Example #4
0
        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);
        }
Example #5
0
        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;
        }
Example #6
0
        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);
        }
Example #8
0
        /// <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");
        }
Example #9
0
        /// <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;
                }
            }
        }
Example #10
0
        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);
            }
        }
Example #11
0
        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;
            }
        }
Example #12
0
        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);
        }
Example #13
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);
        }
Example #14
0
        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));
        }
Example #15
0
        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);
        }
Example #17
0
 /// <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)
 {
 }
Example #18
0
        /// <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);
        }
Example #19
0
        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
        }
Example #20
0
        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);
        }
Example #21
0
 public DeviceCreateInfo(List <String> extensions, List <DeviceQueueCreateInfo> queueCreateInfos, VkPhysicalDeviceFeatures features)
 {
     this.extensions       = extensions;
     this.queueCreateInfos = queueCreateInfos;
     this.features         = features;
 }
Example #22
0
        //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;
        }
Example #23
0
        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);
        }
Example #24
0
 internal DeviceBuilder(PhysicalDevice dev)
 {
     _physicalDevice = dev;
     _features       = default;
 }
Example #25
0
 public DeviceBuilder WithFeatures(VkPhysicalDeviceFeatures f)
 {
     _features = f;
     return(this);
 }
Example #26
0
        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
                );
        }
Example #27
0
 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;
 }
Example #28
0
        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);
            }
        }
Example #29
0
        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);
                }
            }
        }
Example #30
0
 protected override void configureEnabledFeatures(VkPhysicalDeviceFeatures available_features, ref VkPhysicalDeviceFeatures features)
 {
     base.configureEnabledFeatures(available_features, ref features);
     features.textureCompressionBC = available_features.textureCompressionBC;
 }