29 # define __KERNEL_OPTIX__
32 # include <optix_denoiser_tiling.h>
42 # if OPTIX_ABI_VERSION >= 60
43 using ::optixUtilDenoiserInvokeTiled;
45 static OptixResult optixUtilDenoiserSplitImage(
const OptixImage2D &
input,
46 const OptixImage2D &
output,
47 unsigned int overlapWindowSizeInPixels,
48 unsigned int tileWidth,
49 unsigned int tileHeight,
50 std::vector<OptixUtilDenoiserImageTile> &
tiles)
52 if (tileWidth == 0 || tileHeight == 0)
53 return OPTIX_ERROR_INVALID_VALUE;
55 unsigned int inPixelStride = optixUtilGetPixelStride(
input);
56 unsigned int outPixelStride = optixUtilGetPixelStride(
output);
58 int inp_w =
std::min(tileWidth + 2 * overlapWindowSizeInPixels,
input.width);
59 int inp_h =
std::min(tileHeight + 2 * overlapWindowSizeInPixels,
input.height);
60 int inp_y = 0, copied_y = 0;
63 int inputOffsetY = inp_y == 0 ? 0 :
64 std::max((
int)overlapWindowSizeInPixels,
65 inp_h - ((
int)
input.height - inp_y));
66 int copy_y = inp_y == 0 ?
std::min(
input.height, tileHeight + overlapWindowSizeInPixels) :
69 int inp_x = 0, copied_x = 0;
71 int inputOffsetX = inp_x == 0 ? 0 :
72 std::max((
int)overlapWindowSizeInPixels,
73 inp_w - ((
int)
input.width - inp_x));
74 int copy_x = inp_x == 0 ?
std::min(
input.width, tileWidth + overlapWindowSizeInPixels) :
77 OptixUtilDenoiserImageTile
tile;
78 tile.input.data =
input.data + (size_t)(inp_y - inputOffsetY) *
input.rowStrideInBytes +
79 +(size_t)(inp_x - inputOffsetX) * inPixelStride;
80 tile.input.width = inp_w;
81 tile.input.height = inp_h;
82 tile.input.rowStrideInBytes =
input.rowStrideInBytes;
83 tile.input.pixelStrideInBytes =
input.pixelStrideInBytes;
87 (
size_t)inp_x * outPixelStride;
88 tile.output.width = copy_x;
89 tile.output.height = copy_y;
90 tile.output.rowStrideInBytes =
output.rowStrideInBytes;
91 tile.output.pixelStrideInBytes =
output.pixelStrideInBytes;
94 tile.inputOffsetX = inputOffsetX;
95 tile.inputOffsetY = inputOffsetY;
98 inp_x += inp_x == 0 ? tileWidth + overlapWindowSizeInPixels : tileWidth;
100 }
while (inp_x <
static_cast<int>(
input.width));
102 inp_y += inp_y == 0 ? tileHeight + overlapWindowSizeInPixels : tileHeight;
104 }
while (inp_y <
static_cast<int>(
input.height));
106 return OPTIX_SUCCESS;
109 static OptixResult optixUtilDenoiserInvokeTiled(OptixDenoiser denoiser,
111 const OptixDenoiserParams *
params,
112 CUdeviceptr denoiserState,
113 size_t denoiserStateSizeInBytes,
114 const OptixDenoiserGuideLayer *guideLayer,
115 const OptixDenoiserLayer *layers,
116 unsigned int numLayers,
118 size_t scratchSizeInBytes,
119 unsigned int overlapWindowSizeInPixels,
120 unsigned int tileWidth,
121 unsigned int tileHeight)
123 if (!guideLayer || !layers)
124 return OPTIX_ERROR_INVALID_VALUE;
126 std::vector<std::vector<OptixUtilDenoiserImageTile>>
tiles(numLayers);
127 std::vector<std::vector<OptixUtilDenoiserImageTile>> prevTiles(numLayers);
128 for (
unsigned int l = 0;
l < numLayers;
l++) {
129 if (
const OptixResult res = ccl::optixUtilDenoiserSplitImage(layers[
l].
input,
131 overlapWindowSizeInPixels,
137 if (layers[
l].previousOutput.data) {
138 OptixImage2D dummyOutput = layers[
l].previousOutput;
139 if (
const OptixResult res = ccl::optixUtilDenoiserSplitImage(layers[
l].previousOutput,
141 overlapWindowSizeInPixels,
149 std::vector<OptixUtilDenoiserImageTile> albedoTiles;
150 if (guideLayer->albedo.data) {
151 OptixImage2D dummyOutput = guideLayer->albedo;
152 if (
const OptixResult res = ccl::optixUtilDenoiserSplitImage(guideLayer->albedo,
154 overlapWindowSizeInPixels,
161 std::vector<OptixUtilDenoiserImageTile> normalTiles;
162 if (guideLayer->normal.data) {
163 OptixImage2D dummyOutput = guideLayer->normal;
164 if (
const OptixResult res = ccl::optixUtilDenoiserSplitImage(guideLayer->normal,
166 overlapWindowSizeInPixels,
172 std::vector<OptixUtilDenoiserImageTile> flowTiles;
173 if (guideLayer->flow.data) {
174 OptixImage2D dummyOutput = guideLayer->flow;
175 if (
const OptixResult res = ccl::optixUtilDenoiserSplitImage(guideLayer->flow,
177 overlapWindowSizeInPixels,
184 for (
size_t t = 0;
t <
tiles[0].size();
t++) {
185 std::vector<OptixDenoiserLayer> tlayers;
186 for (
unsigned int l = 0;
l < numLayers;
l++) {
187 OptixDenoiserLayer layer = {};
190 if (layers[
l].previousOutput.data)
191 layer.previousOutput = (prevTiles[
l])[
t].
input;
192 tlayers.push_back(layer);
195 OptixDenoiserGuideLayer gl = {};
196 if (guideLayer->albedo.data)
197 gl.albedo = albedoTiles[
t].input;
199 if (guideLayer->normal.data)
200 gl.normal = normalTiles[
t].input;
202 if (guideLayer->flow.data)
203 gl.flow = flowTiles[
t].input;
205 if (
const OptixResult res = optixDenoiserInvoke(denoiser,
209 denoiserStateSizeInBytes,
213 (
tiles[0])[
t].inputOffsetX,
214 (
tiles[0])[
t].inputOffsetY,
219 return OPTIX_SUCCESS;
223 # if OPTIX_ABI_VERSION >= 55
224 static void execute_optix_task(
TaskPool &
pool, OptixTask
task, OptixResult &failure_reason)
226 OptixTask additional_tasks[16];
227 unsigned int num_additional_tasks = 0;
229 const OptixResult
result = optixTaskExecute(
task, additional_tasks, 16, &num_additional_tasks);
230 if (
result == OPTIX_SUCCESS) {
231 for (
unsigned int i = 0; i < num_additional_tasks; ++i) {
233 &execute_optix_task, std::ref(
pool), additional_tasks[i], std::ref(failure_reason)));
244 OptiXDevice::Denoiser::Denoiser(OptiXDevice *device)
245 : device(device),
queue(device),
state(device,
"__denoiser_state", true)
250 : CUDADevice(info, stats, profiler),
252 launch_params(this,
"kernel_params", false),
260 const CUDAContextScope scope(
this);
263 OptixDeviceContextOptions
options = {};
264 # ifdef WITH_CYCLES_LOGGING
266 options.logCallbackFunction = [](
unsigned int level,
const char *,
const char *message,
void *) {
285 options.validationMode = OPTIX_DEVICE_CONTEXT_VALIDATION_MODE_ALL;
287 optix_assert(optixDeviceContextCreate(cuContext, &
options, &
context));
288 # ifdef WITH_CYCLES_LOGGING
289 optix_assert(optixDeviceContextSetLogCallback(
297 launch_params.alloc_to_device(1);
300 OptiXDevice::~OptiXDevice()
303 const CUDAContextScope scope(
this);
305 free_bvh_memory_delayed();
309 launch_params.free();
312 if (optix_module !=
NULL) {
313 optixModuleDestroy(optix_module);
315 for (
unsigned int i = 0; i < 2; ++i) {
316 if (builtin_modules[i] !=
NULL) {
317 optixModuleDestroy(builtin_modules[i]);
320 for (
unsigned int i = 0; i < NUM_PIPELINES; ++i) {
321 if (pipelines[i] !=
NULL) {
322 optixPipelineDestroy(pipelines[i]);
327 if (denoiser_.optix_denoiser !=
nullptr) {
328 optixDenoiserDestroy(denoiser_.optix_denoiser);
331 optixDeviceContextDestroy(
context);
334 unique_ptr<DeviceQueue> OptiXDevice::gpu_queue_create()
336 return make_unique<OptiXDeviceQueue>(
this);
345 string OptiXDevice::compile_kernel_get_common_cflags(
const uint kernel_features)
347 string common_cflags = CUDADevice::compile_kernel_get_common_cflags(kernel_features);
350 const char *optix_sdk_path = getenv(
"OPTIX_ROOT_DIR");
351 if (optix_sdk_path) {
352 common_cflags +=
string_printf(
" -I\"%s/include\"", optix_sdk_path);
357 common_cflags +=
" --keep-device-functions";
360 return common_cflags;
363 bool OptiXDevice::load_kernels(
const uint kernel_features)
371 if (!CUDADevice::load_kernels(kernel_features)) {
380 const CUDAContextScope scope(
this);
383 if (optix_module !=
NULL) {
384 optixModuleDestroy(optix_module);
387 for (
unsigned int i = 0; i < 2; ++i) {
388 if (builtin_modules[i] !=
NULL) {
389 optixModuleDestroy(builtin_modules[i]);
390 builtin_modules[i] =
NULL;
393 for (
unsigned int i = 0; i < NUM_PIPELINES; ++i) {
394 if (pipelines[i] !=
NULL) {
395 optixPipelineDestroy(pipelines[i]);
400 OptixModuleCompileOptions module_options = {};
401 module_options.maxRegisterCount = 0;
404 module_options.optLevel = OPTIX_COMPILE_OPTIMIZATION_LEVEL_0;
405 module_options.debugLevel = OPTIX_COMPILE_DEBUG_LEVEL_FULL;
408 module_options.optLevel = OPTIX_COMPILE_OPTIMIZATION_LEVEL_3;
409 module_options.debugLevel = OPTIX_COMPILE_DEBUG_LEVEL_NONE;
412 module_options.boundValues =
nullptr;
413 module_options.numBoundValues = 0;
414 # if OPTIX_ABI_VERSION >= 55
415 module_options.payloadTypes =
nullptr;
416 module_options.numPayloadTypes = 0;
419 OptixPipelineCompileOptions pipeline_options = {};
421 pipeline_options.usesMotionBlur =
false;
422 pipeline_options.traversableGraphFlags =
423 OPTIX_TRAVERSABLE_GRAPH_FLAG_ALLOW_SINGLE_LEVEL_INSTANCING;
424 pipeline_options.numPayloadValues = 8;
425 pipeline_options.numAttributeValues = 2;
426 pipeline_options.exceptionFlags = OPTIX_EXCEPTION_FLAG_NONE;
427 pipeline_options.pipelineLaunchParamsVariableName =
"kernel_params";
429 pipeline_options.usesPrimitiveTypeFlags = OPTIX_PRIMITIVE_TYPE_FLAGS_TRIANGLE;
432 # if OPTIX_ABI_VERSION >= 55
433 pipeline_options.usesPrimitiveTypeFlags |= OPTIX_PRIMITIVE_TYPE_FLAGS_ROUND_CATMULLROM;
435 pipeline_options.usesPrimitiveTypeFlags |= OPTIX_PRIMITIVE_TYPE_FLAGS_ROUND_CUBIC_BSPLINE;
439 pipeline_options.usesPrimitiveTypeFlags |= OPTIX_PRIMITIVE_TYPE_FLAGS_CUSTOM;
442 pipeline_options.usesPrimitiveTypeFlags |= OPTIX_PRIMITIVE_TYPE_FLAGS_CUSTOM;
451 pipeline_options.usesMotionBlur =
true;
454 pipeline_options.traversableGraphFlags = OPTIX_TRAVERSABLE_GRAPH_FLAG_ALLOW_ANY;
458 string ptx_data, ptx_filename =
path_get(
460 "lib/kernel_optix_shader_raytrace.ptx" :
461 "lib/kernel_optix.ptx");
462 if (use_adaptive_compilation() ||
path_file_size(ptx_filename) == -1) {
463 if (!getenv(
"OPTIX_ROOT_DIR")) {
465 "Missing OPTIX_ROOT_DIR environment variable (which must be set with the path to "
466 "the Optix SDK to be able to compile Optix kernels on demand).");
469 ptx_filename = compile_kernel(
472 "kernel_shader_raytrace" :
477 if (ptx_filename.empty() || !
path_read_text(ptx_filename, ptx_data)) {
478 set_error(
string_printf(
"Failed to load OptiX kernel from '%s'", ptx_filename.c_str()));
482 # if OPTIX_ABI_VERSION >= 84
483 OptixTask
task =
nullptr;
493 if (
result == OPTIX_SUCCESS) {
498 # elif OPTIX_ABI_VERSION >= 55
499 OptixTask
task =
nullptr;
500 OptixResult
result = optixModuleCreateFromPTXWithTasks(
context,
509 if (
result == OPTIX_SUCCESS) {
524 if (
result != OPTIX_SUCCESS) {
525 set_error(
string_printf(
"Failed to load OptiX kernel from '%s' (%s)",
526 ptx_filename.c_str(),
527 optixGetErrorName(
result)));
533 OptixProgramGroup groups[NUM_PROGRAM_GROUPS] = {};
534 OptixProgramGroupDesc group_descs[NUM_PROGRAM_GROUPS] = {};
535 OptixProgramGroupOptions group_options = {};
536 group_descs[PG_RGEN_INTERSECT_CLOSEST].kind = OPTIX_PROGRAM_GROUP_KIND_RAYGEN;
537 group_descs[PG_RGEN_INTERSECT_CLOSEST].raygen.module = optix_module;
538 group_descs[PG_RGEN_INTERSECT_CLOSEST].raygen.entryFunctionName =
539 "__raygen__kernel_optix_integrator_intersect_closest";
540 group_descs[PG_RGEN_INTERSECT_SHADOW].kind = OPTIX_PROGRAM_GROUP_KIND_RAYGEN;
541 group_descs[PG_RGEN_INTERSECT_SHADOW].raygen.module = optix_module;
542 group_descs[PG_RGEN_INTERSECT_SHADOW].raygen.entryFunctionName =
543 "__raygen__kernel_optix_integrator_intersect_shadow";
544 group_descs[PG_RGEN_INTERSECT_SUBSURFACE].kind = OPTIX_PROGRAM_GROUP_KIND_RAYGEN;
545 group_descs[PG_RGEN_INTERSECT_SUBSURFACE].raygen.module = optix_module;
546 group_descs[PG_RGEN_INTERSECT_SUBSURFACE].raygen.entryFunctionName =
547 "__raygen__kernel_optix_integrator_intersect_subsurface";
548 group_descs[PG_RGEN_INTERSECT_VOLUME_STACK].kind = OPTIX_PROGRAM_GROUP_KIND_RAYGEN;
549 group_descs[PG_RGEN_INTERSECT_VOLUME_STACK].raygen.module = optix_module;
550 group_descs[PG_RGEN_INTERSECT_VOLUME_STACK].raygen.entryFunctionName =
551 "__raygen__kernel_optix_integrator_intersect_volume_stack";
552 group_descs[PG_MISS].kind = OPTIX_PROGRAM_GROUP_KIND_MISS;
553 group_descs[PG_MISS].miss.module = optix_module;
554 group_descs[PG_MISS].miss.entryFunctionName =
"__miss__kernel_optix_miss";
555 group_descs[PG_HITD].kind = OPTIX_PROGRAM_GROUP_KIND_HITGROUP;
556 group_descs[PG_HITD].hitgroup.moduleCH = optix_module;
557 group_descs[PG_HITD].hitgroup.entryFunctionNameCH =
"__closesthit__kernel_optix_hit";
558 group_descs[PG_HITD].hitgroup.moduleAH = optix_module;
559 group_descs[PG_HITD].hitgroup.entryFunctionNameAH =
"__anyhit__kernel_optix_visibility_test";
560 group_descs[PG_HITS].kind = OPTIX_PROGRAM_GROUP_KIND_HITGROUP;
561 group_descs[PG_HITS].hitgroup.moduleAH = optix_module;
562 group_descs[PG_HITS].hitgroup.entryFunctionNameAH =
"__anyhit__kernel_optix_shadow_all_hit";
563 group_descs[PG_HITV].kind = OPTIX_PROGRAM_GROUP_KIND_HITGROUP;
564 group_descs[PG_HITV].hitgroup.moduleCH = optix_module;
565 group_descs[PG_HITV].hitgroup.entryFunctionNameCH =
"__closesthit__kernel_optix_hit";
566 group_descs[PG_HITV].hitgroup.moduleAH = optix_module;
567 group_descs[PG_HITV].hitgroup.entryFunctionNameAH =
"__anyhit__kernel_optix_volume_test";
572 OptixBuiltinISOptions builtin_options = {};
573 # if OPTIX_ABI_VERSION >= 55
574 builtin_options.builtinISModuleType = OPTIX_PRIMITIVE_TYPE_ROUND_CATMULLROM;
575 builtin_options.buildFlags = OPTIX_BUILD_FLAG_PREFER_FAST_TRACE |
576 OPTIX_BUILD_FLAG_ALLOW_COMPACTION;
577 builtin_options.curveEndcapFlags = OPTIX_CURVE_ENDCAP_DEFAULT;
579 builtin_options.builtinISModuleType = OPTIX_PRIMITIVE_TYPE_ROUND_CUBIC_BSPLINE;
581 builtin_options.usesMotionBlur =
false;
583 optix_assert(optixBuiltinISModuleGet(
584 context, &module_options, &pipeline_options, &builtin_options, &builtin_modules[0]));
586 group_descs[PG_HITD].hitgroup.moduleIS = builtin_modules[0];
587 group_descs[PG_HITD].hitgroup.entryFunctionNameIS =
nullptr;
588 group_descs[PG_HITS].hitgroup.moduleIS = builtin_modules[0];
589 group_descs[PG_HITS].hitgroup.entryFunctionNameIS =
nullptr;
592 builtin_options.usesMotionBlur =
true;
594 optix_assert(optixBuiltinISModuleGet(
595 context, &module_options, &pipeline_options, &builtin_options, &builtin_modules[1]));
597 group_descs[PG_HITD_MOTION] = group_descs[PG_HITD];
598 group_descs[PG_HITD_MOTION].hitgroup.moduleIS = builtin_modules[1];
599 group_descs[PG_HITS_MOTION] = group_descs[PG_HITS];
600 group_descs[PG_HITS_MOTION].hitgroup.moduleIS = builtin_modules[1];
605 group_descs[PG_HITD].hitgroup.moduleIS = optix_module;
606 group_descs[PG_HITS].hitgroup.moduleIS = optix_module;
607 group_descs[PG_HITD].hitgroup.entryFunctionNameIS =
"__intersection__curve_ribbon";
608 group_descs[PG_HITS].hitgroup.entryFunctionNameIS =
"__intersection__curve_ribbon";
614 group_descs[PG_HITD_POINTCLOUD] = group_descs[PG_HITD];
615 group_descs[PG_HITD_POINTCLOUD].kind = OPTIX_PROGRAM_GROUP_KIND_HITGROUP;
616 group_descs[PG_HITD_POINTCLOUD].hitgroup.moduleIS = optix_module;
617 group_descs[PG_HITD_POINTCLOUD].hitgroup.entryFunctionNameIS =
"__intersection__point";
618 group_descs[PG_HITS_POINTCLOUD] = group_descs[PG_HITS];
619 group_descs[PG_HITS_POINTCLOUD].kind = OPTIX_PROGRAM_GROUP_KIND_HITGROUP;
620 group_descs[PG_HITS_POINTCLOUD].hitgroup.moduleIS = optix_module;
621 group_descs[PG_HITS_POINTCLOUD].hitgroup.entryFunctionNameIS =
"__intersection__point";
626 group_descs[PG_HITL].kind = OPTIX_PROGRAM_GROUP_KIND_HITGROUP;
627 group_descs[PG_HITL].hitgroup.moduleAH = optix_module;
628 group_descs[PG_HITL].hitgroup.entryFunctionNameAH =
"__anyhit__kernel_optix_local_hit";
633 group_descs[PG_RGEN_SHADE_SURFACE_RAYTRACE].kind = OPTIX_PROGRAM_GROUP_KIND_RAYGEN;
634 group_descs[PG_RGEN_SHADE_SURFACE_RAYTRACE].raygen.module = optix_module;
635 group_descs[PG_RGEN_SHADE_SURFACE_RAYTRACE].raygen.entryFunctionName =
636 "__raygen__kernel_optix_integrator_shade_surface_raytrace";
637 group_descs[PG_CALL_SVM_AO].kind = OPTIX_PROGRAM_GROUP_KIND_CALLABLES;
638 group_descs[PG_CALL_SVM_AO].callables.moduleDC = optix_module;
639 group_descs[PG_CALL_SVM_AO].callables.entryFunctionNameDC =
"__direct_callable__svm_node_ao";
640 group_descs[PG_CALL_SVM_BEVEL].kind = OPTIX_PROGRAM_GROUP_KIND_CALLABLES;
641 group_descs[PG_CALL_SVM_BEVEL].callables.moduleDC = optix_module;
642 group_descs[PG_CALL_SVM_BEVEL].callables.entryFunctionNameDC =
643 "__direct_callable__svm_node_bevel";
648 group_descs[PG_RGEN_SHADE_SURFACE_MNEE].kind = OPTIX_PROGRAM_GROUP_KIND_RAYGEN;
649 group_descs[PG_RGEN_SHADE_SURFACE_MNEE].raygen.module = optix_module;
650 group_descs[PG_RGEN_SHADE_SURFACE_MNEE].raygen.entryFunctionName =
651 "__raygen__kernel_optix_integrator_shade_surface_mnee";
654 optix_assert(optixProgramGroupCreate(
655 context, group_descs, NUM_PROGRAM_GROUPS, &group_options,
nullptr, 0, groups));
658 OptixStackSizes stack_size[NUM_PROGRAM_GROUPS] = {};
660 sbt_data.alloc(NUM_PROGRAM_GROUPS);
661 memset(sbt_data.host_pointer, 0,
sizeof(SbtRecord) * NUM_PROGRAM_GROUPS);
662 for (
unsigned int i = 0; i < NUM_PROGRAM_GROUPS; ++i) {
663 optix_assert(optixSbtRecordPackHeader(groups[i], &sbt_data[i]));
664 # if OPTIX_ABI_VERSION >= 84
665 optix_assert(optixProgramGroupGetStackSize(groups[i], &stack_size[i],
nullptr));
667 optix_assert(optixProgramGroupGetStackSize(groups[i], &stack_size[i]));
670 sbt_data.copy_to_device();
673 unsigned int trace_css = stack_size[PG_HITD].cssCH;
675 trace_css =
std::max(trace_css, stack_size[PG_HITD].cssIS + stack_size[PG_HITD].cssAH);
676 trace_css =
std::max(trace_css, stack_size[PG_HITS].cssIS + stack_size[PG_HITS].cssAH);
677 trace_css =
std::max(trace_css, stack_size[PG_HITL].cssIS + stack_size[PG_HITL].cssAH);
678 trace_css =
std::max(trace_css, stack_size[PG_HITV].cssIS + stack_size[PG_HITV].cssAH);
680 stack_size[PG_HITD_MOTION].cssIS + stack_size[PG_HITD_MOTION].cssAH);
682 stack_size[PG_HITS_MOTION].cssIS + stack_size[PG_HITS_MOTION].cssAH);
684 trace_css, stack_size[PG_HITD_POINTCLOUD].cssIS + stack_size[PG_HITD_POINTCLOUD].cssAH);
686 trace_css, stack_size[PG_HITS_POINTCLOUD].cssIS + stack_size[PG_HITS_POINTCLOUD].cssAH);
688 OptixPipelineLinkOptions link_options = {};
689 link_options.maxTraceDepth = 1;
690 # if OPTIX_ABI_VERSION < 84
692 link_options.debugLevel = OPTIX_COMPILE_DEBUG_LEVEL_FULL;
695 link_options.debugLevel = OPTIX_COMPILE_DEBUG_LEVEL_NONE;
702 pipeline_groups.reserve(NUM_PROGRAM_GROUPS);
703 pipeline_groups.push_back(groups[PG_RGEN_SHADE_SURFACE_RAYTRACE]);
704 pipeline_groups.push_back(groups[PG_MISS]);
705 pipeline_groups.push_back(groups[PG_HITD]);
706 pipeline_groups.push_back(groups[PG_HITS]);
707 pipeline_groups.push_back(groups[PG_HITL]);
708 pipeline_groups.push_back(groups[PG_HITV]);
710 pipeline_groups.push_back(groups[PG_HITD_MOTION]);
711 pipeline_groups.push_back(groups[PG_HITS_MOTION]);
714 pipeline_groups.push_back(groups[PG_HITD_POINTCLOUD]);
715 pipeline_groups.push_back(groups[PG_HITS_POINTCLOUD]);
717 pipeline_groups.push_back(groups[PG_CALL_SVM_AO]);
718 pipeline_groups.push_back(groups[PG_CALL_SVM_BEVEL]);
720 optix_assert(optixPipelineCreate(
context,
723 pipeline_groups.data(),
724 pipeline_groups.size(),
727 &pipelines[PIP_SHADE_RAYTRACE]));
730 const unsigned int css = stack_size[PG_RGEN_SHADE_SURFACE_RAYTRACE].cssRG +
731 link_options.maxTraceDepth * trace_css;
732 const unsigned int dss =
std::max(stack_size[PG_CALL_SVM_AO].dssDC,
733 stack_size[PG_CALL_SVM_BEVEL].dssDC);
736 optix_assert(optixPipelineSetStackSize(
737 pipelines[PIP_SHADE_RAYTRACE], 0, dss, css, motion_blur ? 3 : 2));
743 pipeline_groups.reserve(NUM_PROGRAM_GROUPS);
744 pipeline_groups.push_back(groups[PG_RGEN_SHADE_SURFACE_MNEE]);
745 pipeline_groups.push_back(groups[PG_MISS]);
746 pipeline_groups.push_back(groups[PG_HITD]);
747 pipeline_groups.push_back(groups[PG_HITS]);
748 pipeline_groups.push_back(groups[PG_HITL]);
749 pipeline_groups.push_back(groups[PG_HITV]);
751 pipeline_groups.push_back(groups[PG_HITD_MOTION]);
752 pipeline_groups.push_back(groups[PG_HITS_MOTION]);
755 pipeline_groups.push_back(groups[PG_HITD_POINTCLOUD]);
756 pipeline_groups.push_back(groups[PG_HITS_POINTCLOUD]);
758 pipeline_groups.push_back(groups[PG_CALL_SVM_AO]);
759 pipeline_groups.push_back(groups[PG_CALL_SVM_BEVEL]);
761 optix_assert(optixPipelineCreate(
context,
764 pipeline_groups.data(),
765 pipeline_groups.size(),
768 &pipelines[PIP_SHADE_MNEE]));
771 const unsigned int css = stack_size[PG_RGEN_SHADE_SURFACE_MNEE].cssRG +
772 link_options.maxTraceDepth * trace_css;
773 const unsigned int dss = 0;
777 optixPipelineSetStackSize(pipelines[PIP_SHADE_MNEE], 0, dss, css, motion_blur ? 3 : 2));
782 pipeline_groups.reserve(NUM_PROGRAM_GROUPS);
783 pipeline_groups.push_back(groups[PG_RGEN_INTERSECT_CLOSEST]);
784 pipeline_groups.push_back(groups[PG_RGEN_INTERSECT_SHADOW]);
785 pipeline_groups.push_back(groups[PG_RGEN_INTERSECT_SUBSURFACE]);
786 pipeline_groups.push_back(groups[PG_RGEN_INTERSECT_VOLUME_STACK]);
787 pipeline_groups.push_back(groups[PG_MISS]);
788 pipeline_groups.push_back(groups[PG_HITD]);
789 pipeline_groups.push_back(groups[PG_HITS]);
790 pipeline_groups.push_back(groups[PG_HITL]);
791 pipeline_groups.push_back(groups[PG_HITV]);
793 pipeline_groups.push_back(groups[PG_HITD_MOTION]);
794 pipeline_groups.push_back(groups[PG_HITS_MOTION]);
797 pipeline_groups.push_back(groups[PG_HITD_POINTCLOUD]);
798 pipeline_groups.push_back(groups[PG_HITS_POINTCLOUD]);
801 optix_assert(optixPipelineCreate(
context,
804 pipeline_groups.data(),
805 pipeline_groups.size(),
808 &pipelines[PIP_INTERSECT]));
811 const unsigned int css =
812 std::max(stack_size[PG_RGEN_INTERSECT_CLOSEST].cssRG,
813 std::max(stack_size[PG_RGEN_INTERSECT_SHADOW].cssRG,
814 std::max(stack_size[PG_RGEN_INTERSECT_SUBSURFACE].cssRG,
815 stack_size[PG_RGEN_INTERSECT_VOLUME_STACK].cssRG))) +
816 link_options.maxTraceDepth * trace_css;
819 optixPipelineSetStackSize(pipelines[PIP_INTERSECT], 0, 0, css, motion_blur ? 3 : 2));
823 for (
unsigned int i = 0; i < NUM_PROGRAM_GROUPS; ++i) {
824 optixProgramGroupDestroy(groups[i]);
834 class OptiXDevice::DenoiseContext {
838 render_buffers(
task.render_buffers),
839 buffer_params(
task.buffer_params),
843 num_input_passes = 1;
844 if (denoise_params.use_pass_albedo) {
845 num_input_passes += 1;
846 use_pass_albedo =
true;
848 if (denoise_params.use_pass_normal) {
849 num_input_passes += 1;
850 use_pass_normal =
true;
855 if (denoise_params.temporally_stable) {
856 prev_output.device_pointer = render_buffers->buffer.device_pointer;
860 prev_output.stride = buffer_params.stride;
861 prev_output.pass_stride = buffer_params.pass_stride;
863 num_input_passes += 1;
864 use_pass_flow =
true;
865 pass_motion = buffer_params.get_pass_offset(
PASS_MOTION);
868 use_guiding_passes = (num_input_passes - 1) > 0;
870 if (use_guiding_passes) {
871 if (
task.allow_inplace_modification) {
872 guiding_params.device_pointer = render_buffers->buffer.device_pointer;
874 guiding_params.pass_albedo = pass_denoising_albedo;
875 guiding_params.pass_normal = pass_denoising_normal;
876 guiding_params.pass_flow = pass_motion;
878 guiding_params.stride = buffer_params.stride;
879 guiding_params.pass_stride = buffer_params.pass_stride;
882 guiding_params.pass_stride = 0;
883 if (use_pass_albedo) {
884 guiding_params.pass_albedo = guiding_params.pass_stride;
885 guiding_params.pass_stride += 3;
887 if (use_pass_normal) {
888 guiding_params.pass_normal = guiding_params.pass_stride;
889 guiding_params.pass_stride += 3;
892 guiding_params.pass_flow = guiding_params.pass_stride;
893 guiding_params.pass_stride += 2;
896 guiding_params.stride = buffer_params.width;
898 guiding_buffer.alloc_to_device(buffer_params.width * buffer_params.height *
899 guiding_params.pass_stride);
938 int num_input_passes = 0;
939 bool use_guiding_passes =
false;
940 bool use_pass_albedo =
false;
941 bool use_pass_normal =
false;
942 bool use_pass_flow =
false;
956 bool albedo_replaced_with_fake =
false;
959 class OptiXDevice::DenoisePass {
979 bool use_denoising_albedo;
984 const CUDAContextScope scope(
this);
988 if (!denoise_ensure(
context)) {
992 if (!denoise_filter_guiding_preprocess(
context)) {
993 LOG(ERROR) <<
"Error preprocessing guiding passes.";
1009 return &denoiser_.queue;
1012 bool OptiXDevice::denoise_filter_guiding_preprocess(DenoiseContext &
context)
1019 &
context.guiding_params.pass_stride,
1020 &
context.guiding_params.pass_albedo,
1021 &
context.guiding_params.pass_normal,
1022 &
context.guiding_params.pass_flow,
1023 &
context.render_buffers->buffer.device_pointer,
1028 &
context.pass_denoising_albedo,
1029 &
context.pass_denoising_normal,
1033 &buffer_params.
width,
1040 bool OptiXDevice::denoise_filter_guiding_set_fake_albedo(DenoiseContext &
context)
1047 &
context.guiding_params.pass_stride,
1048 &
context.guiding_params.pass_albedo,
1049 &buffer_params.
width,
1055 void OptiXDevice::denoise_pass(DenoiseContext &
context,
PassType pass_type)
1059 const DenoisePass pass(pass_type, buffer_params);
1069 if (pass.use_denoising_albedo) {
1070 if (
context.albedo_replaced_with_fake) {
1071 LOG(ERROR) <<
"Pass which requires albedo is denoised after fake albedo has been set.";
1075 else if (
context.use_guiding_passes && !
context.albedo_replaced_with_fake) {
1076 context.albedo_replaced_with_fake =
true;
1077 if (!denoise_filter_guiding_set_fake_albedo(
context)) {
1078 LOG(ERROR) <<
"Error replacing real albedo with the fake one.";
1084 denoise_color_read(
context, pass);
1085 if (!denoise_filter_color_preprocess(
context, pass)) {
1086 LOG(ERROR) <<
"Error connverting denoising passes to RGB buffer.";
1090 if (!denoise_run(
context, pass)) {
1091 LOG(ERROR) <<
"Error running OptiX denoiser.";
1098 if (!denoise_filter_color_postprocess(
context, pass)) {
1099 LOG(ERROR) <<
"Error copying denoiser result to the denoised pass.";
1103 denoiser_.queue.synchronize();
1106 void OptiXDevice::denoise_color_read(DenoiseContext &
context,
const DenoisePass &pass)
1109 pass_access_info.
type = pass.type;
1111 pass_access_info.
offset = pass.noisy_offset;
1123 &denoiser_.queue, pass_access_info, 1.0f,
context.num_samples);
1126 destination.d_pixels =
context.render_buffers->buffer.device_pointer +
1127 pass.denoised_offset *
sizeof(
float);
1128 destination.num_components = 3;
1129 destination.pixel_stride =
context.buffer_params.pass_stride;
1137 pass_accessor.get_render_tile_pixels(
context.render_buffers, buffer_params, destination);
1140 bool OptiXDevice::denoise_filter_color_preprocess(DenoiseContext &
context,
const DenoisePass &pass)
1149 &buffer_params.
width,
1154 &pass.denoised_offset);
1159 bool OptiXDevice::denoise_filter_color_postprocess(DenoiseContext &
context,
1160 const DenoisePass &pass)
1169 &buffer_params.
width,
1176 &pass.denoised_offset,
1178 &pass.num_components,
1179 &pass.use_compositing);
1184 bool OptiXDevice::denoise_ensure(DenoiseContext &
context)
1186 if (!denoise_create_if_needed(
context)) {
1187 LOG(ERROR) <<
"OptiX denoiser creation has failed.";
1191 if (!denoise_configure_if_needed(
context)) {
1192 LOG(ERROR) <<
"OptiX denoiser configuration has failed.";
1199 bool OptiXDevice::denoise_create_if_needed(DenoiseContext &
context)
1201 const bool recreate_denoiser = (denoiser_.optix_denoiser ==
nullptr) ||
1202 (denoiser_.use_pass_albedo !=
context.use_pass_albedo) ||
1203 (denoiser_.use_pass_normal !=
context.use_pass_normal) ||
1204 (denoiser_.use_pass_flow !=
context.use_pass_flow);
1205 if (!recreate_denoiser) {
1210 if (denoiser_.optix_denoiser) {
1211 optixDenoiserDestroy(denoiser_.optix_denoiser);
1215 OptixDenoiserOptions denoiser_options = {};
1216 denoiser_options.guideAlbedo =
context.use_pass_albedo;
1217 denoiser_options.guideNormal =
context.use_pass_normal;
1219 OptixDenoiserModelKind model = OPTIX_DENOISER_MODEL_KIND_HDR;
1221 model = OPTIX_DENOISER_MODEL_KIND_TEMPORAL;
1224 const OptixResult
result = optixDenoiserCreate(
1225 this->context, model, &denoiser_options, &denoiser_.optix_denoiser);
1227 if (
result != OPTIX_SUCCESS) {
1228 set_error(
"Failed to create OptiX denoiser");
1233 denoiser_.use_pass_albedo =
context.use_pass_albedo;
1234 denoiser_.use_pass_normal =
context.use_pass_normal;
1235 denoiser_.use_pass_flow =
context.use_pass_flow;
1238 denoiser_.is_configured =
false;
1243 bool OptiXDevice::denoise_configure_if_needed(DenoiseContext &
context)
1249 if (denoiser_.is_configured &&
1250 (denoiser_.configured_size.x == tile_size.
x && denoiser_.configured_size.y == tile_size.
y)) {
1254 optix_assert(optixDenoiserComputeMemoryResources(
1255 denoiser_.optix_denoiser, tile_size.
x, tile_size.
y, &denoiser_.sizes));
1258 denoiser_.state.alloc_to_device(denoiser_.sizes.stateSizeInBytes +
1259 denoiser_.sizes.withOverlapScratchSizeInBytes);
1262 const OptixResult
result = optixDenoiserSetup(
1263 denoiser_.optix_denoiser,
1266 tile_size.
x + denoiser_.sizes.overlapWindowSizeInPixels * 2,
1267 tile_size.
y + denoiser_.sizes.overlapWindowSizeInPixels * 2,
1268 denoiser_.state.device_pointer,
1269 denoiser_.sizes.stateSizeInBytes,
1270 denoiser_.state.device_pointer + denoiser_.sizes.stateSizeInBytes,
1271 denoiser_.sizes.withOverlapScratchSizeInBytes);
1272 if (
result != OPTIX_SUCCESS) {
1273 set_error(
"Failed to set up OptiX denoiser");
1277 cuda_assert(cuCtxSynchronize());
1279 denoiser_.is_configured =
true;
1280 denoiser_.configured_size = tile_size;
1285 bool OptiXDevice::denoise_run(DenoiseContext &
context,
const DenoisePass &pass)
1292 OptixImage2D color_layer = {0};
1293 OptixImage2D albedo_layer = {0};
1294 OptixImage2D normal_layer = {0};
1295 OptixImage2D flow_layer = {0};
1297 OptixImage2D output_layer = {0};
1298 OptixImage2D prev_output_layer = {0};
1305 color_layer.data =
context.render_buffers->buffer.device_pointer +
1307 color_layer.width =
width;
1308 color_layer.height =
height;
1309 color_layer.rowStrideInBytes = pass_stride_in_bytes *
context.buffer_params.stride;
1310 color_layer.pixelStrideInBytes = pass_stride_in_bytes;
1311 color_layer.format = OPTIX_PIXEL_FORMAT_FLOAT3;
1318 prev_output_layer.data =
context.prev_output.device_pointer +
1320 prev_output_layer.width =
width;
1321 prev_output_layer.height =
height;
1322 prev_output_layer.rowStrideInBytes = pass_stride_in_bytes *
context.prev_output.stride;
1323 prev_output_layer.pixelStrideInBytes = pass_stride_in_bytes;
1324 prev_output_layer.format = OPTIX_PIXEL_FORMAT_FLOAT3;
1328 if (
context.num_input_passes > 1) {
1331 const int64_t row_stride_in_bytes =
context.guiding_params.stride * pixel_stride_in_bytes;
1333 if (
context.use_pass_albedo) {
1334 albedo_layer.data = d_guiding_buffer +
context.guiding_params.pass_albedo *
sizeof(
float);
1335 albedo_layer.width =
width;
1336 albedo_layer.height =
height;
1337 albedo_layer.rowStrideInBytes = row_stride_in_bytes;
1338 albedo_layer.pixelStrideInBytes = pixel_stride_in_bytes;
1339 albedo_layer.format = OPTIX_PIXEL_FORMAT_FLOAT3;
1342 if (
context.use_pass_normal) {
1343 normal_layer.data = d_guiding_buffer +
context.guiding_params.pass_normal *
sizeof(
float);
1344 normal_layer.width =
width;
1345 normal_layer.height =
height;
1346 normal_layer.rowStrideInBytes = row_stride_in_bytes;
1347 normal_layer.pixelStrideInBytes = pixel_stride_in_bytes;
1348 normal_layer.format = OPTIX_PIXEL_FORMAT_FLOAT3;
1352 flow_layer.data = d_guiding_buffer +
context.guiding_params.pass_flow *
sizeof(
float);
1353 flow_layer.width =
width;
1354 flow_layer.height =
height;
1355 flow_layer.rowStrideInBytes = row_stride_in_bytes;
1356 flow_layer.pixelStrideInBytes = pixel_stride_in_bytes;
1357 flow_layer.format = OPTIX_PIXEL_FORMAT_FLOAT2;
1362 output_layer = color_layer;
1364 OptixDenoiserGuideLayer guide_layers = {};
1365 guide_layers.albedo = albedo_layer;
1366 guide_layers.normal = normal_layer;
1367 guide_layers.flow = flow_layer;
1369 OptixDenoiserLayer image_layers = {};
1370 image_layers.input = color_layer;
1371 image_layers.previousOutput = prev_output_layer;
1372 image_layers.output = output_layer;
1375 OptixDenoiserParams
params = {};
1377 optix_assert(ccl::optixUtilDenoiserInvokeTiled(denoiser_.optix_denoiser,
1378 denoiser_.queue.stream(),
1380 denoiser_.state.device_pointer,
1381 denoiser_.sizes.stateSizeInBytes,
1385 denoiser_.state.device_pointer +
1386 denoiser_.sizes.stateSizeInBytes,
1387 denoiser_.sizes.withOverlapScratchSizeInBytes,
1388 denoiser_.sizes.overlapWindowSizeInPixels,
1389 denoiser_.configured_size.x,
1390 denoiser_.configured_size.y));
1395 bool OptiXDevice::build_optix_bvh(BVHOptiX *bvh,
1396 OptixBuildOperation operation,
1397 const OptixBuildInput &build_input,
1407 const CUDAContextScope scope(
this);
1409 const bool use_fast_trace_bvh = (bvh->params.bvh_type ==
BVH_TYPE_STATIC);
1412 OptixAccelBufferSizes sizes = {};
1413 OptixAccelBuildOptions
options = {};
1414 options.operation = operation;
1415 if (use_fast_trace_bvh ||
1418 build_input.type == OPTIX_BUILD_INPUT_TYPE_CURVES) {
1419 VLOG_INFO <<
"Using fast to trace OptiX BVH";
1420 options.buildFlags = OPTIX_BUILD_FLAG_PREFER_FAST_TRACE | OPTIX_BUILD_FLAG_ALLOW_COMPACTION;
1423 VLOG_INFO <<
"Using fast to update OptiX BVH";
1424 options.buildFlags = OPTIX_BUILD_FLAG_PREFER_FAST_BUILD | OPTIX_BUILD_FLAG_ALLOW_UPDATE;
1427 options.motionOptions.numKeys = num_motion_steps;
1428 options.motionOptions.flags = OPTIX_MOTION_FLAG_START_VANISH | OPTIX_MOTION_FLAG_END_VANISH;
1429 options.motionOptions.timeBegin = 0.0f;
1430 options.motionOptions.timeEnd = 1.0f;
1432 optix_assert(optixAccelComputeMemoryUsage(
context, &
options, &build_input, 1, &sizes));
1436 temp_mem.alloc_to_device(
align_up(sizes.tempSizeInBytes, 8) + 8);
1437 if (!temp_mem.device_pointer) {
1444 if (operation == OPTIX_BUILD_OPERATION_BUILD) {
1445 assert(out_data.
device ==
this);
1456 OptixAccelEmitDesc compacted_size_prop = {};
1457 compacted_size_prop.type = OPTIX_PROPERTY_TYPE_COMPACTED_SIZE;
1460 compacted_size_prop.result =
align_up(temp_mem.device_pointer + sizes.tempSizeInBytes, 8);
1462 OptixTraversableHandle out_handle = 0;
1463 optix_assert(optixAccelBuild(
context,
1468 temp_mem.device_pointer,
1469 sizes.tempSizeInBytes,
1471 sizes.outputSizeInBytes,
1473 use_fast_trace_bvh ? &compacted_size_prop :
NULL,
1474 use_fast_trace_bvh ? 1 : 0));
1475 bvh->traversable_handle =
static_cast<uint64_t>(out_handle);
1478 cuda_assert(cuStreamSynchronize(
NULL));
1482 if (use_fast_trace_bvh) {
1483 uint64_t compacted_size = sizes.outputSizeInBytes;
1484 cuda_assert(cuMemcpyDtoH(&compacted_size, compacted_size_prop.result,
sizeof(compacted_size)));
1490 if (compacted_size < sizes.outputSizeInBytes) {
1492 compacted_data.alloc_to_device(compacted_size);
1493 if (!compacted_data.device_pointer) {
1496 return !have_error();
1499 optix_assert(optixAccelCompact(
1500 context,
NULL, out_handle, compacted_data.device_pointer, compacted_size, &out_handle));
1501 bvh->traversable_handle =
static_cast<uint64_t>(out_handle);
1504 cuda_assert(cuStreamSynchronize(
NULL));
1513 return !have_error();
1520 free_bvh_memory_delayed();
1522 BVHOptiX *
const bvh_optix =
static_cast<BVHOptiX *
>(bvh);
1524 progress.
set_substatus(
"Building OptiX acceleration structure");
1531 OptixBuildOperation operation = OPTIX_BUILD_OPERATION_BUILD;
1532 if (
refit && !use_fast_trace_bvh) {
1533 assert(bvh_optix->traversable_handle != 0);
1534 operation = OPTIX_BUILD_OPERATION_UPDATE;
1537 bvh_optix->as_data->free();
1538 bvh_optix->traversable_handle = 0;
1545 Hair *
const hair =
static_cast<Hair *const
>(geom);
1552 size_t num_motion_steps = 1;
1554 if (motion_blur && hair->get_use_motion_blur() && motion_keys) {
1555 num_motion_steps = hair->get_motion_steps();
1562 const size_t num_vertices = num_segments * 4;
1564 index_data.alloc(num_segments);
1565 vertex_data.alloc(num_vertices * num_motion_steps);
1568 aabb_data.alloc(num_segments * num_motion_steps);
1571 for (
size_t step = 0; step < num_motion_steps; ++step) {
1573 const float3 *keys = hair->get_curve_keys().data();
1574 size_t center_step = (num_motion_steps - 1) / 2;
1575 if (step != center_step) {
1576 size_t attr_offset = (step > center_step) ? step - 1 : step;
1578 keys = motion_keys->
data_float3() + attr_offset * hair->get_curve_keys().size();
1581 for (
size_t j = 0, i = 0; j < hair->
num_curves(); ++j) {
1583 const array<float> &curve_radius = hair->get_curve_radius();
1589 int ka =
max(k0 - 1,
curve.first_key);
1592 index_data[i] = i * 4;
1593 float4 *
const v = vertex_data.data() + step * num_vertices + index_data[i];
1595 # if OPTIX_ABI_VERSION >= 55
1596 v[0] =
make_float4(keys[ka].
x, keys[ka].
y, keys[ka].
z, curve_radius[ka]);
1597 v[1] =
make_float4(keys[k0].
x, keys[k0].
y, keys[k0].
z, curve_radius[k0]);
1598 v[2] =
make_float4(keys[k1].
x, keys[k1].
y, keys[k1].
z, curve_radius[k1]);
1599 v[3] =
make_float4(keys[kb].
x, keys[kb].
y, keys[kb].
z, curve_radius[kb]);
1605 curve_radius[ka], curve_radius[k0], curve_radius[k1], curve_radius[kb]);
1614 dot(cr2bsp0, px),
dot(cr2bsp0, py),
dot(cr2bsp0, pz),
dot(cr2bsp0, pw));
1616 dot(cr2bsp1, px),
dot(cr2bsp1, py),
dot(cr2bsp1, pz),
dot(cr2bsp1, pw));
1618 dot(cr2bsp2, px),
dot(cr2bsp2, py),
dot(cr2bsp2, pz),
dot(cr2bsp2, pw));
1620 dot(cr2bsp3, px),
dot(cr2bsp3, py),
dot(cr2bsp3, pz),
dot(cr2bsp3, pw));
1627 const size_t index = step * num_segments + i;
1628 aabb_data[index].minX =
bounds.min.x;
1629 aabb_data[index].minY =
bounds.min.y;
1630 aabb_data[index].minZ =
bounds.min.z;
1631 aabb_data[index].maxX =
bounds.max.x;
1632 aabb_data[index].maxY =
bounds.max.y;
1633 aabb_data[index].maxZ =
bounds.max.z;
1640 aabb_data.copy_to_device();
1641 index_data.copy_to_device();
1642 vertex_data.copy_to_device();
1645 aabb_ptrs.reserve(num_motion_steps);
1648 width_ptrs.reserve(num_motion_steps);
1649 vertex_ptrs.reserve(num_motion_steps);
1650 for (
size_t step = 0; step < num_motion_steps; ++step) {
1651 aabb_ptrs.push_back(aabb_data.device_pointer + step * num_segments *
sizeof(OptixAabb));
1652 const device_ptr base_ptr = vertex_data.device_pointer +
1653 step * num_vertices *
sizeof(
float4);
1654 width_ptrs.push_back(base_ptr + 3 *
sizeof(
float));
1655 vertex_ptrs.push_back(base_ptr);
1659 unsigned int build_flags = OPTIX_GEOMETRY_FLAG_REQUIRE_SINGLE_ANYHIT_CALL;
1660 OptixBuildInput build_input = {};
1662 build_input.type = OPTIX_BUILD_INPUT_TYPE_CURVES;
1663 # if OPTIX_ABI_VERSION >= 55
1664 build_input.curveArray.curveType = OPTIX_PRIMITIVE_TYPE_ROUND_CATMULLROM;
1666 build_input.curveArray.curveType = OPTIX_PRIMITIVE_TYPE_ROUND_CUBIC_BSPLINE;
1668 build_input.curveArray.numPrimitives = num_segments;
1669 build_input.curveArray.vertexBuffers = (CUdeviceptr *)vertex_ptrs.data();
1670 build_input.curveArray.numVertices = num_vertices;
1671 build_input.curveArray.vertexStrideInBytes =
sizeof(
float4);
1672 build_input.curveArray.widthBuffers = (CUdeviceptr *)width_ptrs.data();
1673 build_input.curveArray.widthStrideInBytes =
sizeof(
float4);
1674 build_input.curveArray.indexBuffer = (CUdeviceptr)index_data.device_pointer;
1675 build_input.curveArray.indexStrideInBytes =
sizeof(
int);
1676 build_input.curveArray.flag = build_flags;
1682 build_flags |= OPTIX_GEOMETRY_FLAG_DISABLE_ANYHIT;
1684 build_input.type = OPTIX_BUILD_INPUT_TYPE_CUSTOM_PRIMITIVES;
1685 build_input.customPrimitiveArray.aabbBuffers = (CUdeviceptr *)aabb_ptrs.data();
1686 build_input.customPrimitiveArray.numPrimitives = num_segments;
1687 build_input.customPrimitiveArray.strideInBytes =
sizeof(OptixAabb);
1688 build_input.customPrimitiveArray.flags = &build_flags;
1689 build_input.customPrimitiveArray.numSbtRecords = 1;
1693 if (!build_optix_bvh(bvh_optix, operation, build_input, num_motion_steps)) {
1694 progress.
set_error(
"Failed to build OptiX acceleration structure");
1704 const size_t num_verts =
mesh->get_verts().
size();
1706 size_t num_motion_steps = 1;
1708 if (motion_blur &&
mesh->get_use_motion_blur() && motion_keys) {
1709 num_motion_steps =
mesh->get_motion_steps();
1713 index_data.alloc(
mesh->get_triangles().
size());
1714 memcpy(index_data.data(),
1715 mesh->get_triangles().data(),
1716 mesh->get_triangles().
size() *
sizeof(
int));
1718 vertex_data.alloc(num_verts * num_motion_steps);
1720 for (
size_t step = 0; step < num_motion_steps; ++step) {
1723 size_t center_step = (num_motion_steps - 1) / 2;
1725 if (step != center_step) {
1726 verts = motion_keys->
data_float3() + (step > center_step ? step - 1 : step) * num_verts;
1729 memcpy(vertex_data.data() + num_verts * step,
verts, num_verts *
sizeof(
float3));
1733 index_data.copy_to_device();
1734 vertex_data.copy_to_device();
1737 vertex_ptrs.reserve(num_motion_steps);
1738 for (
size_t step = 0; step < num_motion_steps; ++step) {
1739 vertex_ptrs.push_back(vertex_data.device_pointer + num_verts * step *
sizeof(
float3));
1743 unsigned int build_flags = OPTIX_GEOMETRY_FLAG_REQUIRE_SINGLE_ANYHIT_CALL;
1744 OptixBuildInput build_input = {};
1745 build_input.type = OPTIX_BUILD_INPUT_TYPE_TRIANGLES;
1746 build_input.triangleArray.vertexBuffers = (CUdeviceptr *)vertex_ptrs.data();
1747 build_input.triangleArray.numVertices = num_verts;
1748 build_input.triangleArray.vertexFormat = OPTIX_VERTEX_FORMAT_FLOAT3;
1749 build_input.triangleArray.vertexStrideInBytes =
sizeof(
float4);
1750 build_input.triangleArray.indexBuffer = index_data.device_pointer;
1752 build_input.triangleArray.indexFormat = OPTIX_INDICES_FORMAT_UNSIGNED_INT3;
1753 build_input.triangleArray.indexStrideInBytes = 3 *
sizeof(int);
1754 build_input.triangleArray.flags = &build_flags;
1758 build_input.triangleArray.numSbtRecords = 1;
1761 if (!build_optix_bvh(bvh_optix, operation, build_input, num_motion_steps)) {
1762 progress.
set_error(
"Failed to build OptiX acceleration structure");
1768 const size_t num_points = pointcloud->
num_points();
1769 if (num_points == 0) {
1773 size_t num_motion_steps = 1;
1775 if (motion_blur && pointcloud->get_use_motion_blur() && motion_points) {
1776 num_motion_steps = pointcloud->get_motion_steps();
1780 aabb_data.alloc(num_points * num_motion_steps);
1783 for (
size_t step = 0; step < num_motion_steps; ++step) {
1785 const float3 *points = pointcloud->get_points().data();
1786 const float *radius = pointcloud->get_radius().data();
1787 size_t center_step = (num_motion_steps - 1) / 2;
1788 if (step != center_step) {
1789 size_t attr_offset = (step > center_step) ? step - 1 : step;
1791 points = motion_points->
data_float3() + attr_offset * num_points;
1794 for (
size_t i = 0; i < num_points; ++i) {
1799 const size_t index = step * num_points + i;
1800 aabb_data[index].minX =
bounds.min.x;
1801 aabb_data[index].minY =
bounds.min.y;
1802 aabb_data[index].minZ =
bounds.min.z;
1803 aabb_data[index].maxX =
bounds.max.x;
1804 aabb_data[index].maxY =
bounds.max.y;
1805 aabb_data[index].maxZ =
bounds.max.z;
1810 aabb_data.copy_to_device();
1813 aabb_ptrs.reserve(num_motion_steps);
1814 for (
size_t step = 0; step < num_motion_steps; ++step) {
1815 aabb_ptrs.push_back(aabb_data.device_pointer + step * num_points *
sizeof(OptixAabb));
1821 unsigned int build_flags = OPTIX_GEOMETRY_FLAG_DISABLE_ANYHIT |
1822 OPTIX_GEOMETRY_FLAG_REQUIRE_SINGLE_ANYHIT_CALL;
1823 OptixBuildInput build_input = {};
1824 build_input.type = OPTIX_BUILD_INPUT_TYPE_CUSTOM_PRIMITIVES;
1825 # if OPTIX_ABI_VERSION < 23
1826 build_input.aabbArray.aabbBuffers = (CUdeviceptr *)aabb_ptrs.data();
1827 build_input.aabbArray.numPrimitives = num_points;
1828 build_input.aabbArray.strideInBytes =
sizeof(OptixAabb);
1829 build_input.aabbArray.flags = &build_flags;
1830 build_input.aabbArray.numSbtRecords = 1;
1831 build_input.aabbArray.primitiveIndexOffset = pointcloud->
prim_offset;
1833 build_input.customPrimitiveArray.aabbBuffers = (CUdeviceptr *)aabb_ptrs.data();
1834 build_input.customPrimitiveArray.numPrimitives = num_points;
1835 build_input.customPrimitiveArray.strideInBytes =
sizeof(OptixAabb);
1836 build_input.customPrimitiveArray.flags = &build_flags;
1837 build_input.customPrimitiveArray.numSbtRecords = 1;
1838 build_input.customPrimitiveArray.primitiveIndexOffset = pointcloud->
prim_offset;
1841 if (!build_optix_bvh(bvh_optix, operation, build_input, num_motion_steps)) {
1842 progress.
set_error(
"Failed to build OptiX acceleration structure");
1847 unsigned int num_instances = 0;
1848 unsigned int max_num_instances = 0xFFFFFFFF;
1850 bvh_optix->as_data->free();
1851 bvh_optix->traversable_handle = 0;
1852 bvh_optix->motion_transform_data->free();
1854 optixDeviceContextGetProperty(
context,
1855 OPTIX_DEVICE_PROPERTY_LIMIT_MAX_INSTANCE_ID,
1857 sizeof(max_num_instances));
1859 max_num_instances >>= 1;
1860 if (bvh->
objects.size() > max_num_instances) {
1862 "Failed to build OptiX acceleration structure because there are too many instances");
1868 instances.alloc(bvh->
objects.size());
1871 size_t motion_transform_offset = 0;
1873 size_t total_motion_transform_size = 0;
1876 total_motion_transform_size =
align_up(total_motion_transform_size,
1877 OPTIX_TRANSFORM_BYTE_ALIGNMENT);
1878 const size_t motion_keys =
max(ob->get_motion().size(), (
size_t)2) - 2;
1879 total_motion_transform_size = total_motion_transform_size +
1880 sizeof(OptixSRTMotionTransform) +
1881 motion_keys *
sizeof(OptixSRTData);
1885 assert(bvh_optix->motion_transform_data->device ==
this);
1886 bvh_optix->motion_transform_data->alloc_to_device(total_motion_transform_size);
1895 BVHOptiX *
const blas =
static_cast<BVHOptiX *
>(ob->get_geometry()->bvh);
1896 OptixTraversableHandle handle = blas->traversable_handle;
1898 OptixInstance &
instance = instances[num_instances++];
1917 if (0 ==
instance.visibilityMask) {
1923 if (motion_blur && ob->get_geometry()->has_motion_blur()) {
1925 instance.sbtOffset = PG_HITD_MOTION - PG_HITD;
1930 instance.sbtOffset = PG_HITD_POINTCLOUD - PG_HITD;
1936 # if OPTIX_ABI_VERSION < 55
1947 instance.flags = OPTIX_INSTANCE_FLAG_DISABLE_ANYHIT;
1952 size_t motion_keys =
max(ob->get_motion().size(), (
size_t)2) - 2;
1953 size_t motion_transform_size =
sizeof(OptixSRTMotionTransform) +
1954 motion_keys *
sizeof(OptixSRTData);
1956 const CUDAContextScope scope(
this);
1958 motion_transform_offset =
align_up(motion_transform_offset,
1959 OPTIX_TRANSFORM_BYTE_ALIGNMENT);
1960 CUdeviceptr motion_transform_gpu = bvh_optix->motion_transform_data->device_pointer +
1961 motion_transform_offset;
1962 motion_transform_offset += motion_transform_size;
1965 OptixSRTMotionTransform &motion_transform = *
reinterpret_cast<OptixSRTMotionTransform *
>(
1966 new uint8_t[motion_transform_size]);
1967 motion_transform.child = handle;
1968 motion_transform.motionOptions.numKeys = ob->get_motion().size();
1969 motion_transform.motionOptions.flags = OPTIX_MOTION_FLAG_NONE;
1970 motion_transform.motionOptions.timeBegin = 0.0f;
1971 motion_transform.motionOptions.timeEnd = 1.0f;
1973 OptixSRTData *
const srt_data = motion_transform.srtData;
1976 decomp.data(), ob->get_motion().
data(), ob->get_motion().size());
1978 for (
size_t i = 0; i < ob->get_motion().
size(); ++i) {
1980 srt_data[i].sx = decomp[i].y.w;
1981 srt_data[i].sy = decomp[i].z.w;
1982 srt_data[i].sz = decomp[i].w.w;
1985 srt_data[i].a = decomp[i].z.x;
1986 srt_data[i].b = decomp[i].z.y;
1987 srt_data[i].c = decomp[i].w.x;
1988 assert(decomp[i].
z.z == 0.0f);
1989 assert(decomp[i].
w.y == 0.0f);
1990 assert(decomp[i].
w.z == 0.0f);
1993 srt_data[i].pvx = 0.0f;
1994 srt_data[i].pvy = 0.0f;
1995 srt_data[i].pvz = 0.0f;
1998 srt_data[i].qx = decomp[i].x.x;
1999 srt_data[i].qy = decomp[i].x.y;
2000 srt_data[i].qz = decomp[i].x.z;
2001 srt_data[i].qw = decomp[i].x.w;
2004 srt_data[i].tx = decomp[i].y.x;
2005 srt_data[i].ty = decomp[i].y.y;
2006 srt_data[i].tz = decomp[i].y.z;
2010 cuMemcpyHtoD(motion_transform_gpu, &motion_transform, motion_transform_size);
2011 delete[]
reinterpret_cast<uint8_t *
>(&motion_transform);
2014 optixConvertPointerToTraversableHandle(
context,
2015 motion_transform_gpu,
2016 OPTIX_TRAVERSABLE_TYPE_SRT_MOTION_TRANSFORM,
2020 instance.traversableHandle = handle;
2022 if (ob->get_geometry()->is_instanced()) {
2030 instances.resize(num_instances);
2031 instances.copy_to_device();
2034 OptixBuildInput build_input = {};
2035 build_input.type = OPTIX_BUILD_INPUT_TYPE_INSTANCES;
2036 build_input.instanceArray.instances = instances.device_pointer;
2037 build_input.instanceArray.numInstances = num_instances;
2039 if (!build_optix_bvh(bvh_optix, OPTIX_BUILD_OPERATION_BUILD, build_input, 0)) {
2040 progress.
set_error(
"Failed to build OptiX acceleration structure");
2042 tlas_handle = bvh_optix->traversable_handle;
2046 void OptiXDevice::release_optix_bvh(
BVH *bvh)
2051 BVHOptiX *
const bvh_optix =
static_cast<BVHOptiX *
>(bvh);
2053 delayed_free_bvh_memory.emplace_back(std::move(bvh_optix->as_data));
2054 delayed_free_bvh_memory.emplace_back(std::move(bvh_optix->motion_transform_data));
2055 bvh_optix->traversable_handle = 0;
2058 void OptiXDevice::free_bvh_memory_delayed()
2061 delayed_free_bvh_memory.free_memory();
2064 void OptiXDevice::const_copy_to(
const char *name,
void *host,
size_t size)
2067 CUDADevice::const_copy_to(name, host,
size);
2069 if (strcmp(name,
"data") == 0) {
2074 *(OptixTraversableHandle *)&
data->device_bvh = tlas_handle;
2081 # define KERNEL_DATA_ARRAY(data_type, data_name) \
2082 if (strcmp(name, #data_name) == 0) { \
2083 update_launch_params(offsetof(KernelParamsOptiX, data_name), host, size); \
2087 # include "kernel/data_arrays.h"
2088 # undef KERNEL_DATA_ARRAY
2091 void OptiXDevice::update_launch_params(
size_t offset,
void *
data,
size_t data_size)
2093 const CUDAContextScope scope(
this);
2095 cuda_assert(cuMemcpyHtoD(launch_params.device_pointer +
offset,
data, data_size));
typedef float(TangentPoint)[2]
_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 z
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_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 y
_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 type
_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 width
_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 stride
_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 instance
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
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
void refit(btStridingMeshInterface *triangles, const btVector3 &aabbMin, const btVector3 &aabbMax)
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Attribute * find(ustring name) const
vector< Geometry * > geometry
vector< Object * > objects
int get_pass_offset(PassType type, PassMode mode=PassMode::NOISY) const
Curve get_curve(size_t i) const
size_t curve_segment_offset
size_t num_curves() const
size_t num_segments() const
CurveShapeType curve_shape
bool use_approximate_shadow_catcher
bool use_approximate_shadow_catcher_background
PassInfo get_info() const
void set_substatus(const string &substatus_)
void set_error(const string &error_message_)
device_ptr device_pointer
void alloc_to_device(size_t num, bool shrink_to_fit=true)
#define CCL_NAMESPACE_END
CCL_NAMESPACE_BEGIN struct Options options
#define KERNEL_DATA_ARRAY(type, name)
DebugFlags & DebugFlags()
ccl_gpu_kernel_postfix ccl_global float * guiding_buffer
ccl_gpu_kernel_postfix ccl_global const int ccl_global float const int work_size
ccl_gpu_kernel_postfix ccl_global float int int int int int int int int int int int int num_components
ccl_gpu_kernel_postfix ccl_global KernelWorkTile * tiles
ccl_gpu_kernel_postfix ccl_global float int int int int int int int int pass_denoised
ccl_global KernelShaderEvalInput ccl_global float * output
ccl_global const KernelWorkTile * tile
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
ccl_global KernelShaderEvalInput * input
ccl_gpu_kernel_postfix ccl_global float int int int int int int int pass_stride
ccl_gpu_kernel_postfix ccl_global float int int int int int int int int int int int pass_sample_count
ccl_gpu_kernel_postfix ccl_global float int int int int ccl_global const float int int int int int int int int int int int int num_samples
ccl_gpu_kernel_postfix ccl_global float int int int int int int int int int int int int bool use_compositing
@ ATTR_STD_MOTION_VERTEX_POSITION
@ KERNEL_FEATURE_OBJECT_MOTION
@ KERNEL_FEATURE_SUBSURFACE
@ KERNEL_FEATURE_HAIR_THICK
@ KERNEL_FEATURE_PATH_TRACING
@ KERNEL_FEATURE_POINTCLOUD
@ KERNEL_FEATURE_NODE_RAYTRACE
@ PASS_SHADOW_CATCHER_MATTE
@ PASS_DENOISING_PREVIOUS
@ DEVICE_KERNEL_FILTER_COLOR_PREPROCESS
@ DEVICE_KERNEL_FILTER_GUIDING_SET_FAKE_ALBEDO
@ DEVICE_KERNEL_FILTER_COLOR_POSTPROCESS
@ DEVICE_KERNEL_FILTER_GUIDING_PREPROCESS
#define VLOG_IS_ON(severity)
Segment< FEdge *, Vec3r > segment
struct blender::compositor::@179::@181 task
T dot(const vec_base< T, Size > &a, const vec_base< T, Size > &b)
CCL_NAMESPACE_BEGIN const char * pass_type_as_string(const PassType type)
size_t path_file_size(const string &path)
string path_get(const string &sub)
bool path_read_text(const string &path, string &text)
unsigned __int64 uint64_t
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
size_t num_triangles() const
int get_device_index() const
bool is_traceable() const
uint visibility_for_tracing() const
bool use_denoising_albedo
Point get_point(int i) const
size_t num_points() const
void push(TaskRunFunction &&task)
void wait_work(Summary *stats=NULL)
std::unique_lock< std::mutex > thread_scoped_lock
CCL_NAMESPACE_BEGIN typedef std::mutex thread_mutex
ccl_device_inline size_t align_up(size_t offset, size_t alignment)