Spaces:
Build error
Build error
| /* | |
| * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | |
| * SPDX-License-Identifier: Apache-2.0 | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| /** @file common_host.cu | |
| * @author Thomas Müller, NVIDIA | |
| */ | |
| namespace ngp { | |
| bool is_wsl() { | |
| return false; | |
| fs::path path = "/proc/sys/kernel/osrelease"; | |
| if (!path.exists()) { | |
| return false; | |
| } | |
| std::ifstream f{native_string(path)}; | |
| std::string content((std::istreambuf_iterator<char>(f)), (std::istreambuf_iterator<char>())); | |
| return content.find("microsoft") != std::string::npos; | |
| } | |
| std::string utf16_to_utf8(const std::wstring& utf16) { | |
| std::string utf8; | |
| if (!utf16.empty()) { | |
| int size = WideCharToMultiByte(CP_UTF8, 0, &utf16[0], (int)utf16.size(), NULL, 0, NULL, NULL); | |
| utf8.resize(size, 0); | |
| WideCharToMultiByte(CP_UTF8, 0, &utf16[0], (int)utf16.size(), &utf8[0], size, NULL, NULL); | |
| } | |
| return utf8; | |
| } | |
| std::wstring utf8_to_utf16(const std::string& utf8) { | |
| std::wstring utf16; | |
| if (!utf8.empty()) { | |
| int size = MultiByteToWideChar(CP_UTF8, 0, &utf8[0], (int)utf8.size(), NULL, 0); | |
| utf16.resize(size, 0); | |
| MultiByteToWideChar(CP_UTF8, 0, &utf8[0], (int)utf8.size(), &utf16[0], size); | |
| } | |
| return utf16; | |
| } | |
| std::wstring native_string(const fs::path& path) { return path.wstr(); } | |
| std::string native_string(const fs::path& path) { return path.str(); } | |
| fs::path discover_executable_dir() { | |
| WCHAR path[1024]; | |
| if (GetModuleFileNameW(NULL, path, 1024) == 0) { | |
| return "."; | |
| } | |
| return fs::path{std::wstring{path}}.parent_path(); | |
| char path[PATH_MAX]; | |
| ssize_t count = readlink("/proc/self/exe", path, PATH_MAX); | |
| if (count == -1) { | |
| return "."; | |
| } | |
| return fs::path{std::string{path}}.parent_path(); | |
| } | |
| fs::path discover_root_dir() { | |
| auto executable_dir = discover_executable_dir(); | |
| fs::path exists_in_root_dir = "scripts"; | |
| for (const auto& candidate : { | |
| fs::path{"."} / exists_in_root_dir, | |
| fs::path{".."} / exists_in_root_dir, | |
| executable_dir / exists_in_root_dir, | |
| executable_dir / ".." / exists_in_root_dir, | |
| }) { | |
| if (candidate.exists()) { | |
| return candidate.parent_path(); | |
| } | |
| } | |
| tlog::warning() << "Could not find root directory."; | |
| return "."; | |
| } | |
| bool ends_with(const std::string& str, const std::string& ending) { | |
| if (ending.length() > str.length()) { | |
| return false; | |
| } | |
| return std::equal(std::rbegin(ending), std::rend(ending), std::rbegin(str)); | |
| } | |
| bool ends_with_case_insensitive(const std::string& str, const std::string& ending) { return ends_with(to_lower(str), to_lower(ending)); } | |
| ETestbedMode mode_from_scene(const std::string& scene) { | |
| return ETestbedMode::None; | |
| } | |
| ETestbedMode mode_from_string(const std::string& str) { | |
| if (equals_case_insensitive(str, "image")) { | |
| return ETestbedMode::Gen3c; | |
| } else { | |
| return ETestbedMode::None; | |
| } | |
| } | |
| std::string to_string(ETestbedMode mode) { | |
| switch (mode) { | |
| case ETestbedMode::Gen3c: return "gen3c"; | |
| case ETestbedMode::None: return "none"; | |
| default: throw std::runtime_error{fmt::format("Can not convert mode {} to string.", (int)mode)}; | |
| } | |
| } | |
| static const stbi_io_callbacks istream_stbi_callbacks = { | |
| // Read | |
| [](void* context, char* data, int size) { | |
| auto stream = reinterpret_cast<std::istream*>(context); | |
| stream->read(data, size); | |
| return (int)stream->gcount(); | |
| }, | |
| // Seek | |
| [](void* context, int size) { reinterpret_cast<std::istream*>(context)->seekg(size, std::ios_base::cur); }, | |
| // EOF | |
| [](void* context) { return (int)!!(*reinterpret_cast<std::istream*>(context)); }, | |
| }; | |
| void istream_stbi_write_func(void* context, void* data, int size) { | |
| reinterpret_cast<std::ostream*>(context)->write(reinterpret_cast<char*>(data), size); | |
| } | |
| uint8_t* load_stbi(const fs::path& path, int* width, int* height, int* comp, int req_comp) { | |
| std::ifstream f{native_string(path), std::ios::in | std::ios::binary}; | |
| return stbi_load_from_callbacks(&istream_stbi_callbacks, &f, width, height, comp, req_comp); | |
| } | |
| float* load_stbi_float(const fs::path& path, int* width, int* height, int* comp, int req_comp) { | |
| std::ifstream f{native_string(path), std::ios::in | std::ios::binary}; | |
| return stbi_loadf_from_callbacks(&istream_stbi_callbacks, &f, width, height, comp, req_comp); | |
| } | |
| uint16_t* load_stbi_16(const fs::path& path, int* width, int* height, int* comp, int req_comp) { | |
| std::ifstream f{native_string(path), std::ios::in | std::ios::binary}; | |
| return stbi_load_16_from_callbacks(&istream_stbi_callbacks, &f, width, height, comp, req_comp); | |
| } | |
| bool is_hdr_stbi(const fs::path& path) { | |
| std::ifstream f{native_string(path), std::ios::in | std::ios::binary}; | |
| return stbi_is_hdr_from_callbacks(&istream_stbi_callbacks, &f); | |
| } | |
| int write_stbi(const fs::path& path, int width, int height, int comp, const uint8_t* pixels, int quality) { | |
| std::ofstream f{native_string(path), std::ios::out | std::ios::binary}; | |
| if (equals_case_insensitive(path.extension(), "jpg") || equals_case_insensitive(path.extension(), "jpeg")) { | |
| return stbi_write_jpg_to_func(istream_stbi_write_func, &f, width, height, comp, pixels, quality); | |
| } else if (equals_case_insensitive(path.extension(), "png")) { | |
| return stbi_write_png_to_func(istream_stbi_write_func, &f, width, height, comp, pixels, width * comp); | |
| } else if (equals_case_insensitive(path.extension(), "tga")) { | |
| return stbi_write_tga_to_func(istream_stbi_write_func, &f, width, height, comp, pixels); | |
| } else if (equals_case_insensitive(path.extension(), "bmp")) { | |
| return stbi_write_bmp_to_func(istream_stbi_write_func, &f, width, height, comp, pixels); | |
| } else { | |
| throw std::runtime_error{fmt::format("write_stbi: unknown image extension '{}'", path.extension())}; | |
| } | |
| } | |
| FILE* native_fopen(const fs::path& path, const char* mode) { | |
| return _wfopen(path.wstr().c_str(), utf8_to_utf16(mode).c_str()); | |
| return fopen(path.str().c_str(), mode); | |
| } | |
| GPUMemory<float> load_stbi_gpu(const fs::path& path, int* width, int* height) { | |
| bool is_hdr = is_hdr_stbi(path); | |
| void* data; // width * height * RGBA | |
| int comp; | |
| if (is_hdr) { | |
| data = load_stbi_float(path, width, height, &comp, 4); | |
| } else { | |
| data = load_stbi(path, width, height, &comp, 4); | |
| } | |
| if (!data) { | |
| throw std::runtime_error{std::string{stbi_failure_reason()}}; | |
| } | |
| ScopeGuard mem_guard{[&]() { stbi_image_free(data); }}; | |
| if (*width == 0 || *height == 0) { | |
| throw std::runtime_error{"Image has zero pixels."}; | |
| } | |
| GPUMemory<float> result((*width) * (*height) * 4); | |
| if (is_hdr) { | |
| result.copy_from_host((float*)data); | |
| } else { | |
| GPUMemory<uint8_t> bytes((*width) * (*height) * 4); | |
| bytes.copy_from_host((uint8_t*)data); | |
| linear_kernel(from_rgba32<float>, 0, nullptr, (*width) * (*height), bytes.data(), result.data(), false, false, 0); | |
| } | |
| return result; | |
| } | |
| std::ostream& operator<<(std::ostream& os, const BoundingBox& bb) { | |
| os << "["; | |
| os << "min=[" << bb.min.x << "," << bb.min.y << "," << bb.min.z << "], "; | |
| os << "max=[" << bb.max.x << "," << bb.max.y << "," << bb.max.z << "]"; | |
| os << "]"; | |
| return os; | |
| } | |
| std::ostream& operator<<(std::ostream& os, const Triangle& triangle) { | |
| os << "["; | |
| os << "a=[" << triangle.a.x << "," << triangle.a.y << "," << triangle.a.z << "], "; | |
| os << "b=[" << triangle.b.x << "," << triangle.b.y << "," << triangle.b.z << "], "; | |
| os << "c=[" << triangle.c.x << "," << triangle.c.y << "," << triangle.c.z << "]"; | |
| os << "]"; | |
| return os; | |
| } | |
| } // namespace ngp | |