From c08f84c4e95fbb981218d31ffd7eb4b831ac6a80 Mon Sep 17 00:00:00 2001 From: N00MKRAD <61149547+n00mkrad@users.noreply.github.com> Date: Thu, 21 Dec 2023 21:05:23 +0100 Subject: [PATCH] Use Vulkan API directly to check Vk devices and compute queue count --- Code/Flowframes.csproj | 7 ++++ Code/Forms/Main/Form1.cs | 1 + Code/Os/AiProcess.cs | 6 ++-- Code/Os/VulkanUtils.cs | 66 +++++++++++++++++++++++++++++++++++++ Code/Utilities/NcnnUtils.cs | 58 +++++--------------------------- Code/packages.config | 1 + 6 files changed, 86 insertions(+), 53 deletions(-) create mode 100644 Code/Os/VulkanUtils.cs diff --git a/Code/Flowframes.csproj b/Code/Flowframes.csproj index b614300..4e714cd 100644 --- a/Code/Flowframes.csproj +++ b/Code/Flowframes.csproj @@ -309,6 +309,12 @@ packages\Tulpep.NotificationWindow.1.1.38\lib\net40\Tulpep.NotificationWindow.dll + + packages\VulkanSharp.0.1.10\lib\net452\Vulkan.dll + + + packages\VulkanSharp.0.1.10\lib\net452\Vulkan.Windows.dll + packages\Win32Interop.Dwmapi.1.0.1\lib\Win32Interop.Dwmapi.dll @@ -475,6 +481,7 @@ + diff --git a/Code/Forms/Main/Form1.cs b/Code/Forms/Main/Form1.cs index f98932d..fea5c9d 100644 --- a/Code/Forms/Main/Form1.cs +++ b/Code/Forms/Main/Form1.cs @@ -61,6 +61,7 @@ namespace Flowframes.Forms.Main Program.mainForm = this; Logger.textbox = logBox; + VulkanUtils.Init(); NvApi.Init(); InterpolationProgress.preview = previewPicturebox; RemovePreviewIfDisabled(); diff --git a/Code/Os/AiProcess.cs b/Code/Os/AiProcess.cs index 93efc46..e6fb68d 100644 --- a/Code/Os/AiProcess.cs +++ b/Code/Os/AiProcess.cs @@ -325,7 +325,7 @@ namespace Flowframes.Os string ttaStr = Config.GetBool(Config.Key.rifeNcnnUseTta, false) ? "-x" : ""; rifeNcnn.StartInfo.Arguments = $"{OsUtils.GetCmdArg()} cd /D {Path.Combine(Paths.GetPkgPath(), Implementations.rifeNcnn.PkgDir).Wrap()} & rife-ncnn-vulkan.exe " + - $" -v -i {inPath.Wrap()} -o {outPath.Wrap()} {frames} -m {mdl.ToLowerInvariant()} {ttaStr} {uhdStr} -g {Config.Get(Config.Key.ncnnGpus)} -f {NcnnUtils.GetNcnnPattern()} -j {await NcnnUtils.GetNcnnThreads(Implementations.rifeNcnn)}"; + $" -v -i {inPath.Wrap()} -o {outPath.Wrap()} {frames} -m {mdl.ToLowerInvariant()} {ttaStr} {uhdStr} -g {Config.Get(Config.Key.ncnnGpus)} -f {NcnnUtils.GetNcnnPattern()} -j {NcnnUtils.GetNcnnThreads(Implementations.rifeNcnn)}"; Logger.Log("cmd.exe " + rifeNcnn.StartInfo.Arguments, true); @@ -386,7 +386,7 @@ namespace Flowframes.Os Res = res, Uhd = InterpolateUtils.UseUhd(res), GpuId = gpuId, - GpuThreads = await NcnnUtils.GetRifeNcnnGpuThreads(res, gpuId, Implementations.rifeNcnnVs), + GpuThreads = NcnnUtils.GetRifeNcnnGpuThreads(res, gpuId, Implementations.rifeNcnnVs), SceneDetectSensitivity = Config.GetBool(Config.Key.scnDetect) ? Config.GetFloat(Config.Key.scnDetectValue) * 0.7f : 0f, Loop = Config.GetBool(Config.Key.enableLoop), MatchDuration = Config.GetBool(Config.Key.fixOutputDuration), @@ -580,7 +580,7 @@ namespace Flowframes.Os string ttaStr = ""; // Config.GetBool(Config.Key.rifeNcnnUseTta, false) ? "-x" : ""; ifrnetNcnn.StartInfo.Arguments = $"{OsUtils.GetCmdArg()} cd /D {Path.Combine(Paths.GetPkgPath(), Implementations.ifrnetNcnn.PkgDir).Wrap()} & ifrnet-ncnn-vulkan.exe " + - $" -v -i {inPath.Wrap()} -o {outPath.Wrap()} -m {mdl} {ttaStr} {uhdStr} -g {Config.Get(Config.Key.ncnnGpus)} -f {NcnnUtils.GetNcnnPattern()} -j {await NcnnUtils.GetNcnnThreads(Implementations.ifrnetNcnn)}"; + $" -v -i {inPath.Wrap()} -o {outPath.Wrap()} -m {mdl} {ttaStr} {uhdStr} -g {Config.Get(Config.Key.ncnnGpus)} -f {NcnnUtils.GetNcnnPattern()} -j {NcnnUtils.GetNcnnThreads(Implementations.ifrnetNcnn)}"; Logger.Log("cmd.exe " + ifrnetNcnn.StartInfo.Arguments, true); diff --git a/Code/Os/VulkanUtils.cs b/Code/Os/VulkanUtils.cs new file mode 100644 index 0000000..8c9434b --- /dev/null +++ b/Code/Os/VulkanUtils.cs @@ -0,0 +1,66 @@ +using Flowframes.MiscUtils; +using System; +using System.Collections.Generic; +using System.Linq; +using Vulkan; + +namespace Flowframes.Os +{ + public class VulkanUtils + { + public class VkDevice + { + public int Id { get; set; } = -1; + public string Name { get; set; } = ""; + public int ComputeQueueCount { get; set; } = 0; + + public override string ToString() + { + return $"[{Id}] {Name} [{ComputeQueueCount} Compute Queues]"; + } + } + + public static List VkDevices { get; private set; } = null; + + public static void Init() + { + var sw = new NmkdStopwatch(); + VkDevices = new List(); + Instance vkInstance = new Instance(new InstanceCreateInfo()); + PhysicalDevice[] physicalDevices = vkInstance.EnumeratePhysicalDevices(); + + for (int idx = 0; idx < physicalDevices.Length; idx++) + { + PhysicalDevice device = physicalDevices[idx]; + + // Get queue families and find the one with Compute support but no Graphics support. This is the one that gives us the correct thread count to use for NCNN etc. + QueueFamilyProperties[] queueFamilies = device.GetQueueFamilyProperties(); + var validQueueFamilies = queueFamilies.Where(q => q.QueueFlags.HasFlag(QueueFlags.Compute) && !q.QueueFlags.HasFlag(QueueFlags.Graphics)); + int compQueues = validQueueFamilies.Any() ? (int)validQueueFamilies.First().QueueCount : 0; + + string name = device.GetProperties().DeviceName; + VkDevices.Add(new VkDevice { Id = idx, Name = name, ComputeQueueCount = compQueues }); + Logger.Log($"[VK] Found Vulkan device: {VkDevices.Last()}", true); + } + + // Clean up Vulkan resources + vkInstance.Destroy(); + Logger.Log($"[VK] Vulkan device check took {sw.ElapsedMs} ms", true); + } + + public static int GetMaxNcnnThreads(int deviceId) + { + var matchingDevices = VkDevices.Where(d => d.Id == deviceId); + + if (matchingDevices.Any()) + return matchingDevices.First().ComputeQueueCount; + + return 0; + } + + public static int GetMaxNcnnThreads(VkDevice device) + { + return device.ComputeQueueCount; + } + } +} \ No newline at end of file diff --git a/Code/Utilities/NcnnUtils.cs b/Code/Utilities/NcnnUtils.cs index c016eed..1337280 100644 --- a/Code/Utilities/NcnnUtils.cs +++ b/Code/Utilities/NcnnUtils.cs @@ -14,51 +14,13 @@ namespace Flowframes.Utilities { class NcnnUtils { - public static Dictionary GpuIdsQueueCounts = null; - - /// Get amount of GPU Compute Queues (VK) for each GPU - public static async Task> GetNcnnGpuComputeQueueCounts () - { - if(GpuIdsQueueCounts != null) - return GpuIdsQueueCounts; - - Dictionary queueCounts = new Dictionary(); // int gpuId, int queueCount - - Process rifeNcnn = OsUtils.NewProcess(true); - rifeNcnn.StartInfo.Arguments = $"{OsUtils.GetCmdArg()} cd /D {Path.Combine(Paths.GetPkgPath(), Implementations.rifeNcnn.PkgDir)} & rife-ncnn-vulkan.exe -i dummydir -o dummydir"; - - string output = await Task.Run(() => OsUtils.GetProcStdOut(rifeNcnn, true)); - var queueLines = output.SplitIntoLines().Where(x => x.MatchesWildcard(@"*queueC=*queue*")); - - foreach (var line in queueLines) - { - int gpuId = line.Split(' ')[0].GetInt(); - int queueCount = line.Split("queue")[1].Split('[')[1].Split(']')[0].GetInt(); - Logger.Log($"NCNN: Found GPU {gpuId} with compute queue count {queueCount}", true); - queueCounts[gpuId] = queueCount; - } - - GpuIdsQueueCounts = queueCounts; - return queueCounts; - } - - public static async Task GetRifeNcnnGpuThreads(Size res, int gpuId, AI ai) + public static int GetRifeNcnnGpuThreads(Size res, int gpuId, AI ai) { int threads = Config.GetInt(Config.Key.ncnnThreads); - //if (res.Width * res.Height > 2560 * 1440) threads = 4; - // if (res.Width * res.Height > 3840 * 2160) threads = 1; + int maxThreads = VulkanUtils.GetMaxNcnnThreads(gpuId); - if (threads != 1) - { - var queueDict = await GetNcnnGpuComputeQueueCounts(); - int maxThreads = queueDict.ContainsKey(gpuId) ? queueDict[gpuId] : 1; - threads = threads.Clamp(1, maxThreads); // To avoid exceeding the max queue count - Logger.Log($"Using {threads}/{maxThreads} GPU threads.", true, false, ai.LogFilename); - } - else - { - Logger.Log($"Using {threads} GPU thread.", true, false, ai.LogFilename); - } + threads = threads.Clamp(1, maxThreads); // To avoid exceeding the max queue count + Logger.Log($"Using {threads}/{maxThreads} GPU compute threads.", true, false, ai.LogFilename); return threads; } @@ -79,15 +41,11 @@ namespace Flowframes.Utilities return tilesizeStr; } - public static async Task GetNcnnThreads(AI ai) + public static string GetNcnnThreads(AI ai) { - int gpusAmount = Config.Get(Config.Key.ncnnGpus).Split(',').Length; - int threads = await GetRifeNcnnGpuThreads(new Size(), Config.Get(Config.Key.ncnnGpus).Split(',')[0].GetInt(), ai); - string progThreadsStr = $"{threads}"; - - for (int i = 1; i < gpusAmount; i++) - progThreadsStr += $",{threads}"; - + List enabledGpuIds = Config.Get(Config.Key.ncnnGpus).Split(',').Select(s => s.GetInt()).ToList(); // Get GPU IDs + List gpuThreadCounts = enabledGpuIds.Select(g => GetRifeNcnnGpuThreads(new Size(), g, ai)).ToList(); // Get max thread count for each GPU + string progThreadsStr = string.Join(",", gpuThreadCounts); return $"{(Interpolate.currentlyUsingAutoEnc ? 2 : 4)}:{progThreadsStr}:4"; // Read threads: 1 for singlethreaded, 2 for autoenc, 4 if order is irrelevant } diff --git a/Code/packages.config b/Code/packages.config index d72eccf..f60848c 100644 --- a/Code/packages.config +++ b/Code/packages.config @@ -74,6 +74,7 @@ +