diff options
author | sr55 <[email protected]> | 2020-10-11 16:12:46 +0100 |
---|---|---|
committer | sr55 <[email protected]> | 2020-10-11 16:13:02 +0100 |
commit | d5a58c985dcb0a9e3326a724b567c8fc1dcb6cb4 (patch) | |
tree | 3465adf7ede04ff5a2ff01fb9b34eba4b6cb07d9 | |
parent | 1883642eb32a2808924c2ef5db06f105657413f6 (diff) |
WinGui: Support allocation of work across multiple Intel GPU's
-rw-r--r-- | win/CS/HandBrake.sln.DotSettings | 1 | ||||
-rw-r--r-- | win/CS/HandBrakeWPF/Services/Queue/QueueResourceService.cs | 72 | ||||
-rw-r--r-- | win/CS/HandBrakeWPF/Services/Queue/QueueService.cs | 10 |
3 files changed, 69 insertions, 14 deletions
diff --git a/win/CS/HandBrake.sln.DotSettings b/win/CS/HandBrake.sln.DotSettings index 0882a1550..bb5657d87 100644 --- a/win/CS/HandBrake.sln.DotSettings +++ b/win/CS/HandBrake.sln.DotSettings @@ -791,6 +791,7 @@ <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=AC/@EntryIndexedValue">AC</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DTS/@EntryIndexedValue">DTS</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DTSHD/@EntryIndexedValue">DTSHD</s:String> + <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GPU/@EntryIndexedValue">GPU</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HD/@EntryIndexedValue">HD</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=MP/@EntryIndexedValue">MP</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RF/@EntryIndexedValue">RF</s:String> diff --git a/win/CS/HandBrakeWPF/Services/Queue/QueueResourceService.cs b/win/CS/HandBrakeWPF/Services/Queue/QueueResourceService.cs index cbd97029d..889007311 100644 --- a/win/CS/HandBrakeWPF/Services/Queue/QueueResourceService.cs +++ b/win/CS/HandBrakeWPF/Services/Queue/QueueResourceService.cs @@ -12,35 +12,48 @@ namespace HandBrakeWPF.Services.Queue using System; using System.Collections.Generic; + using HandBrake.Interop.Interop; using HandBrake.Interop.Interop.Model.Encoding; + using HandBrakeWPF.Services.Encode.Model; + using HandBrakeWPF.Services.Interfaces; + public class QueueResourceService { + private readonly IUserSettingService userSettingService; + private readonly object lockOjb = new object(); - private HashSet<Guid> qsvInstances = new HashSet<Guid>(); - private HashSet<Guid> nvencInstances = new HashSet<Guid>(); - private HashSet<Guid> vceInstances = new HashSet<Guid>(); + private readonly HashSet<Guid> qsvInstances = new HashSet<Guid>(); + private readonly HashSet<Guid> nvencInstances = new HashSet<Guid>(); + private readonly HashSet<Guid> vceInstances = new HashSet<Guid>(); private List<int> qsvGpus = new List<int>(); - + private int intelGpuCounter = -1; // Always default to the first card when allocating. + + public QueueResourceService(IUserSettingService userSettingService) + { + this.userSettingService = userSettingService; + } + public void Init() { - // TODO Coming Soon! - // List<int> qsvGpus = hbFunctions.hb_qsv_adapters_list(); + this.qsvGpus = HandBrakeEncoderHelpers.GetQsvAdaptorList(); } - public Guid? GetHardwareLock(VideoEncoder encoder) + public Guid? GetHardwareLock(EncodeTask task) { lock (this.lockOjb) { - switch (encoder) + switch (task.VideoEncoder) { case VideoEncoder.QuickSync: case VideoEncoder.QuickSyncH265: case VideoEncoder.QuickSyncH26510b: if (this.qsvInstances.Count < 3) { + this.AllocateIntelGPU(task); + Guid guid = Guid.NewGuid(); this.qsvInstances.Add(guid); return guid; @@ -121,5 +134,48 @@ namespace HandBrakeWPF.Services.Queue } } } + + public void AllocateIntelGPU(EncodeTask task) + { + // Validation checks. + if (task.VideoEncoder != VideoEncoder.QuickSync && task.VideoEncoder != VideoEncoder.QuickSyncH265 && task.VideoEncoder != VideoEncoder.QuickSyncH26510b) + { + return; // Not a QSV job. + } + + if (this.qsvGpus.Count <= 1) + { + return; // Not a multi-Intel-GPU system. + } + + if (task.ExtraAdvancedArguments.Contains("gpu")) + { + return; // Users choice + } + + if (!this.userSettingService.GetUserSetting<bool>(UserSettingConstants.ProcessIsolationEnabled)) + { + return; // Multi-Process encoding is disabled. + } + + if (this.userSettingService.GetUserSetting<int>(UserSettingConstants.SimultaneousEncodes) <= 1) + { + return; // Multi-Process encoding is disabled. + } + + this.intelGpuCounter = this.intelGpuCounter + 1; + int modulus = this.intelGpuCounter % 2; + + // For now, it's not expected we'll see users with more than 2 Intel GPUs. Typically 1 CPU, 1 Discrete will likely be the norm. + // Use the modulus of the above counter to flip between the 2 Intel encoders. + // We don't set GPU for the jobs 1, 3, 5, 7, 9 .... etc (Default to first) + // We do set the GPU for jobs 2, 4, 5, 8, 10 .... etc + if (modulus == 1) + { + task.ExtraAdvancedArguments = string.IsNullOrEmpty(task.ExtraAdvancedArguments) + ? string.Format("gpu={0}", this.qsvGpus[1]) + : string.Format("{0}:gpu={1}", task.ExtraAdvancedArguments, this.qsvGpus[1]); + } + } } } diff --git a/win/CS/HandBrakeWPF/Services/Queue/QueueService.cs b/win/CS/HandBrakeWPF/Services/Queue/QueueService.cs index 1c7746cb6..3ccb41044 100644 --- a/win/CS/HandBrakeWPF/Services/Queue/QueueService.cs +++ b/win/CS/HandBrakeWPF/Services/Queue/QueueService.cs @@ -58,7 +58,7 @@ namespace HandBrakeWPF.Services.Queue private readonly string queueFile; private readonly object queueFileLock = new object(); - private readonly QueueResourceService hardwareEncoderResourceManager = new QueueResourceService(); + private readonly QueueResourceService hardwareEncoderResourceManager; private int allowedInstances; private int jobIdCounter = 0; @@ -69,6 +69,7 @@ namespace HandBrakeWPF.Services.Queue public QueueService(IUserSettingService userSettingService, ILog logService, IErrorService errorService, ILogInstanceManager logInstanceManager, IPortService portService) { this.userSettingService = userSettingService; + this.hardwareEncoderResourceManager = new QueueResourceService(userSettingService); this.logService = logService; this.errorService = errorService; this.logInstanceManager = logInstanceManager; @@ -353,7 +354,7 @@ namespace HandBrakeWPF.Services.Queue QueueTask task = this.queue.FirstOrDefault(q => q.Status == QueueItemStatus.Waiting); if (task != null) { - task.HardwareResourceToken = this.hardwareEncoderResourceManager.GetHardwareLock(task.Task.VideoEncoder); + task.HardwareResourceToken = this.hardwareEncoderResourceManager.GetHardwareLock(task.Task); return task; } } @@ -687,10 +688,7 @@ namespace HandBrakeWPF.Services.Queue this.IsProcessing = false; EventHandler handler = this.QueuePaused; - if (handler != null) - { - handler(this, e); - } + handler?.Invoke(this, e); } private string GetQueueJson(List<EncodeTask> tasks, HBConfiguration configuration) |