55 path_trace_device, film, device_scene, &
render_cancel_.is_requested);
78 display_->graphics_interop_activate();
84 display_->graphics_interop_deactivate();
92 path_trace_work->alloc_work_memory();
122 const bool reset_rendering)
135 display_->reset(big_tile_params, reset_rendering);
151 path_trace_work->get_render_buffers()->reset(empty_params);
204 const bool use_guiding =
device_scene_->data.integrator.use_guiding;
209 const bool has_volume =
device_scene_->data.integrator.use_volumes;
223 const bool train_guiding =
device_scene_->data.integrator.train_guiding;
224 if (use_guiding && train_guiding) {
259 path_trace_work->init_execution();
266template<
typename Callback>
271 const Callback &callback)
273 const int num_works = path_trace_works.size();
277 for (
int i = 0;
i < num_works; ++
i) {
278 const double weight = work_balance_infos[
i].weight;
279 const int slice_window_full_y = buffer_params.
full_y + buffer_params.
window_y + current_y;
280 const int slice_window_height =
max(lround(window_height * weight), 1);
284 const int remaining_window_height =
max(0, window_height - current_y);
288 slice_params.
full_y =
max(slice_window_full_y - overscan, buffer_params.
full_y);
289 slice_params.
window_y = slice_window_full_y - slice_params.
full_y;
291 if (
i < num_works - 1) {
292 slice_params.
window_height =
min(slice_window_height, remaining_window_height);
304 callback(path_trace_works[
i].get(), slice_params);
335 scaled_params.
full_x =
params.full_x / resolution_divider;
336 scaled_params.
full_y =
params.full_y / resolution_divider;
342 return scaled_params;
357 scaled_big_tile_params,
361 scaled_full_params, scaled_big_tile_params,
params);
364 render_state_.effective_big_tile_params = scaled_big_tile_params;
390 path_trace_work->zero_render_buffers();
406 const double start_time =
time_dt();
412 parallel_for(0, num_works, [&](
int i) {
413 const double work_start_time =
time_dt();
429 const double work_time =
time_dt() - work_start_time;
433 LOG_INFO <<
"Rendered " << num_samples <<
" samples in " << work_time <<
" seconds ("
434 << work_time / num_samples
435 <<
" seconds per sample), occupancy: " << statistics.
occupancy;
438 float occupancy_accum = 0.0f;
440 occupancy_accum += balance_info.occupancy;
442 const float occupancy = occupancy_accum / num_works;
455 bool did_reschedule_on_idle =
false;
458 LOG_DEBUG <<
"Will filter adaptive stopping buffer, threshold "
461 LOG_DEBUG <<
"Will re-calculate convergency flag for currently converged pixels.";
464 const double start_time =
time_dt();
466 uint num_active_pixels = 0;
468 const uint num_active_pixels_in_work =
469 path_trace_work->adaptive_sampling_converge_filter_count_active(
471 if (num_active_pixels_in_work) {
479 if (num_active_pixels == 0) {
484 LOG_DEBUG <<
"Continuing with lower threshold.";
486 else if (did_reschedule_on_idle) {
489 else if (num_active_pixels < 128 * 128) {
496 LOG_DEBUG <<
"Rescheduling is not possible: final threshold is reached.";
499 LOG_DEBUG <<
"Rescheduling lower threshold.";
500 did_reschedule_on_idle =
true;
517 interop_device =
display_->graphics_interop_get_device();
520 Device *effective_denoise_device;
525 bool need_to_recreate_denoiser =
false;
530 old_denoiser_params.
use_gpu ==
false;
531 const bool requested_gpu_denoising = effective_denoise_params.
type ==
DENOISER_OPTIX ||
532 (effective_denoise_params.
type ==
534 effective_denoise_params.
use_gpu ==
true);
535 if (requested_gpu_denoising && is_cpu_denoising &&
544 const bool is_same_denoising_device_type = old_denoiser_params.
use_gpu ==
545 effective_denoise_params.
use_gpu;
548 if (old_denoiser_params.
type == effective_denoise_params.
type &&
551 denoiser_->set_params(effective_denoise_params);
554 need_to_recreate_denoiser =
true;
559 need_to_recreate_denoiser =
true;
562 if (need_to_recreate_denoiser) {
564 effective_denoise_device, cpu_fallback_device, effective_denoise_params, interop_device);
593 LOG_DEBUG <<
"Perform cryptomatte work.";
596 path_trace_work->cryptomatte_postproces();
613 const double start_time =
time_dt();
616 bool allow_inplace_modification =
false;
633 allow_inplace_modification =
true;
644 allow_inplace_modification))
653 const bool has_volume)
659 LOG_DEBUG <<
"Denoise volume guiding buffers.";
661 const double start_time =
time_dt();
666 path_trace_work->denoise_volume_guiding_buffers();
685 display_ = make_unique<PathTraceDisplay>(std::move(driver));
729 LOG_DEBUG <<
"Skipping PathTraceDisplay update due to 0 size of the render buffer.";
733 const double start_time =
time_dt();
736 LOG_DEBUG <<
"Invoke buffer update callback.";
743 LOG_DEBUG <<
"Perform copy to GPUDisplay work.";
745 const int texture_width =
render_state_.effective_big_tile_params.window_width;
746 const int texture_height =
render_state_.effective_big_tile_params.window_height;
747 if (!
display_->update_begin(texture_width, texture_height)) {
748 LOG_ERROR <<
"Error beginning GPUDisplay update.";
767 path_trace_work->copy_to_display(
display_.get(), pass_mode, num_samples);
785 if (num_works == 1) {
786 LOG_DEBUG <<
"Ignoring rebalance work due to single device render.";
790 const double start_time =
time_dt();
794 LOG_DEBUG <<
"Per-device path tracing time (seconds):";
795 for (
int i = 0;
i < num_works; ++
i) {
804 LOG_DEBUG <<
"Calculated per-device weights for works:";
805 for (
int i = 0;
i < num_works; ++
i) {
811 if (!did_rebalance) {
812 LOG_DEBUG <<
"Balance in path trace works did not change.";
840 const bool has_multiple_tiles =
tile_manager_.has_multiple_tiles();
849 if (!has_multiple_tiles) {
850 LOG_DEBUG <<
"Write tile result via buffer write callback.";
856 LOG_DEBUG <<
"Write tile result to disk.";
867 LOG_DEBUG <<
"Handle full-frame render buffer work.";
938 path_trace_work->copy_render_buffers_from_device();
946 path_trace_work->copy_render_buffers_to_device();
958 if (num_rendered_samples == 0) {
975 buffers = &big_tile_cpu_buffers;
979 device_->set_error(
"Error writing tile to file");
992 progress_->add_samples(num_samples_added, current_sample);
1036 bool success =
true;
1042 if (!path_trace_work->copy_render_buffers_from_device()) {
1054 if (!
buffers.params.layer.empty()) {
1058 if (!
buffers.params.view.empty()) {
1070 LOG_DEBUG <<
"Processing full frame buffer file " << filename;
1077 if (!
tile_manager_.read_full_buffer_from_disk(filename, &full_frame_buffers, &denoise_params)) {
1078 const string error_message =
"Error reading tiles from file";
1108 denoiser_->denoise_buffer(full_frame_buffers.
params, &full_frame_buffers, 0,
false);
1149 bool success =
true;
1155 if (!path_trace_work->get_render_tile_pixels(pass_accessor, destination)) {
1166 bool success =
true;
1172 if (!path_trace_work->set_render_tile_pixels(pass_accessor, source)) {
1227 path_trace_work->destroy_gpu_resources(
display_.get());
1273 string full_description = device_info.
description;
1278 full_description +=
" (display)";
1285 full_description +=
" [" + device_info.
id +
"]";
1287 return full_description;
1305 string result =
"\n" + message +
": ";
1306 const string pad(message.length() + 2,
' ');
1313 bool is_first =
true;
1332 for (
auto &&path_trace_work : path_trace_works) {
1333 device_info.
multi_devices.push_back(path_trace_work->get_device()->info);
1350 if (!denoiser_device) {
1359 string result =
"Full path tracing report:\n";
1375#if defined(WITH_PATH_GUIDING)
1376 if (guiding_params_.modified(guiding_params)) {
1377 guiding_params_ = guiding_params;
1379# if !(OPENPGL_VERSION_MAJOR == 0 && OPENPGL_VERSION_MINOR <= 5)
1380# define OPENPGL_USE_FIELD_CONFIG
1383 if (guiding_params_.use) {
1384# ifdef OPENPGL_USE_FIELD_CONFIG
1385 openpgl::cpp::FieldConfig field_config;
1387 PGLFieldArguments field_args;
1389 switch (guiding_params_.type) {
1393# ifdef OPENPGL_USE_FIELD_CONFIG
1395 PGL_SPATIAL_STRUCTURE_TYPE::PGL_SPATIAL_STRUCTURE_KDTREE,
1396 PGL_DIRECTIONAL_DISTRIBUTION_TYPE::PGL_DIRECTIONAL_DISTRIBUTION_PARALLAX_AWARE_VMM,
1399 pglFieldArgumentsSetDefaults(
1401 PGL_SPATIAL_STRUCTURE_TYPE::PGL_SPATIAL_STRUCTURE_KDTREE,
1402 PGL_DIRECTIONAL_DISTRIBUTION_TYPE::PGL_DIRECTIONAL_DISTRIBUTION_PARALLAX_AWARE_VMM);
1408# ifdef OPENPGL_USE_FIELD_CONFIG
1410 PGL_SPATIAL_STRUCTURE_TYPE::PGL_SPATIAL_STRUCTURE_KDTREE,
1411 PGL_DIRECTIONAL_DISTRIBUTION_TYPE::PGL_DIRECTIONAL_DISTRIBUTION_QUADTREE,
1414 pglFieldArgumentsSetDefaults(
1416 PGL_SPATIAL_STRUCTURE_TYPE::PGL_SPATIAL_STRUCTURE_KDTREE,
1417 PGL_DIRECTIONAL_DISTRIBUTION_TYPE::PGL_DIRECTIONAL_DISTRIBUTION_QUADTREE);
1423# ifdef OPENPGL_USE_FIELD_CONFIG
1424 field_config.Init(PGL_SPATIAL_STRUCTURE_TYPE::PGL_SPATIAL_STRUCTURE_KDTREE,
1425 PGL_DIRECTIONAL_DISTRIBUTION_TYPE::PGL_DIRECTIONAL_DISTRIBUTION_VMM,
1428 pglFieldArgumentsSetDefaults(
1430 PGL_SPATIAL_STRUCTURE_TYPE::PGL_SPATIAL_STRUCTURE_KDTREE,
1431 PGL_DIRECTIONAL_DISTRIBUTION_TYPE::PGL_DIRECTIONAL_DISTRIBUTION_VMM);
1436# ifdef OPENPGL_USE_FIELD_CONFIG
1437 field_config.SetSpatialStructureArgMaxDepth(16);
1440 reinterpret_cast<PGLKDTreeArguments *
>(field_args.spatialSturctureArguments)->maxDepth = 16;
1442 openpgl::cpp::Device *guiding_device =
static_cast<openpgl::cpp::Device *
>(
1443 device_->get_guiding_device());
1444 if (guiding_device) {
1445 guiding_sample_data_storage_ = make_unique<openpgl::cpp::SampleStorage>();
1446# ifdef OPENPGL_USE_FIELD_CONFIG
1447 guiding_field_ = make_unique<openpgl::cpp::Field>(guiding_device, field_config);
1449 guiding_field_ = make_unique<openpgl::cpp::Field>(guiding_device, field_args);
1453 guiding_sample_data_storage_ =
nullptr;
1454 guiding_field_ =
nullptr;
1458 guiding_sample_data_storage_ =
nullptr;
1459 guiding_field_ =
nullptr;
1463 if (guiding_field_) {
1464 guiding_field_->Reset();
1468 (void)guiding_params;
1475#if defined(WITH_PATH_GUIDING)
1476 const bool train = (guiding_params_.training_samples == 0) ||
1477 (guiding_field_->GetIteration() < guiding_params_.training_samples);
1480 path_trace_work->guiding_init_kernel_globals(
1481 guiding_field_.get(), guiding_sample_data_storage_.get(), train);
1500#if defined(WITH_PATH_GUIDING)
1501 LOG_DEBUG <<
"Update path guiding structures";
1503 LOG_TRACE <<
"Number of surface samples: " << guiding_sample_data_storage_->GetSizeSurface();
1504 LOG_TRACE <<
"Number of volume samples: " << guiding_sample_data_storage_->GetSizeVolume();
1506 const size_t num_valid_samples = guiding_sample_data_storage_->GetSizeSurface() +
1507 guiding_sample_data_storage_->GetSizeVolume();
1510 if (num_valid_samples >= 1024) {
1511 guiding_field_->Update(*guiding_sample_data_storage_);
1512 guiding_update_count++;
1514 LOG_TRACE <<
"Path guiding field valid: " << guiding_field_->Validate();
1516 guiding_sample_data_storage_->Clear();
ATOMIC_INLINE unsigned int atomic_add_and_fetch_u(unsigned int *p, unsigned int x)
int pad[32 - sizeof(int)]
unsigned long long int uint64_t
void update_offset_stride()
static unique_ptr< Denoiser > create(Device *denoiser_device, Device *cpu_fallback_device, const DenoiseParams ¶ms, const GraphicsInteropDevice &interop_device)
Device * get_denoiser_device() const
const DenoiseParams & get_params() const
vector< DeviceInfo > multi_devices
bool get_render_tile_pixels(const RenderBuffers *render_buffers, const Destination &destination) const
const PassAccessInfo & get_pass_access_info() const
RenderBuffers * get_render_buffers()
static unique_ptr< PathTraceWork > create(Device *device, Film *film, DeviceScene *device_scene, const bool *cancel_requested_flag)
void set_effective_buffer_params(const BufferParams &effective_full_params, const BufferParams &effective_big_tile_params, const BufferParams &effective_buffer_params)
virtual void render_samples(RenderStatistics &statistics, const int start_sample, const int samples_num, const int sample_offset)=0
Device * get_device() const
void denoise(const RenderWork &render_work)
int2 get_render_tile_size() const
void finalize_full_buffer_on_disk(const RenderWork &render_work)
std::function< void(void)> progress_update_cb
void process_full_buffer_from_disk(string_view filename)
unique_ptr< Denoiser > denoiser_
void update_effective_work_buffer_params(const RenderWork &render_work)
BufferParams full_params_
void rebalance(const RenderWork &render_work)
bool is_cancel_requested()
struct PathTrace::@134371127017210132007075065004246317237136077123 render_state_
void init_render_buffers(const RenderWork &render_work)
void copy_to_render_buffers(RenderBuffers *render_buffers)
void destroy_gpu_resources()
void set_progress(Progress *progress)
vector< unique_ptr< PathTraceWork > > path_trace_works_
void copy_from_render_buffers(RenderBuffers *render_buffers)
void set_denoiser_params(const DenoiseParams ¶ms)
struct PathTrace::@045127216101200035253035102154226266260300121335 full_frame_state_
void progress_update_if_needed(const RenderWork &render_work)
void update_display(const RenderWork &render_work)
void progress_set_status(const string &status, const string &substatus="")
void set_adaptive_sampling(const AdaptiveSampling &adaptive_sampling)
void set_output_driver(unique_ptr< OutputDriver > driver)
void reset(const BufferParams &full_params, const BufferParams &big_tile_params, bool reset_rendering)
DeviceScene * device_scene_
bool get_render_tile_pixels(const PassAccessor &pass_accessor, const PassAccessor::Destination &destination)
void guiding_update_structures()
PathTrace(Device *device, Device *denoise_device, Film *film, DeviceScene *device_scene, RenderScheduler &render_scheduler, TileManager &tile_manager)
void guiding_prepare_structures()
int2 get_render_tile_offset() const
unique_ptr< Device > cpu_device_
void denoise_volume_guiding_buffers(const RenderWork &render_work, const bool has_volume)
void set_guiding_params(const GuidingParams ¶ms, const bool reset)
void tile_buffer_write_to_disk()
void set_display_driver(unique_ptr< DisplayDriver > driver)
void path_trace(RenderWork &render_work)
void render_pipeline(RenderWork render_work)
unique_ptr< OutputDriver > output_driver_
unique_ptr< PathTraceDisplay > display_
vector< WorkBalanceInfo > work_balance_infos_
RenderBuffers * render_buffers
bool copy_render_tile_from_device()
bool did_draw_after_reset_
void render_init_kernel_execution()
int2 get_render_size() const
struct PathTrace::@264204132215367063060273366367103232030034067245 render_cancel_
TileManager & tile_manager_
unique_ptr< PathTraceWork > big_tile_denoise_work_
void update_work_buffer_params_if_needed(const RenderWork &render_work)
BufferParams big_tile_params_
void write_tile_buffer(const RenderWork &render_work)
bool set_render_tile_pixels(PassAccessor &pass_accessor, const PassAccessor::Source &source)
void render(const RenderWork &render_work)
string full_report() const
void adaptive_sample(RenderWork &render_work)
const BufferParams & get_render_tile_params() const
int get_num_render_tile_samples() const
RenderScheduler & render_scheduler_
int get_num_samples_in_buffer()
void cryptomatte_postprocess(const RenderWork &render_work)
void update_allocated_work_buffer_params()
void reset(const BufferParams ¶ms)
void set_need_schedule_rebalance(bool need_schedule_rebalance)
struct RenderWork::@274302037211333357242061375066056076354104241257 cryptomatte
struct RenderWork::@143272241044374345203044061122063322004171016113 tile
struct RenderWork::@332011177057136214007215372066145235154020032310 path_trace
struct RenderWork::@165363207370354371245137325023006326210217053004 adaptive_sampling
struct RenderWork::@226364033061301324161311275016362103243040016376 display
struct RenderWork::@200361311027272113377377324353154145102345065344 full
@ DENOISER_OPENIMAGEDENOISE
DenoiseParams get_effective_denoise_params(Device *denoiser_device, Device *cpu_fallback_device, const DenoiseParams ¶ms, const GraphicsInteropDevice &interop_device, Device *&single_denoiser_device)
void device_cpu_info(vector< DeviceInfo > &devices)
CCL_NAMESPACE_BEGIN unique_ptr< Device > device_cpu_create(const DeviceInfo &info, Stats &stats, Profiler &profiler, bool headless)
#define CCL_NAMESPACE_END
static const char * to_string(const Interpolation &interp)
const ccl_global KernelWorkTile * tile
@ GUIDING_TYPE_DIRECTIONAL_QUAD_TREE
@ GUIDING_TYPE_PARALLAX_AWARE_VMM
#define DCHECK(expression)
ccl_device_inline uint next_power_of_two(const uint x)
bool is_volume_guiding_pass(const PassType pass_type)
static string device_info_list_report(const string &message, const DeviceInfo &device_info)
static void foreach_sliced_buffer_params(const vector< unique_ptr< PathTraceWork > > &path_trace_works, const vector< WorkBalanceInfo > &work_balance_infos, const BufferParams &buffer_params, const int overscan, const Callback &callback)
static string path_trace_devices_report(const vector< unique_ptr< PathTraceWork > > &path_trace_works)
static BufferParams scale_buffer_params(const BufferParams ¶ms, const int resolution_divider)
static string full_device_info_description(const DeviceInfo &device_info)
static string get_layer_view_name(const RenderBuffers &buffers)
static const char * device_type_for_description(const DeviceType type)
static string denoiser_device_report(const Denoiser *denoiser)
static void thread_capture_fp_settings()
std::unique_lock< std::mutex > thread_scoped_lock
CCL_NAMESPACE_BEGIN double time_dt()
CCL_NAMESPACE_BEGIN void work_balance_do_initial(vector< WorkBalanceInfo > &work_balance_infos)
bool work_balance_do_rebalance(vector< WorkBalanceInfo > &work_balance_infos)