13 # include "device/metal/bvh.h"
18 # define BVH_status(...) \
20 string str = string_printf(__VA_ARGS__); \
21 progress.set_substatus(str); \
22 metal_printf("%s\n", str.c_str()); \
25 BVHMetal::BVHMetal(
const BVHParams ¶ms_,
29 :
BVH(params_, geometry_, objects_), stats(device->stats)
35 if (@available(macos 12.0, *)) {
37 stats.mem_free(accel_struct.allocatedSize);
38 [accel_struct release];
43 bool BVHMetal::build_BLAS_mesh(
Progress &progress,
45 id<MTLCommandQueue>
queue,
49 if (@available(macos 12.0, *)) {
65 const size_t num_verts =
verts.size();
68 size_t num_motion_steps = 1;
70 if (motion_blur &&
mesh->get_use_motion_blur() && motion_keys) {
71 num_motion_steps =
mesh->get_motion_steps();
74 MTLResourceOptions storage_mode;
75 if (device.hasUnifiedMemory) {
76 storage_mode = MTLResourceStorageModeShared;
79 storage_mode = MTLResourceStorageModeManaged;
83 id<MTLBuffer> posBuf = nil;
84 id<MTLBuffer> indexBuf = [device newBufferWithBytes:tris.
data()
88 if (num_motion_steps == 1) {
89 posBuf = [device newBufferWithBytes:
verts.data()
94 posBuf = [device newBufferWithLength:num_verts * num_motion_steps *
sizeof(
verts.data()[0])
97 size_t center_step = (num_motion_steps - 1) / 2;
98 for (
size_t step = 0; step < num_motion_steps; ++step) {
102 if (step != center_step) {
103 verts = motion_keys->
data_float3() + (step > center_step ? step - 1 : step) * num_verts;
105 memcpy(dest_data + num_verts * step,
verts, num_verts *
sizeof(
float3));
107 if (storage_mode == MTLResourceStorageModeManaged) {
108 [posBuf didModifyRange:NSMakeRange(0, posBuf.length)];
113 MTLAccelerationStructureGeometryDescriptor *geomDesc;
114 if (num_motion_steps > 1) {
115 std::vector<MTLMotionKeyframeData *> vertex_ptrs;
116 vertex_ptrs.reserve(num_motion_steps);
117 for (
size_t step = 0; step < num_motion_steps; ++step) {
118 MTLMotionKeyframeData *k = [MTLMotionKeyframeData
data];
120 k.offset = num_verts * step *
sizeof(
float3);
121 vertex_ptrs.push_back(k);
124 MTLAccelerationStructureMotionTriangleGeometryDescriptor *geomDescMotion =
125 [MTLAccelerationStructureMotionTriangleGeometryDescriptor
descriptor];
126 geomDescMotion.vertexBuffers = [NSArray arrayWithObjects:vertex_ptrs.data()
127 count:vertex_ptrs.size()];
128 geomDescMotion.vertexStride =
sizeof(
verts.data()[0]);
129 geomDescMotion.indexBuffer = indexBuf;
130 geomDescMotion.indexBufferOffset = 0;
131 geomDescMotion.indexType = MTLIndexTypeUInt32;
133 geomDescMotion.intersectionFunctionTableOffset = 0;
135 geomDesc = geomDescMotion;
138 MTLAccelerationStructureTriangleGeometryDescriptor *geomDescNoMotion =
139 [MTLAccelerationStructureTriangleGeometryDescriptor
descriptor];
140 geomDescNoMotion.vertexBuffer = posBuf;
141 geomDescNoMotion.vertexBufferOffset = 0;
142 geomDescNoMotion.vertexStride =
sizeof(
verts.data()[0]);
143 geomDescNoMotion.indexBuffer = indexBuf;
144 geomDescNoMotion.indexBufferOffset = 0;
145 geomDescNoMotion.indexType = MTLIndexTypeUInt32;
147 geomDescNoMotion.intersectionFunctionTableOffset = 0;
149 geomDesc = geomDescNoMotion;
155 geomDesc.allowDuplicateIntersectionFunctionInvocation =
false;
157 MTLPrimitiveAccelerationStructureDescriptor *accelDesc =
158 [MTLPrimitiveAccelerationStructureDescriptor
descriptor];
159 accelDesc.geometryDescriptors = @[ geomDesc ];
160 if (num_motion_steps > 1) {
161 accelDesc.motionStartTime = 0.0f;
162 accelDesc.motionEndTime = 1.0f;
163 accelDesc.motionStartBorderMode = MTLMotionBorderModeClamp;
164 accelDesc.motionEndBorderMode = MTLMotionBorderModeClamp;
165 accelDesc.motionKeyframeCount = num_motion_steps;
168 if (!use_fast_trace_bvh) {
169 accelDesc.usage |= (MTLAccelerationStructureUsageRefit |
170 MTLAccelerationStructureUsagePreferFastBuild);
173 MTLAccelerationStructureSizes accelSizes = [device
174 accelerationStructureSizesWithDescriptor:accelDesc];
175 id<MTLAccelerationStructure> accel_uncompressed = [device
176 newAccelerationStructureWithSize:accelSizes.accelerationStructureSize];
177 id<MTLBuffer> scratchBuf = [device newBufferWithLength:accelSizes.buildScratchBufferSize
178 options:MTLResourceStorageModePrivate];
179 id<MTLBuffer> sizeBuf = [device newBufferWithLength:8
options:MTLResourceStorageModeShared];
180 id<MTLCommandBuffer> accelCommands = [
queue commandBuffer];
181 id<MTLAccelerationStructureCommandEncoder> accelEnc =
182 [accelCommands accelerationStructureCommandEncoder];
184 [accelEnc refitAccelerationStructure:accel_struct
186 destination:accel_uncompressed
187 scratchBuffer:scratchBuf
188 scratchBufferOffset:0];
191 [accelEnc buildAccelerationStructure:accel_uncompressed
193 scratchBuffer:scratchBuf
194 scratchBufferOffset:0];
196 if (use_fast_trace_bvh) {
197 [accelEnc writeCompactedAccelerationStructureSize:accel_uncompressed
200 sizeDataType:MTLDataTypeULong];
202 [accelEnc endEncoding];
203 [accelCommands addCompletedHandler:^(id<MTLCommandBuffer> command_buffer) {
205 [scratchBuf release];
209 if (use_fast_trace_bvh) {
213 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
214 id<MTLCommandBuffer> accelCommands = [
queue commandBuffer];
215 id<MTLAccelerationStructureCommandEncoder> accelEnc =
216 [accelCommands accelerationStructureCommandEncoder];
217 id<MTLAccelerationStructure> accel = [device
218 newAccelerationStructureWithSize:compressed_size];
219 [accelEnc copyAndCompactAccelerationStructure:accel_uncompressed
220 toAccelerationStructure:accel];
221 [accelEnc endEncoding];
222 [accelCommands addCompletedHandler:^(id<MTLCommandBuffer> command_buffer) {
223 uint64_t allocated_size = [accel allocatedSize];
224 stats.mem_alloc(allocated_size);
225 accel_struct = accel;
226 [accel_uncompressed release];
227 accel_struct_building =
false;
229 [accelCommands commit];
234 accel_struct = accel_uncompressed;
236 uint64_t allocated_size = [accel_struct allocatedSize];
237 stats.mem_alloc(allocated_size);
238 accel_struct_building =
false;
243 accel_struct_building =
true;
244 [accelCommands commit];
251 bool BVHMetal::build_BLAS_hair(
Progress &progress,
252 id<MTLDevice> device,
253 id<MTLCommandQueue>
queue,
257 if (@available(macos 12.0, *)) {
259 Hair *hair =
static_cast<Hair *
>(geom);
266 "Building hair BLAS | %7d curves | %s", (
int)hair->
num_curves(), geom->
name.c_str());
272 size_t num_motion_steps = 1;
274 if (motion_blur && hair->get_use_motion_blur() && motion_keys) {
275 num_motion_steps = hair->get_motion_steps();
278 const size_t num_aabbs = num_segments * num_motion_steps;
280 MTLResourceOptions storage_mode;
281 if (device.hasUnifiedMemory) {
282 storage_mode = MTLResourceStorageModeShared;
285 storage_mode = MTLResourceStorageModeManaged;
289 id<MTLBuffer> aabbBuf = [device
290 newBufferWithLength:num_aabbs *
sizeof(MTLAxisAlignedBoundingBox)
292 MTLAxisAlignedBoundingBox *aabb_data = (MTLAxisAlignedBoundingBox *)[aabbBuf contents];
295 size_t center_step = (num_motion_steps - 1) / 2;
296 for (
size_t step = 0; step < num_motion_steps; ++step) {
298 const float3 *keys = hair->get_curve_keys().data();
299 if (step != center_step) {
300 size_t attr_offset = (step > center_step) ? step - 1 : step;
302 keys = motion_keys->
data_float3() + attr_offset * hair->get_curve_keys().size();
305 for (
size_t j = 0, i = 0; j < hair->
num_curves(); ++j) {
313 const size_t index = step * num_segments + i;
314 aabb_data[index].min = (MTLPackedFloat3 &)
bounds.min;
315 aabb_data[index].max = (MTLPackedFloat3 &)
bounds.max;
321 if (storage_mode == MTLResourceStorageModeManaged) {
322 [aabbBuf didModifyRange:NSMakeRange(0, aabbBuf.length)];
326 for (
size_t i=0; i<num_aabbs && i < 400; i++) {
327 MTLAxisAlignedBoundingBox& bb = aabb_data[i];
328 printf(
" %d: %.1f,%.1f,%.1f -- %.1f,%.1f,%.1f\n",
int(i), bb.min.x, bb.min.y, bb.min.z, bb.max.x, bb.max.y, bb.max.z);
332 MTLAccelerationStructureGeometryDescriptor *geomDesc;
334 std::vector<MTLMotionKeyframeData *> aabb_ptrs;
335 aabb_ptrs.reserve(num_motion_steps);
336 for (
size_t step = 0; step < num_motion_steps; ++step) {
337 MTLMotionKeyframeData *k = [MTLMotionKeyframeData
data];
339 k.offset = step * num_segments *
sizeof(MTLAxisAlignedBoundingBox);
340 aabb_ptrs.push_back(k);
343 MTLAccelerationStructureMotionBoundingBoxGeometryDescriptor *geomDescMotion =
344 [MTLAccelerationStructureMotionBoundingBoxGeometryDescriptor
descriptor];
345 geomDescMotion.boundingBoxBuffers = [NSArray arrayWithObjects:aabb_ptrs.data()
346 count:aabb_ptrs.size()];
347 geomDescMotion.boundingBoxCount = num_segments;
348 geomDescMotion.boundingBoxStride =
sizeof(aabb_data[0]);
349 geomDescMotion.intersectionFunctionTableOffset = 1;
354 geomDescMotion.allowDuplicateIntersectionFunctionInvocation =
false;
355 geomDescMotion.opaque =
true;
356 geomDesc = geomDescMotion;
359 MTLAccelerationStructureBoundingBoxGeometryDescriptor *geomDescNoMotion =
360 [MTLAccelerationStructureBoundingBoxGeometryDescriptor
descriptor];
361 geomDescNoMotion.boundingBoxBuffer = aabbBuf;
362 geomDescNoMotion.boundingBoxBufferOffset = 0;
363 geomDescNoMotion.boundingBoxCount = int(num_aabbs);
364 geomDescNoMotion.boundingBoxStride =
sizeof(aabb_data[0]);
365 geomDescNoMotion.intersectionFunctionTableOffset = 1;
370 geomDescNoMotion.allowDuplicateIntersectionFunctionInvocation =
false;
371 geomDescNoMotion.opaque =
true;
372 geomDesc = geomDescNoMotion;
375 MTLPrimitiveAccelerationStructureDescriptor *accelDesc =
376 [MTLPrimitiveAccelerationStructureDescriptor
descriptor];
377 accelDesc.geometryDescriptors = @[ geomDesc ];
380 accelDesc.motionStartTime = 0.0f;
381 accelDesc.motionEndTime = 1.0f;
382 accelDesc.motionStartBorderMode = MTLMotionBorderModeVanish;
383 accelDesc.motionEndBorderMode = MTLMotionBorderModeVanish;
384 accelDesc.motionKeyframeCount = num_motion_steps;
387 if (!use_fast_trace_bvh) {
388 accelDesc.usage |= (MTLAccelerationStructureUsageRefit |
389 MTLAccelerationStructureUsagePreferFastBuild);
392 MTLAccelerationStructureSizes accelSizes = [device
393 accelerationStructureSizesWithDescriptor:accelDesc];
394 id<MTLAccelerationStructure> accel_uncompressed = [device
395 newAccelerationStructureWithSize:accelSizes.accelerationStructureSize];
396 id<MTLBuffer> scratchBuf = [device newBufferWithLength:accelSizes.buildScratchBufferSize
397 options:MTLResourceStorageModePrivate];
398 id<MTLBuffer> sizeBuf = [device newBufferWithLength:8
options:MTLResourceStorageModeShared];
399 id<MTLCommandBuffer> accelCommands = [
queue commandBuffer];
400 id<MTLAccelerationStructureCommandEncoder> accelEnc =
401 [accelCommands accelerationStructureCommandEncoder];
403 [accelEnc refitAccelerationStructure:accel_struct
405 destination:accel_uncompressed
406 scratchBuffer:scratchBuf
407 scratchBufferOffset:0];
410 [accelEnc buildAccelerationStructure:accel_uncompressed
412 scratchBuffer:scratchBuf
413 scratchBufferOffset:0];
415 if (use_fast_trace_bvh) {
416 [accelEnc writeCompactedAccelerationStructureSize:accel_uncompressed
419 sizeDataType:MTLDataTypeULong];
421 [accelEnc endEncoding];
422 [accelCommands addCompletedHandler:^(id<MTLCommandBuffer> command_buffer) {
424 [scratchBuf release];
427 if (use_fast_trace_bvh) {
431 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
432 id<MTLCommandBuffer> accelCommands = [
queue commandBuffer];
433 id<MTLAccelerationStructureCommandEncoder> accelEnc =
434 [accelCommands accelerationStructureCommandEncoder];
435 id<MTLAccelerationStructure> accel = [device
436 newAccelerationStructureWithSize:compressed_size];
437 [accelEnc copyAndCompactAccelerationStructure:accel_uncompressed
438 toAccelerationStructure:accel];
439 [accelEnc endEncoding];
440 [accelCommands addCompletedHandler:^(id<MTLCommandBuffer> command_buffer) {
441 uint64_t allocated_size = [accel allocatedSize];
442 stats.mem_alloc(allocated_size);
443 accel_struct = accel;
444 [accel_uncompressed release];
445 accel_struct_building =
false;
447 [accelCommands commit];
452 accel_struct = accel_uncompressed;
454 uint64_t allocated_size = [accel_struct allocatedSize];
455 stats.mem_alloc(allocated_size);
456 accel_struct_building =
false;
461 accel_struct_building =
true;
462 [accelCommands commit];
468 bool BVHMetal::build_BLAS_pointcloud(
Progress &progress,
469 id<MTLDevice> device,
470 id<MTLCommandQueue>
queue,
474 if (@available(macos 12.0, *)) {
482 BVH_status(
"Building pointcloud BLAS | %7d points | %s",
487 const size_t num_points = pointcloud->get_points().size();
488 const float3 *points = pointcloud->get_points().data();
489 const float *radius = pointcloud->get_radius().data();
493 size_t num_motion_steps = 1;
495 if (motion_blur && pointcloud->get_use_motion_blur() && motion_keys) {
496 num_motion_steps = pointcloud->get_motion_steps();
499 const size_t num_aabbs = num_motion_steps * num_points;
501 MTLResourceOptions storage_mode;
502 if (device.hasUnifiedMemory) {
503 storage_mode = MTLResourceStorageModeShared;
506 storage_mode = MTLResourceStorageModeManaged;
510 id<MTLBuffer> aabbBuf = [device
511 newBufferWithLength:num_aabbs *
sizeof(MTLAxisAlignedBoundingBox)
513 MTLAxisAlignedBoundingBox *aabb_data = (MTLAxisAlignedBoundingBox *)[aabbBuf contents];
516 size_t center_step = (num_motion_steps - 1) / 2;
517 for (
size_t step = 0; step < num_motion_steps; ++step) {
519 if (step != center_step) {
520 size_t attr_offset = (step > center_step) ? step - 1 : step;
521 points = motion_keys->
data_float3() + attr_offset * num_points;
524 for (
size_t j = 0; j < num_points; ++j) {
529 const size_t index = step * num_points + j;
530 aabb_data[index].min = (MTLPackedFloat3 &)
bounds.min;
531 aabb_data[index].max = (MTLPackedFloat3 &)
bounds.max;
535 if (storage_mode == MTLResourceStorageModeManaged) {
536 [aabbBuf didModifyRange:NSMakeRange(0, aabbBuf.length)];
540 for (
size_t i=0; i<num_aabbs && i < 400; i++) {
541 MTLAxisAlignedBoundingBox& bb = aabb_data[i];
542 printf(
" %d: %.1f,%.1f,%.1f -- %.1f,%.1f,%.1f\n",
int(i), bb.min.x, bb.min.y, bb.min.z, bb.max.x, bb.max.y, bb.max.z);
546 MTLAccelerationStructureGeometryDescriptor *geomDesc;
548 std::vector<MTLMotionKeyframeData *> aabb_ptrs;
549 aabb_ptrs.reserve(num_motion_steps);
550 for (
size_t step = 0; step < num_motion_steps; ++step) {
551 MTLMotionKeyframeData *k = [MTLMotionKeyframeData
data];
553 k.offset = step * num_points *
sizeof(MTLAxisAlignedBoundingBox);
554 aabb_ptrs.push_back(k);
557 MTLAccelerationStructureMotionBoundingBoxGeometryDescriptor *geomDescMotion =
558 [MTLAccelerationStructureMotionBoundingBoxGeometryDescriptor
descriptor];
559 geomDescMotion.boundingBoxBuffers = [NSArray arrayWithObjects:aabb_ptrs.data()
560 count:aabb_ptrs.size()];
561 geomDescMotion.boundingBoxCount = num_points;
562 geomDescMotion.boundingBoxStride =
sizeof(aabb_data[0]);
563 geomDescMotion.intersectionFunctionTableOffset = 2;
568 geomDescMotion.allowDuplicateIntersectionFunctionInvocation =
false;
569 geomDescMotion.opaque =
true;
570 geomDesc = geomDescMotion;
573 MTLAccelerationStructureBoundingBoxGeometryDescriptor *geomDescNoMotion =
574 [MTLAccelerationStructureBoundingBoxGeometryDescriptor
descriptor];
575 geomDescNoMotion.boundingBoxBuffer = aabbBuf;
576 geomDescNoMotion.boundingBoxBufferOffset = 0;
577 geomDescNoMotion.boundingBoxCount = int(num_aabbs);
578 geomDescNoMotion.boundingBoxStride =
sizeof(aabb_data[0]);
579 geomDescNoMotion.intersectionFunctionTableOffset = 2;
584 geomDescNoMotion.allowDuplicateIntersectionFunctionInvocation =
false;
585 geomDescNoMotion.opaque =
true;
586 geomDesc = geomDescNoMotion;
589 MTLPrimitiveAccelerationStructureDescriptor *accelDesc =
590 [MTLPrimitiveAccelerationStructureDescriptor
descriptor];
591 accelDesc.geometryDescriptors = @[ geomDesc ];
594 accelDesc.motionStartTime = 0.0f;
595 accelDesc.motionEndTime = 1.0f;
596 accelDesc.motionStartBorderMode = MTLMotionBorderModeVanish;
597 accelDesc.motionEndBorderMode = MTLMotionBorderModeVanish;
598 accelDesc.motionKeyframeCount = num_motion_steps;
601 if (!use_fast_trace_bvh) {
602 accelDesc.usage |= (MTLAccelerationStructureUsageRefit |
603 MTLAccelerationStructureUsagePreferFastBuild);
606 MTLAccelerationStructureSizes accelSizes = [device
607 accelerationStructureSizesWithDescriptor:accelDesc];
608 id<MTLAccelerationStructure> accel_uncompressed = [device
609 newAccelerationStructureWithSize:accelSizes.accelerationStructureSize];
610 id<MTLBuffer> scratchBuf = [device newBufferWithLength:accelSizes.buildScratchBufferSize
611 options:MTLResourceStorageModePrivate];
612 id<MTLBuffer> sizeBuf = [device newBufferWithLength:8
options:MTLResourceStorageModeShared];
613 id<MTLCommandBuffer> accelCommands = [
queue commandBuffer];
614 id<MTLAccelerationStructureCommandEncoder> accelEnc =
615 [accelCommands accelerationStructureCommandEncoder];
617 [accelEnc refitAccelerationStructure:accel_struct
619 destination:accel_uncompressed
620 scratchBuffer:scratchBuf
621 scratchBufferOffset:0];
624 [accelEnc buildAccelerationStructure:accel_uncompressed
626 scratchBuffer:scratchBuf
627 scratchBufferOffset:0];
629 if (use_fast_trace_bvh) {
630 [accelEnc writeCompactedAccelerationStructureSize:accel_uncompressed
633 sizeDataType:MTLDataTypeULong];
635 [accelEnc endEncoding];
636 [accelCommands addCompletedHandler:^(id<MTLCommandBuffer> command_buffer) {
638 [scratchBuf release];
641 if (use_fast_trace_bvh) {
645 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
646 id<MTLCommandBuffer> accelCommands = [
queue commandBuffer];
647 id<MTLAccelerationStructureCommandEncoder> accelEnc =
648 [accelCommands accelerationStructureCommandEncoder];
649 id<MTLAccelerationStructure> accel = [device
650 newAccelerationStructureWithSize:compressed_size];
651 [accelEnc copyAndCompactAccelerationStructure:accel_uncompressed
652 toAccelerationStructure:accel];
653 [accelEnc endEncoding];
654 [accelCommands addCompletedHandler:^(id<MTLCommandBuffer> command_buffer) {
655 uint64_t allocated_size = [accel allocatedSize];
656 stats.mem_alloc(allocated_size);
657 accel_struct = accel;
658 [accel_uncompressed release];
659 accel_struct_building =
false;
661 [accelCommands commit];
666 accel_struct = accel_uncompressed;
668 uint64_t allocated_size = [accel_struct allocatedSize];
669 stats.mem_alloc(allocated_size);
670 accel_struct_building =
false;
675 accel_struct_building =
true;
676 [accelCommands commit];
682 bool BVHMetal::build_BLAS(
Progress &progress,
683 id<MTLDevice> device,
684 id<MTLCommandQueue>
queue,
687 if (@available(macos 12.0, *)) {
688 assert(objects.size() == 1 && geometry.size() == 1);
695 return build_BLAS_mesh(progress, device,
queue, geom,
refit);
697 return build_BLAS_hair(progress, device,
queue, geom,
refit);
699 return build_BLAS_pointcloud(progress, device,
queue, geom,
refit);
707 bool BVHMetal::build_TLAS(
Progress &progress,
708 id<MTLDevice> device,
709 id<MTLCommandQueue>
queue,
712 if (@available(macos 12.0, *)) {
717 __block
bool complete_bvh =
false;
718 while (!complete_bvh) {
719 dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
721 for (
Object *ob : objects) {
723 if (!ob->is_traceable())
726 Geometry const *geom = ob->get_geometry();
727 BVHMetal
const *blas =
static_cast<BVHMetal
const *
>(geom->
bvh);
728 if (blas->accel_struct_building) {
729 complete_bvh = false;
734 id<MTLCommandBuffer> command_buffer = [queue commandBuffer];
735 [command_buffer commit];
736 [command_buffer waitUntilCompleted];
746 for (
Object *ob : objects) {
748 if (!ob->is_traceable())
752 if (ob->use_motion()) {
753 num_motion_transforms +=
max((
size_t)1, ob->get_motion().size());
756 num_motion_transforms++;
760 if (num_instances == 0) {
765 BVH_status(
"Building TLAS | %7d instances", (
int)num_instances);
770 NSMutableArray *all_blas = [NSMutableArray
array];
771 unordered_map<BVHMetal const *, int> instance_mapping;
774 auto get_blas_index = [&](BVHMetal
const *blas) {
775 auto it = instance_mapping.find(blas);
776 if (it != instance_mapping.end()) {
780 int blas_index = (int)[all_blas
count];
781 instance_mapping[blas] = blas_index;
782 if (@available(macos 12.0, *)) {
783 [all_blas addObject:blas->accel_struct];
789 MTLResourceOptions storage_mode;
790 if (device.hasUnifiedMemory) {
791 storage_mode = MTLResourceStorageModeShared;
794 storage_mode = MTLResourceStorageModeManaged;
797 size_t instance_size;
799 instance_size =
sizeof(MTLAccelerationStructureMotionInstanceDescriptor);
802 instance_size =
sizeof(MTLAccelerationStructureUserIDInstanceDescriptor);
806 id<MTLBuffer> instanceBuf = [device newBufferWithLength:num_instances * instance_size
808 id<MTLBuffer> motion_transforms_buf = nil;
809 MTLPackedFloat4x3 *motion_transforms =
nullptr;
810 if (motion_blur && num_motion_transforms) {
811 motion_transforms_buf = [device
812 newBufferWithLength:num_motion_transforms *
sizeof(MTLPackedFloat4x3)
814 motion_transforms = (MTLPackedFloat4x3 *)motion_transforms_buf.contents;
818 uint32_t motion_transform_index = 0;
819 for (
Object *ob : objects) {
821 if (!ob->is_traceable())
824 Geometry const *geom = ob->get_geometry();
826 BVHMetal
const *blas =
static_cast<BVHMetal
const *
>(geom->
bvh);
827 uint32_t accel_struct_index = get_blas_index(blas);
844 int object_index = ob->get_device_index();
849 MTLAccelerationStructureMotionInstanceDescriptor *instances =
850 (MTLAccelerationStructureMotionInstanceDescriptor *)[instanceBuf contents];
851 MTLAccelerationStructureMotionInstanceDescriptor &desc = instances[instance_index++];
853 desc.accelerationStructureIndex = accel_struct_index;
854 desc.userID = user_id;
856 desc.motionStartTime = 0.0f;
857 desc.motionEndTime = 1.0f;
858 desc.motionTransformsStartIndex = motion_transform_index;
859 desc.motionStartBorderMode = MTLMotionBorderModeVanish;
860 desc.motionEndBorderMode = MTLMotionBorderModeVanish;
861 desc.intersectionFunctionTableOffset = 0;
863 int key_count = ob->get_motion().size();
865 desc.motionTransformsCount = key_count;
867 Transform *keys = ob->get_motion().data();
868 for (
int i = 0; i < key_count; i++) {
869 float *
t = (
float *)&motion_transforms[motion_transform_index++];
871 auto src = (
float const *)&keys[i];
872 for (
int i = 0; i < 12; i++) {
873 t[i] =
src[(i / 3) + 4 * (i % 3)];
878 desc.motionTransformsCount = 1;
880 float *
t = (
float *)&motion_transforms[motion_transform_index++];
881 if (ob->get_geometry()->is_instanced()) {
883 auto src = (
float const *)&ob->get_tfm();
884 for (
int i = 0; i < 12; i++) {
885 t[i] =
src[(i / 3) + 4 * (i % 3)];
890 t[0] =
t[4] =
t[8] = 1.0f;
895 MTLAccelerationStructureUserIDInstanceDescriptor *instances =
896 (MTLAccelerationStructureUserIDInstanceDescriptor *)[instanceBuf contents];
897 MTLAccelerationStructureUserIDInstanceDescriptor &desc = instances[instance_index++];
899 desc.accelerationStructureIndex = accel_struct_index;
900 desc.userID = user_id;
902 desc.intersectionFunctionTableOffset = 0;
904 float *
t = (
float *)&desc.transformationMatrix;
905 if (ob->get_geometry()->is_instanced()) {
907 auto src = (
float const *)&ob->get_tfm();
908 for (
int i = 0; i < 12; i++) {
909 t[i] =
src[(i / 3) + 4 * (i % 3)];
914 t[0] =
t[4] =
t[8] = 1.0f;
919 if (storage_mode == MTLResourceStorageModeManaged) {
920 [instanceBuf didModifyRange:NSMakeRange(0, instanceBuf.length)];
921 if (motion_transforms_buf) {
922 [motion_transforms_buf didModifyRange:NSMakeRange(0, motion_transforms_buf.length)];
923 assert(num_motion_transforms == motion_transform_index);
927 MTLInstanceAccelerationStructureDescriptor *accelDesc =
928 [MTLInstanceAccelerationStructureDescriptor
descriptor];
929 accelDesc.instanceCount = num_instances;
930 accelDesc.instanceDescriptorType = MTLAccelerationStructureInstanceDescriptorTypeUserID;
931 accelDesc.instanceDescriptorBuffer = instanceBuf;
932 accelDesc.instanceDescriptorBufferOffset = 0;
933 accelDesc.instanceDescriptorStride = instance_size;
934 accelDesc.instancedAccelerationStructures = all_blas;
937 accelDesc.instanceDescriptorType = MTLAccelerationStructureInstanceDescriptorTypeMotion;
938 accelDesc.motionTransformBuffer = motion_transforms_buf;
939 accelDesc.motionTransformCount = num_motion_transforms;
942 if (!use_fast_trace_bvh) {
943 accelDesc.usage |= (MTLAccelerationStructureUsageRefit |
944 MTLAccelerationStructureUsagePreferFastBuild);
947 MTLAccelerationStructureSizes accelSizes = [device
948 accelerationStructureSizesWithDescriptor:accelDesc];
949 id<MTLAccelerationStructure> accel = [device
950 newAccelerationStructureWithSize:accelSizes.accelerationStructureSize];
951 id<MTLBuffer> scratchBuf = [device newBufferWithLength:accelSizes.buildScratchBufferSize
952 options:MTLResourceStorageModePrivate];
953 id<MTLCommandBuffer> accelCommands = [
queue commandBuffer];
954 id<MTLAccelerationStructureCommandEncoder> accelEnc =
955 [accelCommands accelerationStructureCommandEncoder];
957 [accelEnc refitAccelerationStructure:accel_struct
960 scratchBuffer:scratchBuf
961 scratchBufferOffset:0];
964 [accelEnc buildAccelerationStructure:accel
966 scratchBuffer:scratchBuf
967 scratchBufferOffset:0];
969 [accelEnc endEncoding];
970 [accelCommands commit];
971 [accelCommands waitUntilCompleted];
973 if (motion_transforms_buf) {
974 [motion_transforms_buf release];
976 [instanceBuf release];
977 [scratchBuf release];
979 uint64_t allocated_size = [accel allocatedSize];
980 stats.mem_alloc(allocated_size);
983 accel_struct = accel;
985 blas_array.reserve(all_blas.count);
986 for (id<MTLAccelerationStructure> blas in all_blas) {
987 blas_array.push_back(blas);
996 id<MTLDevice> device,
997 id<MTLCommandQueue>
queue,
1000 if (@available(macos 12.0, *)) {
1002 assert(accel_struct);
1006 stats.mem_free(accel_struct.allocatedSize);
1007 [accel_struct release];
1014 return build_BLAS(progress, device,
queue,
refit);
1017 return build_TLAS(progress, device,
queue,
refit);
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a point
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
void refit(btStridingMeshInterface *triangles, const btVector3 &aabbMin, const btVector3 &aabbMax)
void build(btStridingMeshInterface *triangles, bool useQuantizedAabbCompression, const btVector3 &bvhAabbMin, const btVector3 &bvhAabbMax)
Attribute * find(ustring name) const
Curve get_curve(size_t i) const
size_t num_curves() const
size_t num_segments() const
#define CCL_NAMESPACE_END
CCL_NAMESPACE_BEGIN struct Options options
SyclQueue void void * src
ccl_gpu_kernel_postfix int ccl_global int ccl_global int * num_indices
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
@ ATTR_STD_MOTION_VERTEX_POSITION
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
Segment< FEdge *, Vec3r > segment
T length(const vec_base< T, Size > &a)
unsigned __int64 uint64_t
size_t num_triangles() const
Point get_point(int i) const
size_t num_points() const