Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trace image improvements #1345

Merged
merged 20 commits into from
Mar 6, 2022
9 changes: 8 additions & 1 deletion apps/ycutrace/ycutrace.cpp
Original file line number Diff line number Diff line change
@@ -234,11 +234,18 @@ void run_view(const view_params& params_) {
tesselate_subdivs(scene);
}

// triangulation
for (auto& shape : scene.shapes) {
if (shape.quads.empty()) continue;
shape.triangles = quads_to_triangles(shape.quads);
shape.quads = {};
}

// find camera
params.camera = find_camera(scene, params.camname);

// run view
show_trace_gui("ycuda", params.scene, scene, params);
show_cutrace_gui("ycutrace", params.scene, scene, params);
}

struct app_params {
94 changes: 74 additions & 20 deletions libs/yocto/yocto_cutrace.cpp
Original file line number Diff line number Diff line change
@@ -91,6 +91,20 @@ static cubuffer<T> make_buffer(const T& data) {
return make_buffer(1, &data);
}

// resize a buffer
template <typename T>
static void resize_buffer(cubuffer<T>& buffer, size_t size, const T* data) {
if (buffer._size != size) {
check_result(cuMemFree(buffer._data));
buffer._size = size;
check_result(cuMemAlloc(&buffer._data, buffer.size_in_bytes()));
}
if (data) {
check_result(
cuMemcpyHtoD(buffer.device_ptr(), data, buffer.size_in_bytes()));
}
}

// update a buffer
template <typename T>
static void update_buffer(cubuffer<T>& buffer, size_t size, const T* data) {
@@ -454,7 +468,7 @@ cusceneext_data make_cutrace_scene(
cucamera.film = camera.film;
cucamera.aperture = camera.aperture;
cucamera.focus = camera.focus;
cucamera.orthographic = (int)camera.orthographic;
cucamera.orthographic = camera.orthographic;
}
cuscene.cameras = make_buffer(cucameras);

@@ -575,6 +589,22 @@ cusceneext_data make_cutrace_scene(
return cuscene;
}

void update_cutrace_cameras(cusceneext_data& cuscene, const scene_data& scene,
const cutrace_params& params) {
auto cucameras = vector<cucamera_data>{};
for (auto& camera : scene.cameras) {
auto& cucamera = cucameras.emplace_back();
cucamera.frame = camera.frame;
cucamera.lens = camera.lens;
cucamera.aspect = camera.aspect;
cucamera.film = camera.film;
cucamera.aperture = camera.aperture;
cucamera.focus = camera.focus;
cucamera.orthographic = camera.orthographic;
}
update_buffer(cuscene.cameras, cucameras);
}

cubvh_data make_cutrace_bvh(cutrace_context& context, cusceneext_data& cuscene,
const scene_data& scene, const cutrace_params& params) {
auto bvh = cubvh_data{};
@@ -745,6 +775,25 @@ cutrace_state make_cutrace_state(
return state;
};

void reset_cutrace_state(cutrace_state& state, const scene_data& scene,
const cutrace_params& params) {
auto& camera = scene.cameras[params.camera];
if (camera.aspect >= 1) {
state.width = params.resolution;
state.height = (int)round(params.resolution / camera.aspect);
} else {
state.height = params.resolution;
state.width = (int)round(params.resolution * camera.aspect);
}
state.samples = 0;
resize_buffer(state.image, state.width * state.height, (vec4f*)nullptr);
resize_buffer(state.albedo, state.width * state.height, (vec3f*)nullptr);
resize_buffer(state.normal, state.width * state.height, (vec3f*)nullptr);
resize_buffer(state.hits, state.width * state.height, (int*)nullptr);
resize_buffer(state.rngs, state.width * state.height, (rng_state*)nullptr);
resize_buffer(state.display, state.width * state.height, (vec4f*)nullptr);
}

// Init trace lights
cutrace_lights make_cutrace_lights(
const scene_data& scene, const cutrace_params& params) {
@@ -777,15 +826,8 @@ image_data cutrace_image(
trace_samples(context, state, cuscene, bvh, lights, scene, params);
}

// copy back image
auto image = make_image(state.width, state.height, true);
download_buffer(state.image, image.pixels);
for (auto& pixel : image.pixels) pixel /= state.samples;

// cleanup

// done
return image;
// copy back image and return
return get_rendered_image(state);
}

// Get resulting render
@@ -796,7 +838,6 @@ image_data get_rendered_image(const cutrace_state& state) {
}
void get_rendered_image(image_data& image, const cutrace_state& state) {
download_buffer(state.image, image.pixels);
for (auto& pixel : image.pixels) pixel /= state.samples;
}

// Get denoised result
@@ -817,10 +858,9 @@ void get_denoised_image(image_data& image, const cutrace_state& state) {
// get albedo and normal
auto albedo = vector<vec3f>(image.pixels.size()),
normal = vector<vec3f>(image.pixels.size());
auto scale = 1.0f / (float)state.samples;
for (auto idx = 0; idx < state.width * state.height; idx++) {
albedo[idx] = state.albedo[idx] * scale;
normal[idx] = state.normal[idx] * scale;
albedo[idx] = state.albedo[idx];
normal[idx] = state.normal[idx];
}

// Create a denoising filter
@@ -853,10 +893,8 @@ image_data get_albedo_image(const cutrace_state& state) {
void get_albedo_image(image_data& image, const cutrace_state& state) {
auto albedo = vector<vec3f>(state.width * state.height);
download_buffer(state.albedo, albedo);
auto scale = 1.0f / (float)state.samples;
for (auto idx = 0; idx < state.width * state.height; idx++) {
image.pixels[idx] = {albedo[idx].x * scale, albedo[idx].y * scale,
albedo[idx].z * scale, 1.0f};
image.pixels[idx] = {albedo[idx].x, albedo[idx].y, albedo[idx].z, 1.0f};
}
}
image_data get_normal_image(const cutrace_state& state) {
@@ -867,13 +905,19 @@ image_data get_normal_image(const cutrace_state& state) {
void get_normal_image(image_data& image, const cutrace_state& state) {
auto normal = vector<vec3f>(state.width * state.height);
download_buffer(state.normal, normal);
auto scale = 1.0f / (float)state.samples;
for (auto idx = 0; idx < state.width * state.height; idx++) {
image.pixels[idx] = {normal[idx].x * scale, normal[idx].y * scale,
normal[idx].z * scale, 1.0f};
image.pixels[idx] = {normal[idx].x, normal[idx].y, normal[idx].z, 1.0f};
}
}

bool is_display(const cutrace_context& context) {
auto device = 0, is_display = 0;
// check_result(cuDevice(&current_device));
check_result(cuDeviceGetAttribute(
&is_display, CU_DEVICE_ATTRIBUTE_KERNEL_EXEC_TIMEOUT, device));
return (bool)is_display;
}

} // namespace yocto

#else
@@ -925,6 +969,12 @@ cusceneext_data make_cutrace_scene(
return {};
}

// Update cameras
void update_cutrace_cameras(cusceneext_data& cuscene, const scene_data& scene,
const cutrace_params& params) {
exit_nocuda();
}

// Build the bvh acceleration structure.
cubvh_data make_cutrace_bvh(cutrace_context& context, cusceneext_data& cuscene,
const scene_data& scene, const cutrace_params& params) {
@@ -938,6 +988,10 @@ cutrace_state make_cutrace_state(
exit_nocuda();
return {};
}
void reset_cutrace_state(cutrace_state& state, const scene_data& scene,
const cutrace_params& params) {
exit_nocuda();
}

// Initialize lights.
cutrace_lights make_cutrace_lights(
65 changes: 50 additions & 15 deletions libs/yocto/yocto_cutrace.cu
Original file line number Diff line number Diff line change
@@ -4033,15 +4033,41 @@ static sampler_func get_trace_sampler_func(const trace_params& params) {
}
}

static trace_result trace_sampler(const scene_data& scene, const trace_bvh& bvh,
const trace_lights& lights, const ray3f& ray, rng_state& rng,
const trace_params& params) {
switch (params.sampler) {
case trace_sampler_type::path:
return trace_path(scene, bvh, lights, ray, rng, params);
case trace_sampler_type::pathdirect:
return trace_pathdirect(scene, bvh, lights, ray, rng, params);
case trace_sampler_type::pathmis:
return trace_pathmis(scene, bvh, lights, ray, rng, params);
case trace_sampler_type::naive:
return trace_naive(scene, bvh, lights, ray, rng, params);
case trace_sampler_type::eyelight:
return trace_eyelight(scene, bvh, lights, ray, rng, params);
case trace_sampler_type::eyelightao:
return trace_eyelightao(scene, bvh, lights, ray, rng, params);
case trace_sampler_type::furnace:
return trace_furnace(scene, bvh, lights, ray, rng, params);
case trace_sampler_type::falsecolor:
return trace_falsecolor(scene, bvh, lights, ray, rng, params);
default: {
return {};
}
}
}

static void trace_sample(cutrace_state& state, const cuscene_data& scene,
const cutrace_bvh& bvh, const cutrace_lights& lights, int i, int j,
const cutrace_params& params) {
auto& camera = scene.cameras[params.camera];
auto sampler = get_trace_sampler_func(params);
auto idx = state.width * j + i;
auto ray = sample_camera(camera, {i, j}, {state.width, state.height},
rand2f(state.rngs[idx]), rand2f(state.rngs[idx]), params.tentfilter);
auto result = sampler(scene, bvh, lights, ray, state.rngs[idx], params);
int sample, const cutrace_params& params) {
auto& camera = scene.cameras[params.camera];
// auto sampler = get_trace_sampler_func(params);
auto idx = state.width * j + i;
auto ray = sample_camera(camera, {i, j}, {state.width, state.height},
rand2f(state.rngs[idx]), rand2f(state.rngs[idx]), params.tentfilter);
auto result = trace_sampler(scene, bvh, lights, ray, state.rngs[idx], params);
// auto [radiance, hit, albedo, normal] = sampler(
// scene, bvh, lights, ray, state.rngs[idx], params);
auto radiance = result.radiance;
@@ -4051,16 +4077,23 @@ static void trace_sample(cutrace_state& state, const cuscene_data& scene,
if (!isfinite(radiance)) radiance = {0, 0, 0};
if (max(radiance) > params.clamp)
radiance = radiance * (params.clamp / max(radiance));
auto weight = 1.0f / (sample + 1);
if (hit) {
state.image[idx] += {radiance.x, radiance.y, radiance.z, 1};
state.albedo[idx] += albedo;
state.normal[idx] += normal;
state.image[idx] = lerp(
state.image[idx], {radiance.x, radiance.y, radiance.z, 1}, weight);
state.albedo[idx] = lerp(state.albedo[idx], albedo, weight);
state.normal[idx] = lerp(state.normal[idx], normal, weight);
state.hits[idx] += 1;
} else if (!params.envhidden && !scene.environments.empty()) {
state.image[idx] += {radiance.x, radiance.y, radiance.z, 1};
state.albedo[idx] += {1, 1, 1};
state.normal[idx] += -ray.d;
state.image[idx] = lerp(
state.image[idx], {radiance.x, radiance.y, radiance.z, 1}, weight);
state.albedo[idx] = lerp(state.albedo[idx], {1, 1, 1}, weight);
state.normal[idx] = lerp(state.normal[idx], -ray.d, weight);
state.hits[idx] += 1;
} else {
state.image[idx] = lerp(state.image[idx], {0, 0, 0, 0}, weight);
state.albedo[idx] = lerp(state.albedo[idx], {0, 0, 0}, weight);
state.normal[idx] = lerp(state.normal[idx], -ray.d, weight);
}
}

@@ -4077,10 +4110,12 @@ optix_shader void __raygen__trace_pixel() {
}

// run shading
auto ssample = globals.state.samples;
auto nsamples = globals.params.batch;
for (auto sample = 0; sample < nsamples; sample++) {
for (auto sample = ssample; sample < ssample + nsamples; sample++) {
trace_sample(globals.state, globals.scene, globals.bvh, globals.lights,
optixGetLaunchIndex().x, optixGetLaunchIndex().y, cutrace_params{});
optixGetLaunchIndex().x, optixGetLaunchIndex().y, sample,
globals.params);
}
}

7 changes: 7 additions & 0 deletions libs/yocto/yocto_cutrace.h
Original file line number Diff line number Diff line change
@@ -97,6 +97,8 @@ cutrace_context make_cutrace_context(const cutrace_params& params);
// Upload the scene to the GPU.
cusceneext_data make_cutrace_scene(
const scene_data& scene, const cutrace_params& params);
void update_cutrace_cameras(cusceneext_data& cuscene, const scene_data& scene,
const cutrace_params& params);

// Build the bvh acceleration structure.
cubvh_data make_cutrace_bvh(cutrace_context& context, cusceneext_data& cuscene,
@@ -105,6 +107,8 @@ cubvh_data make_cutrace_bvh(cutrace_context& context, cusceneext_data& cuscene,
// Initialize state.
cutrace_state make_cutrace_state(
const scene_data& scene, const cutrace_params& params);
void reset_cutrace_state(cutrace_state& state, const scene_data& scene,
const cutrace_params& params);

// Initialize lights.
cutrace_lights make_cutrace_lights(
@@ -136,6 +140,9 @@ void get_albedo_image(image_data& image, const cutrace_state& state);
image_data get_normal_image(const cutrace_state& state);
void get_normal_image(image_data& image, const cutrace_state& state);

// check if display
bool is_display(const cutrace_context& context);

} // namespace yocto

// -----------------------------------------------------------------------------
Loading