Use Vulkan API directly to check Vk devices and compute queue count

This commit is contained in:
N00MKRAD
2023-12-21 21:05:23 +01:00
parent 916dd2fe06
commit c08f84c4e9
6 changed files with 86 additions and 53 deletions

View File

@@ -309,6 +309,12 @@
<Reference Include="Tulpep.NotificationWindow, Version=1.1.38.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\Tulpep.NotificationWindow.1.1.38\lib\net40\Tulpep.NotificationWindow.dll</HintPath>
</Reference>
<Reference Include="Vulkan, Version=0.0.6850.37785, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\VulkanSharp.0.1.10\lib\net452\Vulkan.dll</HintPath>
</Reference>
<Reference Include="Vulkan.Windows, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\VulkanSharp.0.1.10\lib\net452\Vulkan.Windows.dll</HintPath>
</Reference>
<Reference Include="Win32Interop.Dwmapi, Version=1.0.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\Win32Interop.Dwmapi.1.0.1\lib\Win32Interop.Dwmapi.dll</HintPath>
</Reference>
@@ -475,6 +481,7 @@
<Compile Include="Os\StartupChecks.cs" />
<Compile Include="Os\Updater.cs" />
<Compile Include="Os\VapourSynthUtils.cs" />
<Compile Include="Os\VulkanUtils.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="MiscUtils\FormatUtils.cs" />

View File

@@ -61,6 +61,7 @@ namespace Flowframes.Forms.Main
Program.mainForm = this;
Logger.textbox = logBox;
VulkanUtils.Init();
NvApi.Init();
InterpolationProgress.preview = previewPicturebox;
RemovePreviewIfDisabled();

View File

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

66
Code/Os/VulkanUtils.cs Normal file
View File

@@ -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<VkDevice> VkDevices { get; private set; } = null;
public static void Init()
{
var sw = new NmkdStopwatch();
VkDevices = new List<VkDevice>();
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;
}
}
}

View File

@@ -14,51 +14,13 @@ namespace Flowframes.Utilities
{
class NcnnUtils
{
public static Dictionary<int, int> GpuIdsQueueCounts = null;
/// <summary> Get amount of GPU Compute Queues (VK) for each GPU </summary>
public static async Task<Dictionary<int, int>> GetNcnnGpuComputeQueueCounts ()
{
if(GpuIdsQueueCounts != null)
return GpuIdsQueueCounts;
Dictionary<int, int> queueCounts = new Dictionary<int, int>(); // 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<int> 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<string> 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<int> enabledGpuIds = Config.Get(Config.Key.ncnnGpus).Split(',').Select(s => s.GetInt()).ToList(); // Get GPU IDs
List<int> 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
}

View File

@@ -74,6 +74,7 @@
<package id="System.Xml.XDocument" version="4.3.0" targetFramework="net472" />
<package id="TabControl" version="2.1.2" targetFramework="net472" />
<package id="Tulpep.NotificationWindow" version="1.1.38" targetFramework="net472" />
<package id="VulkanSharp" version="0.1.10" targetFramework="net472" />
<package id="Win32Interop.Dwmapi" version="1.0.1" targetFramework="net472" />
<package id="Win32Interop.Gdi32" version="1.0.1" targetFramework="net472" />
<package id="Win32Interop.Kernel32" version="1.0.1" targetFramework="net472" />