Implement GPU backend detection for Blender compatibility
- Added functionality to detect GPU backends (HIP and NVIDIA) during runner registration, enhancing compatibility for Blender versions below 4.x. - Introduced a new method, DetectAndStoreGPUBackends, to download the latest Blender and run a detection script, storing the results for future rendering decisions. - Updated rendering logic to force CPU rendering when HIP is detected on systems with Blender < 4.x, ensuring stability and compatibility. - Enhanced the Context structure to include flags for GPU detection status, improving error handling and rendering decisions based on GPU availability.
This commit is contained in:
@@ -45,6 +45,15 @@ type Runner struct {
|
||||
// when true, the runner forces CPU rendering for all subsequent jobs.
|
||||
gpuLockedOut bool
|
||||
gpuLockedOutMu sync.RWMutex
|
||||
|
||||
// hasHIP/hasNVIDIA are set at startup by running latest Blender to detect GPU backends.
|
||||
// Used to force CPU only for Blender < 4.x when HIP is present (no official HIP support pre-4).
|
||||
// gpuDetectionFailed is true when detection could not run; we then force CPU for all versions (we could not determine HIP vs NVIDIA).
|
||||
gpuBackendMu sync.RWMutex
|
||||
hasHIP bool
|
||||
hasNVIDIA bool
|
||||
gpuBackendProbed bool
|
||||
gpuDetectionFailed bool
|
||||
}
|
||||
|
||||
// New creates a new runner.
|
||||
@@ -124,6 +133,58 @@ func (r *Runner) Register(apiKey string) (int64, error) {
|
||||
return id, nil
|
||||
}
|
||||
|
||||
// DetectAndStoreGPUBackends downloads the latest Blender from the manager (if needed),
|
||||
// runs a detection script to see if HIP (AMD) and/or NVIDIA devices are available,
|
||||
// and stores the result. Call after Register. Used so we only force CPU for Blender < 4.x
|
||||
// when the runner has HIP (no official HIP support pre-4); NVIDIA is allowed.
|
||||
func (r *Runner) DetectAndStoreGPUBackends() {
|
||||
r.gpuBackendMu.Lock()
|
||||
defer r.gpuBackendMu.Unlock()
|
||||
if r.gpuBackendProbed {
|
||||
return
|
||||
}
|
||||
latestVer, err := r.manager.GetLatestBlenderVersion()
|
||||
if err != nil {
|
||||
log.Printf("GPU backend detection failed (could not get latest Blender version: %v). All jobs will use CPU because we could not determine HIP vs NVIDIA.", err)
|
||||
r.gpuBackendProbed = true
|
||||
r.gpuDetectionFailed = true
|
||||
return
|
||||
}
|
||||
binaryPath, err := r.blender.GetBinaryPath(latestVer)
|
||||
if err != nil {
|
||||
log.Printf("GPU backend detection failed (could not get Blender binary: %v). All jobs will use CPU because we could not determine HIP vs NVIDIA.", err)
|
||||
r.gpuBackendProbed = true
|
||||
r.gpuDetectionFailed = true
|
||||
return
|
||||
}
|
||||
hasHIP, hasNVIDIA, err := blender.DetectGPUBackends(binaryPath, r.workspace.BaseDir())
|
||||
if err != nil {
|
||||
log.Printf("GPU backend detection failed (script error: %v). All jobs will use CPU because we could not determine HIP vs NVIDIA.", err)
|
||||
r.gpuBackendProbed = true
|
||||
r.gpuDetectionFailed = true
|
||||
return
|
||||
}
|
||||
r.hasHIP = hasHIP
|
||||
r.hasNVIDIA = hasNVIDIA
|
||||
r.gpuBackendProbed = true
|
||||
r.gpuDetectionFailed = false
|
||||
log.Printf("GPU backend detection: HIP=%v NVIDIA=%v (Blender < 4.x will force CPU only when HIP is present)", hasHIP, hasNVIDIA)
|
||||
}
|
||||
|
||||
// HasHIP returns whether the runner detected HIP (AMD) devices. Used to force CPU for Blender < 4.x only when HIP is present.
|
||||
func (r *Runner) HasHIP() bool {
|
||||
r.gpuBackendMu.RLock()
|
||||
defer r.gpuBackendMu.RUnlock()
|
||||
return r.hasHIP
|
||||
}
|
||||
|
||||
// GPUDetectionFailed returns true when startup GPU backend detection could not run or failed. When true, all jobs use CPU because we could not determine HIP vs NVIDIA.
|
||||
func (r *Runner) GPUDetectionFailed() bool {
|
||||
r.gpuBackendMu.RLock()
|
||||
defer r.gpuBackendMu.RUnlock()
|
||||
return r.gpuDetectionFailed
|
||||
}
|
||||
|
||||
// Start starts the job polling loop.
|
||||
func (r *Runner) Start(pollInterval time.Duration) {
|
||||
log.Printf("Starting job polling loop (interval: %v)", pollInterval)
|
||||
@@ -244,6 +305,8 @@ func (r *Runner) executeJob(job *api.NextJobResponse) (err error) {
|
||||
r.encoder,
|
||||
r.processes,
|
||||
r.IsGPULockedOut(),
|
||||
r.HasHIP(),
|
||||
r.GPUDetectionFailed(),
|
||||
func() { r.SetGPULockedOut(true) },
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user