延迟低了很多
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
#include "event.hpp"
|
||||
#include <stdexcept>
|
||||
|
||||
namespace aethera {
|
||||
Event_Statistics_Accumulator::Event_Statistics_Accumulator(
|
||||
std::size_t capacity) {
|
||||
if (capacity == 0)
|
||||
throw std::invalid_argument(
|
||||
"event statistics capacity must be greater than zero");
|
||||
for (auto& event : values_)
|
||||
for (auto& statistic : event)
|
||||
statistic = Sliding_Statistics{capacity};
|
||||
}
|
||||
|
||||
void Event_Statistics_Accumulator::submit(
|
||||
Event_Type type, std::uint64_t created_steady_ns,
|
||||
std::uint64_t started_steady_ns,
|
||||
std::uint64_t completed_steady_ns) {
|
||||
const auto type_index = static_cast<std::size_t>(type);
|
||||
if (type_index >= event_type_count || created_steady_ns == 0 ||
|
||||
started_steady_ns < created_steady_ns ||
|
||||
completed_steady_ns < started_steady_ns)
|
||||
return;
|
||||
const std::array samples{
|
||||
static_cast<double>(started_steady_ns - created_steady_ns) / 1'000'000.0,
|
||||
static_cast<double>(completed_steady_ns - started_steady_ns) / 1'000'000.0,
|
||||
static_cast<double>(completed_steady_ns - created_steady_ns) / 1'000'000.0};
|
||||
for (std::size_t index = 0; index < samples.size(); ++index)
|
||||
state_.values[type_index][index] =
|
||||
values_[type_index][index].submit(samples[index]);
|
||||
}
|
||||
|
||||
const Event_Statistics_State& Event_Statistics_Accumulator::state() const noexcept {
|
||||
return state_;
|
||||
}
|
||||
|
||||
void Event_Statistics_Accumulator::reset() noexcept {
|
||||
for (auto& event : values_)
|
||||
for (auto& statistic : event)
|
||||
statistic.reset();
|
||||
state_ = {};
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
#pragma once
|
||||
#include "frame_statistics.hpp"
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <concepts>
|
||||
#include <cstdint>
|
||||
@@ -16,10 +18,39 @@ enum class Event_Type : std::uint8_t {
|
||||
key_press,
|
||||
key_release
|
||||
};
|
||||
inline constexpr std::size_t event_type_count =
|
||||
static_cast<std::size_t>(Event_Type::key_release) + 1;
|
||||
enum class Event_Statistic : std::uint8_t {
|
||||
queue_wait_ms,
|
||||
dispatch_ms,
|
||||
total_ms,
|
||||
count
|
||||
};
|
||||
inline constexpr std::size_t event_statistic_count =
|
||||
static_cast<std::size_t>(Event_Statistic::count);
|
||||
struct Event_Statistics_State {
|
||||
std::array<std::array<Statistic_State, event_statistic_count>,
|
||||
event_type_count> values{}; /* 按事件业务类型发布的定长延迟统计结果。 */
|
||||
bool operator==(const Event_Statistics_State&) const = default;
|
||||
};
|
||||
class Event_Statistics_Accumulator final {
|
||||
public:
|
||||
explicit Event_Statistics_Accumulator(std::size_t capacity = 600);
|
||||
void submit(Event_Type type, std::uint64_t created_steady_ns,
|
||||
std::uint64_t started_steady_ns,
|
||||
std::uint64_t completed_steady_ns);
|
||||
[[nodiscard]] const Event_Statistics_State& state() const noexcept;
|
||||
void reset() noexcept;
|
||||
private:
|
||||
std::array<std::array<Sliding_Statistics, event_statistic_count>,
|
||||
event_type_count> values_; /* Scene 单帧准入域内增量维护的统计器。 */
|
||||
Event_Statistics_State state_{}; /* 下一次 Scene State 交换时发布的结果。 */
|
||||
};
|
||||
/* 所有输入事件的公共业务基类。 */
|
||||
struct Event {
|
||||
struct Dispatch_Timing {
|
||||
std::uint64_t frame_sequence{};
|
||||
std::uint64_t created_steady_ns{};
|
||||
std::uint64_t started_steady_ns{};
|
||||
std::uint64_t completed_steady_ns{};
|
||||
};
|
||||
@@ -32,6 +63,10 @@ struct Event {
|
||||
[[nodiscard]] Dispatch_Timing dispatch_timing() const noexcept;
|
||||
Event_Type type; /* 事件种类;构造后保持不变。 */
|
||||
private:
|
||||
friend struct Scene;
|
||||
void observe_with(Event_Statistics_Accumulator* accumulator) noexcept;
|
||||
std::uint64_t created_steady_ns_{}; /* 事件对象进入 Scene 前的内核单调时刻。 */
|
||||
Event_Statistics_Accumulator* statistics_{}; /* 所属 Scene 的统计器;不拥有且不得跨 Scene。 */
|
||||
mutable bool accepted{}; /* 处理链是否已经消费事件。 */
|
||||
mutable std::atomic_uint64_t dispatch_frame_sequence_{};
|
||||
mutable std::atomic_uint64_t dispatch_started_steady_ns_{};
|
||||
|
||||
@@ -7,7 +7,8 @@ inline std::uint64_t event_steady_time_ns() noexcept {
|
||||
std::chrono::steady_clock::now().time_since_epoch()).count());
|
||||
}
|
||||
}
|
||||
inline Event::Event(Event_Type value) : type(value) {}
|
||||
inline Event::Event(Event_Type value)
|
||||
: type(value), created_steady_ns_(detail::event_steady_time_ns()) {}
|
||||
inline Event::~Event() = default;
|
||||
inline void Event::accept() const noexcept { accepted = true; }
|
||||
inline bool Event::is_accepted() const noexcept { return accepted; }
|
||||
@@ -17,13 +18,24 @@ inline void Event::mark_dispatch_started(std::uint64_t frame_sequence) const noe
|
||||
dispatch_started_steady_ns_.store(detail::event_steady_time_ns(), std::memory_order_release);
|
||||
}
|
||||
inline void Event::mark_dispatch_completed() const noexcept {
|
||||
dispatch_completed_steady_ns_.store(detail::event_steady_time_ns(), std::memory_order_release);
|
||||
const auto completed = detail::event_steady_time_ns();
|
||||
dispatch_completed_steady_ns_.store(completed, std::memory_order_release);
|
||||
if (statistics_)
|
||||
statistics_->submit(
|
||||
type, created_steady_ns_,
|
||||
dispatch_started_steady_ns_.load(std::memory_order_acquire),
|
||||
completed);
|
||||
}
|
||||
inline Event::Dispatch_Timing Event::dispatch_timing() const noexcept {
|
||||
return {dispatch_frame_sequence_.load(std::memory_order_relaxed),
|
||||
created_steady_ns_,
|
||||
dispatch_started_steady_ns_.load(std::memory_order_acquire),
|
||||
dispatch_completed_steady_ns_.load(std::memory_order_acquire)};
|
||||
}
|
||||
inline void Event::observe_with(
|
||||
Event_Statistics_Accumulator* accumulator) noexcept {
|
||||
statistics_ = accumulator;
|
||||
}
|
||||
constexpr Keyboard_Modifier operator|(Keyboard_Modifier left, Keyboard_Modifier right) noexcept { return static_cast<Keyboard_Modifier>(static_cast<std::uint8_t>(left) | static_cast<std::uint8_t>(right)); }
|
||||
template <Event_Point Point> Basic_Pointer_Event<Point>::Basic_Pointer_Event(Event_Type value) : Event(value) {}
|
||||
template <Event_Point Point> double Basic_Pointer_Event<Point>::position_x() const noexcept { return static_cast<double>(position.x); }
|
||||
|
||||
@@ -22,6 +22,7 @@ struct Scene : Def<Scene, Root,
|
||||
struct Prop : Prev_Prop {};
|
||||
/* Scene 每次 process(...) 后发布的总图结构与执行统计。 */
|
||||
struct State : Prev_State {
|
||||
Event_Statistics_State event_statistics{}; /* 输入进入 Scene 到 Renderable 消费完成的分类统计。 */
|
||||
bool taskflow_rebuilt{}; /* 本次 process(...) 前的 advance 是否重新构建了总 Taskflow。 */
|
||||
std::size_t renderable_count{}; /* Prepare 数据依赖图中的 Renderable 数量。 */
|
||||
std::size_t taskflow_task_count{}; /* 当前 Prepare Taskflow 中的任务节点数量。 */
|
||||
|
||||
@@ -10,10 +10,11 @@ struct Scene::Private : Prev_Private {
|
||||
struct Result {}; /* process(...) 完成回调的结果类型;当前仅表示完成。 */
|
||||
struct Runtime; /* Scene 的 Taskflow 构建产物;完整定义位于本文件下方。 */
|
||||
std::unique_ptr<Runtime> runtime; /* Scene 唯一运行时构建产物的所有权。 */
|
||||
Event_Statistics_Accumulator event_statistics{}; /* Scene 单帧域内按事件类型增量计算。 */
|
||||
Private();
|
||||
~Private();
|
||||
template <Attached Object>
|
||||
[[nodiscard]] Event_Batch take_events(Object* object, std::uint64_t frame_sequence);
|
||||
[[nodiscard]] Event_Batch take_events(Object* object);
|
||||
template <Attached Object> void bind_private_crtp(Object* object);
|
||||
/* Def CRTP hook:所有缓冲推进后重建必要的总 Taskflow,并更新 Scene_State_Tag 状态层。 */
|
||||
template <Attached Object>
|
||||
@@ -39,23 +40,22 @@ void Scene::Private::bind_private_crtp(Object* object) {
|
||||
runtime = std::make_unique<Runtime>();
|
||||
}
|
||||
template <Attached Object>
|
||||
Scene::Event_Batch Scene::Private::take_events(Object* object, std::uint64_t frame_sequence) {
|
||||
Scene::Event_Batch Scene::Private::take_events(Object* object) {
|
||||
object->template exchange_stream<Scene_Event_Stream_Tag>();
|
||||
return object->template access_rendering_stream<Scene_Event_Stream_Tag>(
|
||||
[&](std::span<Event_Pointer> events) {
|
||||
Event_Batch result{object->memory_resource()};
|
||||
result.reserve(events.size());
|
||||
for (const auto& event : events) {
|
||||
event->mark_dispatch_started(frame_sequence);
|
||||
result.push_back(event);
|
||||
}
|
||||
result.insert(result.end(), events.begin(), events.end());
|
||||
return result;
|
||||
});
|
||||
}
|
||||
template <Event_Object Event_Object_Type, typename... Arguments>
|
||||
std::shared_ptr<Event_Object_Type> Scene::make_event(Arguments&&... arguments) {
|
||||
return std::allocate_shared<Event_Object_Type>(
|
||||
auto event = std::allocate_shared<Event_Object_Type>(
|
||||
allocator<Event_Object_Type>(), std::forward<Arguments>(arguments)...);
|
||||
event->observe_with(&static_cast<Private&>(*d).event_statistics);
|
||||
return event;
|
||||
}
|
||||
template <Attached Object, typename Callback>
|
||||
void Scene::Private::process(Object* object, Callback&& callback) requires std::invocable<Callback, const Result&> {
|
||||
@@ -69,6 +69,7 @@ void Scene::Private::process(Object* object, Render_Frame* frame, Callback&& cal
|
||||
if (frame) frame->mark(Frame_Trace_Marker::prepare_started);
|
||||
if (runtime->taskflow && !runtime->taskflow->empty()) state.taskflow_execution_time_ns = detail::run_taskflow(*runtime->taskflow);
|
||||
if (frame) frame->mark(Frame_Trace_Marker::prepare_finished);
|
||||
state.event_statistics = event_statistics.state();
|
||||
private_data.state.advance();
|
||||
object->template notify_state<Scene::Base_Tag>();
|
||||
Result result;
|
||||
|
||||
Reference in New Issue
Block a user