Files
Renderive/render_2D/renderable/Renderable.h
T
2026-08-12 13:46:53 +08:00

170 lines
5.7 KiB
C++

#pragma once
#include "../base/Types.h"
#include "../event/Event.h"
#include <renderive/renderable/base/Renderable_Base.hpp>
#include <renderive/renderable/base/Renderable_Task_Observer.hpp>
#include <renderive/base/statistics/Rolling_Statistics.hpp>
#include <atomic>
#include <functional>
#include <mutex>
#include <string>
namespace renderive {
class Plot_Core;
namespace detail {
class Painter;
class Renderable_State_Observer;
}
class Event_Handler {
public:
virtual ~Event_Handler() = default;
virtual void handle_event(const Event& event) = 0;
};
enum class Renderable_Observer_Event {
None,
Cache_Updated,
Published,
Render_Started,
Render_Completed,
Render_Failed
};
struct Renderable_Observation {
Renderable_Observer_Event event{Renderable_Observer_Event::None};
std::uint64_t event_time_ns{};
std::uint64_t cache_update_count{};
std::uint64_t publish_count{};
std::uint64_t successful_render_count{};
std::uint64_t failed_render_count{};
std::uint64_t last_render_sequence{};
std::uint64_t last_render_duration_ns{};
std::uint64_t total_render_duration_ns{};
std::uint64_t maximum_render_duration_ns{};
std::size_t render_duration_sample_count{};
std::uint64_t render_duration_average_ns{};
std::uint64_t render_duration_deviation_ns{};
std::uint64_t render_duration_p50_ns{};
std::uint64_t render_duration_p95_ns{};
std::uint64_t render_duration_p99_ns{};
std::uint64_t task_execution_count{};
std::uint64_t failed_task_count{};
std::uint64_t last_task_duration_ns{};
std::uint64_t total_task_duration_ns{};
std::uint64_t maximum_task_duration_ns{};
std::size_t task_duration_sample_count{};
std::uint64_t task_duration_average_ns{};
std::uint64_t task_duration_deviation_ns{};
std::uint64_t task_duration_p50_ns{};
std::uint64_t task_duration_p95_ns{};
std::uint64_t task_duration_p99_ns{};
std::size_t last_task_count{};
std::size_t peak_parallelism{};
};
class LIB_DECL Renderable_Observer final {
public:
[[nodiscard]] Renderable_Observation observation() const noexcept;
void observe_state(Renderable_Observer_Event event, std::uint64_t time_ns,
std::uint64_t cache_update_count,
std::uint64_t publish_count) noexcept;
void observe_task(const Renderable_Task_Observation& observation) noexcept;
void reset_performance() noexcept;
private:
mutable std::mutex mutex_;
Renderable_Observation observation_;
std::uint64_t active_render_sequence_{};
std::uint64_t active_render_started_ns_{};
std::size_t active_task_count_{};
std::size_t completed_task_count_{};
std::size_t running_task_count_{};
std::size_t active_peak_parallelism_{};
bool active_render_failed_{};
Rolling_Statistics render_duration_statistics_{256};
Rolling_Statistics task_duration_statistics_{1024};
};
class LIB_DECL Renderable : public ::Renderable_Base,
public ::Renderable_Task_Observer {
public:
explicit Renderable(Plot_Core& plot, bool cache_enabled = true);
~Renderable() override;
[[nodiscard]] Plot_Core& plot() const noexcept { return plot_; }
[[nodiscard]] Renderable_Cache_Mode get_cache_mode() const noexcept;
void set_cache_mode(Renderable_Cache_Mode mode);
[[nodiscard]] std::string object_name() const;
void set_object_name(std::string name);
[[nodiscard]] bool is_visible() const noexcept;
void set_visible(bool visible);
[[nodiscard]] Renderable_Observation observation() const noexcept;
void render(const ::Scene_Render_Context& context) final;
void observe_task(const Renderable_Task_Observation& observation) noexcept final;
protected:
using Paint_Task_Function =
std::function<void(detail::Painter&, const Render_State_View&,
const Scene_Render_Context&)>;
virtual void paint(detail::Painter& painter, const Render_State_View& state) = 0;
virtual void build_paint_task_graph(Renderable_Task_Graph& graph);
Renderable_Task_Graph::Task add_paint_task(Renderable_Task_Graph& graph,
std::string name,
Paint_Task_Function function);
void changed() noexcept;
void task_graph_changed() noexcept;
[[nodiscard]] Size viewport_size() const noexcept;
private:
void build_task_graph(Renderable_Task_Graph& graph) final;
void reset_task_observation() noexcept final;
void observe_state(Renderable_Observer_Event event, std::uint64_t time_ns,
std::uint64_t cache_update_count,
std::uint64_t publish_count) noexcept;
friend class detail::Renderable_State_Observer;
Plot_Core& plot_;
mutable std::mutex metadata_mutex_;
std::string object_name_;
std::atomic<bool> visible_{true};
Renderable_Observer observer_;
};
namespace detail {
class Renderable_State_Observer {
public:
static constexpr bool enabled = true;
explicit Renderable_State_Observer(Renderable* renderable) noexcept : renderable_(renderable) {}
template <class Observation>
void observe(const Observation& observation) noexcept {
const bool cache_updated =
observation.event == decltype(observation.event)::cache_updated;
renderable_->observe_state(
cache_updated ? Renderable_Observer_Event::Cache_Updated
: Renderable_Observer_Event::Published,
observation.time_ns,
observation.cache_update_count,
observation.publish_count
);
if (cache_updated)
renderable_->changed();
}
private:
Renderable* renderable_;
};
} // namespace detail
} // namespace renderive