7#include "device/cpu/kernel.h"
10#ifdef WITH_CYCLES_DEBUG
39 const int thread_index = tbb::this_task_arena::current_thread_index();
41 DCHECK_LE(thread_index, kernel_thread_globals.size());
43 return &kernel_thread_globals[thread_index];
49 const bool *cancel_requested_flag)
50 :
PathTraceWork(device, film, device_scene, cancel_requested_flag),
63 const int start_sample,
64 const int samples_num,
65 const int sample_offset)
71 if (
device_->profiler.active()) {
73 kernel_globals.start_profiling();
78 local_arena.execute([&]() {
79 parallel_for(
int64_t(0), total_pixels_num, [&](
int64_t work_index) {
103 if (
device_->profiler.active()) {
105 kernel_globals.stop_profiling();
114 const int samples_num)
124 shadow_catcher_state = &integrator_states[1];
137 if (!
kernels_.integrator_init_from_bake(
144 if (!
kernels_.integrator_init_from_camera(
151#ifdef WITH_PATH_GUIDING
152 if (kernel_globals->
data.integrator.train_guiding) {
153 assert(kernel_globals->opgl_path_segment_storage);
154 assert(kernel_globals->opgl_path_segment_storage->GetNumSegments() == 0);
162 if (shadow_catcher_state) {
163 kernel_globals->
data.integrator.train_guiding =
false;
165 kernel_globals->
data.integrator.train_guiding =
true;
172 if (shadow_catcher_state) {
182 const int num_samples)
198 const PassAccessorCPU pass_accessor(pass_access_info, kfilm.exposure, num_samples);
204 local_arena.execute([&]() {
215 return buffers_->copy_from_device();
242 uint num_active_pixels = 0;
247 local_arena.execute([&]() {
248 parallel_for(full_y, full_y + height, [&](
int y) {
251 bool row_converged =
true;
252 uint num_row_pixels_active = 0;
253 for (
int x = 0;
x < width; ++
x) {
254 if (!
kernels_.adaptive_sampling_convergence_check(
257 ++num_row_pixels_active;
258 row_converged =
false;
264 if (!row_converged) {
265 kernels_.adaptive_sampling_filter_x(
271 if (num_active_pixels) {
272 local_arena.execute([&]() {
273 parallel_for(full_x, full_x + width, [&](
int x) {
275 kernels_.adaptive_sampling_filter_y(
276 kernel_globals,
render_buffer,
x, full_y, height, offset, stride);
281 return num_active_pixels;
294 local_arena.execute([&]() {
295 parallel_for(0, height, [&](
int y) {
297 int pixel_index =
y * width;
299 for (
int x = 0;
x < width; ++
x, ++pixel_index) {
306#ifdef WITH_PATH_GUIDING
309void PathTraceWorkCPU::guiding_init_kernel_globals(
void *guiding_field,
310 void *sample_data_storage,
317 openpgl::cpp::Field *field = (openpgl::cpp::Field *)guiding_field;
320 kg.opgl_guiding_field = field;
322# if PATH_GUIDING_LEVEL >= 4
323 if (kg.opgl_surface_sampling_distribution) {
324 kg.opgl_surface_sampling_distribution.reset();
326 if (kg.opgl_volume_sampling_distribution) {
327 kg.opgl_volume_sampling_distribution.reset();
331 kg.opgl_surface_sampling_distribution =
332 make_unique<openpgl::cpp::SurfaceSamplingDistribution>(field);
333 kg.opgl_volume_sampling_distribution = make_unique<openpgl::cpp::VolumeSamplingDistribution>(
339 kg.
data.integrator.train_guiding = train;
340 kg.opgl_sample_data_storage = (openpgl::cpp::SampleStorage *)sample_data_storage;
343 kg.opgl_path_segment_storage->Reserve(kg.
data.integrator.transparent_max_bounce +
344 kg.
data.integrator.max_bounce + 3);
345 kg.opgl_path_segment_storage->Clear();
355# ifdef WITH_CYCLES_DEBUG
358 const bool validSegments = kg->opgl_path_segment_storage->ValidateSegments();
359 if (!validSegments) {
360 VLOG_WORK <<
"Guiding: invalid path segments!";
365 pgl_vec3f pgl_final_color = kg->opgl_path_segment_storage->CalculatePixelEstimate(
false);
367 float3 final_color =
make_float3(pgl_final_color.x, pgl_final_color.y, pgl_final_color.z);
377# if PATH_GUIDING_LEVEL >= 2
378 const bool use_direct_light =
kernel_data.integrator.use_guiding_direct_light;
379 const bool use_mis_weights =
kernel_data.integrator.use_guiding_mis_weights;
380 kg->opgl_path_segment_storage->PrepareSamples(use_mis_weights, use_direct_light,
false);
383# ifdef WITH_CYCLES_DEBUG
386 const bool validSamples = kg->opgl_path_segment_storage->ValidateSamples();
389 <<
"Guiding: path segment storage generated/contains invalid radiance/training samples!";
394# if PATH_GUIDING_LEVEL >= 3
396 size_t num_samples = 0;
397 const openpgl::cpp::SampleData *samples = kg->opgl_path_segment_storage->GetSamples(num_samples);
398 kg->opgl_sample_data_storage->AddSamples(samples, num_samples);
402 kg->opgl_path_segment_storage->Clear();
static constexpr int image_width
static constexpr int image_height
ATOMIC_INLINE uint32_t atomic_fetch_and_add_uint32(uint32_t *p, uint32_t x)
void reset()
clear internal cached data and reset random seed
bool get_render_tile_pixels(const RenderBuffers *render_buffers, const Destination &destination) const
half4 * map_texture_buffer()
void unmap_texture_buffer()
bool copy_render_buffers_to_device() override
vector< ThreadKernelGlobalsCPU > kernel_thread_globals_
void render_samples(RenderStatistics &statistics, const int start_sample, const int samples_num, const int sample_offset) override
void init_execution() override
bool copy_render_buffers_from_device() override
int adaptive_sampling_converge_filter_count_active(const float threshold, bool reset) override
void copy_to_display(PathTraceDisplay *display, PassMode pass_mode, const int num_samples) override
void destroy_gpu_resources(PathTraceDisplay *display) override
void cryptomatte_postproces() override
const CPUKernels & kernels_
void render_samples_full_pipeline(ThreadKernelGlobalsCPU *kernel_globals, const KernelWorkTile &work_tile, const int samples_num)
PathTraceWorkCPU(Device *device, Film *film, DeviceScene *device_scene, const bool *cancel_requested_flag)
bool zero_render_buffers() override
unique_ptr< RenderBuffers > buffers_
PassAccessor::PassAccessInfo get_display_pass_access_info(PassMode pass_mode) const
PassAccessor::Destination get_display_destination_template(const PathTraceDisplay *display) const
BufferParams effective_buffer_params_
DeviceScene * device_scene_
PathTraceWork(Device *device, Film *film, DeviceScene *device_scene, const bool *cancel_requested_flag)
bool is_cancel_requested() const
#define CCL_NAMESPACE_END
#define assert(assertion)
VecBase< float, 3 > float3
ccl_gpu_kernel_postfix ccl_global KernelWorkTile const int ccl_global float * render_buffer
CCL_NAMESPACE_BEGIN ccl_device_inline void path_state_init_queues(IntegratorState state)
static ThreadKernelGlobalsCPU * kernel_thread_globals_get(vector< ThreadKernelGlobalsCPU > &kernel_thread_globals)
static CCL_NAMESPACE_BEGIN tbb::task_arena local_tbb_arena_create(const Device *device)
CCL_NAMESPACE_END KernelData data
ccl_device_inline void film_write_pass_float3(ccl_global float *ccl_restrict buffer, const float3 value)
CCL_NAMESPACE_BEGIN ccl_device_forceinline ccl_global float * film_pass_pixel_render_buffer(KernelGlobals kg, ConstIntegratorState state, ccl_global float *ccl_restrict render_buffer)