Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Headless OpenGL rendering #17

Closed
qianyizh opened this issue May 10, 2017 · 35 comments · Fixed by #273
Closed

Headless OpenGL rendering #17

qianyizh opened this issue May 10, 2017 · 35 comments · Fixed by #273
Assignees
Milestone

Comments

@qianyizh
Copy link
Collaborator

This can be useful in scenarios where users want to render a (long) video.
It can also be useful when Open3D is deployed in a remote server and window creation is a problem.

Some information regarding GLFW: glfw/glfw#648

@qianyizh qianyizh self-assigned this May 10, 2017
@syncle
Copy link
Contributor

syncle commented Aug 17, 2017

I am looking into this issue and read some documents.
According to this glfw 3.3 support headless rendering using OSMesa.
The glfw version included in Open3D seems to be 3.1. Can we upgrade glfw for this?

@qianyizh
Copy link
Collaborator Author

Yes.

@syncle
Copy link
Contributor

syncle commented Aug 18, 2017

As we discussed today, glfw 3.3 is not available yet. So we need to find the detour.
I tested following code with one of GCP virtual machine

glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);

but got the error.

GLFW Error: X11: The DISPLAY environment variable is missing
Failed to initialize GLFW
Failed creating OpenGL window.

Basically glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); hides existing window. This method does not working in the environment GLFW cannot make a window.

@qianyizh
Copy link
Collaborator Author

Recently I have the needs for glfw rendering on headless server and have gain some success.
See this:
glfw/glfw#1004

In short, Alexey's email is absolute correct.

First, you need to setup Xorg correctly.
You can check /etc/X11/xorg.conf to see if it is configured headlessly (usually via sudo nvidia-xconfig -a --use-display-device=none).
Stop lightdm and restart Xorg to make sure the correct configuration is running.

Then, if you don't want to specify a GPU, you can just setup the environment variable DISPLAY to :0 and test the OpenGL setup.

export DISPLAY=:0
glxinfo | grep OpenGL

You should see something like:

OpenGL vendor string: NVIDIA Corporation
OpenGL renderer string: TITAN Xp/PCIe/SSE2
OpenGL core profile version string: 4.5.0 NVIDIA 384.90
OpenGL core profile shading language version string: 4.50 NVIDIA
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile
OpenGL core profile extensions:
OpenGL version string: 4.5.0 NVIDIA 384.90
OpenGL shading language version string: 4.50 NVIDIA
OpenGL context flags: (none)
OpenGL profile mask: (none)
OpenGL extensions:
OpenGL ES profile version string: OpenGL ES 3.2 NVIDIA 384.90
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.20
OpenGL ES profile extensions:

If your server has multiple GPUs, you will be able to see multiple copies of the above information.

If you have passed this test, setup the DISPLAY environment variable and try some program with glfwInit(), say

export DISPLAY=:0
./some_program_that_has_glfwinit

There is a risk that you will have this error

glfw.GLFWError: (65544) b'X11: RandR gamma ramp support seems broken'

This is an error of version 3.2 and older. They don't support headless rendering. Since 3.3 (current master) it is supported.
Then everything should be fine.

In addition, if you want to specify GPU, you can use VirtualGL and TurboVNC to mock a display. This is done with the following steps.

First, install VirtualGL and TurboVNC, something like:

sudo dpkg -i virtualgl_xxx.deb
sudo dpkg -i turbovnc_xxx.deb

Then launch vnc server to run glfw.

// These two steps make sure that the right headless Xorg is configured
sudo service lightdm stop
sudo nohup Xorg :0 &

// Launch a vncserver to mock display on :1
// You can change it to :2, :3, ...
/opt/TurboVNC/bin/vncserver :1

// Launch program on :1
export DISPLAY=:1
vglrun -d :0.0 glxinfo
vglrun -d :0.0 <a script that calls glfw>

@qianyizh
Copy link
Collaborator Author

qianyizh commented Dec 4, 2017

Another option is to mimic libigl's tcpviewer.
See this for reference:
https://github.com/libigl/libigl/blob/master/python/tcpviewer.py

Lower priority. Close for now.

@qianyizh qianyizh closed this as completed Dec 4, 2017
@vkoltun
Copy link

vkoltun commented Dec 4, 2017 via email

@qianyizh
Copy link
Collaborator Author

qianyizh commented Dec 4, 2017

Reopen per request.

@qianyizh qianyizh reopened this Dec 4, 2017
@bhack
Copy link

bhack commented Feb 2, 2018

Other than VNC there is also xpra https://xpra.org/trac/wiki/Usage/OpenGL

@rukie
Copy link

rukie commented Feb 23, 2018

As another user, this would be an excellent feature! 👍

@syncle
Copy link
Contributor

syncle commented Mar 2, 2018

Working on this. I am using glfw3.3_dev to avoid hassles.

Edit: my working branch with glfw3.3_dev.

@syncle syncle added this to the v0.2 milestone Mar 19, 2018
@takanokage
Copy link
Contributor

Another approach is to use Docker to create a headless environment for Open3D.
I already have a docker image based on ubuntu 16.04 with xvfb and x11vnc that works. I've also tested one light window manager (ratpoison) but I'm not too happy with it and want to test others. Next I need to test building/running Open3D inside it.

If we need access to the host GPU (NVIDIA) there are already good solutions to get that: NVIDIA-docker and NVIDIA docker images with CUDA and cuDNN.

I've also been looking into using Alpine as the base if the image size is a concern. The Ubuntu image with xvfb and x1vnc gets to about 450MB while the Alpine image to just about 70MB.

@qianyizh
Copy link
Collaborator Author

The purpose is to make Open3D rendering part running on cloud (AWS/GCloud). @syncle can you help test the solution on GCloud?

@syncle
Copy link
Contributor

syncle commented Mar 23, 2018

Sure. I can use a fresh Ubuntu machine running on GCloud. @takanokage, can you elaborate your steps for me? That will be used for documents too.

takanokage added a commit to takanokage/Open3D that referenced this issue Mar 23, 2018
@takanokage
Copy link
Contributor

I will post more once I have it working.
I'm at the point where I can build Open3D inside the docker container. However the verification step after the build fails, for this reason I added issue 241.

@takanokage
Copy link
Contributor

takanokage commented Mar 24, 2018

I got Open3D built and working inside a Docker container.
However I'm getting the same X11: RandR gamma ramp support seems broken error.
Next: I'll check the VirtualGL suggestion by Qianyi.

$ cd ~/Open3D/build/lib/Tutorial/Basic
$ python3 rgbd_redwood.py
press q

Read Redwood dataset
RGBDImage of size 
Color image : 640x480, with 1 channels.
Depth image : 640x480, with 1 channels.
Use numpy.asarray to access buffer data.
GLFW Error: X11: RandR gamma ramp support seems broken
GLFW Error: Linux: Failed to watch for joystick connections in /dev/input: No such file or directory
GLFW Error: Linux: Failed to open joystick device directory /dev/input: No such file or directory

@syncle
Copy link
Contributor

syncle commented Mar 25, 2018

From @qianyizh's post

There is a risk that you will have this error

glfw.GLFWError: (65544) b'X11: RandR gamma ramp support seems broken'

This is an error of version 3.2 and older. They don't support headless rendering. Since 3.3 (current master) it is supported. Then everything should be fine.

It might be good to try Open3D + GLFW3.3_dev solution via

git clone -b headless_rendering https://github.com/syncle/Open3D.git

@takanokage
Copy link
Contributor

takanokage commented Mar 26, 2018

Jaesik, I just tried your branch with glfw 3.3 inside my docker container.
Somehow I'm still getting the same X11: RandR gamma ramp support seems broken error.
I seem to remember you mentioned I need to build with a particular flag, can you tell me what that was again? tx!

@syncle
Copy link
Contributor

syncle commented Mar 26, 2018

Yes. Try it with

cmake -DOpen3D_USE_NATIVE_DEPENDENCY_BUILD=OFF ../src

Edit:
Check out what cmake says. It should say like building glfw from source.

@takanokage
Copy link
Contributor

Thanks!
So that did something:
GLFW Error: OSMesa: Library not found
Failed to create window
[DrawGeometries] Failed creating OpenGL window.

Did you install a special package for this?

@takanokage
Copy link
Contributor

I have headless rendering working inside docker with the master branch of Open3D.
Next I'll be working on the documentation before submitting a pull request.

This was referenced Mar 29, 2018
Closed
@takanokage takanokage mentioned this issue Mar 29, 2018
@takanokage
Copy link
Contributor

Bind mounts (#254)
I propose we make the whole Open3D folder available both inside the docker container and on the host side. In this way we not only gain direct access to the images generated but we also enable developing Open3D on the host side and testing on both host side and docker side of things.

takanokage added a commit to takanokage/Open3D that referenced this issue Mar 29, 2018
…inal without the need to vnc into the docker container.
@takanokage
Copy link
Contributor

Because we moved #254 under #17 I need to postpone the pull request until after I implement/test it.

takanokage added a commit to takanokage/Open3D that referenced this issue Mar 29, 2018
…rn to enable file transfers and code sharing between the container and the host.
@takanokage
Copy link
Contributor

I got headless working together with bind mounting.
Bind mounting was a ton of work and should've been an independent pull request.

@takanokage
Copy link
Contributor

takanokage commented Mar 29, 2018

Usage notes:

  1. clone my branch
  2. $ cd <Open3D path>/utilities/docker/ubuntu-xvfb/tools
  3. $ ./build.sh to build the image
  4. $ ./attach.sh to clone/build the master Open3D repo and start the Open3D container
  5. $ ./headless_sample.sh to run the sample that renders some images and saves them to disk.
    The sample will render some images which can be accessed on the host at ~/Open3D_docker. These files don't go away if the container is stopped.

Notes:

  • the sample will not return. Ctrl+c to exit. Need to update the sample to exit on it's own.
  • the cloning is done for now to ~/Open3D_docker. We have options: find a way to let the user specify the destination or just reuse the current location of Open3D.
  • TODO: uncomment entries in the dependencies section inside the Dockerfile.

@syncle
Copy link
Contributor

syncle commented Apr 7, 2018

Addressed in #273.

syncle pushed a commit that referenced this issue Apr 12, 2018
* issues #17. first draft of docker files.

* added simpler ways to stop or bash into the container.

* test the push process with 2-factor auth.

* test 2-way auth with credentials cache.

* ratpoison back. clone Open3D.

* install Open3D dependencies and build.

* simple way of deleting the image. won't force the delete if there are child containers running.

* added more dependencies for the python side of things. python3-tk seems to be necessary but wasn't mentioned before in the docs.

* issue #17. builds the headleass_rendering branch by Jaesik.

* added new line at the end of each script. makes it easy to read with cat.

* no upgrade. proper apt-get install pattern. no locales - use defaults. no cd - use WORKDIR. it.sh is just an interactive run.

* stop after 0s. default 10s.

* moved the CMD specifics to entrypoint.sh.

* successfully start both xvfb and ratpoison.
attach.sh will attach to a running container.
test.sh is used to investigate the segmentation fault when running OpenGL apps inside the container.
.xinitrc starts ratpoison. xvfb is started by x11vnc. I can start xvfb and have x11vnc reuse that display and screen however ratpoison doesn't start automatically anymore...
Dockerfile example of using an NVIDIA docker image with driver, CUDA toolkit and cuDNN.
run.sh example of running a container using nvidia-docker.

* cleanup.
test.sh can be run without python3.
attach.sh will run the container first.
bash.sh will run the container first. bash.sh and attach.sh are the identical.
build.sh will first stop a running container.
run.sh will first stop a running container.

* debug. Open3D builds and runs (as much as before) with fewer dependencies.

* cleaned up nvidia.
cleaned up test.py - no more debug prints.
added faulthandler to test.py to display the error line.
installed debug tools gdb and python3.5-dbg.

* debug build.
clone the original repo. turns out a lot more things are working than when using the headless_rendering branch.
Tutorial/Advanced/test.py is looking for a display. what if it finds a display, will it just work from a docker terminal?

* cleanup. removed the code for headless_rendering branch approach.

* included debug dependencies in the main install section.
replaced ratpoison with lxde. works fine with exceptions: lxterminal doesn't start, display size smaller than Open3D tutorial windows, etc.

* deleted because it's identical to attach.sh.

* remove unused containers/images.

* move setup files to Open3D/docker/setup.

* moved docker utilities under Open3D/docker/ubuntu-xvfb/tools.

* fix building by specifying the path to the Dockerfile.

* moved docker inside new folder utilities.

* #17. these changes allow running headless inside the host terminal without the need to vnc into the docker container.

* renamed test.sh/py to headless_sample.sh/py.

* stop before perfoming most actions.

* headless rendering works with preinstalled dependencies.

* #17. #254. Successfully applied the bind mounting pattern to enable file transfers and code sharing between the container and the host.

* added back the ubuntu dependencies.
install only python3 dependencies.

* removed proxy settings.

* renamed utilities/ -> util/.

* removed '5.'

* #17. #251. First draft of headless rendering documentation.

* polished the sections called:
- Docker installation
- Optional steps

* it.sh is basically run.sh but with '-it' instead of '-d'.
'-d' will detach the container from the host terminal.
'-it' will keep the container attached to the host terminal and will display the stdout of the container.

* added 'Usage notes'. needs polishing.

* refine various sections of the documentation.

* more polishing

* renamed ubuntu-xvfb to open3d-xvfb.

* container name changed to open3d-xvfb.
the name can be specified only once in name.sh.
set the container hostname to be the same as the container name.

* removed custom proxy settings. these settings to be modified as needed.

* renamed 'headless_rendering.rst' to 'docker.rst' in order to make room for the glfw3.3 based headless merge.

* renamed docs entries to 'docker' from 'headless_rendering'.

* removed the build command as it won't work after 'run -it'. build manually after remoting into the container.

* polished the documentation. build the Open3D code using the code from External rather than the native dependencies.

* reduced Docker image in half by using the '--no-install-recommends' flag.

* docker image size was reduced to ~1GB.

* use the warning tag to highlight security recommendation.

* remove duplicate. one copy already committed to Tutorial/Advanced.

* renamed headless_sample.sh to docker_sample.sh.

* removed duplicate headless_sample.py. copy the docker_sample.sh.

* removing some spaces.

* removed references to headless.

* removed unnecessary file.
@syncle syncle self-assigned this May 4, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants