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

Implementation of naïve path tracing in CUDA #1341

Merged
merged 20 commits into from
Mar 3, 2022
2 changes: 1 addition & 1 deletion .github/workflows/macos-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
run: |
mkdir build
cd build
cmake .. -G"Unix Makefiles" -DYOCTO_OPENGL=ON -DYOCTO_EMBREE=OFF -DYOCTO_DENOISE=OFF
cmake .. -G"Unix Makefiles" -DYOCTO_OPENGL=ON -DYOCTO_EMBREE=OFF -DYOCTO_DENOISE=OFF -DYOCTO_CUDA=OFF
- name: build
run: |
cd build
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ubuntu-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
run: |
mkdir build
cd build
cmake .. -G"Unix Makefiles" -DYOCTO_OPENGL=ON -DYOCTO_EMBREE=OFF -DYOCTO_DENOISE=OFF
cmake .. -G"Unix Makefiles" -DYOCTO_OPENGL=ON -DYOCTO_EMBREE=OFF -DYOCTO_DENOISE=OFF -DYOCTO_CUDA=OFF
- name: build
run: |
cd build
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/windows-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
run: |
mkdir build
cd build
cmake .. -G "Visual Studio 16 2019" -DYOCTO_OPENGL=ON -DYOCTO_EMBREE=OFF -DYOCTO_DENOISE=OFF
cmake .. -G "Visual Studio 17 2022" -DYOCTO_OPENGL=ON -DYOCTO_EMBREE=OFF -DYOCTO_DENOISE=OFF -DYOCTO_CUDA=OFF
- name: build
run: |
cd build
Expand Down
170 changes: 134 additions & 36 deletions libs/yocto/yocto_cutrace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@

#include "yocto_cutrace.h"

#include "yocto_sampling.h"

#if YOCTO_CUDA

// do not reorder
Expand Down Expand Up @@ -175,11 +177,28 @@ struct cutrace_camera {
struct cutrace_texture {
CUarray array;
CUtexObject texture;
int width = 0;
int height = 0;
bool linear = false;
};

struct cutrace_material {
vec3f color;
int color_tex;
material_type type = material_type::matte;
vec3f emission = {0, 0, 0};
vec3f color = {0, 0, 0};
float roughness = 0;
float metallic = 0;
float ior = 1.5f;
vec3f scattering = {0, 0, 0};
float scanisotropy = 0;
float trdepth = 0.01f;
float opacity = 1;

int emission_tex = invalidid;
int color_tex = invalidid;
int roughness_tex = invalidid;
int scattering_tex = invalidid;
int normal_tex = invalidid;
};

struct cutrace_instance {
Expand All @@ -192,15 +211,23 @@ struct cutrace_shape {
cubuffer<vec3f> positions = {};
cubuffer<vec3f> normals = {};
cubuffer<vec2f> texcoords = {};
cubuffer<vec4f> colors = {};
cubuffer<vec3i> triangles = {};
};

struct cutrace_environment {
frame3f frame = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}, {0, 0, 0}};
vec3f emission = {0, 0, 0};
int emission_tex = invalidid;
};

struct cutrace_scene {
cubuffer<cutrace_camera> cameras = {};
cubuffer<cutrace_texture> textures = {};
cubuffer<cutrace_material> materials = {};
cubuffer<cutrace_shape> shapes = {};
cubuffer<cutrace_instance> instances = {};
cubuffer<cutrace_camera> cameras = {};
cubuffer<cutrace_texture> textures = {};
cubuffer<cutrace_material> materials = {};
cubuffer<cutrace_shape> shapes = {};
cubuffer<cutrace_instance> instances = {};
cubuffer<cutrace_environment> environments = {};
};

struct cutrace_sceneext : cutrace_scene {
Expand All @@ -221,17 +248,46 @@ struct cubvh_data {

// state
struct cutrace_state {
int width = 0;
int height = 0;
int samples = 0;
cubuffer<vec4f> colorBuffer = {};
int width = 0;
int height = 0;
int samples = 0;
cubuffer<vec4f> image = {};
cubuffer<vec3f> albedo = {};
cubuffer<vec3f> normal = {};
cubuffer<int> hits = {};
cubuffer<rng_state> rngs = {};
cubuffer<vec4f> display = {};
};

// params
struct cutrace_dparams {
int camera = 0;
int resolution = 1280;
cutrace_sampler_type sampler = cutrace_sampler_type::path;
cutrace_falsecolor_type falsecolor = cutrace_falsecolor_type::color;
int samples = 512;
int bounces = 8;
float clamp = 10;
bool nocaustics = false;
bool envhidden = false;
bool tentfilter = false;
uint64_t seed = cutrace_default_seed;
bool embreebvh = false;
bool highqualitybvh = false;
bool noparallel = false;
int pratio = 8;
float exposure = 0;
bool filmic = false;
bool denoise = false;
int batch = 1;
};

// device params
struct cutrace_globals {
cutrace_state state = {};
cutrace_scene scene = {};
OptixTraversableHandle bvh = {};
cutrace_state state = {};
cutrace_scene scene = {};
OptixTraversableHandle bvh = {};
cutrace_dparams params = {};
};

// empty stb record
Expand Down Expand Up @@ -383,22 +439,28 @@ static cutrace_context make_cutrace_context(const cutrace_params& params) {
return context;
}

/*! render one frame */
static void render_samples(cutrace_context& context, cutrace_state& state,
// start a new render
static void render_start(cutrace_context& context, cutrace_state& state,
const cutrace_scene& cuscene, const cubvh_data& bvh,
const scene_data& scene, const cutrace_params& params) {
// launch params
auto globals = cutrace_globals{};
globals.state = state;
globals.scene = cuscene;
globals.bvh = bvh.instances_bvh.handle;
auto globals = cutrace_globals{};
globals.state = state;
globals.scene = cuscene;
globals.bvh = bvh.instances_bvh.handle;
globals.params = (const cutrace_dparams&)params;
update_buffer(context.globals_buffer, globals);
// sync so we can get the frame
check_cusync();
}

// render a batch of samples
static void render_samples(cutrace_context& context, cutrace_state& state,
const cutrace_scene& cuscene, const cubvh_data& bvh,
const scene_data& scene, const cutrace_params& params) {
check_result(optixLaunch(context.optix_pipeline, context.cuda_stream,
context.globals_buffer.device_ptr(),
context.globals_buffer.size_in_bytes(), &context.binding_table,
state.width, state.height, 1));

// sync so we can get the frame
check_cusync();
}
Expand Down Expand Up @@ -428,18 +490,25 @@ static cutrace_sceneext make_cutrace_scene(
if (!shape.normals.empty()) cushape.normals = make_buffer(shape.normals);
if (!shape.texcoords.empty())
cushape.texcoords = make_buffer(shape.texcoords);
if (!shape.colors.empty()) cushape.colors = make_buffer(shape.colors);
}
cuscene.shapes = make_buffer(cuscene.cushapes);

// textures
for (auto& texture : scene.textures) {
auto& cutexture = cuscene.cutextures.emplace_back();
auto& cutexture = cuscene.cutextures.emplace_back();
cutexture.width = texture.width;
cutexture.height = texture.height;
cutexture.linear = texture.linear;

auto as_byte = !texture.pixelsb.empty();

auto array_descriptor = CUDA_ARRAY_DESCRIPTOR{};
array_descriptor.Width = texture.width;
array_descriptor.Height = texture.height;
array_descriptor.NumChannels = 4;
array_descriptor.Format = CU_AD_FORMAT_UNSIGNED_INT8;
array_descriptor.Format = as_byte ? CU_AD_FORMAT_UNSIGNED_INT8
: CU_AD_FORMAT_FLOAT;
check_result(cuArrayCreate(&cutexture.array, &array_descriptor));

auto memcpy_descriptor = CUDA_MEMCPY2D{};
Expand All @@ -451,17 +520,15 @@ static cutrace_sceneext make_cutrace_scene(
memcpy_descriptor.srcHost = nullptr;
memcpy_descriptor.srcXInBytes = 0;
memcpy_descriptor.srcY = 0;
memcpy_descriptor.srcPitch = texture.width * 4;
memcpy_descriptor.WidthInBytes = texture.width * 4;
memcpy_descriptor.srcPitch = texture.width * (as_byte ? 4 : 16);
memcpy_descriptor.WidthInBytes = texture.width * (as_byte ? 4 : 16);
memcpy_descriptor.Height = texture.height;
if (!texture.pixelsb.empty()) {
memcpy_descriptor.srcHost = texture.pixelsb.data();
check_result(cuMemcpy2D(&memcpy_descriptor));
}
if (!texture.pixelsf.empty()) {
auto pixelsb = vector<vec4b>(texture.pixelsf.size());
rgb_to_srgb(pixelsb, texture.pixelsf);
memcpy_descriptor.srcHost = pixelsb.data();
memcpy_descriptor.srcHost = texture.pixelsf.data();
check_result(cuMemcpy2D(&memcpy_descriptor));
}

Expand Down Expand Up @@ -489,9 +556,22 @@ static cutrace_sceneext make_cutrace_scene(

auto materials = vector<cutrace_material>{};
for (auto& material : scene.materials) {
auto& cumaterial = materials.emplace_back();
cumaterial.color = material.color;
cumaterial.color_tex = material.color_tex;
auto& cumaterial = materials.emplace_back();
cumaterial.type = material.type;
cumaterial.emission = material.emission;
cumaterial.color = material.color;
cumaterial.roughness = material.roughness;
cumaterial.metallic = material.metallic;
cumaterial.ior = material.ior;
cumaterial.scattering = material.scattering;
cumaterial.trdepth = material.trdepth;
cumaterial.opacity = material.opacity;

cumaterial.emission_tex = material.emission_tex;
cumaterial.color_tex = material.color_tex;
cumaterial.roughness_tex = material.roughness_tex;
cumaterial.scattering_tex = material.scattering_tex;
cumaterial.normal_tex = material.normal_tex;
}
cuscene.materials = make_buffer(materials);

Expand All @@ -504,6 +584,15 @@ static cutrace_sceneext make_cutrace_scene(
}
cuscene.instances = make_buffer(instances);

auto environments = vector<cutrace_environment>{};
for (auto& environment : scene.environments) {
auto& cuenvironment = environments.emplace_back();
cuenvironment.frame = environment.frame;
cuenvironment.emission = environment.emission;
cuenvironment.emission_tex = environment.emission_tex;
}
cuscene.environments = make_buffer(environments);

return cuscene;
}

Expand Down Expand Up @@ -664,8 +753,13 @@ static cutrace_state make_cutrace_state(
state.height = params.resolution;
state.width = (int)round(params.resolution * camera.aspect);
}
state.samples = 0;
state.colorBuffer = make_buffer(state.width * state.height, (vec4f*)nullptr);
state.samples = 0;
state.image = make_buffer(state.width * state.height, (vec4f*)nullptr);
state.albedo = make_buffer(state.width * state.height, (vec3f*)nullptr);
state.normal = make_buffer(state.width * state.height, (vec3f*)nullptr);
state.hits = make_buffer(state.width * state.height, (int*)nullptr);
state.rngs = make_buffer(state.width * state.height, (rng_state*)nullptr);
state.display = make_buffer(state.width * state.height, (vec4f*)nullptr);
return state;
};

Expand All @@ -678,11 +772,14 @@ image_data cutrace_image(
auto state = make_cutrace_state(scene, params);

// rendering
render_start(context, state, cuscene, bvh, scene, params);
// for (auto sample = 0; sample < params.samples; sample++) {
render_samples(context, state, cuscene, bvh, scene, params);
// }

// copy back image
auto image = make_image(state.width, state.height, false);
download_buffer(state.colorBuffer, image.pixels);
auto image = make_image(state.width, state.height, true);
download_buffer(state.image, image.pixels);

// cleanup

Expand All @@ -704,6 +801,7 @@ static void exit_nocuda() { throw std::runtime_error{"cuda not linked\n"}; }
image_data cutrace_image(
const scene_data& scene, const cutrace_params& params) {
exit_nocuda();
return {};
}

} // namespace yocto
Expand Down
Loading