From 3dad0bd7c8d63dfc9cc0efe878d58c733c40af1e Mon Sep 17 00:00:00 2001 From: Mike Date: Thu, 4 Jan 2024 14:34:19 +0800 Subject: [PATCH] wip: support for command line without `.exe` --- src/apps/cli.cpp | 25 ++++++- src/integrators/gpt.cpp | 128 +++++++++++++++++----------------- src/sdl/scene_parser.cpp | 2 +- src/sdl/scene_parser.h | 9 +++ src/sdl/scene_parser_json.cpp | 2 +- 5 files changed, 98 insertions(+), 68 deletions(-) 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] {