From 6aa5b45b80533eea82b2d76254996f1ad3c3992a Mon Sep 17 00:00:00 2001 From: Vladimir Mandic Date: Mon, 10 Aug 2026 13:43:45 +0200 Subject: [PATCH] remove directml Signed-off-by: Vladimir Mandic --- CHANGELOG.md | 1 + TODO.md | 1 - cli/sdnq-attention-benchmark.py | 4 +- extensions-builtin/sdnq | 2 +- installer.py | 85 ++++--------- modules/cmd_args.py | 1 - modules/devices.py | 26 +--- modules/dml/Generator.py | 6 - modules/dml/__init__.py | 116 ------------------ modules/dml/amp/__init__.py | 1 - modules/dml/amp/autocast_mode.py | 66 ---------- modules/dml/backend.py | 80 ------------ modules/dml/device.py | 16 --- modules/dml/device_properties.py | 20 --- modules/dml/hijack/__init__.py | 4 - modules/dml/hijack/realesrgan_model.py | 67 ---------- modules/dml/hijack/tomesd.py | 26 ---- modules/dml/hijack/torch.py | 35 ------ modules/dml/hijack/transformers.py | 43 ------- modules/dml/hijack/utils.py | 19 --- modules/dml/memory.py | 31 ----- modules/dml/memory_amd/__init__.py | 10 -- modules/dml/memory_amd/driver/atiadlxx.py | 47 ------- .../dml/memory_amd/driver/atiadlxx_apis.py | 50 -------- .../dml/memory_amd/driver/atiadlxx_defines.py | 1 - .../memory_amd/driver/atiadlxx_structures.py | 90 -------------- modules/dml/pdh/__init__.py | 90 -------------- modules/dml/pdh/apis.py | 37 ------ modules/dml/pdh/defines.py | 23 ---- modules/dml/pdh/errors.py | 3 - modules/dml/pdh/msvcrt.py | 13 -- modules/dml/pdh/structures.py | 45 ------- modules/dml/utils.py | 9 -- modules/onnx_impl/execution_providers.py | 2 - modules/onnx_impl/ui.py | 4 +- modules/sd_hijack_dynamic_atten.py | 4 - modules/sd_hijack_freeu.py | 8 +- modules/sd_hijack_triton.py | 2 +- modules/sd_offload.py | 4 - modules/shared.py | 10 -- modules/shared_defaults.py | 2 +- modules/ui_definitions.py | 13 -- modules/ui_settings.py | 6 - pyproject.toml | 1 - wiki | 2 +- 45 files changed, 35 insertions(+), 1091 deletions(-) delete mode 100644 modules/dml/Generator.py delete mode 100644 modules/dml/__init__.py delete mode 100644 modules/dml/amp/__init__.py delete mode 100644 modules/dml/amp/autocast_mode.py delete mode 100644 modules/dml/backend.py delete mode 100644 modules/dml/device.py delete mode 100644 modules/dml/device_properties.py delete mode 100644 modules/dml/hijack/__init__.py delete mode 100644 modules/dml/hijack/realesrgan_model.py delete mode 100644 modules/dml/hijack/tomesd.py delete mode 100644 modules/dml/hijack/torch.py delete mode 100644 modules/dml/hijack/transformers.py delete mode 100644 modules/dml/hijack/utils.py delete mode 100644 modules/dml/memory.py delete mode 100644 modules/dml/memory_amd/__init__.py delete mode 100644 modules/dml/memory_amd/driver/atiadlxx.py delete mode 100644 modules/dml/memory_amd/driver/atiadlxx_apis.py delete mode 100644 modules/dml/memory_amd/driver/atiadlxx_defines.py delete mode 100644 modules/dml/memory_amd/driver/atiadlxx_structures.py delete mode 100644 modules/dml/pdh/__init__.py delete mode 100644 modules/dml/pdh/apis.py delete mode 100644 modules/dml/pdh/defines.py delete mode 100644 modules/dml/pdh/errors.py delete mode 100644 modules/dml/pdh/msvcrt.py delete mode 100644 modules/dml/pdh/structures.py delete mode 100644 modules/dml/utils.py diff --git a/CHANGELOG.md b/CHANGELOG.md index dd1608ec5..8d63d3995 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ - **Server** - update handlers for all authenticated workflows - nunchaku-lite support for `torch==2.13` + - remove DirectML support: latest release was over 2 years ago and is not compatible with modern frameworks - **Fixes** - init hf env variables before gradio load - lora skip init and rebuild offload state diff --git a/TODO.md b/TODO.md index 78b2c9ffb..ae6d4a4ab 100644 --- a/TODO.md +++ b/TODO.md @@ -28,7 +28,6 @@ - JSON image metadata - Expand custom VAE support - Refactor: remove obsolete code: - - Remove `directml` - Remove `olive-ai` - Integrate natural language image search - [ImageDB](https://github.com/vladmandic/imagedb) diff --git a/cli/sdnq-attention-benchmark.py b/cli/sdnq-attention-benchmark.py index c13d7ee2a..7dc86a16a 100755 --- a/cli/sdnq-attention-benchmark.py +++ b/cli/sdnq-attention-benchmark.py @@ -743,13 +743,13 @@ def fp8_failure_is_capability(detail): def print_environment(fp8_result, prep_status, prep_detail, weight_dequant_result=None): device = torch.device(torch_device) capability = torch_device_module.get_device_capability(device) - # backend runtime versions (cuda/cudnn/driver, hip, ipex, openvino, directml) so a shared + # backend runtime versions (cuda/cudnn/driver, hip, ipex, openvino) so a shared # report identifies the stack without inferring it from the torch version string try: gpu_info = devices.get_gpu_info() or {} except Exception: gpu_info = {} - runtime_versions = {key: gpu_info[key] for key in ("cuda", "hip", "cudnn", "driver", "ipex", "openvino", "directml") if gpu_info.get(key)} + runtime_versions = {key: gpu_info[key] for key in ("cuda", "hip", "cudnn", "driver", "ipex", "openvino") if gpu_info.get(key)} runtime_line = f"python: {sys.version.split()[0]} ({sys.platform}) backend: {getattr(devices, 'backend', 'unknown')}" if runtime_versions: runtime_line += " " + " ".join(f"{key}: {value}" for key, value in runtime_versions.items()) diff --git a/extensions-builtin/sdnq b/extensions-builtin/sdnq index 01bc5b460..d840854e0 160000 --- a/extensions-builtin/sdnq +++ b/extensions-builtin/sdnq @@ -1 +1 @@ -Subproject commit 01bc5b460edf62227bb22bb7363d085e11b2cc84 +Subproject commit d840854e029292e87e2fe35da89a46ec07672183 diff --git a/installer.py b/installer.py index f05118025..11df91547 100644 --- a/installer.py +++ b/installer.py @@ -54,7 +54,6 @@ args = Dot({ 'skip_requirements': False, 'skip_git': False, 'skip_torch': False, - 'use_directml': False, 'use_ipex': False, 'use_cuda': False, 'use_rocm': False, @@ -586,7 +585,7 @@ def check_diffusers(): if args.skip_all: return target_commit = "6f2010e8bbe61fd2a81a659b858e298edcba8fab" # diffusers commit hash == 0.40.0.dev0 == 08-04-2026 - # if args.use_rocm or args.use_zluda or args.use_directml: + # if args.use_rocm or args.use_zluda: # sha = '043ab2520f6a19fce78e6e060a68dbc947edb9f9' # lock diffusers versions for now pkg = package_spec('diffusers') parts = pkg.version.split('.') if pkg is not None else [] @@ -616,36 +615,21 @@ def check_transformers(): # target_commit = '753d61104116eefc8ffc977327b441ee0c8d599f' # transformers commit hash == 4.57.6 # target_commit = "cf8572d34e39818e42dbf220701fbd3eb5b5a82a" # transformers commit hash == 5.14.0.dev0 == 08-04-2026 target_commit = "b70d02fc724d04c916832ca4ead03ff05e8fb1ee" # transformers commit hash == 5.13.0.dev0 == 07-03-2026 - if args.use_directml: - target_transformers = '4.52.4' - target_tokenizers = '0.21.4' - else: - # target_transformers = '4.57.6' - target_transformers = None - target_tokenizers = '0.22.2' - if target_transformers is not None: - # Pinned release version (e.g. DirectML) - if args.reinstall or (pkg_transformers is None) or ((pkg_transformers.version != target_transformers) or (pkg_tokenizers is None) or ((pkg_tokenizers.version != target_tokenizers) and (not args.experimental))): - if pkg_transformers is None: - log.info(f'Install: package="transformers" version={target_transformers}') - else: - log.info(f'Update: package="transformers" current={pkg_transformers.version} target={target_transformers}') - pip('uninstall --yes transformers', ignore=True, quiet=True) - pip(f'install tokenizers=={target_tokenizers}', ignore=False, quiet=True) - pip(f'install transformers=={target_transformers}', ignore=False, quiet=True) - else: - # Git commit-pinned version - current = package_commit(pkg_transformers) - if args.reinstall or (pkg_transformers is None) or (pkg_transformers.version.startswith('4')) or (current != target_commit): - if pkg_transformers is None: - log.info(f'Install: package="transformers" commit={target_commit}') - else: - log.info(f'Update: package="transformers" current={pkg_transformers.version} commit={current} target={target_commit}') - pip('uninstall --yes transformers', ignore=True, quiet=True) - pip(f'install tokenizers=={target_tokenizers}', ignore=False, quiet=True) - pip(f'install git+https://github.com/huggingface/transformers@{target_commit}', ignore=False, quiet=True) - global transformers_commit # pylint: disable=global-statement - transformers_commit = target_commit + target_tokenizers = '0.22.2' + # Git commit-pinned version + current = package_commit(pkg_transformers) + if args.reinstall or (pkg_transformers is None) or (pkg_transformers.version.startswith('4')) or (current != target_commit): + if pkg_transformers is None: + log.info(f'Install: package="transformers" commit={target_commit}') + else: + log.info(f'Update: package="transformers" current={pkg_transformers.version} commit={current} target={target_commit}') + pip('uninstall --yes transformers', ignore=True, quiet=True) + pip(f'install tokenizers=={target_tokenizers}', ignore=False, quiet=True) + pip(f'install git+https://github.com/huggingface/transformers@{target_commit}', ignore=False, quiet=True) + global transformers_commit # pylint: disable=global-statement + transformers_commit = target_commit + if args.reinstall or (pkg_tokenizers is None) or (pkg_tokenizers.version != target_tokenizers): + pip(f'install tokenizers=={target_tokenizers}', ignore=False, quiet=True) ts('transformers', t_start) @@ -924,20 +908,17 @@ def check_torch(): if args.profile: pr = cProfile.Profile() pr.enable() - allow_cuda = not (args.use_rocm or args.use_directml or args.use_ipex or args.use_openvino) - allow_rocm = not (args.use_cuda or args.use_directml or args.use_ipex or args.use_openvino) - allow_ipex = not (args.use_cuda or args.use_rocm or args.use_directml or args.use_openvino) - allow_directml = not (args.use_cuda or args.use_rocm or args.use_ipex or args.use_openvino) - allow_openvino = not (args.use_cuda or args.use_rocm or args.use_ipex or args.use_directml) - log.debug(f'Torch overrides: cuda={args.use_cuda} rocm={args.use_rocm} ipex={args.use_ipex} directml={args.use_directml} openvino={args.use_openvino} zluda={args.use_zluda}') - # log.debug(f'Torch allowed: cuda={allow_cuda} rocm={allow_rocm} ipex={allow_ipex} diml={allow_directml} openvino={allow_openvino}') + allow_cuda = not (args.use_rocm or args.use_ipex or args.use_openvino) + allow_rocm = not (args.use_cuda or args.use_ipex or args.use_openvino) + allow_ipex = not (args.use_cuda or args.use_rocm or args.use_openvino) + allow_openvino = not (args.use_cuda or args.use_rocm or args.use_ipex) + log.debug(f'Torch overrides: cuda={args.use_cuda} rocm={args.use_rocm} ipex={args.use_ipex} openvino={args.use_openvino} zluda={args.use_zluda}') + # log.debug(f'Torch allowed: cuda={allow_cuda} rocm={allow_rocm} ipex={allow_ipex} openvino={allow_openvino}') torch_command = os.environ.get('TORCH_COMMAND', '') if sys.platform != 'win32': if args.use_zluda: log.error('ZLUDA is only supported on Windows') - if args.use_directml: - log.error('DirectML is only supported on Windows') if torch_command != '': is_cuda_available = False @@ -967,15 +948,8 @@ def check_torch(): elif is_ipex_available: torch_command = install_ipex() else: - machine = platform.machine() if sys.platform == 'darwin': torch_command = os.environ.get('TORCH_COMMAND', 'torch torchvision') - elif allow_directml and args.use_directml and ('arm' not in machine and 'aarch' not in machine): - log.info('DirectML: selected') - torch_command = os.environ.get('TORCH_COMMAND', 'torch==2.4.1 torchvision torch-directml==0.2.4.dev240913') - if 'torch' in torch_command and not args.version: - install(torch_command, 'torch torchvision') - install('onnxruntime-directml', 'onnxruntime-directml', ignore=True) else: log.warning('Torch: CPU-only version installed') torch_command = os.environ.get('TORCH_COMMAND', 'torch torchvision') @@ -1067,21 +1041,6 @@ def check_torch(): except Exception as e: log.error(f'Torch: type=cuda/rocm {e}') - if args.use_directml and allow_directml: - try: - import torch_directml # pylint: disable=import-error - dml_ver = package_version("torch-directml") - log.warning(f'Torch backend: DirectML ({dml_ver})') - log.warning('DirectML: end-of-life') - for i in range(0, torch_directml.device_count()): - gpu = { - 'gpu': torch_directml.device_name(i), - } - gpu_info.append(gpu) - log.info(f'Torch detected: {gpu}') - except Exception as e: - log.warning(f"Torch: type=directml {e}") - except Exception as e: log.error(f'Torch cannot load: {e}') if not args.ignore: diff --git a/modules/cmd_args.py b/modules/cmd_args.py index da5fe2a6c..e7370924c 100644 --- a/modules/cmd_args.py +++ b/modules/cmd_args.py @@ -37,7 +37,6 @@ def add_compute_args(p): p.add_argument("--use-rocm", default=env_flag("SD_USEROCM", False), action='store_true', help="Force use AMD ROCm backend, default: %(default)s") p.add_argument('--use-zluda', default=env_flag("SD_USEZLUDA", False), action='store_true', help="Force use ZLUDA, AMD GPUs only, default: %(default)s") p.add_argument("--use-openvino", default=env_flag("SD_USEOPENVINO", False), action='store_true', help="Use Intel OpenVINO backend, default: %(default)s") - p.add_argument('--use-directml', default=env_flag("SD_USEDIRECTML", False), action='store_true', help="Use DirectML if no compatible GPU is detected, default: %(default)s") p.add_argument("--use-xformers", default=env_flag("SD_USEXFORMERS", False), action='store_true', help="Force use xFormers cross-optimization, default: %(default)s") p.add_argument("--use-nightly", default=env_flag("SD_USENIGHTLY", False), action='store_true', help="Force use nightly torch builds, default: %(default)s") p.add_argument("--no-half", default=env_flag("SD_NOHALF", False), action='store_true', help="Do not switch the model to 16-bit float, default: %(default)s") diff --git a/modules/devices.py b/modules/devices.py index 1ab2d79c1..ea7a2c985 100644 --- a/modules/devices.py +++ b/modules/devices.py @@ -79,8 +79,6 @@ def get_backend(shared_cmd_opts): args = shared_cmd_opts if args.use_openvino: name = 'openvino' - elif args.use_directml: - name = 'directml' elif has_xpu(): name = 'ipex' elif has_zluda(): @@ -131,11 +129,6 @@ def get_gpu_info(): 'devices': devices, 'openvino': get_package_version("openvino"), } - elif backend == 'directml': - return { - 'device': f'{torch.cuda.get_device_name(torch.cuda.current_device())} n={torch.cuda.device_count()}', - 'directml': get_package_version("torch-directml"), - } else: return {} except Exception: @@ -176,10 +169,6 @@ def get_cuda_device_string(): if cmd_opts.device_id is not None: return f"xpu:{cmd_opts.device_id}" return "xpu" - elif backend == 'directml' and torch.dml.is_available(): - if cmd_opts.device_id is not None: - return f"privateuseone:{cmd_opts.device_id}" - return torch.dml.get_device_string(torch.dml.default_device().index) else: if cmd_opts.device_id is not None: return f"cuda:{cmd_opts.device_id}" @@ -189,7 +178,7 @@ def get_cuda_device_string(): def get_optimal_device_name(): if backend == 'openvino': return "cpu" - if cuda_ok or backend == 'directml': + if cuda_ok: return get_cuda_device_string() if has_mps() and backend != 'openvino': return "mps" @@ -205,12 +194,9 @@ def torch_gc(force: bool = False, fast: bool = False, reason: str | None = None) mem_dict = memstats.memory_stats() gpu_dict = mem_dict.get('gpu', {}) ram_dict = mem_dict.get('ram', {}) - oom = gpu_dict.get('oom', 0) ram = ram_dict.get('used', 0) - if backend == "directml": - gpu = torch.cuda.memory_allocated() / (1 << 30) - else: - gpu = gpu_dict.get('used', 0) + oom = gpu_dict.get('oom', 0) + gpu = gpu_dict.get('used', 0) used_gpu = round(100 * gpu / gpu_dict.get('total', 1)) if gpu_dict.get('total', 1) > 1 else 0 used_ram = round(100 * ram / ram_dict.get('total', 1)) if ram_dict.get('total', 1) > 1 else 0 return gpu, used_gpu, ram, used_ram, oom @@ -374,7 +360,7 @@ def test_bf16(): if bf16_ok is not None: return bf16_ok if opts.cuda_dtype != 'BF16': # don't override if the user sets it - if sys.platform == "darwin" or backend in {'directml', 'cpu'}: # override + if sys.platform == "darwin" or backend == 'cpu': # override bf16_ok = False return bf16_ok elif backend == 'openvino': @@ -676,8 +662,6 @@ def randn_without_seed(shape): def autocast(disable=False): if disable or dtype == torch.float32: return contextlib.nullcontext() - if backend == 'directml': - return torch.dml.amp.autocast(dtype) if cuda_ok: return torch.autocast("cuda") else: @@ -687,8 +671,6 @@ def autocast(disable=False): def without_autocast(disable=False): if disable: return contextlib.nullcontext() - if backend == 'directml': - return torch.dml.amp.autocast(enabled=False) if torch.is_autocast_enabled() else contextlib.nullcontext() # pylint: disable=unexpected-keyword-arg if cuda_ok: return torch.autocast("cuda", enabled=False) if torch.is_autocast_enabled() else contextlib.nullcontext() else: diff --git a/modules/dml/Generator.py b/modules/dml/Generator.py deleted file mode 100644 index c6c53f084..000000000 --- a/modules/dml/Generator.py +++ /dev/null @@ -1,6 +0,0 @@ -import torch - - -class Generator(torch.Generator): - def __init__(self, device: torch.device | None = None): - super().__init__("cpu") diff --git a/modules/dml/__init__.py b/modules/dml/__init__.py deleted file mode 100644 index 892a02d42..000000000 --- a/modules/dml/__init__.py +++ /dev/null @@ -1,116 +0,0 @@ -import platform -from typing import NamedTuple -from collections.abc import Callable -import torch -from modules.logger import log -from modules.sd_hijack_utils import CondFunc - - -memory_providers = ["None", "atiadlxx (AMD only)"] -default_memory_provider = "None" -if platform.system() == "Windows": - memory_providers.append("Performance Counter") - default_memory_provider = "Performance Counter" -do_nothing = lambda: None # pylint: disable=unnecessary-lambda-assignment -do_nothing_with_self = lambda self: None # pylint: disable=unnecessary-lambda-assignment - - -def _set_memory_provider(): - from modules.shared import opts, cmd_opts - if opts.directml_memory_provider == "Performance Counter": - from .backend import pdh_mem_get_info - from .memory import MemoryProvider - torch.dml.mem_get_info = pdh_mem_get_info - if torch.dml.memory_provider is not None: - del torch.dml.memory_provider - torch.dml.memory_provider = MemoryProvider() - elif opts.directml_memory_provider == "atiadlxx (AMD only)": - device_name = torch.dml.get_device_name(cmd_opts.device_id) - if "AMD" not in device_name and "Radeon" not in device_name: - log.warning(f"Memory stats provider is changed to None because the current device is not AMDGPU. Current Device: {device_name}") - opts.directml_memory_provider = "None" - _set_memory_provider() - return - from .backend import amd_mem_get_info - torch.dml.mem_get_info = amd_mem_get_info - else: - from .backend import mem_get_info - torch.dml.mem_get_info = mem_get_info - torch.cuda.mem_get_info = torch.dml.mem_get_info - - -def directml_init(): - try: - from modules.dml.backend import DirectML # pylint: disable=ungrouped-imports - # Alternative of torch.cuda for DirectML. - torch.dml = DirectML - - torch.cuda.is_available = lambda: False - torch.cuda.device = torch.dml.device - torch.cuda.device_count = torch.dml.device_count - torch.cuda.current_device = torch.dml.current_device - torch.cuda.get_device_name = torch.dml.get_device_name - torch.cuda.get_device_properties = torch.dml.get_device_properties - - torch.cuda.empty_cache = do_nothing - torch.cuda.ipc_collect = do_nothing - torch.cuda.memory_stats = torch.dml.memory_stats - torch.cuda.mem_get_info = torch.dml.mem_get_info - torch.cuda.memory_allocated = torch.dml.memory_allocated - torch.cuda.max_memory_allocated = torch.dml.max_memory_allocated - torch.cuda.reset_peak_memory_stats = torch.dml.reset_peak_memory_stats - torch.cuda.utilization = lambda: 0 - - torch.Tensor.directml = lambda self: self.to(torch.dml.current_device()) - except Exception as e: - log.error(f'DirectML initialization failed: {e}') - return False, e - return True, None - - -def directml_do_hijack(): - import modules.dml.hijack # pylint: disable=unused-import - from modules.devices import device - - CondFunc('torch.Generator', - lambda orig_func, device = None: orig_func("cpu"), - lambda orig_func, device = None: True) - - if not torch.dml.has_float64_support(device): - torch.Tensor.__str__ = do_nothing_with_self - CondFunc('torch.from_numpy', - lambda orig_func, *args, **kwargs: orig_func(args[0].astype('float32')), - lambda *args, **kwargs: args[1].dtype == float) - - _set_memory_provider() - - -class OverrideItem(NamedTuple): - value: str - condition: Callable | None - message: str | None - - -opts_override_table = { - "diffusers_generator_device": OverrideItem("CPU", None, "DirectML does not support torch Generator API"), -} - - -def directml_override_opts(): - from modules import shared - - if shared.cmd_opts.experimental: - return - - count = 0 - for key in opts_override_table: - item = opts_override_table[key] - if getattr(shared.opts, key) != item.value and (item.condition is None or item.condition(shared.opts)): - count += 1 - setattr(shared.opts, key, item.value) - log.warning(f'Overriding: {key}={item.value} {item.message if item.message is not None else ""}') - - if count > 0: - log.info(f'Options override: count={count}. If you want to keep them from overriding, run with --experimental argument.') - - _set_memory_provider() diff --git a/modules/dml/amp/__init__.py b/modules/dml/amp/__init__.py deleted file mode 100644 index e4fe09f55..000000000 --- a/modules/dml/amp/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .autocast_mode import autocast diff --git a/modules/dml/amp/autocast_mode.py b/modules/dml/amp/autocast_mode.py deleted file mode 100644 index 2c344d53b..000000000 --- a/modules/dml/amp/autocast_mode.py +++ /dev/null @@ -1,66 +0,0 @@ -import importlib -from typing import Any -import torch - - -ops = ["torch.Tensor.__matmul__", "torch.addbmm", "torch.addmm", "torch.addmv", "torch.addr", "torch.baddbmm", "torch.bmm", "torch.chain_matmul", "torch.linalg.multi_dot", "torch.nn.functional.conv1d", "torch.nn.functional.conv2d", "torch.nn.functional.conv3d", "torch.nn.functional.conv_transpose1d", "torch.nn.functional.conv_transpose2d", "torch.nn.functional.conv_transpose3d", "torch.nn.GRUCell", "torch.nn.functional.linear", "torch.nn.LSTMCell", "torch.matmul", "torch.mm", "torch.mv", "torch.prelu", "torch.nn.RNNCell", "torch.embedding"] -supported_cast_pairs = { - torch.float16: (torch.float32,), - torch.float32: (torch.float16,), -} - - -def forward(op, args: tuple, kwargs: dict): - if not torch.dml.is_autocast_enabled: - return op(*args, **kwargs) - args = list(map(cast, args)) - for kwarg in kwargs: - kwargs[kwarg] = cast(kwargs[kwarg]) - return op(*args, **kwargs) - - -def cast(tensor: torch.Tensor): - if not torch.is_tensor(tensor): - return tensor - dtype: torch.dtype = tensor.dtype - if dtype not in supported_cast_pairs or (torch.dml.autocast_gpu_dtype != dtype and torch.dml.autocast_gpu_dtype not in supported_cast_pairs[dtype]): - return tensor - return tensor.type(torch.dml.autocast_gpu_dtype) - - -def cond(op: str): - if isinstance(op, str): - func_path = op.split('.') - for i in range(len(func_path)-1, -1, -1): - try: - resolved_obj = importlib.import_module('.'.join(func_path[:i])) - break - except ImportError: - pass - for attr_name in func_path[i:-1]: - resolved_obj = getattr(resolved_obj, attr_name) - op = getattr(resolved_obj, func_path[-1]) - setattr(resolved_obj, func_path[-1], lambda *args, **kwargs: forward(op, args, kwargs)) - - -for o in ops: - cond(o) - - -class autocast: - prev: bool - - fast_dtype: torch.dtype = torch.float16 - prev_fast_dtype: torch.dtype - def __init__(self, dtype: torch.dtype | None = torch.float16): - self.fast_dtype = dtype - - def __enter__(self): - self.prev = torch.dml.is_autocast_enabled - self.prev_fast_dtype = torch.dml.autocast_gpu_dtype - torch.dml.is_autocast_enabled = True - torch.dml.autocast_gpu_dtype = self.fast_dtype - - def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any): - torch.dml.is_autocast_enabled = self.prev - torch.dml.autocast_gpu_dtype = self.prev_fast_dtype diff --git a/modules/dml/backend.py b/modules/dml/backend.py deleted file mode 100644 index 712e17591..000000000 --- a/modules/dml/backend.py +++ /dev/null @@ -1,80 +0,0 @@ -# pylint: disable=no-member,no-self-argument,no-method-argument -from collections.abc import Callable -import torch -import torch_directml # pylint: disable=import-error -import modules.dml.amp as amp -from .utils import rDevice, get_device -from .device import Device -from .Generator import Generator -from .device_properties import DeviceProperties - - -def amd_mem_get_info(device: rDevice | None=None) -> tuple[int, int]: - from .memory_amd import AMDMemoryProvider - return AMDMemoryProvider.mem_get_info(get_device(device).index) - - -def pdh_mem_get_info(device: rDevice | None=None) -> tuple[int, int]: - mem_info = DirectML.memory_provider.get_memory(get_device(device).index) - return (mem_info["total_committed"] - mem_info["dedicated_usage"], mem_info["total_committed"]) - - -def mem_get_info(device: rDevice | None=None) -> tuple[int, int]: # pylint: disable=unused-argument - return (8589934592, 8589934592) - - -class DirectML: - amp = amp - device = Device - Generator = Generator - - context_device: torch.device | None = None - - is_autocast_enabled = False - autocast_gpu_dtype = torch.float16 - - memory_provider = None - - def is_available() -> bool: - return torch_directml.is_available() - - def is_directml_device(device: torch.device) -> bool: - return device.type == "privateuseone" - - def has_float64_support(device: rDevice | None=None) -> bool: - return torch_directml.has_float64_support(get_device(device).index) - - def device_count() -> int: - return torch_directml.device_count() - - def current_device() -> torch.device: - return DirectML.context_device or DirectML.default_device() - - def default_device() -> torch.device: - return torch_directml.device(torch_directml.default_device()) - - def get_device_string(device: rDevice | None=None) -> str: - return f"privateuseone:{get_device(device).index}" - - def get_device_name(device: rDevice | None=None) -> str: - return torch_directml.device_name(get_device(device).index) - - def get_device_properties(device: rDevice | None=None) -> DeviceProperties: - return DeviceProperties(get_device(device)) - - def memory_stats(device: rDevice | None=None): - return { - "num_ooms": 0, - "num_alloc_retries": 0, - } - - mem_get_info: Callable = mem_get_info - - def memory_allocated(device: rDevice | None=None) -> int: - return sum(torch_directml.gpu_memory(get_device(device).index)) * (1 << 20) - - def max_memory_allocated(device: rDevice | None=None): - return DirectML.memory_allocated(device) # DirectML does not empty GPU memory - - def reset_peak_memory_stats(device: rDevice | None=None): - return diff --git a/modules/dml/device.py b/modules/dml/device.py deleted file mode 100644 index cd7006333..000000000 --- a/modules/dml/device.py +++ /dev/null @@ -1,16 +0,0 @@ -import torch -from .utils import rDevice, get_device - - -class Device: - idx: int - - def __enter__(self, device: rDevice | None=None): - torch.dml.context_device = get_device(device) - self.idx = torch.dml.context_device.index - - def __init__(self, device: rDevice | None=None) -> torch.device: # pylint: disable=return-in-init - self.idx = get_device(device).index - - def __exit__(self, t, v, tb): - torch.dml.context_device = None diff --git a/modules/dml/device_properties.py b/modules/dml/device_properties.py deleted file mode 100644 index 1d8328478..000000000 --- a/modules/dml/device_properties.py +++ /dev/null @@ -1,20 +0,0 @@ -import torch - - -class DeviceProperties: - type: str = "directml" - name: str - major: int = 0 - minor: int = 0 - total_memory: int - multi_processor_count: int = 1 - - def __init__(self, device: torch.device): - self.name = torch.dml.get_device_name(device) - self.total_memory = torch.dml.mem_get_info(device)[0] - - def __str__(self): - return f"DeviceProperties(name='{self.name}', total_memory='{self.total_memory}')" - - def __repr__(self): - return f"DeviceProperties(name='{self.name}', total_memory='{self.total_memory}')" diff --git a/modules/dml/hijack/__init__.py b/modules/dml/hijack/__init__.py deleted file mode 100644 index 46aecf4bd..000000000 --- a/modules/dml/hijack/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -import modules.dml.hijack.torch -import modules.dml.hijack.realesrgan_model -import modules.dml.hijack.transformers -import modules.dml.hijack.tomesd diff --git a/modules/dml/hijack/realesrgan_model.py b/modules/dml/hijack/realesrgan_model.py deleted file mode 100644 index afcda99c8..000000000 --- a/modules/dml/hijack/realesrgan_model.py +++ /dev/null @@ -1,67 +0,0 @@ -import math -import torch -from modules.postprocess.realesrgan_model_arch import RealESRGANer -from modules.logger import log - - -# DML Solution: Some of contents of output tensor turn to 0 after Extended Slices. Move it to cpu. -def tile_process(self): - batch, channel, height, width = self.img.shape - output_height = height * self.scale - output_width = width * self.scale - output_shape = (batch, channel, output_height, output_width) - - # start with black image - self.output = self.img.new_zeros(output_shape) - tiles_x = math.ceil(width / self.tile_size) - tiles_y = math.ceil(height / self.tile_size) - - # loop over all tiles - for y in range(tiles_y): - for x in range(tiles_x): - # extract tile from input image - ofs_x = x * self.tile_size - ofs_y = y * self.tile_size - # input tile area on total image - input_start_x = ofs_x - input_end_x = min(ofs_x + self.tile_size, width) - input_start_y = ofs_y - input_end_y = min(ofs_y + self.tile_size, height) - - # input tile area on total image with padding - input_start_x_pad = max(input_start_x - self.tile_pad, 0) - input_end_x_pad = min(input_end_x + self.tile_pad, width) - input_start_y_pad = max(input_start_y - self.tile_pad, 0) - input_end_y_pad = min(input_end_y + self.tile_pad, height) - - # input tile dimensions - input_tile_width = input_end_x - input_start_x - input_tile_height = input_end_y - input_start_y - _tile_idx = y * tiles_x + x + 1 - input_tile = self.img[0:self.img.shape[0], 0:self.img.shape[1], input_start_y_pad:input_end_y_pad, input_start_x_pad:input_end_x_pad] - - # upscale tile - try: - with torch.no_grad(): - output_tile = self.model(input_tile) - except Exception as e: - log.error(f'Upscale error: type=R-ESRGAN {e}') - - # output tile area on total image - output_start_x = input_start_x * self.scale - output_end_x = input_end_x * self.scale - output_start_y = input_start_y * self.scale - output_end_y = input_end_y * self.scale - - # output tile area without padding - output_start_x_tile = (input_start_x - input_start_x_pad) * self.scale - output_end_x_tile = output_start_x_tile + input_tile_width * self.scale - output_start_y_tile = (input_start_y - input_start_y_pad) * self.scale - output_end_y_tile = output_start_y_tile + input_tile_height * self.scale - - self.output = self.output.cpu() - # put tile into output image - self.output[0:self.output.shape[0], 0:self.output.shape[1], output_start_y:output_end_y, output_start_x:output_end_x] = output_tile.cpu()[0:output_tile.shape[0], 0:output_tile.shape[1], output_start_y_tile:output_end_y_tile, output_start_x_tile:output_end_x_tile] - self.output = self.output.to(output_tile.device) - -RealESRGANer.tile_process = tile_process diff --git a/modules/dml/hijack/tomesd.py b/modules/dml/hijack/tomesd.py deleted file mode 100644 index 0acc657ae..000000000 --- a/modules/dml/hijack/tomesd.py +++ /dev/null @@ -1,26 +0,0 @@ -import torch -from modules.dml.hijack.utils import catch_nan - - -def make_tome_block(block_class: type[torch.nn.Module]) -> type[torch.nn.Module]: - class ToMeBlock(block_class): - # Save for unpatching later - _parent = block_class - - def _forward(self, x: torch.Tensor, context: torch.Tensor = None) -> torch.Tensor: - m_a, m_c, m_m, u_a, u_c, u_m = tomesd.patch.compute_merge(x, self._tome_info) - - # This is where the meat of the computation happens - x = u_a(self.attn1(m_a(self.norm1(x)), context=context if self.disable_self_attn else None)) + x - x = catch_nan(lambda: (u_c(self.attn2(m_c(self.norm2(x)), context=context)) + x)) - x = u_m(self.ff(m_m(self.norm3(x)))) + x - - return x - - return ToMeBlock - -try: - import tomesd - tomesd.patch.make_tome_block = make_tome_block -except Exception: - pass diff --git a/modules/dml/hijack/torch.py b/modules/dml/hijack/torch.py deleted file mode 100644 index 1786a1499..000000000 --- a/modules/dml/hijack/torch.py +++ /dev/null @@ -1,35 +0,0 @@ -import torch -from modules.sd_hijack_utils import CondFunc - - -CondFunc('torchsde._brownian.brownian_interval._randn', lambda _, size, dtype, device, seed: torch.randn(size, dtype=dtype, device=torch.device("cpu"), generator=torch.Generator(torch.device("cpu")).manual_seed(int(seed))).to(device), lambda _, size, dtype, device, seed: device.type == 'privateuseone') -# https://github.com/microsoft/DirectML/issues/400 -CondFunc('torch.Tensor.new', lambda orig, self, *args, **kwargs: orig(self.cpu(), *args, **kwargs).to(self.device), lambda orig, self, *args, **kwargs: torch.dml.is_directml_device(self.device)) - - -def cuda(self: torch.Tensor): - return self.to(torch.dml.current_device()) -torch.Tensor.cuda = cuda - - -# https://github.com/lshqqytiger/stable-diffusion-webui-directml/issues/436 -_pow_ = torch.Tensor.pow_ -def pow_(self: torch.Tensor, *args, **kwargs): - if self.dtype == torch.float64: - return _pow_(self.cpu(), *args, **kwargs).to(self.device) - return _pow_(self, *args, **kwargs) -torch.Tensor.pow_ = pow_ - - -_load = torch.load -def load(f, map_location = "cpu", *args, **kwargs): - if type(map_location) in (str, torch.device,): - device = torch.device(map_location) - if device.type == "privateuseone": - data = _load(f, *args, map_location="cpu", **kwargs) - for k in data: - for weight in data[k]: - data[k][weight] = data[k][weight].to(device) - return data - return _load(f, *args, map_location=map_location, **kwargs) -torch.load = load diff --git a/modules/dml/hijack/transformers.py b/modules/dml/hijack/transformers.py deleted file mode 100644 index 6b4e090e1..000000000 --- a/modules/dml/hijack/transformers.py +++ /dev/null @@ -1,43 +0,0 @@ -import torch -import transformers.models.clip.modeling_clip - -# Copied from transformers.models.bart.modeling_bart._make_causal_mask -def _make_causal_mask( - input_ids_shape: torch.Size, dtype: torch.dtype, device: torch.device, past_key_values_length: int = 0 -): - """ - Make causal mask used for bi-directional self-attention. - """ - bsz, tgt_len = input_ids_shape - min = torch.tensor(torch.finfo(dtype).min, device="cpu") - mask = torch.full((tgt_len, tgt_len), min, device=device) # https://discord.com/channels/1101998836328697867/1127441997184122920 - mask_cond = torch.arange(mask.size(-1), device=device) - mask.masked_fill_(mask_cond < (mask_cond + 1).view(mask.size(-1), 1), 0) - mask = mask.to(dtype) - - if past_key_values_length > 0: - mask = torch.cat([torch.zeros(tgt_len, past_key_values_length, dtype=dtype, device=device), mask], dim=-1) - return mask[None, None, :, :].expand(bsz, 1, tgt_len, tgt_len + past_key_values_length) - -def CLIPTextEmbeddings_forward( - self: transformers.models.clip.modeling_clip.CLIPTextEmbeddings, - input_ids: torch.LongTensor | None = None, - position_ids: torch.LongTensor | None = None, - inputs_embeds: torch.FloatTensor | None = None, -) -> torch.Tensor: - from modules.devices import dtype - seq_length = input_ids.shape[-1] if input_ids is not None else inputs_embeds.shape[-2] - - if position_ids is None: - position_ids = self.position_ids[:, :seq_length] - - if inputs_embeds is None: - inputs_embeds = self.token_embedding(input_ids).type(dtype) # Type correction. - - position_embeddings = self.position_embedding(position_ids) - embeddings = inputs_embeds + position_embeddings - - return embeddings - -transformers.models.clip.modeling_clip._make_causal_mask = _make_causal_mask -transformers.models.clip.modeling_clip.CLIPTextEmbeddings.forward = CLIPTextEmbeddings_forward diff --git a/modules/dml/hijack/utils.py b/modules/dml/hijack/utils.py deleted file mode 100644 index 8817251b0..000000000 --- a/modules/dml/hijack/utils.py +++ /dev/null @@ -1,19 +0,0 @@ -import torch -from collections.abc import Callable -from modules.shared import log, opts - - -def catch_nan(func: Callable[[], torch.Tensor]): - if not opts.directml_catch_nan: - return func() - - tries = 0 - tensor = func() - while tensor.isnan().sum() != 0 and tries < 10: - if tries == 0: - log.warning("NaN is produced. Retry with same values...") - tries += 1 - tensor = func() - if tensor.isnan().sum() != 0: - log.error("Failed to cover NaN.") - return tensor diff --git a/modules/dml/memory.py b/modules/dml/memory.py deleted file mode 100644 index c3ca959b6..000000000 --- a/modules/dml/memory.py +++ /dev/null @@ -1,31 +0,0 @@ -from os import getpid -from collections import defaultdict -from modules.dml.pdh import HQuery, HCounter, expand_wildcard_path - - -class MemoryProvider: - hQuery: HQuery - hCounters: defaultdict[str, list[HCounter]] - - def __init__(self): - self.hQuery = HQuery() - self.hCounters = defaultdict(list) - - def get_memory(self, device_id: int) -> dict[str, int]: - if len(self.hCounters) == 0: - pid = getpid() - paths_dedicated = expand_wildcard_path(f"\\GPU Process Memory(pid_{pid}_*_phys_{device_id})\\Dedicated Usage") - paths_committed = expand_wildcard_path(f"\\GPU Process Memory(pid_{pid}_*_phys_{device_id})\\Total Committed") - for path in paths_dedicated: - self.hCounters["dedicated_usage"].append(self.hQuery.add_counter(path)) - for path in paths_committed: - self.hCounters["total_committed"].append(self.hQuery.add_counter(path)) - self.hQuery.collect_data() - result = defaultdict(int) - for key in self.hCounters: - for hCounter in self.hCounters[key]: - result[key] += hCounter.get_formatted_value(int) - return dict(result) - - def __del__(self): - self.hQuery.close() diff --git a/modules/dml/memory_amd/__init__.py b/modules/dml/memory_amd/__init__.py deleted file mode 100644 index 43907656c..000000000 --- a/modules/dml/memory_amd/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -from .driver.atiadlxx import ATIADLxx - - -class AMDMemoryProvider: - driver: ATIADLxx = ATIADLxx() - - @staticmethod - def mem_get_info(index): - usage = AMDMemoryProvider.driver.get_dedicated_vram_usage(index) * (1 << 20) - return (AMDMemoryProvider.driver.iHyperMemorySize - usage, AMDMemoryProvider.driver.iHyperMemorySize) diff --git a/modules/dml/memory_amd/driver/atiadlxx.py b/modules/dml/memory_amd/driver/atiadlxx.py deleted file mode 100644 index ea47e8c4d..000000000 --- a/modules/dml/memory_amd/driver/atiadlxx.py +++ /dev/null @@ -1,47 +0,0 @@ -import ctypes as C -from modules.dml.memory_amd.driver.atiadlxx_apis import ADL2_Main_Control_Create, ADL_Main_Memory_Alloc, ADL2_Adapter_NumberOfAdapters_Get, ADL2_Adapter_AdapterInfo_Get, ADL2_Adapter_MemoryInfo2_Get, ADL2_Adapter_DedicatedVRAMUsage_Get, ADL2_Adapter_VRAMUsage_Get -from modules.dml.memory_amd.driver.atiadlxx_structures import ADL_CONTEXT_HANDLE, AdapterInfo, LPAdapterInfo, ADLMemoryInfo2 -from modules.dml.memory_amd.driver.atiadlxx_defines import ADL_OK - - -class ATIADLxx: - iHyperMemorySize = 0 - - def __init__(self): - self.context = ADL_CONTEXT_HANDLE() - ADL2_Main_Control_Create(ADL_Main_Memory_Alloc, 1, C.byref(self.context)) - num_adapters = C.c_int(-1) - ADL2_Adapter_NumberOfAdapters_Get(self.context, C.byref(num_adapters)) - AdapterInfoArray = (AdapterInfo * num_adapters.value)() - ADL2_Adapter_AdapterInfo_Get(self.context, C.cast(AdapterInfoArray, LPAdapterInfo), C.sizeof(AdapterInfoArray)) - self.devices = [] - busNumbers = [] - for adapter in AdapterInfoArray: - if adapter.iBusNumber not in busNumbers: # filter duplicate device - self.devices.append(adapter) - busNumbers.append(adapter.iBusNumber) - self.iHyperMemorySize = self.get_memory_info2(0).iHyperMemorySize - - def get_memory_info2(self, adapterIndex: int) -> ADLMemoryInfo2: - info = ADLMemoryInfo2() - - if ADL2_Adapter_MemoryInfo2_Get(self.context, adapterIndex, C.byref(info)) != ADL_OK: - raise RuntimeError("ADL2: Failed to get MemoryInfo2") - - return info - - def get_dedicated_vram_usage(self, index: int) -> int: - usage = C.c_int(-1) - - if ADL2_Adapter_DedicatedVRAMUsage_Get(self.context, self.devices[index].iAdapterIndex, C.byref(usage)) != ADL_OK: - raise RuntimeError("ADL2: Failed to get DedicatedVRAMUsage") - - return usage.value - - def get_vram_usage(self, index: int) -> int: - usage = C.c_int(-1) - - if ADL2_Adapter_VRAMUsage_Get(self.context, self.devices[index].iAdapterIndex, C.byref(usage)) != ADL_OK: - raise RuntimeError("ADL2: Failed to get VRAMUsage") - - return usage.value diff --git a/modules/dml/memory_amd/driver/atiadlxx_apis.py b/modules/dml/memory_amd/driver/atiadlxx_apis.py deleted file mode 100644 index 789622a4c..000000000 --- a/modules/dml/memory_amd/driver/atiadlxx_apis.py +++ /dev/null @@ -1,50 +0,0 @@ -import ctypes as C -from platform import platform -from modules.dml.memory_amd.driver.atiadlxx_structures import ADL_CONTEXT_HANDLE, LPAdapterInfo, ADLMemoryInfo2 - - -if 'Windows' in platform(): - atiadlxx = C.WinDLL("atiadlxx.dll") -else: - atiadlxx = C.CDLL("libatiadlxx.so") # Not tested on Linux system. But will be supported. - - -ADL_MAIN_MALLOC_CALLBACK = C.CFUNCTYPE(C.c_void_p, C.c_int) -ADL_MAIN_FREE_CALLBACK = C.CFUNCTYPE(None, C.POINTER(C.c_void_p)) - - -@ADL_MAIN_MALLOC_CALLBACK -def ADL_Main_Memory_Alloc(iSize): - return C._malloc(iSize) - - -@ADL_MAIN_FREE_CALLBACK -def ADL_Main_Memory_Free(lpBuffer): - if lpBuffer[0] is not None: - C._free(lpBuffer[0]) - lpBuffer[0] = None - - -ADL2_Main_Control_Create = atiadlxx.ADL2_Main_Control_Create -ADL2_Main_Control_Create.restype = C.c_int -ADL2_Main_Control_Create.argtypes = [ADL_MAIN_MALLOC_CALLBACK, C.c_int, ADL_CONTEXT_HANDLE] - -ADL2_Adapter_NumberOfAdapters_Get = atiadlxx.ADL2_Adapter_NumberOfAdapters_Get -ADL2_Adapter_NumberOfAdapters_Get.restype = C.c_int -ADL2_Adapter_NumberOfAdapters_Get.argtypes = [ADL_CONTEXT_HANDLE, C.POINTER(C.c_int)] - -ADL2_Adapter_AdapterInfo_Get = atiadlxx.ADL2_Adapter_AdapterInfo_Get -ADL2_Adapter_AdapterInfo_Get.restype = C.c_int -ADL2_Adapter_AdapterInfo_Get.argtypes = [ADL_CONTEXT_HANDLE, LPAdapterInfo, C.c_int] - -ADL2_Adapter_MemoryInfo2_Get = atiadlxx.ADL2_Adapter_MemoryInfo2_Get -ADL2_Adapter_MemoryInfo2_Get.restype = C.c_int -ADL2_Adapter_MemoryInfo2_Get.argtypes = [ADL_CONTEXT_HANDLE, C.c_int, C.POINTER(ADLMemoryInfo2)] - -ADL2_Adapter_DedicatedVRAMUsage_Get = atiadlxx.ADL2_Adapter_DedicatedVRAMUsage_Get -ADL2_Adapter_DedicatedVRAMUsage_Get.restype = C.c_int -ADL2_Adapter_DedicatedVRAMUsage_Get.argtypes = [ADL_CONTEXT_HANDLE, C.c_int, C.POINTER(C.c_int)] - -ADL2_Adapter_VRAMUsage_Get = atiadlxx.ADL2_Adapter_VRAMUsage_Get -ADL2_Adapter_VRAMUsage_Get.restype = C.c_int -ADL2_Adapter_VRAMUsage_Get.argtypes = [ADL_CONTEXT_HANDLE, C.c_int, C.POINTER(C.c_int)] diff --git a/modules/dml/memory_amd/driver/atiadlxx_defines.py b/modules/dml/memory_amd/driver/atiadlxx_defines.py deleted file mode 100644 index fc1c9d4cb..000000000 --- a/modules/dml/memory_amd/driver/atiadlxx_defines.py +++ /dev/null @@ -1 +0,0 @@ -ADL_OK = 0 diff --git a/modules/dml/memory_amd/driver/atiadlxx_structures.py b/modules/dml/memory_amd/driver/atiadlxx_structures.py deleted file mode 100644 index db8c421c7..000000000 --- a/modules/dml/memory_amd/driver/atiadlxx_structures.py +++ /dev/null @@ -1,90 +0,0 @@ -import ctypes as C - - -class _ADLPMActivity(C.Structure): - __slot__ = [ - 'iActivityPercent', - 'iCurrentBusLanes', - 'iCurrentBusSpeed', - 'iCurrentPerformanceLevel', - 'iEngineClock', - 'iMaximumBusLanes', - 'iMemoryClock', - 'iReserved', - 'iSize', - 'iVddc', - ] -_ADLPMActivity._fields_ = [ # pylint: disable=protected-access - ('iActivityPercent', C.c_int), - ('iCurrentBusLanes', C.c_int), - ('iCurrentBusSpeed', C.c_int), - ('iCurrentPerformanceLevel', C.c_int), - ('iEngineClock', C.c_int), - ('iMaximumBusLanes', C.c_int), - ('iMemoryClock', C.c_int), - ('iReserved', C.c_int), - ('iSize', C.c_int), - ('iVddc', C.c_int), -] -ADLPMActivity = _ADLPMActivity - - -class _ADLMemoryInfo2(C.Structure): - __slot__ = [ - 'iHyperMemorySize', - 'iInvisibleMemorySize', - 'iMemoryBandwidth', - 'iMemorySize', - 'iVisibleMemorySize', - 'strMemoryType' - ] -_ADLMemoryInfo2._fields_ = [ # pylint: disable=protected-access - ('iHyperMemorySize', C.c_longlong), - ('iInvisibleMemorySize', C.c_longlong), - ('iMemoryBandwidth', C.c_longlong), - ('iMemorySize', C.c_longlong), - ('iVisibleMemorySize', C.c_longlong), - ('strMemoryType', C.c_char * 256) -] -ADLMemoryInfo2 = _ADLMemoryInfo2 - - -class _AdapterInfo(C.Structure): - __slot__ = [ - 'iSize', - 'iAdapterIndex', - 'strUDID', - 'iBusNumber', - 'iDeviceNumber', - 'iFunctionNumber', - 'iVendorID', - 'strAdapterName', - 'strDisplayName', - 'iPresent', - 'iExist', - 'strDriverPath', - 'strDriverPathExt', - 'strPNPString', - 'iOSDisplayIndex', - ] -_AdapterInfo._fields_ = [ # pylint: disable=protected-access - ('iSize', C.c_int), - ('iAdapterIndex', C.c_int), - ('strUDID', C.c_char * 256), - ('iBusNumber', C.c_int), - ('iDeviceNumber', C.c_int), - ('iFunctionNumber', C.c_int), - ('iVendorID', C.c_int), - ('strAdapterName', C.c_char * 256), - ('strDisplayName', C.c_char * 256), - ('iPresent', C.c_int), - ('iExist', C.c_int), - ('strDriverPath', C.c_char * 256), - ('strDriverPathExt', C.c_char * 256), - ('strPNPString', C.c_char * 256), - ('iOSDisplayIndex', C.c_int) -] -AdapterInfo = _AdapterInfo -LPAdapterInfo = C.POINTER(_AdapterInfo) - -ADL_CONTEXT_HANDLE = C.c_void_p diff --git a/modules/dml/pdh/__init__.py b/modules/dml/pdh/__init__.py deleted file mode 100644 index 6f7ac9f72..000000000 --- a/modules/dml/pdh/__init__.py +++ /dev/null @@ -1,90 +0,0 @@ -from ctypes import byref, cast, c_size_t -from ctypes.wintypes import LPCWSTR, DWORD, WCHAR -from typing import NamedTuple, TypeVar -from .apis import PdhExpandWildCardPathW, PdhOpenQueryW, PdhAddEnglishCounterW, PdhCollectQueryData, PdhGetFormattedCounterValue, PdhGetFormattedCounterArrayW, PdhCloseQuery -from .structures import PDH_HQUERY, PDH_HCOUNTER, PDH_FMT_COUNTERVALUE, PPDH_FMT_COUNTERVALUE_ITEM_W -from .defines import PDH_FMT_LARGE, PDH_FMT_DOUBLE, PDH_FMT_NOSCALE, PDH_NOEXPANDCOUNTERS, PDH_MORE_DATA, PDH_OK -from .msvcrt import malloc -from .errors import PDHError - - -class __InternalAbstraction(NamedTuple): - flag: int - attr_name: str - - -_type_map = { - int: __InternalAbstraction(PDH_FMT_LARGE, "largeValue"), - float: __InternalAbstraction(PDH_FMT_DOUBLE, "doubleValue"), -} - - -def expand_wildcard_path(path: str) -> list[str]: - listLength = DWORD(0) - if PdhExpandWildCardPathW(None, LPCWSTR(path), None, byref(listLength), PDH_NOEXPANDCOUNTERS) != PDH_MORE_DATA: - raise PDHError("Something went wrong.") - expanded = (WCHAR * listLength.value)() - if PdhExpandWildCardPathW(None, LPCWSTR(path), expanded, byref(listLength), PDH_NOEXPANDCOUNTERS) != PDH_OK: - raise PDHError(f"Couldn't expand wildcard path '{path}'") - result = [] - cur = "" - for c in expanded: - if c == '\0': - result.append(cur) - cur = "" - else: - cur += c - result.pop() - return result - - -T = TypeVar("T", *_type_map.keys()) - - -class HCounter(PDH_HCOUNTER): - def get_formatted_value(self, typ: T) -> T: - if typ not in _type_map: - raise PDHError(f"Invalid value type: {typ}") - flag, attr_name = _type_map[typ] - value = PDH_FMT_COUNTERVALUE() - if PdhGetFormattedCounterValue(self, DWORD(flag | PDH_FMT_NOSCALE), None, byref(value)) != PDH_OK: - raise PDHError("Couldn't get formatted counter value.") - return getattr(value.u, attr_name) - - def get_formatted_dict(self, typ: T) -> dict[str, T]: - if typ not in _type_map: - raise PDHError(f"Invalid value type: {typ}") - flag, attr_name = _type_map[typ] - bufferSize = DWORD(0) - itemCount = DWORD(0) - if PdhGetFormattedCounterArrayW(self, DWORD(flag | PDH_FMT_NOSCALE), byref(bufferSize), byref(itemCount), None) != PDH_MORE_DATA: - raise PDHError("Something went wrong.") - itemBuffer = cast(malloc(c_size_t(bufferSize.value)), PPDH_FMT_COUNTERVALUE_ITEM_W) - if PdhGetFormattedCounterArrayW(self, DWORD(flag | PDH_FMT_NOSCALE), byref(bufferSize), byref(itemCount), itemBuffer) != PDH_OK: - raise PDHError("Couldn't get formatted counter array.") - result: dict[str, T] = {} - for i in range(0, itemCount.value): - item = itemBuffer[i] - result[item.szName] = getattr(item.FmtValue.u, attr_name) - return result - - -class HQuery(PDH_HQUERY): - def __init__(self): - super().__init__() - if PdhOpenQueryW(None, None, byref(self)) != PDH_OK: - raise PDHError("Couldn't open PDH query.") - - def add_counter(self, path: str) -> HCounter: - hCounter = HCounter() - if PdhAddEnglishCounterW(self, LPCWSTR(path), None, byref(hCounter)) != PDH_OK: - raise PDHError("Couldn't add counter query.") - return hCounter - - def collect_data(self): - if PdhCollectQueryData(self) != PDH_OK: - raise PDHError("Couldn't collect query data.") - - def close(self): - if PdhCloseQuery(self) != PDH_OK: - raise PDHError("Couldn't close PDH query.") diff --git a/modules/dml/pdh/apis.py b/modules/dml/pdh/apis.py deleted file mode 100644 index 9486e3321..000000000 --- a/modules/dml/pdh/apis.py +++ /dev/null @@ -1,37 +0,0 @@ -from ctypes import CDLL, POINTER -from ctypes.wintypes import LPCWSTR, LPDWORD, DWORD -from collections.abc import Callable -from .structures import PDH_HQUERY, PDH_HCOUNTER, PPDH_FMT_COUNTERVALUE, PPDH_FMT_COUNTERVALUE_ITEM_W -from .defines import PDH_FUNCTION, PZZWSTR, DWORD_PTR - - -pdh = CDLL("pdh.dll") - - -PdhExpandWildCardPathW: Callable = pdh.PdhExpandWildCardPathW -PdhExpandWildCardPathW.restype = PDH_FUNCTION -PdhExpandWildCardPathW.argtypes = [LPCWSTR, LPCWSTR, PZZWSTR, LPDWORD, DWORD] - -PdhOpenQueryW: Callable = pdh.PdhOpenQueryW -PdhOpenQueryW.restype = PDH_FUNCTION -PdhOpenQueryW.argtypes = [LPCWSTR, DWORD_PTR, POINTER(PDH_HQUERY)] - -PdhAddEnglishCounterW: Callable = pdh.PdhAddEnglishCounterW -PdhAddEnglishCounterW.restype = PDH_FUNCTION -PdhAddEnglishCounterW.argtypes = [PDH_HQUERY, LPCWSTR, DWORD_PTR, POINTER(PDH_HCOUNTER)] - -PdhCollectQueryData: Callable = pdh.PdhCollectQueryData -PdhCollectQueryData.restype = PDH_FUNCTION -PdhCollectQueryData.argtypes = [PDH_HQUERY] - -PdhGetFormattedCounterValue: Callable = pdh.PdhGetFormattedCounterValue -PdhGetFormattedCounterValue.restype = PDH_FUNCTION -PdhGetFormattedCounterValue.argtypes = [PDH_HCOUNTER, DWORD, LPDWORD, PPDH_FMT_COUNTERVALUE] - -PdhGetFormattedCounterArrayW: Callable = pdh.PdhGetFormattedCounterArrayW -PdhGetFormattedCounterArrayW.restype = PDH_FUNCTION -PdhGetFormattedCounterArrayW.argtypes = [PDH_HCOUNTER, DWORD, LPDWORD, LPDWORD, PPDH_FMT_COUNTERVALUE_ITEM_W] - -PdhCloseQuery: Callable = pdh.PdhCloseQuery -PdhCloseQuery.restype = PDH_FUNCTION -PdhCloseQuery.argtypes = [PDH_HQUERY] diff --git a/modules/dml/pdh/defines.py b/modules/dml/pdh/defines.py deleted file mode 100644 index 1d55bcf73..000000000 --- a/modules/dml/pdh/defines.py +++ /dev/null @@ -1,23 +0,0 @@ -from ctypes import c_int, POINTER -from ctypes.wintypes import DWORD, WCHAR - - -PDH_FUNCTION = c_int -PDH_OK = 0x00000000 -PDH_MORE_DATA = -2147481646#0x800007D2 - -DWORD_PTR = POINTER(DWORD) -PWSTR = POINTER(WCHAR) -PZZWSTR = POINTER(WCHAR) - -PDH_NOEXPANDCOUNTERS = 1 -PDH_NOEXPANDINSTANCES = 2 -PDH_REFRESHCOUNTERS = 4 - -PDH_FMT_LONG = 0x00000100 -PDH_FMT_DOUBLE = 0x00000200 -PDH_FMT_LARGE = 0x00000400 - -PDH_FMT_NOSCALE = 0x00001000 -PDH_FMT_1000 = 0x00002000 -PDH_FMT_NOCAP100 = 0x00008000 diff --git a/modules/dml/pdh/errors.py b/modules/dml/pdh/errors.py deleted file mode 100644 index 3d8270219..000000000 --- a/modules/dml/pdh/errors.py +++ /dev/null @@ -1,3 +0,0 @@ -class PDHError(Exception): - def __init__(self, message: str): - super().__init__(message) diff --git a/modules/dml/pdh/msvcrt.py b/modules/dml/pdh/msvcrt.py deleted file mode 100644 index 22374cccd..000000000 --- a/modules/dml/pdh/msvcrt.py +++ /dev/null @@ -1,13 +0,0 @@ -from ctypes import CDLL, c_void_p, c_size_t - - -msvcrt = CDLL("msvcrt") - - -malloc = msvcrt.malloc -malloc.restype = c_void_p -malloc.argtypes = [c_size_t] - -free = msvcrt.free -free.restype = None -free.argtypes = [c_void_p] diff --git a/modules/dml/pdh/structures.py b/modules/dml/pdh/structures.py deleted file mode 100644 index e38556ccf..000000000 --- a/modules/dml/pdh/structures.py +++ /dev/null @@ -1,45 +0,0 @@ -from ctypes import Union, c_double, c_longlong, Structure, POINTER -from ctypes.wintypes import HANDLE, LONG, LPCSTR, LPCWSTR, DWORD, LPWSTR - - -PDH_HQUERY = HANDLE -PDH_HCOUNTER = HANDLE - - -class PDH_FMT_COUNTERVALUE_U(Union): - _fields_ = [ - ("longValue", LONG), - ("doubleValue", c_double), - ("largeValue", c_longlong), - ("AnsiStringValue", LPCSTR), - ("WideStringValue", LPCWSTR), - ] - - longValue: int - doubleValue: float - largeValue: int - AnsiStringValue: LPCSTR - WideStringValue: LPCWSTR - - -class PDH_FMT_COUNTERVALUE(Structure): - _anonymous_ = ("u",) - _fields_ = [ - ("CStatus", DWORD), - ("u", PDH_FMT_COUNTERVALUE_U), - ] - - CStatus: DWORD - u: PDH_FMT_COUNTERVALUE_U -PPDH_FMT_COUNTERVALUE = POINTER(PDH_FMT_COUNTERVALUE) - - -class PDH_FMT_COUNTERVALUE_ITEM_W(Structure): - _fields_ = [ - ("szName", LPWSTR), - ("FmtValue", PDH_FMT_COUNTERVALUE), - ] - - szName: str - FmtValue: PDH_FMT_COUNTERVALUE -PPDH_FMT_COUNTERVALUE_ITEM_W = POINTER(PDH_FMT_COUNTERVALUE_ITEM_W) diff --git a/modules/dml/utils.py b/modules/dml/utils.py deleted file mode 100644 index 58dd3238b..000000000 --- a/modules/dml/utils.py +++ /dev/null @@ -1,9 +0,0 @@ -from typing import Union -import torch - - -rDevice = Union[torch.device, int] -def get_device(device: rDevice | None=None) -> torch.device: - if device is None: - device = torch.dml.current_device() - return torch.device(device) diff --git a/modules/onnx_impl/execution_providers.py b/modules/onnx_impl/execution_providers.py index e493dffca..497fee4c3 100644 --- a/modules/onnx_impl/execution_providers.py +++ b/modules/onnx_impl/execution_providers.py @@ -47,8 +47,6 @@ else: def get_default_execution_provider() -> ExecutionProvider: if devices.backend == "cpu": return ExecutionProvider.CPU - elif devices.backend == "directml": - return ExecutionProvider.DirectML elif devices.backend == "cuda": return ExecutionProvider.CUDA elif devices.backend == "rocm": diff --git a/modules/onnx_impl/ui.py b/modules/onnx_impl/ui.py index 0a8ca2d22..45118b8df 100644 --- a/modules/onnx_impl/ui.py +++ b/modules/onnx_impl/ui.py @@ -24,9 +24,7 @@ def create_ui(): with gr.TabItem("Provider", id="onnxep"): gr.Markdown("Install ONNX execution provider") ep_default = None - if cmd_opts.use_directml: - ep_default = ExecutionProvider.DirectML - elif cmd_opts.use_cuda: + if cmd_opts.use_cuda: ep_default = ExecutionProvider.CUDA elif cmd_opts.use_rocm: ep_default = ExecutionProvider.ROCm diff --git a/modules/sd_hijack_dynamic_atten.py b/modules/sd_hijack_dynamic_atten.py index 6410b5a71..5a715125e 100644 --- a/modules/sd_hijack_dynamic_atten.py +++ b/modules/sd_hijack_dynamic_atten.py @@ -108,8 +108,6 @@ def dynamic_scaled_dot_product_attention(query: torch.FloatTensor, key: torch.Fl attn_mask=attn_mask[start_idx:end_idx, :, :, :] if attn_mask is not None else attn_mask, dropout_p=dropout_p, is_causal=is_causal, scale=scale, **kwargs ) - if devices.backend != "directml": - getattr(torch, query.device.type).synchronize() else: hidden_states = devices.sdpa_pre_dyanmic_atten(query, key, value, attn_mask=attn_mask, dropout_p=dropout_p, is_causal=is_causal, scale=scale, **kwargs) if is_unsqueezed: @@ -252,8 +250,6 @@ class DynamicAttnProcessorBMM: hidden_states[start_idx:end_idx] = attn_slice del attn_slice - if devices.backend != "directml": - getattr(torch, query.device.type).synchronize() else: attention_probs = attn.get_attention_scores(query, key, attention_mask) hidden_states = torch.bmm(attention_probs, value) diff --git a/modules/sd_hijack_freeu.py b/modules/sd_hijack_freeu.py index 7f29de9e8..30064adba 100644 --- a/modules/sd_hijack_freeu.py +++ b/modules/sd_hijack_freeu.py @@ -98,13 +98,7 @@ def get_fft_device(): def no_gpu_complex_support(): mps_available = hasattr(torch.backends, "mps") and torch.backends.mps.is_available() - try: - import torch_directml - except ImportError: - dml_available = False - else: - dml_available = torch_directml.is_available() - return mps_available or dml_available + return mps_available def filter_skip(x, threshold, scale, scale_high): diff --git a/modules/sd_hijack_triton.py b/modules/sd_hijack_triton.py index ca2441e88..c8429623f 100644 --- a/modules/sd_hijack_triton.py +++ b/modules/sd_hijack_triton.py @@ -129,6 +129,6 @@ def install(): knobs.autotuning.listener = make_autotune_listener(getattr(knobs.autotuning, 'listener', None)) knobs.compilation.listener = make_compile_listener(getattr(knobs.compilation, 'listener', None)) Autotuner._bench = bench_hook(Autotuner._bench) # pylint: disable=protected-access - log.debug('Kernel autotune: reporting installed') + # log.debug('Kernel autotune: reporting installed') except Exception as e: log.warning(f'Kernel autotune: reporting install failed: {e}') diff --git a/modules/sd_offload.py b/modules/sd_offload.py index 246ac6e2f..a0bfa6901 100644 --- a/modules/sd_offload.py +++ b/modules/sd_offload.py @@ -270,10 +270,6 @@ class OffloadHook(accelerate.hooks.ModelHook): clean_result=False, ) offload_dir = getattr(module, "offload_dir", os.path.join(shared.opts.accelerate_offload_path, module.__class__.__name__)) - if devices.backend == "directml": - for k, v in device_map.items(): - if isinstance(v, int): - device_map[k] = f"{devices.device.type}:{v}" # int implies CUDA or XPU device, but it will break DirectML backend so we add type if debug: log.trace(f'Offload: type=balanced op=dispatch map={device_map}') if device_map is not None: diff --git a/modules/shared.py b/modules/shared.py index e9054160c..b08e1d44e 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -88,13 +88,6 @@ elif cmd_opts.use_ipex or devices.has_xpu(): log.error(f'IPEX initialization failed: {e}') if os.environ.get('SD_DEVICE_DEBUG', None) is not None: errors.display(e, 'IPEX') -elif cmd_opts.use_directml: - from modules.dml import directml_init - ok, e = directml_init() - if not ok: - log.error(f'DirectML initialization failed: {e}') - if os.environ.get('SD_DEVICE_DEBUG', None) is not None: - errors.display(e, 'DirectML') elif cmd_opts.use_rocm or devices.has_rocm(): from modules.rocm import rocm_init ok, e = rocm_init() @@ -167,7 +160,6 @@ if cmd_opts.locale is not None: opts.data['ui_locale'] = cmd_opts.locale log.debug('Initializing: backend') -from modules.dml import directml_do_hijack if cmd_opts.use_xformers: opts.data['cross_attention_optimization'] = 'xFormers' opts.data['uni_pc_lower_order_final'] = opts.schedulers_use_loworder # compatibility @@ -191,8 +183,6 @@ device = devices.device parallel_processing_allowed = not cmd_opts.lowvram mem_mon = modules.memmon.MemUsageMonitor("MemMon", devices.device) history = history.History() -if devices.backend == "directml": - directml_do_hijack() log.debug('Quantization: registered=SDNQ') try: diff --git a/modules/shared_defaults.py b/modules/shared_defaults.py index a20216823..512f5913b 100644 --- a/modules/shared_defaults.py +++ b/modules/shared_defaults.py @@ -56,7 +56,7 @@ def get_default_modes(cmd_opts, mem_stat): agent = devices.get_hip_agent() if agent.gfx_version < 0x1100: default_sdp_override_options = ['Dynamic attention'] # only RDNA2 and older GPUs needs this - elif devices.backend in {"directml", "cpu", "mps"}: + elif devices.backend in {"cpu", "mps"}: default_sdp_override_options = ['Dynamic attention'] if devices.get_optimal_device_name() != "cpu": diff --git a/modules/ui_definitions.py b/modules/ui_definitions.py index 5b895646a..c01e52fb7 100644 --- a/modules/ui_definitions.py +++ b/modules/ui_definitions.py @@ -25,14 +25,6 @@ def list_onnx_providers(): return "CPU", [] -def list_dml_providers(): - try: - from modules.dml import memory_providers, default_memory_provider - return default_memory_provider, memory_providers - except Exception: - return "Performance Counter", [] - - def list_checkpoint_titles(): import modules.sd_models # pylint: disable=redefined-outer-name return modules.sd_models.checkpoint_titles() @@ -83,7 +75,6 @@ def create_settings(cmd_opts): default_xetcache_dir = os.environ.get("HF_XET_CACHE ", None) or os.path.join(paths.models_path, 'xet') default_onnx_execution_provider, default_onnx_execution_providers = list_onnx_providers() - default_dml_memory_provider, default_dml_memory_providers = list_dml_providers() hide_dirs = {"visible": not cmd_opts.hide_ui_dir_config} @@ -313,10 +304,6 @@ def create_settings(cmd_opts): "openvino_compile_backend": OptionInfo("openvino_fx", "OpenVINO compile backend", gr.Radio, {"choices": ["openvino", "openvino_fx"], "visible": cmd_opts.use_openvino}), "openvino_disable_model_caching": OptionInfo(True, "OpenVINO disable model caching", gr.Checkbox, {"visible": cmd_opts.use_openvino}), "openvino_disable_memory_cleanup": OptionInfo(True, "OpenVINO disable memory cleanup", gr.Checkbox, {"visible": cmd_opts.use_openvino}), - - "directml_sep": OptionInfo("

DirectML

", "", gr.HTML, {"visible": devices.backend == "directml"}), - "directml_memory_provider": OptionInfo(default_dml_memory_provider, "DirectML memory stats provider", gr.Radio, {"choices": default_dml_memory_providers, "visible": devices.backend == "directml"}), - "directml_catch_nan": OptionInfo(False, "DirectML retry ops for NaN", gr.Checkbox, {"visible": devices.backend == "directml"}), })) # --- Pipeline Modifiers --- diff --git a/modules/ui_settings.py b/modules/ui_settings.py index 74787c431..0a94dcb52 100644 --- a/modules/ui_settings.py +++ b/modules/ui_settings.py @@ -135,9 +135,6 @@ def run_settings(*args): from modules.onnx_impl import install_olive, initialize_onnx_pipelines install_olive() initialize_onnx_pipelines() - if shared.cmd_opts.use_directml: - from modules.dml import directml_override_opts - directml_override_opts() if shared.cmd_opts.use_openvino: if "Model" not in shared.opts.cuda_compile: log.warning("OpenVINO: Overriding Torch Compile Model") @@ -196,9 +193,6 @@ def run_settings_single(value, key, progress=False, force=False): if key == "cuda_compile_backend" and value == "olive-ai": from modules.onnx_impl import install_olive install_olive() - if shared.cmd_opts.use_directml: - from modules.dml import directml_override_opts - directml_override_opts() shared.opts.save(silent=True) if key == 'sd_text_encoder': sd_models.reload_text_encoder() # apply the change now; reloads the model for encoders with no in-place swap diff --git a/pyproject.toml b/pyproject.toml index c77d1d6fd..e7094dfbc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -109,7 +109,6 @@ main.ignore-paths=[ "modules/schedulers/scheduler_*.py", "modules/apg", "modules/cfgzero", - "modules/dml", "modules/face", "modules/flash_attn_triton_amd", "modules/ggml", diff --git a/wiki b/wiki index ee4e24dbb..9ff9ec3bb 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit ee4e24dbb80ac1c9b110271f49f44b0f23e1271c +Subproject commit 9ff9ec3bb0d8432405fb62db397b18e38747d94f