internal static DeviceInfo[] GetSuitablePhysicalDevices(Vk api) { var appName = Marshal.StringToHGlobalAnsi(AppName); var applicationInfo = new ApplicationInfo { PApplicationName = (byte *)appName, ApplicationVersion = 1, PEngineName = (byte *)appName, EngineVersion = 1, ApiVersion = Vk.Version12.Value }; var instanceCreateInfo = new InstanceCreateInfo { SType = StructureType.InstanceCreateInfo, PApplicationInfo = &applicationInfo, PpEnabledExtensionNames = null, PpEnabledLayerNames = null, EnabledExtensionCount = 0, EnabledLayerCount = 0 }; api.CreateInstance(in instanceCreateInfo, null, out var instance).ThrowOnError(); Marshal.FreeHGlobal(appName); uint physicalDeviceCount; api.EnumeratePhysicalDevices(instance, &physicalDeviceCount, null).ThrowOnError(); PhysicalDevice[] physicalDevices = new PhysicalDevice[physicalDeviceCount]; fixed(PhysicalDevice *pPhysicalDevices = physicalDevices) { api.EnumeratePhysicalDevices(instance, &physicalDeviceCount, pPhysicalDevices).ThrowOnError(); } DeviceInfo[] devices = new DeviceInfo[physicalDevices.Length]; for (int i = 0; i < physicalDevices.Length; i++) { var physicalDevice = physicalDevices[i]; api.GetPhysicalDeviceProperties(physicalDevice, out var properties); devices[i] = new DeviceInfo( StringFromIdPair(properties.VendorID, properties.DeviceID), VendorUtils.GetNameFromId(properties.VendorID), Marshal.PtrToStringAnsi((IntPtr)properties.DeviceName), properties.DeviceType == PhysicalDeviceType.DiscreteGpu); } api.DestroyInstance(instance, null); return(devices); }
public static Device CreateDevice(Vk api, PhysicalDevice physicalDevice, uint queueFamilyIndex, string[] supportedExtensions, uint queueCount) { if (queueCount > QueuesCount) { queueCount = QueuesCount; } float *queuePriorities = stackalloc float[(int)queueCount]; for (int i = 0; i < queueCount; i++) { queuePriorities[i] = 1f; } var queueCreateInfo = new DeviceQueueCreateInfo() { SType = StructureType.DeviceQueueCreateInfo, QueueFamilyIndex = queueFamilyIndex, QueueCount = queueCount, PQueuePriorities = queuePriorities }; api.GetPhysicalDeviceProperties(physicalDevice, out var properties); bool useRobustBufferAccess = VendorUtils.FromId(properties.VendorID) == Vendor.Nvidia; var supportedFeatures = api.GetPhysicalDeviceFeature(physicalDevice); var features = new PhysicalDeviceFeatures() { DepthBiasClamp = true, DepthClamp = true, DualSrcBlend = true, FragmentStoresAndAtomics = true, GeometryShader = true, ImageCubeArray = true, IndependentBlend = true, LogicOp = true, MultiViewport = true, PipelineStatisticsQuery = true, SamplerAnisotropy = true, ShaderClipDistance = true, ShaderFloat64 = supportedFeatures.ShaderFloat64, ShaderImageGatherExtended = true, // ShaderStorageImageReadWithoutFormat = true, // ShaderStorageImageWriteWithoutFormat = true, TessellationShader = true, VertexPipelineStoresAndAtomics = true, RobustBufferAccess = useRobustBufferAccess }; void *pExtendedFeatures = null; var featuresTransformFeedback = new PhysicalDeviceTransformFeedbackFeaturesEXT() { SType = StructureType.PhysicalDeviceTransformFeedbackFeaturesExt, PNext = pExtendedFeatures, TransformFeedback = true }; pExtendedFeatures = &featuresTransformFeedback; var featuresRobustness2 = new PhysicalDeviceRobustness2FeaturesEXT() { SType = StructureType.PhysicalDeviceRobustness2FeaturesExt, PNext = pExtendedFeatures, NullDescriptor = true }; pExtendedFeatures = &featuresRobustness2; var featuresExtendedDynamicState = new PhysicalDeviceExtendedDynamicStateFeaturesEXT() { SType = StructureType.PhysicalDeviceExtendedDynamicStateFeaturesExt, PNext = pExtendedFeatures, ExtendedDynamicState = supportedExtensions.Contains(ExtExtendedDynamicState.ExtensionName) }; pExtendedFeatures = &featuresExtendedDynamicState; var featuresVk11 = new PhysicalDeviceVulkan11Features() { SType = StructureType.PhysicalDeviceVulkan11Features, PNext = pExtendedFeatures, ShaderDrawParameters = true }; pExtendedFeatures = &featuresVk11; var featuresVk12 = new PhysicalDeviceVulkan12Features() { SType = StructureType.PhysicalDeviceVulkan12Features, PNext = pExtendedFeatures, DescriptorIndexing = supportedExtensions.Contains("VK_EXT_descriptor_indexing"), DrawIndirectCount = supportedExtensions.Contains(KhrDrawIndirectCount.ExtensionName) }; pExtendedFeatures = &featuresVk12; PhysicalDeviceIndexTypeUint8FeaturesEXT featuresIndexU8; if (supportedExtensions.Contains("VK_EXT_index_type_uint8")) { featuresIndexU8 = new PhysicalDeviceIndexTypeUint8FeaturesEXT() { SType = StructureType.PhysicalDeviceIndexTypeUint8FeaturesExt, PNext = pExtendedFeatures, IndexTypeUint8 = true }; pExtendedFeatures = &featuresIndexU8; } PhysicalDeviceFragmentShaderInterlockFeaturesEXT featuresFragmentShaderInterlock; if (supportedExtensions.Contains("VK_EXT_fragment_shader_interlock")) { featuresFragmentShaderInterlock = new PhysicalDeviceFragmentShaderInterlockFeaturesEXT() { SType = StructureType.PhysicalDeviceFragmentShaderInterlockFeaturesExt, PNext = pExtendedFeatures, FragmentShaderPixelInterlock = true }; pExtendedFeatures = &featuresFragmentShaderInterlock; } PhysicalDeviceSubgroupSizeControlFeaturesEXT featuresSubgroupSizeControl; if (supportedExtensions.Contains("VK_EXT_subgroup_size_control")) { featuresSubgroupSizeControl = new PhysicalDeviceSubgroupSizeControlFeaturesEXT() { SType = StructureType.PhysicalDeviceSubgroupSizeControlFeaturesExt, PNext = pExtendedFeatures, SubgroupSizeControl = true }; pExtendedFeatures = &featuresSubgroupSizeControl; } var enabledExtensions = RequiredExtensions.Union(DesirableExtensions.Intersect(supportedExtensions)).ToArray(); IntPtr *ppEnabledExtensions = stackalloc IntPtr[enabledExtensions.Length]; for (int i = 0; i < enabledExtensions.Length; i++) { ppEnabledExtensions[i] = Marshal.StringToHGlobalAnsi(enabledExtensions[i]); } var deviceCreateInfo = new DeviceCreateInfo() { SType = StructureType.DeviceCreateInfo, PNext = pExtendedFeatures, QueueCreateInfoCount = 1, PQueueCreateInfos = &queueCreateInfo, PpEnabledExtensionNames = (byte **)ppEnabledExtensions, EnabledExtensionCount = (uint)enabledExtensions.Length, PEnabledFeatures = &features }; api.CreateDevice(physicalDevice, in deviceCreateInfo, null, out var device).ThrowOnError(); for (int i = 0; i < enabledExtensions.Length; i++) { Marshal.FreeHGlobal(ppEnabledExtensions[i]); } return(device); }