pyrender icon indicating copy to clipboard operation
pyrender copied to clipboard

Is it possible to do offscreen rendering with multithreading or multiprocessing?

Open YufengJin opened this issue 4 years ago • 5 comments

Does anyone have any relevant experience? As I don't want Scenes to interfere with each other due to multithreading and multiprocessing, I created multi OffscreenRenderers running on independent threads. The parts of code show below

import threading
import pyrender
...
# load meshes

fuze_mesh = Mesh.from_trimesh(fuze_trimesh)


# offscreen rendering for multithreading
def offrendering():
    r = OffscreenRenderer(viewpoint_width = 640*2, viewpoint_height = 480*2)
    scene = Scene()

    # add object and camera
    scene.add(fuze_mesh, pose = fuze_pose)
    scene.add(camera, pose = cam_pose)
    color, depth = r.render(scene)


# threadlist
renderList = list()

# 4 threads
for _ in range(4);
    t= threading.Thread(target= offrendering)
    renderList.append(t)
    t.start()

waitthreads = [t.join() for t in renderList]

But it comes up with OpenGL.error.Error - No valid context in thread I know that rendering run on multiple threads, but is it mean that pyrender can't do multithreading rendering? also, I've tried multi-processing rendering and it doesn't work.

I hope some experts can solve the problem. Thanks

YufengJin avatar Sep 02 '21 08:09 YufengJin

This should work with multiprocessing. However, be careful to only import pyrender in the process-specific part.

import os
os.environ["PYOPENGL_PLATFORM"] = "egl"

from multiprocessing import Process

def render_offscreen():
    import pyrender # <-- This is important!
    # Render away ...

processes = []
for _ in range(4):
    process = Process(target=render_offscreen)
    process.start()
    processes.append(process)

for process in processes:
    process.join()

pderoovere avatar May 11 '22 12:05 pderoovere

@pderoovere interestingly I keep getting segfault even I tried this (I'm using joblib to launch multi-process jobs). I verified the call pyrender.OffscreenRenderer is crashing the program. I didn't find anything useful online regarding the issue in joblib context though. Any suggestions? Thanks.

danielyan86129 avatar Jul 15 '22 19:07 danielyan86129

@danielyan86129 Does your program work if you don't use parallel processing? And if you use only 1 job? Anyway, there is not a lot of information here. Can you provide (a simplified version of) your code?

pderoovere avatar Jul 15 '22 21:07 pderoovere

Thanks for the quick reply @pderoovere . In fact my program works if I don't use sharedmem of joblib, and yes it also works with 1 job. I need the shared mem because I have a set maintaining available GPU ids which I assign to process.

It seems that things also work if I use a multiprocessing.Queue to maintain the GPU ids, and turn off joblib's sharedmem. Does that make sense?

danielyan86129 avatar Jul 15 '22 23:07 danielyan86129

It's hard to estimate how using sharedmem interacts with pyrender just from your explanation. Again, it would be easier if you could provide your code. Using a Queue to exchange data between processes does make sense.

pderoovere avatar Jul 29 '22 18:07 pderoovere