This commit is contained in:
2026-08-16 21:18:28 +08:00
parent 9d544c7ba9
commit 3153f7d64f
15 changed files with 387 additions and 200 deletions
@@ -91,10 +91,11 @@ struct Type_Descriptor<renderive::web::Gallery_Session_Control<Scene_Type>> {
[dirty](T& value, bool enabled) {
if (enabled) {
if (value.scene_.max_render_fps() <= 0.0 &&
value.scene_.set_max_render_fps(30.0) != renderive::Plot_Control_Error::none)
!value.scene_.set_max_render_fps(30.0))
return;
} else {
value.scene_.clear_max_render_fps();
if (!value.scene_.clear_max_render_fps())
return;
}
dirty(value);
}),
@@ -106,7 +107,7 @@ struct Type_Descriptor<renderive::web::Gallery_Session_Control<Scene_Type>> {
},
[dirty](T& value, double fps) {
if (value.scene_.max_render_fps() > 0.0 &&
value.scene_.set_max_render_fps(fps) != renderive::Plot_Control_Error::none)
!value.scene_.set_max_render_fps(fps))
return;
dirty(value);
}),
+8 -3
View File
@@ -1,11 +1,13 @@
#include "Web_Plot_Session.h"
#include "Pixel_Frame.h"
#include "render_2D/export.h"
#include <renderive/error/Error_Policy.hpp>
#include <algorithm>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <mutex>
#include <stdexcept>
#include <type_traits>
#include <utility>
#include <vector>
@@ -64,7 +66,9 @@ struct Web_Plot_Session::Impl {
Impl() {
plot.init();
plot.set_background_color({3, 7, 18, 255});
static_cast<void>(plot.set_max_render_fps(30.0));
if (!plot.set_max_render_fps(30.0))
::renderive::error::unexpected<std::logic_error>(
"validated web plot frame rate was rejected");
plot.set_viewport_size({960, 600});
const auto root = plot.root_renderable();
constexpr Color axis_color{93, 116, 151, 255};
@@ -160,7 +164,7 @@ struct Web_Plot_Session::Impl {
plot.activate_view();
update_model();
const auto initial_render = plot.render_frame(true);
if (initial_render != Plot_Render_Result::none)
if (!initial_render || *initial_render != Plot_Render_Status::rendered)
plot.request_redraw();
}
~Impl() {
@@ -268,7 +272,8 @@ struct Web_Plot_Session::Impl {
if (!plot.view_active())
return std::nullopt;
update_model();
if (plot.render_frame(true) != Plot_Render_Result::none)
const auto render = plot.render_frame(true);
if (!render || *render != Plot_Render_Status::rendered)
return std::nullopt;
std::string pixels;
const Color background = plot.background_color();
+42 -25
View File
@@ -29,23 +29,36 @@
#include <vector>
namespace renderive::web {
namespace {
Gallery_Render_Result gallery_render_error(Plot_Render_Result error) {
switch (error) {
case Plot_Render_Result::none:
return Gallery_Render_Result::none;
case Plot_Render_Result::view_inactive:
return Gallery_Render_Result::inactive;
case Plot_Render_Result::cancelled:
Gallery_Render_Result gallery_render_result(
const tl::expected<Plot_Render_Status, Plot_Render_Frame_Error>& result) {
if (result) {
switch (*result) {
case Plot_Render_Status::rendered:
return Gallery_Render_Result::none;
case Plot_Render_Status::view_inactive:
return Gallery_Render_Result::inactive;
case Plot_Render_Status::empty_viewport:
case Plot_Render_Status::model_unchanged:
return Gallery_Render_Result::frame_unavailable;
}
::renderive::error::unexpected<std::logic_error>("unknown plot render status");
}
switch (result.error()) {
case Plot_Render_Frame_Error::cancelled:
return Gallery_Render_Result::cancelled;
case Plot_Render_Result::deadline_exceeded:
case Plot_Render_Frame_Error::deadline_exceeded:
return Gallery_Render_Result::deadline_exceeded;
case Plot_Render_Result::external_failure:
case Plot_Render_Frame_Error::external_failure:
return Gallery_Render_Result::backend_failure;
case Plot_Render_Result::scene_shutting_down:
case Plot_Render_Frame_Error::scene_shutting_down:
return Gallery_Render_Result::shutting_down;
default:
case Plot_Render_Frame_Error::painter_unavailable:
case Plot_Render_Frame_Error::manual_refresh_not_supported:
case Plot_Render_Frame_Error::no_pending_frame:
case Plot_Render_Frame_Error::renderer_unavailable:
return Gallery_Render_Result::frame_unavailable;
}
::renderive::error::unexpected<std::logic_error>("unknown plot render error");
}
template <class Update>
void update_axis_state(const renderive_Owner<Abs_Axis>& axis, Update&& update) {
@@ -209,11 +222,14 @@ public:
plot_, *primary_, feedback_policy_);
register_controls();
set_performance_plot_name(plot_, case_id_ + "/" + gallery_enum_id(frame_mode_));
if (frame_mode_ == Gallery_Frame_Mode::Low_Latency)
static_cast<void>(plot_.set_max_render_fps(30.0));
if (frame_mode_ == Gallery_Frame_Mode::Low_Latency &&
!plot_.set_max_render_fps(30.0))
::renderive::error::unexpected<std::logic_error>(
"validated gallery frame rate was rejected");
plot_.activate_view();
update_model();
if (plot_.render_frame(true) != Plot_Render_Result::none)
const auto initial_render = plot_.render_frame(true);
if (!initial_render || *initial_render != Plot_Render_Status::rendered)
plot_.request_redraw();
}
~Gallery_Scene() {
@@ -354,12 +370,12 @@ public:
return Gallery_Render_Result::inactive;
update_model();
const auto started = std::chrono::steady_clock::now();
const auto error = plot_.render_frame(true);
const bool rendered = error == Plot_Render_Result::none;
const auto result = plot_.render_frame(true);
const bool rendered = result && *result == Plot_Render_Status::rendered;
record_performance(started, rendered);
if (rendered)
rendered_since_last_pixel_ = true;
return gallery_render_error(error);
return gallery_render_result(result);
}
[[nodiscard]] std::optional<std::string> encode_latest_pixels() {
if (!plot_.view_active())
@@ -420,7 +436,7 @@ public:
}
if (request.id == "mode_prepare" || request.id == "mode_enqueue") {
update_model();
const bool prepared = plot_.prepare_frame() == Plot_Render_Result::none;
const bool prepared = plot_.prepare_frame().has_value();
last_action_result_ = prepared ? "frame prepared" : "prepare rejected";
return prepared ? "Kernel 帧已准备/入队" : "Kernel 拒绝准备帧";
}
@@ -432,19 +448,19 @@ public:
int prepared{};
for (int index = 0; index < count; ++index) {
update_model();
prepared += plot_.prepare_frame() == Plot_Render_Result::none ? 1 : 0;
prepared += plot_.prepare_frame().has_value() ? 1 : 0;
}
last_action_result_ = "enqueued=" + std::to_string(prepared);
return "回放帧已批量压入 Flow 队列";
}
if (request.id == "mode_refresh") {
const bool refreshed = plot_.refresh_manual_frame() == Plot_Render_Result::none;
const bool refreshed = plot_.refresh_manual_frame().has_value();
last_action_result_ = refreshed ? "manual refresh succeeded" : "manual refresh failed";
return refreshed ? "Manual 待处理帧已提交刷新" : "当前没有可刷新的 Manual 帧";
}
if (request.id == "mode_render" || request.id == "mode_dequeue") {
const auto started = std::chrono::steady_clock::now();
const bool rendered = plot_.render_prepared_frame() == Plot_Render_Result::none;
const bool rendered = plot_.render_prepared_frame().has_value();
record_performance(started, rendered);
rendered_since_last_pixel_ = rendered;
last_action_result_ = rendered ? "prepared frame rendered" : "no prepared frame";
@@ -458,7 +474,8 @@ public:
if (request.id == "mode_cycle") {
update_model();
const auto started = std::chrono::steady_clock::now();
const bool rendered = plot_.render_frame(true) == Plot_Render_Result::none;
const auto result = plot_.render_frame(true);
const bool rendered = result && *result == Plot_Render_Status::rendered;
record_performance(started, rendered);
rendered_since_last_pixel_ = rendered;
last_action_result_ = rendered ? "full frame cycle rendered" : "frame cycle skipped";
@@ -916,7 +933,7 @@ private:
consumer_manual_interval_ns_ = frequency_to_ns(feedback_policy_.manual_fps);
consumer_feedback_source_ = "none";
if (!feedback_policy_.enabled) {
if (plot_.clear_consumer_feedback() != Plot_Control_Error::none)
if (!plot_.clear_consumer_feedback())
::renderive::error::unexpected<std::logic_error>("low-latency feedback clearing failed");
consumer_feedback_source_ = "disabled";
return;
@@ -944,11 +961,11 @@ private:
select_source(feedback_policy_.manual,
consumer_manual_interval_ns_, "manual");
if (interval_ns == 0) {
if (plot_.clear_consumer_feedback() != Plot_Control_Error::none)
if (!plot_.clear_consumer_feedback())
::renderive::error::unexpected<std::logic_error>("low-latency feedback clearing failed");
return;
}
if (plot_.set_consumer_feedback({interval_ns}) != Plot_Control_Error::none)
if (!plot_.set_consumer_feedback({interval_ns}))
::renderive::error::unexpected<std::logic_error>("validated low-latency feedback was rejected");
}
void record_performance(std::chrono::steady_clock::time_point started, bool rendered) {