Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 1 addition & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
name: ci
on:
push:
tags-ignore: v*.*
branches:
- '*'
pull_request:
branches:
- '*'
on: [push, pull_request]
jobs:
build-linux:
runs-on: ubuntu-latest
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ compile_commands.json

wiki
imgui.ini

facade.log*
25 changes: 14 additions & 11 deletions facade-lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ target_compile_definitions(${PROJECT_NAME}
target_sources(${PROJECT_NAME} PRIVATE
include/facade/defines.hpp

include/facade/util/async_queue.hpp
include/facade/util/byte_buffer.hpp
include/facade/util/colour_space.hpp
include/facade/util/data_provider.hpp
Expand All @@ -85,9 +86,6 @@ target_sources(${PROJECT_NAME} PRIVATE
include/facade/util/unique.hpp
include/facade/util/visitor.hpp

include/facade/glfw/glfw.hpp
include/facade/glfw/input.hpp

include/facade/vk/buffer.hpp
include/facade/vk/cmd.hpp
include/facade/vk/defer.hpp
Expand All @@ -109,10 +107,10 @@ target_sources(${PROJECT_NAME} PRIVATE
include/facade/vk/vma.hpp
include/facade/vk/wsi.hpp

include/facade/dear_imgui/dear_imgui.hpp
include/facade/glfw/glfw.hpp
include/facade/glfw/input.hpp

include/facade/engine/engine.hpp
include/facade/engine/renderer.hpp
include/facade/dear_imgui/dear_imgui.hpp

include/facade/scene/camera.hpp
include/facade/scene/fly_cam.hpp
Expand All @@ -121,20 +119,22 @@ target_sources(${PROJECT_NAME} PRIVATE
include/facade/scene/material.hpp
include/facade/scene/node.hpp
include/facade/scene/rect.hpp
include/facade/scene/renderer.hpp
include/facade/scene/scene.hpp
include/facade/scene/transform.hpp

include/facade/engine/engine.hpp

include/facade/editor/common.hpp
include/facade/editor/inspector.hpp
include/facade/editor/log.hpp

src/util/data_provider.cpp
src/util/geometry.cpp
src/util/image.cpp
src/util/logger.cpp
src/util/time.cpp

src/glfw/glfw.cpp

src/vk/buffer.cpp
src/vk/cmd.cpp
src/vk/descriptor_set.cpp
Expand All @@ -153,19 +153,22 @@ target_sources(${PROJECT_NAME} PRIVATE
src/vk/vk.cpp
src/vk/vma.cpp

src/glfw/glfw.cpp

src/dear_imgui/dear_imgui.cpp

src/detail/gltf.cpp
src/detail/gltf.hpp

src/engine/engine.cpp
src/engine/renderer.cpp

src/scene/camera.cpp
src/scene/material.cpp
src/scene/renderer.cpp
src/scene/scene.cpp
src/scene/transform.cpp

src/engine/engine.cpp

src/editor/common.cpp
src/editor/inspector.cpp
src/editor/log.cpp
)
91 changes: 81 additions & 10 deletions facade-lib/include/facade/editor/common.hpp
Original file line number Diff line number Diff line change
@@ -1,28 +1,99 @@
#pragma once
#include <facade/util/pinned.hpp>
#include <glm/vec2.hpp>
#include <cassert>
#include <concepts>

namespace facade::editor {
class Window : public Pinned {
///
/// \brief Base class for RAII Dear ImGui wrappers whose widgets return a boolean on Begin()
///
class Openable : public Pinned {
public:
explicit Window(char const* label, bool* open_if = {}, int flags = {});
~Window();

bool is_open() const { return m_open; }
explicit operator bool() const { return is_open(); }

protected:
Openable(bool is_open);
bool m_open;
};

///
/// \brief Required dependency on an Openable which must be open (when used as an argument)
///
template <typename T>
struct NotClosed {
NotClosed([[maybe_unused]] T const& t) { assert(t.is_open()); }
};

///
/// \brief RAII Dear ImGui window
///
class Window : public Openable {
public:
class Menu;

explicit Window(char const* label, bool* open_if = {}, int flags = {});
Window(NotClosed<Window> parent, char const* label, glm::vec2 size = {}, bool border = {}, int flags = {});
~Window();

private:
bool m_open{};
bool m_child{};
};

class TreeNode : public Pinned {
///
/// \brief RAII Dear ImGui TreeNode
///
class TreeNode : public Openable {
public:
explicit TreeNode(char const* label, int flags = {});
~TreeNode();
};

bool is_open() const { return m_open; }
explicit operator bool() const { return is_open(); }
///
/// \brief Base class for Dear ImGui MenuBars
///
class MenuBar : public Openable {
protected:
using Openable::Openable;
};

private:
bool m_open{};
///
/// \brief RAII Dear ImGui Menu object
///
class Menu : public Openable {
public:
explicit Menu(NotClosed<MenuBar>, char const* label, bool enabled = true);
~Menu();
};

///
/// \brief RAII Dear ImGui windowed MenuBar
///
class Window::Menu : public MenuBar {
public:
explicit Menu(NotClosed<Window>);
~Menu();
};

///
/// \brief RAII Dear ImGui MainMenuBar
///
class MainMenu : public MenuBar {
public:
explicit MainMenu();
~MainMenu();
};

///
/// \brief RAII Dear ImGui StyleVar stack
///
class StyleVar : public Pinned {
public:
explicit StyleVar(int index, glm::vec2 value);
explicit StyleVar(int index, float value);
~StyleVar();

explicit operator bool() const { return true; }
};
} // namespace facade::editor
20 changes: 20 additions & 0 deletions facade-lib/include/facade/editor/log.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#pragma once
#include <facade/util/enum_array.hpp>
#include <facade/util/logger.hpp>
#include <vector>

namespace facade::editor {
class Log : public logger::Accessor {
public:
void render();

bool show{};

private:
void operator()(std::span<logger::Entry const> entries) final;

std::vector<logger::Entry const*> m_list{};
EnumArray<logger::Level, bool> m_level_filter{true, true, true, debug_v};
int m_display_count{50};
};
} // namespace facade::editor
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ struct FrameStats {
/// \brief Framerate (until previous frame)
///
std::uint32_t fps{};
///
/// \brief Current present mode
///
vk::PresentModeKHR mode{};
};

struct RendererCreateInfo {
Expand Down
85 changes: 85 additions & 0 deletions facade-lib/include/facade/util/async_queue.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#pragma once
#include <condition_variable>
#include <deque>
#include <mutex>
#include <optional>
#include <stop_token>

namespace facade {
///
/// \brief Basic multi-producer, multi-consumer FIFO queue
///
template <typename Type>
class AsyncQueue {
public:
///
/// \brief Push t to the back
///
void push(Type t) {
auto lock = std::unique_lock{m_mutex};
m_queue.push_back(std::move(t));
lock.unlock();
m_cv.notify_one();
}

///
/// \brief Push [*first, *last) in order to the back
///
template <typename It>
void push(It first, It last) {
auto lock = std::unique_lock{m_mutex};
m_queue.insert(m_queue.end(), first, last);
lock.unlock();
m_cv.notify_all();
}

///
/// \brief Try to dequeue an item: non-blocking
/// \returns std::nullopt if queue is empty, else the front
///
std::optional<Type> try_pop() {
auto lock = std::unique_lock{m_mutex};
if (m_queue.empty()) { return {}; }
return pop_front(lock);
}

///
/// \brief Try to dequeue an item: blocking
/// \returns std::nullopt if queue is empty or stop has been requested, else the front
///
std::optional<Type> pop(std::stop_token const& stop) {
auto lock = std::unique_lock{m_mutex};
m_cv.wait(lock, [this, stop] { return !m_queue.empty() || stop.stop_requested(); });
if (stop.stop_requested() || m_queue.empty()) { return {}; }
return pop_front(lock);
}

///
/// \brief Notify all sleeping threads
///
void ping() { m_cv.notify_all(); }

///
/// \brief Empty queue into drain, notify all sleeping threads, and return drain
/// \returns Items left in the queue
///
std::deque<Type> release() {
auto lock = std::unique_lock{m_mutex};
auto ret = std::move(m_queue);
lock.unlock();
m_cv.notify_all();
return ret;
}

private:
std::optional<Type> pop_front(std::unique_lock<std::mutex> const&) {
auto ret = std::move(m_queue.front());
m_queue.pop_front();
return ret;
}

std::deque<Type> m_queue{};
std::condition_variable m_cv{};
std::mutex m_mutex{};
};
} // namespace facade
40 changes: 30 additions & 10 deletions facade-lib/include/facade/util/logger.hpp
Original file line number Diff line number Diff line change
@@ -1,38 +1,58 @@
#pragma once
#include <fmt/format.h>
#include <facade/defines.hpp>
#include <facade/util/pinned.hpp>
#include <span>

namespace facade::logger {
enum class Pipe { eStdOut, eStdErr };
enum class Pipe : std::uint8_t { eStdOut, eStdErr };
enum class Level : std::uint8_t { eError, eWarn, eInfo, eDebug, eCOUNT_ };
inline constexpr char levels_v[] = {'E', 'W', 'I', 'D'};

inline std::string g_format{"[{thread}] [{severity}] {message} [{timestamp}]"};
inline std::string g_format{"[T{thread}] [{level}] {message} [{timestamp}]"};

struct Entry {
std::string message{};
Level level{};
};

struct Accessor {
virtual void operator()(std::span<Entry const> entries) = 0;
};

int thread_id();
std::string format(char severity, std::string_view const message);
void print_to(Pipe pipe, char const* text);
std::string format(Level level, std::string_view const message);
void log_to(Pipe pipe, Entry entry);
void access_buffer(Accessor& accessor);

class Instance : public Pinned {
public:
Instance(std::size_t buffer_limit = 500, std::size_t buffer_extra = 100);
~Instance();
};

template <typename... Args>
std::string format(char severity, fmt::format_string<Args...> fmt, Args const&... args) {
return format(severity, fmt::vformat(fmt, fmt::make_format_args(args...)));
std::string format(Level level, fmt::format_string<Args...> fmt, Args const&... args) {
return format(level, fmt::vformat(fmt, fmt::make_format_args(args...)));
}

template <typename... Args>
void error(fmt::format_string<Args...> fmt, Args const&... args) {
print_to(Pipe::eStdErr, format('E', fmt, args...).c_str());
log_to(Pipe::eStdErr, {format(Level::eError, fmt, args...), Level::eError});
}

template <typename... Args>
void warn(fmt::format_string<Args...> fmt, Args const&... args) {
print_to(Pipe::eStdOut, format('W', fmt, args...).c_str());
log_to(Pipe::eStdOut, {format(Level::eWarn, fmt, args...), Level::eWarn});
}

template <typename... Args>
void info(fmt::format_string<Args...> fmt, Args const&... args) {
print_to(Pipe::eStdOut, format('I', fmt, args...).c_str());
log_to(Pipe::eStdOut, {format(Level::eInfo, fmt, args...), Level::eInfo});
}

template <typename... Args>
void debug(fmt::format_string<Args...> fmt, Args const&... args) {
if constexpr (debug_v) { print_to(Pipe::eStdOut, format('D', fmt, args...).c_str()); }
if constexpr (debug_v) { log_to(Pipe::eStdOut, {format(Level::eDebug, fmt, args...), Level::eDebug}); }
}
} // namespace facade::logger
Loading