Skip to content

src/KDGpuExample/engine.h

Namespaces

Name
KDGpuExample

Classes

Name
class KDGpuExample::Engine
Engine ...

Types

Name
using std::chrono::time_point< std::chrono::high_resolution_clock > TimePoint

Types Documentation

using TimePoint

1
using TimePoint =  std::chrono::time_point<std::chrono::high_resolution_clock>;

Source code

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
/*
  This file is part of KDGpu.

  SPDX-FileCopyrightText: 2023 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>

  SPDX-License-Identifier: MIT

  Contact KDAB at <info@kdab.com> for commercial licensing options.
*/

#pragma once

#include "engine_layer.h"

#include <KDGpuExample/kdgpuexample_export.h>

#include <KDFoundation/object.h>
#include <KDUtils/logging.h>

#include <kdbindings/property.h>

#include <chrono>
#include <memory>
#include <vector>

using TimePoint = std::chrono::time_point<std::chrono::high_resolution_clock>;

namespace KDGpuExample {

class KDGPUEXAMPLE_EXPORT Engine : public KDFoundation::Object
{
public:
    KDBindings::Property<bool> running{ false };
    KDBindings::Property<double> fps{ 0.0 };

    Engine();
    ~Engine() override;

    EngineLayer *attachEngineLayer(std::unique_ptr<EngineLayer> &&engineLayer);
    std::unique_ptr<EngineLayer> detachEngineLayer(EngineLayer *engineLayer);
    const std::vector<std::unique_ptr<EngineLayer>> &engineLayers() const { return m_engineLayers; }

    template<typename T, typename... Ts>
    T *createEngineLayer(Ts... args)
    {
        static_assert(std::is_base_of<EngineLayer, T>::value,
                      "The T type must inherit from EngineLayer.");
        auto engineLayer = std::make_unique<T>(std::forward<Ts>(args)...);
        return static_cast<T *>(this->attachEngineLayer(std::move(engineLayer)));
    }

    template<typename T>
    T *engineLayer() const
    {
        for (const auto &engineLayer : m_engineLayers) {
            const auto t = dynamic_cast<T *>(engineLayer.get());
            if (t)
                return t;
        }
        return nullptr;
    }

    void event(KDFoundation::EventReceiver *target, KDFoundation::Event *ev) override;

    void requestFrame();
    void doFrame();

    // Frame timing
    TimePoint startTime() const { return m_startTime; }
    TimePoint currentFrameTime() const { return m_currentFrameTime; }
    TimePoint previousFrameTime() const { return m_previousFrameTime; }
    uint64_t frameNumber() const { return m_totalFrameCounter; }
    float deltaTimeSeconds() const
    {
        return std::chrono::nanoseconds(
                       currentFrameTime() - previousFrameTime())
                       .count() *
                1.0e-9f;
    }

    std::chrono::nanoseconds simulationTime() const
    {
        return std::chrono::duration_cast<std::chrono::nanoseconds>(m_currentFrameTime - m_startTime);
    }

private:
    void onRunningChanged(const bool &newValue);

    std::shared_ptr<spdlog::logger> m_logger;
    std::vector<std::unique_ptr<EngineLayer>> m_engineLayers;

    // Current and previous frame times
    TimePoint m_startTime;
    TimePoint m_currentFrameTime;
    TimePoint m_previousFrameTime;

    // Frames per second reporting
    uint32_t m_frameCounter{ 0 };
    uint64_t m_totalFrameCounter{ 0 };
    TimePoint m_lastFpsTimestamp;
};

} // namespace KDGpuExample

Updated on 2024-09-08 at 00:13:11 +0000