#pragma once
#include <pathtracer.h>
#include <renderer.h>
#include <rt.h>
#include <mesh/MeshStorage.h>
#include <cugar/basic/timer.h>
#include <cugar/basic/primitives.h>
#include <cugar/basic/memory_arena.h>
#include <pathtracer_core.h>
#include <pathtracer_queues.h>
#include <pathtracer_kernels.h>
#include <pathtracer_vertex_processor.h>
#define SHIFT_RES 256
namespace {
template <typename TDirectLightingSampler>
{
TDirectLightingSampler dl;
};
{
vtls_rl->init(
VTL_RL_HASH_SIZE,
mesh_vtls->get_bvh_clusters_count(),
mesh_vtls->get_bvh_cluster_offsets());
}
{
vtls_rl->init(
VTL_RL_HASH_SIZE,
mesh_vtls->get_bvh_nodes(),
mesh_vtls->get_bvh_parents(),
mesh_vtls->get_bvh_ranges(),
mesh_vtls->get_bvh_clusters_count(),
mesh_vtls->get_bvh_clusters(),
mesh_vtls->get_bvh_cluster_offsets());
}
}
PathTracer::PathTracer() :
m_generator(32,
cugar::LFSRGeneratorMatrix::GOOD_PROJECTIONS),
m_random(&m_generator, 1u, 1351u)
{
m_vtls_rl = new VTLRLStorage;
}
{
const uint2 res = renderer.
res();
const uint32 n_pixels = res.x * res.y;
m_options.
parse(argc, argv);
const char* nee_alg[] = { "mesh", "vpl", "rl" };
fprintf(stderr, " PT settings:\n");
fprintf(stderr, " path-length : %u\n", m_options.max_path_length);
fprintf(stderr, " direct-nee : %u\n", m_options.direct_lighting_nee ? 1 : 0);
fprintf(stderr, " direct-bsdf : %u\n", m_options.direct_lighting_bsdf ? 1 : 0);
fprintf(stderr, " indirect-nee : %u\n", m_options.indirect_lighting_nee ? 1 : 0);
fprintf(stderr, " indirect-bsdf : %u\n", m_options.indirect_lighting_bsdf ? 1 : 0);
fprintf(stderr, " visible-lights : %u\n", m_options.visible_lights ? 1 : 0);
fprintf(stderr, " direct lighting : %u\n", m_options.direct_lighting ? 1 : 0);
fprintf(stderr, " diffuse : %u\n", m_options.diffuse_scattering ? 1 : 0);
fprintf(stderr, " glossy : %u\n", m_options.glossy_scattering ? 1 : 0);
fprintf(stderr, " indirect glossy : %u\n", m_options.indirect_glossy ? 1 : 0);
fprintf(stderr, " RR : %u\n", m_options.rr ? 1 : 0);
fprintf(stderr, " nee algorithm : %s\n", nee_alg[ m_options.nee_type ]);
{
m_options,
n_pixels,
input_queue,
scatter_queue,
shadow_queue,
arena );
arena.
alloc<int64>( 16 );
fprintf(stderr, " allocating queue storage: %.1f MB\n", float(arena.size) / (1024*1024));
m_memory_pool.alloc(arena.size);
}
const uint32 n_dimensions = 6 * (m_options.max_path_length + 1);
fprintf(stderr, " initializing sampler: %u dimensions\n", n_dimensions);
m_sequence.setup(n_dimensions, SHIFT_RES);
const uint32 n_light_paths = n_pixels;
fprintf(stderr, " creating mesh lights... started\n");
fprintf(stderr, " creating mesh lights... done\n");
m_options.nee_type = NEE_ALGORITHM_MESH;
if (m_options.nee_type == NEE_ALGORITHM_RL)
{
fprintf(stderr, " creating mesh VTLs... started\n");
m_mesh_vtls->init(n_light_paths, renderer, 0u );
fprintf(stderr, " creating mesh VTLs... done (%u VTLs, %u clusters)\n", m_mesh_vtls->get_vtl_count(), m_mesh_vtls->get_bvh_clusters_count());
fprintf(stderr, " initializing VTLs RL... started\n");
::init( m_vtls_rl, m_mesh_vtls );
fprintf(stderr, " initializing VTLs RL... done (%.1f MB)\n", m_vtls_rl->needed_bytes(VTL_RL_HASH_SIZE, m_mesh_vtls->get_bvh_clusters_count()) / float(1024*1024));
}
}
void PathTracer::update_vtls_rl(const uint32 instance)
{
if ((instance % 32) == 0)
{
m_vtls_rl->clear();
}
else
{
m_vtls_rl->update();
CUDA_CHECK(cugar::cuda::sync_and_check_error("vtl-rl update"));
}
}
{
const uint2 res = renderer.
res();
const uint32 n_pixels = res.x * res.y;
m_options,
n_pixels,
in_queue,
scatter_queue,
shadow_queue,
arena );
uint64* device_timers = arena.
alloc<uint64>( 16 );
if (m_options.nee_type == NEE_ALGORITHM_RL)
update_vtls_rl( instance );
m_sequence.set_instance(instance);
{
if (m_options.nee_type == NEE_ALGORITHM_RL)
{
PathTracingContext<DirectLightingRL> context;
context.options = m_options;
context.in_bounce = 0;
context.in_queue = in_queue;
context.scatter_queue = scatter_queue;
context.shadow_queue = shadow_queue;
context.sequence = m_sequence.view();
context.frame_weight = 1.0f / float(renderer_view.instance + 1);
context.device_timers = device_timers;
context.bbox = m_bbox;
view( *m_vtls_rl ),
m_mesh_vtls->view() );
path_trace_loop( context, vertex_processor, renderer, renderer_view, stats );
}
else
{
MeshLight mesh_light = m_options.nee_type == NEE_ALGORITHM_VPL ? renderer_view.mesh_vpls : renderer_view.mesh_light;
PathTracingContext<DirectLightingMesh> context;
context.options = m_options;
context.in_bounce = 0;
context.in_queue = in_queue;
context.scatter_queue = scatter_queue;
context.shadow_queue = shadow_queue;
context.sequence = m_sequence.view();
context.frame_weight = 1.0f / float(renderer_view.instance + 1);
context.device_timers = device_timers;
context.bbox = m_bbox;
path_trace_loop( context, vertex_processor, renderer, renderer_view, stats );
}
}
timer.stop();
const float time = timer.seconds();
if (instance == 0)
m_time = time;
else
m_time += time;
fprintf(stderr, "\r %.1fs (%.1fms = rt[%.1fms + %.1fms + %.1fms] + shade[%.1fms + %.1fms] - %uK cells) ",
m_time,
time * 1000.0f,
m_options.nee_type == NEE_ALGORITHM_RL ? m_vtls_rl->size() / 1000 : 0);
#if defined(DEVICE_TIMING) && DEVICE_TIMING
if (instance % 64 == 0)
print_timer_stats( device_timers, stats );
#endif
if (instance)
{
}
}
{
invalidate = false;
switch (character)
{
case 'i':
m_options.direct_lighting = !m_options.direct_lighting;
invalidate = true;
break;
}
}
{
fprintf(stats, "%f, %f, %f, %f, %f\n",
m_stats.primary_rt_time.mean() * 1000.0f,
m_stats.path_rt_time.mean() * 1000.0f,
m_stats.shadow_rt_time.mean() * 1000.0f,
m_stats.path_shade_time.mean() * 1000.0f,
m_stats.shadow_shade_time.mean() * 1000.0f);
}