仍然闪烁

This commit is contained in:
2026-08-02 18:58:35 +08:00
parent ffaca5b05f
commit 9a39f88427
54 changed files with 2257 additions and 2424 deletions
+6
View File
@@ -16,8 +16,13 @@ struct Frame_Lifecycle_Observer {
struct Refresh_Control_Snapshot {
Refresh_Limit_Source source = Refresh_Limit_Source::Unknown;
Refresh_Limit_Source candidate_source = Refresh_Limit_Source::Unknown;
Low_Latency_Bottleneck_State bottleneck = Low_Latency_Bottleneck_State::Unknown;
Low_Latency_Bottleneck_State stable_bottleneck = Low_Latency_Bottleneck_State::Unknown;
Low_Latency_Bottleneck_State candidate_bottleneck = Low_Latency_Bottleneck_State::Unknown;
Low_Latency_Production_Strategy production_strategy = Low_Latency_Production_Strategy::Latency_Eager;
std::uint64_t candidate_age_ns{};
std::uint64_t candidate_samples{};
std::uint64_t input_period_ns{};
std::uint64_t input_jitter_ns{};
std::uint64_t render_period_ns{};
@@ -34,6 +39,7 @@ struct Refresh_Control_Snapshot {
std::uint64_t frame_age_jitter_ns{};
std::uint64_t user_period_ns{};
std::uint64_t target_period_ns{};
std::uint64_t effective_min_render_interval_ns{};
std::uint64_t presented_frame_count{};
std::uint64_t superseded_frame_count{};
std::uint64_t repeated_frame_count{};
+1 -4
View File
@@ -3,10 +3,6 @@
#include <cstdint>
namespace renderive {
using Plot_Execution_Id = std::uint64_t;
enum class Renderable_Runtime_Strategy : std::uint8_t {
Low_Latency,
Explicit
};
enum class Dirty_Reason : std::uint8_t {
Core_Data,
Config,
@@ -58,6 +54,7 @@ struct Frame_Worker_Stats {
};
enum class Refresh_Limit_Source : std::uint8_t {
Unknown,
Input,
Render,
Paint,
User
+108 -41
View File
@@ -12,6 +12,7 @@
#include "global.h"
#include <concepts>
#include <cstdint>
#include <functional>
#include <memory>
#include <memory_resource>
#include <type_traits>
@@ -21,7 +22,8 @@ namespace renderive {
class Canvas;
struct Render_Frame_Snapshot;
struct Renderable;
class Renderable;
class Renderable_Runtime;
struct Input_Data {
virtual ~Input_Data() = default;
@@ -148,17 +150,25 @@ struct Render_State_Read_Handle {
virtual ~Render_State_Read_Handle() = default;
};
struct Render_State_Edit_Handle {
virtual ~Render_State_Edit_Handle() = default;
struct Render_State_Write_Handle {
virtual ~Render_State_Write_Handle() = default;
};
struct Render_Input_Edit_Handle {
virtual ~Render_Input_Edit_Handle() = default;
struct Render_Input_Write_Handle {
virtual ~Render_Input_Write_Handle() = default;
virtual void set_completion(std::shared_ptr<Update_State> state) {
(void)state;
}
};
struct Render_Input_Frame_Handle {
virtual ~Render_Input_Frame_Handle() = default;
virtual void consume_input(Input_Data* input) {
if (input)
input->clear();
}
};
struct Render_State_Read_Guard : Move_Only {
Render_State_Read_Guard() = default;
Render_State_Read_Guard(Render_State* state, std::unique_ptr<Render_State_Read_Handle> handle)
@@ -175,36 +185,36 @@ struct Render_State_Read_Guard : Move_Only {
std::unique_ptr<Render_State_Read_Handle> handle;
};
struct Render_State_Edit_Guard : Move_Only {
Render_State_Edit_Guard() = default;
Render_State_Edit_Guard(Render_State* state, std::unique_ptr<Render_State_Edit_Handle> handle)
struct Render_State_Write_Guard : Move_Only {
Render_State_Write_Guard() = default;
Render_State_Write_Guard(Render_State* state, std::unique_ptr<Render_State_Write_Handle> handle)
: state(state), handle(std::move(handle)) {}
Render_State_Edit_Guard(Render_State_Edit_Guard&&) noexcept = default;
Render_State_Edit_Guard& operator=(Render_State_Edit_Guard&&) noexcept = default;
~Render_State_Edit_Guard() = default;
Render_State_Write_Guard(Render_State_Write_Guard&&) noexcept = default;
Render_State_Write_Guard& operator=(Render_State_Write_Guard&&) noexcept = default;
~Render_State_Write_Guard() = default;
explicit operator bool() const noexcept {
return state && handle;
}
Render_State* state{};
std::unique_ptr<Render_State_Edit_Handle> handle;
std::unique_ptr<Render_State_Write_Handle> handle;
};
struct Render_Input_Edit_Guard : Move_Only {
Render_Input_Edit_Guard() = default;
Render_Input_Edit_Guard(Input_Data* input, std::unique_ptr<Render_Input_Edit_Handle> handle)
struct Render_Input_Write_Guard : Move_Only {
Render_Input_Write_Guard() = default;
Render_Input_Write_Guard(Input_Data* input, std::unique_ptr<Render_Input_Write_Handle> handle)
: input(input), handle(std::move(handle)) {}
Render_Input_Edit_Guard(Render_Input_Edit_Guard&&) noexcept = default;
Render_Input_Edit_Guard& operator=(Render_Input_Edit_Guard&&) noexcept = default;
~Render_Input_Edit_Guard() = default;
Render_Input_Write_Guard(Render_Input_Write_Guard&&) noexcept = default;
Render_Input_Write_Guard& operator=(Render_Input_Write_Guard&&) noexcept = default;
~Render_Input_Write_Guard() = default;
explicit operator bool() const noexcept {
return input && handle;
}
Input_Data* input{};
std::unique_ptr<Render_Input_Edit_Handle> handle;
std::unique_ptr<Render_Input_Write_Handle> handle;
void set_completion(std::shared_ptr<Update_State> state) {
if (handle)
@@ -212,6 +222,27 @@ struct Render_Input_Edit_Guard : Move_Only {
}
};
struct Render_Input_Frame_Guard : Move_Only {
Render_Input_Frame_Guard() = default;
Render_Input_Frame_Guard(Input_Data* input, std::unique_ptr<Render_Input_Frame_Handle> handle)
: input(input), handle(std::move(handle)) {}
Render_Input_Frame_Guard(Render_Input_Frame_Guard&&) noexcept = default;
Render_Input_Frame_Guard& operator=(Render_Input_Frame_Guard&&) noexcept = default;
~Render_Input_Frame_Guard() = default;
explicit operator bool() const noexcept {
return input && handle;
}
Input_Data* input{};
std::unique_ptr<Render_Input_Frame_Handle> handle;
void consume_input() const {
if (handle)
handle->consume_input(input);
}
};
enum class Renderable_State_Role : std::uint8_t {
Edit,
Ready,
@@ -224,20 +255,62 @@ enum class Renderable_Input_Role : std::uint8_t {
Render
};
struct Render_Data {
Renderable* q_ptr{};
struct Renderable_Frame_View : Move_Only {
Renderable_Frame_View() = default;
Renderable_Frame_View(Render_State_Read_Guard state_guard, Render_Input_Frame_Guard input_guard)
: state(state_guard.state),
input(input_guard.input),
state_guard(std::move(state_guard)),
input_guard(std::move(input_guard)) {}
Renderable_Frame_View(Renderable_Frame_View&&) noexcept = default;
Renderable_Frame_View& operator=(Renderable_Frame_View&&) noexcept = default;
~Renderable_Frame_View() = default;
virtual void initialize_runtime(Renderable& owner, Renderable_Runtime_Strategy strategy) = 0;
[[nodiscard]] virtual Renderable_Runtime_Strategy runtime_strategy() const = 0;
explicit operator bool() const noexcept {
return state && state_guard;
}
Render_State* state{};
Input_Data* input{};
Render_State_Read_Guard state_guard;
Render_Input_Frame_Guard input_guard;
void consume_input() const {
input_guard.consume_input();
}
};
class Renderable_Runtime {
public:
using Copy_Render_State_Function = std::function<void(Render_State&, const Render_State&)>;
virtual ~Renderable_Runtime() = default;
virtual void set_render_state_copier(Copy_Render_State_Function copier) = 0;
virtual void cancel_pending_completions() = 0;
virtual void drain_committed_update_states(std::pmr::vector<std::shared_ptr<Update_State>>& output) = 0;
virtual Render_State_Read_Guard acquire_state_read(Renderable_State_Role role) = 0;
virtual Render_State_Read_Guard acquire_render_state_read() = 0;
virtual Render_State_Read_Guard acquire_edit_state_read() = 0;
virtual Render_State_Read_Guard acquire_prepare_state_read() = 0;
virtual Render_State_Edit_Guard acquire_edit_state() = 0;
virtual Render_Input_Edit_Guard acquire_edit_input(bool notify_render) = 0;
virtual void sync_state_pipeline() = 0;
virtual Render_State_Write_Guard acquire_edit_state() = 0;
virtual Render_Input_Write_Guard acquire_edit_input(bool notify_render) = 0;
virtual Renderable_Frame_View capture_frame_view() = 0;
virtual Render_State* state(Renderable_State_Role role) = 0;
virtual Input_Data* input_data(Renderable_Input_Role role) = 0;
virtual void clear_render_input() = 0;
};
struct Render_Data {
Renderable* q_ptr{};
virtual void initialize_runtime(std::unique_ptr<Renderable_Runtime> runtime) = 0;
virtual void cancel_pending_completions() = 0;
virtual void drain_committed_update_states(std::pmr::vector<std::shared_ptr<Update_State>>& output) = 0;
virtual Render_State_Read_Guard acquire_state_read(Renderable_State_Role role) = 0;
virtual Render_State_Read_Guard acquire_render_state_read() = 0;
virtual Render_State_Read_Guard acquire_edit_state_read() = 0;
virtual Render_State_Write_Guard acquire_edit_state() = 0;
virtual Render_Input_Write_Guard acquire_edit_input(bool notify_render) = 0;
virtual Renderable_Frame_View capture_frame_view() = 0;
virtual Render_State* state(Renderable_State_Role role) = 0;
virtual Render_State* render_state() = 0;
virtual Render_State* ready_state() = 0;
@@ -246,10 +319,8 @@ struct Render_Data {
virtual Input_Data* render_input_data() = 0;
virtual Input_Data* edit_input_data() = 0;
virtual ~Render_Data() = default;
virtual void draw(Canvas& canvas, const Render_Frame_Snapshot& snapshot) {}
virtual void prepare_data(const Render_Frame_Snapshot& snapshot) {
sync_state_pipeline();
}
virtual void draw(Canvas& canvas, const Render_Frame_Snapshot& snapshot, const Renderable_Frame_View& frame_view) {}
virtual void prepare_data(const Render_Frame_Snapshot& snapshot, const Renderable_Frame_View& frame_view) {}
virtual Rect pixel_bounds(const Size& plot_size) {
return {0, 0, plot_size.width, plot_size.height};
}
@@ -260,10 +331,7 @@ protected:
};
struct Base_Render_Data : Render_Data {
void initialize_runtime(Renderable&, Renderable_Runtime_Strategy) override {}
[[nodiscard]] Renderable_Runtime_Strategy runtime_strategy() const override {
return Renderable_Runtime_Strategy::Explicit;
}
void initialize_runtime(std::unique_ptr<Renderable_Runtime>) override {}
void cancel_pending_completions() override {}
void drain_committed_update_states(std::pmr::vector<std::shared_ptr<Update_State>>&) override {}
Render_State_Read_Guard acquire_state_read(Renderable_State_Role) override {
@@ -275,13 +343,10 @@ struct Base_Render_Data : Render_Data {
Render_State_Read_Guard acquire_edit_state_read() override {
return {};
}
Render_State_Read_Guard acquire_prepare_state_read() override {
Render_State_Write_Guard acquire_edit_state() override {
return {};
}
Render_State_Edit_Guard acquire_edit_state() override {
return {};
}
Render_Input_Edit_Guard acquire_edit_input(bool) override {
Render_Input_Write_Guard acquire_edit_input(bool) override {
return {};
}
Render_State* state(Renderable_State_Role) override {
@@ -305,7 +370,9 @@ struct Base_Render_Data : Render_Data {
Input_Data* input_data(Renderable_Input_Role) override {
return nullptr;
}
void sync_state_pipeline() override {}
Renderable_Frame_View capture_frame_view() override {
return {};
}
};
template <typename T>
+8 -2
View File
@@ -26,6 +26,12 @@ struct Typed_Render_Data_Base : Base {
Input* edit_input_data() override {
return reinterpret_cast<Input*>(this->input_data(Renderable_Input_Role::Edit));
}
State* render_state(const Renderable_Frame_View& frame_view) const {
return reinterpret_cast<State*>(frame_view.state);
}
Input* render_input_data(const Renderable_Frame_View& frame_view) const {
return reinterpret_cast<Input*>(frame_view.input);
}
State* state_data(Renderable_State_Role role) {
return reinterpret_cast<State*>(this->state(role));
}
@@ -152,7 +158,7 @@ struct Render_Edit_Lease : Immovable {
return state && guard;
}
Data* data{};
Render_State_Edit_Guard guard;
Render_State_Write_Guard guard;
State* state{};
};
@@ -178,7 +184,7 @@ struct Render_Input_Lease : Immovable {
}
Data* data{};
bool notify_render{};
Render_Input_Edit_Guard guard;
Render_Input_Write_Guard guard;
Input* input{};
};
+29 -21
View File
@@ -126,7 +126,7 @@ void Renderable::init_common(Plot_Core* plot) {
d_ptr = d_owner.get<Render_Data>();
}
d_ptr->q_ptr = this;
d_ptr->initialize_runtime(*this, plot->renderable_runtime_strategy());
d_ptr->initialize_runtime(plot->create_renderable_runtime(*this));
plot->notify_model_dirty(Dirty_Reason::Config);
}
void Renderable::add_child(const std::shared_ptr<Renderable>& child) {
@@ -176,18 +176,20 @@ void Renderable::append_tree_snapshot(
int cache_tree_depth) {
std::size_t index = snapshot.size();
Renderable_Cache_Mode mode = get_cache_mode();
snapshot.push_back(Renderable_Frame_Node{
shared_from_this(),
index + 1,
node_id_,
parent_node_id,
parent_object_name,
render_tree_depth,
object_name_,
cache_parent_node_id,
cache_parent_object_name,
cache_tree_depth
});
Renderable_Frame_Node node;
node.renderable = shared_from_this();
node.subtree_end = index + 1;
node.node_id = node_id_;
node.parent_node_id = parent_node_id;
node.parent_object_name = parent_object_name;
node.render_tree_depth = render_tree_depth;
node.object_name = object_name_;
node.cache_parent_node_id = cache_parent_node_id;
node.cache_parent_object_name = cache_parent_object_name;
node.cache_tree_depth = cache_tree_depth;
if (d_ptr && should_prepare())
node.frame_view = d_ptr->capture_frame_view();
snapshot.push_back(std::move(node));
std::string child_cache_parent = cache_parent_object_name;
std::uint64_t child_cache_parent_id = cache_parent_node_id;
int child_cache_depth = cache_tree_depth;
@@ -376,12 +378,17 @@ void Renderable::render_self(Canvas& canvas, const Render_Frame_Snapshot& snapsh
void Renderable::render_self(Canvas& canvas, const Render_Frame_Snapshot& snapshot, const Renderable_Frame_Node* node) {
if (!d_ptr)
return;
auto guard = d_ptr->acquire_render_state_read();
if (!guard)
Renderable_Frame_View local_frame_view;
const Renderable_Frame_View* frame_view = node ? &node->frame_view : nullptr;
if (!frame_view) {
local_frame_view = d_ptr->capture_frame_view();
frame_view = &local_frame_view;
}
if (!*frame_view)
return;
Renderable_Cache_Mode mode = get_cache_mode();
std::uint64_t begin_time = steady_now_ns();
draw(canvas, snapshot);
draw(canvas, snapshot, *frame_view);
std::uint64_t draw_time = steady_now_ns() - begin_time;
if (snapshot.frame_metadata) {
const std::string& parent_name = node ? node->parent_object_name : render_parent_object_name();
@@ -389,16 +396,17 @@ void Renderable::render_self(Canvas& canvas, const Render_Frame_Snapshot& snapsh
snapshot.frame_metadata->record_renderable_self_draw(node ? node->node_id : node_id_, node ? node->parent_node_id : 0, node ? node->object_name : object_name_, parent_name, depth, mode, draw_time);
}
}
void Renderable::draw(Canvas& canvas, const Render_Frame_Snapshot& snapshot) {
void Renderable::draw(Canvas& canvas, const Render_Frame_Snapshot& snapshot, const Renderable_Frame_View& frame_view) {
if (get_retiring())
return;
d_ptr->draw(canvas, snapshot);
d_ptr->draw(canvas, snapshot, frame_view);
}
void Renderable::prepare_data(const Render_Frame_Snapshot& snapshot) {
void Renderable::prepare_data(const Render_Frame_Snapshot& snapshot, const Renderable_Frame_View& frame_view) {
if (get_retiring())
return;
auto prepare_guard = d_ptr->acquire_prepare_state_read();
d_ptr->prepare_data(snapshot);
if (!frame_view)
return;
d_ptr->prepare_data(snapshot, frame_view);
if (snapshot.frame_update_states)
d_ptr->drain_committed_update_states(*snapshot.frame_update_states);
}
+2 -2
View File
@@ -56,8 +56,8 @@ public:
int cache_tree_depth = 0);
void render(Canvas& canvas, const Render_Frame_Snapshot& snapshot);
void render_tree_snapshot(Canvas& canvas, const Render_Frame_Snapshot& snapshot, const Renderable_Frame_Tree& tree, std::size_t index);
void draw(Canvas& canvas, const Render_Frame_Snapshot& snapshot);
void prepare_data(const Render_Frame_Snapshot& snapshot);
void draw(Canvas& canvas, const Render_Frame_Snapshot& snapshot, const Renderable_Frame_View& frame_view);
void prepare_data(const Render_Frame_Snapshot& snapshot, const Renderable_Frame_View& frame_view);
bool select_test(const PointF& pos);
void plot_event(const Event& event);
void mouse_press_event(const Pointer_Event& event);
@@ -0,0 +1,65 @@
#include "Strategy_Render_Data.h"
#include <utility>
namespace renderive {
Strategy_Render_Data::Strategy_Render_Data() = default;
Strategy_Render_Data::~Strategy_Render_Data() = default;
void Strategy_Render_Data::initialize_runtime(std::unique_ptr<Renderable_Runtime> value) {
runtime = std::move(value);
if (!runtime)
return;
runtime->set_render_state_copier([this](Render_State& target, const Render_State& source) {
copy_render_state_object(target, source);
});
}
void Strategy_Render_Data::cancel_pending_completions() {
if (runtime)
runtime->cancel_pending_completions();
}
void Strategy_Render_Data::drain_committed_update_states(std::pmr::vector<std::shared_ptr<Update_State>>& output) {
if (runtime)
runtime->drain_committed_update_states(output);
}
Render_State_Read_Guard Strategy_Render_Data::acquire_state_read(Renderable_State_Role role) {
return runtime ? runtime->acquire_state_read(role) : Render_State_Read_Guard{};
}
Render_State_Read_Guard Strategy_Render_Data::acquire_render_state_read() {
return runtime ? runtime->acquire_render_state_read() : Render_State_Read_Guard{};
}
Render_State_Read_Guard Strategy_Render_Data::acquire_edit_state_read() {
return runtime ? runtime->acquire_edit_state_read() : Render_State_Read_Guard{};
}
Render_State_Write_Guard Strategy_Render_Data::acquire_edit_state() {
return runtime ? runtime->acquire_edit_state() : Render_State_Write_Guard{};
}
Render_Input_Write_Guard Strategy_Render_Data::acquire_edit_input(bool notify_render) {
return runtime ? runtime->acquire_edit_input(notify_render) : Render_Input_Write_Guard{};
}
Renderable_Frame_View Strategy_Render_Data::capture_frame_view() {
return runtime ? runtime->capture_frame_view() : Renderable_Frame_View{};
}
Render_State* Strategy_Render_Data::state(Renderable_State_Role role) {
return runtime ? runtime->state(role) : nullptr;
}
Input_Data* Strategy_Render_Data::input_data(Renderable_Input_Role role) {
return runtime ? runtime->input_data(role) : nullptr;
}
void Strategy_Render_Data::clear_render_input() {
if (runtime)
runtime->clear_render_input();
}
} // namespace renderive
+5 -9
View File
@@ -9,31 +9,27 @@
namespace renderive {
struct Strategy_Render_Data_Private;
struct LIB_DECL Strategy_Render_Data : Render_Data {
Strategy_Render_Data();
Strategy_Render_Data(const Strategy_Render_Data&) = delete;
Strategy_Render_Data& operator=(const Strategy_Render_Data&) = delete;
~Strategy_Render_Data() override;
void initialize_runtime(Renderable& owner, Renderable_Runtime_Strategy strategy) override;
[[nodiscard]] Renderable_Runtime_Strategy runtime_strategy() const override;
void initialize_runtime(std::unique_ptr<Renderable_Runtime> runtime) override;
void cancel_pending_completions() override;
void drain_committed_update_states(std::pmr::vector<std::shared_ptr<Update_State>>& output) override;
Render_State_Read_Guard acquire_state_read(Renderable_State_Role role) override;
Render_State_Read_Guard acquire_render_state_read() override;
Render_State_Read_Guard acquire_edit_state_read() override;
Render_State_Read_Guard acquire_prepare_state_read() override;
Render_State_Edit_Guard acquire_edit_state() override;
Render_Input_Edit_Guard acquire_edit_input(bool notify_render) override;
void sync_state_pipeline() override;
Render_State_Write_Guard acquire_edit_state() override;
Render_Input_Write_Guard acquire_edit_input(bool notify_render) override;
Renderable_Frame_View capture_frame_view() override;
Render_State* state(Renderable_State_Role role) override;
Input_Data* input_data(Renderable_Input_Role role) override;
void clear_render_input();
private:
std::unique_ptr<Strategy_Render_Data_Private> runtime;
std::unique_ptr<Renderable_Runtime> runtime;
};
} // namespace renderive