diff --git a/Code/Forms/SettingsForm.Designer.cs b/Code/Forms/SettingsForm.Designer.cs index 608d300..fad7c36 100644 --- a/Code/Forms/SettingsForm.Designer.cs +++ b/Code/Forms/SettingsForm.Designer.cs @@ -164,6 +164,8 @@ this.cmdDebugMode = new System.Windows.Forms.ComboBox(); this.titleLabel = new System.Windows.Forms.Label(); this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); + this.label65 = new System.Windows.Forms.Label(); + this.rifeCudaFp16 = new System.Windows.Forms.CheckBox(); this.settingsTabList.SuspendLayout(); this.generalTab.SuspendLayout(); this.tabListPage2.SuspendLayout(); @@ -821,6 +823,8 @@ // aiOptsPage // this.aiOptsPage.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(48)))), ((int)(((byte)(48)))), ((int)(((byte)(48))))); + this.aiOptsPage.Controls.Add(this.rifeCudaFp16); + this.aiOptsPage.Controls.Add(this.label65); this.aiOptsPage.Controls.Add(this.label35); this.aiOptsPage.Controls.Add(this.panel12); this.aiOptsPage.Controls.Add(this.dainNcnnTilesize); @@ -849,7 +853,7 @@ // this.label35.AutoSize = true; this.label35.ForeColor = System.Drawing.Color.Silver; - this.label35.Location = new System.Drawing.Point(412, 261); + this.label35.Location = new System.Drawing.Point(412, 291); this.label35.Margin = new System.Windows.Forms.Padding(10, 10, 10, 7); this.label35.Name = "label35"; this.label35.Size = new System.Drawing.Size(258, 13); @@ -860,7 +864,7 @@ // this.panel12.BackgroundImage = global::Flowframes.Properties.Resources.baseline_create_white_18dp_semiTransparent; this.panel12.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom; - this.panel12.Location = new System.Drawing.Point(378, 257); + this.panel12.Location = new System.Drawing.Point(378, 287); this.panel12.Name = "panel12"; this.panel12.Size = new System.Drawing.Size(21, 21); this.panel12.TabIndex = 78; @@ -880,7 +884,7 @@ "1024", "1536", "2048"}); - this.dainNcnnTilesize.Location = new System.Drawing.Point(280, 257); + this.dainNcnnTilesize.Location = new System.Drawing.Point(280, 287); this.dainNcnnTilesize.Margin = new System.Windows.Forms.Padding(3, 3, 8, 3); this.dainNcnnTilesize.Name = "dainNcnnTilesize"; this.dainNcnnTilesize.Size = new System.Drawing.Size(87, 21); @@ -889,7 +893,7 @@ // label27 // this.label27.AutoSize = true; - this.label27.Location = new System.Drawing.Point(10, 260); + this.label27.Location = new System.Drawing.Point(10, 290); this.label27.Margin = new System.Windows.Forms.Padding(10, 10, 10, 7); this.label27.Name = "label27"; this.label27.Size = new System.Drawing.Size(93, 13); @@ -900,7 +904,7 @@ // this.label26.AutoSize = true; this.label26.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Bold); - this.label26.Location = new System.Drawing.Point(10, 230); + this.label26.Location = new System.Drawing.Point(10, 260); this.label26.Margin = new System.Windows.Forms.Padding(10, 10, 10, 7); this.label26.Name = "label26"; this.label26.Size = new System.Drawing.Size(152, 16); @@ -1884,6 +1888,25 @@ this.titleLabel.TabIndex = 1; this.titleLabel.Text = "Settings"; // + // label65 + // + this.label65.AutoSize = true; + this.label65.Location = new System.Drawing.Point(11, 210); + this.label65.Margin = new System.Windows.Forms.Padding(10, 10, 10, 7); + this.label65.Name = "label65"; + this.label65.Size = new System.Drawing.Size(120, 13); + this.label65.TabIndex = 81; + this.label65.Text = "Fast Mode (CUDA Only)"; + // + // rifeCudaFp16 + // + this.rifeCudaFp16.AutoSize = true; + this.rifeCudaFp16.Location = new System.Drawing.Point(280, 210); + this.rifeCudaFp16.Name = "rifeCudaFp16"; + this.rifeCudaFp16.Size = new System.Drawing.Size(15, 14); + this.rifeCudaFp16.TabIndex = 82; + this.rifeCudaFp16.UseVisualStyleBackColor = true; + // // SettingsForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -2058,5 +2081,7 @@ private System.Windows.Forms.ComboBox modelsBaseUrl; private System.Windows.Forms.Label label42; private System.Windows.Forms.Panel panel13; + private System.Windows.Forms.CheckBox rifeCudaFp16; + private System.Windows.Forms.Label label65; } } \ No newline at end of file diff --git a/Code/Forms/SettingsForm.cs b/Code/Forms/SettingsForm.cs index 931fc74..13f6964 100644 --- a/Code/Forms/SettingsForm.cs +++ b/Code/Forms/SettingsForm.cs @@ -84,6 +84,7 @@ namespace Flowframes.Forms ConfigParser.SaveGuiElement(ncnnGpus); ConfigParser.SaveGuiElement(ncnnThreads); ConfigParser.SaveGuiElement(uhdThresh); + ConfigParser.SaveGuiElement(rifeCudaFp16); ConfigParser.SaveGuiElement(dainNcnnTilesize, ConfigParser.StringMode.Int); // Video Export ConfigParser.SaveGuiElement(minOutVidLength, ConfigParser.StringMode.Int); @@ -135,6 +136,7 @@ namespace Flowframes.Forms ConfigParser.LoadGuiElement(ncnnGpus); ConfigParser.LoadGuiElement(ncnnThreads); ConfigParser.LoadGuiElement(uhdThresh); + ConfigParser.LoadGuiElement(rifeCudaFp16); ConfigParser.LoadGuiElement(dainNcnnTilesize); // Video Export ConfigParser.LoadGuiElement(minOutVidLength); diff --git a/Code/IO/Config.cs b/Code/IO/Config.cs index 8d68a11..d3ef38c 100644 --- a/Code/IO/Config.cs +++ b/Code/IO/Config.cs @@ -152,6 +152,7 @@ namespace Flowframes.IO if (key == "minVidLength") return WriteDefault(key, "2"); // AI if (key == "uhdThresh") return WriteDefault(key, "1440"); + if (key == "rifeCudaFp16") return WriteDefault(key, NvApi.HasTensorCores().ToString()); if (key == "ncnnThreads") return WriteDefault(key, "1"); if (key == "dainNcnnTilesize") return WriteDefault(key, "768"); // Debug / Other / Experimental diff --git a/Code/OS/AiProcess.cs b/Code/OS/AiProcess.cs index 438670b..857f9bc 100644 --- a/Code/OS/AiProcess.cs +++ b/Code/OS/AiProcess.cs @@ -120,7 +120,8 @@ namespace Flowframes string outPath = Path.Combine(inPath.GetParentDir(), outDir); string wthreads = $"--wthreads {2 * (int)interpFactor}"; string rbuffer = $"--rbuffer {Config.GetInt("rifeCudaBufferSize", 200)}"; - string args = $" --input {inPath.Wrap()} --output {outDir} --model {mdl} --exp {(int)Math.Log(interpFactor, 2)} {wthreads} {rbuffer}"; + string prec = Config.GetBool("rifeCudaFp16") ? "--fp16" : ""; + string args = $" --input {inPath.Wrap()} --output {outDir} --model {mdl} --exp {(int)Math.Log(interpFactor, 2)} {wthreads} {rbuffer} {prec}"; // if (parallel) args = $" --input {inPath.Wrap()} --output {outPath} --model {mdl} --factor {interpFactor}"; // if (parallel) script = "rife-parallel.py"; diff --git a/Code/OS/NvApi.cs b/Code/OS/NvApi.cs index fc22f7f..94cce2a 100644 --- a/Code/OS/NvApi.cs +++ b/Code/OS/NvApi.cs @@ -24,7 +24,7 @@ namespace Flowframes.OS return; gpu = gpus[0]; - Logger.Log($"Initialized NvApi. GPU: {gpu.FullName}"); + Logger.Log($"Initialized NvApi. GPU: {gpu.FullName} - Tensor Cores: {HasTensorCores()}"); } catch (Exception e) { @@ -50,7 +50,7 @@ namespace Flowframes.OS { return (gpu.MemoryInformation.CurrentAvailableDedicatedVideoMemoryInkB / 1000f / 1024f); } - catch (Exception e) + catch { return 0f; } @@ -72,5 +72,18 @@ namespace Flowframes.OS return ""; } } + + public static bool HasTensorCores () + { + if (gpu == null) + Init(); + + if (gpu == null) + return false; + + string gpuName = gpu.FullName; + + return (gpuName.Contains("RTX 20") || gpuName.Contains("RTX 30") || gpuName.Contains("Tesla V") || gpuName.Contains("Tesla T")); + } } } diff --git a/Pkgs/rife-cuda/model/warplayer.py b/Pkgs/rife-cuda/model/warplayer.py index bf52972..70dee9b 100644 --- a/Pkgs/rife-cuda/model/warplayer.py +++ b/Pkgs/rife-cuda/model/warplayer.py @@ -8,9 +8,9 @@ backwarp_tenGrid = {} def warp(tenInput, tenFlow): k = (str(tenFlow.device), str(tenFlow.size())) if k not in backwarp_tenGrid: - tenHorizontal = torch.linspace(-1.0, 1.0, tenFlow.shape[3]).view( + tenHorizontal = torch.linspace(-1.0, 1.0, tenFlow.shape[3], device=device).view( 1, 1, 1, tenFlow.shape[3]).expand(tenFlow.shape[0], -1, tenFlow.shape[2], -1) - tenVertical = torch.linspace(-1.0, 1.0, tenFlow.shape[2]).view( + tenVertical = torch.linspace(-1.0, 1.0, tenFlow.shape[2], device=device).view( 1, 1, tenFlow.shape[2], 1).expand(tenFlow.shape[0], -1, -1, tenFlow.shape[3]) backwarp_tenGrid[k] = torch.cat( [tenHorizontal, tenVertical], 1).to(device) @@ -19,4 +19,4 @@ def warp(tenInput, tenFlow): tenFlow[:, 1:2, :, :] / ((tenInput.shape[2] - 1.0) / 2.0)], 1) g = (backwarp_tenGrid[k] + tenFlow).permute(0, 2, 3, 1) - return torch.nn.functional.grid_sample(input=tenInput, grid=torch.clamp(g, -1, 1), mode='bilinear', padding_mode='zeros', align_corners=True) + return torch.nn.functional.grid_sample(input=tenInput, grid=torch.clamp(g, -1, 1), mode='bilinear', padding_mode='zeros', align_corners=True) \ No newline at end of file diff --git a/Pkgs/rife-cuda/rife.py b/Pkgs/rife-cuda/rife.py index 0b00ee6..60ba319 100644 --- a/Pkgs/rife-cuda/rife.py +++ b/Pkgs/rife-cuda/rife.py @@ -19,11 +19,29 @@ os.chdir(os.path.dirname(dname)) print("Added {0} to temporary PATH".format(dname)) sys.path.append(dname) + +parser = argparse.ArgumentParser(description='Interpolation for a pair of images') +parser.add_argument('--input', dest='input', type=str, default=None) +parser.add_argument('--output', required=False, default='frames-interpolated') +parser.add_argument('--model', required=False, default='models') +parser.add_argument('--imgformat', default="png") +parser.add_argument('--rbuffer', dest='rbuffer', type=int, default=200) +parser.add_argument('--wthreads', dest='wthreads', type=int, default=4) +parser.add_argument('--fp16', dest='fp16', action='store_true', help='half-precision mode') +parser.add_argument('--UHD', dest='UHD', action='store_true', help='support 4k video') +parser.add_argument('--exp', dest='exp', type=int, default=1) +args = parser.parse_args() +assert (not args.input is None) + + device = torch.device("cuda" if torch.cuda.is_available() else "cpu") torch.set_grad_enabled(False) if torch.cuda.is_available(): torch.backends.cudnn.enabled = True torch.backends.cudnn.benchmark = True + if(args.fp16): + torch.set_default_tensor_type(torch.HalfTensor) + print("RIFE is running in FP16 mode.") else: print("WARNING: CUDA is not available, RIFE is running on CPU! [ff:nocuda-cpu]") @@ -34,18 +52,6 @@ try: except: print("Failed to get hardware info!") -parser = argparse.ArgumentParser(description='Interpolation for a pair of images') -parser.add_argument('--input', dest='input', type=str, default=None) -parser.add_argument('--output', required=False, default='frames-interpolated') -parser.add_argument('--model', required=False, default='models') -parser.add_argument('--imgformat', default="png") -parser.add_argument('--rbuffer', dest='rbuffer', type=int, default=200) -parser.add_argument('--wthreads', dest='wthreads', type=int, default=4) -parser.add_argument('--UHD', dest='UHD', action='store_true', help='support 4k video') -parser.add_argument('--exp', dest='exp', type=int, default=1) -args = parser.parse_args() -assert (not args.input is None) - try: from model.RIFE_HD import Model model = Model() @@ -104,6 +110,12 @@ def make_inference(I0, I1, exp): first_half = make_inference(I0, middle, exp=exp - 1) second_half = make_inference(middle, I1, exp=exp - 1) return [*first_half, middle, *second_half] + +def pad_image(img): + if(args.fp16): + return F.pad(img, padding).half() + else: + return F.pad(img, padding) if args.UHD: print("UHD mode enabled.") @@ -122,7 +134,7 @@ for x in range(args.wthreads): _thread.start_new_thread(clear_write_buffer, (args, write_buffer, x)) I1 = torch.from_numpy(np.transpose(lastframe, (2,0,1))).to(device, non_blocking=True).unsqueeze(0).float() / 255. -I1 = F.pad(I1, padding) +I1 = F.pad(I1, padding).half() while True: frame = read_buffer.get() @@ -130,7 +142,7 @@ while True: break I0 = I1 I1 = torch.from_numpy(np.transpose(frame, (2,0,1))).to(device, non_blocking=True).unsqueeze(0).float() / 255. - I1 = F.pad(I1, padding) + I1 = pad_image(I1) output = make_inference(I0, I1, args.exp) write_buffer.put([cnt, lastframe])