"""Blender GPU preferences setup for native animation render (-a). Called as: blender --background scene.blend --python turntable_gpu_setup.py -a Reads the intended cycles_device from the scene custom property set by turntable_setup.py, then applies the matching GPU compute device preferences. GPU preferences are user-level and not stored in .blend, so they must be re-applied at render time. After this script runs, Blender processes -a and renders all animation frames natively — keeping the GPU scene (BVH, textures) loaded across all frames. """ import bpy scene = bpy.context.scene cycles_device = scene.get("_cycles_device", "gpu") denoiser_override = scene.get("_denoiser_override", "") if scene.render.engine != 'CYCLES': # EEVEE or other engine — no Cycles GPU preferences needed print(f"[turntable_gpu] engine={scene.render.engine} — no Cycles GPU setup needed") elif cycles_device == "cpu": scene.cycles.device = 'CPU' print("[turntable_gpu] Using CPU (explicit override)") else: gpu_found = False try: cycles_prefs = bpy.context.preferences.addons['cycles'].preferences for device_type in ('OPTIX', 'CUDA', 'HIP', 'ONEAPI'): try: cycles_prefs.compute_device_type = device_type cycles_prefs.get_devices() gpu_devs = [d for d in cycles_prefs.devices if d.type != 'CPU'] if gpu_devs: for d in gpu_devs: d.use = True scene.cycles.device = 'GPU' gpu_found = True # OptiX denoiser is fully GPU-native and faster than OIDN on NVIDIA. # Fall back to OIDN (also GPU-accelerated) on CUDA/HIP. if not denoiser_override: if device_type == 'OPTIX': try: scene.cycles.denoiser = 'OPTIX' print("[turntable_gpu] OptiX denoiser active (GPU-native)") except Exception: pass # Keep OIDN else: try: scene.cycles.denoiser = denoiser_override print(f"[turntable_gpu] Denoiser override: {denoiser_override}") except Exception: pass # Blender 4.x+: explicitly route OIDN through GPU path try: scene.cycles.denoising_use_gpu = True except AttributeError: pass # Older Blender — OIDN uses GPU automatically when device=GPU print(f"[turntable_gpu] Cycles GPU ({device_type}) — rendering {scene.frame_end - scene.frame_start + 1} frames") break except Exception: continue except Exception: pass if not gpu_found: scene.cycles.device = 'CPU' print("[turntable_gpu] WARNING: GPU not found — falling back to CPU") print(f"[turntable_gpu] Output: {scene.render.filepath}#### (frames {scene.frame_start}–{scene.frame_end})")