2 Commits

Author SHA1 Message Date
28cb50492c Update jiggablend-runner script to accept additional runner flags
All checks were successful
Release Tag / release (push) Successful in 17s
- Modified the jiggablend-runner script to allow passing extra flags during execution, enhancing flexibility for users.
- Updated usage instructions to reflect the new syntax, providing examples for better clarity on how to utilize the runner with various options.
2026-03-13 21:18:04 -05:00
dc525fbaa4 Add hardware compatibility flags for CPU rendering and HIPRT control
- Introduced `--force-cpu-rendering` and `--disable-hiprt` flags to the runner command, allowing users to enforce CPU rendering and disable HIPRT acceleration.
- Updated the runner initialization and context structures to accommodate the new flags, enhancing flexibility in rendering configurations.
- Modified the rendering logic to respect these flags, improving compatibility and user control over rendering behavior in Blender.
2026-03-13 21:15:44 -05:00
7 changed files with 63 additions and 10 deletions

View File

@@ -154,6 +154,9 @@ bin/jiggablend runner --api-key <your-api-key>
# With custom options # With custom options
bin/jiggablend runner --manager http://localhost:8080 --name my-runner --api-key <key> --log-file runner.log bin/jiggablend runner --manager http://localhost:8080 --name my-runner --api-key <key> --log-file runner.log
# Hardware compatibility flags (force CPU + disable HIPRT)
bin/jiggablend runner --api-key <key> --force-cpu-rendering --disable-hiprt
# Using environment variables # Using environment variables
JIGGABLEND_MANAGER=http://localhost:8080 JIGGABLEND_API_KEY=<key> bin/jiggablend runner JIGGABLEND_MANAGER=http://localhost:8080 JIGGABLEND_API_KEY=<key> bin/jiggablend runner
``` ```

View File

@@ -37,6 +37,8 @@ func init() {
runnerCmd.Flags().String("log-level", "info", "Log level (debug, info, warn, error)") runnerCmd.Flags().String("log-level", "info", "Log level (debug, info, warn, error)")
runnerCmd.Flags().BoolP("verbose", "v", false, "Enable verbose logging (same as --log-level=debug)") runnerCmd.Flags().BoolP("verbose", "v", false, "Enable verbose logging (same as --log-level=debug)")
runnerCmd.Flags().Duration("poll-interval", 5*time.Second, "Job polling interval") runnerCmd.Flags().Duration("poll-interval", 5*time.Second, "Job polling interval")
runnerCmd.Flags().Bool("force-cpu-rendering", false, "Force CPU rendering for all jobs (disables GPU rendering)")
runnerCmd.Flags().Bool("disable-hiprt", false, "Disable HIPRT acceleration in Blender Cycles")
// Bind flags to viper with JIGGABLEND_ prefix // Bind flags to viper with JIGGABLEND_ prefix
runnerViper.SetEnvPrefix("JIGGABLEND") runnerViper.SetEnvPrefix("JIGGABLEND")
@@ -51,6 +53,8 @@ func init() {
runnerViper.BindPFlag("log_level", runnerCmd.Flags().Lookup("log-level")) runnerViper.BindPFlag("log_level", runnerCmd.Flags().Lookup("log-level"))
runnerViper.BindPFlag("verbose", runnerCmd.Flags().Lookup("verbose")) runnerViper.BindPFlag("verbose", runnerCmd.Flags().Lookup("verbose"))
runnerViper.BindPFlag("poll_interval", runnerCmd.Flags().Lookup("poll-interval")) runnerViper.BindPFlag("poll_interval", runnerCmd.Flags().Lookup("poll-interval"))
runnerViper.BindPFlag("force_cpu_rendering", runnerCmd.Flags().Lookup("force-cpu-rendering"))
runnerViper.BindPFlag("disable_hiprt", runnerCmd.Flags().Lookup("disable-hiprt"))
} }
func runRunner(cmd *cobra.Command, args []string) { func runRunner(cmd *cobra.Command, args []string) {
@@ -63,6 +67,8 @@ func runRunner(cmd *cobra.Command, args []string) {
logLevel := runnerViper.GetString("log_level") logLevel := runnerViper.GetString("log_level")
verbose := runnerViper.GetBool("verbose") verbose := runnerViper.GetBool("verbose")
pollInterval := runnerViper.GetDuration("poll_interval") pollInterval := runnerViper.GetDuration("poll_interval")
forceCPURendering := runnerViper.GetBool("force_cpu_rendering")
disableHIPRT := runnerViper.GetBool("disable_hiprt")
var r *runner.Runner var r *runner.Runner
@@ -118,7 +124,7 @@ func runRunner(cmd *cobra.Command, args []string) {
} }
// Create runner // Create runner
r = runner.New(managerURL, name, hostname) r = runner.New(managerURL, name, hostname, forceCPURendering, disableHIPRT)
// Check for required tools early to fail fast // Check for required tools early to fail fast
if err := r.CheckRequiredTools(); err != nil { if err := r.CheckRequiredTools(); err != nil {

View File

@@ -79,17 +79,23 @@ cat << 'EOF' > jiggablend-runner.sh
set -euo pipefail set -euo pipefail
# Wrapper to run jiggablend runner with test setup # Wrapper to run jiggablend runner with test setup
# Usage: jiggablend-runner [MANAGER_URL] # Usage: jiggablend-runner [MANAGER_URL] [RUNNER_FLAGS...]
# Default MANAGER_URL: http://localhost:8080 # Default MANAGER_URL: http://localhost:8080
# Run this in a directory where you want the logs # Run this in a directory where you want the logs
MANAGER_URL="${1:-http://localhost:8080}" MANAGER_URL="http://localhost:8080"
if [[ $# -gt 0 && "$1" != -* ]]; then
MANAGER_URL="$1"
shift
fi
EXTRA_ARGS=("$@")
mkdir -p logs mkdir -p logs
rm -f logs/runner.log rm -f logs/runner.log
# Run runner # Run runner
jiggablend runner -l logs/runner.log --api-key=jk_r0_test_key_123456789012345678901234567890 --manager "$MANAGER_URL" jiggablend runner -l logs/runner.log --api-key=jk_r0_test_key_123456789012345678901234567890 --manager "$MANAGER_URL" "${EXTRA_ARGS[@]}"
EOF EOF
chmod +x jiggablend-runner.sh chmod +x jiggablend-runner.sh
sudo install -m 0755 jiggablend-runner.sh /usr/local/bin/jiggablend-runner sudo install -m 0755 jiggablend-runner.sh /usr/local/bin/jiggablend-runner
@@ -102,5 +108,6 @@ echo "Installation complete!"
echo "Binary: jiggablend" echo "Binary: jiggablend"
echo "Wrappers: jiggablend-manager, jiggablend-runner" echo "Wrappers: jiggablend-manager, jiggablend-runner"
echo "Run 'jiggablend-manager' to start the manager with test config." echo "Run 'jiggablend-manager' to start the manager with test config."
echo "Run 'jiggablend-runner [url]' to start the runner, e.g., jiggablend-runner http://your-manager:8080" echo "Run 'jiggablend-runner [url] [runner flags...]' to start the runner."
echo "Example: jiggablend-runner http://your-manager:8080 --force-cpu-rendering --disable-hiprt"
echo "Note: Depending on whether you're running the manager or runner, additional dependencies like Blender, ImageMagick, or FFmpeg may be required. See the project README for details." echo "Note: Depending on whether you're running the manager or runner, additional dependencies like Blender, ImageMagick, or FFmpeg may be required. See the project README for details."

View File

@@ -54,10 +54,15 @@ type Runner struct {
hasNVIDIA bool hasNVIDIA bool
gpuBackendProbed bool gpuBackendProbed bool
gpuDetectionFailed bool gpuDetectionFailed bool
// forceCPURendering forces CPU rendering for all jobs regardless of metadata/backend detection.
forceCPURendering bool
// disableHIPRT disables HIPRT acceleration when configuring Cycles HIP devices.
disableHIPRT bool
} }
// New creates a new runner. // New creates a new runner.
func New(managerURL, name, hostname string) *Runner { func New(managerURL, name, hostname string, forceCPURendering, disableHIPRT bool) *Runner {
manager := api.NewManagerClient(managerURL) manager := api.NewManagerClient(managerURL)
r := &Runner{ r := &Runner{
@@ -67,6 +72,9 @@ func New(managerURL, name, hostname string) *Runner {
processes: executils.NewProcessTracker(), processes: executils.NewProcessTracker(),
stopChan: make(chan struct{}), stopChan: make(chan struct{}),
processors: make(map[string]tasks.Processor), processors: make(map[string]tasks.Processor),
forceCPURendering: forceCPURendering,
disableHIPRT: disableHIPRT,
} }
// Generate fingerprint // Generate fingerprint
@@ -307,6 +315,8 @@ func (r *Runner) executeJob(job *api.NextJobResponse) (err error) {
r.IsGPULockedOut(), r.IsGPULockedOut(),
r.HasHIP(), r.HasHIP(),
r.GPUDetectionFailed(), r.GPUDetectionFailed(),
r.forceCPURendering,
r.disableHIPRT,
func() { r.SetGPULockedOut(true) }, func() { r.SetGPULockedOut(true) },
) )

View File

@@ -49,6 +49,10 @@ type Context struct {
GPUDetectionFailed bool GPUDetectionFailed bool
// OnGPUError is called when a GPU error line is seen in render logs; typically sets runner GPU lockout. // OnGPUError is called when a GPU error line is seen in render logs; typically sets runner GPU lockout.
OnGPUError func() OnGPUError func()
// ForceCPURendering is a runner-level override that forces CPU rendering for all jobs.
ForceCPURendering bool
// DisableHIPRT is a runner-level override that disables HIPRT acceleration in Blender.
DisableHIPRT bool
} }
// ErrJobCancelled indicates the manager-side job was cancelled during execution. // ErrJobCancelled indicates the manager-side job was cancelled during execution.
@@ -73,6 +77,8 @@ func NewContext(
gpuLockedOut bool, gpuLockedOut bool,
hasHIP bool, hasHIP bool,
gpuDetectionFailed bool, gpuDetectionFailed bool,
forceCPURendering bool,
disableHIPRT bool,
onGPUError func(), onGPUError func(),
) *Context { ) *Context {
if frameEnd < frameStart { if frameEnd < frameStart {
@@ -97,6 +103,8 @@ func NewContext(
GPULockedOut: gpuLockedOut, GPULockedOut: gpuLockedOut,
HasHIP: hasHIP, HasHIP: hasHIP,
GPUDetectionFailed: gpuDetectionFailed, GPUDetectionFailed: gpuDetectionFailed,
ForceCPURendering: forceCPURendering,
DisableHIPRT: disableHIPRT,
OnGPUError: onGPUError, OnGPUError: onGPUError,
} }
} }
@@ -182,6 +190,9 @@ func (c *Context) ShouldEnableExecution() bool {
// (runner GPU lockout, GPU detection failed at startup for any version, metadata force_cpu, // (runner GPU lockout, GPU detection failed at startup for any version, metadata force_cpu,
// or Blender < 4.x when the runner has HIP). // or Blender < 4.x when the runner has HIP).
func (c *Context) ShouldForceCPU() bool { func (c *Context) ShouldForceCPU() bool {
if c.ForceCPURendering {
return true
}
if c.GPULockedOut { if c.GPULockedOut {
return true return true
} }

View File

@@ -107,7 +107,9 @@ func (p *RenderProcessor) Process(ctx *Context) error {
v := ctx.GetBlenderVersion() v := ctx.GetBlenderVersion()
major := parseBlenderMajor(v) major := parseBlenderMajor(v)
isPre4 := v != "" && major >= 0 && major < 4 isPre4 := v != "" && major >= 0 && major < 4
if ctx.GPUDetectionFailed { if ctx.ForceCPURendering {
ctx.Info("Runner compatibility flag is enabled: forcing CPU rendering for this job")
} else if ctx.GPUDetectionFailed {
ctx.Info("GPU backend detection failed at startup—we could not determine whether this machine has HIP (AMD) or NVIDIA GPUs, so rendering will use CPU to avoid compatibility issues") ctx.Info("GPU backend detection failed at startup—we could not determine whether this machine has HIP (AMD) or NVIDIA GPUs, so rendering will use CPU to avoid compatibility issues")
} else if isPre4 && ctx.HasHIP { } else if isPre4 && ctx.HasHIP {
ctx.Info("Blender < 4.x has no official HIP support: using CPU rendering only") ctx.Info("Blender < 4.x has no official HIP support: using CPU rendering only")
@@ -193,6 +195,7 @@ func (p *RenderProcessor) createRenderScript(ctx *Context, renderFormat string)
settingsMap = make(map[string]interface{}) settingsMap = make(map[string]interface{})
} }
settingsMap["force_cpu"] = ctx.ShouldForceCPU() settingsMap["force_cpu"] = ctx.ShouldForceCPU()
settingsMap["disable_hiprt"] = ctx.DisableHIPRT
settingsJSON, err := json.Marshal(settingsMap) settingsJSON, err := json.Marshal(settingsMap)
if err == nil { if err == nil {
if err := os.WriteFile(renderSettingsFilePath, settingsJSON, 0644); err != nil { if err := os.WriteFile(renderSettingsFilePath, settingsJSON, 0644); err != nil {

View File

@@ -175,9 +175,13 @@ if render_settings_override:
if current_engine == 'CYCLES': if current_engine == 'CYCLES':
# Check if CPU rendering is forced # Check if CPU rendering is forced
force_cpu = False force_cpu = False
disable_hiprt = False
if render_settings_override and render_settings_override.get('force_cpu'): if render_settings_override and render_settings_override.get('force_cpu'):
force_cpu = render_settings_override.get('force_cpu', False) force_cpu = render_settings_override.get('force_cpu', False)
print("Force CPU rendering is enabled - skipping GPU detection") print("Force CPU rendering is enabled - skipping GPU detection")
if render_settings_override and render_settings_override.get('disable_hiprt'):
disable_hiprt = render_settings_override.get('disable_hiprt', False)
print("Disable HIPRT flag is enabled")
# Ensure Cycles addon is enabled # Ensure Cycles addon is enabled
try: try:
@@ -321,7 +325,16 @@ if current_engine == 'CYCLES':
try: try:
if best_device_type == 'HIP': if best_device_type == 'HIP':
# HIPRT (HIP Ray Tracing) for AMD GPUs # HIPRT (HIP Ray Tracing) for AMD GPUs
if disable_hiprt:
if hasattr(cycles_prefs, 'use_hiprt'): if hasattr(cycles_prefs, 'use_hiprt'):
cycles_prefs.use_hiprt = False
print(f" Disabled HIPRT (HIP Ray Tracing) via runner compatibility flag")
elif hasattr(scene.cycles, 'use_hiprt'):
scene.cycles.use_hiprt = False
print(f" Disabled HIPRT (HIP Ray Tracing) via runner compatibility flag")
else:
print(f" HIPRT toggle not available on this Blender version")
elif hasattr(cycles_prefs, 'use_hiprt'):
cycles_prefs.use_hiprt = True cycles_prefs.use_hiprt = True
print(f" Enabled HIPRT (HIP Ray Tracing) for faster rendering") print(f" Enabled HIPRT (HIP Ray Tracing) for faster rendering")
elif hasattr(scene.cycles, 'use_hiprt'): elif hasattr(scene.cycles, 'use_hiprt'):