diff --git a/src/apps/cli.cpp b/src/apps/cli.cpp
index 1d5f7c32..61af74b2 100644
--- a/src/apps/cli.cpp
+++ b/src/apps/cli.cpp
@@ -13,6 +13,25 @@
#include
#include
+#ifdef LUISA_PLATFORM_WINDOWS
+[[nodiscard]] auto get_current_exe_path() noexcept {
+ constexpr auto max_path_length = static_cast(4096);
+ std::filesystem::path::value_type path[max_path_length] = {};
+ auto nchar = GetModuleFileNameW(nullptr, path, max_path_length);
+ if (nchar == 0 ||
+ (nchar == MAX_PATH &&
+ ((GetLastError() == ERROR_INSUFFICIENT_BUFFER) ||
+ (path[MAX_PATH - 1] != 0)))) {
+ LUISA_ERROR_WITH_LOCATION("Failed to get current executable path.");
+ }
+ return std::filesystem::canonical(path).string();
+}
+#else
+[[nodiscard]] auto get_current_exe_path() noexcept {
+ LUISA_NOT_IMPLEMENTED();// TODO
+}
+#endif
+
[[nodiscard]] auto parse_cli_options(int argc, const char *const *argv) noexcept {
cxxopts::Options cli{"luisa-render-cli"};
cli.add_option("", "b", "backend", "Compute backend name", cxxopts::value(), "");
@@ -111,7 +130,9 @@ using namespace luisa::render;
int main(int argc, char *argv[]) {
log_level_info();
- luisa::compute::Context context{argv[0]};
+
+ auto exe_path = get_current_exe_path();
+ luisa::compute::Context context{exe_path};
auto macros = parse_cli_macros(argc, argv);
for (auto &&[k, v] : macros) {
LUISA_INFO("Found CLI Macro: {} = {}", k, v);
@@ -123,7 +144,7 @@ int main(int argc, char *argv[]) {
auto path = options["scene"].as();
compute::DeviceConfig config;
config.device_index = index;
- config.inqueue_buffer_limit = false; // Do not limit the number of in-queue buffers --- we are doing offline rendering!
+ config.inqueue_buffer_limit = false;// Do not limit the number of in-queue buffers --- we are doing offline rendering!
auto device = context.create_device(backend, &config);
Clock clock;
diff --git a/src/integrators/gpt.cpp b/src/integrators/gpt.cpp
index 7e463be4..c4ccabc6 100644
--- a/src/integrators/gpt.cpp
+++ b/src/integrators/gpt.cpp
@@ -206,7 +206,7 @@ class ImageBuffer {
return [host_image, size = _resolution, path = std::move(path), raw] {
for (auto &p : *host_image) {
if (raw) {
- p = make_float4(p.xyz(), 1.f); // don't divide effective_spp
+ p = make_float4(p.xyz(), 1.f);// don't divide effective_spp
} else {
p = make_float4(p.xyz() / p.w, 1.f);
}
@@ -278,12 +278,12 @@ luisa::unique_ptr GradientPathTracing::build(
[[nodiscard]] auto GradientPathTracingInstance::get_vertex_type(luisa::shared_ptr it, const SampledWavelengths &swl, Expr time) const noexcept {
auto surface_tag = it->shape().surface_tag();
Float2 roughness;
- PolymorphicCall call;
pipeline().surfaces().dispatch(surface_tag, [&](auto surface) noexcept {
+ PolymorphicCall call;
surface->closure(call, *it, swl, make_float3(0.f, 0.f, 1.f), 1.f, time);// TODO fix
- });
- call.execute([&](auto closure) noexcept {
- roughness = closure->roughness();
+ call.execute([&](auto closure) noexcept {
+ roughness = closure->roughness();
+ });
});
return get_vertex_type_by_roughness(min(roughness.x, roughness.y));
}
@@ -455,18 +455,18 @@ luisa::unique_ptr GradientPathTracing::build(
auto surface_tag = it.shape().surface_tag();
auto u_lobe = sampler()->generate_1d();
auto u_bsdf = sampler()->generate_2d();
- PolymorphicCall call;
pipeline().surfaces().dispatch(surface_tag, [&](auto surface) noexcept {
+ PolymorphicCall call;
surface->closure(call, it, swl, -ray->direction(), 1.f, time);
- });
- call.execute([&](auto closure) noexcept {
- // if (auto o = closure->opacity()) {
- // auto opacity = saturate(*o);
- // result.alpha_skip = u_lobe >= opacity;
- // u_lobe = ite(result.alpha_skip, (u_lobe - opacity) / (1.f - opacity), u_lobe / opacity);
- // }
- result.sample = closure->sample(-ray->direction(), u_lobe, u_bsdf);
- result.eta = closure->eta().value_or(1.f);
+ call.execute([&](auto closure) noexcept {
+ // if (auto o = closure->opacity()) {
+ // auto opacity = saturate(*o);
+ // result.alpha_skip = u_lobe >= opacity;
+ // u_lobe = ite(result.alpha_skip, (u_lobe - opacity) / (1.f - opacity), u_lobe / opacity);
+ // }
+ result.sample = closure->sample(-ray->direction(), u_lobe, u_bsdf);
+ result.eta = closure->eta().value_or(1.f);
+ });
});
result.weight = result.sample.eval.f;
result.pdf = result.sample.eval.pdf;
@@ -569,12 +569,12 @@ luisa::unique_ptr GradientPathTracing::build(
Surface::Evaluation main_light_eval{.f = SampledSpectrum{swl.dimension(), 0.f}, .pdf = 0.f};
- PolymorphicCall light_eval_call;
pipeline().surfaces().dispatch(main_surface_tag, [&](auto surface) noexcept {
+ PolymorphicCall light_eval_call;
surface->closure(light_eval_call, main.it, swl, wo, 1.f, time);
- });
- light_eval_call.execute([&](auto closure) noexcept {
- main_light_eval = closure->evaluate(wo, wi);
+ light_eval_call.execute([&](auto closure) noexcept {
+ main_light_eval = closure->evaluate(wo, wi);
+ });
});
auto main_distance_squared = length_squared(main.it.p() - main_light_sample.eval.p);
@@ -623,12 +623,12 @@ luisa::unique_ptr GradientPathTracing::build(
auto incoming_direction = normalize(shifted.it.p() - main.it.p());
Surface::Evaluation shifted_bsdf_eval{.f = SampledSpectrum{swl.dimension(), 0.f}, .pdf = 0.f};
- PolymorphicCall shifted_eval_call;
pipeline().surfaces().dispatch(main_surface_tag, [&](auto surface) noexcept {
+ PolymorphicCall shifted_eval_call;
surface->closure(shifted_eval_call, main.it, swl, incoming_direction, 1.f, time);
- });
- shifted_eval_call.execute([&](auto closure) noexcept {
- shifted_bsdf_eval = closure->evaluate(incoming_direction, main_light_sample.shadow_ray->direction());
+ shifted_eval_call.execute([&](auto closure) noexcept {
+ shifted_bsdf_eval = closure->evaluate(incoming_direction, main_light_sample.shadow_ray->direction());
+ });
});
auto shifted_emitter_pdf = main_light_sample.eval.pdf;
auto shifted_bsdf_value = shifted_bsdf_eval.f;
@@ -647,8 +647,8 @@ luisa::unique_ptr GradientPathTracing::build(
auto shifted_vertex_type = get_vertex_type(make_shared(shifted.it), swl, time);
$if(main_vertex_type == (uint)VertexType::VERTEX_TYPE_DIFFUSE & shifted_vertex_type == (uint)VertexType::VERTEX_TYPE_DIFFUSE) {
-// u_light_selection = sampler()->generate_1d();
-// u_light_surface = sampler()->generate_2d();
+ // u_light_selection = sampler()->generate_1d();
+ // u_light_surface = sampler()->generate_2d();
auto shifted_light_sample = light_sampler()->sample(shifted.it, u_light_selection, u_light_surface, swl, time);
auto shifted_occluded = pipeline().geometry()->intersect_any(shifted_light_sample.shadow_ray);
$if(shifted_occluded | shifted_light_sample.eval.pdf <= 0.f) {// shifted failed, no light
@@ -665,12 +665,12 @@ luisa::unique_ptr GradientPathTracing::build(
// TODO: No strict normal here
auto shifted_surface_tag = shifted.it.shape().surface_tag();
Surface::Evaluation shifted_light_eval{.f = SampledSpectrum{swl.dimension(), 0.f}, .pdf = 0.f};
- PolymorphicCall shifted_light_call;
pipeline().surfaces().dispatch(shifted_surface_tag, [&](auto surface) noexcept {
+ PolymorphicCall shifted_light_call;
surface->closure(shifted_light_call, shifted.it, swl, -shifted.ray->direction(), 1.f, time);
- });
- shifted_light_call.execute([&](auto closure) noexcept {
- shifted_light_eval = closure->evaluate(-shifted.ray->direction(), shifted_light_sample.shadow_ray->direction());
+ shifted_light_call.execute([&](auto closure) noexcept {
+ shifted_light_eval = closure->evaluate(-shifted.ray->direction(), shifted_light_sample.shadow_ray->direction());
+ });
});
auto shifted_bsdf_value = shifted_light_eval.f;
@@ -809,12 +809,12 @@ luisa::unique_ptr GradientPathTracing::build(
$case((uint)RayConnection::RAY_RECENTLY_CONNECTED) {
auto incoming_direction = normalize(shifted.it.p() - previous_main_it.p());
Surface::Evaluation shifted_bsdf_eval{.f = SampledSpectrum{swl.dimension(), 0.f}, .pdf = 0.f};
- PolymorphicCall call;
pipeline().surfaces().dispatch(previous_main_it.shape().surface_tag(), [&](auto surface) noexcept {
+ PolymorphicCall call;
surface->closure(call, previous_main_it, swl, incoming_direction, 1.f, time);
- });
- call.execute([&](auto closure) noexcept {
- shifted_bsdf_eval = closure->evaluate(incoming_direction, main.ray->direction());// TODO check if main.ray right
+ call.execute([&](auto closure) noexcept {
+ shifted_bsdf_eval = closure->evaluate(incoming_direction, main.ray->direction());// TODO check if main.ray right
+ });
});
auto shifted_bsdf_value = shifted_bsdf_eval.f;
auto shifted_bsdf_pdf = shifted_bsdf_eval.pdf;
@@ -865,14 +865,14 @@ luisa::unique_ptr GradientPathTracing::build(
// TODO strict normal check
auto shifted_bsdf_pdf = def(0.f);
auto shifted_bsdf_value = SampledSpectrum{swl.dimension(), 0.f};
- PolymorphicCall call;
pipeline().surfaces().dispatch(shifted.it.shape().surface_tag(), [&](auto surface) noexcept {
+ PolymorphicCall call;
surface->closure(call, shifted.it, swl, incoming_direction, 1.f, time);
- });
- call.execute([&](auto closure) noexcept {
- auto shifted_bsdf_eval = closure->evaluate(incoming_direction, outgoing_direction);// TODO check
- shifted_bsdf_pdf = shifted_bsdf_eval.pdf;
- shifted_bsdf_value = shifted_bsdf_eval.f;
+ call.execute([&](auto closure) noexcept {
+ auto shifted_bsdf_eval = closure->evaluate(incoming_direction, outgoing_direction);// TODO check
+ shifted_bsdf_pdf = shifted_bsdf_eval.pdf;
+ shifted_bsdf_value = shifted_bsdf_eval.f;
+ });
});
$if(shifted_bsdf_pdf <= 0.f) {
@@ -927,20 +927,20 @@ luisa::unique_ptr GradientPathTracing::build(
// TODO check if wo is wo
auto main_bsdf_eta = def(0.f);// eta at previous main it
- PolymorphicCall main_call;
pipeline().surfaces().dispatch(previous_main_it.shape().surface_tag(), [&](auto surface) noexcept {
+ PolymorphicCall main_call;
surface->closure(main_call, previous_main_it, swl, -previous_main_ray->direction(), 1.f, time);
- });
- main_call.execute([&](auto closure) noexcept {
- main_bsdf_eta = closure->eta().value_or(1.f);
+ main_call.execute([&](auto closure) noexcept {
+ main_bsdf_eta = closure->eta().value_or(1.f);
+ });
});
auto shifted_bsdf_eta = def(0.f);// eta at previous main it
- PolymorphicCall shifted_call;
pipeline().surfaces().dispatch(shifted.it.shape().surface_tag(), [&](auto surface) noexcept {
+ PolymorphicCall shifted_call;
surface->closure(shifted_call, shifted.it, swl, -shifted.ray->direction(), 1.f, time);
- });
- shifted_call.execute([&](auto closure) noexcept {
- shifted_bsdf_eta = closure->eta().value_or(1.f);
+ shifted_call.execute([&](auto closure) noexcept {
+ shifted_bsdf_eta = closure->eta().value_or(1.f);
+ });
});
auto main_tangent_space_wo = previous_main_it.shading().world_to_local(main_bsdf_result.wo);
@@ -967,26 +967,26 @@ luisa::unique_ptr GradientPathTracing::build(
auto outgoing_direction = shifted.it.shading().local_to_world(tangent_space_outgoing_direction);
$if(!shift_failed_flag) {
- PolymorphicCall call;
pipeline().surfaces().dispatch(shifted.it.shape().surface_tag(), [&](auto surface) noexcept {
+ PolymorphicCall call;
surface->closure(call, shifted.it, swl, -shifted.ray->direction(), 1.f, time);
+ call.execute([&](auto closure) noexcept {
+ // TODO check if tangent space is correct
+ auto eval = closure->evaluate(-shifted.ray->direction(), outgoing_direction);
+ $if(eval.pdf <= 0.f) {
+ // invalid path
+ shifted.alive = false;
+ shift_failed_flag = true;
+ }
+ $else {
+ shifted_bsdf_pdf = eval.pdf;
+ shifted_bsdf_value = eval.f;
+ shifted.weight *= eval.f / eval.pdf;
+ shifted.pdf_div_main_pdf *= eval.pdf / main_bsdf_pdf;
+ };
+ });
+ // Strict normal TODO
});
- call.execute([&](auto closure) noexcept {
- // TODO check if tangent space is correct
- auto eval = closure->evaluate(-shifted.ray->direction(), outgoing_direction);
- $if(eval.pdf <= 0.f) {
- // invalid path
- shifted.alive = false;
- shift_failed_flag = true;
- }
- $else {
- shifted_bsdf_pdf = eval.pdf;
- shifted_bsdf_value = eval.f;
- shifted.weight *= eval.f / eval.pdf;
- shifted.pdf_div_main_pdf *= eval.pdf / main_bsdf_pdf;
- };
- });
- // Strict normal TODO
};
$if(!shift_failed_flag) {
diff --git a/src/sdl/scene_parser.cpp b/src/sdl/scene_parser.cpp
index a4a555cc..2a14702d 100644
--- a/src/sdl/scene_parser.cpp
+++ b/src/sdl/scene_parser.cpp
@@ -17,7 +17,7 @@ namespace luisa::render {
inline SceneParser::SceneParser(SceneDesc &desc, const std::filesystem::path &path,
const MacroMap &cli_macros) noexcept
: _desc{desc}, _cli_macros{cli_macros},
- _location{desc.register_path(std::filesystem::canonical(path))},
+ _location{desc.register_path(LUISA_SCENE_PARSER_CHECKED_CANONICAL_PATH(path))},
_cursor{0u} {}
void SceneParser::_dispatch_parse(SceneDesc &desc, const std::filesystem::path &path,
diff --git a/src/sdl/scene_parser.h b/src/sdl/scene_parser.h
index 0731af81..00907608 100644
--- a/src/sdl/scene_parser.h
+++ b/src/sdl/scene_parser.h
@@ -11,6 +11,15 @@
#include
#include
+#define LUISA_SCENE_PARSER_CHECKED_CANONICAL_PATH(...) ([&] { \
+ try { \
+ return std::filesystem::canonical(__VA_ARGS__); \
+ } catch (const std::filesystem::filesystem_error &e) { \
+ LUISA_ERROR_WITH_LOCATION( \
+ "Failed to open file: {}", e.what()); \
+ } \
+}())
+
namespace luisa::render {
class SceneDesc;
diff --git a/src/sdl/scene_parser_json.cpp b/src/sdl/scene_parser_json.cpp
index 3636a95c..ae5c40e8 100644
--- a/src/sdl/scene_parser_json.cpp
+++ b/src/sdl/scene_parser_json.cpp
@@ -17,7 +17,7 @@ namespace luisa::render {
SceneParserJSON::SceneParserJSON(SceneDesc &desc, const std::filesystem::path &path,
const MacroMap &cli_macros) noexcept
: _desc{desc}, _cli_macros{cli_macros},
- _location{desc.register_path(std::filesystem::canonical(path))} {}
+ _location{desc.register_path(LUISA_SCENE_PARSER_CHECKED_CANONICAL_PATH(path))} {}
void SceneParserJSON::parse() const noexcept {
auto root = [this] {