diff --git a/Keishiki/CMakeLists.txt b/Keishiki/CMakeLists.txt index ca0d31a..f1f85e5 100644 --- a/Keishiki/CMakeLists.txt +++ b/Keishiki/CMakeLists.txt @@ -18,6 +18,7 @@ set_property(TARGET Keishiki PROPERTY CXX_STANDARD 23) include_directories ("include" "include/ext" "ext/imgui" "ext/implot" "ext/plf_colony") +add_subdirectory("ext/fmt") add_subdirectory("ext/freetype") add_compile_definitions(WL_EGL_PLATFORM) @@ -46,5 +47,5 @@ else () find_package(ECM REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH ${ECM_FIND_MODULE_DIR}) find_package(Wayland REQUIRED Egl) - target_link_libraries (Keishiki PRIVATE freetype bgfx bx SDL3::SDL3 ${Wayland_LIBRARIES}) + target_link_libraries (Keishiki PRIVATE freetype bgfx bx SDL3::SDL3 ${Wayland_LIBRARIES} fmt) endif () diff --git a/Keishiki/Graphics.cpp b/Keishiki/Graphics.cpp index cb3bd8e..ea30c17 100644 --- a/Keishiki/Graphics.cpp +++ b/Keishiki/Graphics.cpp @@ -5,13 +5,9 @@ #include -#include #include #include -#define STB_IMAGE_IMPLEMENTATION -#include - namespace { struct PosUVVertex { f32 x; @@ -52,7 +48,7 @@ namespace { error = FT_Load_Char(face, c, FT_LOAD_RENDER); if (error) { - K::LogError("Failed to load character"); + K::Log(K::K_L_Error, "Failed to load character"); } if (slot->bitmap.width != 0) { @@ -95,17 +91,17 @@ namespace { error = FT_New_Face(library, path, 0, &f.face); if (error == FT_Err_Unknown_File_Format) { - K::LogError("FreeType Unknown_File_Format"); + K::Log(K::K_L_Error, "FreeType Unknown_File_Format"); return std::nullopt; } else if (error) { - K::LogError("FreeType font loading error"); + K::Log(K::K_L_Error, "FreeType font loading error"); return std::nullopt; } error = FT_Set_Char_Size(f.face, 0, 20 * 64, 72, 72); if (error) { - K::LogError("FreeType Set_Char_Size error"); + K::Log(K::K_L_Error, "FreeType Set_Char_Size error"); return std::nullopt; } @@ -140,7 +136,7 @@ namespace K::Graphics { bool Init() { error = FT_Init_FreeType(&library); if (error) { - LogError("FreeType init error: " + std::to_string(error)); + Log(K_L_Info, "FreeType init error: {}", error); return false; } diff --git a/Keishiki/Keishiki.cpp b/Keishiki/Keishiki.cpp index 54d5bf3..4662a76 100644 --- a/Keishiki/Keishiki.cpp +++ b/Keishiki/Keishiki.cpp @@ -20,16 +20,14 @@ namespace K { bool Init() { if (SDL_Init(SDL_INIT_VIDEO)) { - LogError(SDL_GetError()); + Log(K_L_Error, "{}", SDL_GetError()); return false; } - app_state.window = SDL_CreateWindow("Keishiki", - app_state.window_width, app_state.window_height, - SDL_WINDOW_RESIZABLE); + app_state.window = SDL_CreateWindow("Keishiki", app_state.window_width, app_state.window_height, SDL_WINDOW_RESIZABLE); if (app_state.window == nullptr) { - LogError(SDL_GetError()); + Log(K_L_Error, "{}", SDL_GetError()); return false; } @@ -65,15 +63,16 @@ namespace K { #endif if (!bgfx::init(bgfxInit)) { - LogError("bgfx initialization failed"); + Log(K_L_Error, "bgfx initialization failed"); return false; } - K::Resource::Init(); + if (!K::Resource::Init()) + return false; K::UI::Init(app_state.window); if (!K::Graphics::Init()) { - LogError("Graphics init failed"); + Log(K_L_Error, "Graphics init failed"); return false; } diff --git a/Keishiki/Plugboard.cpp b/Keishiki/Plugboard.cpp index f7699f6..ee352f0 100644 --- a/Keishiki/Plugboard.cpp +++ b/Keishiki/Plugboard.cpp @@ -33,7 +33,7 @@ namespace K::Plugboard { to->out[to_out_index].outgoing.push_back({from_instance, input_index}); }, from_instance, to_instance); else - Log("Connect failed -- Cycle detected"); + Log(K_L_Warning, "Connect failed -- Cycle detected"); } void Disconnect(NodeInstanceP from_instance, u8 input_index) { @@ -58,7 +58,7 @@ namespace K::Plugboard { return arg; }, socket.value), type, good)); if (!good) - K::LogError("Type mismatch on plugboard evaluation!"); + Log(K_L_Warning, "Type mismatch on plugboard evaluation!"); return v; } diff --git a/Keishiki/Resource.cpp b/Keishiki/Resource.cpp index f65dd29..0124ea5 100644 --- a/Keishiki/Resource.cpp +++ b/Keishiki/Resource.cpp @@ -3,6 +3,8 @@ #include #include #include + +#define STB_IMAGE_IMPLEMENTATION #include namespace { @@ -37,6 +39,7 @@ namespace K::Resource { std::filesystem::path ffmpeg_path = "ffmpeg"; std::filesystem::path shaderc_path = "./ext/bgfx/cmake/bgfx/shaderc"; + const char *shaderc_temp_args; Resource *fallback_still; @@ -46,7 +49,7 @@ namespace K::Resource { Resource res{.last_updated = std::filesystem::last_write_time(p)}; res.buf = stbi_load(p.c_str(), &res.w, &res.h, &res.channels, 0); if (res.buf == nullptr) { - K::LogError("Image loading failed for " + p.string()); + Log(K_L_Error, "Image loading failed for {}", p.string()); return nullptr; } const bgfx::Memory *ref = bgfx::makeRef(res.buf, res.w * res.h * res.channels * sizeof(Byte)); @@ -107,7 +110,7 @@ namespace K::Resource { i32 w, h, channels; Byte *buf = stbi_load(path.c_str(), &w, &h, &channels, 0); if (buf == nullptr) { - K::LogError("Image loading failed for " + path.string()); + Log(K_L_Error, "Image loading failed for {}", path.string()); return; } const bgfx::Memory *ref = bgfx::makeRef(buf, w * h * channels * sizeof(Byte)); @@ -127,7 +130,7 @@ namespace K::Resource { arg.tex = tex; } else { - LogError("Bad image! Has your app finished writing? -- " + path.string()); + Log(K_L_Error, "Bad image! Has your app finished writing? -- {}", path.string()); stbi_image_free(buf); } } @@ -148,21 +151,57 @@ namespace K::Resource { } } - void Init() { + bool Init() { switch (bgfx::getRendererType()) { case bgfx::RendererType::Noop: case bgfx::RendererType::Direct3D11: - case bgfx::RendererType::Direct3D12: shader_path = "shaders/dx11/"; break; - case bgfx::RendererType::Gnm: shader_path = "shaders/pssl/"; break; - case bgfx::RendererType::Metal: shader_path = "shaders/metal/"; break; - case bgfx::RendererType::OpenGL: shader_path = "shaders/glsl/"; break; - case bgfx::RendererType::OpenGLES: shader_path = "shaders/essl/"; break; - case bgfx::RendererType::Vulkan: shader_path = "shaders/spirv/"; break; - default: K::LogError("Unsupported renderer"); + case bgfx::RendererType::Direct3D12: + shader_path = "shaders/dx11/"; + shaderc_temp_args = "-f temp.frag " + "--type fragment " + "--platform windows " + "--profile " "s_5_0" " " + "--varyingdef temp.varying.def.sc " + "-i ./ " + "-o shaders/" "dx11" "/temp.frag.bin"; + break; + case bgfx::RendererType::Metal: + shader_path = "shaders/metal/"; + shaderc_temp_args = "-f temp.frag " + "--type fragment " + "--platform osx " + "--profile " "metal" " " + "--varyingdef temp.varying.def.sc " + "-i ./ " + "-o shaders/" "metal" "/temp.frag.bin"; + break; + case bgfx::RendererType::OpenGL: + shader_path = "shaders/glsl/"; + shaderc_temp_args = "-f temp.frag " + "--type fragment " + "--platform windows " + "--profile " "140" " " + "--varyingdef temp.varying.def.sc " + "-i ./ " + "-o shaders/" "glsl" "/temp.frag.bin"; + break; + case bgfx::RendererType::Vulkan: + shader_path = "shaders/spirv/"; + shaderc_temp_args = "-f temp.frag " + "--type fragment " + "--platform linux " + "--profile " "spirv" " ""--varyingdef temp.varying.def.sc " + "-i ./ " + "-o shaders/" "spirv" "/temp.frag.bin"; + break; + default: + Log(K_L_Info, "Unsupported renderer"); + return false; } reload_worker = std::thread(HotReload); fallback_still = Load("mmaker.png"); + return fallback_still != nullptr; } void Shutdown() { diff --git a/Keishiki/UI.cpp b/Keishiki/UI.cpp index 9b7b9bb..6da3216 100644 --- a/Keishiki/UI.cpp +++ b/Keishiki/UI.cpp @@ -12,11 +12,11 @@ #include #include -#include #define STB_IMAGE_WRITE_IMPLEMENTATION #include #include +#include namespace { const K::Resource::Resource *logo; @@ -1826,10 +1826,10 @@ namespace K::UI { } ImGui::TableNextColumn(); if constexpr (std::is_same_v>) { - ImGui::Text("%s", std::format("{:%Y-%m-%d %X}", arg.frag_last_updated).c_str()); + ImGui::Text("%s", fmt::format("{:%Y-%m-%d %X}", std::chrono::file_clock::to_sys(arg.frag_last_updated)).c_str()); } else { - ImGui::Text("%s", std::format("{:%Y-%m-%d %X}", arg.last_updated).c_str()); + ImGui::Text("%s", fmt::format("{:%Y-%m-%d %X}", std::chrono::file_clock::to_sys(arg.last_updated)).c_str()); } }, res); ImGui::PopID(); @@ -1914,7 +1914,7 @@ namespace K::UI { ImGui_ImplSDL3_InitForVulkan(window); break; default: - LogError("Unsupported Renderer"); + Log(K_L_Error, "Unsupported Renderer"); } bg.pg = Resource::Load("Checkerboard")->pg; diff --git a/Keishiki/VisualTrack.cpp b/Keishiki/VisualTrack.cpp index 777aeb4..bc43800 100644 --- a/Keishiki/VisualTrack.cpp +++ b/Keishiki/VisualTrack.cpp @@ -127,45 +127,14 @@ namespace K { String s = Resource::shaderc_path; s += " "; - switch (bgfx::getRendererType()) { - case bgfx::RendererType::Noop: - case bgfx::RendererType::Direct3D11: - case bgfx::RendererType::Direct3D12: s += "-f temp.frag " - "--type fragment " - "--platform windows " - "--profile " "s_5_0" " " - "--varyingdef temp.varying.def.sc " - "-i ./ " - "-o shaders/" "dx11" "/temp.frag.bin"; break; - case bgfx::RendererType::Metal: s += "-f temp.frag " - "--type fragment " - "--platform osx " - "--profile " "metal" " " - "--varyingdef temp.varying.def.sc " - "-i ./ " - "-o shaders/" "metal" "/temp.frag.bin"; break; - case bgfx::RendererType::OpenGL: s += "-f temp.frag " - "--type fragment " - "--platform windows " - "--profile " "140" " " - "--varyingdef temp.varying.def.sc " - "-i ./ " - "-o shaders/" "glsl" "/temp.frag.bin"; break; - case bgfx::RendererType::Vulkan: s += "-f temp.frag " - "--type fragment " - "--platform linux " - "--profile " "spirv" " ""--varyingdef temp.varying.def.sc " - "-i ./ " - "-o shaders/" "spirv" "/temp.frag.bin"; break; - default: LogError("Unsupported renderer"); break; - } + s += Resource::shaderc_temp_args; if (std::system(s.c_str()) == 0) { if (isValid(pg)) bgfx::destroy(pg); pg = Resource::FetchUnmanagedShaderProgram("temp"); } else - Log("User shader compilation failed"); + Log(K_L_Warning, "User shader compilation failed"); } void VisualTrack::Clear() { diff --git a/Keishiki/include/Common.h b/Keishiki/include/Common.h index 412bb08..df91105 100644 --- a/Keishiki/include/Common.h +++ b/Keishiki/include/Common.h @@ -16,7 +16,7 @@ typedef uint64_t u64; #include #include #include -#include +#include namespace K { using String = std::string; @@ -25,19 +25,23 @@ namespace K { template using Vector = std::vector; template using Dict = std::unordered_map; - inline void LogBase(const std::string_view& s, u8 level) { - static const char *levels[] = { - "Info", - "Warning", - "Error" - }; - level > 1 ? std::cerr : std::cout << "[" << levels[level] << "] Keishiki: " << s << std::endl; - } - inline void Log(const std::string_view& s) { - LogBase(s, 0); - } - inline void LogError(const std::string_view& s) { - LogBase(s, 2); + enum LogLevel { + K_L_Info, + K_L_Warning, + K_L_Error + }; + + static const char *LogLevelNames[] = { + "Info", + "Warning", + "Error" + }; + + template + inline void Log(LogLevel level, fmt::format_string fmt, Ts&&... args) { + fmt::print(level > K_L_Info ? stderr : stdout, "[{}] Keishiki: ", LogLevelNames[level]); + fmt::print(fmt, std::forward(args)...); + fmt::print("\n"); } struct CompState; // fwd declared -- Keishiki.h <-> VisualTrack.h has dependency cycle diff --git a/Keishiki/include/Plugboard.h b/Keishiki/include/Plugboard.h index bbf160a..740dd99 100644 --- a/Keishiki/include/Plugboard.h +++ b/Keishiki/include/Plugboard.h @@ -1,10 +1,8 @@ #pragma once #include "Common.h" #include "Graphics.h" -#include #include #include -#include #include #include #include diff --git a/Keishiki/include/Resource.h b/Keishiki/include/Resource.h index 92f099a..1e7b55a 100644 --- a/Keishiki/include/Resource.h +++ b/Keishiki/include/Resource.h @@ -7,6 +7,7 @@ namespace K::Resource { extern std::filesystem::path ffmpeg_path; extern std::filesystem::path shaderc_path; + extern const char *shaderc_temp_args; extern std::shared_mutex resource_lock; @@ -75,7 +76,7 @@ namespace K::Resource { extern Resource *fallback_still; - void Init(); + bool Init(); void Shutdown(); template diff --git a/Keishiki/include/VisualTrack.h b/Keishiki/include/VisualTrack.h index 5b4eb16..5ddcbdc 100644 --- a/Keishiki/include/VisualTrack.h +++ b/Keishiki/include/VisualTrack.h @@ -26,7 +26,7 @@ namespace K { Plugboard::T_Map::type ShaderValToPlugboard(const ShaderGraph::T_Map::type& val); struct VisualTrack { - ShaderGraph::ShaderGraph tree; +// ShaderGraph::ShaderGraph tree; bgfx::ProgramHandle pg = BGFX_INVALID_HANDLE; String shader; Vector uniforms; diff --git a/README.md b/README.md index 8c96f43..00e676d 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,10 @@ ## Libraries - [bgfx](https://github.com/bkaradzic/bgfx) - [Dear ImGui](https://github.com/ocornut/imgui) -- [ImPlot](https://github.com/epezent/implot) +- [fmt](https://github.com/fmtlib/fmt) - [FreeType](https://freetype.org/) - [imgui_impl_bgfx](https://gist.github.com/pr0g/aff79b71bf9804ddb03f39ca7c0c3bbb) +- [ImPlot](https://github.com/epezent/implot) - [SDL2](https://www.libsdl.org/) - [stb](https://github.com/nothings/stb) - [SRELL](https://www.akenotsuki.com/misc/srell/en/)