More Invoke() for cross-thread UI access, fix log box issue, allow -1 as GPU ID for CPU

This commit is contained in:
N00MKRAD
2024-12-27 19:14:43 +01:00
parent 482ed1bca9
commit 048a849e49
9 changed files with 65 additions and 50 deletions

View File

@@ -262,7 +262,7 @@
this.generalTab.Controls.Add(this.flowPanelApplication);
this.generalTab.ForeColor = System.Drawing.Color.White;
this.generalTab.Name = "generalTab";
this.generalTab.Size = new System.Drawing.Size(762, 771);
this.generalTab.Size = new System.Drawing.Size(762, 419);
this.generalTab.Text = "Application";
//
// flowPanelApplication
@@ -281,7 +281,7 @@
this.flowPanelApplication.Location = new System.Drawing.Point(0, 0);
this.flowPanelApplication.Margin = new System.Windows.Forms.Padding(0);
this.flowPanelApplication.Name = "flowPanelApplication";
this.flowPanelApplication.Size = new System.Drawing.Size(762, 771);
this.flowPanelApplication.Size = new System.Drawing.Size(762, 419);
this.flowPanelApplication.TabIndex = 96;
//
// panProcessingStyle
@@ -700,7 +700,7 @@
this.tabListPage2.Controls.Add(this.flowPanelInterpolation);
this.tabListPage2.ForeColor = System.Drawing.Color.White;
this.tabListPage2.Name = "tabListPage2";
this.tabListPage2.Size = new System.Drawing.Size(762, 771);
this.tabListPage2.Size = new System.Drawing.Size(762, 419);
this.tabListPage2.Text = "Interpolation";
//
// flowPanelInterpolation
@@ -722,7 +722,7 @@
this.flowPanelInterpolation.Location = new System.Drawing.Point(0, 0);
this.flowPanelInterpolation.Margin = new System.Windows.Forms.Padding(0);
this.flowPanelInterpolation.Name = "flowPanelInterpolation";
this.flowPanelInterpolation.Size = new System.Drawing.Size(762, 771);
this.flowPanelInterpolation.Size = new System.Drawing.Size(762, 419);
this.flowPanelInterpolation.TabIndex = 94;
//
// panTitleInputMedia

View File

@@ -54,10 +54,13 @@ namespace Flowframes.Forms
tooltipTorch += $"{i} = {NvApi.NvGpus[i].FullName} ({NvApi.NvGpus[i].GetVramGb().ToString("0.")} GB)\n";
}
ncnnGpus.Items.Add(-1);
tooltipNcnn += $"-1 = CPU\n";
foreach (var vkGpu in VulkanUtils.VkDevices)
{
ncnnGpus.Items.Add(vkGpu.Id);
tooltipNcnn += $"{vkGpu.Id} = {vkGpu.Name}\n";
tooltipNcnn += $"{vkGpu.Id.ToString().PadLeft(2)} = {vkGpu.Name}\n";
}
toolTip1.SetToolTip(tooltipTorchGpu, tooltipTorch.Trim());

View File

@@ -120,9 +120,6 @@
<metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<data name="info1.ToolTip" xml:space="preserve">
<value>Set the filename patterns using placeholders:
[NAME] for the input filename

View File

@@ -3,6 +3,7 @@ using Flowframes.Ui;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows.Forms;
@@ -58,7 +59,10 @@ namespace Flowframes
public static void Show(LogEntry entry, bool logToFile = true)
{
if (string.IsNullOrWhiteSpace(entry.logMessage))
//if (entry.logMessage.Contains("frame order info"))
// Debugger.Break();
if (entry.logMessage.IsEmpty())
return;
string msg = entry.logMessage;
@@ -77,12 +81,18 @@ namespace Flowframes
{
if (!entry.hidden && entry.replaceLastLine)
{
textbox.Suspend();
string[] lines = textbox.Text.SplitIntoLines();
textbox.Text = string.Join(Environment.NewLine, lines.Take(lines.Count() - 1).ToArray());
textbox.Invoke(new Action(() => {
textbox.Suspend();
string[] lines = textbox.Text.SplitIntoLines();
textbox.Text = string.Join(Environment.NewLine, lines.Take(lines.Count() - 1).ToArray());
}));
}
}
catch { }
catch (Exception ex)
{
Console.WriteLine($"{ex.Message}\n{ex.StackTrace}");
if (Debugger.IsAttached) Debugger.Break();
}
msg = msg.Replace("\n", Environment.NewLine);
@@ -91,7 +101,7 @@ namespace Flowframes
if (entry.replaceLastLine)
{
textbox.Resume();
textbox.Invoke(() => textbox.Resume());
msg = "[^] " + msg;
}

View File

@@ -158,8 +158,8 @@ namespace Flowframes.Main
Array.Resize(ref frameFilesWithoutLast, frameFilesWithoutLast.Length - 1);
string framesFile = Path.Combine(tempFolder, Paths.GetFrameOrderFilename(interpFactor));
string fileContent = "";
string dupesFile = Path.Combine(tempFolder, "dupes.json");
LoadDupesFile(dupesFile);
// string dupesFile = Path.Combine(tempFolder, "dupes.json");
// LoadDupesFile(dupesFile);
string scnFramesPath = Path.Combine(tempFolder, Paths.scenesDir);

View File

@@ -35,7 +35,7 @@ namespace Flowframes
if (!BatchProcessing.busy && Program.busy) return;
canceled = false;
Program.initialRun = false;
Program.mainForm.SetWorking(true);
Program.mainForm.Invoke(() => Program.mainForm.SetWorking(true));
if (!Utils.InputIsValid(currentSettings)) return; // General input checks
if (!Utils.CheckPathValid(currentSettings.inPath)) return; // Check if input path/file is valid
if (!Utils.CheckAiAvailable(currentSettings.ai, currentSettings.model)) return; // Check if selected AI pkg is installed
@@ -43,7 +43,7 @@ namespace Flowframes
if (!(await Utils.CheckEncoderValid())) return; // Check encoder compat
Utils.ShowWarnings(currentSettings.interpFactor, currentSettings.ai);
currentSettings.stepByStep = false;
Program.mainForm.SetStatus("Starting...");
Program.mainForm.Invoke(() => Program.mainForm.SetStatus("Starting..."));
sw.Restart();
if (currentMediaFile.IsVfr)
@@ -63,7 +63,7 @@ namespace Flowframes
if (skip || canceled) return;
await RunAi(currentSettings.interpFolder, currentSettings.ai);
if (canceled) return;
Program.mainForm.SetProgress(100);
Program.mainForm.Invoke(() => Program.mainForm.SetProgress(100));
if (!currentlyUsingAutoEnc)
{
@@ -88,36 +88,36 @@ namespace Flowframes
public static async Task Done()
{
await Cleanup();
Program.mainForm.SetWorking(false);
Program.mainForm.Invoke(() => Program.mainForm.SetWorking(false));
Logger.Log("Total processing time: " + FormatUtils.Time(sw.Elapsed));
sw.Stop();
if (!BatchProcessing.busy)
OsUtils.ShowNotificationIfInBackground("Flowframes", $"Finished interpolation after {FormatUtils.Time(sw.Elapsed)}.");
Program.mainForm.InterpolationDone();
Program.mainForm.Invoke(() => Program.mainForm.InterpolationDone());
}
public static async Task Realtime ()
{
canceled = false;
Program.mainForm.SetWorking(true);
Program.mainForm.Invoke(() => Program.mainForm.SetWorking(true));
if(currentSettings.ai.NameInternal != Implementations.rifeNcnnVs.NameInternal)
Cancel($"Real-time interpolation is only available when using {Implementations.rifeNcnnVs.FriendlyName}.");
if (canceled) return;
Program.mainForm.SetStatus("Downloading models...");
Program.mainForm.Invoke(() => Program.mainForm.SetStatus("Downloading models..."));
await ModelDownloader.DownloadModelFiles(currentSettings.ai, currentSettings.model.Dir);
if (canceled) return;
Program.mainForm.SetStatus("Running real-time interpolation...");
Program.mainForm.Invoke(() => Program.mainForm.SetStatus("Running real-time interpolation..."));
await AiProcess.RunRifeNcnnVs(currentSettings.framesFolder, "", currentSettings.interpFactor, currentSettings.model.Dir, true);
Program.mainForm.SetStatus("Ready");
Program.mainForm.SetWorking(false);
Program.mainForm.Invoke(() => Program.mainForm.SetStatus("Ready"));
Program.mainForm.Invoke(() => Program.mainForm.SetWorking(false));
}
public static async Task GetFrames()
@@ -127,7 +127,7 @@ namespace Flowframes
if (Config.GetBool(Config.Key.scnDetect) && !currentSettings.ai.Piped)
{
Program.mainForm.SetStatus("Extracting scenes from video...");
Program.mainForm.Invoke(() => Program.mainForm.SetStatus("Extracting scenes from video..."));
await FfmpegExtract.ExtractSceneChanges(currentSettings.inPath, Path.Combine(currentSettings.tempFolder, Paths.scenesDir), new Fraction(), currentSettings.inputIsFrames, currentSettings.framesExt);
}
@@ -140,7 +140,7 @@ namespace Flowframes
public static async Task ExtractFrames(string inPath, string outPath, bool alpha)
{
if (canceled) return;
Program.mainForm.SetStatus("Extracting frames from video...");
Program.mainForm.Invoke(() => Program.mainForm.SetStatus("Extracting frames from video..."));
currentSettings.RefreshExtensions(InterpSettings.FrameType.Import);
bool mpdecimate = Config.GetInt(Config.Key.dedupMode) == 2;
Size res = await Utils.GetOutputResolution(FfmpegCommands.ModuloMode.ForEncoding, inPath, print: true);
@@ -170,7 +170,7 @@ namespace Flowframes
{
if (canceled) return;
Program.mainForm.SetStatus("Processing frames...");
Program.mainForm.Invoke(() => Program.mainForm.SetStatus("Processing frames..."));
int extractedFrames = IoUtils.GetAmountOfFiles(currentSettings.framesFolder, false, "*" + currentSettings.framesExt);
@@ -226,7 +226,7 @@ namespace Flowframes
if (canceled) return;
Program.mainForm.SetStatus("Downloading models...");
Program.mainForm.Invoke(() => Program.mainForm.SetStatus("Downloading models..."));
await ModelDownloader.DownloadModelFiles(ai, currentSettings.model.Dir);
if (canceled) return;
@@ -263,18 +263,19 @@ namespace Flowframes
tasks.Add(AutoEncode.MainLoop(outpath));
}
Program.mainForm.SetStatus("Running AI...");
Program.mainForm.Invoke(() => Program.mainForm.SetStatus("Running AI..."));
await Task.WhenAll(tasks);
}
public static void Cancel(string reason = "", bool noMsgBox = false)
{
if (currentSettings == null)
if (currentSettings == null || canceled)
return;
canceled = true;
Program.mainForm.SetStatus("Canceled.");
Program.mainForm.SetProgress(0);
Program.mainForm.Invoke(() => Program.mainForm.SetStatus("Canceled."));
Program.mainForm.Invoke(() => Program.mainForm.SetProgress(0));
AiProcess.Kill();
AvProcess.Kill();
@@ -296,8 +297,8 @@ namespace Flowframes
}
AutoEncode.busy = false;
Program.mainForm.SetWorking(false);
Program.mainForm.SetTab(Program.mainForm.interpOptsTab.Name);
Program.mainForm.Invoke(() => Program.mainForm.SetWorking(false));
Program.mainForm.Invoke(() => Program.mainForm.SetTab(Program.mainForm.interpOptsTab.Name));
Logger.LogIfLastLineDoesNotContainMsg("Canceled interpolation.");
if(Cli.AutoRun)

View File

@@ -26,7 +26,8 @@ namespace Flowframes.Os
public static Stopwatch processTimeMulti = new Stopwatch();
public static int lastStartupTimeMs = 1000;
static string lastInPath;
private static string lastInPath;
private static string NcnnGpuIds => Config.Get(Config.Key.ncnnGpus).Trim();
public static void Kill()
{
@@ -330,7 +331,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.Lower()} {ttaStr} {uhdStr} -g {Config.Get(Config.Key.ncnnGpus)} -f {NcnnUtils.GetNcnnPattern()} -j {NcnnUtils.GetNcnnThreads(Implementations.rifeNcnn)}";
$" -v -i {inPath.Wrap()} -o {outPath.Wrap()} {frames} -m {mdl.Lower()} {ttaStr} {uhdStr} -g {NcnnGpuIds} -f {NcnnUtils.GetNcnnPattern()} -j {NcnnUtils.GetNcnnThreads(Implementations.rifeNcnn)}";
Logger.Log("cmd.exe " + rifeNcnn.StartInfo.Arguments, true);
@@ -379,7 +380,7 @@ namespace Flowframes.Os
string avDir = Path.Combine(Paths.GetPkgPath(), Paths.audioVideoDir);
string pipedTargetArgs = $"{Path.Combine(avDir, "ffmpeg").Wrap()} -loglevel warning -stats -y {await Export.GetPipedFfmpegCmd(rt)}";
string pkgDir = Path.Combine(Paths.GetPkgPath(), Implementations.rifeNcnnVs.PkgDir);
int gpuId = Config.Get(Config.Key.ncnnGpus).Split(',')[0].GetInt();
int gpuId = NcnnGpuIds.Split(',')[0].GetInt();
var vsSettings = new VapourSynthUtils.VsSettings()
{
@@ -462,7 +463,7 @@ namespace Flowframes.Os
int targetFrames = ((IoUtils.GetAmountOfFiles(lastInPath, false, "*.*") * factor).RoundToInt());
string args = $" -v -i {framesPath.Wrap()} -o {outPath.Wrap()} -n {targetFrames} -m {mdl.Lower()}" +
$" -t {NcnnUtils.GetNcnnTilesize(tilesize)} -g {Config.Get(Config.Key.ncnnGpus)} -f {NcnnUtils.GetNcnnPattern()} -j 2:1:2";
$" -t {NcnnUtils.GetNcnnTilesize(tilesize)} -g {NcnnGpuIds} -f {NcnnUtils.GetNcnnPattern()} -j 2:1:2";
dain.StartInfo.Arguments = $"{OsUtils.GetCmdArg()} cd /D {dainDir.Wrap()} & dain-ncnn-vulkan.exe {args}";
Logger.Log("Running DAIN...", false);
@@ -584,7 +585,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 {NcnnUtils.GetNcnnThreads(Implementations.ifrnetNcnn)}";
$" -v -i {inPath.Wrap()} -o {outPath.Wrap()} -m {mdl} {ttaStr} {uhdStr} -g {NcnnGpuIds} -f {NcnnUtils.GetNcnnPattern()} -j {NcnnUtils.GetNcnnThreads(Implementations.ifrnetNcnn)}";
Logger.Log("cmd.exe " + ifrnetNcnn.StartInfo.Arguments, true);

View File

@@ -138,7 +138,7 @@ namespace Flowframes.Os
Fraction factor = new Fraction(s.Factor);
string interpStr = alwaysPreferFactorOverFps || Interpolate.currentMediaFile.IsVfr ? $"factor_num={factor.Numerator}, factor_den={factor.Denominator}" : $"fps_num={outFps.Numerator}, fps_den={outFps.Denominator}";
l.Add($"clip = core.rife.RIFE(clip, {interpStr}, model_path={mdlPath}, gpu_id={s.GpuId}, gpu_thread={s.GpuThreads}, tta={s.Tta}, uhd={s.Uhd}, sc={sc})"); // Interpolate
l.Add($"clip = core.rife.RIFE(clip, {interpStr}, model_path={mdlPath}, gpu_id={s.GpuId.ToString().Replace("-1", "None")}, gpu_thread={s.GpuThreads}, tta={s.Tta}, uhd={s.Uhd}, sc={sc})"); // Interpolate
if (s.Dedupe && !s.Realtime)
{

View File

@@ -53,19 +53,22 @@ namespace Flowframes.Os
// Clean up Vulkan resources
vkInstance.Destroy();
Logger.Log($"[VK] Vulkan device check completed after {sw.ElapsedMs} ms", true);
if (VkDevices.Count == 0)
return;
// Set the device that has the most compute queues as default GPU
var maxQueuesDevice = VkDevices.OrderByDescending(d => d.ComputeQueueCount).First();
Config.Set(Config.Key.ncnnGpus, $"{maxQueuesDevice.Id}");
}
catch(Exception ex)
{
Logger.Log($"Vulkan Error: {ex.Message}", true);
Logger.Log($"Vulkan initialization failed. NCNN implementations might not work, or run on the CPU.");
}
if (VkDevices.Count == 0)
{
Logger.Log($"No Vulkan-capable GPUs found. NCNN implementations will run on the CPU instead and may be unstable.");
Config.Set(Config.Key.ncnnGpus, "-1"); // -1 = CPU
return;
}
// Set the device that has the most compute queues as default GPU
var maxQueuesDevice = VkDevices.OrderByDescending(d => d.ComputeQueueCount).First();
Config.Set(Config.Key.ncnnGpus, $"{maxQueuesDevice.Id}");
}
public static int GetMaxNcnnThreads(int deviceId)