7#include "device/cpu/kernel.h"
38 const int thread_index = tbb::this_task_arena::current_thread_index();
40 DCHECK_LE(thread_index, kernel_thread_globals.size());
42 return &kernel_thread_globals[thread_index];
48 bool *cancel_requested_flag)
49 :
PathTraceWork(device, film, device_scene, cancel_requested_flag),
50 kernels_(
Device::get_cpu_kernels())
72 kernel_globals.start_profiling();
77 local_arena.execute([&]() {
78 parallel_for(
int64_t(0), total_pixels_num, [&](
int64_t work_index) {
104 kernel_globals.stop_profiling();
108 statistics.occupancy = 1.0f;
113 const int samples_num)
123 shadow_catcher_state = &integrator_states[1];
152#ifdef WITH_PATH_GUIDING
153 if (kernel_globals->
data.integrator.train_guiding) {
159 if (shadow_catcher_state) {
171 half4 *rgba_half = display->map_texture_buffer();
185 const PassAccessorCPU pass_accessor(pass_access_info, kfilm.exposure, num_samples);
188 destination.pixels_half_rgba = rgba_half;
191 local_arena.execute([&]() {
195 display->unmap_texture_buffer();
202 return buffers_->copy_from_device();
228 uint num_active_pixels = 0;
233 local_arena.execute([&]() {
234 parallel_for(full_y, full_y + height, [&](
int y) {
237 bool row_converged =
true;
238 uint num_row_pixels_active = 0;
239 for (
int x = 0; x < width; ++
x) {
243 ++num_row_pixels_active;
244 row_converged = false;
250 if (!row_converged) {
252 kernel_globals,
render_buffer, y, full_x, width, offset, stride);
257 if (num_active_pixels) {
258 local_arena.execute([&]() {
259 parallel_for(full_x, full_x + width, [&](
int x) {
262 kernel_globals,
render_buffer, x, full_y, height, offset, stride);
267 return num_active_pixels;
280 local_arena.execute([&]() {
281 parallel_for(0, height, [&](
int y) {
283 int pixel_index = y * width;
285 for (
int x = 0; x < width; ++
x, ++pixel_index) {
292#ifdef WITH_PATH_GUIDING
295void PathTraceWorkCPU::guiding_init_kernel_globals(
void *guiding_field,
296 void *sample_data_storage,
303 openpgl::cpp::Field *field = (openpgl::cpp::Field *)guiding_field;
306 kg.opgl_guiding_field = field;
308# if PATH_GUIDING_LEVEL >= 4
309 if (kg.opgl_surface_sampling_distribution) {
310 delete kg.opgl_surface_sampling_distribution;
311 kg.opgl_surface_sampling_distribution =
nullptr;
313 if (kg.opgl_volume_sampling_distribution) {
314 delete kg.opgl_volume_sampling_distribution;
315 kg.opgl_volume_sampling_distribution =
nullptr;
319 kg.opgl_surface_sampling_distribution =
new openpgl::cpp::SurfaceSamplingDistribution(field);
320 kg.opgl_volume_sampling_distribution =
new openpgl::cpp::VolumeSamplingDistribution(field);
325 kg.
data.integrator.train_guiding = train;
326 kg.opgl_sample_data_storage = (openpgl::cpp::SampleStorage *)sample_data_storage;
329 kg.opgl_path_segment_storage->Reserve(kg.
data.integrator.transparent_max_bounce +
330 kg.
data.integrator.max_bounce + 3);
331 kg.opgl_path_segment_storage->Clear();
336void PathTraceWorkCPU::guiding_push_sample_data_to_global_storage(
339# ifdef WITH_CYCLES_DEBUG
342 const bool validSegments = kg->opgl_path_segment_storage->ValidateSegments();
343 if (!validSegments) {
344 VLOG_WORK <<
"Guiding: invalid path segments!";
349 pgl_vec3f pgl_final_color = kg->opgl_path_segment_storage->CalculatePixelEstimate(
false);
351 float3 final_color =
make_float3(pgl_final_color.x, pgl_final_color.y, pgl_final_color.z);
361# if PATH_GUIDING_LEVEL >= 2
362 const bool use_direct_light =
kernel_data.integrator.use_guiding_direct_light;
363 const bool use_mis_weights =
kernel_data.integrator.use_guiding_mis_weights;
364 kg->opgl_path_segment_storage->PrepareSamples(use_mis_weights, use_direct_light,
false);
367# ifdef WITH_CYCLES_DEBUG
370 const bool validSamples = kg->opgl_path_segment_storage->ValidateSamples();
373 <<
"Guiding: path segment storage generated/contains invalid radiance/training samples!";
378# if PATH_GUIDING_LEVEL >= 3
380 size_t num_samples = 0;
381 const openpgl::cpp::SampleData *samples = kg->opgl_path_segment_storage->GetSamples(num_samples);
382 kg->opgl_sample_data_storage->AddSamples(samples, num_samples);
386 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
AdaptiveSamplingConvergenceCheckFunction adaptive_sampling_convergence_check
CryptomattePostprocessFunction cryptomatte_postprocess
IntegratorShadeFunction integrator_megakernel
AdaptiveSamplingFilterYFunction adaptive_sampling_filter_y
IntegratorInitFunction integrator_init_from_bake
AdaptiveSamplingFilterXFunction adaptive_sampling_filter_x
IntegratorInitFunction integrator_init_from_camera
virtual void get_cpu_kernel_thread_globals(vector< CPUKernelThreadGlobals > &)
bool get_render_tile_pixels(const RenderBuffers *render_buffers, const Destination &destination) const
virtual bool copy_render_buffers_to_device() override
virtual void render_samples(RenderStatistics &statistics, int start_sample, int samples_num, int sample_offset) override
vector< CPUKernelThreadGlobals > kernel_thread_globals_
virtual void init_execution() override
virtual void copy_to_display(PathTraceDisplay *display, PassMode pass_mode, int num_samples) override
virtual bool copy_render_buffers_from_device() override
virtual void destroy_gpu_resources(PathTraceDisplay *display) override
virtual int adaptive_sampling_converge_filter_count_active(float threshold, bool reset) override
virtual void cryptomatte_postproces() override
const CPUKernels & kernels_
PathTraceWorkCPU(Device *device, Film *film, DeviceScene *device_scene, bool *cancel_requested_flag)
void render_samples_full_pipeline(KernelGlobalsCPU *kernel_globals, const KernelWorkTile &work_tile, const int samples_num)
virtual 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_
bool is_cancel_requested() const
#define CCL_NAMESPACE_END
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 CPUKernelThreadGlobals * kernel_thread_globals_get(vector< CPUKernelThreadGlobals > &kernel_thread_globals)
static CCL_NAMESPACE_BEGIN tbb::task_arena local_tbb_arena_create(const Device *device)
ccl_device_inline void film_write_pass_float3(ccl_global float *ccl_restrict buffer, 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)