blender-render-studio / tests /test_render_modes.py
cpuai's picture
Configure GPU Eevee defaults and verify graphics backends across ZeroGPU sizes
d443689 verified
Raw History Blame Contribute Delete
4.91 kB
import importlib
import os
import sys
from pathlib import Path
import pytest
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from render_config import RenderConfig, parse_config
from blender_runtime import _worker_environment
def test_explicit_cpu_bypasses_zerogpu_even_when_deployment_is_zerogpu(monkeypatch):
import service
monkeypatch.setenv('RENDER_BACKEND', 'zerogpu')
cfg = parse_config('{"device":"CPU"}')
assert (cfg.engine, cfg.device) == ('EEVEE', 'CPU')
assert service._backend(cfg) == 'cpu'
calls = []
monkeypatch.setattr(service, 'run_task', lambda *args: calls.append('cpu') or {'ok': True})
monkeypatch.setattr(service, '_zero_render', lambda *args: pytest.fail('CPU must not allocate a GPU'))
service._execute({}, Path('/tmp'), service._backend(cfg), cfg, Path('/tmp/mode-test.log'))
assert calls == ['cpu']
def test_default_gpu_and_cycles_only_devices_are_validated(monkeypatch):
import service
from spaces.config import Config
monkeypatch.setenv('RENDER_BACKEND', 'auto')
monkeypatch.setattr(Config, 'zero_gpu', True)
assert (RenderConfig().engine, RenderConfig().device) == ('EEVEE', 'AUTO')
assert service._backend(RenderConfig()) == 'zerogpu'
assert service._backend(RenderConfig(engine='CYCLES', device='AUTO')) == 'zerogpu'
assert service._backend(RenderConfig(engine='CYCLES', device='CPU')) == 'cpu'
with pytest.raises(ValueError, match='CUDA / OPTIX'):
RenderConfig(engine='EEVEE', device='CUDA')
def test_software_gl_environment_does_not_leak_into_gpu_jobs(monkeypatch):
monkeypatch.setenv('LIBGL_ALWAYS_SOFTWARE', 'true')
monkeypatch.setenv('GALLIUM_DRIVER', 'llvmpipe')
cpu = _worker_environment({'engine': 'EEVEE', 'device': 'CPU'})
gpu = _worker_environment({'engine': 'EEVEE', 'device': 'AUTO'})
assert cpu['LIBGL_ALWAYS_SOFTWARE'] == 'true'
assert cpu['GALLIUM_DRIVER'] == 'llvmpipe'
assert 'LIBGL_ALWAYS_SOFTWARE' not in gpu
assert 'GALLIUM_DRIVER' not in gpu
@pytest.mark.skipif(not hasattr(os, 'fork'), reason='Linux fork regression')
def test_lock_released_while_forked_worker_still_holds_descriptor(tmp_path):
import service
r, w = os.pipe()
child = None
try:
with service._lock(tmp_path):
child = os.fork()
if child == 0:
os.close(w)
os.read(r, 1)
os._exit(0)
# Child still owns an inherited descriptor, but must not own the lock.
with service._lock(tmp_path):
pass
finally:
if child:
os.write(w, b'x')
os.waitpid(child, 0)
os.close(r)
os.close(w)
def test_legacy_jobs_resume_with_cycles():
import service
assert service._config({'config': {'device': 'AUTO'}}).engine == 'CYCLES'
assert service._config({'config': {'engine': 'EEVEE', 'device': 'CPU'}}).engine == 'EEVEE'
def test_zerogpu_preserves_worker_error_details(monkeypatch):
import service
def failed_worker(*args):
raise RuntimeError('EGL initialization failed: no graphics device')
monkeypatch.setattr(service, 'run_task', failed_worker)
report = service._allocated_render({}, '/tmp/probe.log', '', 30)
assert not report['ok']
assert 'no graphics device' in report['error']
def test_eevee_gpu_probe_is_explicit_and_truthful(monkeypatch):
import service
configs = []
def probe(cfg):
configs.append(cfg)
return {'ok': False, 'gpu_verified': False, 'error': 'No EGL device'}, [], None
monkeypatch.setattr(service, '_self_test', probe)
report, _, _ = service.eevee_gpu_self_test()
assert configs[0].engine == 'EEVEE' and configs[0].device == 'AUTO'
assert not report['gpu_eevee_usable']
assert 'No EGL device' == report['error']
def test_requested_zerogpu_size_routes_exactly_once(monkeypatch):
import service
calls = []
monkeypatch.setattr(service, '_zero_render', lambda *a: calls.append('large') or {'ok': True})
monkeypatch.setattr(service, '_zero_render_xlarge', lambda *a: calls.append('xlarge') or {'ok': True})
for size in ('large', 'xlarge'):
cfg = RenderConfig(gpu_size=size)
service._execute({}, Path('/tmp'), 'zerogpu', cfg, Path('/tmp/probe.log'))
assert calls == ['large', 'xlarge']
def test_graphics_probe_preserves_requested_backend_and_size(monkeypatch):
import service
configs = []
monkeypatch.setattr(service, '_self_test', lambda cfg: (configs.append(cfg) or
{'ok': True, 'gpu_verified': True}, [], None))
report, _, _ = service.eevee_gpu_self_test('xlarge', 'vulkan')
assert configs[0].gpu_size == 'xlarge' and configs[0].graphics_backend == 'vulkan'
assert report['gpu_eevee_usable']
with pytest.raises(ValueError):
RenderConfig(graphics_backend='opengl --python unsafe.py')