Skip to content

Commit

Permalink
v0.2: Add ui::Element, graphics::NineSlice, graphics::RoundedQuad (#76)
Browse files Browse the repository at this point in the history
* Refactor ui::View into that + ui::Element.

Move build version into generated header.

* Add ui::Element::m_active

* Add Engine::min_frame_time.

Improve engine stats.

* Make Primitive movable.

Fix dangling access in `Resources::store()`.
Add some consts in lit.frag.

* Set window and framebuffer extents on startup.

* Add graphics::Circle.

* Move RenderLayer to dedicated header.

* Move PolygonMode out of PipelineState into Renderer.

* Add graphics::NineSlice

* RoundedQuad, NineSlice.

- Fix sector UVs and verts.

* Add FDuration<PeriodT>.

* Linearize all vertex colours.
  • Loading branch information
karnkaul committed Aug 24, 2023
1 parent edd3021 commit 309bfcf
Show file tree
Hide file tree
Showing 47 changed files with 589 additions and 140 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

project(little-engine VERSION 0.1.0)
project(little-engine VERSION 0.2.0)

set(is_root_project OFF)

Expand Down
6 changes: 3 additions & 3 deletions engine/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ target_compile_definitions(${PROJECT_NAME} PUBLIC
$<$<BOOL:${LE_PCH}>:LE_PCH>
$<$<BOOL:${LE_USE_FREETYPE}>:LE_USE_FREETYPE>
$<$<BOOL:${CAPO_USE_OPENAL}>:CAPO_USE_OPENAL>
LE_VERSION_MAJOR=${PROJECT_VERSION_MAJOR}
LE_VERSION_MINOR=${PROJECT_VERSION_MINOR}
LE_VERSION_PATCH=${PROJECT_VERSION_PATCH}
)

target_link_libraries(${PROJECT_NAME} PUBLIC
Expand All @@ -21,6 +18,7 @@ target_link_libraries(${PROJECT_NAME} PRIVATE

target_include_directories(${PROJECT_NAME} PUBLIC
include
"${CMAKE_CURRENT_BINARY_DIR}/include"
)

target_include_directories(${PROJECT_NAME} PRIVATE
Expand All @@ -31,6 +29,8 @@ target_compile_features(${PROJECT_NAME} PUBLIC
cxx_std_20
)

configure_file(src/build_version.hpp.in "${CMAKE_CURRENT_BINARY_DIR}/include/le/build_version.hpp")

add_subdirectory(src)

include(header_list.cmake)
Expand Down
6 changes: 5 additions & 1 deletion engine/include/le/core/time.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ using namespace std::chrono_literals;

namespace le {
using Clock = std::chrono::steady_clock;
using Duration = std::chrono::duration<float>;

template <typename PeriodT = std::ratio<1, 1>>
using FDuration = std::chrono::duration<float, PeriodT>;

using Duration = FDuration<>;

///
/// \brief Stateful delta-time computer.
Expand Down
2 changes: 0 additions & 2 deletions engine/include/le/core/version.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,5 @@ struct Version {
auto operator<=>(Version const&) const = default;
};

constexpr Version const build_version_v{LE_VERSION_MAJOR, LE_VERSION_MINOR, LE_VERSION_PATCH};

auto to_string(Version const& version) -> std::string;
} // namespace le
13 changes: 9 additions & 4 deletions engine/include/le/core/wrap.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,17 @@ struct Wrap {
StorageT data{};
std::size_t offset{};

[[nodiscard]] constexpr auto get_current() const -> decltype(auto) { return data[offset]; }
[[nodiscard]] constexpr auto get_current() -> decltype(auto) { return data[offset]; }
[[nodiscard]] constexpr auto get_current() const -> decltype(auto) { return data.at(offset); }
[[nodiscard]] constexpr auto get_current() -> decltype(auto) { return data.at(offset); }

[[nodiscard]] constexpr auto get_previous() const -> decltype(auto) { return data[decrement_wrapped(offset, data.size())]; }
[[nodiscard]] constexpr auto get_previous() -> decltype(auto) { return data[decrement_wrapped(offset, data.size())]; }
[[nodiscard]] constexpr auto get_previous() const -> decltype(auto) { return data.at(decrement_wrapped(offset, data.size())); }
[[nodiscard]] constexpr auto get_previous() -> decltype(auto) { return data.at(decrement_wrapped(offset, data.size())); }

constexpr auto advance() -> void { offset = increment_wrapped(offset, data.size()); }

constexpr auto update_offset() -> decltype(auto) {
if (offset >= data.size()) { offset = 0; }
return get_current();
}
};
} // namespace le
2 changes: 2 additions & 0 deletions engine/include/le/engine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ class Engine : public MonoInstance<Engine> {

Engine([[maybe_unused]] ConstructTag tag) noexcept {}

Duration min_frame_time{};

private:
auto update_stats() -> void;

Expand Down
1 change: 1 addition & 0 deletions engine/include/le/environment.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#pragma once
#include <le/build_version.hpp>

namespace le {
constexpr bool debug_v =
Expand Down
5 changes: 3 additions & 2 deletions engine/include/le/graphics/cache/pipeline_cache.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class PipelineCache : public MonoInstance<PipelineCache> {
[[nodiscard]] auto shader_layout() const -> ShaderLayout const& { return m_shader_layout; }
auto set_shader_layout(ShaderLayout shader_layout) -> void;

[[nodiscard]] auto load(PipelineFormat format, Shader shader, PipelineState state = {}) -> vk::Pipeline;
[[nodiscard]] auto load(PipelineFormat format, Shader shader, PipelineState state, vk::PolygonMode polygon_mode) -> vk::Pipeline;

[[nodiscard]] auto pipeline_layout() const -> vk::PipelineLayout { return *m_pipeline_layout; }
[[nodiscard]] auto descriptor_set_layouts() const -> std::span<vk::DescriptorSetLayout const> { return m_descriptor_set_layouts_view; }
Expand All @@ -30,7 +30,7 @@ class PipelineCache : public MonoInstance<PipelineCache> {
private:
struct Key {
public:
Key(PipelineFormat format, Shader shader, PipelineState state);
Key(PipelineFormat format, Shader shader, PipelineState state, vk::PolygonMode polygon_mode);

[[nodiscard]] auto hash() const -> std::size_t { return cached_hash; }

Expand All @@ -39,6 +39,7 @@ class PipelineCache : public MonoInstance<PipelineCache> {
PipelineFormat format{};
Shader shader{};
PipelineState state{};
vk::PolygonMode polygon_mode{};
std::size_t cached_hash{};
};

Expand Down
52 changes: 47 additions & 5 deletions engine/include/le/graphics/geometry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,55 @@

namespace le::graphics {
struct Quad {
glm::vec2 size{1.0f, 1.0f};
glm::vec2 size{1.0f};
UvRect uv{uv_rect_v};
Rgba rgb{white_v};
Rgba rgba{white_v};
glm::vec3 origin{};

auto operator==(Quad const&) const -> bool = default;
};

struct Circle {
static constexpr int resolution_v{128};

float diameter{1.0f};
int resolution{resolution_v};
Rgba rgba{white_v};
glm::vec3 origin{};

auto operator==(Circle const&) const -> bool = default;
};

struct RoundedQuad : Quad {
float corner_radius{0.25f};
int corner_resolution{8};

auto operator==(RoundedQuad const&) const -> bool = default;
};

struct NineSlice {
struct Size {
glm::vec2 total{1.0f};
glm::vec2 top{0.25f};
glm::vec2 bottom{0.25f};

[[nodiscard]] auto rescaled(glm::vec2 extent) const -> Size;

auto operator==(Size const&) const -> bool = default;
};

Size size{};
UvRect top_uv{.lt = {}, .rb = glm::vec2{0.25f}};
UvRect bottom_uv{.lt = glm::vec2{0.75f}, .rb = glm::vec2{1.0f}};
Rgba rgba{white_v};
glm::vec3 origin{};

auto operator==(NineSlice const&) const -> bool = default;
};

struct Cube {
glm::vec3 size{1.0f, 1.0f, 1.0f};
Rgba rgb{white_v};
glm::vec3 size{1.0f};
Rgba rgba{white_v};
glm::vec3 origin{};

auto operator==(Cube const&) const -> bool = default;
Expand All @@ -30,7 +68,7 @@ struct Sphere {

float diameter{1.0f};
std::uint32_t resolution{resolution_v};
Rgba rgb{white_v};
Rgba rgba{white_v};
glm::vec3 origin{};

auto operator==(Sphere const&) const -> bool = default;
Expand All @@ -56,6 +94,10 @@ struct Geometry {
auto append(std::span<Vertex const> vs, std::span<std::uint32_t const> is) -> Geometry&;

auto append(Quad const& quad) -> Geometry&;
auto append(Circle const& circle) -> Geometry&;
auto append(RoundedQuad const& rounded_quad) -> Geometry&;
auto append(NineSlice const& nine_slice) -> Geometry&;

auto append(Cube const& cube) -> Geometry&;
auto append(Sphere const& sphere) -> Geometry&;

Expand Down
4 changes: 1 addition & 3 deletions engine/include/le/graphics/pipeline_state.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#pragma once
#include <le/vfs/uri.hpp>
#include <vulkan/vulkan.hpp>

namespace le::graphics {
Expand All @@ -10,9 +9,8 @@ struct PipelineFormat {

struct PipelineState {
vk::PrimitiveTopology topology{vk::PrimitiveTopology::eTriangleList};
vk::PolygonMode polygon_mode{vk::PolygonMode::eFill};
vk::CompareOp depth_compare{vk::CompareOp::eLess};
vk::Bool32 depth_test_write{1};
vk::Bool32 depth_test_write{vk::True};
float line_width{1.0f};
};
} // namespace le::graphics
8 changes: 4 additions & 4 deletions engine/include/le/graphics/primitive.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@
namespace le::graphics {
class Primitive {
public:
Primitive() = default;

Primitive(Primitive const&) = delete;
Primitive(Primitive&&) = delete;
auto operator=(Primitive const&) -> Primitive& = delete;
auto operator=(Primitive&&) -> Primitive& = delete;

Primitive(Primitive&&) = default;
auto operator=(Primitive&&) -> Primitive& = default;

Primitive() = default;
virtual ~Primitive() = default;

struct Layout {
Expand Down
3 changes: 2 additions & 1 deletion engine/include/le/graphics/renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class Renderer : public MonoInstance<Renderer> {
std::optional<glm::vec2> custom_world_frustum{};
glm::vec3 shadow_frustum{100.0f};
vk::Extent2D shadow_map_extent{2048, 2048};
vk::PolygonMode polygon_mode{vk::PolygonMode::eFill};

private:
struct Frame {
Expand Down Expand Up @@ -100,7 +101,7 @@ class Renderer : public MonoInstance<Renderer> {
auto bake_objects(RenderFrame const& render_frame) -> void;

std::unique_ptr<DearImGui> m_imgui{};
PipelineCache m_pipeline_cache;
PipelineCache m_pipeline_cache{};
SamplerCache m_sampler_cache{};
DescriptorCache m_descriptor_cache{};
ScratchBufferCache m_scratch_buffer_cache{};
Expand Down
18 changes: 16 additions & 2 deletions engine/include/le/imcpp/engine_stats.hpp
Original file line number Diff line number Diff line change
@@ -1,20 +1,34 @@
#pragma once
#include <glm/vec3.hpp>
#include <le/core/time.hpp>
#include <le/core/wrap.hpp>
#include <le/imcpp/common.hpp>
#include <vector>

namespace le::imcpp {
class EngineStats {
public:
static constexpr std::size_t frame_time_count_v{200};
struct FpsRgb {
std::uint32_t lower_bound{};
glm::vec3 rgb{};
};

static constexpr int frame_time_count_v{200};

auto draw_to(OpenWindow w) -> void;

auto set_frame_time_count(std::size_t count) -> void;

int frame_samples{frame_time_count_v};
std::vector<FpsRgb> fps_rgb{
FpsRgb{.lower_bound = 30, .rgb = {1.0f, 0.0f, 0.0f}},
FpsRgb{.lower_bound = 45, .rgb = {1.0f, 1.0f, 0.0f}},
FpsRgb{.lower_bound = 60, .rgb = {0.25f, 1.0f, 0.0f}},
};

private:
auto push_frame_time(Duration dt) -> void;

Wrap<std::vector<float>> m_frame_times{std::vector<float>(frame_time_count_v)};
Wrap<std::vector<float>> m_frame_times{};
};
} // namespace le::imcpp
3 changes: 2 additions & 1 deletion engine/include/le/resources/resources.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once
#include <le/core/mono_instance.hpp>
#include <le/core/ptr.hpp>
#include <le/core/time.hpp>
#include <le/error.hpp>
#include <le/resources/asset.hpp>
#include <le/vfs/uri.hpp>
Expand Down Expand Up @@ -53,7 +54,7 @@ class Resources : public MonoInstance<Resources> {
template <std::derived_from<Asset> Type>
[[nodiscard]] static auto is_ready(std::future<Ptr<Type>> const& future) -> bool {
if (!future.valid()) { return false; }
return future.wait_for(std::chrono::seconds{}) == std::future_status::ready;
return future.wait_for(0s) == std::future_status::ready;
}

auto clear() -> void;
Expand Down
10 changes: 10 additions & 0 deletions engine/src/build_version.hpp.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#pragma once
#include <le/core/version.hpp>

namespace le {
constexpr Version build_version_v{
.major = @PROJECT_VERSION_MAJOR@,
.minor = @PROJECT_VERSION_MINOR@,
.patch = @PROJECT_VERSION_PATCH@,
};
}
10 changes: 10 additions & 0 deletions engine/src/engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <le/error.hpp>
#include <le/input/receiver.hpp>
#include <format>
#include <thread>

namespace le {
namespace {
Expand Down Expand Up @@ -225,6 +226,12 @@ auto Engine::render(graphics::RenderFrame const& frame) -> void {
}

FrameProfiler::self().finish();

if (min_frame_time > 0s) {
auto const frame_time = Clock::now() - m_delta_time.start;
auto const remain = min_frame_time - frame_time;
if (remain > 0s) { std::this_thread::sleep_for(remain); }
}
}

auto Engine::shutdown() -> void {
Expand Down Expand Up @@ -291,6 +298,9 @@ auto Engine::Builder::build() -> std::unique_ptr<Engine> {

ret->m_audio_device = std::make_unique<audio::Device>();

g_input_state.window_extent = ret->window_extent();
g_input_state.framebuffer_extent = ret->framebuffer_extent();

return ret;
}
} // namespace le
15 changes: 8 additions & 7 deletions engine/src/graphics/cache/pipeline_cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,10 @@ struct PipelineShaderLayout {
auto const g_log{logger::Logger{"Cache"}};
} // namespace

PipelineCache::Key::Key(PipelineFormat format, Shader shader, PipelineState state) : format(format), shader(std::move(shader)), state(state) {
cached_hash = make_combined_hash(shader.vertex.hash(), shader.fragment.hash(), state.topology, state.polygon_mode, state.depth_compare,
state.depth_test_write, format.colour, format.depth);
PipelineCache::Key::Key(PipelineFormat format, Shader shader, PipelineState state, vk::PolygonMode polygon_mode)
: format(format), shader(std::move(shader)), state(state), polygon_mode(polygon_mode) {
cached_hash = make_combined_hash(shader.vertex.hash(), shader.fragment.hash(), state.topology, polygon_mode, state.depth_compare, state.depth_test_write,
format.colour, format.depth);
}

PipelineCache::PipelineCache(ShaderLayout shader_layout) { set_shader_layout(std::move(shader_layout)); }
Expand All @@ -71,8 +72,8 @@ auto PipelineCache::set_shader_layout(ShaderLayout shader_layout) -> void {
m_pipeline_layout = m_device.createPipelineLayoutUnique(plci);
}

auto PipelineCache::load(PipelineFormat format, Shader shader, PipelineState state) -> vk::Pipeline {
auto const key = Key{format, std::move(shader), state};
auto PipelineCache::load(PipelineFormat format, Shader shader, PipelineState state, vk::PolygonMode polygon_mode) -> vk::Pipeline {
auto const key = Key{format, std::move(shader), state, polygon_mode};
auto itr = m_pipelines.find(key);
if (itr == m_pipelines.end()) {
auto ret = build(key);
Expand All @@ -92,7 +93,7 @@ auto PipelineCache::clear_pipelines() -> void {
}

auto PipelineCache::clear_pipelines_and_shaders() -> void {
Device::self().get_device().waitIdle();
m_device.waitIdle();
clear_pipelines();
m_shader_cache.clear_shaders();
}
Expand Down Expand Up @@ -123,7 +124,7 @@ auto PipelineCache::build(Key const& key) -> vk::UniquePipeline {
gpci.pStages = shader_stages.data();

auto prsci = vk::PipelineRasterizationStateCreateInfo{};
prsci.polygonMode = key.state.polygon_mode;
prsci.polygonMode = key.polygon_mode;
prsci.cullMode = vk::CullModeFlagBits::eNone;
gpci.pRasterizationState = &prsci;

Expand Down

0 comments on commit 309bfcf

Please sign in to comment.