Open qo4on opened 4 years ago
I am getting the same issue when running in docker. Something to do with the fact that pyglet needs a display to run. There may be a solution using Xvfb
xvfb doesn't work either. We need to change manim window.py
backend from pyglet
to headless
.
from moderngl_window.context.headless.window import Window as HeadlessWindow
But I didn't managed to make it work.
Running Win10, I couldn't get it to work when using the preview setting (-p) due to no configs for the window:
Traceback (most recent call last):
File "C:\Users\Tyler Wolfe-Adam\Documents\Python\manim-shaders\manim.py", line 5, in <module>
manimlib.main()
File "C:\Users\Tyler Wolfe-Adam\Documents\Python\manim-shaders\manimlib\__init__.py", line 11, in main
scenes = manimlib.extract_scene.main(config)
File "C:\Users\Tyler Wolfe-Adam\Documents\Python\manim-shaders\manimlib\extract_scene.py", line 104, in main
scenes = get_scenes_to_render(all_scene_classes, config)
File "C:\Users\Tyler Wolfe-Adam\Documents\Python\manim-shaders\manimlib\extract_scene.py", line 72, in get_scenes_to_render
scene = scene_class(**scene_kwargs)
File "C:\Users\Tyler Wolfe-Adam\Documents\Python\manim-shaders\manimlib\scene\scene.py", line 44, in __init__
self.window = Window(self, **self.window_config)
File "C:\Users\Tyler Wolfe-Adam\Documents\Python\manim-shaders\manimlib\window.py", line 21, in __init__
super().__init__(**kwargs)
File "C:\Program Files\Python37\lib\site-packages\moderngl_window\context\pyglet\window.py", line 54, in __init__
config=config,
File "C:\Program Files\Python37\lib\site-packages\pyglet\window\win32\__init__.py", line 130, in __init__
super(Win32Window, self).__init__(*args, **kwargs)
File "C:\Program Files\Python37\lib\site-packages\pyglet\window\__init__.py", line 591, in __init__
config = screen.get_best_config(config)
File "C:\Program Files\Python37\lib\site-packages\pyglet\canvas\base.py", line 194, in get_best_config
raise window.NoSuchConfigException()
pyglet.window.NoSuchConfigException
It does work when just writing to a file (-w). However, just for the shape examples. Anything with text doesn't work due to (unrelated) issues with dvisvgm not converting the dvi to svg.
What text doesn't work? tex_mobject
or text_mobject
?
What text doesn't work?
tex_mobject
ortext_mobject
?
Both, unfortunately; I also tried modifying the example scenes with just using one or the other. Both result in OSError: No file matching ./media\Tex\ab47de5016aed0d4.svg in image directory
.
I dug into it and it stems from the dvisvgm
command (called from the dvi_to_svg
function inside \manimlib\utils\tex_file_writing.py
) - the command executes successfully but nothing gets outputted (no files or messages, even with the highest level of verbosity). I even tried searching my entire file system for the file and still nothing. It's really weird.
I'm currently getting it setup to try on WSL. Hopefully that works better. No luck on googling the problem either. I'll probably open a new thread somewhere if it doesn't work with WSL :/
Edit: The problem with dvisvgm seems to be a Windows thing. I found out it's returning exit code -1073740791, which is apparently a stack buffer overflow. dvisvgm works fine on WSL, so for now I've implemented a hacky solution where Windows waits until Ubuntu has converted the necessary files.
Edit 2: Found the fix! For future readers: Running dvisvgm --version
reported 2.7. I ran where dvisvgm
and it reported two versions: the v2.7 (installed in Program Files) showed before the other, which was part of MikTex and version 2.8.2. Removing the v2.7 copy fixed this issue.
I am now able to render videos in this branch, as long as I'm writing to file (w
flag) and not showing preview (p
flag).
Update: Ran into the same problems with the display. Tried using xvfb like so:
xvfb-run -s "-screen 0 640x360x24" python3.7 -m manim example_scenes.py SquareToCircle -ql
That returned the same error for me as when I tried to use the q
flag on Windows:
Traceback (most recent call last):
File "/usr/lib/python3.7/runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "/usr/lib/python3.7/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/home/tyler/Documents/manim/manim.py", line 5, in <module>
manimlib.main()
File "/home/tyler/Documents/manim/manimlib/__init__.py", line 11, in main
scenes = manimlib.extract_scene.main(config)
File "/home/tyler/Documents/manim/manimlib/extract_scene.py", line 104, in main
scenes = get_scenes_to_render(all_scene_classes, config)
File "/home/tyler/Documents/manim/manimlib/extract_scene.py", line 72, in get_scenes_to_render
scene = scene_class(**scene_kwargs)
File "/home/tyler/Documents/manim/manimlib/scene/scene.py", line 44, in __init__
self.window = Window(self, **self.window_config)
File "/home/tyler/Documents/manim/manimlib/window.py", line 21, in __init__
super().__init__(**kwargs)
File "/home/tyler/.local/lib/python3.7/site-packages/moderngl_window/context/pyglet/window.py", line 54, in __init__
config=config,
File "/home/tyler/.local/lib/python3.7/site-packages/pyglet/window/xlib/__init__.py", line 171, in __init__
super(XlibWindow, self).__init__(*args, **kwargs)
File "/home/tyler/.local/lib/python3.7/site-packages/pyglet/window/__init__.py", line 591, in __init__
config = screen.get_best_config(config)
File "/home/tyler/.local/lib/python3.7/site-packages/pyglet/canvas/base.py", line 194, in get_best_config
raise window.NoSuchConfigException()
pyglet.window.NoSuchConfigException
Tried again with the w
flag, but then got the following error:
Media will be written to ./media/. You can change this behavior with the --media_dir flag.
Traceback (most recent call last):
File "/usr/lib/python3.7/runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "/usr/lib/python3.7/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/home/tyler/Documents/manim/manim.py", line 5, in <module>
manimlib.main()
File "/home/tyler/Documents/manim/manimlib/__init__.py", line 14, in main
scene.run()
File "/home/tyler/Documents/manim/manimlib/scene/scene.py", line 74, in run
self.construct()
File "example_scenes.py", line 84, in construct
self.play(Transform(square, circle))
File "/home/tyler/Documents/manim/manimlib/scene/scene.py", line 357, in wrapper
func(self, *args, **kwargs)
File "/home/tyler/Documents/manim/manimlib/scene/scene.py", line 425, in play
self.progress_through_animations(animations)
File "/home/tyler/Documents/manim/manimlib/scene/scene.py", line 402, in progress_through_animations
self.update_frame(dt)
File "/home/tyler/Documents/manim/manimlib/scene/scene.py", line 140, in update_frame
self.camera.capture(*self.mobjects)
File "/home/tyler/Documents/manim/manimlib/camera/camera.py", line 228, in capture
shader = self.get_shader(info_group[0])
File "/home/tyler/Documents/manim/manimlib/camera/camera.py", line 253, in get_shader
fragment_shader=get_shader_code_from_file(info["frag"]),
File "/home/tyler/.local/lib/python3.7/site-packages/moderngl/context.py", line 1037, in program
varyings
moderngl.error.Error: GLSL Compiler failed
fragment_shader
===============
0:179(24): error: `return' with wrong type int, in function `sdf' returning float
``
You can't get hardware acceleration with virtual displays such as xvfb. Can you render SquareToCircle
in shaders
version correctly?
I was able to do it on mac - not in docker
Can you try to run it in Colab? I had no success there.
Lengthy issue about this in the modengl project: https://github.com/moderngl/moderngl/issues/392 We do actually get it running in Google Colab with EGL, but it gets stuck in an infinite loop. That I think is a flow issue in the Manim code itself.. or at least it needs to be debugged properly to make a conclusion.
Manim is using moderngl and moderngl-window. I think the main issues is that it extends the pyglet window backend directly. If headless rendering is needed it should use the headless.Window
instead.
The BaseWindow.init_mgl_context
should be probably also be overridden to create the correct context type or I can add some features for this in the moderngl-window project if we figure out what is needed. Right now it tries to detect the context pyglet creates**, but in headless we just need to make our own context with no window (X11 or EGL).
It's not that complicated to fix thankfully.
I am willing to help out giving pointers for the moderngl specific things, but I don't really know much about Manim (at least yet).
You can't get hardware acceleration with virtual displays such as xvfb. Can you render
SquareToCircle
inshaders
version correctly?
Good to know! I can in Windows, but not in the Ubuntu subsystem. For both the q
and w
flags I get the pyglet.canvas.xlib.NoSuchDisplayException: Cannot connect to "None"
exception.
I released a new version of moderngl-window what should at least solve the NoSuchConfig
for a lot of people. You maye also have to go into the window.py
module and set samples = 0
.
@t-wolfeadam The shader error you are getting is an error in the glsl code here : https://github.com/3b1b/manim/blob/2ce0b72c440fadbfba990bdac8bc9c2ea8bff4e7/manimlib/shaders/quadratic_bezier_fill_frag.glsl#L41
It should return a float
, not an int
. Not all GLSL compilers are nice and convert constants for you automatically. I would fix that line and test it again. Make a PR as well while you are at it (if it works) π
You may see more of those, but they are quick and easy to fix if you search for the variable or function names reported by the GLSL compiler.
I released a new version of moderngl-window what should at least solve the
NoSuchConfig
for a lot of people. You may also have to go into thewindow.py
module and setsamples = 0
.
Fantastic, thanks! I can confirm for Windows that updating + setting samples to 0 fixed it!
@t-wolfeadam The shader error you are getting is an error in the glsl code here :
It should return a
float
, not anint
. Not all GLSL compilers are nice and convert constants for you automatically. I would fix that line and test it again. Make a PR as well while you are at it (if it works) π
Ahh, so that's what sdf was referring to. That also did the trick, so thank you for that as well! (and fortunately, it was the only instance).
Edit: looks like someone already made the PR for that issue
@t-wolfeadam Yep. We just sorted out a PR after discussing the issue on the manim discord server π
And here it is: https://github.com/3b1b/manim/pull/950
I tried running the project for SIR simulation (https://www.youtube.com/watch?v=gxAaO2rsdIs) and got this error: "~\Anaconda3\envs\manim\lib\site-packages\pyglet\canvas\base.py", line 194, in get_best_config raise window.NoSuchConfigException() pyglet.window.NoSuchConfigException "
I was able to run the Test case but basically everything else crashed
NoSuchConfigException
is related to a hardcoded samples = 1
in the window. That needs to be removed or be configurable. The branch is super alpha and needs a bit of hacking to work.
@einarf
NoSuchConfigException
is related to a hardcodedsamples = 1
in the window. That needs to be removed or be configurable. The branch is super alpha and needs a bit of hacking to work.
I got it to work by removing the samples = 1 line, but it is sluggish, could you explain how to make it configurable?
@einarf I found that we can skip the loop when running -w
option to write directly to a file. I set HeadlessWindow
and backend='egl'
. But got an exception with XOpenDisplay
. Do you know how to fix that?
!python3 -m manim example_scenes.py SquareToCircle -w
Traceback (most recent call last):
File "/usr/lib/python3.6/runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "/usr/lib/python3.6/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/content/manim/manim.py", line 5, in <module>
manimlib.main()
File "/content/manim/manimlib/__init__.py", line 11, in main
scenes = manimlib.extract_scene.main(config)
File "/content/manim/manimlib/extract_scene.py", line 104, in main
scenes = get_scenes_to_render(all_scene_classes, config)
File "/content/manim/manimlib/extract_scene.py", line 72, in get_scenes_to_render
scene = scene_class(**scene_kwargs)
File "/content/manim/manimlib/scene/scene.py", line 51, in __init__
self.camera = self.camera_class(**self.camera_config)
File "/content/manim/manimlib/camera/camera.py", line 65, in __init__
self.init_context(ctx)
File "/content/manim/manimlib/camera/camera.py", line 77, in init_context
self.ctx = moderngl.create_standalone_context()
File "/usr/local/lib/python3.6/dist-packages/moderngl/context.py", line 1466, in create_standalone_context
ctx.mglo, ctx.version_code = mgl.create_context(glversion=require, mode=mode, **settings)
File "/usr/local/lib/python3.6/dist-packages/glcontext/__init__.py", line 76, in create
return x11.create_context(**kwargs)
Exception: (standalone) XOpenDisplay: cannot open display
The stack trace above is from another context creation. Maybe that's the one that is used when no preview is used and the HeadlessWindow
thing is not needed at all? : https://github.com/3b1b/manim/blob/ec4a70ad3511805c3b5ec55b43ac548be85555e8/manimlib/camera/camera.py#L77
XOpenDisplay
means it's and x11 headless context and not egl, and clearly backend='egl'
is not passed in there.
Thanks. I replaced it with
self.ctx = moderngl.create_standalone_context(require=460, backend='egl')
ran
!python3 -m manim example_scenes.py SquareToCircle -w
and got rendered file
/content/manim/media/videos/example_scenes/1440p60/SquareToCircle.mp4
One problem: there is no GPU acceleration. On CPU this SquareToCircle
example finishes in 17 seconds. On GPU it took 18 seconds. When GPU works the rendering time should be around 3 seconds. Is there anything we can do with it?
Whole context function:
def init_context(self, ctx=None):
if ctx is not None:
self.ctx = ctx
self.fbo = self.ctx.detect_framebuffer()
else:
self.ctx = moderngl.create_standalone_context(require=460, backend='egl')
self.fbo = self.get_fbo()
self.fbo.use()
self.ctx.enable(moderngl.BLEND)
self.ctx.blend_func = (
moderngl.SRC_ALPHA, moderngl.ONE_MINUS_SRC_ALPHA,
moderngl.ONE, moderngl.ONE
)
self.background_fbo = None
hmm. Grab the self.ctx.info
and paste here.
{'GL_ALIASED_LINE_WIDTH_RANGE': (1.0, 10.0),
'GL_CONTEXT_PROFILE_MASK': 1,
'GL_DOUBLEBUFFER': False,
'GL_MAJOR_VERSION': 4,
'GL_MAX_3D_TEXTURE_SIZE': 16384,
'GL_MAX_ARRAY_TEXTURE_LAYERS': 2048,
'GL_MAX_CLIP_DISTANCES': 8,
'GL_MAX_COLOR_ATTACHMENTS': 8,
'GL_MAX_COLOR_TEXTURE_SAMPLES': 32,
'GL_MAX_COMBINED_ATOMIC_COUNTERS': 98304,
'GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS': 231424,
'GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS': 233472,
'GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS': 231424,
'GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS': 96,
'GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS': 192,
'GL_MAX_COMBINED_UNIFORM_BLOCKS': 84,
'GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS': 233472,
'GL_MAX_COMPUTE_ATOMIC_COUNTERS': 16384,
'GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS': 8,
'GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS': 16,
'GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS': 32,
'GL_MAX_COMPUTE_UNIFORM_BLOCKS': 14,
'GL_MAX_COMPUTE_UNIFORM_COMPONENTS': 2048,
'GL_MAX_COMPUTE_WORK_GROUP_COUNT': (2147483647, 65535, 65535),
'GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS': 1536,
'GL_MAX_COMPUTE_WORK_GROUP_SIZE': (1536, 1024, 64),
'GL_MAX_CUBE_MAP_TEXTURE_SIZE': 32768,
'GL_MAX_DEPTH_TEXTURE_SAMPLES': 32,
'GL_MAX_DRAW_BUFFERS': 8,
'GL_MAX_DUAL_SOURCE_DRAW_BUFFERS': 1,
'GL_MAX_ELEMENTS_INDICES': 1048576,
'GL_MAX_ELEMENTS_VERTICES': 1048576,
'GL_MAX_ELEMENT_INDEX': 4294967295,
'GL_MAX_FRAGMENT_ATOMIC_COUNTERS': 16384,
'GL_MAX_FRAGMENT_INPUT_COMPONENTS': 128,
'GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS': 16,
'GL_MAX_FRAGMENT_UNIFORM_BLOCKS': 14,
'GL_MAX_FRAGMENT_UNIFORM_COMPONENTS': 4096,
'GL_MAX_FRAGMENT_UNIFORM_VECTORS': 1024,
'GL_MAX_FRAMEBUFFER_HEIGHT': 32768,
'GL_MAX_FRAMEBUFFER_LAYERS': 2048,
'GL_MAX_FRAMEBUFFER_SAMPLES': 32,
'GL_MAX_FRAMEBUFFER_WIDTH': 32768,
'GL_MAX_GEOMETRY_ATOMIC_COUNTERS': 16384,
'GL_MAX_GEOMETRY_INPUT_COMPONENTS': 128,
'GL_MAX_GEOMETRY_OUTPUT_COMPONENTS': 128,
'GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS': 16,
'GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS': 32,
'GL_MAX_GEOMETRY_UNIFORM_BLOCKS': 14,
'GL_MAX_GEOMETRY_UNIFORM_COMPONENTS': 2048,
'GL_MAX_INTEGER_SAMPLES': 32,
'GL_MAX_PROGRAM_TEXEL_OFFSET': 7.0,
'GL_MAX_RECTANGLE_TEXTURE_SIZE': 32768,
'GL_MAX_RENDERBUFFER_SIZE': 32768,
'GL_MAX_SAMPLES': 32,
'GL_MAX_SAMPLE_MASK_WORDS': 2,
'GL_MAX_SERVER_WAIT_TIMEOUT': -1,
'GL_MAX_SHADER_STORAGE_BLOCK_SIZE': 2147483647,
'GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS': 96,
'GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS': 16384,
'GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS': 16,
'GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS': 16384,
'GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS': 16,
'GL_MAX_TEXTURE_BUFFER_SIZE': 134217728,
'GL_MAX_TEXTURE_IMAGE_UNITS': 32,
'GL_MAX_TEXTURE_LOD_BIAS': 15,
'GL_MAX_TEXTURE_SIZE': 32768,
'GL_MAX_UNIFORM_BLOCK_SIZE': 65536,
'GL_MAX_UNIFORM_BUFFER_BINDINGS': 84,
'GL_MAX_UNIFORM_LOCATIONS': 65536,
'GL_MAX_VARYING_VECTORS': 31,
'GL_MAX_VERTEX_ATOMIC_COUNTERS': 16384,
'GL_MAX_VERTEX_ATTRIBS': 16,
'GL_MAX_VERTEX_ATTRIB_BINDINGS': 16,
'GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET': 2047,
'GL_MAX_VERTEX_OUTPUT_COMPONENTS': 128,
'GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS': 16,
'GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS': 32,
'GL_MAX_VERTEX_UNIFORM_BLOCKS': 14,
'GL_MAX_VERTEX_UNIFORM_COMPONENTS': 4096,
'GL_MAX_VERTEX_UNIFORM_VECTORS': 1024,
'GL_MAX_VIEWPORTS': 16,
'GL_MAX_VIEWPORT_DIMS': (32768, 32768),
'GL_MINOR_VERSION': 6,
'GL_MIN_MAP_BUFFER_ALIGNMENT': 64,
'GL_MIN_PROGRAM_TEXEL_OFFSET': -8.0,
'GL_POINT_FADE_THRESHOLD_SIZE': 1.0,
'GL_POINT_SIZE_GRANULARITY': 0.125,
'GL_POINT_SIZE_RANGE': (1.0, 189.875),
'GL_RENDERER': 'Tesla P100-PCIE-16GB/PCIe/SSE2',
'GL_SAMPLE_BUFFERS': 0,
'GL_SMOOTH_LINE_WIDTH_GRANULARITY': 0.125,
'GL_SMOOTH_LINE_WIDTH_RANGE': (0.5, 10.0),
'GL_STEREO': False,
'GL_SUBPIXEL_BITS': 8,
'GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT': 256,
'GL_VENDOR': 'NVIDIA Corporation',
'GL_VERSION': '4.6.0 NVIDIA 418.67',
'GL_VIEWPORT_BOUNDS_RANGE': (-65536, 65536),
'GL_VIEWPORT_SUBPIXEL_BITS': 8}
It is from the end of init_context
function.
When we replaced manim window.py
with the code below it redered faster, but we've got into a loop.
import moderngl_window as mglw
from moderngl_window.context.headless.window import Window as HeadlessWindow
from moderngl_window.timers.clock import Timer
from manimlib.constants import DEFAULT_PIXEL_WIDTH
from manimlib.constants import DEFAULT_PIXEL_HEIGHT
from manimlib.utils.config_ops import digest_config
class Window(HeadlessWindow):
size = (DEFAULT_PIXEL_WIDTH, DEFAULT_PIXEL_HEIGHT)
fullscreen = False
resizable = False
gl_version = (4, 6)
vsync = False
samples = 1
cursor = False
def __init__(self, scene, **kwargs):
digest_config(self, kwargs)
super().__init__(**kwargs)
self.scene = scene
self.title = str(scene)
# Put at the top of the screen
self.position = (self.position[0], 0)
mglw.activate_context(window=self)
self.timer = Timer()
self.config = mglw.WindowConfig(ctx=self.ctx, wnd=self, timer=self.timer)
self.timer.start()
# Delegate event handling to scene
def pixel_coords_to_space_coords(self, px, py, relative=False):
return self.scene.camera.pixel_coords_to_space_coords(px, py, relative)""")
Hard to say about performance to be honest. Manim in shader branch is a mix of gpu and cpu rendering as far as I have seen, so that needs to be profiled locally. If this is Google Colab still I would guess you only won't get the performance of that entire card. Also I don't know if there's any setup or teardown cost.
So does it create two opengl contexts when not using a preview?
I don't know. How can I check that?
Add some prints before every context creation or open and append something to file if you cannot see output.
It creates context in /content/manim/manimlib/camera/camera.py
And does not in /usr/local/lib/python3.6/dist-packages/moderngl_window/context/headless/window.py
There are different steps after context creation. In camera.py
he does:
self.ctx = moderngl.create_standalone_context(require=460, backend='egl')
self.fbo = self.get_fbo()
self.fbo.use()
self.ctx.enable(moderngl.BLEND)
self.ctx.blend_func = (
moderngl.SRC_ALPHA, moderngl.ONE_MINUS_SRC_ALPHA,
moderngl.ONE, moderngl.ONE
)
self.background_fbo = None
But in your window.py
:
self._ctx = moderngl.create_standalone_context(require=self.gl_version_code, backend='egl')
self._fbo = self.ctx.framebuffer(
color_attachments=self.ctx.texture(self.size, 4, samples=self._samples),
depth_attachment=self.ctx.depth_texture(self.size, samples=self._samples),
)
self.use()
The camera.py
one is slower I guess? .. and you only saw one single context creation I hope?
You can try commenting out blending and see if that affects anything
self.ctx.enable(moderngl.BLEND)
self.ctx.blend_func = (
moderngl.SRC_ALPHA, moderngl.ONE_MINUS_SRC_ALPHA,
moderngl.ONE, moderngl.ONE
)
The second thing you can test is to use same framebuffer configuration as the window.
The
camera.py
one is slower
Yes
you only saw one single context creation I hope?
Yes. The conext creates in camera.py
.
You can try commenting out blending and see if that affects anything
Rendering took 17 seconds
Modify get_fbo()
to make the same framebuffer format? I don't understand why changing the window class affects anything in the first place π
I tried this:
def init_context(self, ctx=None):
if ctx is not None:
self.ctx = ctx
self.fbo = self.ctx.detect_framebuffer()
else:
self.ctx = moderngl.create_standalone_context(require=460, backend='egl')
size = (DEFAULT_PIXEL_WIDTH, DEFAULT_PIXEL_HEIGHT)
samples = 1
self.fbo = self.ctx.framebuffer(
color_attachments=self.ctx.texture(size, 4, samples=samples),
depth_attachment=self.ctx.depth_texture(size, samples=samples),
)
self.background_fbo = None
Rendering time 15 seconds, but the resulting file is a black window.
Modify
get_fbo()
to make the same framebuffer format?
I'm not sure what you mean.
I don't understand why changing the window class affects anything in the first place π
It does not affect anything when writing to a file enabled !python3 -m manim example_scenes.py SquareToCircle -w
.
But it affects when running headless widow: !python3 -m manim example_scenes.py SquareToCircle
.
I think we need to recreate steps you did in window.py
inside manim camera.py
.
I think we need to recreate steps you did in
window.py
inside manimcamera.py
.
Probably a good idea. It might just even be a fluke. I don't really know how much gpu resources is allocated per user or if the tesla have a much lower latency. I'm guessing the setup is configured to do longer running gppgu and machine learning tasks.
I'd try to experiment over several runs. Try to replicate the speedup you saw.
One difference I see is in scene.py
/update_frame
. If you have a window it will call swap_buffers
. That's just doing a ctx.finish()
that will wait for all rendering operations to complete. There is no equivalent for swap_buffers
when camera.py
creates the context.
I believe when you are connected to Colab GPU you are getting all its power.
Do you know how to setup antialiasing samples
in /content/manim/manimlib/camera/camera.py
?
When sapples = 0
it creates a video in 13 seconds:
!python3 -m manim example_scenes.py SquareToCircle -w
def init_context(self, ctx=None):
if ctx is not None:
self.ctx = ctx
self.fbo = self.ctx.detect_framebuffer()
else:
self.ctx = moderngl.create_standalone_context(require=460, backend='egl')
self.fbo = self.get_fbo()
self.fbo.use()
self.ctx.enable(moderngl.BLEND)
self.ctx.blend_func = (
moderngl.SRC_ALPHA, moderngl.ONE_MINUS_SRC_ALPHA,
moderngl.ONE, moderngl.ONE
)
self.background_fbo = None
from pprint import pprint
pprint(self.__dict__)
# Methods associated with the frame buffer
def get_fbo(self):
samples = 0
return self.ctx.framebuffer(
color_attachments=self.ctx.texture((self.pixel_width, self.pixel_height), 4, samples=samples),
depth_attachment=self.ctx.depth_texture((self.pixel_width, self.pixel_height), samples=samples)
)
{'background_color': '#000000',
'background_fbo': None,
'background_image': None,
'background_opacity': 1,
'ctx': <Context 140226494281160 version_code=460>,
'fbo': <Framebuffer: 1>,
'frame': <manimlib.camera.camera.CameraFrame object at 0x7f8911b19080>,
'frame_config': {'center': array([0., 0., 0.]),
'height': 8.0,
'width': 14.222222222222221},
'frame_rate': 60,
'image_mode': 'RGBA',
'line_width_multiple': 0.01,
'max_allowable_norm': 14.222222222222221,
'n_channels': 4,
'pixel_array_dtype': 'uint8',
'pixel_height': 1440,
'pixel_width': 2560,
'rgb_max_val': 255}
But when I change it to samples = 1
the video is a black screen.
Do it in get_fbo
..
# Methods associated with the frame buffer
def get_fbo(self):
return self.ctx.framebuffer(
color_attachments=self.ctx.texture(self.size, 4, samples=8),
depth_attachment=self.ctx.depth_texture(self.size, samples=8),
)
Restore init_context
to the original state except the backend part.
This returns a black video with colored artifacts at the bottom edge. Your example shows white screen with this settings:
import numpy as np
from PIL import Image
import moderngl
ctx = moderngl.create_standalone_context(require=460, backend='egl')
samples = 8
fbo = ctx.framebuffer(
color_attachments=ctx.texture((512, 512), 4, samples=samples),
depth_attachment=ctx.depth_texture((512, 512), samples=samples)
)
fbo.use()
vertices = np.array([
-1.0, -1.0, 1.0, 0.0, 0.0,
1.0, -1.0, 0.0, 1.0, 0.0,
0.0, 1.0, 0.0, 0.0, 1.0],
dtype='f4',
)
prog = ctx.program(vertex_shader="""
#version 330
in vec2 in_vert;
in vec3 in_color;
out vec3 color;
void main() {
gl_Position = vec4(in_vert, 0.0, 1.0);
color = in_color;
}
""",
fragment_shader="""
#version 330
out vec4 fragColor;
in vec3 color;
void main() {
fragColor = vec4(color, 1.0);
}
""",
)
vao = ctx.simple_vertex_array(prog, ctx.buffer(vertices), 'in_vert', 'in_color')
vao.render(mode=moderngl.TRIANGLES)
image = Image.frombytes('RGBA', (512, 512), fbo.read(components=4))
image = image.transpose(Image.FLIP_TOP_BOTTOM)
image.save('triangle.png', format='png')
with samples = 0
it renders colored triangle.
There is only one change in ctx.info
: samples = 0; 'GL_SAMPLE_BUFFERS': 0
and when samples>0
: samples = 8; 'GL_SAMPLE_BUFFERS': 1
.
@einarf Investigating this further I found that it is possibly a bug of the Moderngl
.
Oh. I'll have to look into that. Thanks!
@einarf Do you have any comments on this?
Not anything that I've already said in the post above.
I'm wondering if manim even needs a depth buffer, so you can try dropping it.
Can you tell when a depth buffer is needed?
Search for DEPTH_TEST
in the source. That`s the enum name for the flag that enables or disable depth testing.
I found that for now manim has gpu accleration only when it works with pyglet window:
!python3 -m manim example_scenes.py SquareToCircle -p
What I didn't find is where pyglet window defines a framebuffer and where it uses samples=1
.
I get an error in Colab trying to run Manim from "shaders" branch. I see
tqdm
for each animation, that means they are successful. But then it gets into a loop and I have to stop it with the error:UPDATE: If you want to try it in Colab, the code is here.