Skip to content
Merged
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -81,5 +81,8 @@ uv.lock
# Examples
/examples/

# Custom
/custom/

# ROCmRoll
rocmroll.ini
63 changes: 59 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,17 +112,72 @@ If more than one ready instance exists, `instance launch` can run without `--nam
.\rocmroll.bat launch
```

## Custom Resources

ROCmRoll supports per-instance resource overlays in the `custom\` folder at the repository root. Files placed there are loaded after the global manifests and do not require editing any source file.

### Layout

```text
custom\
<instanceName>\
requirements.txt Optional extra pip packages for this instance
custom_nodes.json Optional extra custom nodes for this instance
```

### Custom requirements

Place a standard `requirements.txt` in `custom\<instanceName>\`:

```text
custom\rocm-stable\requirements.txt
```

ROCmRoll installs it after ComfyUI's own `requirements.txt` using the same pip cache and upgrade strategy. A non-zero pip exit code is a fatal error and reports `ROCMROLL-COMFY-005`.

This file is picked up by every code path that runs ComfyUI dependency installation:

- `instance install`
- `comfyui requirements`
- `instance update --comfyui`
- `instance repair --comfyui`

### Custom nodes

Place a `custom_nodes.json` in `custom\<instanceName>\` using the same format as `source\manifests\custom-nodes.json`:

```json
{
"default": [
{
"name": "MyCustomNode",
"repo": "https://github.com/user/MyCustomNode.git",
"ref": "main",
"installRequirements": true
}
]
}
```

ROCmRoll clones and configures these nodes after the default manifest nodes. Clone failures are non-fatal warnings. The list is processed by every code path that handles custom nodes:

- `instance install`
- `comfyui nodes --install` / `--update`
- `instance repair --custom-nodes`

The `custom\` folder is root-relative and is not user-configurable in `rocmroll.ini`.

## Channels

Channels are defined in `source\manifests\channels.json`.

| Channel | ComfyUI ref | ROCm source | Default profile | Notes |
| --- | --- | --- | --- | --- |
| `stable` | `v0.24.0` | AMD ROCm 7.2.1 direct URLs | `stable` | Pinned ROCmRoll baseline; Python 3.12 required |
| `stable` | `v0.26.0` | AMD ROCm 7.2.1 direct URLs | `stable` | Pinned ROCmRoll baseline; Python 3.12 required |
| `preview` | `master` | `https://rocm.nightlies.amd.com/v2/<rocmIndex>/` | `optimized` | Promoted nightly index |
| `nightly` | `master` | `https://rocm.nightlies.amd.com/v2-staging/<rocmIndex>/` | `optimized` | Cutting-edge staging index |
| `rdna1` | `v0.24.0` | `https://rocm.nightlies.amd.com/v2/<rocmIndex>/` | `stable` | Experimental RDNA 1 support |
| `rdna2` | `v0.24.0` | `https://rocm.nightlies.amd.com/v2-staging/<rocmIndex>/` | `stable` | Experimental RDNA 2 support |
| `rdna1` | `v0.26.0` | `https://rocm.nightlies.amd.com/v2/<rocmIndex>/` | `stable` | Experimental RDNA 1 support |
| `rdna2` | `v0.26.0` | `https://rocm.nightlies.amd.com/v2-staging/<rocmIndex>/` | `stable` | Experimental RDNA 2 support |

Stable currently installs:

Expand Down Expand Up @@ -533,7 +588,7 @@ The full install applies the `rocm-performance` profile from `source\manifests\p

Current performance packages:

- `triton-windows==3.7.0.post26`
- `triton-windows==3.7.1.post27`
- `sageattention==1.0.6`
- `bitsandbytes` from a release wheel URL
- `flash-attn` from a release wheel URL
Expand Down
33 changes: 29 additions & 4 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,31 @@ patch
help
```

## Custom Resources Overlay

ROCmRoll supports per-instance resource overlays in a `custom\` folder at the repository root. The folder is root-relative and not user-configurable via `rocmroll.ini`, following the same convention as `workspaces\`.

### Layout

```text
custom\
<instanceName>\
requirements.txt Extra pip packages installed after ComfyUI requirements
custom_nodes.json Extra custom nodes installed after the default manifest
```

### Custom requirements

`Invoke-InstallComfyDeps` (in `RocmRoll.ComfyUI`) checks for `custom\<instanceName>\requirements.txt` after installing ComfyUI's own `requirements.txt` and `manager_requirements.txt`. If the file exists it is installed with `pip install --upgrade-strategy only-if-needed -r <file>` using the shared pip cache. A failed install raises `ROCMROLL-COMFY-005`.

Because the custom requirements block lives inside `Invoke-InstallComfyDeps` it is automatically executed by all call sites: full install, `comfyui requirements`, `instance update --comfyui`, and `instance repair --comfyui`.

### Custom nodes

`Invoke-InstallCustomNodes` (in `RocmRoll.CustomNodes`) checks for `custom\<instanceName>\custom_nodes.json` after processing the global manifest. The file uses the same JSON schema (`{ "default": [ { name, repo, ref, installRequirements } ] }`). Each entry is processed by the shared `Invoke-ProcessNodeEntry` helper that handles clone, update, and requirements installation. Clone failures are non-fatal warnings.

Because the custom nodes block lives inside `Invoke-InstallCustomNodes` it is automatically executed by all call sites: full install, `comfyui nodes --install`, `comfyui nodes --update`, and `instance repair --custom-nodes`.

## Install Pipeline

`RocmRoll.Core.Invoke-FullInstall` is the high-level install pipeline. It is idempotent where practical and is protected by an instance lock.
Expand Down Expand Up @@ -194,11 +219,11 @@ Channels live in `source\manifests\channels.json`.

| Channel | ComfyUI ref | ROCm source | Default profile | Notes |
| --- | --- | --- | --- | --- |
| `stable` | `v0.24.0` | AMD ROCm 7.2.1 direct URLs | `stable` | Pinned release wheels tagged `cp312`; requires Python 3.12 |
| `stable` | `v0.26.0` | AMD ROCm 7.2.1 direct URLs | `stable` | Pinned release wheels tagged `cp312`; requires Python 3.12 |
| `preview` | `master` | `https://rocm.nightlies.amd.com/v2/<rocmIndex>/` | `optimized` | Promoted nightly index |
| `nightly` | `master` | `https://rocm.nightlies.amd.com/v2-staging/<rocmIndex>/` | `optimized` | Most volatile staging index |
| `rdna1` | `v0.24.0` | `https://rocm.nightlies.amd.com/v2/<rocmIndex>/` | `stable` | Experimental RDNA 1 support, no torch/ROCm `--pre` |
| `rdna2` | `v0.24.0` | `https://rocm.nightlies.amd.com/v2-staging/<rocmIndex>/` | `stable` | Experimental RDNA 2 support, torch uses `--pre` |
| `rdna1` | `v0.26.0` | `https://rocm.nightlies.amd.com/v2/<rocmIndex>/` | `stable` | Experimental RDNA 1 support, no torch/ROCm `--pre` |
| `rdna2` | `v0.26.0` | `https://rocm.nightlies.amd.com/v2-staging/<rocmIndex>/` | `stable` | Experimental RDNA 2 support, torch uses `--pre` |

`RocmRoll.Rocm.Resolve-RocmInstallPlan` handles the difference between direct URL installs and index-based installs:

Expand Down Expand Up @@ -292,7 +317,7 @@ Current default nodes:

Performance packages are defined in `source\manifests\package-profiles.json`. The full install applies `rocm-performance`, which currently contains:

- `triton-windows==3.7.0.post26`
- `triton-windows==3.7.1.post27`
- `sageattention==1.0.6`
- `bitsandbytes` from a release wheel URL, skipped on `gfx90X`, `gfx94X`, and `gfx950`
- `flash-attn` from a release wheel URL
Expand Down
43 changes: 43 additions & 0 deletions profiles/flash-attention.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"name": "flash-attention",
"description": "Full ROCm performance profile. Enables Flash-Attention Triton backend, MIOpen kernel search, SageAttention, and dynamic VRAM. Disables smart memory and pinned memory for better AMD GPU performance. Default for the nightly channel.",
"version": "1.0",
"defaultForChannels": ["nightly"],
"env": {
"COMFYUI_ENABLE_MIOPEN": "0",
"FLASH_ATTENTION_TRITON_AMD_ENABLE": "TRUE",
"FLASH_ATTENTION_TRITON_AMD_AUTOTUNE": "FALSE",
"MIOPEN_FIND_ENFORCE": "1",
"MIOPEN_FIND_MODE": "2",
"MIOPEN_DEBUG_DISABLE_FIND_DB": "0",
"MIOPEN_SEARCH_CUTOFF": "1",
"MIOPEN_ENABLE_LOGGING": "0",
"MIOPEN_LOG_LEVEL": "0",
"MIOPEN_ENABLE_LOGGING_CMD": "0",
"TRITON_PRINT_AUTOTUNING": "0",
"TRITON_CACHE_AUTOTUNING": "0",
"PYTHONUNBUFFERED": "1",
"PYTHONIOENCODING": "utf-8",
"PYTHONUTF8": "1"
},
"launchArgs": [
"--disable-api-nodes",
"--disable-smart-memory",
"--disable-pinned-memory",
"--preview-method", "auto",
"--use-flash-attention",
"--enable-manager",
"--enable-manager-legacy-ui",
"--enable-dynamic-vram"
],
"legacyGpuOverrides": {
"env": {
"TORCH_BACKENDS_CUDA_FLASH_SDP_ENABLED": "0",
"TORCH_BACKENDS_CUDA_MEM_EFF_SDP_ENABLED": "0",
"TORCH_BACKENDS_CUDA_MATH_SDP_ENABLED": "1"
},
"launchArgs": [
"--use-quad-cross-attention"
]
}
}
2 changes: 1 addition & 1 deletion profiles/optimized.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "optimized",
"description": "Full ROCm performance profile. Enables Flash-Attention Triton backend, MIOpen kernel search, SageAttention, and dynamic VRAM. Disables smart memory and pinned memory for better AMD GPU performance. Default for the nightly channel.",
"description": "Full ROCm performance profile. Enables Sage-Attention Triton backend, MIOpen kernel search, SageAttention, and dynamic VRAM. Disables smart memory and pinned memory for better AMD GPU performance. Default for the nightly channel.",
"version": "1.0",
"defaultForChannels": ["nightly"],
"env": {
Expand Down
43 changes: 43 additions & 0 deletions profiles/sage-attention.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"name": "sage-attention",
"description": "Full ROCm performance profile. Enables Sage Attention Triton backend, MIOpen kernel search, SageAttention, and dynamic VRAM. Disables smart memory and pinned memory for better AMD GPU performance. Default for the nightly channel.",
"version": "1.0",
"defaultForChannels": ["nightly"],
"env": {
"COMFYUI_ENABLE_MIOPEN": "0",
"FLASH_ATTENTION_TRITON_AMD_ENABLE": "TRUE",
"FLASH_ATTENTION_TRITON_AMD_AUTOTUNE": "TRUE",
"MIOPEN_FIND_ENFORCE": "1",
"MIOPEN_FIND_MODE": "2",
"MIOPEN_DEBUG_DISABLE_FIND_DB": "0",
"MIOPEN_SEARCH_CUTOFF": "1",
"MIOPEN_ENABLE_LOGGING": "0",
"MIOPEN_LOG_LEVEL": "0",
"MIOPEN_ENABLE_LOGGING_CMD": "0",
"TRITON_PRINT_AUTOTUNING": "0",
"TRITON_CACHE_AUTOTUNING": "0",
"PYTHONUNBUFFERED": "1",
"PYTHONIOENCODING": "utf-8",
"PYTHONUTF8": "1"
},
"launchArgs": [
"--disable-api-nodes",
"--disable-smart-memory",
"--disable-pinned-memory",
"--preview-method", "auto",
"--use-sage-attention",
"--enable-manager",
"--enable-manager-legacy-ui",
"--enable-dynamic-vram"
],
"legacyGpuOverrides": {
"env": {
"TORCH_BACKENDS_CUDA_FLASH_SDP_ENABLED": "0",
"TORCH_BACKENDS_CUDA_MEM_EFF_SDP_ENABLED": "0",
"TORCH_BACKENDS_CUDA_MATH_SDP_ENABLED": "1"
},
"launchArgs": [
"--use-quad-cross-attention"
]
}
}
16 changes: 8 additions & 8 deletions source/manifests/channels.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"comfyui": {
"source": "git",
"repo": "https://github.com/Comfy-Org/ComfyUI.git",
"ref": "v0.24.0",
"ref": "v0.26.0",
"pinCommit": null
},
"python": {
Expand Down Expand Up @@ -34,7 +34,7 @@
}
},
"packages": {
"tritonWindows": "3.7.0.post26",
"tritonWindows": "3.7.1.post27",
"sageAttention": "1.0.6"
}
},
Expand Down Expand Up @@ -77,7 +77,7 @@
]
},
"packages": {
"tritonWindows": "3.7.0.post26",
"tritonWindows": "3.7.1.post27",
"sageAttention": "1.0.6"
}
},
Expand Down Expand Up @@ -120,7 +120,7 @@
]
},
"packages": {
"tritonWindows": "3.7.0.post26",
"tritonWindows": "3.7.1.post27",
"sageAttention": "1.0.6"
}
},
Expand All @@ -130,7 +130,7 @@
"comfyui": {
"source": "git",
"repo": "https://github.com/Comfy-Org/ComfyUI.git",
"ref": "v0.24.0",
"ref": "v0.26.0",
"pinCommit": null
},
"python": {
Expand Down Expand Up @@ -165,7 +165,7 @@
]
},
"packages": {
"tritonWindows": "3.7.0.post26",
"tritonWindows": "3.7.1.post27",
"sageAttention": "1.0.6"
}
},
Expand All @@ -175,7 +175,7 @@
"comfyui": {
"source": "git",
"repo": "https://github.com/Comfy-Org/ComfyUI.git",
"ref": "v0.24.0",
"ref": "v0.26.0",
"pinCommit": null
},
"python": {
Expand Down Expand Up @@ -210,7 +210,7 @@
]
},
"packages": {
"tritonWindows": "3.7.0.post26",
"tritonWindows": "3.7.1.post27",
"sageAttention": "1.0.6"
}
}
Expand Down
2 changes: 1 addition & 1 deletion source/manifests/package-profiles.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"packages": [
{
"name": "triton-windows",
"version": "3.7.0.post26",
"version": "3.7.1.post27",
"source": "pypi",
"required": true
},
Expand Down
9 changes: 9 additions & 0 deletions source/modules/RocmRoll.ComfyUI.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,15 @@ function Invoke-InstallComfyDeps {
if ($managerPipExitCode -ne 0) { throw "ROCMROLL-COMFY-003: pip install manager_requirements.txt failed (exit $managerPipExitCode)" }
Write-LogSuccess "ComfyUI manager dependencies installed" -Comp 'RocmRoll.ComfyUI'
}

$customReqFile = Join-Path (Join-Path (Join-Path $cfg.RootFolder 'custom') $InstanceName) 'requirements.txt'
if (Test-Path $customReqFile) {
Write-LogInfo "Installing custom requirements from custom\$InstanceName\requirements.txt" -Comp 'RocmRoll.ComfyUI' -Op 'InstallDeps' -Inst $InstanceName
$customPipArgs = @('-m', 'pip', 'install', '--cache-dir', $cfg.PipCacheFolder, '--upgrade-strategy', 'only-if-needed', '-r', $customReqFile)
$customPipExitCode = Invoke-LoggedNativeCommand -FilePath $pythonExe -Arguments $customPipArgs -Comp 'RocmRoll.ComfyUI' -Op 'InstallDeps' -Inst $InstanceName
if ($customPipExitCode -ne 0) { throw "ROCMROLL-COMFY-005: pip install custom requirements.txt failed (exit $customPipExitCode)" }
Write-LogSuccess "Custom requirements installed" -Comp 'RocmRoll.ComfyUI'
}
}

function Invoke-UpdateComfyUIInstance {
Expand Down
2 changes: 1 addition & 1 deletion source/modules/RocmRoll.Core.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ function Invoke-FullInstall {
Import-Module (Join-Path $modDir 'RocmRoll.ComfyDesktop.psm1') -Force -Global

$cfg = Get-Config
$now = (Get-Date).ToString('yyyy-MM-dd')
$now = (Get-Date).ToString('yyyy-MM-dd_HHmmss')

# Logging setup
$logPrefix = Join-Path $cfg.LogsInstallFolder "${now}_${InstanceName}_install"
Expand Down
Loading
Loading