diff --git a/README.md b/README.md index 6a53c87..4dab50e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# ComfyUI-Crystools [![Hits](https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fgithub.com%2Fcrystian%2FComfyUI-Crystools&count_bg=%2379C83D&title_bg=%23555555&icon=&icon_color=%23E7E7E7&title=hits&edge_flat=false)](https://hits.seeyoufarm.com) [![Donate](https://img.shields.io/badge/Donate-PayPal-blue.svg)](https://paypal.me/crystian77) +# ComfyUI-Crystools [![Hits](https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fgithub.com%2Fcrystian%2FComfyUI-Crystools&count_bg=%2379C83D&title_bg=%23555555&icon=&icon_color=%23E7E7E7&title=hits&edge_flat=false)](https://hits.seeyoufarm.com) [![Donate](https://img.shields.io/badge/Donate-PayPal-blue.svg)](https://paypal.me/crystian77) Open in Colab **_🪛 A powerful set of tools for your belt when you work with ComfyUI 🪛_** @@ -37,13 +37,12 @@ You can configure the refresh rate which resources to show: > **Notes:** > - The GPU data is only available when you use CUDA (only NVIDIA cards, sorry AMD users). -> - It is not perfect, but it is a good approximation. +> - This extension needs ComfyUI 1915 (or higher). +> - The cost of the monitor is low (0.1 to 0.5% of utilization), you can disable it from settings (`Refres rate` to `0`). > - Data comes from these libraries: > - [psutil](https://pypi.org/project/psutil/) > - [torch](https://pytorch.org/) > - [pynvml](https://pypi.org/project/pynvml/) (official NVIDIA library) -> - This is a beta version, so please report any issue you find. - ### Progress bar @@ -513,6 +512,9 @@ You have predefined switches (string, latent, image, conditioning) but you can u ### Crystools +### 1.10.0 (17/01/2024) +- Multi-gpu added + ### 1.9.2 (15/01/2024) - Big refactor on hardwareInfo and monitor.ts, gpu was separated on another file, preparing for multi-gpu support diff --git a/__init__.py b/__init__.py index a0f4a81..ebafca8 100644 --- a/__init__.py +++ b/__init__.py @@ -2,7 +2,7 @@ @author: Crystian @title: Crystools @nickname: Crystools -@version: 1.9.3 +@version: 1.10.0 @project: "https://github.com/crystian/ComfyUI-Crystools", @description: Plugins for multiples uses, mainly for debugging, you need them! IG: https://www.instagram.com/crystian.ia """ diff --git a/core/version.py b/core/version.py index a52be3a..890002b 100644 --- a/core/version.py +++ b/core/version.py @@ -1 +1 @@ -version = "1.9.3" +version = "1.10.0" diff --git a/general/gpu.py b/general/gpu.py index 0c7c55e..e652a5d 100644 --- a/general/gpu.py +++ b/general/gpu.py @@ -15,8 +15,8 @@ class CGPUInfo: torchDevice = 'cpu' cudaDevice = 'cpu' cudaDevicesFound = 0 - switchGPU = False - switchVRAM = False + switchGPU = True + switchVRAM = True gpus = [] gpusUtilization = [] gpusVRAM = [] @@ -31,11 +31,17 @@ class CGPUInfo: if self.pynvmlLoaded and pynvml.nvmlDeviceGetCount() > 0: self.cudaDevicesFound = pynvml.nvmlDeviceGetCount() + + logger.info(f"GPU/s:") + + # for simulate multiple GPUs (for testing) interchange these comments: + # for deviceIndex in range(3): + # deviceHandle = pynvml.nvmlDeviceGetHandleByIndex(0) for deviceIndex in range(self.cudaDevicesFound): deviceHandle = pynvml.nvmlDeviceGetHandleByIndex(deviceIndex) + gpuName = pynvml.nvmlDeviceGetName(deviceHandle) - logger.info(f"GPU/s:") logger.info(f"{deviceIndex}) {gpuName}") self.gpus.append({ @@ -44,8 +50,8 @@ class CGPUInfo: }) # same index as gpus, with default values - self.gpusUtilization.append(False) - self.gpusVRAM.append(False) + self.gpusUtilization.append(True) + self.gpusVRAM.append(True) self.cuda = True logger.info(f'NVIDIA Driver: {pynvml.nvmlSystemGetDriverVersion()}') @@ -80,26 +86,39 @@ class CGPUInfo: if self.cudaDevice == 'cpu': gpuType = 'cpu' gpus.append({ - 'gpu_utilization': -1, - 'vram_total': -1, - 'vram_used': -1, - 'vram_used_percent': -1, + 'gpu_utilization': 0, + 'vram_total': 0, + 'vram_used': 0, + 'vram_used_percent': 0, }) else: gpuType = self.cudaDevice if self.pynvmlLoaded and self.cuda and self.cudaAvailable: + + # for simulate multiple GPUs (for testing) interchange these comments: + # for deviceIndex in range(3): + # deviceHandle = pynvml.nvmlDeviceGetHandleByIndex(0) for deviceIndex in range(self.cudaDevicesFound): deviceHandle = pynvml.nvmlDeviceGetHandleByIndex(deviceIndex) # GPU Utilization - # if self.switchGPU and self.gpusUtilization[deviceIndex]: - if self.switchGPU: - utilization = pynvml.nvmlDeviceGetUtilizationRates(deviceHandle) - gpuUtilization = utilization.gpu + if self.switchGPU and self.gpusUtilization[deviceIndex]: + gpuUtilization = 0 + try: + utilization = pynvml.nvmlDeviceGetUtilizationRates(deviceHandle) + gpuUtilization = utilization.gpu + except Exception as e: + if str(e) == "Unknown Error": + logger.error('For some reason, pynvml is not working in a laptop with only battery, try to connect and turn on the monitor') + else: + logger.error('Could not get GPU utilization.' + str(e)) + + logger.error('Monitor of GPU is turning off (not on UI!)') + self.switchGPU = False # VRAM - if self.switchVRAM: + if self.switchVRAM and self.gpusVRAM[deviceIndex]: # Torch or pynvml?, pynvml is more accurate with the system, torch is more accurate with comfyUI memory = pynvml.nvmlDeviceGetMemoryInfo(deviceHandle) vramUsed = memory.used diff --git a/server/monitor.py b/server/monitor.py index 5ccb35e..b77144d 100644 --- a/server/monitor.py +++ b/server/monitor.py @@ -28,13 +28,6 @@ async def newSettings(request): cmonitor.hardwareInfo.switchCPU = switchCPU - if 'switchGPU' in settings is not None: - switchGPU = settings['switchGPU'] - if type(switchGPU) is not bool: - raise Exception('switchGPU must be an boolean.') - - cmonitor.hardwareInfo.switchGPU = switchGPU - if 'switchHDD' in settings is not None: switchHDD = settings['switchHDD'] if type(switchHDD) is not bool: @@ -49,13 +42,6 @@ async def newSettings(request): cmonitor.hardwareInfo.switchRAM = switchRAM - if 'switchVRAM' in settings is not None: - switchVRAM = settings['switchVRAM'] - if type(switchVRAM) is not bool: - raise Exception('switchVRAM must be an boolean.') - - cmonitor.hardwareInfo.switchVRAM = switchVRAM - if 'whichHDD' in settings is not None: whichHDD = settings['whichHDD'] if type(whichHDD) is not str: @@ -104,7 +90,6 @@ def getHDDs(request): def getGPUs(request): try: gpuInfo = cmonitor.hardwareInfo.getGPUInfo() - print(gpuInfo) return web.json_response(gpuInfo) except Exception as e: logger.error(e) @@ -122,6 +107,12 @@ async def getGPUs(request): cmonitor.hardwareInfo.GPUInfo.gpusUtilization[int(index)] = settings['utilization'] + if 'vram' in settings is not None: + if type(settings['vram']) is not bool: + raise Exception('vram must be an boolean.') + + cmonitor.hardwareInfo.GPUInfo.gpusVRAM[int(index)] = settings['vram'] + return web.Response(status=200) except Exception as e: logger.error(e) diff --git a/version b/version index 77fee73..81c871d 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.9.3 +1.10.0 diff --git a/web/monitor.js b/web/monitor.js index fb67c8a..7e02709 100644 --- a/web/monitor.js +++ b/web/monitor.js @@ -51,6 +51,18 @@ class CrystoolsMonitor { writable: true, value: '/' }); + Object.defineProperty(this, "monitorGPUSettings", { + enumerable: true, + configurable: true, + writable: true, + value: [] + }); + Object.defineProperty(this, "monitorVRAMSettings", { + enumerable: true, + configurable: true, + writable: true, + value: [] + }); Object.defineProperty(this, "monitorCPUElement", { enumerable: true, configurable: true, @@ -118,50 +130,6 @@ class CrystoolsMonitor { }, } }); - Object.defineProperty(this, "monitorGPUElement", { - enumerable: true, - configurable: true, - writable: true, - value: { - id: 'Crystools.switchGPU', - name: this.menuPrefix + ' [monitor] GPU Usage', - type: 'boolean', - label: 'GPU', - defaultValue: true, - htmlMonitorRef: undefined, - htmlMonitorSliderRef: undefined, - htmlMonitorLabelRef: undefined, - cssColor: '#0C86F4', - onChange: async (value) => { - this.updateWidget(this.monitorGPUElement); - await this.updateServer({ - switchGPU: value, - }); - }, - } - }); - Object.defineProperty(this, "monitorVRAMElement", { - enumerable: true, - configurable: true, - writable: true, - value: { - id: 'Crystools.switchVRAM', - name: this.menuPrefix + ' [monitor] VRAM Used', - type: 'boolean', - label: 'VRAM', - defaultValue: true, - htmlMonitorRef: undefined, - htmlMonitorSliderRef: undefined, - htmlMonitorLabelRef: undefined, - cssColor: '#176EC7', - onChange: async (value) => { - this.updateWidget(this.monitorVRAMElement); - await this.updateServer({ - switchVRAM: value, - }); - }, - } - }); Object.defineProperty(this, "createSettings", { enumerable: true, configurable: true, @@ -169,8 +137,6 @@ class CrystoolsMonitor { value: () => { app.ui.settings.addSetting(this.monitorCPUElement); app.ui.settings.addSetting(this.monitorRAMElement); - app.ui.settings.addSetting(this.monitorGPUElement); - app.ui.settings.addSetting(this.monitorVRAMElement); app.ui.settings.addSetting(this.monitorHDDElement); app.ui.settings.addSetting({ id: this.idInputRate, @@ -246,6 +212,64 @@ class CrystoolsMonitor { }, }); }); + void this.getGPUsFromServer().then((gpus) => { + let moreThanOneGPU = false; + if (gpus.length > 1) { + moreThanOneGPU = true; + } + gpus?.forEach(({ name, index }) => { + if (name === undefined || index === undefined) { + console.warn('getGPUsFromServer: name or index undefined', name, index); + return; + } + let label = 'GPU'; + let labelVRAM = 'VRAM'; + if (moreThanOneGPU) { + label = 'GPU ' + index; + labelVRAM = 'VRAM' + index; + } + const monitorGPUNElement = { + id: 'Crystools.switchGPU' + index, + name: this.menuPrefix + `[menu] Display GPU monitor\r\n[${index}] ${name}`, + type: 'boolean', + label, + title: `${index}: ${name}`, + defaultValue: true, + htmlMonitorRef: undefined, + htmlMonitorSliderRef: undefined, + htmlMonitorLabelRef: undefined, + cssColor: '#0C86F4', + onChange: async (value) => { + this.updateWidget(monitorGPUNElement); + void await this.updateServerGPU(index, { + utilization: value + }); + }, + }; + const monitorVRAMNElement = { + id: 'Crystools.switchVRAM' + index, + name: this.menuPrefix + `[menu] Display GPU VRAM monitor\r\n[${index}] ${name}`, + type: 'boolean', + label: labelVRAM, + title: `${index}: ${name}`, + defaultValue: true, + htmlMonitorRef: undefined, + htmlMonitorSliderRef: undefined, + htmlMonitorLabelRef: undefined, + cssColor: '#176EC7', + onChange: async (value) => { + this.updateWidget(monitorVRAMNElement); + void await this.updateServerGPU(index, { + vram: value + }); + }, + }; + this.monitorGPUSettings[index] = monitorGPUNElement; + this.monitorVRAMSettings[index] = monitorVRAMNElement; + app.ui.settings.addSetting(this.monitorGPUSettings[index]); + app.ui.settings.addSetting(this.monitorVRAMSettings[index]); + }); + }); } }); Object.defineProperty(this, "updateServer", { @@ -264,6 +288,22 @@ class CrystoolsMonitor { throw new Error(resp.statusText); } }); + Object.defineProperty(this, "updateServerGPU", { + enumerable: true, + configurable: true, + writable: true, + value: async (index, data) => { + const resp = await api.fetchApi(`/crystools/monitor/GPU/${index}`, { + method: 'PATCH', + body: JSON.stringify(data), + cache: 'no-store', + }); + if (resp.status === 200) { + return await resp.text(); + } + throw new Error(resp.statusText); + } + }); Object.defineProperty(this, "getHDDsFromServer", { enumerable: true, configurable: true, @@ -272,6 +312,14 @@ class CrystoolsMonitor { return this.getDataFromServer('HDD'); } }); + Object.defineProperty(this, "getGPUsFromServer", { + enumerable: true, + configurable: true, + writable: true, + value: async () => { + return this.getDataFromServer('GPU'); + } + }); Object.defineProperty(this, "getDataFromServer", { enumerable: true, configurable: true, @@ -294,9 +342,13 @@ class CrystoolsMonitor { value: () => { this.updateWidget(this.monitorCPUElement); this.updateWidget(this.monitorRAMElement); - this.updateWidget(this.monitorGPUElement); - this.updateWidget(this.monitorVRAMElement); this.updateWidget(this.monitorHDDElement); + this.monitorGPUSettings.forEach((monitorSettings) => { + monitorSettings && this.updateWidget(monitorSettings); + }); + this.monitorVRAMSettings.forEach((monitorSettings) => { + monitorSettings && this.updateWidget(monitorSettings); + }); } }); Object.defineProperty(this, "updateWidget", { @@ -322,13 +374,28 @@ class CrystoolsMonitor { console.warn('UpdateAllMonitors: no GPU data'); return; } - const gpu = data.gpus[0] ? data.gpus[0] : { - gpu_utilization: 0, vram_used_percent: 0, - }; - const gpu_utilization = gpu.gpu_utilization; - const vram_used_percent = gpu.vram_used_percent; - this.updateMonitor(this.monitorGPUElement, gpu_utilization); - this.updateMonitor(this.monitorVRAMElement, vram_used_percent); + this.monitorGPUSettings.forEach((monitorSettings, index) => { + if (data.gpus[index]) { + const gpu = data.gpus[index]; + if (gpu === undefined) { + return; + } + this.updateMonitor(monitorSettings, gpu.gpu_utilization); + } + else { + } + }); + this.monitorVRAMSettings.forEach((monitorSettings, index) => { + if (data.gpus[index]) { + const gpu = data.gpus[index]; + if (gpu === undefined) { + return; + } + this.updateMonitor(monitorSettings, gpu.vram_used_percent); + } + else { + } + }); } }); Object.defineProperty(this, "updateMonitor", { @@ -341,9 +408,6 @@ class CrystoolsMonitor { } monitorSettings.htmlMonitorLabelRef.innerHTML = `${Math.floor(percent)}%`; monitorSettings.htmlMonitorSliderRef.style.width = monitorSettings.htmlMonitorLabelRef.innerHTML; - if (monitorSettings.tooltip) { - monitorSettings.htmlMonitorLabelRef.title = monitorSettings.tooltip; - } } }); Object.defineProperty(this, "updateAllAnimationDuration", { @@ -353,9 +417,13 @@ class CrystoolsMonitor { value: (value) => { this.updatedAnimationDuration(this.monitorCPUElement, value); this.updatedAnimationDuration(this.monitorRAMElement, value); - this.updatedAnimationDuration(this.monitorGPUElement, value); - this.updatedAnimationDuration(this.monitorVRAMElement, value); this.updatedAnimationDuration(this.monitorHDDElement, value); + this.monitorGPUSettings.forEach((monitorSettings) => { + monitorSettings && this.updatedAnimationDuration(monitorSettings, value); + }); + this.monitorVRAMSettings.forEach((monitorSettings) => { + monitorSettings && this.updatedAnimationDuration(monitorSettings, value); + }); } }); Object.defineProperty(this, "updatedAnimationDuration", { @@ -375,6 +443,9 @@ class CrystoolsMonitor { configurable: true, writable: true, value: (monitorSettings) => { + if (!monitorSettings) { + return document.createElement('div'); + } const htmlMain = document.createElement('div'); htmlMain.setAttribute('id', monitorSettings.id); htmlMain.style.margin = '2px 10px'; @@ -384,6 +455,9 @@ class CrystoolsMonitor { htmlMain.style.alignItems = 'center'; htmlMain.style.flexDirection = 'row'; monitorSettings.htmlMonitorRef = htmlMain; + if (monitorSettings.title) { + htmlMain.title = monitorSettings.title; + } const htmlMonitorText = document.createElement('div'); htmlMonitorText.style.width = '35px'; htmlMonitorText.style.fontSize = '10px'; @@ -448,8 +522,12 @@ class CrystoolsMonitor { ctoolsRoot.append(htmlContainer); htmlContainer.append(this.createMonitor(this.monitorCPUElement)); htmlContainer.append(this.createMonitor(this.monitorRAMElement)); - htmlContainer.append(this.createMonitor(this.monitorGPUElement)); - htmlContainer.append(this.createMonitor(this.monitorVRAMElement)); + this.monitorGPUSettings.forEach((monitorSettings) => { + monitorSettings && htmlContainer.append(this.createMonitor(monitorSettings)); + }); + this.monitorVRAMSettings.forEach((monitorSettings) => { + monitorSettings && htmlContainer.append(this.createMonitor(monitorSettings)); + }); htmlContainer.append(this.createMonitor(this.monitorHDDElement)); const currentRate = parseFloat(app.ui.settings.getSettingValue(this.idInputRate, this.defaultRate)); this.updateAllAnimationDuration(currentRate); diff --git a/web/monitor.ts b/web/monitor.ts index 34c4e71..e8681f7 100644 --- a/web/monitor.ts +++ b/web/monitor.ts @@ -12,6 +12,8 @@ class CrystoolsMonitor { defaultRate = .5; idWhichHDD = 'Crystools.whichHDD'; defaultWhichHDD = '/'; + monitorGPUSettings: TMonitorSettings[] = []; + monitorVRAMSettings: TMonitorSettings[] = []; // CPU Variables monitorCPUElement: TMonitorSettings = { @@ -71,44 +73,6 @@ class CrystoolsMonitor { }, }; - // GPU Variables - monitorGPUElement: TMonitorSettings = { - id: 'Crystools.switchGPU', - name: this.menuPrefix + ' [monitor] GPU Usage', - type: 'boolean', - label: 'GPU', - defaultValue: true, - htmlMonitorRef: undefined, - htmlMonitorSliderRef: undefined, - htmlMonitorLabelRef: undefined, - cssColor: '#0C86F4', - onChange: async(value: boolean) => { - this.updateWidget(this.monitorGPUElement); - await this.updateServer({ - switchGPU: value, - }); - }, - }; - - // VRAM Variables - monitorVRAMElement: TMonitorSettings = { - id: 'Crystools.switchVRAM', - name: this.menuPrefix + ' [monitor] VRAM Used', - type: 'boolean', - label: 'VRAM', - defaultValue: true, - htmlMonitorRef: undefined, - htmlMonitorSliderRef: undefined, - htmlMonitorLabelRef: undefined, - cssColor: '#176EC7', - onChange: async(value: boolean) => { - this.updateWidget(this.monitorVRAMElement); - await this.updateServer({ - switchVRAM: value, - }); - }, - }; - constructor() { this.createSettings(); } @@ -116,8 +80,6 @@ class CrystoolsMonitor { createSettings = (): void => { app.ui.settings.addSetting(this.monitorCPUElement); app.ui.settings.addSetting(this.monitorRAMElement); - app.ui.settings.addSetting(this.monitorGPUElement); - app.ui.settings.addSetting(this.monitorVRAMElement); app.ui.settings.addSetting(this.monitorHDDElement); app.ui.settings.addSetting({ @@ -199,27 +161,76 @@ class CrystoolsMonitor { }); }); + void this.getGPUsFromServer().then((gpus: TGpuName[]): void => { + let moreThanOneGPU = false; + if (gpus.length > 1) { + moreThanOneGPU = true; + } - // void this.getGPUsFromServer().then((gpus: TGpuName[]): void => { - // console.log(gpus); - // gpus?.forEach(({ - // name, index - // }) => { - // const id = this.idSwitchGPU + index; - // app.ui.settings.addSetting({ - // id, - // name: this.menuPrefix + `[menu] Display GPU monitor\r\n[${index}] ${name}`, - // type: 'boolean', - // defaultValue: this.defaultSwitchGPU, - // onChange: async(value: boolean)=> { - // // this.updateWidget(value, this.htmlMonitorGPURef); - // void await this.updateServerGPU(index,{ - // utilization: value - // }); - // }, - // }); - // }); - // }); + gpus?.forEach(({ + name, index + }) => { + + if(name === undefined || index === undefined) { + console.warn('getGPUsFromServer: name or index undefined', name, index); + return; + } + + let label = 'GPU'; + let labelVRAM = 'VRAM'; + if (moreThanOneGPU) { + label = 'GPU '+index; + labelVRAM = 'VRAM'+index; + } + + // GPU Utilization Variables + const monitorGPUNElement: TMonitorSettings = { + id: 'Crystools.switchGPU' + index, + name: this.menuPrefix + `[menu] Display GPU monitor\r\n[${index}] ${name}`, + type: 'boolean', + label, + title: `${index}: ${name}`, + defaultValue: true, + htmlMonitorRef: undefined, + htmlMonitorSliderRef: undefined, + htmlMonitorLabelRef: undefined, + cssColor: '#0C86F4', + onChange: async(value: boolean) => { + this.updateWidget(monitorGPUNElement); + void await this.updateServerGPU(index,{ + utilization: value + }); + }, + }; + + // GPU VRAM Variables + const monitorVRAMNElement: TMonitorSettings = { + id: 'Crystools.switchVRAM' + index, + name: this.menuPrefix + `[menu] Display GPU VRAM monitor\r\n[${index}] ${name}`, + type: 'boolean', + label: labelVRAM, + title: `${index}: ${name}`, + defaultValue: true, + htmlMonitorRef: undefined, + htmlMonitorSliderRef: undefined, + htmlMonitorLabelRef: undefined, + cssColor: '#176EC7', + onChange: async(value: boolean) => { + this.updateWidget(monitorVRAMNElement); + void await this.updateServerGPU(index,{ + vram: value + }); + }, + }; + + this.monitorGPUSettings[index] = monitorGPUNElement; + this.monitorVRAMSettings[index] = monitorVRAMNElement; + // @ts-ignore + app.ui.settings.addSetting(this.monitorGPUSettings[index]); + // @ts-ignore + app.ui.settings.addSetting(this.monitorVRAMSettings[index]); + }); + }); }; @@ -235,26 +246,25 @@ class CrystoolsMonitor { throw new Error(resp.statusText); }; - // updateServerGPU = async(index: number, data: TGpuSettings): Promise => { - // console.log('updateServerGPU', index, data); - // const resp = await api.fetchApi(`/crystools/monitor/GPU/${index}`, { - // method: 'PATCH', - // body: JSON.stringify(data), - // cache: 'no-store', - // }); - // if (resp.status === 200) { - // return await resp.text(); - // } - // throw new Error(resp.statusText); - // }; + updateServerGPU = async(index: number, data: TGpuSettings): Promise => { + const resp = await api.fetchApi(`/crystools/monitor/GPU/${index}`, { + method: 'PATCH', + body: JSON.stringify(data), + cache: 'no-store', + }); + if (resp.status === 200) { + return await resp.text(); + } + throw new Error(resp.statusText); + }; getHDDsFromServer = async(): Promise => { return this.getDataFromServer('HDD'); }; - // getGPUsFromServer = async(): Promise => { - // return this.getDataFromServer('GPU'); - // }; + getGPUsFromServer = async(): Promise => { + return this.getDataFromServer('GPU'); + }; getDataFromServer = async(what: string): Promise => { const resp = await api.fetchApi(`/crystools/monitor/${what}`, { @@ -270,9 +280,14 @@ class CrystoolsMonitor { updateAllWidget = (): void => { this.updateWidget(this.monitorCPUElement); this.updateWidget(this.monitorRAMElement); - this.updateWidget(this.monitorGPUElement); - this.updateWidget(this.monitorVRAMElement); this.updateWidget(this.monitorHDDElement); + + this.monitorGPUSettings.forEach((monitorSettings) => { + monitorSettings && this.updateWidget(monitorSettings); + }); + this.monitorVRAMSettings.forEach((monitorSettings) => { + monitorSettings && this.updateWidget(monitorSettings); + }); }; updateWidget = (monitorSettings: TMonitorSettings): void => { @@ -293,15 +308,34 @@ class CrystoolsMonitor { return; } - const gpu = data.gpus[0] ? data.gpus[0] : { - gpu_utilization: 0, vram_used_percent: 0, - }; - const gpu_utilization = gpu.gpu_utilization; - const vram_used_percent = gpu.vram_used_percent; + this.monitorGPUSettings.forEach((monitorSettings, index) => { + if (data.gpus[index]) { + const gpu = data.gpus[index]; + if (gpu === undefined) { + // console.error('UpdateAllMonitors: no GPU data for index', index); + return; + } - this.updateMonitor(this.monitorGPUElement, gpu_utilization); - this.updateMonitor(this.monitorVRAMElement, vram_used_percent); + this.updateMonitor(monitorSettings, gpu.gpu_utilization); + } else { + // console.error('UpdateAllMonitors: no GPU data for index', index); + } + }); + + this.monitorVRAMSettings.forEach((monitorSettings, index) => { + if (data.gpus[index]) { + const gpu = data.gpus[index]; + if (gpu === undefined) { + // console.error('UpdateAllMonitors: no GPU VRAM data for index', index); + return; + } + + this.updateMonitor(monitorSettings, gpu.vram_used_percent); + } else { + // console.error('UpdateAllMonitors: no GPU VRAM data for index', index); + } + }); }; updateMonitor = (monitorSettings: TMonitorSettings, percent: number): void => { @@ -311,17 +345,18 @@ class CrystoolsMonitor { monitorSettings.htmlMonitorLabelRef.innerHTML = `${Math.floor(percent)}%`; monitorSettings.htmlMonitorSliderRef.style.width = monitorSettings.htmlMonitorLabelRef.innerHTML; - if (monitorSettings.tooltip) { - monitorSettings.htmlMonitorLabelRef.title = monitorSettings.tooltip; - } }; updateAllAnimationDuration = (value: number): void => { this.updatedAnimationDuration(this.monitorCPUElement, value); this.updatedAnimationDuration(this.monitorRAMElement, value); - this.updatedAnimationDuration(this.monitorGPUElement, value); - this.updatedAnimationDuration(this.monitorVRAMElement, value); this.updatedAnimationDuration(this.monitorHDDElement, value); + this.monitorGPUSettings.forEach((monitorSettings) => { + monitorSettings && this.updatedAnimationDuration(monitorSettings, value); + }); + this.monitorVRAMSettings.forEach((monitorSettings) => { + monitorSettings && this.updatedAnimationDuration(monitorSettings, value); + }); }; updatedAnimationDuration = (monitorSettings: TMonitorSettings, value: number): void => { @@ -356,8 +391,21 @@ class CrystoolsMonitor { htmlContainer.append(this.createMonitor(this.monitorCPUElement)); htmlContainer.append(this.createMonitor(this.monitorRAMElement)); - htmlContainer.append(this.createMonitor(this.monitorGPUElement)); - htmlContainer.append(this.createMonitor(this.monitorVRAMElement)); + + // gpu0 > gpu1 > vram0 > vram1 + this.monitorGPUSettings.forEach((monitorSettings) => { + monitorSettings && htmlContainer.append(this.createMonitor(monitorSettings)); + }); + this.monitorVRAMSettings.forEach((monitorSettings) => { + monitorSettings && htmlContainer.append(this.createMonitor(monitorSettings)); + }); + + // gpu0 > vram0 > gpu1 > vram1 + // this.monitorGPUSettings.forEach((_monitorSettings, index) => { + // this.monitorGPUSettings[index] && htmlContainer.append(this.createMonitor(this.monitorGPUSettings[index])); + // this.monitorVRAMSettings[index] && htmlContainer.append(this.createMonitor(this.monitorVRAMSettings[index])); + // }); + htmlContainer.append(this.createMonitor(this.monitorHDDElement)); const currentRate = parseFloat(app.ui.settings.getSettingValue(this.idInputRate, this.defaultRate)); @@ -366,7 +414,11 @@ class CrystoolsMonitor { this.registerListeners(); } - createMonitor = (monitorSettings: TMonitorSettings): HTMLDivElement => { + createMonitor = (monitorSettings?: TMonitorSettings): HTMLDivElement => { + if (!monitorSettings) { + // just for typescript + return document.createElement('div'); + } const htmlMain = document.createElement('div'); htmlMain.setAttribute('id', monitorSettings.id); htmlMain.style.margin = '2px 10px'; @@ -377,6 +429,10 @@ class CrystoolsMonitor { htmlMain.style.flexDirection = 'row'; monitorSettings.htmlMonitorRef = htmlMain; + if (monitorSettings.title) { + htmlMain.title = monitorSettings.title; + } + const htmlMonitorText = document.createElement('div'); htmlMonitorText.style.width = '35px'; htmlMonitorText.style.fontSize = '10px'; @@ -395,7 +451,6 @@ class CrystoolsMonitor { htmlMonitorSlider.style.height = '100%'; htmlMonitorSlider.style.width = '0'; htmlMonitorSlider.style.backgroundColor = monitorSettings.cssColor; - // htmlMonitorSlider.style.transition = 'width 0.5s'; monitorSettings.htmlMonitorSliderRef = htmlMonitorSlider; htmlMonitorContent.append(htmlMonitorSlider); diff --git a/web/monitor.types.d.ts b/web/monitor.types.d.ts index 99e83ce..2160da5 100644 --- a/web/monitor.types.d.ts +++ b/web/monitor.types.d.ts @@ -41,7 +41,8 @@ type TMonitorSettings = { id: string, name: string, label: string, // on monitor - tooltip?: string, + title?: string, // on monitor + tooltip?: string, // on settings type: 'boolean' | 'number' | 'string', defaultValue: boolean, onChange: (value: boolean) => Promise, diff --git a/web/progressBar.js b/web/progressBar.js index ef0df06..7cdcd9a 100644 --- a/web/progressBar.js +++ b/web/progressBar.js @@ -126,7 +126,6 @@ class CrystoolsProgressBar { else if (this.currentStatus === EStatus.execution_error) { this.htmlProgressLabelRef.innerHTML = 'ERROR'; this.htmlProgressSliderRef.style.backgroundColor = 'var(--error-text)'; - console.log('execution_error'); } else if (this.currentStatus === EStatus.executing) { this.htmlProgressLabelRef.innerHTML = `${this.currentProgress}%`; diff --git a/web/progressBar.ts b/web/progressBar.ts index f1f3e9c..4fe5e1e 100644 --- a/web/progressBar.ts +++ b/web/progressBar.ts @@ -68,7 +68,6 @@ class CrystoolsProgressBar { // an error occurred this.htmlProgressLabelRef.innerHTML = 'ERROR'; this.htmlProgressSliderRef.style.backgroundColor = 'var(--error-text)'; - console.log('execution_error'); } else if (this.currentStatus === EStatus.executing) { // on going