warp-lang 1.8.1__py3-none-macosx_10_13_universal2.whl → 1.9.0__py3-none-macosx_10_13_universal2.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of warp-lang might be problematic. Click here for more details.

Files changed (134) hide show
  1. warp/__init__.py +282 -103
  2. warp/__init__.pyi +482 -110
  3. warp/bin/libwarp-clang.dylib +0 -0
  4. warp/bin/libwarp.dylib +0 -0
  5. warp/build.py +93 -30
  6. warp/build_dll.py +47 -67
  7. warp/builtins.py +955 -137
  8. warp/codegen.py +312 -206
  9. warp/config.py +1 -1
  10. warp/context.py +1249 -784
  11. warp/examples/core/example_marching_cubes.py +1 -0
  12. warp/examples/core/example_render_opengl.py +100 -3
  13. warp/examples/fem/example_apic_fluid.py +98 -52
  14. warp/examples/fem/example_convection_diffusion_dg.py +25 -4
  15. warp/examples/fem/example_diffusion_mgpu.py +8 -3
  16. warp/examples/fem/utils.py +68 -22
  17. warp/fabric.py +1 -1
  18. warp/fem/cache.py +27 -19
  19. warp/fem/domain.py +2 -2
  20. warp/fem/field/nodal_field.py +2 -2
  21. warp/fem/field/virtual.py +264 -166
  22. warp/fem/geometry/geometry.py +5 -5
  23. warp/fem/integrate.py +129 -51
  24. warp/fem/space/restriction.py +4 -0
  25. warp/fem/space/shape/tet_shape_function.py +3 -10
  26. warp/jax_experimental/custom_call.py +1 -1
  27. warp/jax_experimental/ffi.py +2 -1
  28. warp/marching_cubes.py +708 -0
  29. warp/native/array.h +99 -4
  30. warp/native/builtin.h +82 -5
  31. warp/native/bvh.cpp +64 -28
  32. warp/native/bvh.cu +58 -58
  33. warp/native/bvh.h +2 -2
  34. warp/native/clang/clang.cpp +7 -7
  35. warp/native/coloring.cpp +8 -2
  36. warp/native/crt.cpp +2 -2
  37. warp/native/crt.h +3 -5
  38. warp/native/cuda_util.cpp +41 -10
  39. warp/native/cuda_util.h +10 -4
  40. warp/native/exports.h +1842 -1908
  41. warp/native/fabric.h +2 -1
  42. warp/native/hashgrid.cpp +37 -37
  43. warp/native/hashgrid.cu +2 -2
  44. warp/native/initializer_array.h +1 -1
  45. warp/native/intersect.h +2 -2
  46. warp/native/mat.h +1910 -116
  47. warp/native/mathdx.cpp +43 -43
  48. warp/native/mesh.cpp +24 -24
  49. warp/native/mesh.cu +26 -26
  50. warp/native/mesh.h +4 -2
  51. warp/native/nanovdb/GridHandle.h +179 -12
  52. warp/native/nanovdb/HostBuffer.h +8 -7
  53. warp/native/nanovdb/NanoVDB.h +517 -895
  54. warp/native/nanovdb/NodeManager.h +323 -0
  55. warp/native/nanovdb/PNanoVDB.h +2 -2
  56. warp/native/quat.h +331 -14
  57. warp/native/range.h +7 -1
  58. warp/native/reduce.cpp +10 -10
  59. warp/native/reduce.cu +13 -14
  60. warp/native/runlength_encode.cpp +2 -2
  61. warp/native/runlength_encode.cu +5 -5
  62. warp/native/scan.cpp +3 -3
  63. warp/native/scan.cu +4 -4
  64. warp/native/sort.cpp +10 -10
  65. warp/native/sort.cu +22 -22
  66. warp/native/sparse.cpp +8 -8
  67. warp/native/sparse.cu +13 -13
  68. warp/native/spatial.h +366 -17
  69. warp/native/temp_buffer.h +2 -2
  70. warp/native/tile.h +283 -69
  71. warp/native/vec.h +381 -14
  72. warp/native/volume.cpp +54 -54
  73. warp/native/volume.cu +1 -1
  74. warp/native/volume.h +2 -1
  75. warp/native/volume_builder.cu +30 -37
  76. warp/native/warp.cpp +150 -149
  77. warp/native/warp.cu +323 -192
  78. warp/native/warp.h +227 -226
  79. warp/optim/linear.py +736 -271
  80. warp/render/imgui_manager.py +289 -0
  81. warp/render/render_opengl.py +85 -6
  82. warp/sim/graph_coloring.py +2 -2
  83. warp/sparse.py +558 -175
  84. warp/tests/aux_test_module_aot.py +7 -0
  85. warp/tests/cuda/test_async.py +3 -3
  86. warp/tests/cuda/test_conditional_captures.py +101 -0
  87. warp/tests/geometry/test_marching_cubes.py +233 -12
  88. warp/tests/sim/test_coloring.py +6 -6
  89. warp/tests/test_array.py +56 -5
  90. warp/tests/test_codegen.py +3 -2
  91. warp/tests/test_context.py +8 -15
  92. warp/tests/test_enum.py +136 -0
  93. warp/tests/test_examples.py +2 -2
  94. warp/tests/test_fem.py +45 -2
  95. warp/tests/test_fixedarray.py +229 -0
  96. warp/tests/test_func.py +18 -15
  97. warp/tests/test_future_annotations.py +7 -5
  98. warp/tests/test_linear_solvers.py +30 -0
  99. warp/tests/test_map.py +1 -1
  100. warp/tests/test_mat.py +1518 -378
  101. warp/tests/test_mat_assign_copy.py +178 -0
  102. warp/tests/test_mat_constructors.py +574 -0
  103. warp/tests/test_module_aot.py +287 -0
  104. warp/tests/test_print.py +69 -0
  105. warp/tests/test_quat.py +140 -34
  106. warp/tests/test_quat_assign_copy.py +145 -0
  107. warp/tests/test_reload.py +2 -1
  108. warp/tests/test_sparse.py +71 -0
  109. warp/tests/test_spatial.py +140 -34
  110. warp/tests/test_spatial_assign_copy.py +160 -0
  111. warp/tests/test_struct.py +43 -3
  112. warp/tests/test_types.py +0 -20
  113. warp/tests/test_vec.py +179 -34
  114. warp/tests/test_vec_assign_copy.py +143 -0
  115. warp/tests/tile/test_tile.py +184 -18
  116. warp/tests/tile/test_tile_cholesky.py +605 -0
  117. warp/tests/tile/test_tile_load.py +169 -0
  118. warp/tests/tile/test_tile_mathdx.py +2 -558
  119. warp/tests/tile/test_tile_matmul.py +1 -1
  120. warp/tests/tile/test_tile_mlp.py +1 -1
  121. warp/tests/tile/test_tile_shared_memory.py +5 -5
  122. warp/tests/unittest_suites.py +6 -0
  123. warp/tests/walkthrough_debug.py +1 -1
  124. warp/thirdparty/unittest_parallel.py +108 -9
  125. warp/types.py +554 -264
  126. warp/utils.py +68 -86
  127. {warp_lang-1.8.1.dist-info → warp_lang-1.9.0.dist-info}/METADATA +28 -65
  128. {warp_lang-1.8.1.dist-info → warp_lang-1.9.0.dist-info}/RECORD +131 -121
  129. warp/native/marching.cpp +0 -19
  130. warp/native/marching.cu +0 -514
  131. warp/native/marching.h +0 -19
  132. {warp_lang-1.8.1.dist-info → warp_lang-1.9.0.dist-info}/WHEEL +0 -0
  133. {warp_lang-1.8.1.dist-info → warp_lang-1.9.0.dist-info}/licenses/LICENSE.md +0 -0
  134. {warp_lang-1.8.1.dist-info → warp_lang-1.9.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,289 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ from __future__ import annotations
17
+
18
+ import warp as wp
19
+
20
+
21
+ class ImGuiManager:
22
+ """Base class for managing an ImGui UI."""
23
+
24
+ def __init__(self, renderer):
25
+ try:
26
+ import imgui
27
+ from imgui.integrations.pyglet import PygletProgrammablePipelineRenderer
28
+
29
+ self.imgui = imgui
30
+ self.is_available = True
31
+ except ImportError:
32
+ self.is_available = False
33
+ print('Warning: imgui not found. To use the UI, please install it with: pip install "imgui[pyglet]"')
34
+ return
35
+
36
+ self.imgui.create_context()
37
+ self.renderer = renderer
38
+ self.impl = PygletProgrammablePipelineRenderer(self.renderer.window)
39
+
40
+ def render_frame(self):
41
+ """Renders a single frame of the UI. This should be called from the main render loop."""
42
+ if not self.is_available:
43
+ return
44
+
45
+ io = self.imgui.get_io()
46
+ self.renderer.enable_mouse_interaction = not io.want_capture_mouse
47
+ self.renderer.enable_keyboard_interaction = not io.want_capture_keyboard
48
+ io.display_size = self.renderer.screen_width, self.renderer.screen_height
49
+
50
+ self.imgui.new_frame()
51
+
52
+ self.draw_ui()
53
+
54
+ self.imgui.render()
55
+ self.imgui.end_frame()
56
+ self.impl.render(self.imgui.get_draw_data())
57
+
58
+ def draw_ui(self):
59
+ """Draws the UI. To be implemented by subclasses."""
60
+ pass
61
+
62
+ def open_save_file_dialog(
63
+ self,
64
+ title: str = "Save File",
65
+ defaultextension: str = "",
66
+ filetypes: list[tuple[str, str]] | None = None,
67
+ ) -> str | None:
68
+ """Opens a file dialog for saving a file and returns the selected path."""
69
+ try:
70
+ import tkinter as tk
71
+ from tkinter import filedialog
72
+ except ImportError:
73
+ print("Warning: tkinter not found. To use the file dialog, please install it.")
74
+ return None
75
+
76
+ try:
77
+ root = tk.Tk()
78
+ except tk.TclError:
79
+ print("Warning: no display found - cannot open file dialog.")
80
+ return None
81
+
82
+ root.withdraw() # Hide the main window
83
+ file_path = filedialog.asksaveasfilename(
84
+ defaultextension=defaultextension,
85
+ filetypes=filetypes or [("All Files", "*.*")],
86
+ title=title,
87
+ )
88
+ root.destroy()
89
+ return file_path
90
+
91
+ def open_load_file_dialog(
92
+ self, title: str = "Open File", filetypes: list[tuple[str, str]] | None = None
93
+ ) -> str | None:
94
+ """Opens a file dialog for loading a file and returns the selected path."""
95
+ try:
96
+ import tkinter as tk
97
+ from tkinter import filedialog
98
+ except ImportError:
99
+ print("Warning: tkinter not found. To use the file dialog, please install it.")
100
+ return None
101
+
102
+ try:
103
+ root = tk.Tk()
104
+ except tk.TclError:
105
+ print("Warning: no display found - cannot open file dialog.")
106
+ return None
107
+
108
+ root.withdraw() # Hide the main window
109
+ file_path = filedialog.askopenfilename(
110
+ filetypes=filetypes or [("All Files", "*.*")],
111
+ title=title,
112
+ )
113
+ root.destroy()
114
+ return file_path
115
+
116
+ def drag_vec3(self, label, vec, speed=0.1, min_val=0.0, max_val=100.0):
117
+ """Helper method to create a drag widget for a wp.vec3"""
118
+ changed, *values = self.imgui.drag_float3(label, *vec, speed, min_val, max_val)
119
+ if changed:
120
+ vec = wp.vec3(*values)
121
+ return changed, vec
122
+
123
+ def drag_vec3_list(
124
+ self,
125
+ label_prefix: str,
126
+ vec_list: list[wp.vec3] | wp.array,
127
+ speed: float = 0.1,
128
+ min_val: float = 0.0,
129
+ max_val: float = 100.0,
130
+ max_num_elements: int = 10,
131
+ ) -> tuple[bool, list[wp.vec3] | wp.array]:
132
+ """Helper method to create drag widgets for a list of wp.vec3.
133
+
134
+ Note: The `label_prefix` is used to create unique IDs for each widget.
135
+ If you are displaying multiple lists, ensure that `label_prefix` is unique
136
+ for each list to prevent UI elements from interfering with each other.
137
+ """
138
+ self.imgui.text(f"List: {label_prefix} with {len(vec_list)} elements")
139
+ changed = False
140
+
141
+ # Convert to numpy array if it's a warp array
142
+ is_warp_array = isinstance(vec_list, wp.array)
143
+ working_array = vec_list.numpy() if is_warp_array else vec_list
144
+
145
+ for i, vec in enumerate(working_array[:max_num_elements]):
146
+ vec_changed, new_vec = self.drag_vec3(f"{label_prefix} {i}", vec, speed, min_val, max_val)
147
+ if vec_changed:
148
+ working_array[i] = new_vec
149
+ changed = True
150
+
151
+ if is_warp_array:
152
+ if changed:
153
+ return changed, wp.array(working_array, dtype=wp.vec3)
154
+ return changed, vec_list
155
+ return changed, working_array
156
+
157
+ def drag_vec2(
158
+ self, label: str, vec: wp.vec2, speed: float = 0.1, min_val: float = 0.0, max_val: float = 100.0
159
+ ) -> tuple[bool, wp.vec2]:
160
+ """Helper method to create a drag widget for a wp.vec2"""
161
+ changed, *values = self.imgui.drag_float2(label, *vec, speed, min_val, max_val)
162
+ if changed:
163
+ vec = wp.vec2(*values)
164
+ return changed, vec
165
+
166
+ def drag_vec2_list(
167
+ self,
168
+ label_prefix: str,
169
+ vec_list: list[wp.vec2] | wp.array,
170
+ speed: float = 0.1,
171
+ min_val: float = 0.0,
172
+ max_val: float = 100.0,
173
+ max_num_elements: int = 10,
174
+ ) -> tuple[bool, list[wp.vec2] | wp.array]:
175
+ """Helper method to create drag widgets for a list of wp.vec2.
176
+
177
+ Note: The `label_prefix` is used to create unique IDs for each widget.
178
+ If you are displaying multiple lists, ensure that `label_prefix` is unique
179
+ for each list to prevent UI elements from interfering with each other.
180
+ """
181
+ self.imgui.text(f"List: {label_prefix} with {len(vec_list)} elements")
182
+ changed = False
183
+
184
+ # Convert to numpy array if it's a warp array
185
+ is_warp_array = isinstance(vec_list, wp.array)
186
+ working_array = vec_list.numpy() if is_warp_array else vec_list
187
+
188
+ for i, vec in enumerate(working_array[:max_num_elements]):
189
+ vec_changed, new_vec = self.drag_vec2(f"{label_prefix} {i}", vec, speed, min_val, max_val)
190
+ if vec_changed:
191
+ working_array[i] = new_vec
192
+ changed = True
193
+
194
+ if is_warp_array:
195
+ if changed:
196
+ return changed, wp.array(working_array, dtype=wp.vec2)
197
+ return changed, vec_list
198
+ return changed, working_array
199
+
200
+ def drag_vec4(
201
+ self, label: str, vec: wp.vec4, speed: float = 0.1, min_val: float = 0.0, max_val: float = 100.0
202
+ ) -> tuple[bool, wp.vec4]:
203
+ """Helper method to create a drag widget for a wp.vec4"""
204
+ changed, *values = self.imgui.drag_float4(label, *vec, speed, min_val, max_val)
205
+ if changed:
206
+ vec = wp.vec4(*values)
207
+ return changed, vec
208
+
209
+ def drag_vec4_list(
210
+ self,
211
+ label_prefix: str,
212
+ vec_list: list[wp.vec4] | wp.array,
213
+ speed: float = 0.1,
214
+ min_val: float = 0.0,
215
+ max_val: float = 100.0,
216
+ max_num_elements: int = 10,
217
+ ) -> tuple[bool, list[wp.vec4] | wp.array]:
218
+ """Helper method to create drag widgets for a list of wp.vec4.
219
+
220
+ Note: The `label_prefix` is used to create unique IDs for each widget.
221
+ If you are displaying multiple lists, ensure that `label_prefix` is unique
222
+ for each list to prevent UI elements from interfering with each other.
223
+ """
224
+ self.imgui.text(f"List: {label_prefix} with {len(vec_list)} elements")
225
+ changed = False
226
+
227
+ # Convert to numpy array if it's a warp array
228
+ is_warp_array = isinstance(vec_list, wp.array)
229
+ working_array = vec_list.numpy() if is_warp_array else vec_list
230
+
231
+ for i, vec in enumerate(working_array[:max_num_elements]):
232
+ vec_changed, new_vec = self.drag_vec4(f"{label_prefix} {i}", vec, speed, min_val, max_val)
233
+ if vec_changed:
234
+ working_array[i] = new_vec
235
+ changed = True
236
+
237
+ if is_warp_array:
238
+ if changed:
239
+ return changed, wp.array(working_array, dtype=wp.vec4)
240
+ return changed, vec_list
241
+ return changed, working_array
242
+
243
+ def drag_float(
244
+ self, label: str, val: float, speed: float = 0.1, min_val: float = 0.0, max_val: float = 100.0
245
+ ) -> tuple[bool, float]:
246
+ """Helper method to create a drag widget for a float"""
247
+ changed, value = self.imgui.drag_float(label, val, speed, min_val, max_val)
248
+ if changed:
249
+ val = value
250
+ return changed, val
251
+
252
+ def drag_float_list(
253
+ self,
254
+ label_prefix: str,
255
+ float_list: list[float] | wp.array,
256
+ speed: float = 0.1,
257
+ min_val: float = 0.0,
258
+ max_val: float = 100.0,
259
+ max_num_elements: int = 10,
260
+ ) -> tuple[bool, list[float] | wp.array]:
261
+ """Helper method to create drag widgets for a list of floats.
262
+
263
+ Note: The `label_prefix` is used to create unique IDs for each widget.
264
+ If you are displaying multiple lists, ensure that `label_prefix` is unique
265
+ for each list to prevent UI elements from interfering with each other.
266
+ """
267
+ self.imgui.text(f"List: {label_prefix} with {len(float_list)} elements")
268
+ changed = False
269
+
270
+ # Convert to numpy array if it's a warp array
271
+ is_warp_array = isinstance(float_list, wp.array)
272
+ working_array = float_list.numpy() if is_warp_array else float_list
273
+
274
+ for i, val in enumerate(working_array[:max_num_elements]):
275
+ val_changed, new_val = self.drag_float(f"{label_prefix} {i}", val, speed, min_val, max_val)
276
+ if val_changed:
277
+ working_array[i] = new_val
278
+ changed = True
279
+
280
+ if is_warp_array:
281
+ if changed:
282
+ return changed, wp.array(working_array, dtype=float_list.dtype)
283
+ return changed, float_list
284
+ return changed, working_array
285
+
286
+ def shutdown(self):
287
+ if not self.is_available:
288
+ return
289
+ self.impl.shutdown()
@@ -998,6 +998,7 @@ class OpenGLRenderer:
998
998
  enable_mouse_interaction=True,
999
999
  enable_keyboard_interaction=True,
1000
1000
  device=None,
1001
+ use_legacy_opengl: bool | None = None,
1001
1002
  ):
1002
1003
  """
1003
1004
  Args:
@@ -1028,6 +1029,7 @@ class OpenGLRenderer:
1028
1029
  enable_mouse_interaction (bool): Whether to enable mouse interaction.
1029
1030
  enable_keyboard_interaction (bool): Whether to enable keyboard interaction.
1030
1031
  device (Devicelike): Where to store the internal data.
1032
+ use_legacy_opengl (bool | None): Whether to use a legacy OpenGL implementation that is more compatible with macOS. If ``None``, it will be automatically detected based on the operating system.
1031
1033
 
1032
1034
  Note:
1033
1035
 
@@ -1073,6 +1075,11 @@ class OpenGLRenderer:
1073
1075
  self.render_depth = render_depth
1074
1076
  self.enable_backface_culling = enable_backface_culling
1075
1077
 
1078
+ if use_legacy_opengl is None:
1079
+ self.use_legacy_opengl = sys.platform == "darwin"
1080
+ else:
1081
+ self.use_legacy_opengl = use_legacy_opengl
1082
+
1076
1083
  if device is None:
1077
1084
  self._device = wp.get_preferred_device()
1078
1085
  else:
@@ -1162,6 +1169,8 @@ class OpenGLRenderer:
1162
1169
  self._wp_instance_bodies = None
1163
1170
  self._update_shape_instances = False
1164
1171
  self._add_shape_instances = False
1172
+ self.instance_matrix_size = 0
1173
+ self.instance_color_size = 0
1165
1174
 
1166
1175
  # additional shape instancer used for points and line rendering
1167
1176
  self._shape_instancers = {}
@@ -2051,9 +2060,43 @@ Instances: {len(self._instances)}"""
2051
2060
  num_instances = len(self._shape_instances[shape])
2052
2061
 
2053
2062
  gl.glBindVertexArray(vao)
2054
- gl.glDrawElementsInstancedBaseInstance(
2055
- gl.GL_TRIANGLES, tri_count, gl.GL_UNSIGNED_INT, None, num_instances, start_instance_idx
2056
- )
2063
+ if self.use_legacy_opengl:
2064
+ if self.instance_matrix_size > 0 and self.instance_color_size:
2065
+ # update attribute pointers
2066
+ matrix_size = self.instance_matrix_size
2067
+ color_size = self.instance_color_size
2068
+
2069
+ # update transforms
2070
+ gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self._instance_transform_gl_buffer)
2071
+ for i in range(4):
2072
+ gl.glVertexAttribPointer(
2073
+ 3 + i,
2074
+ 4,
2075
+ gl.GL_FLOAT,
2076
+ gl.GL_FALSE,
2077
+ matrix_size,
2078
+ ctypes.c_void_p(start_instance_idx * matrix_size + i * matrix_size // 4),
2079
+ )
2080
+ gl.glVertexAttribDivisor(3 + i, 1)
2081
+
2082
+ # update colors
2083
+ gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self._instance_color1_buffer)
2084
+ gl.glVertexAttribPointer(
2085
+ 7, 3, gl.GL_FLOAT, gl.GL_FALSE, color_size, ctypes.c_void_p(start_instance_idx * color_size)
2086
+ )
2087
+ gl.glVertexAttribDivisor(7, 1)
2088
+
2089
+ gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self._instance_color2_buffer)
2090
+ gl.glVertexAttribPointer(
2091
+ 8, 3, gl.GL_FLOAT, gl.GL_FALSE, color_size, ctypes.c_void_p(start_instance_idx * color_size)
2092
+ )
2093
+ gl.glVertexAttribDivisor(8, 1)
2094
+
2095
+ gl.glDrawElementsInstanced(gl.GL_TRIANGLES, tri_count, gl.GL_UNSIGNED_INT, None, num_instances)
2096
+ else:
2097
+ gl.glDrawElementsInstancedBaseInstance(
2098
+ gl.GL_TRIANGLES, tri_count, gl.GL_UNSIGNED_INT, None, num_instances, start_instance_idx
2099
+ )
2057
2100
 
2058
2101
  start_instance_idx += num_instances
2059
2102
 
@@ -2103,9 +2146,43 @@ Instances: {len(self._instances)}"""
2103
2146
  start_instance_idx = self._inverse_instance_ids[instance]
2104
2147
 
2105
2148
  gl.glBindVertexArray(vao)
2106
- gl.glDrawElementsInstancedBaseInstance(
2107
- gl.GL_TRIANGLES, tri_count, gl.GL_UNSIGNED_INT, None, 1, start_instance_idx
2108
- )
2149
+ if self.use_legacy_opengl:
2150
+ if self.instance_matrix_size > 0 and self.instance_color_size:
2151
+ # update attribute pointers
2152
+ matrix_size = self.instance_matrix_size
2153
+ color_size = self.instance_color_size
2154
+
2155
+ # update transforms
2156
+ gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self._instance_transform_gl_buffer)
2157
+ for j in range(4):
2158
+ gl.glVertexAttribPointer(
2159
+ 3 + j,
2160
+ 4,
2161
+ gl.GL_FLOAT,
2162
+ gl.GL_FALSE,
2163
+ matrix_size,
2164
+ ctypes.c_void_p(start_instance_idx * matrix_size + j * matrix_size // 4),
2165
+ )
2166
+ gl.glVertexAttribDivisor(3 + j, 1)
2167
+
2168
+ # update colors
2169
+ gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self._instance_color1_buffer)
2170
+ gl.glVertexAttribPointer(
2171
+ 7, 3, gl.GL_FLOAT, gl.GL_FALSE, color_size, ctypes.c_void_p(start_instance_idx * color_size)
2172
+ )
2173
+ gl.glVertexAttribDivisor(7, 1)
2174
+
2175
+ gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self._instance_color2_buffer)
2176
+ gl.glVertexAttribPointer(
2177
+ 8, 3, gl.GL_FLOAT, gl.GL_FALSE, color_size, ctypes.c_void_p(start_instance_idx * color_size)
2178
+ )
2179
+ gl.glVertexAttribDivisor(8, 1)
2180
+
2181
+ gl.glDrawElementsInstanced(gl.GL_TRIANGLES, tri_count, gl.GL_UNSIGNED_INT, None, 1)
2182
+ else:
2183
+ gl.glDrawElementsInstancedBaseInstance(
2184
+ gl.GL_TRIANGLES, tri_count, gl.GL_UNSIGNED_INT, None, 1, start_instance_idx
2185
+ )
2109
2186
 
2110
2187
  if self.draw_axis:
2111
2188
  self._axis_instancer.render()
@@ -2393,6 +2470,7 @@ Instances: {len(self._instances)}"""
2393
2470
 
2394
2471
  # set up instance attribute pointers
2395
2472
  matrix_size = transforms[0].nbytes
2473
+ self.instance_matrix_size = matrix_size
2396
2474
 
2397
2475
  instance_ids = []
2398
2476
  instance_custom_ids = []
@@ -2401,6 +2479,7 @@ Instances: {len(self._instances)}"""
2401
2479
  inverse_instance_ids = {}
2402
2480
  instance_count = 0
2403
2481
  colors_size = np.zeros(3, dtype=np.float32).nbytes
2482
+ self.instance_color_size = colors_size
2404
2483
  for shape, (vao, _vbo, _ebo, _tri_count, _vertex_cuda_buffer) in self._shape_gl_buffers.items():
2405
2484
  gl.glBindVertexArray(vao)
2406
2485
 
@@ -234,7 +234,7 @@ def color_graph(
234
234
  f"graph_edge_indices must be a 2 dimensional array! The provided one is {graph_edge_indices.ndim} dimensional."
235
235
  )
236
236
 
237
- num_colors = wp.context.runtime.core.graph_coloring(
237
+ num_colors = wp.context.runtime.core.wp_graph_coloring(
238
238
  num_nodes,
239
239
  graph_edge_indices.__ctype__(),
240
240
  algorithm.value,
@@ -242,7 +242,7 @@ def color_graph(
242
242
  )
243
243
 
244
244
  if balance_colors:
245
- max_min_ratio = wp.context.runtime.core.balance_coloring(
245
+ max_min_ratio = wp.context.runtime.core.wp_balance_coloring(
246
246
  num_nodes,
247
247
  graph_edge_indices.__ctype__(),
248
248
  num_colors,