Ejemplo n.º 1
0
        private void CreateLogicalDevice()
        {
            var indices = new QueueFamilyIndices(vkPhysicalDevice, vkSurface);

            float priority         = 1f;
            var   queueCreateInfos = stackalloc VkDeviceQueueCreateInfo[]
            {
                new VkDeviceQueueCreateInfo()
                {
                    sType            = VkStructureType.VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
                    queueFamilyIndex = (uint)indices.GraphicsFamily,
                    queueCount       = 1,
                    pQueuePriorities = &priority,
                }
            };

            int     extensionsCount         = 1;
            IntPtr *extensionsToEnableArray = stackalloc IntPtr[extensionsCount];

            for (int i = 0; i < extensionsCount; i++)
            {
                string extension = "VK_KHR_swapchain";
                extensionsToEnableArray[i] = Marshal.StringToHGlobalAnsi(extension);
            }

            VkPhysicalDeviceFeatures deviceFeatures = new VkPhysicalDeviceFeatures();

            var createInfo = new VkDeviceCreateInfo()
            {
                sType = VkStructureType.VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
                ppEnabledExtensionNames = (byte **)extensionsToEnableArray,
                enabledExtensionCount   = (uint)extensionsCount,
                pQueueCreateInfos       = queueCreateInfos,
                queueCreateInfoCount    = 1,
                pEnabledFeatures        = &deviceFeatures,
            };

            VkDevice newDevice;
            var      result = VulkanNative.vkCreateDevice(this.vkPhysicalDevice, &createInfo, null, &newDevice);

            this.vkDevice = newDevice;
            Helpers.CheckErrors(result);

            for (int i = 0; i < extensionsCount; i++)
            {
                Marshal.FreeHGlobal(extensionsToEnableArray[i]);
            }

            VkQueue newGraphicsQueue;

            VulkanNative.vkGetDeviceQueue(vkDevice, (uint)indices.GraphicsFamily, 0, &newGraphicsQueue);
            this.vkGraphicsQueue = newGraphicsQueue;

            VkQueue newPresentQueue;

            VulkanNative.vkGetDeviceQueue(vkDevice, (uint)indices.PresentFamily, 0, &newPresentQueue);
            this.vkPresentQueue = newPresentQueue;
        }
Ejemplo n.º 2
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.º 3
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.º 4
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.º 5
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.º 6
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.º 7
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.º 8
0
        public DummyDevice(DummyPhysicalDevice physicalDevice, VkDeviceCreateInfo createInfo)
            : base(physicalDevice.m_Instance)
        {
            this.m_PhysicalDevice = physicalDevice;
            this.m_createInfo     = createInfo;

            foreach (var item in createInfo.pQueueCreateInfos)
            {
                List <VkQueue> list = new List <VkQueue>();

                for (int i = 0; i < item.queueCount; i++)
                {
                    list.Add(new DummyQueue(this, item.queueFamilyIndex));
                }

                m_Queue.Add(item.queueFamilyIndex, list);
            }
        }
Ejemplo n.º 9
0
        private void CreateLogicalDevice()
        {
            var queueFamilies = FindQueueFamilies(physicalDevice, surface).Value;

            var queueCreateInfos = queueFamilies.GraphicsFamily == queueFamilies.PresentFamily
                ? new[]
            { new VkDeviceQueueCreateInfo
              {
                  QueueFamilyIndex = queueFamilies.GraphicsFamily,
                  QueuePriorities  = new [] { 1f }
              } }
                : new []
            {
                new VkDeviceQueueCreateInfo
                {
                    QueueFamilyIndex = queueFamilies.GraphicsFamily,
                    QueuePriorities  = new[] { 1f }
                },
                new VkDeviceQueueCreateInfo
                {
                    QueueFamilyIndex = queueFamilies.PresentFamily,
                    QueuePriorities  = new[] { 1f }
                }
            };
            var deviceFeatures = new VkPhysicalDeviceFeatures
            {
            };
            var createInfo = new VkDeviceCreateInfo
            {
                QueueCreateInfos      = queueCreateInfos,
                EnabledFeatures       = deviceFeatures,
                EnabledExtensionNames = DeviceExtensions,
                EnabledLayerNames     = LayerNames
            };

            device        = physicalDevice.CreateDevice(createInfo, null).Object;
            graphicsQueue = device.GetDeviceQueue(queueFamilies.GraphicsFamily, 0);
            presentQueue  = device.GetDeviceQueue(queueFamilies.PresentFamily, 0);
        }
Ejemplo n.º 10
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.º 11
0
 public abstract VkResult CreateDevice(VkDeviceCreateInfo createInfo, out VkDevice device);
Ejemplo n.º 12
0
 internal static VkResult Create(SoftwarePhysicalDevice softwarePhysicalDevice, VkDeviceCreateInfo createInfo, out VkDevice device)
 {
     device = new SoftwareDevice(softwarePhysicalDevice, createInfo);
     return(VkResult.VK_SUCCESS);
 }
Ejemplo n.º 13
0
 public static extern VkResult CreateDevice(
     VkPhysicalDevice physicalDevice,
     ref VkDeviceCreateInfo pCreateInfo,
     IntPtr pAllocator,
     out VkDevice pDevice
     );
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
        /// <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.º 16
0
 public override VkResult CreateDevice(VkDeviceCreateInfo createInfo, out VkDevice device)
 {
     return(SoftwareDevice.Create(this, createInfo, out device));
 }
Ejemplo n.º 17
0
 public override VkResult CreateDevice(VkDeviceCreateInfo createInfo, out VkDevice device)
 {
     device = new DummyDevice(this, createInfo);
     return(VkResult.VK_SUCCESS);
 }
Ejemplo n.º 18
0
        public unsafe Device(VkPhysicalDevice physicalDevice)
        {
            _physicalDevice = physicalDevice;

            //get physical device information
            VulkanNative.vkGetPhysicalDeviceProperties(
                _physicalDevice,
                out _properties
                );
            VulkanNative.vkGetPhysicalDeviceMemoryProperties(
                _physicalDevice,
                out _memoryProperties
                );
            VulkanNative.vkGetPhysicalDeviceFeatures(
                _physicalDevice,
                out _features
                );

            //get family queue properties
            uint familyQueuePropertiesCount;

            VulkanNative.vkGetPhysicalDeviceQueueFamilyProperties(
                _physicalDevice,
                &familyQueuePropertiesCount,
                null
                );
            var familyQueueProperties = new NativeList <VkQueueFamilyProperties>(
                familyQueuePropertiesCount
                );

            familyQueueProperties.Count = familyQueuePropertiesCount;
            VulkanNative.vkGetPhysicalDeviceQueueFamilyProperties(
                _physicalDevice,
                &familyQueuePropertiesCount,
                (VkQueueFamilyProperties *)familyQueueProperties.Data.ToPointer()
                );

            //setup queue families
            _queueFamilies = new List <QueueFamily>();
            for (uint i = 0; i < familyQueuePropertiesCount; i++)
            {
                var familyQueueProperty = familyQueueProperties[i];
                _queueFamilies.Add(new QueueFamily(
                                       i,
                                       familyQueueProperty.queueCount,
                                       (QueueFamilyType)familyQueueProperty.queueFlags
                                       ));
            }

            //get queue create infos
            var queueCreateInfos = new NativeList <VkDeviceQueueCreateInfo>(
                familyQueuePropertiesCount
                );

            queueCreateInfos.Count = familyQueuePropertiesCount;
            for (int i = 0; i < familyQueuePropertiesCount; i++)
            {
                queueCreateInfos[i] = _queueFamilies[i].QueueCreateInfo;
            }

            //enable extra device features
            var enabledFeatures = new VkPhysicalDeviceFeatures()
            {
                samplerAnisotropy = true,
                dualSrcBlend      = true
            };

            //enable swapchain extension for window support
            var enabledExtensions = new NativeList <IntPtr>();

            enabledExtensions.Add(GraphicsApiConstants.VK_KHR_SWAPCHAIN_EXTENSION_NAME);

            var deviceInfo = new VkDeviceCreateInfo
            {
                sType                   = VkStructureType.DeviceCreateInfo,
                pEnabledFeatures        = &enabledFeatures,
                enabledExtensionCount   = enabledExtensions.Count,
                ppEnabledExtensionNames = (byte **)enabledExtensions.Data,
                enabledLayerCount       = 0,
                ppEnabledLayerNames     = null,
                queueCreateInfoCount    = queueCreateInfos.Count,
                pQueueCreateInfos       = (VkDeviceQueueCreateInfo *)queueCreateInfos.Data.ToPointer()
            };

            //setup device
            VkDevice device;

            if (VulkanNative.vkCreateDevice(
                    _physicalDevice,
                    &deviceInfo,
                    null,
                    &device
                    ) != VkResult.Success)
            {
                throw new Exception("failed to initialize device");
            }
            _handle = device;

            //setup device queues
            foreach (var queueFamily in _queueFamilies)
            {
                queueFamily.GetQueuesFromDevice(this);
            }

            //calculate device score
            _score = 0;
            if (_properties.deviceType == VkPhysicalDeviceType.DiscreteGpu)
            {
                _score += 10;
            }
            else if (_properties.deviceType == VkPhysicalDeviceType.IntegratedGpu)
            {
                _score += 5;
            }
            else if (_properties.deviceType == VkPhysicalDeviceType.VirtualGpu)
            {
                _score += 3;
            }
            else if (_properties.deviceType == VkPhysicalDeviceType.Cpu)
            {
                _score += 1;
            }

            _score += (
                //1073741824 = 1024 * 1024 * 1024
                _properties.limits.maxMemoryAllocationCount / 1073741824.0f
                );
        }
Ejemplo n.º 19
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.º 20
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.º 21
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.º 22
0
        public void Activate(VkPhysicalDeviceFeatures enabledFeatures, params string[] extensions)
        {
            List <VkDeviceQueueCreateInfo> qInfos          = new List <VkDeviceQueueCreateInfo> ();
            List <List <float> >           prioritiesLists = new List <List <float> > ();//store pinned lists for later unpin

            foreach (IGrouping <uint, Queue> qfams in queues.GroupBy(q => q.qFamIndex))
            {
                int          qTot          = qfams.Count();
                uint         qIndex        = 0;
                List <float> priorities    = new List <float> ();
                bool         qCountReached = false;        //true when queue count of that family is reached

                foreach (Queue q in qfams)
                {
                    if (!qCountReached)
                    {
                        priorities.Add(q.priority);
                    }
                    q.index = qIndex++;
                    if (qIndex == phy.QueueFamilies[qfams.Key].queueCount)
                    {
                        qIndex        = 0;
                        qCountReached = true;
                    }
                }

                qInfos.Add(new VkDeviceQueueCreateInfo {
                    sType            = VkStructureType.DeviceQueueCreateInfo,
                    queueCount       = qCountReached ? phy.QueueFamilies[qfams.Key].queueCount : qIndex,
                    queueFamilyIndex = qfams.Key,
                    pQueuePriorities = priorities.Pin()
                });
                prioritiesLists.Add(priorities);                 //add for unpined
            }

            //enable only supported exceptions
            List <IntPtr> deviceExtensions = new List <IntPtr> ();

            for (int i = 0; i < extensions.Length; i++)
            {
                if (phy.GetDeviceExtensionSupported(extensions[i]))
                {
                    deviceExtensions.Add(new FixedUtf8String(extensions[i]));
                }
            }

            VkDeviceCreateInfo deviceCreateInfo = VkDeviceCreateInfo.New();

            deviceCreateInfo.queueCreateInfoCount = (uint)qInfos.Count;
            deviceCreateInfo.pQueueCreateInfos    = qInfos.Pin();
            deviceCreateInfo.pEnabledFeatures     = enabledFeatures.Pin();

            if (deviceExtensions.Count > 0)
            {
                deviceCreateInfo.enabledExtensionCount   = (uint)deviceExtensions.Count;
                deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions.Pin();
            }

            Utils.CheckResult(vkCreateDevice(phy.Handle, ref deviceCreateInfo, IntPtr.Zero, out dev));
            qInfos.Unpin();
            enabledFeatures.Unpin();
            foreach (List <float> fa in prioritiesLists)
            {
                fa.Unpin();
            }

            deviceExtensions.Unpin();

            //Vk.LoadDeviceFunctionPointers (dev);

            foreach (Queue q in queues)
            {
                q.updateHandle();
            }

#if MEMORY_POOLS
            resourceManager = new ResourceManager(this);
#endif
        }
Ejemplo n.º 23
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.º 24
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.º 25
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.º 26
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);
        }
Ejemplo n.º 27
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.º 28
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.º 29
0
        public VkResult CreateLogicalDevice(
            VkPhysicalDeviceFeatures enabledFeatures,
            NativeList <IntPtr> enabledExtensions,
            bool useSwapChain = true,
            VkQueueFlags requestedQueueTypes = VkQueueFlags.Graphics | VkQueueFlags.Compute)
        {
            // Desired queues need to be requested upon logical device creation
            // Due to differing queue family configurations of Vulkan implementations this can be a bit tricky, especially if the application
            // requests different queue types

            using (NativeList <VkDeviceQueueCreateInfo> queueCreateInfos = new NativeList <VkDeviceQueueCreateInfo>())
            {
                float defaultQueuePriority = 0.0f;

                // Graphics queue
                if ((requestedQueueTypes & VkQueueFlags.Graphics) != 0)
                {
                    QFIndices.Graphics = GetQueueFamilyIndex(VkQueueFlags.Graphics);
                    VkDeviceQueueCreateInfo queueInfo = new VkDeviceQueueCreateInfo();
                    queueInfo.sType            = VkStructureType.DeviceQueueCreateInfo;
                    queueInfo.queueFamilyIndex = QFIndices.Graphics;
                    queueInfo.queueCount       = 1;
                    queueInfo.pQueuePriorities = &defaultQueuePriority;
                    queueCreateInfos.Add(queueInfo);
                }
                else
                {
                    QFIndices.Graphics = (uint)NullHandle;
                }

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

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

                // Create the logical device representation
                using (NativeList <IntPtr> deviceExtensions = new NativeList <IntPtr>(enabledExtensions))
                {
                    if (useSwapChain)
                    {
                        // If the device will be used for presenting to a display via a swapchain we need to request the swapchain extension
                        deviceExtensions.Add(Strings.VK_KHR_SWAPCHAIN_EXTENSION_NAME);
                    }

                    VkDeviceCreateInfo deviceCreateInfo = VkDeviceCreateInfo.New();
                    deviceCreateInfo.queueCreateInfoCount = queueCreateInfos.Count;
                    deviceCreateInfo.pQueueCreateInfos    = (VkDeviceQueueCreateInfo *)queueCreateInfos.Data.ToPointer();
                    deviceCreateInfo.pEnabledFeatures     = &enabledFeatures;

                    if (deviceExtensions.Count > 0)
                    {
                        deviceCreateInfo.enabledExtensionCount   = deviceExtensions.Count;
                        deviceCreateInfo.ppEnabledExtensionNames = (byte **)deviceExtensions.Data.ToPointer();
                    }

                    VkResult result = vkCreateDevice(PhysicalDevice, &deviceCreateInfo, null, out _logicalDevice);
                    if (result == VkResult.Success)
                    {
                        // Create a default command pool for graphics command buffers
                        CommandPool = CreateCommandPool(QFIndices.Graphics);
                    }

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