Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-comfy-aimdo for 
openSUSE:Factory checked in at 2026-09-11 18:02:21
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-comfy-aimdo (Old)
 and      /work/SRC/openSUSE:Factory/.python-comfy-aimdo.new.1265 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-comfy-aimdo"

Fri Sep 11 18:02:21 2026 rev:6 rq:1376991 version:0.5.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-comfy-aimdo/python-comfy-aimdo.changes    
2026-09-08 16:55:30.622451681 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-comfy-aimdo.new.1265/python-comfy-aimdo.changes
  2026-09-11 18:05:49.896121151 +0200
@@ -1,0 +2,16 @@
+Thu Sep 10 18:34:20 UTC 2026 - Martin Pluskal <[email protected]>
+
+- Update to 0.5.3:
+  * Runtime simple_vram_headroom accessors, so the VRAM budget can be
+    retuned without re-running init() (which resets its other args)
+  * Refuse a second init_devices() without deinit() first: it used to
+    orphan live CUDA hooks and segfault on the next torch allocation
+  * detect_vendor() now reads torch.version hip/cuda first -- the
+    upstream half of our downstream vendor-detection patch, which
+    shrinks to the quiet-no-accelerator hunk (rebased, still needed)
+  * ROCm 7 runtime preferred, integrated ROCm GPUs budgeted against
+    system RAM on Linux
+  * torch floor stays >= 2.8.0: README still names PyTorch 2.8+, and
+    the sdist declares no install dependencies
+
+-------------------------------------------------------------------

Old:
----
  comfy-aimdo-0.5.2.tar.gz

New:
----
  comfy-aimdo-0.5.3.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-comfy-aimdo.spec ++++++
--- /var/tmp/diff_new_pack.CaL1LY/_old  2026-09-11 18:05:51.570191136 +0200
+++ /var/tmp/diff_new_pack.CaL1LY/_new  2026-09-11 18:05:51.573191262 +0200
@@ -18,13 +18,13 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-comfy-aimdo
-Version:        0.5.2
+Version:        0.5.3
 Release:        0
 Summary:        AI Model Dynamic Offloader for ComfyUI (pure-Python fallback)
 License:        GPL-3.0-only
 URL:            https://github.com/Comfy-Org/comfy-aimdo
 Source:         
https://github.com/Comfy-Org/comfy-aimdo/archive/refs/tags/v%{version}.tar.gz#/comfy-aimdo-%{version}.tar.gz
-# PATCH-FIX-OPENSUSE comfy-aimdo-detect-vendor-without-local-version.patch 
[email protected] -- read torch's own cuda/hip attributes instead of the 
wheel-only version suffix, and skip quietly when there is no accelerator
+# PATCH-FIX-OPENSUSE comfy-aimdo-detect-vendor-without-local-version.patch 
[email protected] -- return False quietly when PyTorch has no accelerator, 
instead of guessing cuda with a warning (the torch.version hip/cuda detection 
half is upstream since 0.5.3)
 Patch0:         comfy-aimdo-detect-vendor-without-local-version.patch
 BuildRequires:  %{python_module pip}
 BuildRequires:  %{python_module setuptools >= 61.0}

++++++ comfy-aimdo-0.5.2.tar.gz -> comfy-aimdo-0.5.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/comfy-aimdo-0.5.2/comfy_aimdo/control.py 
new/comfy-aimdo-0.5.3/comfy_aimdo/control.py
--- old/comfy-aimdo-0.5.2/comfy_aimdo/control.py        2026-09-05 
00:25:48.000000000 +0200
+++ new/comfy-aimdo-0.5.3/comfy_aimdo/control.py        2026-09-08 
12:59:20.000000000 +0200
@@ -28,6 +28,8 @@
 
 def detect_vendor():
     version = ""
+    hip = None
+    cuda = None
     try:
         torch_spec = importlib.util.find_spec("torch")
         for folder in torch_spec.submodule_search_locations:
@@ -37,10 +39,19 @@
                 module = importlib.util.module_from_spec(spec)
                 spec.loader.exec_module(module)
                 version = module.__version__
+                hip = getattr(module, "hip", None)
+                cuda = getattr(module, "cuda", None)
     except Exception as e:
         logging.warning("Failed to detect Torch version")
         pass
 
+    # torch.version.hip/cuda are authoritative. The local version segment is 
only
+    # a fallback: ROCm nightlies do not always carry a +rocm suffix.
+    if hip:
+        return "rocm"
+    if cuda:
+        return "cuda"
+
     if '+cu' in version:
         return "cuda"
     if '+rocm' in version:
@@ -101,6 +112,9 @@
     lib.set_simple_vram_headroom.argtypes = [ctypes.c_int64]
     lib.set_simple_vram_headroom.restype = None
 
+    lib.get_simple_vram_headroom.argtypes = []
+    lib.get_simple_vram_headroom.restype = ctypes.c_int64
+
     lib.set_nvml_pressure.argtypes = [ctypes.c_bool]
     lib.set_nvml_pressure.restype = None
 
@@ -146,6 +160,10 @@
     if lib is None:
         return False
 
+    if devctxs:
+        logging.warning("comfy-aimdo devices are already initialized, call 
deinit() first")
+        return False
+
     requested = []
     headrooms = []
     for device_id in device_ids:
@@ -194,6 +212,33 @@
         return devctx
     raise RuntimeError(f"comfy-aimdo device {device_id} is not initialized")
 
+def set_simple_vram_headroom(headroom: int):
+    """Set the VRAM the simple budget keeps free, in bytes.
+
+    One process wide value, compared against each device's own capacity. It
+    is separate from the per device extra_vram_headroom given to
+    init_devices(). Only the simple budget term reads it; the measured poll
+    term keeps its own compile time floor of 256 MB (VRAM_HEADROOM) and the
+    budget takes the larger of the two, so raising this above 256 MB is
+    honoured but lowering it below 256 MB changes nothing. Raising it takes
+    effect at the next VBAR fault or hooked device allocation and is honoured
+    by evicting VBAR pages only; torch allocations are counted against it
+    but never refused. Lowering it does not refill anything by itself: pages
+    come back when a VBAR is next prioritized, which ComfyUI does when it
+    loads a model.
+    """
+    headroom = int(headroom)
+    if headroom < 0 or headroom > (1 << 60):
+        raise ValueError("simple_vram_headroom must be between 0 and 2**60 
bytes")
+    if lib is None:
+        raise RuntimeError("comfy-aimdo is not initialized")
+    lib.set_simple_vram_headroom(headroom)
+
+def get_simple_vram_headroom():
+    if lib is None:
+        raise RuntimeError("comfy-aimdo is not initialized")
+    return int(lib.get_simple_vram_headroom())
+
 def deinit():
     global lib, devctxs, _log_callback
     if lib is not None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/comfy-aimdo-0.5.2/comfy_aimdo/malloc_graph.py 
new/comfy-aimdo-0.5.3/comfy_aimdo/malloc_graph.py
--- old/comfy-aimdo-0.5.2/comfy_aimdo/malloc_graph.py   2026-09-05 
00:25:48.000000000 +0200
+++ new/comfy-aimdo-0.5.3/comfy_aimdo/malloc_graph.py   2026-09-08 
12:59:20.000000000 +0200
@@ -66,6 +66,7 @@
     peak_used = property(lambda self: self._stat(0))
     virtual_bytes = property(lambda self: self._stat(1))
     physical_bytes = property(lambda self: self._stat(2))
+    rogue_count = property(lambda self: self._stat(3))
 
     def __del__(self):
         handle = getattr(self, "_handle", None)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/comfy-aimdo-0.5.2/src/control.c 
new/comfy-aimdo-0.5.3/src/control.c
--- old/comfy-aimdo-0.5.2/src/control.c 2026-09-05 00:25:48.000000000 +0200
+++ new/comfy-aimdo-0.5.3/src/control.c 2026-09-08 12:59:20.000000000 +0200
@@ -2,7 +2,7 @@
 #include "aimdo-time.h"
 #include "xfer-file.h"
 
-#if !defined(_WIN32) && !defined(_WIN64) && defined(AIMDO_CUDA)
+#if !defined(_WIN32) && !defined(_WIN64)
 #define INTEGRATED_RAM_HEADROOM_MIN (2ULL * G)
 #define INTEGRATED_RAM_HEADROOM_MAX (8ULL * G)
 #define INTEGRATED_SIMPLE_ONLY_DEFICIT (-(ssize_t)(1ULL << 60))
@@ -65,6 +65,11 @@
 }
 
 SHARED_EXPORT
+int64_t get_simple_vram_headroom(void) {
+    return simple_vram_headroom;
+}
+
+SHARED_EXPORT
 void set_nvml_pressure(bool enabled) {
     nvml_pressure = enabled;
 }
@@ -140,7 +145,7 @@
     control_timestamp_last_check = now;
     total_vram_last_check = total_vram_usage;
 
-#if !defined(_WIN32) && !defined(_WIN64) && defined(AIMDO_CUDA)
+#if !defined(_WIN32) && !defined(_WIN64)
     if (integrated_device) {
         size_t mem_available = 0;
 
@@ -209,6 +214,7 @@
         set_devctx(&g_all_devctxs[i]);
         hostbuf_file_reader_cleanup();
         aimdo_wddm_cleanup();
+        va_pool_cleanup();
         allocations_cleanup();
 
         free(highest_priority_p); /* FIXME: move the model_vbar. */
@@ -242,12 +248,13 @@
         set_devctx(devctx);
 
         if (!allocations_init() ||
+            !va_pool_init() ||
             !CHECK_CU(cuDeviceGet(&dev, cuda_device_ids[i])) ||
             !CHECK_CU(cuDeviceTotalMem(&vram_capacity, dev))) {
             goto fail;
         }
 
-#if !defined(_WIN32) && !defined(_WIN64) && defined(AIMDO_CUDA)
+#if !defined(_WIN32) && !defined(_WIN64)
         devctx->_integrated_device = is_integrated_cuda_device(dev);
         if (devctx->_integrated_device) {
             devctx->_integrated_ram_headroom = 
calculate_integrated_ram_headroom(vram_capacity);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/comfy-aimdo-0.5.2/src/control.h 
new/comfy-aimdo-0.5.3/src/control.h
--- old/comfy-aimdo-0.5.2/src/control.h 2026-09-05 00:25:48.000000000 +0200
+++ new/comfy-aimdo-0.5.3/src/control.h 2026-09-08 12:59:20.000000000 +0200
@@ -53,6 +53,7 @@
     int _hostbuf_file_reader_active;
 #if defined(__HIP_PLATFORM_AMD__) && defined(_WIN32)
     VramBuffer *_va_pool;
+    void *_va_pool_lock;
 #endif
 #if defined(_WIN32) || defined(_WIN64)
     void *_wddm_adapter; /* IDXGIAdapter3* */
@@ -91,6 +92,7 @@
 #define global_rogue_candidates     (g_devctx->_rogue_candidates)
 #if defined(__HIP_PLATFORM_AMD__) && defined(_WIN32)
 #define va_pool                     (g_devctx->_va_pool)
+#define va_pool_lock                (g_devctx->_va_pool_lock)
 #endif
 #if defined(_WIN32) || defined(_WIN64)
 #define g_wddm_adapter              (*(IDXGIAdapter3 
**)&g_devctx->_wddm_adapter)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/comfy-aimdo-0.5.2/src/gpu_abi.h 
new/comfy-aimdo-0.5.3/src/gpu_abi.h
--- old/comfy-aimdo-0.5.2/src/gpu_abi.h 2026-09-05 00:25:48.000000000 +0200
+++ new/comfy-aimdo-0.5.3/src/gpu_abi.h 2026-09-08 12:59:20.000000000 +0200
@@ -31,8 +31,16 @@
     char bytes[16];
 } CUuuid;
 
+/* hipDeviceAttribute_t is not numerically compatible with CUdevice_attribute.
+ * hipDeviceAttributeIntegrated is 16, so querying a HIP device with the CUDA
+ * value would read hipDeviceAttributeKernelExecTimeout instead.
+ */
 typedef enum CUdevice_attribute_enum {
+#if defined(__HIP_PLATFORM_AMD__)
+    CU_DEVICE_ATTRIBUTE_INTEGRATED = 16,
+#else
     CU_DEVICE_ATTRIBUTE_INTEGRATED = 18,
+#endif
 } CUdevice_attribute;
 
 typedef enum cudaError_enum {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/comfy-aimdo-0.5.2/src/malloc-graph.c 
new/comfy-aimdo-0.5.3/src/malloc-graph.c
--- old/comfy-aimdo-0.5.2/src/malloc-graph.c    2026-09-05 00:25:48.000000000 
+0200
+++ new/comfy-aimdo-0.5.3/src/malloc-graph.c    2026-09-08 12:59:20.000000000 
+0200
@@ -112,6 +112,7 @@
     size_t small_pages;
     size_t used;
     size_t peak_used;
+    size_t rogue_count;
 
     bool failed;
     bool complete;
@@ -310,6 +311,7 @@
         }
         allocation->allocation_previous = g->rogue_candidates;
         g->rogue_candidates = allocation;
+        g->rogue_count++;
         allocation = previous;
     }
     g->state->allocations = NULL;
@@ -976,7 +978,7 @@
     return true;
 }
 
-bool malloc_graph_free(CUdeviceptr ptr, size_t size, CUstream stream, int 
*result) {
+bool malloc_graph_free(CUdeviceptr ptr, CUstream stream, int *result) {
     MallocGraph *g = active_graph;
 
     if (!g || graph_failed(g) || g->paused || stream != g->stream) {
@@ -987,7 +989,6 @@
     CUdeviceptr small_base = virtual_range_get(g->small_base);
     bool small = ptr >= small_base && ptr < small_base + MG_SMALL_PAGES * 
MG_PAGE;
     if (!small && (ptr < base || ptr >= base + MG_PAGES * MG_PAGE)) {
-        RETURN_G_FAILED(size, false);
         return false;
     }
 
@@ -1207,6 +1208,8 @@
         return (g->va_count + g->small_pages) * MG_PAGE;
     case 2:
         return (g->phys_count + g->small_pages) * MG_PAGE;
+    case 3:
+        return g->rogue_count;
     default:
         return 0;
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/comfy-aimdo-0.5.2/src/plat.h 
new/comfy-aimdo-0.5.3/src/plat.h
--- old/comfy-aimdo-0.5.2/src/plat.h    2026-09-05 00:25:48.000000000 +0200
+++ new/comfy-aimdo-0.5.3/src/plat.h    2026-09-08 12:59:20.000000000 +0200
@@ -221,6 +221,15 @@
     return err;
 }
 
+/* vrambuf.c */
+#if defined(__HIP_PLATFORM_AMD__) && defined(_WIN32)
+bool va_pool_init(void);
+void va_pool_cleanup(void);
+#else
+static inline bool va_pool_init(void) { return true; }
+static inline void va_pool_cleanup(void) {}
+#endif
+
 /* model_vbar.c */
 size_t vbars_free(ssize_t size);
 SHARED_EXPORT
@@ -238,7 +247,7 @@
                           CUresult (*true_cuMemFreeAsync)(CUdeviceptr, 
CUstream));
 
 bool malloc_graph_alloc(CUdeviceptr *ptr, size_t size, CUstream stream);
-bool malloc_graph_free(CUdeviceptr ptr, size_t size, CUstream stream, int 
*result);
+bool malloc_graph_free(CUdeviceptr ptr, CUstream stream, int *result);
 bool malloc_graph_sync_paused(void);
 
 bool allocations_init(void);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/comfy-aimdo-0.5.2/src/pyt-cu-plug-alloc-async.c 
new/comfy-aimdo-0.5.3/src/pyt-cu-plug-alloc-async.c
--- old/comfy-aimdo-0.5.2/src/pyt-cu-plug-alloc-async.c 2026-09-05 
00:25:48.000000000 +0200
+++ new/comfy-aimdo-0.5.3/src/pyt-cu-plug-alloc-async.c 2026-09-08 
12:59:20.000000000 +0200
@@ -151,21 +151,6 @@
     log(DEBUG, "%s: could not account free at %p\n", __func__, (void 
*)(uintptr_t)ptr);
 }
 
-static size_t allocation_size(CUdeviceptr ptr) {
-    SizeEntry *entry;
-    size_t size = 0;
-
-    allocations_lock();
-    for (entry = size_table[size_hash(ptr)]; entry; entry = entry->next) {
-        if (entry->ptr == ptr) {
-            size = entry->size;
-            break;
-        }
-    }
-    allocations_unlock();
-    return size;
-}
-
 int aimdo_cuda_malloc(CUdeviceptr *devPtr, size_t size,
                       CUresult (*true_cuMemAlloc_v2)(CUdeviceptr*, size_t)) {
     CUdeviceptr dptr;
@@ -284,7 +269,7 @@
     if (free_rogue(devPtr, &status)) {
         return status;
     }
-    if (malloc_graph_free(devPtr, allocation_size(devPtr), hStream, &status)) {
+    if (malloc_graph_free(devPtr, hStream, &status)) {
         return status;
     }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/comfy-aimdo-0.5.2/src/vrambuf.c 
new/comfy-aimdo-0.5.3/src/vrambuf.c
--- old/comfy-aimdo-0.5.2/src/vrambuf.c 2026-09-05 00:25:48.000000000 +0200
+++ new/comfy-aimdo-0.5.3/src/vrambuf.c 2026-09-08 12:59:20.000000000 +0200
@@ -1,4 +1,5 @@
 #include "vrambuf.h"
+#include "thread-plat.h"
 
 #if defined(__HIP_PLATFORM_AMD__) && !defined(_WIN32)
 #  define VRAM_CHUNK_SIZE      CUDA_PAGE_SIZE
@@ -11,6 +12,38 @@
  * and reuse it per max_size on the current device context; physical VRAM is
  * still released on destroy, only the reserve/free pair is elided. */
 
+#if defined(__HIP_PLATFORM_AMD__) && defined(_WIN32)
+/* The pool hangs off AimdoContext, which is shared by every thread bound to 
the
+ * device, and vrambuf_destroy runs on whichever thread drops the last python
+ * reference. The list therefore needs the same treatment as the size table.
+ */
+bool va_pool_init(void) {
+    return (va_pool_lock = (void *)mutex_create()) != NULL;
+}
+
+void va_pool_cleanup(void) {
+    VramBuffer *buf;
+
+    if (!va_pool_lock) {
+        return;
+    }
+
+    mutex_lock((Mutex)va_pool_lock);
+    for (buf = va_pool; buf; ) {
+        VramBuffer *next = buf->next;
+
+        CHECK_CU(cuMemAddressFree(buf->base_ptr, buf->max_size));
+        free(buf);
+        buf = next;
+    }
+    va_pool = NULL;
+    mutex_unlock((Mutex)va_pool_lock);
+
+    mutex_destroy((Mutex)va_pool_lock);
+    va_pool_lock = NULL;
+}
+#endif
+
 SHARED_EXPORT
 void *vrambuf_create(int device, size_t max_size) {
     VramBuffer *buf;
@@ -22,14 +55,17 @@
     max_size = CUDA_ALIGN_UP(max_size);
 
 #if defined(__HIP_PLATFORM_AMD__) && defined(_WIN32)
+    mutex_lock((Mutex)va_pool_lock);
     for (VramBuffer **p = &va_pool; *p; p = &(*p)->next) {
         if ((*p)->max_size == max_size) {
             buf = *p;
             *p = buf->next;
             buf->next = NULL;
+            mutex_unlock((Mutex)va_pool_lock);
             return (void *)buf;
         }
     }
+    mutex_unlock((Mutex)va_pool_lock);
 #endif
 
     buf = (VramBuffer *)calloc(1, sizeof(*buf) + 
sizeof(CUmemGenericAllocationHandle) * max_size / VRAM_CHUNK_SIZE);
@@ -134,8 +170,10 @@
     /* VRAM freed; keep the VA reservation and park it for reuse. */
     buf->allocated = 0;
     buf->handle_count = 0;
+    mutex_lock((Mutex)va_pool_lock);
     buf->next = va_pool;
     va_pool = buf;
+    mutex_unlock((Mutex)va_pool_lock);
     return true;
 #else
     CHECK_CU(cuMemAddressFree(buf->base_ptr, buf->max_size));
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/comfy-aimdo-0.5.2/src-hip/dispatch.c 
new/comfy-aimdo-0.5.3/src-hip/dispatch.c
--- old/comfy-aimdo-0.5.2/src-hip/dispatch.c    2026-09-05 00:25:48.000000000 
+0200
+++ new/comfy-aimdo-0.5.3/src-hip/dispatch.c    2026-09-08 12:59:20.000000000 
+0200
@@ -31,9 +31,14 @@
 static const DispatchSymbol dispatch_symbols[] = {
     { (void **)&g_cuda.p_cuInit, "hipInit" },
     { (void **)&g_cuda.p_cuGetErrorString, "hipDrvGetErrorString" },
+    /* hipGetDevice cannot report the absent-context failure cuCtxGetDevice 
uses,
+     * but HIP binds an unbound thread to device 0 and allocates there, so
+     * following the current device stays correct.
+     */
     { (void **)&g_cuda.p_cuCtxGetDevice, "hipGetDevice" },
     { (void **)&g_cuda.p_cuCtxSynchronize, "hipDeviceSynchronize" },
     { (void **)&g_cuda.p_cuDeviceGet, "hipDeviceGet" },
+    { (void **)&g_cuda.p_cuDeviceGetAttribute, "hipDeviceGetAttribute" },
     { (void **)&g_cuda.p_cuDeviceTotalMem, "hipDeviceTotalMem" },
     { (void **)&g_cuda.p_cuDeviceGetName, "hipDeviceGetName" },
     { (void **)&g_cuda.p_cuMemGetInfo, "hipMemGetInfo" },
@@ -61,8 +66,8 @@
 
 static const char *const hip_library_names[] = {
 #if defined(_WIN32) || defined(_WIN64)
-    "amdhip64.dll",
     "amdhip64_7.dll",
+    "amdhip64.dll",
 #else
     "libamdhip64.so.7",
     "libamdhip64.so.6",
@@ -106,9 +111,15 @@
     g_cuda.p_cuMemAllocAsync_ptsz = g_cuda.p_cuMemAllocAsync;
     g_cuda.p_cuMemFreeAsync_ptsz = g_cuda.p_cuMemFreeAsync;
 
-    g_device_get_properties = 
(PFN_deviceGetProperties)aimdo_hip_resolve_symbol("hipGetDevicePropertiesR0600");
+    /* Only the R0600 revision is usable: callers read the uuid and luid 
fields,
+     * which the R0000 struct does not have. The unversioned 
hipGetDeviceProperties
+     * export still resolves on current runtimes but carries the R0000 layout, 
so
+     * falling back to it would hand back an unrelated LUID.
+     */
+    g_device_get_properties =
+        
(PFN_deviceGetProperties)aimdo_hip_resolve_symbol("hipGetDevicePropertiesR0600");
     if (!g_device_get_properties) {
-        g_device_get_properties = 
(PFN_deviceGetProperties)aimdo_hip_resolve_symbol("hipGetDeviceProperties");
+        log(WARNING, "%s: hipGetDevicePropertiesR0600 unavailable\n", 
__func__);
     }
 
     {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/comfy-aimdo-0.5.2/src-win/shmem-detect.c 
new/comfy-aimdo-0.5.3/src-win/shmem-detect.c
--- old/comfy-aimdo-0.5.2/src-win/shmem-detect.c        2026-09-05 
00:25:48.000000000 +0200
+++ new/comfy-aimdo-0.5.3/src-win/shmem-detect.c        2026-09-08 
12:59:20.000000000 +0200
@@ -91,7 +91,7 @@
     if (factory) {
         factory->lpVtbl->Release(factory);
     }
-    log(WARNING, "comfy-aimdo WDDM init failed (%d). aimdo is blind to the 
CUDA Sysmem Fallback Policy\n", fail_code);
+    log(WARNING, "comfy-aimdo WDDM init failed (%d). aimdo is blind to the 
driver sysmem fallback policy\n", fail_code);
     return false;
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/comfy-aimdo-0.5.2/tests/init-devices-twice-cuda.py 
new/comfy-aimdo-0.5.3/tests/init-devices-twice-cuda.py
--- old/comfy-aimdo-0.5.2/tests/init-devices-twice-cuda.py      1970-01-01 
01:00:00.000000000 +0100
+++ new/comfy-aimdo-0.5.3/tests/init-devices-twice-cuda.py      2026-09-08 
12:59:20.000000000 +0200
@@ -0,0 +1,19 @@
+# A second init_devices() must be refused, not reinstall the CUDA hooks over
+# the live ones and crash the next allocation.
+import comfy_aimdo.control as aimdo
+import torch
+
+
+assert aimdo.init("cuda")
+device = torch.cuda.current_device()
+assert aimdo.init_device(device)
+assert not aimdo.init_device(device)
+
+x = torch.empty(64 * 1024 * 1024, dtype=torch.uint8, device="cuda")
+x.fill_(1)
+torch.cuda.synchronize()
+assert x[-1].item() == 1
+assert aimdo.get_total_vram_usage() > 0
+del x
+aimdo.deinit()
+print("init_devices twice test passed")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/comfy-aimdo-0.5.2/tests/malloc-graph-abort-cuda.py 
new/comfy-aimdo-0.5.3/tests/malloc-graph-abort-cuda.py
--- old/comfy-aimdo-0.5.2/tests/malloc-graph-abort-cuda.py      2026-09-05 
00:25:48.000000000 +0200
+++ new/comfy-aimdo-0.5.3/tests/malloc-graph-abort-cuda.py      2026-09-08 
12:59:20.000000000 +0200
@@ -21,6 +21,7 @@
 nested.fill_(23)
 graph.abort()
 graph.abort()
+assert graph.rogue_count == 2
 del graph
 gc.collect()
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/comfy-aimdo-0.5.2/tests/malloc-graph-free-external-cuda.py 
new/comfy-aimdo-0.5.3/tests/malloc-graph-free-external-cuda.py
--- old/comfy-aimdo-0.5.2/tests/malloc-graph-free-external-cuda.py      
2026-09-05 00:25:48.000000000 +0200
+++ new/comfy-aimdo-0.5.3/tests/malloc-graph-free-external-cuda.py      
2026-09-08 12:59:20.000000000 +0200
@@ -1,24 +1,20 @@
-import os
-
 import comfy_aimdo.control as aimdo
 import torch
 
 
 M = 1024 * 1024
-ERROR = "aimdo memory compile error"
 
 assert aimdo.init("cuda")
 assert aimdo.init_device(torch.cuda.current_device())
 torch.empty(1, device="cuda")
 
-value = torch.empty(8 * M, dtype=torch.uint8, device="cuda")
 graph = aimdo.record(torch.cuda.current_stream())
+graph.pause()
+value = torch.empty(8 * M, dtype=torch.uint8, device="cuda")
+graph.resume()
 del value
+assert not graph.pop()
 
-try:
-    graph.pop()
-except RuntimeError as error:
-    assert ERROR in str(error)
-    print(f"Free external allocation: {error}", flush=True)
-    os._exit(0)
-raise AssertionError(f"freeing an external allocation did not raise {ERROR}")
+graph.push()
+assert not graph.pop()
+print("CUDA malloc graph external free test passed")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/comfy-aimdo-0.5.2/tests/malloc-graph-free-external-subgraph-cuda.py 
new/comfy-aimdo-0.5.3/tests/malloc-graph-free-external-subgraph-cuda.py
--- old/comfy-aimdo-0.5.2/tests/malloc-graph-free-external-subgraph-cuda.py     
2026-09-05 00:25:48.000000000 +0200
+++ new/comfy-aimdo-0.5.3/tests/malloc-graph-free-external-subgraph-cuda.py     
2026-09-08 12:59:20.000000000 +0200
@@ -1,11 +1,8 @@
-import os
-
 import comfy_aimdo.control as aimdo
 import torch
 
 
 M = 1024 * 1024
-ERROR = "aimdo memory compile error"
 
 assert aimdo.init("cuda")
 assert aimdo.init_device(torch.cuda.current_device())
@@ -15,11 +12,11 @@
 graph = aimdo.record(torch.cuda.current_stream())
 graph.push("inner")
 del value
+assert not graph.pop()
+assert not graph.pop()
 
-try:
-    graph.pop()
-except RuntimeError as error:
-    assert ERROR in str(error)
-    print(f"Free external allocation in subgraph: {error}", flush=True)
-    os._exit(0)
-raise AssertionError(f"freeing an external allocation in a subgraph did not 
raise {ERROR}")
+graph.push()
+graph.push("inner")
+assert not graph.pop()
+assert not graph.pop()
+print("CUDA malloc graph external free subgraph test passed")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/comfy-aimdo-0.5.2/tests/malloc-graph-leak-cuda.py 
new/comfy-aimdo-0.5.3/tests/malloc-graph-leak-cuda.py
--- old/comfy-aimdo-0.5.2/tests/malloc-graph-leak-cuda.py       2026-09-05 
00:25:48.000000000 +0200
+++ new/comfy-aimdo-0.5.3/tests/malloc-graph-leak-cuda.py       2026-09-08 
12:59:20.000000000 +0200
@@ -16,6 +16,7 @@
 pointer = value.data_ptr()
 value.fill_(17)
 graph.pop()
+assert graph.rogue_count == 1
 
 graph.push()
 replacement = torch.empty(8 * M, dtype=torch.uint8, device="cuda")
@@ -23,6 +24,7 @@
 replacement.fill_(23)
 del replacement
 graph.pop()
+assert graph.rogue_count == 1
 assert value[0].item() == 17
 
 del graph
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/comfy-aimdo-0.5.2/tests/malloc-graph-small-rogue-cuda.py 
new/comfy-aimdo-0.5.3/tests/malloc-graph-small-rogue-cuda.py
--- old/comfy-aimdo-0.5.2/tests/malloc-graph-small-rogue-cuda.py        
2026-09-05 00:25:48.000000000 +0200
+++ new/comfy-aimdo-0.5.3/tests/malloc-graph-small-rogue-cuda.py        
2026-09-08 12:59:20.000000000 +0200
@@ -17,6 +17,7 @@
 first.fill_(41)
 second.fill_(42)
 graph.pop()
+assert graph.rogue_count == 2
 
 graph.push()
 replacement_first = torch.empty(M, dtype=torch.uint8, device="cuda")
@@ -25,6 +26,7 @@
 assert replacement_second.data_ptr() not in pointers
 del replacement_first, replacement_second
 graph.pop()
+assert graph.rogue_count == 2
 
 del graph
 gc.collect()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/comfy-aimdo-0.5.2/tests/simple-vram-headroom-runtime-cuda.py 
new/comfy-aimdo-0.5.3/tests/simple-vram-headroom-runtime-cuda.py
--- old/comfy-aimdo-0.5.2/tests/simple-vram-headroom-runtime-cuda.py    
1970-01-01 01:00:00.000000000 +0100
+++ new/comfy-aimdo-0.5.3/tests/simple-vram-headroom-runtime-cuda.py    
2026-09-08 12:59:20.000000000 +0200
@@ -0,0 +1,81 @@
+# A simple_vram_headroom set after init_devices() steers the next VBAR fault.
+# The model is a quarter of VRAM; the runtime headroom leaves room for half.
+import gc
+import os
+
+os.environ.setdefault("PYTORCH_ALLOC_CONF", "backend:cudaMallocAsync")
+
+import comfy_aimdo.control as aimdo
+import torch
+
+
+M = 1024 * 1024
+PAGE = 32 * M
+CHUNK = 128 * M
+DEFAULT_HEADROOM = 256 * M
+
+assert aimdo.init("cuda")
+import comfy_aimdo.torch  # noqa: E402
+from comfy_aimdo.model_vbar import ModelVBAR, vbar_fault, vbar_unpin  # noqa: 
E402
+
+device = torch.cuda.current_device()
+assert aimdo.init_device(device)
+torch.empty(1, device="cuda")
+cuda_device = torch.device("cuda", device)
+
+free, capacity = torch.cuda.mem_get_info(device)
+model = capacity // 4
+model -= model % CHUNK
+chunks = model // CHUNK
+
+vbar = ModelVBAR(model * 10, device)
+vbar.prioritize()
+allocs = [vbar.alloc(CHUNK) for _ in range(chunks)]
+
+
+def forward(fill=None):
+    faulted = 0
+    for alloc in allocs:
+        if vbar_fault(alloc) is None:
+            continue
+        if fill is not None:
+            comfy_aimdo.torch.aimdo_to_tensor(alloc, cuda_device).fill_(fill)
+        vbar_unpin(alloc)
+        faulted += 1
+    torch.cuda.synchronize()
+    return faulted
+
+
+forward(1)
+assert vbar.loaded_size() == model
+
+free_now, _ = torch.cuda.mem_get_info(device)
+headroom = free_now + aimdo.get_total_vram_usage() - model // 2
+budget = capacity - headroom
+aimdo.set_simple_vram_headroom(headroom)
+assert aimdo.get_simple_vram_headroom() == headroom
+
+faulted = forward()
+pressed = vbar.loaded_size()
+assert faulted < chunks
+assert pressed <= budget + PAGE
+assert pressed < model * 0.9
+
+spill = torch.empty(min(model // 4, budget // 2), dtype=torch.uint8, 
device=cuda_device)
+torch.cuda.synchronize()
+forward()
+assert vbar.loaded_size() <= pressed - spill.numel() + 2 * PAGE
+del spill
+torch.cuda.empty_cache()
+
+aimdo.set_simple_vram_headroom(DEFAULT_HEADROOM)
+vbar.prioritize()
+forward()
+assert vbar.loaded_size() == model
+
+del allocs
+del vbar
+gc.collect()
+torch.cuda.synchronize()
+aimdo.deinit()
+print("simple_vram_headroom runtime test passed")

++++++ comfy-aimdo-detect-vendor-without-local-version.patch ++++++
--- /var/tmp/diff_new_pack.CaL1LY/_old  2026-09-11 18:05:51.843202550 +0200
+++ /var/tmp/diff_new_pack.CaL1LY/_new  2026-09-11 18:05:51.848202759 +0200
@@ -1,21 +1,11 @@
-Detect the PyTorch flavour properly, and stay quiet when there is none.
+Stay quiet when PyTorch has no accelerator, instead of guessing CUDA.
 
-detect_vendor() decides which native allocator to load by looking for the
-substrings "+cu" and "+rocm" in torch.__version__. Those only appear when
-PyTorch carries a local version label, which is how the upstream wheels are
-built but not how a distribution builds it: openSUSE's PyTorch reports a plain
-"2.12.0a0". The very version.py that detect_vendor() executes also defines the
-authoritative "cuda" and "hip" attributes, so read those first and keep the
-substring test as a fallback. This half matched Comfy-Org/comfy-aimdo#84, which
-upstream closed without merging, so the patch stays downstream.
-
-When neither is set, PyTorch genuinely has no CUDA and no ROCm support, and
-there is no allocator that could be loaded. init() previously logged
+When detect_vendor() finds neither CUDA nor ROCm support, init() logged
 
     Could not autodetect AIMDO implementation, assuming Nvidia
 
-at warning level and then went on to guess "cuda", which only picked which of
-the two .so names to try before failing to open it a moment later. On a
+at warning level and then went on to guess "cuda", which only picked which
+of the two .so names to try before failing to open it a moment later. On a
 distribution build of PyTorch that warning is printed on every single start,
 for every user, whatever hardware they have, and it invites the reading that
 the wrong GPU vendor was selected. Return False instead, with an informational
@@ -23,44 +13,23 @@
 this path once the CDLL fails, and its callers check the return value, so
 nothing downstream changes.
 
---- comfy-aimdo-0.4.14.orig/comfy_aimdo/control.py
-+++ comfy-aimdo-0.4.14/comfy_aimdo/control.py
-@@ -28,6 +28,8 @@
- 
- def detect_vendor():
-     version = ""
-+    cuda = None
-+    hip = None
-     try:
-         torch_spec = importlib.util.find_spec("torch")
-         for folder in torch_spec.submodule_search_locations:
-@@ -37,10 +39,16 @@
-                 module = importlib.util.module_from_spec(spec)
-                 spec.loader.exec_module(module)
-                 version = module.__version__
-+                cuda = getattr(module, "cuda", None)
-+                hip = getattr(module, "hip", None)
-     except Exception as e:
-         logging.warning("Failed to detect Torch version")
-         pass
- 
-+    if hip:
-+        return "rocm"
-+    if cuda:
-+        return "cuda"
-     if '+cu' in version:
-         return "cuda"
-     if '+rocm' in version:
-@@ -61,8 +69,9 @@
+The other half of the original downstream patch (reading torch.version's
+cuda/hip attributes before the wheel-only version suffix) is upstream since
+0.5.3 ("control: prefer torch.version.hip over the local version segment"),
+so only this hunk remains.
+
+--- comfy-aimdo-0.5.3.orig/comfy_aimdo/control.py
++++ comfy-aimdo-0.5.3/comfy_aimdo/control.py
+@@ -72,8 +72,9 @@
          implementation = detect_vendor()
- 
+
      if implementation is None:
 -        logging.warning("Could not autodetect AIMDO implementation, assuming 
Nvidia")
 -        implementation = "cuda"
 +        logging.info("comfy-aimdo: this PyTorch reports neither CUDA nor 
ROCm, "
 +                     "DynamicVRAM stays disabled")
 +        return False
- 
+
      impl = {
          "cuda": "aimdo",
 

Reply via email to