Skip to content

Commit a3e61ea

Browse files
committed
lib: Compute BVHs asynchronously
A new cr_mesh_finalize() API function starts the BVH build task while other meshes are still being loaded to reduce initialization time.
1 parent fb3157c commit a3e61ea

File tree

10 files changed

+56
-40
lines changed

10 files changed

+56
-40
lines changed

bindings/blender_init.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ def sync_scene(self, depsgraph):
323323
facebuf = (c_ray.cr_face * len(faces))(*faces)
324324
cr_mesh.bind_faces(bytearray(facebuf), len(faces))
325325
cr_mesh.bind_vertex_buf(me)
326+
cr_mesh.finalize()
326327

327328
# Set background shader
328329
bl_nodetree = bpy.data.worlds[0].node_tree

bindings/c_ray.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,8 @@ def bind_vertex_buf(self, me):
264264
_lib.mesh_bind_vertex_buf(self.scene_ptr, self.cr_idx, self.v, self.vn, self.n, self.nn, self.t, self.tn)
265265
def bind_faces(self, faces, face_count):
266266
_lib.mesh_bind_faces(self.scene_ptr, self.cr_idx, faces, face_count)
267+
def finalize(self):
268+
_lib.mesh_finalize(self.scene_ptr, self.cr_idx)
267269
def instance_new(self):
268270
self.instances.append(instance(self.scene_ptr, self, 0))
269271
return self.instances[-1]

bindings/cray_wrap.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,19 @@ static PyObject *py_cr_mesh_bind_faces(PyObject *self, PyObject *args) {
424424
Py_RETURN_NONE;
425425
}
426426

427+
static PyObject *py_cr_mesh_finalize(PyObject *self, PyObject *args) {
428+
(void)self; (void)args;
429+
PyObject *s_ext;
430+
cr_mesh mesh;
431+
if (!PyArg_ParseTuple(args, "Ol", &s_ext, &mesh)) {
432+
return NULL;
433+
}
434+
435+
struct cr_scene *s = PyCapsule_GetPointer(s_ext, "cray.cr_scene");
436+
cr_mesh_finalize(s, mesh);
437+
Py_RETURN_NONE;
438+
}
439+
427440
static PyObject *py_cr_scene_mesh_new(PyObject *self, PyObject *args) {
428441
(void)self; (void)args;
429442
PyObject *s_ext;
@@ -732,6 +745,7 @@ static PyMethodDef cray_methods[] = {
732745
{ "scene_add_sphere", py_cr_scene_add_sphere, METH_VARARGS, "" },
733746
{ "mesh_bind_vertex_buf", py_cr_mesh_bind_vertex_buf, METH_VARARGS, "" },
734747
{ "mesh_bind_faces", py_cr_mesh_bind_faces, METH_VARARGS, "" },
748+
{ "mesh_finalize", py_cr_mesh_finalize, METH_VARARGS, "" },
735749
{ "scene_mesh_new", py_cr_scene_mesh_new, METH_VARARGS, "" },
736750
{ "scene_get_mesh", py_cr_scene_get_mesh, METH_VARARGS, "" },
737751
{ "camera_new", py_cr_camera_new, METH_VARARGS, "" },

include/c-ray/c-ray.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ CR_EXPORT cr_mesh cr_scene_get_mesh(struct cr_scene *s_ext, const char *name);
198198

199199
CR_EXPORT void cr_mesh_bind_vertex_buf(struct cr_scene *s_ext, cr_mesh mesh, struct cr_vertex_buf_param buf);
200200
CR_EXPORT void cr_mesh_bind_faces(struct cr_scene *s_ext, cr_mesh mesh, struct cr_face *faces, size_t face_count);
201+
CR_EXPORT void cr_mesh_finalize(struct cr_scene *s_ext, cr_mesh mesh);
201202

202203
// -- Camera --
203204
// FIXME: Use cr_vector

src/lib/accelerators/bvh.c

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@
1616
#include "../datatypes/poly.h"
1717
#include "../renderer/instance.h"
1818
#include "../../common/vector.h"
19-
#include "../../common/platform/thread.h"
20-
#include "../../common/platform/thread_pool.h"
21-
#include "../../common/platform/capabilities.h"
2219
#include "../../common/platform/signal.h"
2320
#include "../../common/timer.h"
2421

@@ -689,32 +686,3 @@ void destroy_bvh(struct bvh *bvh) {
689686
free(bvh);
690687
}
691688

692-
void bvh_build_task(void *arg) {
693-
block_signals();
694-
struct mesh *mesh = (struct mesh *)arg;
695-
struct timeval timer = { 0 };
696-
timer_start(&timer);
697-
mesh->bvh = build_mesh_bvh(mesh);
698-
if (mesh->bvh) {
699-
logr(debug, "Built BVH for %s, took %lums\n", mesh->name, timer_get_ms(timer));
700-
} else {
701-
logr(debug, "BVH build FAILED for %s\n", mesh->name);
702-
}
703-
}
704-
705-
// FIXME: Add pthread_cancel() support
706-
void compute_accels(struct mesh_arr meshes) {
707-
struct cr_thread_pool *pool = thread_pool_create(sys_get_cores());
708-
logr(info, "Updating %zu BVHs: ", meshes.count);
709-
struct timeval timer = { 0 };
710-
timer_start(&timer);
711-
for (size_t i = 0; i < meshes.count; ++i) {
712-
if (!meshes.items[i].bvh) thread_pool_enqueue(pool, bvh_build_task, &meshes.items[i]);
713-
}
714-
thread_pool_wait(pool);
715-
716-
printSmartTime(timer_get_ms(timer));
717-
logr(plain, "\n");
718-
thread_pool_destroy(pool);
719-
}
720-

src/lib/accelerators/bvh.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,3 @@ bool traverse_bottom_level_bvh(
5555

5656
/// Frees the memory allocated by the given BVH
5757
void destroy_bvh(struct bvh *);
58-
59-
void compute_accels(struct mesh_arr meshes);

src/lib/api/c-ray.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "../../common/gitsha1.h"
1919
#include "../../common/fileio.h"
2020
#include "../../common/platform/terminal.h"
21+
#include "../../common/platform/signal.h"
2122
#include "../../common/assert.h"
2223
#include "../../common/texture.h"
2324
#include "../../common/string.h"
@@ -29,6 +30,8 @@
2930
#include "../../common/json_loader.h"
3031
#include "../protocol/protocol.h"
3132
#include "../../common/node_parse.h"
33+
#include "../../common/platform/thread_pool.h"
34+
#include "../accelerators/bvh.h"
3235

3336
#ifdef CRAY_DEBUG_ENABLED
3437
#define DEBUG "D"
@@ -254,6 +257,20 @@ cr_sphere cr_scene_add_sphere(struct cr_scene *s_ext, float radius) {
254257
return sphere_arr_add(&scene->spheres, (struct sphere){ .radius = radius });
255258
}
256259

260+
void bvh_build_task(void *arg) {
261+
block_signals();
262+
struct mesh *mesh = (struct mesh *)arg;
263+
if (mesh->bvh) destroy_bvh(mesh->bvh);
264+
struct timeval timer = { 0 };
265+
timer_start(&timer);
266+
mesh->bvh = build_mesh_bvh(mesh);
267+
if (mesh->bvh) {
268+
logr(debug, "Built BVH for %s, took %lums\n", mesh->name, timer_get_ms(timer));
269+
} else {
270+
logr(debug, "BVH build FAILED for %s\n", mesh->name);
271+
}
272+
}
273+
257274
void cr_mesh_bind_vertex_buf(struct cr_scene *s_ext, cr_mesh mesh, struct cr_vertex_buf_param buf) {
258275
if (!s_ext) return;
259276
struct world *scene = (struct world *)s_ext;
@@ -290,6 +307,14 @@ void cr_mesh_bind_faces(struct cr_scene *s_ext, cr_mesh mesh, struct cr_face *fa
290307
}
291308
}
292309

310+
void cr_mesh_finalize(struct cr_scene *s_ext, cr_mesh mesh) {
311+
if (!s_ext) return;
312+
struct world *scene = (struct world *)s_ext;
313+
if ((size_t)mesh > scene->meshes.count - 1) return;
314+
struct mesh *m = &scene->meshes.items[mesh];
315+
thread_pool_enqueue(scene->bvh_builder, bvh_build_task, m);
316+
}
317+
293318
cr_mesh cr_scene_mesh_new(struct cr_scene *s_ext, const char *name) {
294319
if (!s_ext) return -1;
295320
struct world *scene = (struct world *)s_ext;
@@ -844,6 +869,7 @@ void cr_renderer_restart_interactive(struct cr_renderer *ext) {
844869
r->state.workers.items[i].totalSamples = 0;
845870
}
846871
update_toplevel_bvh(r->scene);
872+
thread_pool_wait(r->scene->bvh_builder);
847873
mutex_release(r->state.current_set->tile_mutex);
848874
}
849875

src/lib/datatypes/scene.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ struct world {
4040
struct cr_rwlock bvh_lock;
4141
struct bvh *topLevel; // FIXME: Move to state?
4242
bool top_level_dirty;
43+
struct cr_thread_pool *bvh_builder;
44+
4345
struct sphere_arr spheres;
4446
struct camera_arr cameras;
4547
struct node_storage storage; // FIXME: Move to state?

src/lib/protocol/worker.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "../../common/texture.h"
2828
#include "../../common/platform/mutex.h"
2929
#include "../../common/platform/thread.h"
30+
#include "../../common/platform/thread_pool.h"
3031
#include "../../common/networking.h"
3132
#include "../../common/string.h"
3233
#include "../../common/gitsha1.h"
@@ -231,9 +232,8 @@ static cJSON *startRender(int connectionSocket, size_t thread_limit) {
231232
struct tile_set set = tile_quantize(selected_cam.width, selected_cam.height, r->prefs.tileWidth, r->prefs.tileHeight, r->prefs.tileOrder);
232233

233234
logr(info, "%u x %u tiles\n", r->prefs.tileWidth, r->prefs.tileHeight);
234-
// Do some pre-render preparations
235-
// Compute BVH acceleration structures for all meshes in the scene
236-
compute_accels(r->scene->meshes);
235+
// Ensure BVHs are up to date
236+
thread_pool_wait(r->scene->bvh_builder);
237237

238238
// And then compute a single top-level BVH that contains all the objects
239239
logr(info, "Computing top-level BVH: ");

src/lib/renderer/renderer.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "../../common/timer.h"
1616
#include "../../common/texture.h"
1717
#include "../../common/platform/thread.h"
18+
#include "../../common/platform/thread_pool.h"
1819
#include "../../common/platform/mutex.h"
1920
#include "../../common/platform/capabilities.h"
2021
#include "../../common/platform/signal.h"
@@ -175,9 +176,10 @@ void renderer_render(struct renderer *r) {
175176
inst->bbuf = &r->scene->shader_buffers.items[inst->bbuf_idx];
176177
}
177178

178-
// Do some pre-render preparations
179-
// Compute BVH acceleration structures for all meshes in the scene
180-
compute_accels(r->scene->meshes);
179+
// Ensure BVHs are up to date
180+
logr(debug, "Waiting for BVH thread pool\n");
181+
thread_pool_wait(r->scene->bvh_builder);
182+
logr(debug, "Continuing\n");
181183

182184
// And compute an initial top-level BVH.
183185
update_toplevel_bvh(r->scene);
@@ -479,11 +481,13 @@ struct renderer *renderer_new(void) {
479481
r->scene->asset_path = stringCopy("./");
480482
r->scene->storage.node_pool = newBlock(NULL, 1024);
481483
r->scene->storage.node_table = newHashtable(compareNodes, &r->scene->storage.node_pool);
484+
r->scene->bvh_builder = thread_pool_create(sys_get_cores());
482485
return r;
483486
}
484487

485488
void renderer_destroy(struct renderer *r) {
486489
if (!r) return;
490+
thread_pool_destroy(r->scene->bvh_builder);
487491
scene_destroy(r->scene);
488492
worker_arr_free(&r->state.workers);
489493
render_client_arr_free(&r->state.clients);

0 commit comments

Comments
 (0)