Files

187 lines
6.9 KiB
Python

# Dreamfast LTX2 Multi-GPU
# Copyright (C) 2025 Dreamfast
# Multi-GPU device selection for LTXV2 video generation
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Device utilities based on ComfyUI-MultiGPU by pollockjj (GPL-3.0)
import logging
import sys
logger = logging.getLogger("LTXV2MultiGPU")
# ============================================================================
# Detect if ComfyUI-MultiGPU is installed and use its infrastructure
# ============================================================================
_USING_MULTIGPU = False
# Check for ComfyUI-MultiGPU module
for module_name in list(sys.modules.keys()):
if 'comfyui-multigpu' in module_name.lower() or module_name.startswith('custom_nodes.ComfyUI-MultiGPU'):
_USING_MULTIGPU = True
break
# Also try direct import
if not _USING_MULTIGPU:
try:
# Try importing from custom_nodes path patterns
import importlib.util
import os
# Check common custom_nodes locations
possible_paths = []
for path in sys.path:
if 'custom_nodes' in path:
multigpu_path = os.path.join(os.path.dirname(path), 'ComfyUI-MultiGPU', '__init__.py')
if os.path.exists(multigpu_path):
_USING_MULTIGPU = True
break
# Also check sibling
multigpu_path = os.path.join(path, '..', 'ComfyUI-MultiGPU', '__init__.py')
if os.path.exists(os.path.normpath(multigpu_path)):
_USING_MULTIGPU = True
break
except Exception:
pass
if _USING_MULTIGPU:
# ========================================================================
# USE COMFYUI-MULTIGPU INFRASTRUCTURE
# ========================================================================
logger.info("[LTXV2 MultiGPU] ComfyUI-MultiGPU detected, using its device management")
try:
# Import from ComfyUI-MultiGPU
from custom_nodes import ComfyUI_MultiGPU as multigpu
# Use their wrappers and device functions
override_class = multigpu.override_class
override_class_clip = multigpu.override_class_clip
get_device_list = multigpu.get_device_list
logger.info("[LTXV2 MultiGPU] Successfully imported ComfyUI-MultiGPU functions")
except ImportError:
# Fallback: try alternate import path
try:
# Some installations use different module names
for mod_name, mod in sys.modules.items():
if 'multigpu' in mod_name.lower() and hasattr(mod, 'override_class'):
override_class = mod.override_class
override_class_clip = mod.override_class_clip
get_device_list = mod.get_device_list
logger.info(f"[LTXV2 MultiGPU] Found ComfyUI-MultiGPU via {mod_name}")
break
else:
raise ImportError("Could not find ComfyUI-MultiGPU exports")
except Exception as e:
logger.warning(f"[LTXV2 MultiGPU] Failed to import from ComfyUI-MultiGPU: {e}")
logger.warning("[LTXV2 MultiGPU] Falling back to standalone mode")
_USING_MULTIGPU = False
if not _USING_MULTIGPU:
# ========================================================================
# STANDALONE MODE - Apply our own patches
# ========================================================================
logger.info("[LTXV2 MultiGPU] Running in standalone mode")
import torch
import comfy.model_management as mm
from .device_utils import get_device_list
from .wrappers import (
override_class,
override_class_clip,
get_current_device,
set_current_device,
get_current_text_encoder_device,
set_current_text_encoder_device,
)
# Initialize device state from ComfyUI defaults
_initial_device = mm.get_torch_device()
_initial_text_encoder_device = mm.text_encoder_device()
set_current_device(_initial_device)
set_current_text_encoder_device(_initial_text_encoder_device)
# Store original functions
_original_get_torch_device = mm.get_torch_device
_original_text_encoder_device = mm.text_encoder_device
def get_torch_device_patched():
"""Return the user-selected device instead of ComfyUI default."""
current = get_current_device()
if current is None:
return _original_get_torch_device()
devs = get_device_list()
current_str = str(current)
if mm.cpu_state == mm.CPUState.CPU or "cpu" in current_str.lower():
return torch.device("cpu")
if current_str in devs:
return torch.device(current_str)
return _original_get_torch_device()
def text_encoder_device_patched():
"""Return the user-selected text encoder device."""
current = get_current_text_encoder_device()
if current is None:
return _original_text_encoder_device()
devs = get_device_list()
current_str = str(current)
if current_str in devs:
return torch.device(current_str)
return _original_text_encoder_device()
# Apply patches
mm.get_torch_device = get_torch_device_patched
mm.text_encoder_device = text_encoder_device_patched
logger.info("[LTXV2 MultiGPU] Patched comfy.model_management for device selection")
# ============================================================================
# Import nodes (always needed)
# ============================================================================
from .nodes import (
LTXV2AudioVAELoader,
LTXV2AVTextEncoderLoader,
LatentUpscaleModelLoader,
LTXV2CheckpointLoader,
)
# ============================================================================
# Register nodes
# ============================================================================
NODE_CLASS_MAPPINGS = {
"LTXV2CheckpointLoaderMultiGPU": override_class(LTXV2CheckpointLoader),
"LTXV2AudioVAELoaderMultiGPU": override_class(LTXV2AudioVAELoader),
"LTXV2AVTextEncoderLoaderMultiGPU": override_class_clip(LTXV2AVTextEncoderLoader),
"LatentUpscaleModelLoaderMultiGPU": override_class(LatentUpscaleModelLoader),
}
NODE_DISPLAY_NAME_MAPPINGS = {
"LTXV2CheckpointLoaderMultiGPU": "LTXV2 Checkpoint Loader (MultiGPU)",
"LTXV2AudioVAELoaderMultiGPU": "LTXV2 Audio VAE Loader (MultiGPU)",
"LTXV2AVTextEncoderLoaderMultiGPU": "LTXV2 Text Encoder Loader (MultiGPU)",
"LatentUpscaleModelLoaderMultiGPU": "Latent Upscale Model Loader (MultiGPU)",
}
logger.info(f"[LTXV2 MultiGPU] Registered {len(NODE_CLASS_MAPPINGS)} nodes")
if not _USING_MULTIGPU:
logger.info(f"[LTXV2 MultiGPU] Available devices: {get_device_list()}")
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS"]