Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/integrator/path_trace_work_cpu.cpp')
-rw-r--r--intern/cycles/integrator/path_trace_work_cpu.cpp110
1 files changed, 110 insertions, 0 deletions
diff --git a/intern/cycles/integrator/path_trace_work_cpu.cpp b/intern/cycles/integrator/path_trace_work_cpu.cpp
index 518ef3185f9..188ec28cf65 100644
--- a/intern/cycles/integrator/path_trace_work_cpu.cpp
+++ b/intern/cycles/integrator/path_trace_work_cpu.cpp
@@ -6,6 +6,7 @@
#include "device/cpu/kernel.h"
#include "device/device.h"
+#include "kernel/film/write.h"
#include "kernel/integrator/path_state.h"
#include "integrator/pass_accessor_cpu.h"
@@ -145,6 +146,13 @@ void PathTraceWorkCPU::render_samples_full_pipeline(KernelGlobalsCPU *kernel_glo
kernels_.integrator_megakernel(kernel_globals, state, render_buffer);
+#ifdef WITH_PATH_GUIDING
+ if (kernel_globals->data.integrator.train_guiding) {
+ /* Push the generated sample data to the global sample data storage. */
+ guiding_push_sample_data_to_global_storage(kernel_globals, state, render_buffer);
+ }
+#endif
+
if (shadow_catcher_state) {
kernels_.integrator_megakernel(kernel_globals, shadow_catcher_state, render_buffer);
}
@@ -276,4 +284,106 @@ void PathTraceWorkCPU::cryptomatte_postproces()
});
}
+#ifdef WITH_PATH_GUIDING
+/* NOTE: It seems that this is called before every rendering iteration/progression and not once per
+ * rendering. May be we find a way to call it only once per rendering. */
+void PathTraceWorkCPU::guiding_init_kernel_globals(void *guiding_field,
+ void *sample_data_storage,
+ const bool train)
+{
+ /* Linking the global guiding structures (e.g., Field and SampleStorage) to the per-thread
+ * kernel globals. */
+ for (int thread_index = 0; thread_index < kernel_thread_globals_.size(); thread_index++) {
+ CPUKernelThreadGlobals &kg = kernel_thread_globals_[thread_index];
+ openpgl::cpp::Field *field = (openpgl::cpp::Field *)guiding_field;
+
+ /* Allocate sampling distributions. */
+ kg.opgl_guiding_field = field;
+
+# if PATH_GUIDING_LEVEL >= 4
+ if (kg.opgl_surface_sampling_distribution) {
+ delete kg.opgl_surface_sampling_distribution;
+ kg.opgl_surface_sampling_distribution = nullptr;
+ }
+ if (kg.opgl_volume_sampling_distribution) {
+ delete kg.opgl_volume_sampling_distribution;
+ kg.opgl_volume_sampling_distribution = nullptr;
+ }
+
+ if (field) {
+ kg.opgl_surface_sampling_distribution = new openpgl::cpp::SurfaceSamplingDistribution(field);
+ kg.opgl_volume_sampling_distribution = new openpgl::cpp::VolumeSamplingDistribution(field);
+ }
+# endif
+
+ /* Reserve storage for training. */
+ kg.data.integrator.train_guiding = train;
+ kg.opgl_sample_data_storage = (openpgl::cpp::SampleStorage *)sample_data_storage;
+
+ if (train) {
+ kg.opgl_path_segment_storage->Reserve(kg.data.integrator.transparent_max_bounce +
+ kg.data.integrator.max_bounce + 3);
+ kg.opgl_path_segment_storage->Clear();
+ }
+ }
+}
+
+void PathTraceWorkCPU::guiding_push_sample_data_to_global_storage(
+ KernelGlobalsCPU *kg, IntegratorStateCPU *state, ccl_global float *ccl_restrict render_buffer)
+{
+# ifdef WITH_CYCLES_DEBUG
+ if (VLOG_WORK_IS_ON) {
+ /* Check if the generated path segments contain valid values. */
+ const bool validSegments = kg->opgl_path_segment_storage->ValidateSegments();
+ if (!validSegments) {
+ VLOG_WORK << "Guiding: invalid path segments!";
+ }
+ }
+
+ /* Write debug render pass to validate it matches combined pass. */
+ pgl_vec3f pgl_final_color = kg->opgl_path_segment_storage->CalculatePixelEstimate(false);
+ const uint32_t render_pixel_index = INTEGRATOR_STATE(state, path, render_pixel_index);
+ const uint64_t render_buffer_offset = (uint64_t)render_pixel_index *
+ kernel_data.film.pass_stride;
+ ccl_global float *buffer = render_buffer + render_buffer_offset;
+ float3 final_color = make_float3(pgl_final_color.x, pgl_final_color.y, pgl_final_color.z);
+ if (kernel_data.film.pass_guiding_color != PASS_UNUSED) {
+ film_write_pass_float3(buffer + kernel_data.film.pass_guiding_color, final_color);
+ }
+# else
+ (void)state;
+ (void)render_buffer;
+# endif
+
+ /* Convert the path segment representation of the random walk into radiance samples. */
+# if PATH_GUIDING_LEVEL >= 2
+ const bool use_direct_light = kernel_data.integrator.use_guiding_direct_light;
+ const bool use_mis_weights = kernel_data.integrator.use_guiding_mis_weights;
+ kg->opgl_path_segment_storage->PrepareSamples(
+ false, nullptr, use_mis_weights, use_direct_light, false);
+# endif
+
+# ifdef WITH_CYCLES_DEBUG
+ /* Check if the training/radiance samples generated py the path segment storage are valid.*/
+ if (VLOG_WORK_IS_ON) {
+ const bool validSamples = kg->opgl_path_segment_storage->ValidateSamples();
+ if (!validSamples) {
+ VLOG_WORK
+ << "Guiding: path segment storage generated/contains invalid radiance/training samples!";
+ }
+ }
+# endif
+
+# if PATH_GUIDING_LEVEL >= 3
+ /* Push radiance samples from current random walk/path to the global sample storage. */
+ size_t num_samples = 0;
+ const openpgl::cpp::SampleData *samples = kg->opgl_path_segment_storage->GetSamples(num_samples);
+ kg->opgl_sample_data_storage->AddSamples(samples, num_samples);
+# endif
+
+ /* Clear storage for the current path, to be ready for the next path. */
+ kg->opgl_path_segment_storage->Clear();
+}
+#endif
+
CCL_NAMESPACE_END