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 @@
+