Added handle system and improve resource management.
This commit is contained in:
@@ -20,7 +20,7 @@ static inline void create_target_if_required(aov_flags_t aov_flags, aov_flags_t
|
||||
*render_target = temp;
|
||||
}
|
||||
|
||||
bool renderer_aov_target_init(render_job_t* job, aov_flags_t aov_flags)
|
||||
bool renderer_aov_target_init(render_job_t* job)
|
||||
{
|
||||
job->aov_target = (render_target_t**)malloc(sizeof(render_target_t*) * MAX_AOV_TARGET);
|
||||
if (job->aov_target == NULL)
|
||||
@@ -28,14 +28,14 @@ bool renderer_aov_target_init(render_job_t* job, aov_flags_t aov_flags)
|
||||
return false;
|
||||
}
|
||||
|
||||
create_target_if_required(aov_flags, AOV_BEAUTY, &job->aov_target[AOV_BEAUTY_INDEX], job->config->width, job->config->height);
|
||||
create_target_if_required(aov_flags, AOV_AlBEDO, &job->aov_target[AOV_AlBEDO_INDEX], job->config->width, job->config->height);
|
||||
create_target_if_required(aov_flags, AOV_NORMAL, &job->aov_target[AOV_NORMAL_INDEX], job->config->width, job->config->height);
|
||||
create_target_if_required(aov_flags, AOV_DEPTH, &job->aov_target[AOV_DEPTH_INDEX], job->config->width, job->config->height);
|
||||
create_target_if_required(aov_flags, AOV_POSITION, &job->aov_target[AOV_POSITION_INDEX], job->config->width, job->config->height);
|
||||
create_target_if_required(job->config.aov_flags, AOV_BEAUTY, &job->aov_target[AOV_BEAUTY_INDEX], job->config.width, job->config.height);
|
||||
create_target_if_required(job->config.aov_flags, AOV_AlBEDO, &job->aov_target[AOV_AlBEDO_INDEX], job->config.width, job->config.height);
|
||||
create_target_if_required(job->config.aov_flags, AOV_NORMAL, &job->aov_target[AOV_NORMAL_INDEX], job->config.width, job->config.height);
|
||||
create_target_if_required(job->config.aov_flags, AOV_DEPTH, &job->aov_target[AOV_DEPTH_INDEX], job->config.width, job->config.height);
|
||||
create_target_if_required(job->config.aov_flags, AOV_POSITION, &job->aov_target[AOV_POSITION_INDEX], job->config.width, job->config.height);
|
||||
|
||||
create_target_if_required(aov_flags, AOV_DIRECT, &job->aov_target[AOV_DIRECT_INDEX], job->config->width, job->config->height);
|
||||
create_target_if_required(aov_flags, AOV_INDIRECT, &job->aov_target[AOV_INDIRECT_INDEX], job->config->width, job->config->height);
|
||||
create_target_if_required(job->config.aov_flags, AOV_DIRECT, &job->aov_target[AOV_DIRECT_INDEX], job->config.width, job->config.height);
|
||||
create_target_if_required(job->config.aov_flags, AOV_INDIRECT, &job->aov_target[AOV_INDIRECT_INDEX], job->config.width, job->config.height);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -67,17 +67,34 @@ static inline bool aov_needs_lighting_samples(aov_flags_t flags)
|
||||
return has_flag(flags, AOV_BEAUTY) || has_flag(flags, AOV_DIRECT) || has_flag(flags, AOV_INDIRECT);
|
||||
}
|
||||
|
||||
static inline uint32_t get_minimal_sample_count(render_job_t* job)
|
||||
{
|
||||
if (aov_needs_lighting_samples(job->config.aov_flags))
|
||||
{
|
||||
if (job->config.aov_flags == AOV_DIRECT)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return job->config.sample_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline vec4s running_average_vec4(vec4s prev_avg, vec4s sample, uint32_t prev_count)
|
||||
{
|
||||
float n = (float)prev_count;
|
||||
float inv = 1.0f / (n + 1.0f);
|
||||
|
||||
vec4s out;
|
||||
out.x = (prev_avg.x * n + sample.x) * inv;
|
||||
out.y = (prev_avg.y * n + sample.y) * inv;
|
||||
out.z = (prev_avg.z * n + sample.z) * inv;
|
||||
out.w = 1.0f;
|
||||
return out;
|
||||
return (vec4s){
|
||||
.x = (prev_avg.x * n + sample.x) * inv,
|
||||
.y = (prev_avg.y * n + sample.y) * inv,
|
||||
.z = (prev_avg.z * n + sample.z) * inv,
|
||||
.w = 1.0f
|
||||
};
|
||||
}
|
||||
|
||||
static inline void clear_render_target(render_target_t* target)
|
||||
@@ -108,7 +125,13 @@ static inline void clear_aov_targets(render_job_t* job)
|
||||
}
|
||||
}
|
||||
|
||||
static void render_pixel(const rendering_config_t* config, scene_t* scene, vec3s coord, uint32_t x, uint32_t y, aov_flags_t aov_flags, aov_output_t* pixel_output)
|
||||
static void render_pixel(const rendering_config_t* config,
|
||||
const scene_t* scene,
|
||||
vec3s coord,
|
||||
uint32_t x,
|
||||
uint32_t y,
|
||||
aov_flags_t aov_flags,
|
||||
aov_output_t* pixel_output)
|
||||
{
|
||||
aov_output_t accumulated_color = {0};
|
||||
|
||||
@@ -155,12 +178,11 @@ static void render_pixel(const rendering_config_t* config, scene_t* scene, vec3s
|
||||
}
|
||||
|
||||
static void render_pixel_one_sample(const rendering_config_t* config,
|
||||
scene_t* scene,
|
||||
const scene_t* scene,
|
||||
vec3s coord,
|
||||
uint32_t x,
|
||||
uint32_t y,
|
||||
uint32_t sample_index,
|
||||
aov_flags_t aov_flags,
|
||||
aov_output_t* pixel_output)
|
||||
{
|
||||
uint32_t pixel_id = y * config->width + x;
|
||||
@@ -192,7 +214,7 @@ static void render_pixel_one_sample(const rendering_config_t* config,
|
||||
spread_angle);
|
||||
|
||||
aov_output_t out = {0};
|
||||
path_trace_aov(scene, ray, sobol_idx, config->max_depth, aov_flags, &out);
|
||||
path_trace_aov(scene, ray, sobol_idx, config->max_depth, config->aov_flags, &out);
|
||||
*pixel_output = out;
|
||||
}
|
||||
|
||||
@@ -220,23 +242,24 @@ static inline void update_aov(render_target_t** target, const aov_output_t* aov,
|
||||
|
||||
void renderer_start(render_job_t* job)
|
||||
{
|
||||
ensure_camera_aspect_ratio(&job->scene->camera, job->config);
|
||||
ensure_camera_aspect_ratio(&job->scene->camera, &job->config);
|
||||
job->config.sample_count = get_minimal_sample_count(job);
|
||||
|
||||
// Reset progressive state whenever we (re)start.
|
||||
job->progressive_sample_index = 0;
|
||||
|
||||
vec3s coord = glms_vec3_add(job->scene->camera.position, glms_vec3_scale(quat_get_forward(job->scene->camera.rotation), job->scene->camera.focal_length));
|
||||
|
||||
if (job->rendering_mode == RENDER_PROGRESSIVE)
|
||||
if (job->config.rendering_mode == RENDER_PROGRESSIVE)
|
||||
{
|
||||
// Progressive mode: accumulate 1 spp per pass until sample_count or stop requested.
|
||||
clear_aov_targets(job);
|
||||
job->is_done = false;
|
||||
|
||||
uint32_t width = job->config->width;
|
||||
uint32_t height = job->config->height;
|
||||
uint32_t width = job->config.width;
|
||||
uint32_t height = job->config.height;
|
||||
|
||||
for (uint32_t s = 0; s < job->config->sample_count; ++s)
|
||||
for (uint32_t s = 0; s < job->config.sample_count; ++s)
|
||||
{
|
||||
if (job->is_done)
|
||||
{
|
||||
@@ -257,10 +280,10 @@ void renderer_start(render_job_t* job)
|
||||
}
|
||||
|
||||
aov_output_t pixel = {0};
|
||||
render_pixel_one_sample(job->config, job->scene, coord, (uint32_t)x, (uint32_t)y, s, job->aov_flags, &pixel);
|
||||
render_pixel_one_sample(&job->config, job->scene, coord, (uint32_t)x, (uint32_t)y, s, &pixel);
|
||||
|
||||
// Accumulate lighting AOVs; write non-stochastic AOVs once.
|
||||
if (has_flag(job->aov_flags, AOV_BEAUTY))
|
||||
if (has_flag(job->config.aov_flags, AOV_BEAUTY))
|
||||
{
|
||||
vec4s prev = render_target_get_pixel(job->aov_target[AOV_BEAUTY_INDEX], (uint32_t)x, (uint32_t)y);
|
||||
vec4s avg = running_average_vec4(prev, pixel.beauty, s);
|
||||
@@ -275,14 +298,14 @@ void renderer_start(render_job_t* job)
|
||||
update_aov_pixel_if_exist(&job->aov_target[AOV_POSITION_INDEX], pixel.position, (uint32_t)x, (uint32_t)y);
|
||||
}
|
||||
|
||||
if (has_flag(job->aov_flags, AOV_DIRECT))
|
||||
if (has_flag(job->config.aov_flags, AOV_DIRECT))
|
||||
{
|
||||
vec4s prev = render_target_get_pixel(job->aov_target[AOV_DIRECT_INDEX], (uint32_t)x, (uint32_t)y);
|
||||
vec4s avg = running_average_vec4(prev, pixel.direct, s);
|
||||
render_target_set_pixel(job->aov_target[AOV_DIRECT_INDEX], (uint32_t)x, (uint32_t)y, avg);
|
||||
}
|
||||
|
||||
if (has_flag(job->aov_flags, AOV_INDIRECT))
|
||||
if (has_flag(job->config.aov_flags, AOV_INDIRECT))
|
||||
{
|
||||
vec4s prev = render_target_get_pixel(job->aov_target[AOV_INDIRECT_INDEX], (uint32_t)x, (uint32_t)y);
|
||||
vec4s avg = running_average_vec4(prev, pixel.indirect, s);
|
||||
@@ -299,20 +322,20 @@ void renderer_start(render_job_t* job)
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t tile_count_x = (job->config->width + job->config->bucket_size - 1) / job->config->bucket_size;
|
||||
uint32_t tile_count_y = (job->config->height + job->config->bucket_size - 1) / job->config->bucket_size;
|
||||
uint32_t tile_count_x = (job->config.width + job->config.bucket_size - 1) / job->config.bucket_size;
|
||||
uint32_t tile_count_y = (job->config.height + job->config.bucket_size - 1) / job->config.bucket_size;
|
||||
uint32_t tile_count = tile_count_x * tile_count_y;
|
||||
|
||||
int64_t x, y, tile_index; // OpenMP requires these to be declared outside the parallel region.
|
||||
#pragma omp parallel for schedule(dynamic, 1) default(none) \
|
||||
shared(tile_count_x, tile_count_y, tile_count, coord, job) \
|
||||
private(x, y, tile_index)
|
||||
#pragma omp parallel for schedule(dynamic, 1) default(none) \
|
||||
shared(tile_count_x, tile_count_y, tile_count, coord, job) \
|
||||
private(x, y, tile_index)
|
||||
for (tile_index = 0; tile_index < tile_count; tile_index++)
|
||||
{
|
||||
uint32_t tile_x_0 = (uint32_t)tile_index % tile_count_x * job->config->bucket_size;
|
||||
uint32_t tile_y_0 = (uint32_t)tile_index / tile_count_x * job->config->bucket_size;
|
||||
uint32_t tile_x_1 = (uint32_t)fmin(tile_x_0 + job->config->bucket_size, job->config->width);
|
||||
uint32_t tile_y_1 = (uint32_t)fmin(tile_y_0 + job->config->bucket_size, job->config->height);
|
||||
uint32_t tile_x_0 = (uint32_t)tile_index % tile_count_x * job->config.bucket_size;
|
||||
uint32_t tile_y_0 = (uint32_t)tile_index / tile_count_x * job->config.bucket_size;
|
||||
uint32_t tile_x_1 = (uint32_t)fmin(tile_x_0 + job->config.bucket_size, job->config.width);
|
||||
uint32_t tile_y_1 = (uint32_t)fmin(tile_y_0 + job->config.bucket_size, job->config.height);
|
||||
|
||||
for (y = tile_y_0; y < tile_y_1; y++)
|
||||
{
|
||||
@@ -324,7 +347,7 @@ void renderer_start(render_job_t* job)
|
||||
}
|
||||
|
||||
aov_output_t pixel_output = {0};
|
||||
render_pixel(job->config, job->scene, coord, (uint32_t)x, (uint32_t)y, job->aov_flags, &pixel_output);
|
||||
render_pixel(&job->config, job->scene, coord, (uint32_t)x, (uint32_t)y, job->config.aov_flags, &pixel_output);
|
||||
update_aov(job->aov_target, &pixel_output, (uint32_t)x, (uint32_t)y);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user