架构微调

This commit is contained in:
2026-08-11 09:24:12 +08:00
parent 14a6e97b64
commit 462baeca76
14 changed files with 179 additions and 110 deletions
+48 -46
View File
@@ -26,9 +26,6 @@ namespace {
struct Frame_Observer_Data {
mutable std::mutex mutex;
std::uint32_t last_event{};
std::uint32_t limit_state{};
bool has_limit_state{};
double frequency_hz{};
std::uint64_t observation_count{};
std::uint64_t produced_frame_count{};
std::uint64_t consumed_frame_count{};
@@ -38,9 +35,6 @@ struct Frame_Observer_Data {
std::uint64_t latest_sequence{};
std::uint64_t paint_duration_ns{};
std::uint64_t render_duration_ns{};
std::uint64_t target_interval_ns{};
std::uint64_t bottleneck_duration_ns{};
std::uint64_t next_refresh_interval_ns{};
std::uint64_t paint_lease_wait_ns{};
std::uint64_t paint_state_wait_ns{};
std::uint64_t publish_state_wait_ns{};
@@ -50,7 +44,6 @@ struct Frame_Observer_Data {
std::uint64_t render_state_wait_ns{};
std::uint64_t render_finish_state_wait_ns{};
std::uint64_t queue_wait_ns{};
std::uint64_t end_to_end_ns{};
};
struct Frame_Observer {
@@ -95,15 +88,6 @@ struct Frame_Observer {
data->failed_operation_count = observation.state.failed_refresh_count;
data->pending_frame_count = observation.state.pending_frame ? 1U : 0U;
} else if constexpr (requires { observation.state.limit_state; }) {
data->has_limit_state = true;
data->limit_state = static_cast<std::uint32_t>(observation.state.limit_state);
data->frequency_hz = observation.state.frequency_hz;
data->target_interval_ns = observation.state.target_interval_ns;
data->paint_duration_ns = observation.state.paint_duration_ns;
data->render_duration_ns = observation.state.render_duration_ns;
data->bottleneck_duration_ns = observation.state.bottleneck_duration_ns;
data->next_refresh_interval_ns = observation.state.next_refresh_interval_ns;
data->end_to_end_ns = observation.state.end_to_end_ns;
data->produced_frame_count = observation.statistics.counters.published_frame_count;
data->consumed_frame_count = observation.state.completed_lifecycle_count;
data->dropped_frame_count =
@@ -181,7 +165,8 @@ std::string observer_event_name(Frame_Control_Mode mode, std::uint32_t event) {
std::string limit_state_name(bool available, std::uint32_t state) {
if (!available)
return "not_applicable";
static constexpr const char* names[]{"frequency_limited", "paint_limited", "render_limited"};
static constexpr const char* names[]{"frequency_limited", "paint_limited", "render_limited",
"consumer_limited"};
return state < std::size(names) ? names[state] : "unknown";
}
@@ -475,6 +460,12 @@ void Plot_Core::set_max_render_fps(double fps) {
notify_model_dirty();
}
void Plot_Core::set_consumer_feedback(Frame_Consumer_Feedback feedback) {
if (impl_->mode != Frame_Control_Mode::Low_Latency)
throw std::logic_error("consumer feedback is only available in low-latency mode");
std::get<std::unique_ptr<Low_Latency_Plot_Scene>>(impl_->scene)->frame_control.set_consumer_feedback(feedback);
}
double Plot_Core::max_render_fps() const noexcept {
if (impl_->mode != Frame_Control_Mode::Low_Latency)
return std::numeric_limits<double>::quiet_NaN();
@@ -502,35 +493,46 @@ Frame_Control_Mode Plot_Core::frame_control_mode() const noexcept {
}
Frame_Observer_Snapshot Plot_Core::frame_observer_snapshot() const {
std::lock_guard lock(impl_->observer->mutex);
return {impl_->mode,
impl_->observer->observation_count == 0
? std::string("none")
: observer_event_name(impl_->mode, impl_->observer->last_event),
limit_state_name(impl_->observer->has_limit_state, impl_->observer->limit_state),
impl_->observer->frequency_hz,
impl_->observer->observation_count,
impl_->observer->produced_frame_count,
impl_->observer->consumed_frame_count,
impl_->observer->dropped_frame_count,
impl_->observer->failed_operation_count,
impl_->observer->pending_frame_count,
impl_->observer->latest_sequence,
impl_->observer->paint_duration_ns,
impl_->observer->render_duration_ns,
impl_->observer->target_interval_ns,
impl_->observer->bottleneck_duration_ns,
impl_->observer->next_refresh_interval_ns,
impl_->observer->paint_lease_wait_ns,
impl_->observer->paint_state_wait_ns,
impl_->observer->publish_state_wait_ns,
impl_->observer->ready_wait_ns,
impl_->observer->frame_age_at_render_ns,
impl_->observer->render_lease_wait_ns,
impl_->observer->render_state_wait_ns,
impl_->observer->render_finish_state_wait_ns,
impl_->observer->queue_wait_ns,
impl_->observer->end_to_end_ns};
Frame_Observer_Snapshot snapshot;
{
std::lock_guard lock(impl_->observer->mutex);
snapshot.mode = impl_->mode;
snapshot.last_event = impl_->observer->observation_count == 0 ?
std::string("none") :
observer_event_name(impl_->mode, impl_->observer->last_event);
snapshot.limit_state = "not_applicable";
snapshot.observation_count = impl_->observer->observation_count;
snapshot.produced_frame_count = impl_->observer->produced_frame_count;
snapshot.consumed_frame_count = impl_->observer->consumed_frame_count;
snapshot.dropped_frame_count = impl_->observer->dropped_frame_count;
snapshot.failed_operation_count = impl_->observer->failed_operation_count;
snapshot.pending_frame_count = impl_->observer->pending_frame_count;
snapshot.latest_sequence = impl_->observer->latest_sequence;
snapshot.paint_duration_ns = impl_->observer->paint_duration_ns;
snapshot.render_duration_ns = impl_->observer->render_duration_ns;
snapshot.paint_lease_wait_ns = impl_->observer->paint_lease_wait_ns;
snapshot.paint_state_wait_ns = impl_->observer->paint_state_wait_ns;
snapshot.publish_state_wait_ns = impl_->observer->publish_state_wait_ns;
snapshot.ready_wait_ns = impl_->observer->ready_wait_ns;
snapshot.frame_age_at_render_ns = impl_->observer->frame_age_at_render_ns;
snapshot.render_lease_wait_ns = impl_->observer->render_lease_wait_ns;
snapshot.render_state_wait_ns = impl_->observer->render_state_wait_ns;
snapshot.render_finish_state_wait_ns = impl_->observer->render_finish_state_wait_ns;
snapshot.queue_wait_ns = impl_->observer->queue_wait_ns;
}
if (impl_->mode == Frame_Control_Mode::Low_Latency) {
const auto state = std::get<std::unique_ptr<Low_Latency_Plot_Scene>>(impl_->scene)->frame_control.state();
snapshot.limit_state = limit_state_name(true, static_cast<std::uint32_t>(state.limit_state));
snapshot.frequency_hz = state.frequency_hz;
snapshot.paint_duration_ns = state.paint_duration_ns;
snapshot.render_duration_ns = state.render_duration_ns;
snapshot.target_interval_ns = state.target_interval_ns;
snapshot.bottleneck_duration_ns = state.bottleneck_duration_ns;
snapshot.consumer_interval_ns = state.consumer_interval_ns;
snapshot.next_refresh_interval_ns = state.next_refresh_interval_ns;
snapshot.end_to_end_ns = state.end_to_end_ns;
}
return snapshot;
}
void Plot_Core::set_presentation_sink(std::weak_ptr<Presentation_Sink> sink) {
+3
View File
@@ -2,6 +2,7 @@
#include "../base/Types.h"
#include "../event/Event.h"
#include <renderive/frame_control/Frame_Consumer_Feedback.hpp>
#include <atomic>
#include <concepts>
@@ -50,6 +51,7 @@ struct Frame_Observer_Snapshot {
std::uint64_t render_duration_ns{};
std::uint64_t target_interval_ns{};
std::uint64_t bottleneck_duration_ns{};
std::uint64_t consumer_interval_ns{};
std::uint64_t next_refresh_interval_ns{};
std::uint64_t paint_lease_wait_ns{};
std::uint64_t paint_state_wait_ns{};
@@ -112,6 +114,7 @@ public:
[[nodiscard]] bool view_active() const noexcept;
void set_max_render_fps(double fps);
void set_consumer_feedback(Frame_Consumer_Feedback feedback);
[[nodiscard]] double max_render_fps() const noexcept;
[[nodiscard]] Low_Latency_Diagnostics diagnostics() const;
[[nodiscard]] Refresh_Control_Snapshot refresh_feedback_snapshot() const;
@@ -80,6 +80,22 @@ TEST(Renderive_Core2_Frame_Pipeline, HighFrequencyLowLatencyLifecycleExposesKern
EXPECT_EQ(refresh.next_refresh_interval_ns, snapshot.next_refresh_interval_ns);
}
TEST(Renderive_Core2_Frame_Pipeline, LowLatencyConsumerFeedbackFlowsThroughCore2IntoKernelScheduling) {
Plot_Core plot(Frame_Control_Mode::Low_Latency);
plot.init();
plot.set_viewport_size({96, 54});
plot.set_max_render_fps(100.0);
plot.set_consumer_feedback({40'000'000});
ASSERT_TRUE(plot.prepare_frame());
ASSERT_TRUE(plot.render_prepared_frame());
const auto snapshot = plot.frame_observer_snapshot();
EXPECT_EQ(snapshot.limit_state, "consumer_limited");
EXPECT_EQ(snapshot.target_interval_ns, 10'000'000u);
EXPECT_EQ(snapshot.consumer_interval_ns, 40'000'000u);
EXPECT_EQ(snapshot.next_refresh_interval_ns, 40'000'000u);
EXPECT_EQ(plot.refresh_feedback_snapshot().next_refresh_interval_ns, 40'000'000u);
}
TEST(Renderive_Core2_Frame_Pipeline, LowLatencyReplacementRetiresOldFrameWithoutPhantomPendingFrame) {
Plot_Core plot(Frame_Control_Mode::Low_Latency);
plot.init();