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);
201 const bool use_guiding =
device_scene_->data.integrator.use_guiding;
213 const bool train_guiding =
device_scene_->data.integrator.train_guiding;
214 if (use_guiding && train_guiding) {
244 path_trace_work->init_execution();
251template<
typename Callback>
256 const Callback &callback)
258 const int num_works = path_trace_works.size();
262 for (
int i = 0;
i < num_works; ++
i) {
263 const double weight = work_balance_infos[
i].weight;
264 const int slice_window_full_y = buffer_params.
full_y + buffer_params.
window_y + current_y;
265 const int slice_window_height =
max(lround(window_height * weight), 1);
269 const int remaining_window_height =
max(0, window_height - current_y);
273 slice_params.
full_y =
max(slice_window_full_y - overscan, buffer_params.
full_y);
274 slice_params.
window_y = slice_window_full_y - slice_params.
full_y;
276 if (
i < num_works - 1) {
277 slice_params.
window_height =
min(slice_window_height, remaining_window_height);
289 callback(path_trace_works[
i].get(), slice_params);
320 scaled_params.
full_x =
params.full_x / resolution_divider;
321 scaled_params.
full_y =
params.full_y / resolution_divider;
327 return scaled_params;
342 scaled_big_tile_params,
346 scaled_full_params, scaled_big_tile_params,
params);
349 render_state_.effective_big_tile_params = scaled_big_tile_params;
375 path_trace_work->zero_render_buffers();
391 const double start_time =
time_dt();
397 parallel_for(0, num_works, [&](
int i) {
398 const double work_start_time =
time_dt();
414 const double work_time =
time_dt() - work_start_time;
418 VLOG_INFO <<
"Rendered " << num_samples <<
" samples in " << work_time <<
" seconds ("
419 << work_time / num_samples
420 <<
" seconds per sample), occupancy: " << statistics.
occupancy;
423 float occupancy_accum = 0.0f;
425 occupancy_accum += balance_info.occupancy;
427 const float occupancy = occupancy_accum / num_works;
440 bool did_reschedule_on_idle =
false;
443 VLOG_WORK <<
"Will filter adaptive stopping buffer, threshold "
446 VLOG_WORK <<
"Will re-calculate convergency flag for currently converged pixels.";
449 const double start_time =
time_dt();
451 uint num_active_pixels = 0;
453 const uint num_active_pixels_in_work =
454 path_trace_work->adaptive_sampling_converge_filter_count_active(
456 if (num_active_pixels_in_work) {
464 if (num_active_pixels == 0) {
469 VLOG_WORK <<
"Continuing with lower threshold.";
471 else if (did_reschedule_on_idle) {
474 else if (num_active_pixels < 128 * 128) {
481 VLOG_WORK <<
"Rescheduling is not possible: final threshold is reached.";
484 VLOG_WORK <<
"Rescheduling lower threshold.";
485 did_reschedule_on_idle =
true;
502 interop_device =
display_->graphics_interop_get_device();
505 Device *effective_denoise_device;
510 bool need_to_recreate_denoiser =
false;
515 old_denoiser_params.
use_gpu ==
false;
516 const bool requested_gpu_denoising = effective_denoise_params.
type ==
DENOISER_OPTIX ||
517 (effective_denoise_params.
type ==
519 effective_denoise_params.
use_gpu ==
true);
520 if (requested_gpu_denoising && is_cpu_denoising &&
529 const bool is_same_denoising_device_type = old_denoiser_params.
use_gpu ==
530 effective_denoise_params.
use_gpu;
533 if (old_denoiser_params.
type == effective_denoise_params.
type &&
536 denoiser_->set_params(effective_denoise_params);
539 need_to_recreate_denoiser =
true;
544 need_to_recreate_denoiser =
true;
547 if (need_to_recreate_denoiser) {
549 effective_denoise_device, cpu_fallback_device, effective_denoise_params, interop_device);
578 VLOG_WORK <<
"Perform cryptomatte work.";
581 path_trace_work->cryptomatte_postproces();
598 const double start_time =
time_dt();
601 bool allow_inplace_modification =
false;
618 allow_inplace_modification =
true;
629 allow_inplace_modification))
650 display_ = make_unique<PathTraceDisplay>(std::move(driver));
694 VLOG_WORK <<
"Skipping PathTraceDisplay update due to 0 size of the render buffer.";
698 const double start_time =
time_dt();
701 VLOG_WORK <<
"Invoke buffer update callback.";
708 VLOG_WORK <<
"Perform copy to GPUDisplay work.";
710 const int texture_width =
render_state_.effective_big_tile_params.window_width;
711 const int texture_height =
render_state_.effective_big_tile_params.window_height;
712 if (!
display_->update_begin(texture_width, texture_height)) {
713 LOG(ERROR) <<
"Error beginning GPUDisplay update.";
730 path_trace_work->copy_to_display(
display_.get(), pass_mode, num_samples);
748 if (num_works == 1) {
749 VLOG_WORK <<
"Ignoring rebalance work due to single device render.";
753 const double start_time =
time_dt();
757 VLOG_WORK <<
"Per-device path tracing time (seconds):";
758 for (
int i = 0;
i < num_works; ++
i) {
767 VLOG_WORK <<
"Calculated per-device weights for works:";
768 for (
int i = 0;
i < num_works; ++
i) {
774 if (!did_rebalance) {
775 VLOG_WORK <<
"Balance in path trace works did not change.";
803 const bool has_multiple_tiles =
tile_manager_.has_multiple_tiles();
812 if (!has_multiple_tiles) {
813 VLOG_WORK <<
"Write tile result via buffer write callback.";
819 VLOG_WORK <<
"Write tile result to disk.";
830 VLOG_WORK <<
"Handle full-frame render buffer work.";
901 path_trace_work->copy_render_buffers_from_device();
909 path_trace_work->copy_render_buffers_to_device();
921 if (num_rendered_samples == 0) {
938 buffers = &big_tile_cpu_buffers;
942 device_->set_error(
"Error writing tile to file");
955 progress_->add_samples(num_samples_added, current_sample);
966 progress_->set_status(status, substatus);
1005 if (!path_trace_work->copy_render_buffers_from_device()) {
1017 if (!
buffers.params.layer.empty()) {
1021 if (!
buffers.params.view.empty()) {
1033 VLOG_WORK <<
"Processing full frame buffer file " << filename;
1040 if (!
tile_manager_.read_full_buffer_from_disk(filename, &full_frame_buffers, &denoise_params)) {
1041 const string error_message =
"Error reading tiles from file";
1047 LOG(ERROR) << error_message;
1071 denoiser_->denoise_buffer(full_frame_buffers.
params, &full_frame_buffers, 0,
false);
1112 bool success =
true;
1118 if (!path_trace_work->get_render_tile_pixels(pass_accessor, destination)) {
1129 bool success =
true;
1135 if (!path_trace_work->set_render_tile_pixels(pass_accessor, source)) {
1190 path_trace_work->destroy_gpu_resources(
display_.get());
1236 string full_description = device_info.
description;
1241 full_description +=
" (display)";
1248 full_description +=
" [" + device_info.
id +
"]";
1250 return full_description;
1268 string result =
"\n" + message +
": ";
1269 const string pad(message.length() + 2,
' ');
1276 bool is_first =
true;
1295 for (
auto &&path_trace_work : path_trace_works) {
1296 device_info.
multi_devices.push_back(path_trace_work->get_device()->info);
1313 if (!denoiser_device) {
1322 string result =
"\nFull path tracing report\n";
1338#ifdef WITH_PATH_GUIDING
1339 if (guiding_params_.modified(guiding_params)) {
1340 guiding_params_ = guiding_params;
1342# if !(OPENPGL_VERSION_MAJOR == 0 && OPENPGL_VERSION_MINOR <= 5)
1343# define OPENPGL_USE_FIELD_CONFIG
1346 if (guiding_params_.use) {
1347# ifdef OPENPGL_USE_FIELD_CONFIG
1348 openpgl::cpp::FieldConfig field_config;
1350 PGLFieldArguments field_args;
1352 switch (guiding_params_.type) {
1356# ifdef OPENPGL_USE_FIELD_CONFIG
1358 PGL_SPATIAL_STRUCTURE_TYPE::PGL_SPATIAL_STRUCTURE_KDTREE,
1359 PGL_DIRECTIONAL_DISTRIBUTION_TYPE::PGL_DIRECTIONAL_DISTRIBUTION_PARALLAX_AWARE_VMM,
1362 pglFieldArgumentsSetDefaults(
1364 PGL_SPATIAL_STRUCTURE_TYPE::PGL_SPATIAL_STRUCTURE_KDTREE,
1365 PGL_DIRECTIONAL_DISTRIBUTION_TYPE::PGL_DIRECTIONAL_DISTRIBUTION_PARALLAX_AWARE_VMM);
1371# ifdef OPENPGL_USE_FIELD_CONFIG
1373 PGL_SPATIAL_STRUCTURE_TYPE::PGL_SPATIAL_STRUCTURE_KDTREE,
1374 PGL_DIRECTIONAL_DISTRIBUTION_TYPE::PGL_DIRECTIONAL_DISTRIBUTION_QUADTREE,
1377 pglFieldArgumentsSetDefaults(
1379 PGL_SPATIAL_STRUCTURE_TYPE::PGL_SPATIAL_STRUCTURE_KDTREE,
1380 PGL_DIRECTIONAL_DISTRIBUTION_TYPE::PGL_DIRECTIONAL_DISTRIBUTION_QUADTREE);
1386# ifdef OPENPGL_USE_FIELD_CONFIG
1387 field_config.Init(PGL_SPATIAL_STRUCTURE_TYPE::PGL_SPATIAL_STRUCTURE_KDTREE,
1388 PGL_DIRECTIONAL_DISTRIBUTION_TYPE::PGL_DIRECTIONAL_DISTRIBUTION_VMM,
1391 pglFieldArgumentsSetDefaults(
1393 PGL_SPATIAL_STRUCTURE_TYPE::PGL_SPATIAL_STRUCTURE_KDTREE,
1394 PGL_DIRECTIONAL_DISTRIBUTION_TYPE::PGL_DIRECTIONAL_DISTRIBUTION_VMM);
1399# ifdef OPENPGL_USE_FIELD_CONFIG
1400 field_config.SetSpatialStructureArgMaxDepth(16);
1403 reinterpret_cast<PGLKDTreeArguments *
>(field_args.spatialSturctureArguments)->maxDepth = 16;
1405 openpgl::cpp::Device *guiding_device =
static_cast<openpgl::cpp::Device *
>(
1406 device_->get_guiding_device());
1407 if (guiding_device) {
1408 guiding_sample_data_storage_ = make_unique<openpgl::cpp::SampleStorage>();
1409# ifdef OPENPGL_USE_FIELD_CONFIG
1410 guiding_field_ = make_unique<openpgl::cpp::Field>(guiding_device, field_config);
1412 guiding_field_ = make_unique<openpgl::cpp::Field>(guiding_device, field_args);
1416 guiding_sample_data_storage_ =
nullptr;
1417 guiding_field_ =
nullptr;
1421 guiding_sample_data_storage_ =
nullptr;
1422 guiding_field_ =
nullptr;
1426 if (guiding_field_) {
1427 guiding_field_->Reset();
1431 (void)guiding_params;
1438#ifdef WITH_PATH_GUIDING
1439 const bool train = (guiding_params_.training_samples == 0) ||
1440 (guiding_field_->GetIteration() < guiding_params_.training_samples);
1443 path_trace_work->guiding_init_kernel_globals(
1444 guiding_field_.get(), guiding_sample_data_storage_.get(), train);
1463#ifdef WITH_PATH_GUIDING
1464 VLOG_WORK <<
"Update path guiding structures";
1466 VLOG_DEBUG <<
"Number of surface samples: " << guiding_sample_data_storage_->GetSizeSurface();
1467 VLOG_DEBUG <<
"Number of volume samples: " << guiding_sample_data_storage_->GetSizeVolume();
1469 const size_t num_valid_samples = guiding_sample_data_storage_->GetSizeSurface() +
1470 guiding_sample_data_storage_->GetSizeVolume();
1473 if (num_valid_samples >= 1024) {
1474 guiding_field_->Update(*guiding_sample_data_storage_);
1475 guiding_update_count++;
1477 VLOG_DEBUG <<
"Path guiding field valid: " << guiding_field_->Validate();
1479 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()
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)
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)
struct PathTrace::@302344231114375033127004234070152003340355025232 full_frame_state_
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)
struct PathTrace::@014001306360020237171347255006316036071250375356 render_state_
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 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
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)
struct PathTrace::@224227240077371035336157150015037333254237322171 render_cancel_
void update_allocated_work_buffer_params()
void reset(const BufferParams ¶ms)
void set_need_schedule_rebalance(bool need_schedule_rebalance)
struct RenderWork::@063216132251123170370353251200240227371364310276 full
struct RenderWork::@255150175261212255042175367266367372050067152060 path_trace
struct RenderWork::@013040061270373137315310144332363355371166250150 tile
struct RenderWork::@221146205233306371270226043111110064012110021230 display
struct RenderWork::@365223156106100071160056310357324351275265115143 adaptive_sampling
struct RenderWork::@126231202227170004250210357045070360172012131352 cryptomatte
@ 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 VLOG_IS_ON(severity)
#define DCHECK(expression)
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)