Ejemplo n.º 1
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);
        }
Ejemplo n.º 2
0
        private static VkDevice CreateDevice(VkInstance instance, out VkPhysicalDevice physicalDevice,
                                             VkSurfaceKHR surface, out uint queueFamilyIndex)
        {
            queueFamilyIndex = 0;//SHORTCUT computed from queue properties
            physicalDevice   = PickPhysicalDevice(instance, surface, out queueFamilyIndex);

            List <GCHandle> handles            = new List <GCHandle>();
            List <string>   requiredExtensions = new List <string>();

            requiredExtensions.Add("VK_KHR_swapchain");
            string[] extensionNames        = requiredExtensions.ToArray();
            byte[][] pExtensionNames       = new byte[extensionNames.Length][];
            byte *[] ppExtensionNamesArray = new byte *[extensionNames.Length];

            for (int i = 0; i < pExtensionNames.Length; i++)
            {
                pExtensionNames[i] = Encoding.UTF8.GetBytes(extensionNames[i] + char.MinValue);
                GCHandle handle = GCHandle.Alloc(pExtensionNames[i]);
                handles.Add(handle);
                fixed(byte *p = &(((byte[])handle.Target)[0]))
                {
                    ppExtensionNamesArray[i] = p;
                }
            }
            VkDevice device;

            fixed(byte **extensions = &ppExtensionNamesArray[0])
            {
                float[] pQueuePriorities = new float[] { 1.0f };
                VkDeviceQueueCreateInfo deviceQueueCreateInfo = VkDeviceQueueCreateInfo.New();

                deviceQueueCreateInfo.queueFamilyIndex = queueFamilyIndex;
                deviceQueueCreateInfo.queueCount       = 1;

                fixed(float *ptr = &(pQueuePriorities[0]))
                deviceQueueCreateInfo.pQueuePriorities = ptr;

                VkDeviceCreateInfo createInfo = VkDeviceCreateInfo.New();

                createInfo.queueCreateInfoCount    = 1;
                createInfo.pQueueCreateInfos       = &deviceQueueCreateInfo;
                createInfo.ppEnabledExtensionNames = extensions;
                createInfo.enabledExtensionCount   = (uint)extensionNames.Length;

                device = VkDevice.Null;
                Assert(vkCreateDevice(physicalDevice, &createInfo, null, &device));

                foreach (var handle in handles)
                {
                    handle.Free();
                }
            }

            return(device);
        }
Ejemplo n.º 3
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;

            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);
        }
Ejemplo n.º 4
0
        void CreateDevice(DeviceCreateInfo mInfo)
        {
            var extensionsMarshalled = new NativeStringArray(mInfo.extensions);
            MarshalledArray <VkDeviceQueueCreateInfo> queueInfos           = null;
            DisposableList <NativeArray <float> >     prioritiesMarshalled = null;
            Marshalled <VkPhysicalDeviceFeatures>     features             = new Marshalled <VkPhysicalDeviceFeatures>(mInfo.features);

            var info = new VkDeviceCreateInfo();

            info.sType = VkStructureType.DeviceCreateInfo;
            info.enabledExtensionCount   = (uint)extensionsMarshalled.Count;
            info.ppEnabledExtensionNames = extensionsMarshalled.Address;
            info.pEnabledFeatures        = features.Address;

            if (mInfo.queueCreateInfos != null)
            {
                int length = mInfo.queueCreateInfos.Count;
                info.queueCreateInfoCount = (uint)length;
                queueInfos           = new MarshalledArray <VkDeviceQueueCreateInfo>(length);
                prioritiesMarshalled = new DisposableList <NativeArray <float> >(length);

                for (int i = 0; i < length; i++)
                {
                    var mi    = mInfo.queueCreateInfos[i];
                    var qInfo = new VkDeviceQueueCreateInfo();
                    qInfo.sType = VkStructureType.DeviceQueueCreateInfo;

                    var priorityMarshalled = new NativeArray <float>(mi.priorities);
                    prioritiesMarshalled.Add(priorityMarshalled);
                    qInfo.pQueuePriorities = priorityMarshalled.Address;
                    qInfo.queueCount       = mi.queueCount;
                    qInfo.queueFamilyIndex = mi.queueFamilyIndex;

                    queueInfos[i] = qInfo;
                }

                info.pQueueCreateInfos = queueInfos.Address;
            }

            using (extensionsMarshalled)
                using (queueInfos)
                    using (features)
                        using (prioritiesMarshalled) {
                            var result = Instance.Commands.createDevice(PhysicalDevice.Native, ref info, Instance.AllocationCallbacks, out device);
                            if (result != VkResult.Success)
                            {
                                throw new DeviceException(string.Format("Error creating device: {0}", result));
                            }
                        }
        }
Ejemplo n.º 5
0
        void CreateDevice()
        {
            var features = new Native <VkPhysicalDeviceFeatures>();

            VK.GetPhysicalDeviceFeatures(physicalDevice, features.Address);

            HashSet <uint> uniqueIndices = new HashSet <uint> {
                graphicsIndex, presentIndex
            };
            var queueInfos = new NativeArray <VkDeviceQueueCreateInfo>(uniqueIndices.Count);
            var priorities = new Native <float>(1);

            int i = 0;

            foreach (var ind in uniqueIndices)
            {
                var queueInfo = new VkDeviceQueueCreateInfo();
                queueInfo.sType            = CSGL.Vulkan.VkStructureType.DeviceQueueCreateInfo;
                queueInfo.queueFamilyIndex = ind;
                queueInfo.queueCount       = 1;

                queueInfo.pQueuePriorities = priorities.Address;

                queueInfos[i] = queueInfo;
                i++;
            }

            var info = new VkDeviceCreateInfo();

            info.sType                = CSGL.Vulkan.VkStructureType.DeviceCreateInfo;
            info.pQueueCreateInfos    = queueInfos.Address;
            info.queueCreateInfoCount = (uint)uniqueIndices.Count;
            info.pEnabledFeatures     = features.Address;

            var extensionsNative = new NativeStringArray(deviceExtensions);

            info.ppEnabledExtensionNames = extensionsNative.Address;
            info.enabledExtensionCount   = (uint)deviceExtensions.Length;

            var result = VK.CreateDevice(physicalDevice, ref info, alloc, out device);

            VK.GetDeviceQueue(device, graphicsIndex, 0, out graphicsQueue);
            VK.GetDeviceQueue(device, presentIndex, 0, out presentQueue);

            features.Dispose();
            priorities.Dispose();
            queueInfos.Dispose();
            extensionsNative.Dispose();
        }
Ejemplo n.º 6
0
        private VkDevice CreateDevice(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface)
        {
            //VkQueueFamilyProperties[] properties = physicalDevice.GetQueueFamilyProperties();
            VkQueueFamilyProperties[] properties = vkAPI.QueueFamilyProperties(physicalDevice);
            uint index;

            for (index = 0; index < properties.Length; ++index)
            {
                VkBool32 supported;
                //physicalDevice.GetSurfaceSupportKHR(index, surface, out supported);
                vkAPI.vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, index, surface, &supported).Check();
                if (!supported)
                {
                    continue;
                }

                if (properties[index].queueFlags.HasFlag(VkQueueFlagBits.Graphics))
                {
                    break;
                }
            }

            var queueInfo = new VkDeviceQueueCreateInfo {
                sType = VkStructureType.DeviceQueueCreateInfo
            };

            queueInfo.queuePriorities  = 1.0f;
            queueInfo.queueFamilyIndex = index;

            var info = new VkDeviceCreateInfo {
                sType = VkStructureType.DeviceCreateInfo
            };

            info.EnabledExtensions = vkAPI.VK_KHR_swapchain;
            info.queueCreateInfos  = queueInfo;

            VkDevice vkDevice;

            //physicalDevice.CreateDevice(ref deviceInfo, null, out device);
            vkAPI.vkCreateDevice(physicalDevice, &info, null, &vkDevice).Check();

            info.Free();
            queueInfo.Free();

            return(vkDevice);
        }
Ejemplo n.º 7
0
        void CreateDevice()
        {
            var features = physicalDevice.Features;

            var uniqueIndices = new HashSet <int> {
                graphicsIndex, presentIndex
            };
            var priorities = new List <float> {
                1f
            };
            var queueInfos = new List <VkDeviceQueueCreateInfo>(uniqueIndices.Count);

            int i = 0;

            foreach (var ind in uniqueIndices)
            {
                var queueInfo = new VkDeviceQueueCreateInfo {
                    queueFamilyIndex = ind,
                    queueCount       = 1,
                    priorities       = priorities
                };

                queueInfos.Add(queueInfo);
                i++;
            }

            var info = new VkDeviceCreateInfo {
                extensions       = deviceExtensions,
                queueCreateInfos = queueInfos,
                features         = features
            };

            device = new VkDevice(physicalDevice, info);

            graphicsQueue = device.GetQueue(graphicsIndex, 0);
            presentQueue  = device.GetQueue(presentIndex, 0);
        }
Ejemplo n.º 8
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);
        }
Ejemplo n.º 9
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);
        }
Ejemplo n.º 10
0
            protected override void Initialize()
            {
                var result = vkInitialize();

                result.CheckResult();

                var version         = vkEnumerateInstanceVersion();
                var queryExtensions = vkEnumerateInstanceExtensionProperties();
                var queryLayers     = vkEnumerateInstanceLayerProperties();

                VkString name    = "01-ClearScreen";
                var      appInfo = new VkApplicationInfo
                {
                    sType              = VkStructureType.ApplicationInfo,
                    pApplicationName   = name,
                    applicationVersion = new VkVersion(1, 0, 0),
                    pEngineName        = s_EngineName,
                    engineVersion      = new VkVersion(1, 0, 0),
                    apiVersion         = VkVersion.Version_1_0,
                };

                var instanceExtensions = new List <string>
                {
                    KHRSurfaceExtensionName,
                    KHRWin32SurfaceExtensionName
                };

                var instanceLayers = new List <string>();

                if (EnableValidationLayers)
                {
                    FindValidationLayers(instanceLayers);
                }

                if (instanceLayers.Count > 0)
                {
                    instanceExtensions.Add(EXTDebugUtilsExtensionName);
                }

                using var vkInstanceExtensions = new VkStringArray(instanceExtensions);
                var instanceCreateInfo = new VkInstanceCreateInfo
                {
                    sType                   = VkStructureType.InstanceCreateInfo,
                    pApplicationInfo        = &appInfo,
                    enabledExtensionCount   = vkInstanceExtensions.Length,
                    ppEnabledExtensionNames = vkInstanceExtensions
                };

                using var vkLayerNames = new VkStringArray(instanceLayers);
                if (instanceLayers.Count > 0)
                {
                    instanceCreateInfo.enabledLayerCount   = vkLayerNames.Length;
                    instanceCreateInfo.ppEnabledLayerNames = vkLayerNames;
                }

                result = vkCreateInstance(&instanceCreateInfo, null, out instance);
                vkLoadInstance(instance);

                if (instanceLayers.Count > 0)
                {
                    _debugMessengerCallbackFunc = DebugMessengerCallback;
                    var debugCreateInfo = new VkDebugUtilsMessengerCreateInfoEXT
                    {
                        sType           = VkStructureType.DebugUtilsMessengerCreateInfoEXT,
                        messageSeverity = /*VkDebugUtilsMessageSeverityFlagsEXT.VerboseEXT | */ VkDebugUtilsMessageSeverityFlagsEXT.ErrorEXT | VkDebugUtilsMessageSeverityFlagsEXT.WarningEXT,
                        messageType     = VkDebugUtilsMessageTypeFlagsEXT.GeneralEXT | VkDebugUtilsMessageTypeFlagsEXT.ValidationEXT | VkDebugUtilsMessageTypeFlagsEXT.PerformanceEXT,
                        pfnUserCallback = Marshal.GetFunctionPointerForDelegate(_debugMessengerCallbackFunc)
                    };

                    vkCreateDebugUtilsMessengerEXT(instance, &debugCreateInfo, null, out debugMessenger).CheckResult();
                }

                var surfaceCreateInfo = new VkWin32SurfaceCreateInfoKHR
                {
                    sType     = VkStructureType.Win32SurfaceCreateInfoKHR,
                    hinstance = HInstance,
                    hwnd      = MainWindow.Handle
                };

                result = vkCreateWin32SurfaceKHR(instance, &surfaceCreateInfo, null, out surface);

                var physicalDevices = vkEnumeratePhysicalDevices(instance);

                foreach (var physicalDevice in physicalDevices)
                {
                    vkGetPhysicalDeviceProperties(physicalDevice, out var properties);
                    var deviceName = properties.GetDeviceName();
                }

                physicalDevice = physicalDevices[0];

                var queueFamilies = FindQueueFamilies(physicalDevice, surface);

                var priority        = 1.0f;
                var queueCreateInfo = new VkDeviceQueueCreateInfo
                {
                    sType            = VkStructureType.DeviceQueueCreateInfo,
                    queueFamilyIndex = queueFamilies.graphicsFamily,
                    queueCount       = 1,
                    pQueuePriorities = &priority
                };

                List <string> deviceExtensions = new List <string>
                {
                    KHRSwapchainExtensionName
                };
                var deviceCreateInfo = new VkDeviceCreateInfo
                {
                    sType                = VkStructureType.DeviceCreateInfo,
                    pQueueCreateInfos    = &queueCreateInfo,
                    queueCreateInfoCount = 1,
                    pEnabledFeatures     = null,
                };

                using var deviceExtensionNames           = new VkStringArray(deviceExtensions);
                deviceCreateInfo.enabledExtensionCount   = deviceExtensionNames.Length;
                deviceCreateInfo.ppEnabledExtensionNames = deviceExtensionNames;

                result = vkCreateDevice(physicalDevice, &deviceCreateInfo, null, out device);
                if (result != VkResult.Success)
                {
                    throw new Exception($"Failed to create Vulkan Logical Device, {result}");
                }

                vkGetDeviceQueue(device, queueFamilies.graphicsFamily, 0, out graphicsQueue);
                vkGetDeviceQueue(device, queueFamilies.presentFamily, 0, out presentQueue);

                CreateSwapchain();
                CreateSyncPrimitives();
            }
Ejemplo n.º 11
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);
            }
        }
Ejemplo n.º 12
0
        internal void CreateDevice()
        {
            VkDeviceQueueCreateInfo *queueCreateInfos = stackalloc VkDeviceQueueCreateInfo[3];

            float defaultQueuePriority = 0.0f;

            VkQueueFlags requestedQueueTypes = VkQueueFlags.Graphics | VkQueueFlags.Compute | VkQueueFlags.Transfer;


            // Graphics queue
            if ((requestedQueueTypes & VkQueueFlags.Graphics) != 0)
            {
                GraphicsFamily = GetQueueFamilyIndex(VkQueueFlags.Graphics, QueueFamilyProperties);

                VkDeviceQueueCreateInfo queueInfo = new VkDeviceQueueCreateInfo
                {
                    sType            = VkStructureType.DeviceQueueCreateInfo,
                    queueFamilyIndex = GraphicsFamily,
                    queueCount       = 1,
                    pQueuePriorities = &defaultQueuePriority
                };

                queueCreateInfos[0] = (queueInfo);
            }
            else
            {
                GraphicsFamily = (uint)NullHandle;
            }



            // Dedicated compute queue
            if ((requestedQueueTypes & VkQueueFlags.Compute) != 0)
            {
                ComputeFamily = GetQueueFamilyIndex(VkQueueFlags.Compute, QueueFamilyProperties);

                if (ComputeFamily != GraphicsFamily)
                {
                    // If compute family index differs, we need an additional queue create info for the compute queue
                    VkDeviceQueueCreateInfo queueInfo = new VkDeviceQueueCreateInfo
                    {
                        sType            = VkStructureType.DeviceQueueCreateInfo,
                        queueFamilyIndex = ComputeFamily,
                        queueCount       = 1,
                        pQueuePriorities = &defaultQueuePriority
                    };

                    queueCreateInfos[1] = (queueInfo);
                }
            }
            else
            {
                // Else we use the same queue
                ComputeFamily = GraphicsFamily;
            }


            // Dedicated transfer queue
            if ((requestedQueueTypes & VkQueueFlags.Transfer) != 0)
            {
                TransferFamily = GetQueueFamilyIndex(VkQueueFlags.Transfer, QueueFamilyProperties);

                if (TransferFamily != GraphicsFamily && TransferFamily != ComputeFamily)
                {
                    // If compute family index differs, we need an additional queue create info for the transfer queue
                    VkDeviceQueueCreateInfo queueInfo = new VkDeviceQueueCreateInfo
                    {
                        sType            = VkStructureType.DeviceQueueCreateInfo,
                        queueFamilyIndex = TransferFamily,
                        queueCount       = 1,
                        pQueuePriorities = &defaultQueuePriority
                    };

                    queueCreateInfos[2] = (queueInfo);
                }
            }
            else
            {
                // Else we use the same queue
                TransferFamily = GraphicsFamily;
            }


            // Create the logical device representation
            List <string> deviceExtensions = new List <string>();

            // If the device will be used for presenting to a display via a swapchain we need to request the swapchain extension
            deviceExtensions.Add("VK_KHR_swapchain");

            var oldFeatures = Features;
            VkDeviceCreateInfo deviceCreateInfo = VkDeviceCreateInfo.New();

            deviceCreateInfo.queueCreateInfoCount = 3;
            deviceCreateInfo.pQueueCreateInfos    = queueCreateInfos;
            deviceCreateInfo.pEnabledFeatures     = &oldFeatures;

            if (deviceExtensions.Count > 0)
            {
                deviceCreateInfo.enabledExtensionCount   = (uint)deviceExtensions.Count;
                deviceCreateInfo.ppEnabledExtensionNames = Interop.String.AllocToPointers(deviceExtensions.ToArray());
            }

            vkCreateDevice(NativeAdapter.NativePhysicalDevice, &deviceCreateInfo, null, out var device);

            Device = device;
        }
Ejemplo n.º 13
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);
                }
            }
        }
Ejemplo n.º 14
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 ?¿?¿
            }
        }
Ejemplo n.º 15
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);
        }
Ejemplo n.º 16
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.Last();

            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,
            };

            vkGetPhysicalDeviceFeatures(NativePhysicalDevice, out VkPhysicalDeviceFeatures features);

            var enabledFeature = new VkPhysicalDeviceFeatures
            {
                fillModeNonSolid   = features.fillModeNonSolid,
                shaderClipDistance = features.shaderClipDistance,
                shaderCullDistance = features.shaderCullDistance,
                samplerAnisotropy  = features.samplerAnisotropy,
                depthClamp         = features.depthClamp,
            };

            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("VK_KHR_swapchain");
            desiredExtensionNames.Add("VK_KHR_external_memory");
            desiredExtensionNames.Add("VK_KHR_external_semaphore");
            desiredExtensionNames.Add("VK_KHR_dedicated_allocation");
            desiredExtensionNames.Add("VK_KHR_get_memory_requirements2");
            desiredExtensionNames.Add("VK_KHR_external_memory_win32");
            desiredExtensionNames.Add("VK_KHR_win32_keyed_mutex");

            if (!availableExtensionNames.Contains("VK_KHR_swapchain"))
            {
                throw new InvalidOperationException();
            }

            if (availableExtensionNames.Contains("VK_EXT_debug_marker") && IsDebugMode)
            {
                desiredExtensionNames.Add("VK_EXT_debug_marker");
                IsProfilingSupported = true;
            }

            // take out any extensions not supported
            for (int i = 0; i < desiredExtensionNames.Count; i++)
            {
                if (availableExtensionNames.Contains(desiredExtensionNames[i]) == false)
                {
                    desiredExtensionNames.RemoveAt(i);
                    i--;
                }
            }

            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);

            //// 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 NativeCopyCommandPool);

            var commandBufferAllocationInfo = new VkCommandBufferAllocateInfo
            {
                sType              = VkStructureType.CommandBufferAllocateInfo,
                level              = VkCommandBufferLevel.Primary,
                commandPool        = NativeCopyCommandPool,
                commandBufferCount = 1
            };
            VkCommandBuffer nativeCommandBuffer;

            vkAllocateCommandBuffers(NativeDevice, &commandBufferAllocationInfo, &nativeCommandBuffer);
            NativeCopyCommandBuffer = nativeCommandBuffer;

            DescriptorPools = new HeapPool(this);

            nativeResourceCollector       = new NativeResourceCollector(this);
            graphicsResourceLinkCollector = new GraphicsResourceLinkCollector(this);

            EmptyTexelBuffer = Buffer.Typed.New(this, 1, PixelFormat.R32G32B32A32_Float);
            EmptyTexture     = Texture.New2D(this, 1, 1, PixelFormat.R8G8B8A8_UNorm_SRgb, TextureFlags.ShaderResource);

            // prepare upload buffer now
            // Allocate buffer that will be recycled
            nativeUploadBufferSize = Buffer.UploadBufferSizeInMB * 1024 * 1024;

            var bufferCreateInfo = new VkBufferCreateInfo
            {
                sType = VkStructureType.BufferCreateInfo,
                size  = (ulong)nativeUploadBufferSize,
                flags = VkBufferCreateFlags.None,
                usage = VkBufferUsageFlags.TransferSrc,
            };

            vkCreateBuffer(NativeDevice, &bufferCreateInfo, null, out nativeUploadBuffer);
            AllocateMemory(VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent);

            fixed(IntPtr *nativeUploadBufferStartPtr = &nativeUploadBufferStart)
            vkMapMemory(NativeDevice, nativeUploadBufferMemory, 0, (ulong)nativeUploadBufferSize, VkMemoryMapFlags.None, (void **)nativeUploadBufferStartPtr);

            nativeUploadBufferOffset = 0;
        }
Ejemplo n.º 17
0
        protected override void FirstWindowCreated()
        {
            VK = new VK(this);

            // Debug Callback
            if (HasValidationLayers)
            {
                DebugMessenger = CreateDebugMessenger((messageSeverity, messageTypes, pCallbackData, pUserData) =>
                {
                    var message = VK.STRING(pCallbackData->pMessage);

                    if (messageSeverity.HasFlag(VkDebugUtilsMessageSeverityFlagsEXT.Error))
                    {
                        Log.Error(Name, message);
                    }
                    else if (messageSeverity.HasFlag(VkDebugUtilsMessageSeverityFlagsEXT.Warning))
                    {
                        Log.Warning(Name, message);
                    }
                    else
                    {
                        Log.Message(Name, message);
                    }

                    return(VkConst.FALSE);
                });
            }

            // Pick a Physical Device
            PhysicalDevice = PickPhysicalDevice();

            // get the API version
            {
                VkPhysicalDeviceProperties properties;
                VK.GetPhysicalDeviceProperties(PhysicalDevice, &properties);
                ApiVersion = VK.UNMAKE_VERSION(properties.apiVersion);

                int length = 0;
                while (length < VkConst.MAX_PHYSICAL_DEVICE_NAME_SIZE && properties.deviceName[length] != 0)
                {
                    length++;
                }
                DeviceName = Encoding.UTF8.GetString(properties.deviceName, length);
            }

            // Create the Device
            {
                TryGetQueueFamilyIndex(PhysicalDevice, VkQueueFlags.GraphicsBit, out uint graphicsFamilyIndex);

                // Graphics Family Queue
                var priority        = 1.0f;
                var queueCreateInfo = new VkDeviceQueueCreateInfo
                {
                    sType            = VkStructureType.DeviceQueueCreateInfo,
                    queueFamilyIndex = graphicsFamilyIndex,
                    queueCount       = 1,
                    pQueuePriorities = &priority
                };

                // Device Features
                var deviceFeatures = new VkPhysicalDeviceFeatures();

                var createInfo = new VkDeviceCreateInfo
                {
                    sType                = VkStructureType.DeviceCreateInfo,
                    pQueueCreateInfos    = &queueCreateInfo,
                    queueCreateInfoCount = 1,
                    pEnabledFeatures     = &deviceFeatures,
                };

                // Device Extensions
                using var deviceExtensionNames     = new NativeStringArray(deviceExtensions);
                createInfo.enabledExtensionCount   = deviceExtensionNames.Length;
                createInfo.ppEnabledExtensionNames = deviceExtensionNames;

                var result = VK.CreateDevice(PhysicalDevice, &createInfo, null, out Device);
                if (result != VkResult.Success)
                {
                    throw new Exception($"Failed to create Vulkan Logical Device, {result}");
                }

                // Get the Graphics Queue
                VK.GetDeviceQueue(Device, graphicsFamilyIndex, 0, out GraphicsQueue);
            }
        }
Ejemplo n.º 18
0
        public GraphicsDevice(string applicationName, bool enableValidation, Window?window)
        {
            VkString name    = applicationName;
            var      appInfo = new VkApplicationInfo
            {
                sType              = VkStructureType.ApplicationInfo,
                pApplicationName   = name,
                applicationVersion = new VkVersion(1, 0, 0),
                pEngineName        = s_EngineName,
                engineVersion      = new VkVersion(1, 0, 0),
                apiVersion         = vkEnumerateInstanceVersion()
            };

            List <string> instanceExtensions = new List <string>
            {
                KHRSurfaceExtensionName
            };

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                instanceExtensions.Add(KHRWin32SurfaceExtensionName);
            }

            List <string> instanceLayers = new List <string>();

            if (enableValidation)
            {
                FindValidationLayers(instanceLayers);
            }

            if (instanceLayers.Count > 0)
            {
                instanceExtensions.Add(EXTDebugUtilsExtensionName);
            }

            using var vkInstanceExtensions = new VkStringArray(instanceExtensions);

            var instanceCreateInfo = new VkInstanceCreateInfo
            {
                sType                   = VkStructureType.InstanceCreateInfo,
                pApplicationInfo        = &appInfo,
                enabledExtensionCount   = vkInstanceExtensions.Length,
                ppEnabledExtensionNames = vkInstanceExtensions
            };

            using var vkLayerNames = new VkStringArray(instanceLayers);
            if (instanceLayers.Count > 0)
            {
                instanceCreateInfo.enabledLayerCount   = vkLayerNames.Length;
                instanceCreateInfo.ppEnabledLayerNames = vkLayerNames;
            }

            var debugUtilsCreateInfo = new VkDebugUtilsMessengerCreateInfoEXT
            {
                sType = VkStructureType.DebugUtilsMessengerCreateInfoEXT
            };

            if (instanceLayers.Count > 0)
            {
                _debugMessengerCallbackFunc          = DebugMessengerCallback;
                debugUtilsCreateInfo.messageSeverity = VkDebugUtilsMessageSeverityFlagsEXT.Error | VkDebugUtilsMessageSeverityFlagsEXT.Warning;
                debugUtilsCreateInfo.messageType     = VkDebugUtilsMessageTypeFlagsEXT.Validation | VkDebugUtilsMessageTypeFlagsEXT.Performance;
                debugUtilsCreateInfo.pfnUserCallback = Marshal.GetFunctionPointerForDelegate(_debugMessengerCallbackFunc);

                instanceCreateInfo.pNext = &debugUtilsCreateInfo;
            }

            VkResult result = vkCreateInstance(&instanceCreateInfo, null, out VkInstance);

            if (result != VkResult.Success)
            {
                throw new InvalidOperationException($"Failed to create vulkan instance: {result}");
            }

            vkLoadInstance(VkInstance);

            if (instanceLayers.Count > 0)
            {
                vkCreateDebugUtilsMessengerEXT(VkInstance, &debugUtilsCreateInfo, null, out _debugMessenger).CheckResult();
            }

            Log.Info($"Created VkInstance with version: {appInfo.apiVersion.Major}.{appInfo.apiVersion.Minor}.{appInfo.apiVersion.Patch}");
            if (instanceLayers.Count > 0)
            {
                foreach (var layer in instanceLayers)
                {
                    Log.Info($"Instance layer '{layer}'");
                }
            }

            foreach (string extension in instanceExtensions)
            {
                Log.Info($"Instance extension '{extension}'");
            }

            _surface = CreateSurface(window);

            // Find physical device, setup queue's and create device.
            var physicalDevices = vkEnumeratePhysicalDevices(VkInstance);

            foreach (var physicalDevice in physicalDevices)
            {
                vkGetPhysicalDeviceProperties(physicalDevice, out var properties);
                var deviceName = properties.GetDeviceName();
            }

            PhysicalDevice = physicalDevices[0];

            var queueFamilies = FindQueueFamilies(PhysicalDevice, _surface);

            var priority        = 1.0f;
            var queueCreateInfo = new VkDeviceQueueCreateInfo
            {
                sType            = VkStructureType.DeviceQueueCreateInfo,
                queueFamilyIndex = queueFamilies.graphicsFamily,
                queueCount       = 1,
                pQueuePriorities = &priority
            };

            List <string> deviceExtensions = new List <string>
            {
                KHRSwapchainExtensionName
            };
            var deviceCreateInfo = new VkDeviceCreateInfo
            {
                sType                = VkStructureType.DeviceCreateInfo,
                pQueueCreateInfos    = &queueCreateInfo,
                queueCreateInfoCount = 1,
                pEnabledFeatures     = null,
            };

            using var deviceExtensionNames           = new VkStringArray(deviceExtensions);
            deviceCreateInfo.enabledExtensionCount   = deviceExtensionNames.Length;
            deviceCreateInfo.ppEnabledExtensionNames = deviceExtensionNames;

            result = vkCreateDevice(PhysicalDevice, &deviceCreateInfo, null, out VkDevice);
            if (result != VkResult.Success)
            {
                throw new Exception($"Failed to create Vulkan Logical Device, {result}");
            }

            vkGetDeviceQueue(VkDevice, queueFamilies.graphicsFamily, 0, out GraphicsQueue);
            vkGetDeviceQueue(VkDevice, queueFamilies.presentFamily, 0, out PresentQueue);

            // Create swap chain
            Swapchain = new Swapchain(this, window);
            _perFrame = new PerFrame[Swapchain.ImageCount];
            for (var i = 0; i < _perFrame.Length; i++)
            {
                VkFenceCreateInfo fenceCreateInfo = new VkFenceCreateInfo(VkFenceCreateFlags.Signaled);
                vkCreateFence(VkDevice, &fenceCreateInfo, null, out _perFrame[i].QueueSubmitFence).CheckResult();

                VkCommandPoolCreateInfo poolCreateInfo = new VkCommandPoolCreateInfo
                {
                    sType            = VkStructureType.CommandPoolCreateInfo,
                    flags            = VkCommandPoolCreateFlags.Transient,
                    queueFamilyIndex = queueFamilies.graphicsFamily,
                };
                vkCreateCommandPool(VkDevice, &poolCreateInfo, null, out _perFrame[i].PrimaryCommandPool).CheckResult();

                VkCommandBufferAllocateInfo commandBufferInfo = new VkCommandBufferAllocateInfo
                {
                    sType              = VkStructureType.CommandBufferAllocateInfo,
                    commandPool        = _perFrame[i].PrimaryCommandPool,
                    level              = VkCommandBufferLevel.Primary,
                    commandBufferCount = 1
                };
                vkAllocateCommandBuffers(VkDevice, &commandBufferInfo, out _perFrame[i].PrimaryCommandBuffer).CheckResult();
            }
        }
Ejemplo n.º 19
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));
        }
Ejemplo n.º 20
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);
        }
Ejemplo n.º 21
0
        public VulkanContext(VkInstance instance, VkSurfaceKHR surface, Platform platform)
        {
            // Find graphics and presentation capable physical device(s) that support
            // the provided surface for platform.
            int graphicsQueueFamilyIndex = -1;
            int computeQueueFamilyIndex  = -1;
            int presentQueueFamilyIndex  = -1;

            var physicalDevices = vkEnumeratePhysicalDevices(instance);

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

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

                vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &Count, queueFamilyPropertiesptr);

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

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

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

                            if (presentationSupport)
                            {
                                presentQueueFamilyIndex = i;
                            }
                        }

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

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

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

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

            float defaultQueuePriority = 1.0f;

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

            queueCreateInfos[0] = queueInfoGraphics;

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

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

            deviceCreateInfo.pEnabledFeatures = &features;

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

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

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

            result2.CheckResult();

            Device = device;

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

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

            GraphicsCommandPool = CreateCommandPool((uint)graphicsQueueFamilyIndex);
            ComputeCommandPool  = CreateCommandPool((uint)computeQueueFamilyIndex);
        }
Ejemplo n.º 22
0
        public static void Init()
        {
            optionalExtn_avail      = new bool[optionalDeviceExtns.Length];
            Console.BackgroundColor = ConsoleColor.Black;
            Console.ForegroundColor = ConsoleColor.White;
            Window = new GameWindow(AppName);
            fixed(IntPtr *instancePtr = &instanceHndl)
            fixed(IntPtr * surfacePtr = &surfaceHndl)
            {
                VkResult res;
                var      instLayers  = new List <string>();
                var      instExtns   = new List <string>();
                var      devExtns    = new List <string>();
                uint     glfwExtnCnt = 0;
                var      glfwExtns   = glfwGetRequiredInstanceExtensions(&glfwExtnCnt);

                for (int i = 0; i < glfwExtnCnt; i++)
                {
                    instExtns.Add(Marshal.PtrToStringAnsi(glfwExtns[i]));
                }

                instExtns.Add(VkKhrGetPhysicalDeviceProperties2ExtensionName);

                if (EnableValidation)
                {
                    instLayers.Add("VK_LAYER_KHRONOS_validation");
                    instExtns.Add(VkExtDebugUtilsExtensionName);
                }

                var layers = stackalloc IntPtr[instLayers.Count];

                for (int i = 0; i < instLayers.Count; i++)
                {
                    layers[i] = Marshal.StringToHGlobalAnsi(instLayers[i]);
                }

                var extns = stackalloc IntPtr[instExtns.Count];

                for (int i = 0; i < instExtns.Count; i++)
                {
                    extns[i] = Marshal.StringToHGlobalAnsi(instExtns[i]);
                }
                {
                    var appInfo =
                        new VkApplicationInfo()
                    {
                        sType              = VkStructureType.StructureTypeApplicationInfo,
                        pApplicationName   = AppName,
                        pEngineName        = EngineName,
                        apiVersion         = VkApiVersion12,
                        applicationVersion = 1,
                        engineVersion      = 1,
                        pNext              = IntPtr.Zero
                    };
                    var appInfo_ptr = appInfo.Pointer();

                    var instCreatInfo = new VkInstanceCreateInfo()
                    {
                        sType            = VkStructureType.StructureTypeInstanceCreateInfo,
                        pApplicationInfo = appInfo_ptr,
                    };

                    instCreatInfo.ppEnabledLayerNames     = layers;
                    instCreatInfo.enabledLayerCount       = (uint)instLayers.Count;
                    instCreatInfo.ppEnabledExtensionNames = extns;
                    instCreatInfo.enabledExtensionCount   = (uint)instExtns.Count;

                    var instCreatInfo_ptr = instCreatInfo.Pointer();

                    //register instance create debug message handler
                    debugCreatInfo = new VkDebugUtilsMessengerCreateInfoEXT()
                    {
                        sType           = VkStructureType.StructureTypeDebugUtilsMessengerCreateInfoExt,
                        messageSeverity = VkDebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityErrorBitExt | VkDebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityWarningBitExt | VkDebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityVerboseBitExt | VkDebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityInfoBitExt,
                        messageType     = VkDebugUtilsMessageTypeFlagsEXT.DebugUtilsMessageTypeGeneralBitExt | VkDebugUtilsMessageTypeFlagsEXT.DebugUtilsMessageTypePerformanceBitExt | VkDebugUtilsMessageTypeFlagsEXT.DebugUtilsMessageTypeValidationBitExt,
                        pfnUserCallback = DebugCallback
                    };
                    var debugCreatInfo_ptr = debugCreatInfo.Pointer();

                    if (EnableValidation)
                    {
                        instCreatInfo.pNext = debugCreatInfo_ptr;
                    }

                    res = vkCreateInstance(instCreatInfo_ptr, null, instancePtr);
                    if (res != VkResult.Success)
                    {
                        throw new Exception("Failed to create instance.");
                    }
                }

                if (EnableValidation)
                {
                    SetupDebugMessengers(instanceHndl);
                    var debugCreatInfo_ptr = debugCreatInfo.Pointer();

                    fixed(IntPtr *dbg_ptr = &debugMessenger)
                    res = CreateDebugUtilsMessengerEXT(instanceHndl, debugCreatInfo_ptr, IntPtr.Zero, dbg_ptr);

                    if (res != VkResult.Success)
                    {
                        throw new Exception("Failed to register debug callback.");
                    }
                }

                res = Window.CreateSurface(instanceHndl, surfacePtr);
                if (res != VkResult.Success)
                {
                    throw new Exception("Failed to create surface.");
                }

                uint devCount = 0;

                vkEnumeratePhysicalDevices(instanceHndl, &devCount, null);
                if (devCount == 0)
                {
                    throw new Exception("Failed to find Vulkan compatible devices.");
                }

                var devices = new IntPtr[devCount];

                fixed(IntPtr *devicesPtr = devices)
                vkEnumeratePhysicalDevices(instanceHndl, &devCount, devicesPtr);

                var ratedDevices = new List <(uint, IntPtr)>();

                for (int i = 0; i < devices.Length; i++)
                {
                    //rate each device
                    ratedDevices.Add((RateDevice(devices[i]), devices[i]));
                }
                var orderedDevices = ratedDevices.OrderByDescending(a => a.Item1)
                                     .Select(a => a.Item2)
                                     .ToArray();

                DeviceInformation    = new DeviceInfo[orderedDevices.Length];
                DeviceInformation[0] = new DeviceInfo()
                {
                    PhysicalDevice = orderedDevices[0]
                };
                //TODO for now just choose the first device

                {
                    //allocate queues for primary device
                    uint graphicsFamily = ~0u;
                    uint computeFamily  = ~0u;
                    uint transferFamily = ~0u;
                    uint presentFamily  = ~0u;

                    uint qfam_cnt = 0;
                    vkGetPhysicalDeviceQueueFamilyProperties(orderedDevices[0], &qfam_cnt, null);
                    var qFams_ptr = new ManagedPtrArray <VkQueueFamilyProperties>(qfam_cnt);
                    vkGetPhysicalDeviceQueueFamilyProperties(orderedDevices[0], &qfam_cnt, qFams_ptr);
                    var qFams = qFams_ptr.Value;

                    uint qFamIdx = 0;
                    foreach (var qFam in qFams)
                    {
                        bool presentSupport = false;
                        vkGetPhysicalDeviceSurfaceSupportKHR(orderedDevices[0], qFamIdx, surfaceHndl, &presentSupport);

                        if ((qFam.queueFlags & VkQueueFlags.QueueGraphicsBit) != 0 && graphicsFamily == ~0u)
                        {
                            graphicsFamily = qFamIdx;
                            if (presentSupport)
                            {
                                presentFamily = qFamIdx;
                            }
                            qFamIdx++;
                            continue;
                        }

                        if ((qFam.queueFlags & VkQueueFlags.QueueComputeBit) != 0 && computeFamily == ~0u)
                        {
                            computeFamily = qFamIdx;
                            if ((qFam.queueFlags & VkQueueFlags.QueueTransferBit) != 0)
                            {
                                transferFamily = qFamIdx;
                            }
                            qFamIdx++;
                            continue;
                        }

                        if ((qFam.queueFlags & VkQueueFlags.QueueTransferBit) != 0)
                        {
                            transferFamily = qFamIdx;
                        }

                        if (graphicsFamily != ~0u && computeFamily != ~0u && transferFamily != ~0u && presentFamily != ~0u)
                        {
                            break;
                        }
                        qFamIdx++;
                    }

                    if (presentFamily == ~0u)
                    {
                        throw new Exception("Separate present queue support hasn't been implemented.");
                    }

                    var max_q_priority          = stackalloc float[] { 1.0f };
                    var dual_graph_q_priority   = stackalloc float[] { 1.0f };
                    var triple_graph_q_priority = stackalloc float[] { 1.0f, 1.0f, 1.0f };

                    VkDeviceQueueCreateInfo graphics_qCreatInfo = new VkDeviceQueueCreateInfo()
                    {
                        sType            = VkStructureType.StructureTypeDeviceQueueCreateInfo,
                        queueFamilyIndex = graphicsFamily,
                        queueCount       = 1,
                        pQueuePriorities = max_q_priority
                    };

                    VkDeviceQueueCreateInfo compute_qCreatInfo = new VkDeviceQueueCreateInfo
                    {
                        sType            = VkStructureType.StructureTypeDeviceQueueCreateInfo,
                        queueFamilyIndex = computeFamily,
                        queueCount       = 1,
                        pQueuePriorities = max_q_priority
                    };

                    VkDeviceQueueCreateInfo transfer_qCreatInfo = new VkDeviceQueueCreateInfo();
                    if (transferFamily != graphicsFamily)
                    {
                        transfer_qCreatInfo.sType            = VkStructureType.StructureTypeDeviceQueueCreateInfo;
                        transfer_qCreatInfo.queueFamilyIndex = transferFamily;
                        transfer_qCreatInfo.queueCount       = 1;
                        transfer_qCreatInfo.pQueuePriorities = max_q_priority;
                    }
                    else
                    {
                        graphics_qCreatInfo.queueCount       = 2;
                        graphics_qCreatInfo.pQueuePriorities = dual_graph_q_priority;
                    }


                    var qCreatInfos = new VkDeviceQueueCreateInfo[3];
                    qCreatInfos[0] = graphics_qCreatInfo;
                    qCreatInfos[1] = compute_qCreatInfo;
                    if (transferFamily != graphicsFamily)
                    {
                        qCreatInfos[2] = transfer_qCreatInfo;
                    }

                    DeviceInformation[0].GraphicsFamily = graphicsFamily;
                    DeviceInformation[0].ComputeFamily  = computeFamily;
                    DeviceInformation[0].TransferFamily = transferFamily;
                    DeviceInformation[0].PresentFamily  = presentFamily;

                    VkPhysicalDeviceFeatures devFeats = new VkPhysicalDeviceFeatures()
                    {
                        multiDrawIndirect              = true,
                        drawIndirectFirstInstance      = true,
                        fullDrawIndexUint32            = true,
                        tessellationShader             = true,
                        fragmentStoresAndAtomics       = true,
                        vertexPipelineStoresAndAtomics = true,
                        robustBufferAccess             = EnableValidation,
                        shaderInt16       = true,
                        samplerAnisotropy = true,
                        fillModeNonSolid  = true,
                        largePoints       = true,
                    };

                    var devFeats11 = new VkPhysicalDeviceVulkan11Features()
                    {
                        sType = VkStructureType.StructureTypePhysicalDeviceVulkan11Features,
                        shaderDrawParameters = true,
                        //storageBuffer16BitAccess = true,
                        //uniformAndStorageBuffer16BitAccess = true,
                        //storagePushConstant16 = true,
                    };
                    var devFeats11_ptr = devFeats11.Pointer();

                    /*
                     * var depthStenc = new VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures()
                     * {
                     *  sType = VkStructureType.StructureTypePhysicalDeviceSeparateDepthStencilLayoutsFeatures,
                     *  separateDepthStencilLayouts = true,
                     *  pNext = devFeats11_ptr
                     * };
                     * var depthStenc_ptr = depthStenc.Pointer();
                     *
                     * var timelineSems = new VkPhysicalDeviceTimelineSemaphoreFeatures()
                     * {
                     *  sType = VkStructureType.StructureTypePhysicalDeviceTimelineSemaphoreFeatures,
                     *  timelineSemaphore = true,
                     *  pNext = depthStenc_ptr,
                     * };
                     * var timelineSems_ptr = timelineSems.Pointer();
                     *
                     * var indirectCnt = new VkPhysicalDeviceShaderFloat16Int8Features()
                     * {
                     *  sType = VkStructureType.StructureTypePhysicalDeviceShaderFloat16Int8Features,
                     *  shaderFloat16 = true,
                     *  shaderInt8 = true,
                     *  pNext = timelineSems_ptr,
                     * };
                     * var indirectCnt_ptr = indirectCnt.Pointer();
                     *
                     * var uboLayout = new VkPhysicalDeviceUniformBufferStandardLayoutFeatures()
                     * {
                     *  sType = VkStructureType.StructureTypePhysicalDeviceUniformBufferStandardLayoutFeatures,
                     *  uniformBufferStandardLayout = true,
                     *  pNext = indirectCnt_ptr
                     * };
                     * var uboLayout_ptr = uboLayout.Pointer();
                     *
                     * var storageByte = new VkPhysicalDevice8BitStorageFeatures()
                     * {
                     *  sType = VkStructureType.StructureTypePhysicalDevice8bitStorageFeatures,
                     *  storageBuffer8BitAccess = true,
                     *  uniformAndStorageBuffer8BitAccess = true,
                     *  pNext = uboLayout_ptr
                     * };
                     * var storageByte_ptr = storageByte.Pointer();
                     * var descIndexing = new VkPhysicalDeviceDescriptorIndexingFeatures()
                     * {
                     *  sType = VkStructureType.StructureTypePhysicalDeviceDescriptorIndexingFeatures,
                     *  descriptorBindingSampledImageUpdateAfterBind = true,
                     *  descriptorBindingStorageBufferUpdateAfterBind = true,
                     *  descriptorBindingStorageImageUpdateAfterBind = true,
                     *  descriptorBindingStorageTexelBufferUpdateAfterBind = true,
                     *  descriptorBindingUniformBufferUpdateAfterBind = true,
                     *  descriptorBindingUniformTexelBufferUpdateAfterBind = true,
                     *  descriptorBindingUpdateUnusedWhilePending = true,
                     *  descriptorBindingPartiallyBound = true,
                     *  shaderStorageTexelBufferArrayDynamicIndexing = true,
                     *  pNext = storageByte_ptr,
                     * };
                     * var descIndexing_ptr = descIndexing.Pointer();*/

                    //var drawIndirectCount = new VkDrawIndirecCount

                    var devFeats12 = new VkPhysicalDeviceVulkan12Features()
                    {
                        sType = VkStructureType.StructureTypePhysicalDeviceVulkan12Features,
                        separateDepthStencilLayouts = true,
                        timelineSemaphore           = true,
                        drawIndirectCount           = true,
                        shaderFloat16 = true,
                        shaderInt8    = true,
                        uniformBufferStandardLayout       = true,
                        storageBuffer8BitAccess           = true,
                        uniformAndStorageBuffer8BitAccess = true,
                        descriptorIndexing = true,
                        descriptorBindingSampledImageUpdateAfterBind       = true,
                        descriptorBindingStorageBufferUpdateAfterBind      = true,
                        descriptorBindingStorageImageUpdateAfterBind       = true,
                        descriptorBindingStorageTexelBufferUpdateAfterBind = true,
                        descriptorBindingUniformBufferUpdateAfterBind      = true,
                        descriptorBindingUniformTexelBufferUpdateAfterBind = true,
                        descriptorBindingUpdateUnusedWhilePending          = true,
                        descriptorBindingPartiallyBound = true,
                        shaderStorageTexelBufferArrayDynamicIndexing = true,

                        shaderStorageBufferArrayNonUniformIndexing = true,
                        runtimeDescriptorArray = true,
                        descriptorBindingVariableDescriptorCount = true,

                        pNext = devFeats11_ptr
                    };
                    var devFeats12_ptr = devFeats12.Pointer();

                    devExtns.AddRange(requiredDeviceExtns);
                    for (int i = 0; i < optionalExtn_avail.Length; i++)
                    {
                        if (optionalExtn_avail[i])
                        {
                            devExtns.Add(optionalDeviceExtns[i]);
                        }
                    }
                    var devExtns_ptr = stackalloc IntPtr[devExtns.Count];
                    for (int i = 0; i < devExtns.Count; i++)
                    {
                        devExtns_ptr[i] = Marshal.StringToHGlobalAnsi(devExtns[i]);
                    }

                    var qCreatInfos_ptr = qCreatInfos.Pointer();
                    var devFeats_ptr    = devFeats.Pointer();
                    var devCreatInfo    = new VkDeviceCreateInfo()
                    {
                        sType = VkStructureType.StructureTypeDeviceCreateInfo,
                        queueCreateInfoCount    = (uint)(transferFamily != graphicsFamily ? 3 : 2),
                        enabledExtensionCount   = (uint)devExtns.Count,
                        ppEnabledExtensionNames = devExtns_ptr,
                        enabledLayerCount       = (uint)instLayers.Count,
                        ppEnabledLayerNames     = layers,
                        pEnabledFeatures        = devFeats_ptr,
                        pQueueCreateInfos       = qCreatInfos_ptr,
                        pNext = devFeats12_ptr
                    };
                    var    devCreatInfo_ptr = devCreatInfo.Pointer();
                    IntPtr deviceHndl       = IntPtr.Zero;
                    res = vkCreateDevice(orderedDevices[0], devCreatInfo_ptr, null, &deviceHndl);
                    if (res != VkResult.Success)
                    {
                        throw new Exception("Failed to create logical device.");
                    }
                    DeviceInformation[0].Device = deviceHndl;

                    //Setup memory allocator
                    var allocCreatInfo = new VmaAllocatorCreateInfo()
                    {
                        physicalDevice = DeviceInformation[0].PhysicalDevice,
                        device         = DeviceInformation[0].Device
                    };
                    var allocCreatInfo_ptr = allocCreatInfo.Pointer();

                    fixed(IntPtr *vma_alloc_ptr = &DeviceInformation[0].vmaAllocator)
                    res = vmaCreateAllocator(allocCreatInfo_ptr, vma_alloc_ptr);

                    if (res != VkResult.Success)
                    {
                        throw new Exception("Failed to initialize allocator.");
                    }

                    IntPtr graph_q_hndl = IntPtr.Zero;
                    IntPtr trans_q_hndl = IntPtr.Zero;
                    IntPtr comp_q_hndl  = IntPtr.Zero;
                    vkGetDeviceQueue(DeviceInformation[0].Device, graphicsFamily, 0, &graph_q_hndl);
                    vkGetDeviceQueue(DeviceInformation[0].Device, computeFamily, 0, &comp_q_hndl);
                    if (transferFamily != graphicsFamily)
                    {
                        vkGetDeviceQueue(DeviceInformation[0].Device, transferFamily, 0, &trans_q_hndl);
                    }
                    else
                    {
                        vkGetDeviceQueue(DeviceInformation[0].Device, graphicsFamily, 1, &trans_q_hndl);
                    }

                    DeviceInformation[0].GraphicsQueue = new GpuQueue(CommandQueueKind.Graphics, graph_q_hndl, graphicsFamily, 0);
                    DeviceInformation[0].TransferQueue = new GpuQueue(CommandQueueKind.Transfer, trans_q_hndl, transferFamily, 0);
                    DeviceInformation[0].ComputeQueue  = new GpuQueue(CommandQueueKind.Compute, comp_q_hndl, computeFamily, 0);

                    var queue_indices = new List <uint>();
                    if (!queue_indices.Contains(DeviceInformation[0].GraphicsFamily))
                    {
                        queue_indices.Add(DeviceInformation[0].GraphicsFamily);
                    }
                    if (!queue_indices.Contains(DeviceInformation[0].ComputeFamily))
                    {
                        queue_indices.Add(DeviceInformation[0].ComputeFamily);
                    }
                    if (!queue_indices.Contains(DeviceInformation[0].PresentFamily))
                    {
                        queue_indices.Add(DeviceInformation[0].PresentFamily);
                    }
                    if (!queue_indices.Contains(DeviceInformation[0].TransferFamily))
                    {
                        queue_indices.Add(DeviceInformation[0].TransferFamily);
                    }
                    DeviceInformation[0].QueueFamilyIndices = queue_indices.ToArray();

                    var physDeviceProps = new ManagedPtr <VkPhysicalDeviceProperties>();
                    vkGetPhysicalDeviceProperties(DeviceInformation[0].PhysicalDevice, physDeviceProps);
                    DeviceInformation[0].Properties = physDeviceProps.Value;

                    var caps_ptr = new ManagedPtr <VkSurfaceCapabilitiesKHR>();
                    vkGetPhysicalDeviceSurfaceCapabilitiesKHR(DeviceInformation[0].PhysicalDevice, surfaceHndl, caps_ptr);
                    var caps = caps_ptr.Value;

                    VkExtent2D cur_extent = new VkExtent2D();
                    if (caps.currentExtent.width != uint.MaxValue)
                    {
                        cur_extent = caps.currentExtent;
                    }
                    else
                    {
                        cur_extent.width  = System.Math.Clamp((uint)Window.Width, caps.minImageExtent.width, caps.maxImageExtent.width);
                        cur_extent.height = System.Math.Clamp((uint)Window.Height, caps.minImageExtent.height, caps.maxImageExtent.height);
                    }

                    uint img_cnt = caps.minImageCount + 1;

                    VkSwapchainCreateInfoKHR swapCreatInfo = new VkSwapchainCreateInfoKHR()
                    {
                        sType                 = VkStructureType.StructureTypeSwapchainCreateInfoKhr,
                        surface               = surfaceHndl,
                        minImageCount         = img_cnt,
                        imageFormat           = surface_fmt.format,
                        imageColorSpace       = surface_fmt.colorSpace,
                        imageExtent           = cur_extent,
                        imageArrayLayers      = 1,
                        imageUsage            = VkImageUsageFlags.ImageUsageColorAttachmentBit | VkImageUsageFlags.ImageUsageTransferDstBit | VkImageUsageFlags.ImageUsageTransferSrcBit,
                        imageSharingMode      = VkSharingMode.SharingModeExclusive,
                        queueFamilyIndexCount = 0,
                        pQueueFamilyIndices   = null,
                        preTransform          = caps.currentTransform,
                        compositeAlpha        = VkCompositeAlphaFlagsKHR.CompositeAlphaOpaqueBitKhr,
                        presentMode           = present_mode,
                        clipped               = true,
                        oldSwapchain          = IntPtr.Zero
                    };
                    var swapCreatInfo_ptr = swapCreatInfo.Pointer();

                    fixed(IntPtr *swapchain_ptr = &swapChainHndl)
                    res = vkCreateSwapchainKHR(DeviceInformation[0].Device, swapCreatInfo_ptr, null, swapchain_ptr);

                    if (res != VkResult.Success)
                        throw new Exception("Failed to create swapchain.");

                    fixed(uint *swapchain_img_cnt_ptr = &swapchain_img_cnt)
                    {
                        vkGetSwapchainImagesKHR(DeviceInformation[0].Device, swapChainHndl, swapchain_img_cnt_ptr, null);
                        var swapchainImages_l = new IntPtr[swapchain_img_cnt];

                        fixed(IntPtr *swapchain_imgs = swapchainImages_l)
                        vkGetSwapchainImagesKHR(DeviceInformation[0].Device, swapChainHndl, swapchain_img_cnt_ptr, swapchain_imgs);

                        MaxFramesInFlight = swapchain_img_cnt;
                        MaxFrameCount     = swapchain_img_cnt;
                        swapchainImages   = new Image[swapchain_img_cnt];
                        for (int i = 0; i < swapchainImages.Length; i++)
                        {
                            swapchainImages[i] = new Image($"Swapchain_{i}")
                            {
                                Dimensions    = 2,
                                Width         = cur_extent.width,
                                Height        = cur_extent.height,
                                Depth         = 1,
                                Format        = (ImageFormat)surface_fmt.format,
                                Layers        = 1,
                                Levels        = 1,
                                MemoryUsage   = MemoryUsage.GpuOnly,
                                Usage         = ImageUsage.Sampled,
                                InitialLayout = ImageLayout.Undefined,
                                Cubemappable  = false,
                            };
                            swapchainImages[i].Build(0, swapchainImages_l[i]);
                        }


                        surface_extent     = cur_extent;
                        swapchainViews     = new ImageView[swapchain_img_cnt];
                        DefaultFramebuffer = new Framebuffer[swapchain_img_cnt];
                        for (int i = 0; i < swapchainImages.Length; i++)
                        {
                            swapchainViews[i] = new ImageView($"Swapchain_{i}")
                            {
                                BaseLayer  = 0,
                                BaseLevel  = 0,
                                Format     = (ImageFormat)surface_fmt.format,
                                LayerCount = 1,
                                LevelCount = 1,
                                ViewType   = ImageViewType.View2D,
                            };
                            swapchainViews[i].Build(swapchainImages[i]);

                            DefaultFramebuffer[i]                  = new Framebuffer();
                            DefaultFramebuffer[i].Width            = surface_extent.width;
                            DefaultFramebuffer[i].Height           = surface_extent.height;
                            DefaultFramebuffer[i].Name             = $"Swapchain_{i}";
                            DefaultFramebuffer[i].ColorAttachments = new ImageView[] { swapchainViews[i] };
                        }
                    }

                    for (int i = 0; i < instLayers.Count; i++)
                    {
                        Marshal.FreeHGlobal(layers[i]);
                    }
                    for (int i = 0; i < instExtns.Count; i++)
                    {
                        Marshal.FreeHGlobal(extns[i]);
                    }
                    for (int i = 0; i < devExtns.Count; i++)
                    {
                        Marshal.FreeHGlobal(devExtns_ptr[i]);
                    }

                    //TODO allocate compute and trasnfer queues for all secondary devices
                }

                for (int i = 0; i < 1 /*DeviceInformation.Length*/; i++)
                {
                    var    devInfo    = DeviceInformation[i];
                    IntPtr rrCtxtHndl = IntPtr.Zero;

                    if (rrCreateContextVk(RrApiVersion, devInfo.Device, devInfo.PhysicalDevice, devInfo.ComputeQueue.Handle, devInfo.ComputeFamily, &rrCtxtHndl) != RRError.RrSuccess)
                    {
                        Console.WriteLine($"Failed to initialize RadeonRays for device #{i}.");
                    }
                    DeviceInformation[i].RaysContext = rrCtxtHndl;
                }

                FrameFinishedSemaphore  = new GpuSemaphore[MaxFramesInFlight];
                ImageAvailableSemaphore = new GpuSemaphore[MaxFramesInFlight];
                InflightFences          = new Fence[MaxFramesInFlight];
                for (int i = 0; i < MaxFramesInFlight; i++)
                {
                    FrameFinishedSemaphore[i] = new GpuSemaphore();
                    FrameFinishedSemaphore[i].Build(0, false, 0);

                    ImageAvailableSemaphore[i] = new GpuSemaphore();
                    ImageAvailableSemaphore[i].Build(0, false, 0);

                    InflightFences[i] = new Fence
                    {
                        CreateSignaled = true
                    };
                    InflightFences[i].Build(0);
                }

                Width  = (uint)Window.Width;
                Height = (uint)Window.Height;
            }
        }
Ejemplo n.º 23
0
        static void Main(string[] args)
        {
            VkInstance inst;

            using (VkApplicationInfo ai = new VkApplicationInfo()) {
                using (VkInstanceCreateInfo ci = new VkInstanceCreateInfo {
                    pApplicationInfo = ai
                }){
                    CheckResult(vkCreateInstance(ci, IntPtr.Zero, out inst));
                }
            }

            Vk.LoadInstanceFunctionPointers(inst);

            if (!TryGetPhysicalDevice(inst, VkPhysicalDeviceType.DiscreteGpu, out VkPhysicalDevice phy))
            {
                if (!TryGetPhysicalDevice(inst, VkPhysicalDeviceType.IntegratedGpu, out phy))
                {
                    if (!TryGetPhysicalDevice(inst, VkPhysicalDeviceType.Cpu, out phy))
                    {
                        throw new Exception("no suitable physical device found");
                    }
                }
            }

            foreach (VkPhysicalDeviceToolPropertiesEXT toolProp in GetToolProperties(phy))
            {
                Console.ForegroundColor = ConsoleColor.DarkYellow;
                Console.WriteLine($"Enabled Tool: {toolProp.name}({toolProp.version})");
                Console.ResetColor();
            }

            vkGetPhysicalDeviceQueueFamilyProperties(phy, out uint queueFamilyCount, IntPtr.Zero);
            VkQueueFamilyProperties[] qFamProps = new VkQueueFamilyProperties[queueFamilyCount];
            vkGetPhysicalDeviceQueueFamilyProperties(phy, out queueFamilyCount, qFamProps.Pin());
            qFamProps.Unpin();
            Console.WriteLine($"Queues:");
            for (int i = 0; i < queueFamilyCount; i++)
            {
                Console.WriteLine($"\t{i}: {qFamProps[i].queueFlags,-60} ({qFamProps[i].queueCount})");
            }

            uint qFamIndex = (uint)qFamProps.Select((qFam, index) => (qFam, index))
                             .First(qfp => qfp.qFam.queueFlags.HasFlag(VkQueueFlags.Graphics)).index;

            VkDevice dev = default;

            float[] priorities = { 0 };
            using (VkDeviceQueueCreateInfo qInfo = new VkDeviceQueueCreateInfo(qFamIndex, 1, priorities)) {
                using (VkDeviceCreateInfo deviceCreateInfo = new VkDeviceCreateInfo()
                {
                    pQueueCreateInfos = qInfo
                }) {
                    CheckResult(vkCreateDevice(phy, deviceCreateInfo, IntPtr.Zero, out dev));
                }
            }
            vkGetDeviceQueue(dev, qFamIndex, 0, out VkQueue gQ);

            vkDestroyDevice(dev, IntPtr.Zero);

            vkDestroyInstance(inst, IntPtr.Zero);
        }