Skip to content

Commit

Permalink
Merge branch 'ershi/NVIDIAGH-412' into 'main'
Browse files Browse the repository at this point in the history
Store gl as a class-level variable to avoid shutdown issues

Closes NVIDIAGH-412

See merge request omniverse/warp!949
  • Loading branch information
shi-eric committed Jan 2, 2025
2 parents 292510f + 8164a7c commit 3d7e316
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 22 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
- Fix errors during graph capture caused by module unloading ([GH-401](https://github.com/NVIDIA/warp/issues/401)).
- Fix incorrect CUDA driver function versions ([GH-402](https://github.com/NVIDIA/warp/issues/402)).
- Fix allocating arrays with strides ([GH-404](https://github.com/NVIDIA/warp/issues/404)).
- Fix `ImportError` exception being thrown during `OpenGLRenderer` interpreter shutdown on Windows
([GH-412](https://github.com/NVIDIA/warp/issues/412)).

## [1.5.0] - 2024-12-02

Expand Down
66 changes: 44 additions & 22 deletions warp/render/render_opengl.py
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,15 @@ class ShapeInstancer:
[3D point, 3D normal, UV texture coordinates]
"""

gl = None # Class-level variable to hold the imported module

@classmethod
def initialize_gl(cls):
if cls.gl is None: # Only import if not already imported
from pyglet import gl

cls.gl = gl

def __new__(cls, *args, **kwargs):
instance = super(ShapeInstancer, cls).__new__(cls)
instance.instance_transform_gl_buffer = None
Expand All @@ -690,8 +699,10 @@ def __init__(self, shape_shader, device):
self.scalings = None
self._instance_transform_cuda_buffer = None

ShapeInstancer.initialize_gl()

def __del__(self):
from pyglet import gl
gl = ShapeInstancer.gl

if self.instance_transform_gl_buffer is not None:
try:
Expand All @@ -709,7 +720,7 @@ def __del__(self):
pass

def register_shape(self, vertices, indices, color1=(1.0, 1.0, 1.0), color2=(0.0, 0.0, 0.0)):
from pyglet import gl
gl = ShapeInstancer.gl

if color1 is not None and color2 is None:
color2 = np.clip(np.array(color1) + 0.25, 0.0, 1.0)
Expand Down Expand Up @@ -750,7 +761,7 @@ def register_shape(self, vertices, indices, color1=(1.0, 1.0, 1.0), color2=(0.0,
self.face_count = len(indices)

def update_colors(self, colors1, colors2):
from pyglet import gl
gl = ShapeInstancer.gl

if colors1 is None:
colors1 = np.tile(self.color1, (self.num_instances, 1))
Expand Down Expand Up @@ -789,7 +800,7 @@ def update_colors(self, colors1, colors2):
gl.glVertexAttribDivisor(8, 1)

def allocate_instances(self, positions, rotations=None, colors1=None, colors2=None, scalings=None):
from pyglet import gl
gl = ShapeInstancer.gl

gl.glBindVertexArray(self.vao)

Expand Down Expand Up @@ -864,7 +875,7 @@ def allocate_instances(self, positions, rotations=None, colors1=None, colors2=No
gl.glBindVertexArray(0)

def update_instances(self, transforms: wp.array = None, scalings: wp.array = None, colors1=None, colors2=None):
from pyglet import gl
gl = ShapeInstancer.gl

if transforms is not None:
if transforms.device.is_cuda:
Expand Down Expand Up @@ -905,7 +916,7 @@ def update_instances(self, transforms: wp.array = None, scalings: wp.array = Non
self.update_colors(colors1, colors2)

def render(self):
from pyglet import gl
gl = ShapeInstancer.gl

gl.glUseProgram(self.shape_shader.id)

Expand All @@ -915,7 +926,7 @@ def render(self):

# scope exposes VBO transforms to be set directly by a warp kernel
def __enter__(self):
from pyglet import gl
gl = ShapeInstancer.gl

gl.glBindVertexArray(self.vao)
self.vbo_transforms = self._instance_transform_cuda_buffer.map(dtype=wp.mat44, shape=(self.num_instances,))
Expand All @@ -941,6 +952,15 @@ class OpenGLRenderer:
# number of segments to use for rendering spheres, capsules, cones and cylinders
default_num_segments = 32

gl = None # Class-level variable to hold the imported module

@classmethod
def initialize_gl(cls):
if cls.gl is None: # Only import if not already imported
from pyglet import gl

cls.gl = gl

def __init__(
self,
title="Warp",
Expand Down Expand Up @@ -1023,9 +1043,11 @@ def __init__(
# disable error checking for performance
pyglet.options["debug_gl"] = False

from pyglet import gl
from pyglet.graphics.shader import Shader, ShaderProgram
from pyglet.math import Vec3 as PyVec3

OpenGLRenderer.initialize_gl()
gl = OpenGLRenderer.gl
except ImportError as e:
raise Exception("OpenGLRenderer requires pyglet (version >= 2.0) to be installed.") from e

Expand Down Expand Up @@ -1411,7 +1433,7 @@ def has_exit(self):
return self.app.event_loop.has_exit

def clear(self):
from pyglet import gl
gl = OpenGLRenderer.gl

if not self.headless:
self.app.event_loop.dispatch_event("on_exit")
Expand Down Expand Up @@ -1605,7 +1627,7 @@ def update_tile(
self._tile_viewports[tile_id] = (x, y, w, h)

def _setup_framebuffer(self):
from pyglet import gl
gl = OpenGLRenderer.gl

if self._frame_texture is None:
self._frame_texture = gl.GLuint()
Expand Down Expand Up @@ -1773,7 +1795,7 @@ def compute_model_matrix(camera_axis: int, scaling: float):
return np.array((scaling, 0, 0, 0, 0, scaling, 0, 0, 0, 0, scaling, 0, 0, 0, 0, 1), dtype=np.float32)

def update_model_matrix(self, model_matrix: Optional[Mat44] = None):
from pyglet import gl
gl = OpenGLRenderer.gl

if model_matrix is None:
self._model_matrix = self.compute_model_matrix(self._camera_axis, self._scaling)
Expand Down Expand Up @@ -1868,7 +1890,7 @@ def update(self):
self._draw()

def _draw(self):
from pyglet import gl
gl = OpenGLRenderer.gl

if not self.headless:
# catch key hold events
Expand Down Expand Up @@ -1967,7 +1989,7 @@ def _draw(self):
cb()

def _draw_grid(self, is_tiled=False):
from pyglet import gl
gl = OpenGLRenderer.gl

if not is_tiled:
gl.glUseProgram(self._grid_shader.id)
Expand All @@ -1980,7 +2002,7 @@ def _draw_grid(self, is_tiled=False):
gl.glBindVertexArray(0)

def _draw_sky(self, is_tiled=False):
from pyglet import gl
gl = OpenGLRenderer.gl

if not is_tiled:
gl.glUseProgram(self._sky_shader.id)
Expand All @@ -1994,7 +2016,7 @@ def _draw_sky(self, is_tiled=False):
gl.glBindVertexArray(0)

def _render_scene(self):
from pyglet import gl
gl = OpenGLRenderer.gl

start_instance_idx = 0

Expand All @@ -2017,7 +2039,7 @@ def _render_scene(self):
gl.glBindVertexArray(0)

def _render_scene_tiled(self):
from pyglet import gl
gl = OpenGLRenderer.gl

for i, viewport in enumerate(self._tile_viewports):
projection_matrix_ptr = arr_pointer(self._tile_projection_matrices[i])
Expand Down Expand Up @@ -2162,7 +2184,7 @@ def _window_resize_callback(self, width, height):
self._setup_framebuffer()

def register_shape(self, geo_hash, vertices, indices, color1=None, color2=None):
from pyglet import gl
gl = OpenGLRenderer.gl

shape = len(self._shapes)
if color1 is None:
Expand Down Expand Up @@ -2211,7 +2233,7 @@ def register_shape(self, geo_hash, vertices, indices, color1=None, color2=None):
return shape

def deregister_shape(self, shape):
from pyglet import gl
gl = OpenGLRenderer.gl

if shape not in self._shape_gl_buffers:
return
Expand Down Expand Up @@ -2270,7 +2292,7 @@ def remove_shape_instance(self, name: str):
del self._instances[name]

def update_instance_colors(self):
from pyglet import gl
gl = OpenGLRenderer.gl

colors1, colors2 = [], []
all_instances = list(self._instances.values())
Expand All @@ -2291,7 +2313,7 @@ def update_instance_colors(self):
gl.glBufferData(gl.GL_ARRAY_BUFFER, colors2.nbytes, colors2.ctypes.data, gl.GL_STATIC_DRAW)

def allocate_shape_instances(self):
from pyglet import gl
gl = OpenGLRenderer.gl

self._add_shape_instances = False
self._wp_instance_transforms = wp.array(
Expand Down Expand Up @@ -2393,7 +2415,7 @@ def update_shape_instance(self, name, pos=None, rot=None, color1=None, color2=No
color2: The second color of the checker pattern
visible: Whether the shape is visible
"""
from pyglet import gl
gl = OpenGLRenderer.gl

if name in self._instances:
i, body, shape, tf, scale, old_color1, old_color2, v = self._instances[name]
Expand Down Expand Up @@ -2504,7 +2526,7 @@ def get_pixels(self, target_image: wp.array, split_up_tiles=True, mode="rgb", us
Returns:
bool: Whether the pixels were successfully read.
"""
from pyglet import gl
gl = OpenGLRenderer.gl

channels = 3 if mode == "rgb" else 1

Expand Down

0 comments on commit 3d7e316

Please sign in to comment.