// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved. // See the file LICENSE for licensing terms. package config import ( "fmt" "runtime" "sync" ) // GPUConfig holds GPU acceleration configuration. type GPUConfig struct { // Enabled controls whether GPU acceleration is used Enabled bool // Backend specifies which GPU backend to use: "auto", "metal", "cuda", "cpu" Backend string // DeviceIndex specifies which GPU device to use when multiple are available DeviceIndex int // LogLevel sets the GPU subsystem log level: "debug", "info", "warn", "error" LogLevel string } // DefaultGPUConfig returns the default GPU configuration. func DefaultGPUConfig() GPUConfig { return GPUConfig{ Enabled: true, Backend: "auto", DeviceIndex: 0, LogLevel: "warn", } } // Validate checks that the GPU configuration is valid. func (c GPUConfig) Validate() error { switch c.Backend { case "auto", "metal", "cuda", "cpu": // Valid backends default: return fmt.Errorf("invalid GPU backend %q: must be auto, metal, cuda, or cpu", c.Backend) } // Validate backend is supported on current platform if c.Backend == "metal" && runtime.GOOS != "darwin" { return fmt.Errorf("metal backend is only supported on macOS") } if c.Backend == "cuda" && runtime.GOOS == "darwin" { return fmt.Errorf("cuda backend is not supported on macOS") } if c.DeviceIndex < 0 { return fmt.Errorf("GPU device index must be non-negative") } switch c.LogLevel { case "debug", "info", "warn", "error": // Valid log levels default: return fmt.Errorf("invalid GPU log level %q: must be debug, info, warn, or error", c.LogLevel) } return nil } // ResolveBackend returns the actual backend to use based on configuration. // If Backend is "auto", it detects the best available backend. func (c GPUConfig) ResolveBackend() string { if !c.Enabled { return "cpu" } if c.Backend != "auto" { return c.Backend } // Auto-detect based on platform switch runtime.GOOS { case "darwin": return "metal" case "linux": return "cuda" default: return "cpu" } } // Global GPU configuration (set during node initialization) var ( globalGPUConfig GPUConfig globalGPUConfigOnce sync.Once globalGPUConfigSet bool ) // SetGlobalGPUConfig sets the global GPU configuration. // This should be called once during node initialization before any GPU accelerators are created. func SetGlobalGPUConfig(cfg GPUConfig) error { var setErr error globalGPUConfigOnce.Do(func() { if err := cfg.Validate(); err != nil { setErr = err return } globalGPUConfig = cfg globalGPUConfigSet = true }) return setErr } // GetGlobalGPUConfig returns the global GPU configuration. // If not set, returns the default configuration. func GetGlobalGPUConfig() GPUConfig { if !globalGPUConfigSet { return DefaultGPUConfig() } return globalGPUConfig } // IsGPUEnabled returns whether GPU acceleration is enabled globally. func IsGPUEnabled() bool { return GetGlobalGPUConfig().Enabled } // GPUBackend returns the configured GPU backend. func GPUBackend() string { return GetGlobalGPUConfig().ResolveBackend() }