diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..ae42f91 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,12 @@ +## 设计约束 + +1. 每个状态只能有一个权威来源,禁止在不同对象中重复保存并手工同步。 +2. 能通过计算、查询或快照得到的数据,不要保存为成员变量。 +3. 禁止增加只做值转发的成员、getter、setter 和兼容中间层。 +4. 公共接口只表达业务语义,不泄漏缓冲区角色、线程状态、Private 类型和内部指针。 +5. 接口必须正交,避免语义重叠、调用顺序依赖和多套相同实现。 +6. 类只保存自身职责需要的状态,不替其他对象保存配置或运行状态。 +7. 不要用大量默认空实现的虚函数,能力应按需拆分和组合。 +8. 不要提前加入空配置、无消费者统计和未完成接口。 +9. 替换实现时直接删除旧实现,不保留兼容转发。 +10. 修改后检查新增成员的写入者、读取者、生命周期,以及是否形成重复状态源。 diff --git a/Demo_Gallery/Afterglow_Plot.h b/Demo_Gallery/Afterglow_Plot.h index 4d35617..b4c9737 100644 --- a/Demo_Gallery/Afterglow_Plot.h +++ b/Demo_Gallery/Afterglow_Plot.h @@ -1,5 +1,5 @@ #pragma once -#include "../Renderive/base/Tool.h" +#include "base/Tool.h" static QWidget* create_afterglow() { class Afterglow_Plot : public renderive::Latency_Eager_Plot { public: diff --git a/Demo_Gallery/Audio_Plot.h b/Demo_Gallery/Audio_Plot.h index 548400f..e7c3dc3 100644 --- a/Demo_Gallery/Audio_Plot.h +++ b/Demo_Gallery/Audio_Plot.h @@ -1,5 +1,5 @@ #pragma once -#include "../Renderive/base/Tool.h" +#include "base/Tool.h" static QWidget* create_audio_plot() { class Audio_Plot : public renderive::Latency_Eager_Plot { public: diff --git a/Demo_Gallery/Normal_test.h b/Demo_Gallery/Normal_test.h index 172f224..0ac227e 100644 --- a/Demo_Gallery/Normal_test.h +++ b/Demo_Gallery/Normal_test.h @@ -1,6 +1,6 @@ #pragma once #include "../Widget/component/Table/export.h" -#include "../Renderive/base/Tool.h" +#include "base/Tool.h" namespace Psc { // // static std::vector cw(Table_View* view) { diff --git a/Demo_Gallery/Planisphere_Plot.h b/Demo_Gallery/Planisphere_Plot.h index 5749778..6c9d719 100644 --- a/Demo_Gallery/Planisphere_Plot.h +++ b/Demo_Gallery/Planisphere_Plot.h @@ -1,5 +1,5 @@ #pragma once -#include "../Renderive/base/Tool.h" +#include "base/Tool.h" static QWidget* create_planisphere_plot() { class Time_Axis; class Planisphere_Plot : public renderive::Latency_Eager_Plot { diff --git a/Demo_Gallery/Spectrum_Plot.h b/Demo_Gallery/Spectrum_Plot.h index 8072182..83823a2 100644 --- a/Demo_Gallery/Spectrum_Plot.h +++ b/Demo_Gallery/Spectrum_Plot.h @@ -1,5 +1,5 @@ #pragma once -#include "../Renderive/base/Tool.h" +#include "base/Tool.h" static QWidget* create_spectrun_plot() { class Spectrum_Plot : public renderive::Latency_Eager_Plot { public: diff --git a/Demo_Gallery/Sweep_Frequent_Plot.h b/Demo_Gallery/Sweep_Frequent_Plot.h index 1df769f..e864974 100644 --- a/Demo_Gallery/Sweep_Frequent_Plot.h +++ b/Demo_Gallery/Sweep_Frequent_Plot.h @@ -1,5 +1,5 @@ #pragma once -#include "../Renderive/base/Tool.h" +#include "base/Tool.h" static QWidget* create_sweep_frequent_plot() { class Sweep_Frequent_Plot : public renderive::Latency_Eager_Plot { public: diff --git a/Demo_Gallery/Waterfall_Plot.h b/Demo_Gallery/Waterfall_Plot.h index e9013c2..d7c4add 100644 --- a/Demo_Gallery/Waterfall_Plot.h +++ b/Demo_Gallery/Waterfall_Plot.h @@ -1,5 +1,5 @@ #pragma once -#include "../Renderive/base/Tool.h" +#include "base/Tool.h" static QWidget* create_water_fall_plot() { class Waterfall_Plot : public renderive::Latency_Eager_Plot { public: diff --git a/Demo_Gallery/base/Axis_Test.h b/Demo_Gallery/base/Axis_Test.h index 20ce1a9..3d92b61 100644 --- a/Demo_Gallery/base/Axis_Test.h +++ b/Demo_Gallery/base/Axis_Test.h @@ -1,5 +1,5 @@ #pragma once -#include "../../Renderive/base/Tool.h" +#include "Tool.h" static QWidget* create_axis_test_plot() { class Axis_Test_Plot : public renderive::Latency_Eager_Plot { public: diff --git a/Demo_Gallery/base/Frequency_Axis.h b/Demo_Gallery/base/Frequency_Axis.h index 3e81bee..fe1e35d 100644 --- a/Demo_Gallery/base/Frequency_Axis.h +++ b/Demo_Gallery/base/Frequency_Axis.h @@ -1,5 +1,5 @@ #pragma once -#include "../../Renderive/base/Tool.h" +#include "Tool.h" static QWidget* create_frequent_axis_test_plot() { class Axis_Test_Plot : public renderive::Latency_Eager_Plot { public: diff --git a/Demo_Gallery/base/Frequency_Axis_Test.h b/Demo_Gallery/base/Frequency_Axis_Test.h index 3e81bee..fe1e35d 100644 --- a/Demo_Gallery/base/Frequency_Axis_Test.h +++ b/Demo_Gallery/base/Frequency_Axis_Test.h @@ -1,5 +1,5 @@ #pragma once -#include "../../Renderive/base/Tool.h" +#include "Tool.h" static QWidget* create_frequent_axis_test_plot() { class Axis_Test_Plot : public renderive::Latency_Eager_Plot { public: diff --git a/Demo_Gallery/base/Multi_Select_Test.h b/Demo_Gallery/base/Multi_Select_Test.h index 895e4a4..9e2b3c2 100644 --- a/Demo_Gallery/base/Multi_Select_Test.h +++ b/Demo_Gallery/base/Multi_Select_Test.h @@ -1,5 +1,5 @@ #pragma once -#include "../../Renderive/base/Tool.h" +#include "Tool.h" static QWidget* create_Multi_Select_Plot() { class Multi_Select_Plot : public renderive::Latency_Eager_Plot { public: diff --git a/Demo_Gallery/base/Time_Axis_Test.h b/Demo_Gallery/base/Time_Axis_Test.h index 58090d8..421e35c 100644 --- a/Demo_Gallery/base/Time_Axis_Test.h +++ b/Demo_Gallery/base/Time_Axis_Test.h @@ -1,5 +1,5 @@ #pragma once -#include "../../Renderive/base/Tool.h" +#include "Tool.h" static QWidget* create_time_axis_test_plot() { class Axis_Test_Plot : public renderive::Latency_Eager_Plot { public: diff --git a/Renderive/base/Tool.h b/Demo_Gallery/base/Tool.h similarity index 98% rename from Renderive/base/Tool.h rename to Demo_Gallery/base/Tool.h index 8ad4034..6b7e970 100644 --- a/Renderive/base/Tool.h +++ b/Demo_Gallery/base/Tool.h @@ -1,4 +1,5 @@ #pragma once +#include #include #include #include @@ -12,11 +13,11 @@ #include #include #include -#include "../Axis/export.h" -#include "../Generate_Mock_Data.h" -#include "../architecture/export.h" +#include "../../Renderive/Axis/export.h" +#include "../../Widget/base/Generate_Mock_Data.h" +#include "../../Renderive/architecture/export.h" #include "../../Widget/base/export.h" -#include "../plottable/export.h" +#include "../../Renderive/plottable/export.h" #include "Renderive/plot/Latency_Eager_Plot.h" #include "Renderive/plot/Plot.h" namespace renderive { @@ -280,8 +281,8 @@ static QWidget* create_control(renderive::Abs_Plot* plot, const std::vectoris_rendering() ? plot->pause_render() : plot->start_render(); }, plot->is_rendering()), renderive::create_toggle_button("停止性能测试", "启动性能测试", [plot]() { - plot->set_use_performance_shower(plot->get_use_performance_shower() ? false : true); - }, plot->get_use_performance_shower()), + renderive::set_performance_shower_enabled(*plot, !renderive::performance_shower_enabled(*plot)); + }, renderive::performance_shower_enabled(*plot)), renderive::create_select_color("更改背景色", [plot](const QColor& color) { plot->set_background_color(color); }, plot->background_color()), @@ -528,7 +529,7 @@ static std::vector cw(renderive::Afterglow* it, int num_pre_second = - else { rate = renderive::get_data({0.8, 1.2}); } - ret[i] = renderive::clamp(ret[i - 1] * rate, r.origin, r.target); + ret[i] = std::clamp(ret[i - 1] * rate, r.origin, r.target); } return ret; }; @@ -540,7 +541,7 @@ static std::vector cw(renderive::Afterglow* it, int num_pre_second = - std::vector cur_data(n); for (int i = 0; i < n; ++i) { double rate = renderive::get_data({0.8, 1.2}); - cur_data[i] = renderive::clamp(base_data[i] * rate, r.origin, r.target); + cur_data[i] = std::clamp(base_data[i] * rate, r.origin, r.target); } it->give_data(cur_data); }); diff --git a/Demo_Gallery/export.h b/Demo_Gallery/export.h index ded23fe..8305a4a 100644 --- a/Demo_Gallery/export.h +++ b/Demo_Gallery/export.h @@ -6,7 +6,7 @@ #include "Planisphere_Plot.h" #include "Spectrum_Plot.h" #include "Sweep_Frequent_Plot.h" -#include "../Renderive/base/Tool.h" +#include "base/Tool.h" #include "Waterfall_Plot.h" #include "base/Axis_Test.h" #include "base/Frequency_Axis_Test.h" diff --git a/Renderive/Axis/Abs_Axis.cpp b/Renderive/Axis/Abs_Axis.cpp index 3b1da22..06f80f8 100644 --- a/Renderive/Axis/Abs_Axis.cpp +++ b/Renderive/Axis/Abs_Axis.cpp @@ -2,106 +2,26 @@ #include #include "Abs_Axis_p.h" namespace renderive { -using Abs_Axis_Binding = Renderable_Binding; -Abs_Axis::Abs_Axis() { - Abs_Axis_Binding::init(this, "AbsAxis"); -} -Abs_Axis_Private* Abs_Axis::d() { - return Abs_Axis_Binding::d(this); -} -Render_Object_Owner Abs_Axis::create_render_data() { - return Abs_Axis_Binding::create_render_data(); -} -Render_Object_Owner Abs_Axis::create_render_state() { - return Abs_Axis_Binding::create_render_state(); -} -Render_Object_Owner Abs_Axis::create_input_data() { - return Abs_Axis_Binding::create_input_data(); -} -int Abs_Axis::x(SRC src) { - return d()->state_value(&Abs_Axis_Render_State::x, src); -} -void Abs_Axis::set_x(int value) { - d()->set_state_value(&Abs_Axis_Render_State::x, value); -} -int Abs_Axis::y(SRC src) { - return d()->state_value(&Abs_Axis_Render_State::y, src); -} -void Abs_Axis::set_y(int value) { - d()->set_state_value(&Abs_Axis_Render_State::y, value); -} -Qt::Orientation Abs_Axis::orientation(SRC src) { - return d()->state_value(&Abs_Axis_Render_State::orientation, src); -} -void Abs_Axis::set_orientation(Qt::Orientation value) { - d()->set_state_value(&Abs_Axis_Render_State::orientation, value); -} +RENDERIVE_DEFINE_RENDERABLE_BINDING(Abs_Axis, Abs_Axis_Private, Abs_Axis_Render_State, Abs_Axis_Input_Data, "AbsAxis") +RENDERIVE_DEFINE_STATE_PROP(Abs_Axis, Abs_Axis_Render_State, int, x) +RENDERIVE_DEFINE_STATE_PROP(Abs_Axis, Abs_Axis_Render_State, int, y) +RENDERIVE_DEFINE_STATE_PROP(Abs_Axis, Abs_Axis_Render_State, Qt::Orientation, orientation) size_t Abs_Axis::pixel_size(SRC src) { return d()->state_value(&Abs_Axis_Render_State::pixel_size, src); } void Abs_Axis::set_pixel_size(size_t value) { d()->set_state_value(&Abs_Axis_Render_State::pixel_size, std::max(1, value)); } -int Abs_Axis::tick_length(SRC src) { - return d()->state_value(&Abs_Axis_Render_State::tick_length, src); -} -void Abs_Axis::set_tick_length(int value) { - d()->set_state_value(&Abs_Axis_Render_State::tick_length, value); -} -int Abs_Axis::sub_tick_length(SRC src) { - return d()->state_value(&Abs_Axis_Render_State::sub_tick_length, src); -} -void Abs_Axis::set_sub_tick_length(int value) { - d()->set_state_value(&Abs_Axis_Render_State::sub_tick_length, value); -} -QColor Abs_Axis::color(SRC src) { - return d()->state_value(&Abs_Axis_Render_State::color, src); -} -void Abs_Axis::set_color(QColor value) { - d()->set_state_value(&Abs_Axis_Render_State::color, std::move(value)); -} -QChar Abs_Axis::format_char(SRC src) { - return d()->state_value(&Abs_Axis_Render_State::format_char, src); -} -void Abs_Axis::set_format_char(QChar value) { - d()->set_state_value(&Abs_Axis_Render_State::format_char, std::move(value)); -} -QLocale Abs_Axis::locale(SRC src) { - return d()->state_value(&Abs_Axis_Render_State::locale, src); -} -void Abs_Axis::set_locale(QLocale value) { - d()->set_state_value(&Abs_Axis_Render_State::locale, std::move(value)); -} -QString Abs_Axis::unit_text(SRC src) { - return d()->state_value(&Abs_Axis_Render_State::unit_text, src); -} -void Abs_Axis::set_unit_text(QString value) { - d()->set_state_value(&Abs_Axis_Render_State::unit_text, std::move(value)); -} -QFont Abs_Axis::unit_text_font(SRC src) { - return d()->state_value(&Abs_Axis_Render_State::unit_text_font, src); -} -void Abs_Axis::set_unit_text_font(QFont value) { - d()->set_state_value(&Abs_Axis_Render_State::unit_text_font, std::move(value)); -} -QPen Abs_Axis::unit_text_pen(SRC src) { - return d()->state_value(&Abs_Axis_Render_State::unit_text_pen, src); -} -void Abs_Axis::set_unit_text_pen(QPen value) { - d()->set_state_value(&Abs_Axis_Render_State::unit_text_pen, std::move(value)); -} -QBrush Abs_Axis::unit_text_background_brush(SRC src) { - return d()->state_value(&Abs_Axis_Render_State::unit_text_background_brush, src); -} -void Abs_Axis::set_unit_text_background_brush(QBrush value) { - d()->set_state_value(&Abs_Axis_Render_State::unit_text_background_brush, std::move(value)); -} -int Abs_Axis::rotate(SRC src) { - return d()->state_value(&Abs_Axis_Render_State::rotate, src); -} -void Abs_Axis::set_rotate(int value) { - d()->set_state_value(&Abs_Axis_Render_State::rotate, value); -} +RENDERIVE_DEFINE_STATE_PROP(Abs_Axis, Abs_Axis_Render_State, int, tick_length) +RENDERIVE_DEFINE_STATE_PROP(Abs_Axis, Abs_Axis_Render_State, int, sub_tick_length) +RENDERIVE_DEFINE_STATE_PROP(Abs_Axis, Abs_Axis_Render_State, QColor, color) +RENDERIVE_DEFINE_STATE_PROP(Abs_Axis, Abs_Axis_Render_State, QChar, format_char) +RENDERIVE_DEFINE_STATE_PROP(Abs_Axis, Abs_Axis_Render_State, QLocale, locale) +RENDERIVE_DEFINE_STATE_PROP(Abs_Axis, Abs_Axis_Render_State, QString, unit_text) +RENDERIVE_DEFINE_STATE_PROP(Abs_Axis, Abs_Axis_Render_State, QFont, unit_text_font) +RENDERIVE_DEFINE_STATE_PROP(Abs_Axis, Abs_Axis_Render_State, QPen, unit_text_pen) +RENDERIVE_DEFINE_STATE_PROP(Abs_Axis, Abs_Axis_Render_State, QBrush, unit_text_background_brush) +RENDERIVE_DEFINE_STATE_PROP(Abs_Axis, Abs_Axis_Render_State, int, rotate) double Abs_Axis::pixel_to_coord(double pixel, SRC src) { return d()->pixel_to_coord(pixel, src); } diff --git a/Renderive/Axis/Abs_Axis_p.h b/Renderive/Axis/Abs_Axis_p.h index 010f43b..744bbb1 100644 --- a/Renderive/Axis/Abs_Axis_p.h +++ b/Renderive/Axis/Abs_Axis_p.h @@ -5,8 +5,6 @@ namespace renderive { struct Abs_Axis_Render_State : Render_State, Abs_Axis_Prop { size_t pixel_size{}; int number_precision = 2; - double coord_start = 0; - double coord_length = 20; void scale_range(double factor, double center) { coord_start = (coord_start - center) * factor + center; coord_length *= factor; @@ -15,7 +13,9 @@ struct Abs_Axis_Render_State : Render_State, Abs_Axis_Prop { struct Abs_Axis_Input_Data : Input_Data {}; struct Abs_Axis_Private : Typed_Render_Data { int tick_count = 2; - std::atomic pixel_start{}; + static int pixel_start_of(const Abs_Axis_Render_State* s) { + return s->orientation == Qt::Horizontal ? s->x : s->y; + } double get_mantissa(double input, double* magnitude = nullptr); [[nodiscard]] double clean_mantissa(double input); [[nodiscard]] double pick_closest(double target, const std::vector& candidates); @@ -24,7 +24,7 @@ struct Abs_Axis_Private : Typed_Render_Dataorientation == Qt::Horizontal ? s->x : s->y; + const int pixel_start = pixel_start_of(s); Range range = {s->coord_start, s->coord_start + s->coord_length}; Abs_Axis* q = this->q(); double tick_step = q->get_tick_step(range); @@ -106,11 +106,11 @@ struct Abs_Axis_Private : Typed_Render_Data(state(src)); - return s->coord_start + s->coord_length * (pixel - (double)pixel_start) / (double)s->pixel_size; + return s->coord_start + s->coord_length * (pixel - (double)pixel_start_of(s)) / (double)s->pixel_size; } [[nodiscard]] virtual double coord_to_pixel(double coord, SRC src) { auto s = static_cast(state(src)); - return pixel_start + (double)s->pixel_size * (coord - s->coord_start) / s->coord_length; + return pixel_start_of(s) + (double)s->pixel_size * (coord - s->coord_start) / s->coord_length; } virtual double get_tick_step(const Range& range) { double exact_step = range.size() / double(tick_count + 1e-10); diff --git a/Renderive/Axis/Axis.cpp b/Renderive/Axis/Axis.cpp index 1188d5b..70b5180 100644 --- a/Renderive/Axis/Axis.cpp +++ b/Renderive/Axis/Axis.cpp @@ -1,34 +1,9 @@ #include "Axis_p.h" #include "../base/Memory.h" namespace renderive { -using Axis_Binding = Renderable_Binding; -Axis::Axis() { - Axis_Binding::init(this, "Axis"); -} -Axis_Private* Axis::d() { - return Axis_Binding::d(this); -} -Render_Object_Owner Axis::create_render_data() { - return Axis_Binding::create_render_data(); -} -Render_Object_Owner Axis::create_render_state() { - return Axis_Binding::create_render_state(); -} -Render_Object_Owner Axis::create_input_data() { - return Axis_Binding::create_input_data(); -} -int Axis::number_precision(SRC src) { - return d()->state_value(&Axis_Render_State::number_precision, src); -} -void Axis::set_number_precision(int value) { - d()->set_state_value(&Axis_Render_State::number_precision, value); -} -double Axis::coord_start(SRC src) { - return d()->state_value(&Axis_Render_State::coord_start, src); -} -void Axis::set_coord_start(double value) { - d()->set_state_value(&Axis_Render_State::coord_start, value); -} +RENDERIVE_DEFINE_RENDERABLE_BINDING(Axis, Axis_Private, Axis_Render_State, Axis_Input_Data, "Axis") +RENDERIVE_DEFINE_STATE_PROP(Axis, Axis_Render_State, int, number_precision) +RENDERIVE_DEFINE_STATE_PROP(Axis, Axis_Render_State, double, coord_start) double Axis::coord_length(SRC src) { return d()->state_value(&Axis_Render_State::coord_length, src); } diff --git a/Renderive/Axis/Axis_p.h b/Renderive/Axis/Axis_p.h index f8d3474..d2004c2 100644 --- a/Renderive/Axis/Axis_p.h +++ b/Renderive/Axis/Axis_p.h @@ -17,7 +17,8 @@ struct Axis_Private : Typed_Render_Data_BaseangleDelta().y(); double wheel_steps = delta / 120.0; double factor = std::pow(0.8, wheel_steps); - double cursor_coord = pixel_to_coord(event->position().x(), SRC::Edit); + double cursor_pixel = edit->orientation == Qt::Horizontal ? event->position().x() : event->position().y(); + double cursor_coord = pixel_to_coord(cursor_pixel, SRC::Edit); double new_coord_length = edit->coord_length * factor; double new_coord_start = cursor_coord - new_coord_length * (cursor_coord - edit->coord_start) / edit->coord_length; edit->coord_start = new_coord_start; @@ -25,7 +26,7 @@ struct Axis_Private : Typed_Render_Data_Basepos(); Render_State_Lease state(this); start_coord_value = state->coord_start; pixel_pre_coord = state->coord_length / static_cast(state->pixel_size); diff --git a/Renderive/Axis/Frequency_Axis.cpp b/Renderive/Axis/Frequency_Axis.cpp index d4ab8c1..4bb99d4 100644 --- a/Renderive/Axis/Frequency_Axis.cpp +++ b/Renderive/Axis/Frequency_Axis.cpp @@ -2,22 +2,7 @@ #include "Frequency_Axis_p.h" #include "../base/Memory.h" namespace renderive { -using Frequency_Axis_Binding = Renderable_Binding; -Frequency_Axis::Frequency_Axis() { - Frequency_Axis_Binding::init(this, "Frequency_Axis"); -} -Frequency_Axis_Private* Frequency_Axis::d() { - return Frequency_Axis_Binding::d(this); -} -Render_Object_Owner Frequency_Axis::create_render_data() { - return Frequency_Axis_Binding::create_render_data(); -} -Render_Object_Owner Frequency_Axis::create_render_state() { - return Frequency_Axis_Binding::create_render_state(); -} -Render_Object_Owner Frequency_Axis::create_input_data() { - return Frequency_Axis_Binding::create_input_data(); -} +RENDERIVE_DEFINE_RENDERABLE_BINDING(Frequency_Axis, Frequency_Axis_Private, Frequency_Axis_Render_State, Frequency_Axis_Input_Data, "Frequency_Axis") Frequency_Axis::Builder::Builder(std::shared_ptr parent, Qt::Orientation orientation) { ASSERT(parent && parent->plot, "Frequency_Axis build error! parent invalid"); this->parent = parent; diff --git a/Renderive/Axis/Time_Axis.cpp b/Renderive/Axis/Time_Axis.cpp index 8309f43..630e2f5 100644 --- a/Renderive/Axis/Time_Axis.cpp +++ b/Renderive/Axis/Time_Axis.cpp @@ -1,22 +1,7 @@ #include "Time_Axis_p.h" #include "../base/Memory.h" namespace renderive { -using Time_Axis_Binding = Renderable_Binding; -Time_Axis::Time_Axis() { - Time_Axis_Binding::init(this, "time_axis"); -} -Time_Axis_Private* Time_Axis::d() { - return Time_Axis_Binding::d(this); -} -Render_Object_Owner Time_Axis::create_render_data() { - return Time_Axis_Binding::create_render_data(); -} -Render_Object_Owner Time_Axis::create_render_state() { - return Time_Axis_Binding::create_render_state(); -} -Render_Object_Owner Time_Axis::create_input_data() { - return Time_Axis_Binding::create_input_data(); -} +RENDERIVE_DEFINE_RENDERABLE_BINDING(Time_Axis, Time_Axis_Private, Time_Axis_Render_State, Time_Axis_Input_Data, "time_axis") int Time_Axis::time_point_size(SRC src) { return d()->state_value(&Time_Axis_Render_State::time_point_size, src); } @@ -32,25 +17,15 @@ int Time_Axis::tick_pixel_space(SRC src) { void Time_Axis::set_tick_pixel_space(int value) { d()->set_state_value(&Time_Axis_Render_State::tick_pixel_space, qMax(1, value)); } -QString Time_Axis::time_format(SRC src) { - return d()->state_value(&Time_Axis_Render_State::time_format, src); -} -void Time_Axis::set_time_format(QString value) { - d()->set_state_value(&Time_Axis_Render_State::time_format, std::move(value)); -} -QFont Time_Axis::font(SRC src) { - return d()->state_value(&Time_Axis_Render_State::font, src); -} -void Time_Axis::set_font(QFont value) { - d()->set_state_value(&Time_Axis_Render_State::font, std::move(value)); -} +RENDERIVE_DEFINE_STATE_PROP(Time_Axis, Time_Axis_Render_State, QString, time_format) +RENDERIVE_DEFINE_STATE_PROP(Time_Axis, Time_Axis_Render_State, QFont, font) std::shared_ptr Time_Axis::timeline_stream(SRC src) { return d()->state_value(&Time_Axis_Render_State::timeline_stream, src); } void Time_Axis::set_timeline_stream(std::shared_ptr value) { if (value) { value->set_time_point_size(time_point_size()); - value->set_tick_space(d()->state_data(SRC::Edit)->tick_space); + value->set_tick_space(d()->state_data(SRC::Edit)->get_tick_space_hint()); value->set_start_coord_to_end_coord(start_coord_to_end_coord()); } d()->set_state_value(&Time_Axis_Render_State::timeline_stream, std::move(value)); @@ -101,9 +76,8 @@ std::shared_ptr Time_Axis::Builder::build() { sc->tick_pixel_space = qMax(1, sc->tick_pixel_space); if (!sc->timeline_stream) sc->timeline_stream = renderive::make_shared(); - sc->tick_space = sc->get_tick_space_hint(); sc->timeline_stream->set_time_point_size(sc->time_point_size); - sc->timeline_stream->set_tick_space(sc->tick_space); + sc->timeline_stream->set_tick_space(sc->get_tick_space_hint()); sc->timeline_stream->set_start_coord_to_end_coord(sc->start_coord_to_end_coord); return ret; } diff --git a/Renderive/Axis/Time_Axis_p.h b/Renderive/Axis/Time_Axis_p.h index 422fd64..0eb6ea5 100644 --- a/Renderive/Axis/Time_Axis_p.h +++ b/Renderive/Axis/Time_Axis_p.h @@ -11,8 +11,7 @@ namespace renderive { struct Time_Axis_Input_Data : Abs_Axis_Input_Data {}; struct Time_Axis_Render_State : Abs_Axis_Render_State, Time_Axis_Prop { - int tick_space = 4; - int get_tick_space_hint(SRC src = SRC::Edit) { + int get_tick_space_hint() const { QFontMetrics fm(font); double rate = (double)time_point_size / (double)pixel_size; double ret = rate * (tick_pixel_space + (orientation == Qt::Horizontal ? fm.horizontalAdvance(time_format) : fm.height())); @@ -20,16 +19,10 @@ struct Time_Axis_Render_State : Abs_Axis_Render_State, Time_Axis_Prop { } }; struct Time_Axis_Private : Typed_Render_Data_Base { - Timeline_Stream_Snapshot timeline_snapshot; - std::pmr::vector time_snapshot{memory_resource(Memory_Domain::Axis)}; - std::pmr::vector data{memory_resource(Memory_Domain::Axis)}; - int time_data_count{}; - int tick_pixel_space{}; - QFont font; - QString time_format; + std::shared_ptr timeline_snapshot; std::vector ticks; QTime time_by_tick(int tick) const { - return timeline_snapshot.time_by_tick(tick); + return timeline_snapshot ? timeline_snapshot->time_by_tick(tick) : QTime{}; } void prepare_data(const Plot_Render_Snapshot& snapshot) override { sync_state_pipeline(); @@ -39,41 +32,23 @@ struct Time_Axis_Private : Typed_Render_Data_Base(state_by_index(state_lease.index)); - bool refresh_space = false; - if (tick_pixel_space != s->tick_pixel_space) { - tick_pixel_space = s->tick_pixel_space; - refresh_space = true; - } - if (font != s->font) { - font = s->font; - refresh_space = true; - } - if (time_format != s->time_format) { - time_format = s->time_format; - if (s->orientation == Qt::Horizontal) - refresh_space = true; - } - if (refresh_space || s->tick_space <= 0) { - s->tick_space = s->get_tick_space_hint(); - sc->tick_space = s->tick_space; - } + int tick_space = s->get_tick_space_hint(); stream->set_time_point_size(s->time_point_size); - stream->set_tick_space(s->tick_space); + stream->set_tick_space(tick_space); stream->set_start_coord_to_end_coord(s->start_coord_to_end_coord); auto captured = snapshot.timeline_snapshot(stream); if (captured) - timeline_snapshot = *captured; - s->coord_start = timeline_snapshot.lower; - s->coord_length = timeline_snapshot.time_point_size; - sc->coord_start = timeline_snapshot.lower; - sc->coord_length = timeline_snapshot.time_point_size; - time_snapshot.clear(); - time_snapshot.resize(static_cast(timeline_snapshot.time_point_size)); - std::copy(timeline_snapshot.times.begin(), timeline_snapshot.times.end(), time_snapshot.begin()); - time_data_count = static_cast(timeline_snapshot.times.size()); - data.assign(timeline_snapshot.ticks.begin(), timeline_snapshot.ticks.end()); + timeline_snapshot = std::move(captured); + if (!timeline_snapshot) { + state_control.unmark_use(state_lease); + return; + } + s->coord_start = timeline_snapshot->lower; + s->coord_length = timeline_snapshot->time_point_size; + sc->coord_start = timeline_snapshot->lower; + sc->coord_length = timeline_snapshot->time_point_size; ticks.clear(); - for (const Timeline_Tick& tick : data) { + for (const Timeline_Tick& tick : timeline_snapshot->ticks) { ticks.push_back(tick.tick); } state_control.unmark_use(state_lease); diff --git a/Renderive/algorithm.hpp b/Renderive/algorithm.hpp deleted file mode 100644 index 7dac197..0000000 --- a/Renderive/algorithm.hpp +++ /dev/null @@ -1,94 +0,0 @@ -#pragma once -#include -namespace YSG { -#define LOWER(offset) l_lower(spaces[offset]) -#define UPPER(offset) l_upper(spaces[offset]) -template -int binary_search(double value, T** spaces, int space_size, std::function& l_lower, std::function& l_upper) { - int start_index = 0, end_index = space_size - 1; - if (start_index == end_index) - return start_index; - double min = LOWER(start_index), max = UPPER(end_index); - if (value < min) { - // qDebug() << QString("warnning binary_search value:%1 < %2").arg(value).arg(min); - return start_index; - } - if (value > max) { - // qDebug() << QString("warnning binary_search value:%1 > %2").arg(value).arg(max); - return end_index; - } - while (start_index != end_index) { - if (start_index + 1 == end_index) { - double mid = (UPPER(start_index) + LOWER(end_index)) / 2.0; - if (value < mid) - return start_index; - return end_index; - } - int m = (start_index + end_index) / 2; - double lower = m != 0 ? (UPPER(m - 1) + LOWER(m)) / 2.0 : min; - double upper = m != space_size - 1 ? (UPPER(m) + LOWER(m + 1)) / 2.0 : max; - // qDebug() << " lower == " << lower << " upper == " << upper << "midIndex == " << m << " value == " << value; - // qDebug() << " start_index == " << start_index << " end_index == " << end_index; - if (value < lower) { - end_index = m; - } - else if (value > upper) { - start_index = m; - } - else { - return m; - } - } - qDebug() << QString("warnning start_index:%1, end_index:%2").arg(start_index).arg(end_index); - return start_index; -} -#undef LOWER -#undef UPPER -static int binary_search(double value, const std::vector& data, bool& ok) { - if (data.empty()) { - ok = false; - return -1; // 返回 -1 表示数组为空 - } - // 判断排序顺序 - bool ascending_order = data[0] < data[data.size() - 1]; - int left = 0; - int right = data.size() - 1; - // 二分查找 - while (left <= right) { - int mid = left + (right - left) / 2; - if (mid < data.size() - 1) { - if (ascending_order) { - if (data[mid] <= value && data[mid + 1] > value) { - ok = true; - return mid; - } - else if (data[mid] < value) { - left = mid + 1; - } - else { - right = mid - 1; - } - } - else { - // 处理降序排列的情况 - if (data[mid] >= value && data[mid + 1] < value) { - ok = true; - return mid; - } - else if (data[mid] > value) { - left = mid + 1; - } - else { - right = mid - 1; - } - } - } - else { - break; // 如果 mid 已经是最后一个元素,不再继续查找 - } - } - ok = false; - // 如果找不到,则返回 -1,表示 value 不在区间内 - return -1; -} -} // namespace YSG diff --git a/Renderive/architecture/Bounded_Input_Buffer.h b/Renderive/architecture/Bounded_Input_Buffer.h index a175a71..4e6fea4 100644 --- a/Renderive/architecture/Bounded_Input_Buffer.h +++ b/Renderive/architecture/Bounded_Input_Buffer.h @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -19,12 +18,7 @@ public: while (!buffer.write(data, size)) { if (!buffer.skip_one()) return; - dropped_count.fetch_add(1, std::memory_order_relaxed); - capacity_dropped_count.fetch_add(1, std::memory_order_relaxed); - decrement_pending(); } - pending_count.fetch_add(1, std::memory_order_relaxed); - pushed_count.fetch_add(1, std::memory_order_relaxed); } template void read_all(Handler handler) { @@ -34,64 +28,27 @@ public: std::size_t read_size = packet_size; if (!buffer.read(read_buffer.data(), read_size)) return; - decrement_pending(); handler(read_buffer.data(), read_size); } } void clear() { while (buffer.skip_one()) {} - pending_count.store(0, std::memory_order_relaxed); - } - [[nodiscard]] std::uint64_t get_pending_count() const { - return pending_count.load(std::memory_order_relaxed); - } - [[nodiscard]] std::uint64_t get_dropped_count() const { - return dropped_count.load(std::memory_order_relaxed); - } - [[nodiscard]] std::uint64_t get_capacity_dropped_count() const { - return capacity_dropped_count.load(std::memory_order_relaxed); - } - [[nodiscard]] std::uint64_t get_rebuild_dropped_count() const { - return rebuild_dropped_count.load(std::memory_order_relaxed); - } - [[nodiscard]] std::uint64_t get_consumer_dropped_count() const { - return consumer_dropped_count.load(std::memory_order_relaxed); - } - [[nodiscard]] std::uint64_t get_pushed_count() const { - return pushed_count.load(std::memory_order_relaxed); - } - void record_consumer_dropped() { - dropped_count.fetch_add(1, std::memory_order_relaxed); - consumer_dropped_count.fetch_add(1, std::memory_order_relaxed); } + void record_consumer_dropped() {} private: void configure(std::size_t max_packet_size, std::size_t max_packet_count) { max_packet_count = std::max(1, max_packet_count); max_packet_size = std::max(1, max_packet_size); if (Initialized && max_packet_size <= this->max_packet_size && max_packet_count == this->max_packet_count) return; - std::uint64_t pending = pending_count.load(std::memory_order_relaxed); - dropped_count.fetch_add(pending, std::memory_order_relaxed); - rebuild_dropped_count.fetch_add(pending, std::memory_order_relaxed); this->max_packet_size = max_packet_size; this->max_packet_count = max_packet_count; - pending_count.store(0, std::memory_order_relaxed); buffer.init((Psc::RingBuffer_ST::HEADER_SIZE + max_packet_size) * max_packet_count); Initialized = true; } - void decrement_pending() { - std::uint64_t pending = pending_count.load(std::memory_order_relaxed); - while (pending && !pending_count.compare_exchange_weak(pending, pending - 1, std::memory_order_relaxed)) {} - } bool Initialized = false; std::size_t max_packet_size{}; std::size_t max_packet_count{}; - std::atomic pending_count{}; - std::atomic dropped_count{}; - std::atomic capacity_dropped_count{}; - std::atomic rebuild_dropped_count{}; - std::atomic consumer_dropped_count{}; - std::atomic pushed_count{}; Psc::RingBuffer_ST buffer{memory_resource(Memory_Domain::Input_Buffer)}; std::pmr::vector read_buffer{memory_resource(Memory_Domain::Input_Buffer)}; }; @@ -102,49 +59,22 @@ public: std::pmr::vector& row = row_at(row_count); row.assign(data.begin(), data.end()); ++row_count; - pending_count_value.store(row_count, std::memory_order_relaxed); - pushed_count_value.fetch_add(1, std::memory_order_relaxed); } void push(std::pmr::vector&& data, std::size_t max_packet_count) { prepare_push(max_packet_count); rows[row_count].emplace(std::move(data)); ++row_count; - pending_count_value.store(row_count, std::memory_order_relaxed); - pushed_count_value.fetch_add(1, std::memory_order_relaxed); } template void read_all(Handler handler) { for (std::size_t i = 0; i < row_count; ++i) handler(*rows[i]); row_count = 0; - pending_count_value.store(0, std::memory_order_relaxed); } void clear() { row_count = 0; - pending_count_value.store(0, std::memory_order_relaxed); - } - [[nodiscard]] std::uint64_t pending_count() const { - return pending_count_value.load(std::memory_order_relaxed); - } - [[nodiscard]] std::uint64_t dropped_count() const { - return dropped_count_value.load(std::memory_order_relaxed); - } - [[nodiscard]] std::uint64_t capacity_dropped_count() const { - return capacity_dropped_value.load(std::memory_order_relaxed); - } - [[nodiscard]] std::uint64_t rebuild_dropped_count() const { - return 0; - } - [[nodiscard]] std::uint64_t consumer_dropped_count() const { - return consumer_dropped_value.load(std::memory_order_relaxed); - } - [[nodiscard]] std::uint64_t pushed_count() const { - return pushed_count_value.load(std::memory_order_relaxed); - } - void record_consumer_dropped() { - dropped_count_value.fetch_add(1, std::memory_order_relaxed); - consumer_dropped_value.fetch_add(1, std::memory_order_relaxed); } + void record_consumer_dropped() {} private: static constexpr std::size_t Storage_Count = 64; std::pmr::vector& row_at(std::size_t index) { @@ -166,57 +96,8 @@ private: rows[i].reset(); } --row_count; - pending_count_value.store(row_count, std::memory_order_relaxed); - dropped_count_value.fetch_add(1, std::memory_order_relaxed); - capacity_dropped_value.fetch_add(1, std::memory_order_relaxed); } std::array>, Storage_Count> rows; std::size_t row_count{}; - std::atomic pending_count_value{}; - std::atomic dropped_count_value{}; - std::atomic capacity_dropped_value{}; - std::atomic consumer_dropped_value{}; - std::atomic pushed_count_value{}; -}; -class Bounded_Double_Input_Buffer { -public: - void push(double data, std::size_t max_packet_count) { - buffer.push(&data, sizeof(data), max_packet_count); - } - template - void read_all(Handler handler) { - buffer.read_all([this, &handler](const void* data, std::size_t size) { - (void)size; - std::memcpy(&value_buffer, data, sizeof(value_buffer)); - handler(value_buffer); - }); - } - void clear() { - buffer.clear(); - } - [[nodiscard]] std::uint64_t pending_count() const { - return buffer.get_pending_count(); - } - [[nodiscard]] std::uint64_t dropped_count() const { - return buffer.get_dropped_count(); - } - [[nodiscard]] std::uint64_t capacity_dropped_count() const { - return buffer.get_capacity_dropped_count(); - } - [[nodiscard]] std::uint64_t rebuild_dropped_count() const { - return buffer.get_rebuild_dropped_count(); - } - [[nodiscard]] std::uint64_t consumer_dropped_count() const { - return buffer.get_consumer_dropped_count(); - } - [[nodiscard]] std::uint64_t pushed_count() const { - return buffer.get_pushed_count(); - } - void record_consumer_dropped() { - buffer.record_consumer_dropped(); - } -private: - Bounded_Input_Buffer buffer; - double value_buffer{}; }; } diff --git a/Renderive/architecture/Frame_Scheduler.h b/Renderive/architecture/Frame_Scheduler.h index d4fa4bd..71ec0c5 100644 --- a/Renderive/architecture/Frame_Scheduler.h +++ b/Renderive/architecture/Frame_Scheduler.h @@ -66,11 +66,8 @@ struct Renderable_Cache_Frame_Stat { QString parent_object_name; int tree_depth{}; std::uint64_t hit_count{}; - std::uint64_t stale_hit_count{}; std::uint64_t miss_count{}; std::uint64_t rebuild_count{}; - std::uint64_t stale_rebuild_count{}; - std::uint64_t miss_rebuild_count{}; std::uint64_t rebuild_time_ns{}; std::uint64_t compose_time_ns{}; std::uint64_t last_rebuild_time_ns{}; @@ -96,13 +93,8 @@ struct Renderable_Frame_Stat { struct Frame_Lifecycle_Record { std::uint64_t frame_id{}; std::uint64_t input_version{}; - std::uint64_t snapshot_version{}; std::uint64_t frame_slot_generation{}; std::uint64_t core_data_time{}; - std::uint64_t source_data_time_begin{}; - std::uint64_t source_data_time_end{}; - std::uint64_t snapshot_capture_begin_time{}; - std::uint64_t snapshot_capture_end_time{}; std::uint64_t render_request_time{}; std::uint64_t render_queue_enter_time{}; std::uint64_t render_begin_time{}; @@ -120,16 +112,10 @@ struct Frame_Lifecycle_Record { std::uint64_t superseded_time{}; Frame_Outcome frame_outcome = Frame_Outcome::Produced; std::uint64_t raw_input_count{}; - std::uint64_t visible_input_count{}; std::uint64_t prepared_output_count{}; - std::uint64_t draw_point_count{}; - std::uint64_t draw_segment_count{}; std::uint64_t renderable_cache_hit_count{}; - std::uint64_t renderable_cache_stale_hit_count{}; std::uint64_t renderable_cache_miss_count{}; std::uint64_t renderable_cache_rebuild_count{}; - std::uint64_t renderable_cache_stale_rebuild_count{}; - std::uint64_t renderable_cache_miss_rebuild_count{}; std::uint64_t renderable_cache_rebuild_time_ns{}; std::uint64_t renderable_cache_compose_time_ns{}; std::uint64_t renderable_cache_image_bytes{}; @@ -161,17 +147,23 @@ struct Frame_Lifecycle_Record { ++renderable_cache_hit_count; ++cache_stat(object_name, parent_object_name, tree_depth).hit_count; } - void record_renderable_cache_stale_hit(const QString& object_name, const QString& parent_object_name, int tree_depth) { - ++renderable_cache_stale_hit_count; - ++cache_stat(object_name, parent_object_name, tree_depth).stale_hit_count; - } void record_renderable_cache_miss(const QString& object_name, const QString& parent_object_name, int tree_depth) { ++renderable_cache_miss_count; ++cache_stat(object_name, parent_object_name, tree_depth).miss_count; } - void record_renderable_cache_rebuild(const QString& object_name, const QString& parent_object_name, int tree_depth, std::uint64_t rebuild_time_ns, std::uint64_t image_bytes, std::uint64_t image_area, std::uint64_t edit_version, std::uint64_t ready_version, bool stale, bool miss) { + void record_renderable_cache_rebuild(const QString& object_name, const QString& parent_object_name, int tree_depth, std::uint64_t rebuild_time_ns, std::uint64_t image_bytes, std::uint64_t image_area, std::uint64_t edit_version, std::uint64_t ready_version) { ++renderable_cache_rebuild_count; - record_renderable_cache_rebuild_detail(cache_stat(object_name, parent_object_name, tree_depth), rebuild_time_ns, image_bytes, image_area, edit_version, ready_version, stale, miss); + Renderable_Cache_Frame_Stat& stat = cache_stat(object_name, parent_object_name, tree_depth); + renderable_cache_rebuild_time_ns += rebuild_time_ns; + renderable_cache_image_bytes += image_bytes; + renderable_cache_image_area += image_area; + ++stat.rebuild_count; + stat.rebuild_time_ns += rebuild_time_ns; + stat.last_rebuild_time_ns = rebuild_time_ns; + stat.last_image_bytes = image_bytes; + stat.last_image_area = image_area; + stat.last_edit_version = edit_version; + stat.last_ready_version = ready_version; } void record_renderable_cache_compose(const QString& object_name, const QString& parent_object_name, int tree_depth, std::uint64_t compose_time_ns, std::uint64_t image_bytes, std::uint64_t image_area, std::uint64_t edit_version, std::uint64_t ready_version) { renderable_cache_compose_time_ns += compose_time_ns; @@ -183,24 +175,6 @@ struct Frame_Lifecycle_Record { stat.last_edit_version = edit_version; stat.last_ready_version = ready_version; } - void merge_renderable_cache_stats(const Frame_Lifecycle_Record& other) { - renderable_cache_hit_count += other.renderable_cache_hit_count; - renderable_cache_stale_hit_count += other.renderable_cache_stale_hit_count; - renderable_cache_miss_count += other.renderable_cache_miss_count; - renderable_cache_rebuild_count += other.renderable_cache_rebuild_count; - renderable_cache_stale_rebuild_count += other.renderable_cache_stale_rebuild_count; - renderable_cache_miss_rebuild_count += other.renderable_cache_miss_rebuild_count; - renderable_cache_rebuild_time_ns += other.renderable_cache_rebuild_time_ns; - renderable_cache_compose_time_ns += other.renderable_cache_compose_time_ns; - renderable_cache_image_bytes += other.renderable_cache_image_bytes; - renderable_cache_image_area += other.renderable_cache_image_area; - for (const auto& other_stat : other.renderable_cache_stats) - merge_cache_stat(cache_stat(other_stat.object_name, other_stat.parent_object_name, other_stat.tree_depth), other_stat); - } - void merge_renderable_stats(const Frame_Lifecycle_Record& other) { - for (const auto& other_stat : other.renderable_stats) - merge_renderable_stat(renderable_stat(other_stat.object_name, other_stat.parent_object_name, other_stat.tree_depth), other_stat); - } Renderable_Frame_Stat& renderable_stat(const QString& object_name, const QString& parent_object_name, int tree_depth) { for (auto& stat : renderable_stats) { if (stat.object_name == object_name && stat.parent_object_name == parent_object_name && stat.tree_depth == tree_depth) @@ -225,57 +199,15 @@ struct Frame_Lifecycle_Record { renderable_cache_stats.push_back(std::move(stat)); return renderable_cache_stats.back(); } -private: - static void merge_renderable_stat(Renderable_Frame_Stat& target, const Renderable_Frame_Stat& source) { - target.parent_object_name = source.parent_object_name; - target.tree_depth = source.tree_depth; - target.cache_enabled = source.cache_enabled; - target.render_count += source.render_count; - target.self_draw_count += source.self_draw_count; - target.total_render_time_ns += source.total_render_time_ns; - target.self_draw_time_ns += source.self_draw_time_ns; - target.last_total_render_time_ns = source.last_total_render_time_ns ? source.last_total_render_time_ns : target.last_total_render_time_ns; - target.last_self_draw_time_ns = source.last_self_draw_time_ns ? source.last_self_draw_time_ns : target.last_self_draw_time_ns; - } - void record_renderable_cache_rebuild_detail(Renderable_Cache_Frame_Stat& stat, std::uint64_t rebuild_time_ns, std::uint64_t image_bytes, std::uint64_t image_area, std::uint64_t edit_version, std::uint64_t ready_version, bool stale, bool miss) { - renderable_cache_rebuild_time_ns += rebuild_time_ns; - renderable_cache_image_bytes += image_bytes; - renderable_cache_image_area += image_area; - if (stale) { - ++renderable_cache_stale_rebuild_count; - ++stat.stale_rebuild_count; - } - if (miss) { - ++renderable_cache_miss_rebuild_count; - ++stat.miss_rebuild_count; - } - ++stat.rebuild_count; - stat.rebuild_time_ns += rebuild_time_ns; - stat.last_rebuild_time_ns = rebuild_time_ns; - stat.last_image_bytes = image_bytes; - stat.last_image_area = image_area; - stat.last_edit_version = edit_version; - stat.last_ready_version = ready_version; - } - static void merge_cache_stat(Renderable_Cache_Frame_Stat& target, const Renderable_Cache_Frame_Stat& source) { - target.parent_object_name = source.parent_object_name; - target.tree_depth = source.tree_depth; - target.hit_count += source.hit_count; - target.stale_hit_count += source.stale_hit_count; - target.miss_count += source.miss_count; - target.rebuild_count += source.rebuild_count; - target.stale_rebuild_count += source.stale_rebuild_count; - target.miss_rebuild_count += source.miss_rebuild_count; - target.rebuild_time_ns += source.rebuild_time_ns; - target.compose_time_ns += source.compose_time_ns; - target.last_rebuild_time_ns = source.last_rebuild_time_ns ? source.last_rebuild_time_ns : target.last_rebuild_time_ns; - target.last_compose_time_ns = source.last_compose_time_ns ? source.last_compose_time_ns : target.last_compose_time_ns; - target.last_image_bytes = source.last_image_bytes ? source.last_image_bytes : target.last_image_bytes; - target.last_image_area = source.last_image_area ? source.last_image_area : target.last_image_area; - target.last_edit_version = source.last_edit_version ? source.last_edit_version : target.last_edit_version; - target.last_ready_version = source.last_ready_version ? source.last_ready_version : target.last_ready_version; - } }; +inline std::uint64_t renderable_cache_subtree_compose_time(const std::vector& stats, const Renderable_Cache_Frame_Stat& node) { + std::uint64_t compose_time_ns = node.compose_time_ns; + for (const auto& stat : stats) { + if (stat.parent_object_name == node.object_name && stat.tree_depth == node.tree_depth + 1) + compose_time_ns += renderable_cache_subtree_compose_time(stats, stat); + } + return compose_time_ns; +} class Frame_Feedback_Controller { public: void reset(); diff --git a/Renderive/architecture/Plot_Render_Context.h b/Renderive/architecture/Plot_Render_Context.h index 0cfc3fd..72126e0 100644 --- a/Renderive/architecture/Plot_Render_Context.h +++ b/Renderive/architecture/Plot_Render_Context.h @@ -7,8 +7,16 @@ #include "Frame_Scheduler.h" namespace renderive { class Abs_Plot; -class Performance_Shower; +struct Renderable; class Timeline_Stream; +struct Frame_Lifecycle_Observer { + virtual ~Frame_Lifecycle_Observer() = default; + virtual bool enabled() const = 0; + virtual void collect_frame(const Frame_Lifecycle_Record& frame) = 0; + virtual Renderable* renderable() const { + return nullptr; + } +}; struct Timeline_Stream_Snapshot; struct Timeline_Stream_Cache_Item { std::weak_ptr stream; @@ -25,7 +33,7 @@ struct Plot_Render_Context { std::atomic_int render_height{0}; std::atomic background_rgba{0xff000000u}; std::atomic_int refresh_times_per_second{30}; - std::shared_ptr performance_shower_value; + std::shared_ptr frame_lifecycle_observer; std::atomic plot{}; }; struct Plot_Render_Snapshot { diff --git a/Renderive/architecture/Render_Data.cpp b/Renderive/architecture/Render_Data.cpp index b2bab65..ae0dc0b 100644 --- a/Renderive/architecture/Render_Data.cpp +++ b/Renderive/architecture/Render_Data.cpp @@ -14,13 +14,6 @@ Render_Edit_Guard::~Render_Edit_Guard() { data->q_ptr->mark_render_dirty(); data->unmark_state(lease); } -Render_Input_Guard::Render_Input_Guard(Render_Data* data, Triple_Buffer_Lease lease) : data(data), lease(lease) {} -Render_Input_Guard::~Render_Input_Guard() { - if (!data) - return; - data->mark_input_dirty(lease); - data->input_control.unmark_use(lease); -} void Render_Data::mark_input_dirty(Triple_Buffer_Lease lease, bool notify_render) { Input_Buffer_Slot& slot = input_slot_by_index(lease.index); slot.version = ++input_version; @@ -63,12 +56,4 @@ void Render_Data::cancel_pending_completions() { } cancel_update_states(committed_update_states); } -SRC Render_State::src() { - auto view = d_ptr->state_control.read_view(); - for (std::uint8_t role = State_Edit; role <= State_Render; ++role) { - if (d_ptr->state_buffers[view[role]] == this) - return static_cast(role); - } - return SRC::Edit; -} } // namespace renderive diff --git a/Renderive/architecture/Render_Data.h b/Renderive/architecture/Render_Data.h index 0b25384..8c47125 100644 --- a/Renderive/architecture/Render_Data.h +++ b/Renderive/architecture/Render_Data.h @@ -28,30 +28,19 @@ struct Renderable; struct Input_Data { virtual ~Input_Data() = default; virtual void clear() {} - [[nodiscard]] virtual std::uint64_t get_pending_count() const { - return 0; +}; +struct Latest_Input_Data : Input_Data { + bool pending = false; + void mark_latest_pushed() { + pending = true; } - [[nodiscard]] virtual std::uint64_t get_dropped_count() const { - return 0; - } - [[nodiscard]] virtual std::uint64_t get_capacity_dropped_count() const { - return 0; - } - [[nodiscard]] virtual std::uint64_t rebuild_dropped_count() const { - return 0; - } - [[nodiscard]] virtual std::uint64_t consumer_dropped_count() const { - return 0; - } - [[nodiscard]] virtual std::uint64_t get_pushed_count() const { - return 0; + void clear_latest() { + pending = false; } }; struct Render_State { virtual ~Render_State() = default; std::uint64_t version = 0; - Render_Data* d_ptr{}; - SRC src(); }; struct Render_Object_Owner : Move_Only { Render_Object_Owner() noexcept = default; @@ -113,18 +102,11 @@ struct Input_Buffer_Slot { std::shared_ptr completion_state; }; struct Render_Data { - Render_Data() { - state_control.set_stats(&state_buffer_stats); - input_control.set_stats(&input_buffer_stats); - } - Renderable* q_ptr{}; - bool render_start = false; + Renderable* q_ptr{}; Triple_Role_Buffer_Control state_control; - Triple_Buffer_Stats state_buffer_stats; std::array state_buffers{}; std::array state_buffer_owners{}; Triple_Role_Buffer_Control input_control; - Triple_Buffer_Stats input_buffer_stats; std::array input_buffers{}; std::array input_buffer_owners{}; std::pmr::vector> committed_update_states{memory_resource(Memory_Domain::Update_Completion)}; @@ -169,20 +151,6 @@ struct Render_Data { const Input_Buffer_Slot& input_slot_by_index(std::uint8_t index) const { return input_buffers[index]; } - bool has_pending_state() const { - auto view = state_control.read_view(); - return buffer_version_newer(state_buffers[view[State_Edit]]->version, state_buffers[view[State_Render]]->version); - } - bool has_pending_input() const { - auto view = input_control.read_view(); - const Input_Buffer_Slot& edit = input_buffers[view[Input_Edit]]; - const Input_Buffer_Slot& ready = input_buffers[view[Input_Ready]]; - const Input_Buffer_Slot& render = input_buffers[view[Input_Render]]; - return (edit.pending && buffer_version_newer(edit.version, render.version)) || (ready.pending && buffer_version_newer(ready.version, render.version)); - } - bool has_pending_render_data() const { - return has_pending_state() || has_pending_input(); - } void mark_input_dirty(Triple_Buffer_Lease lease, bool notify_render = true); void set_input_completion(Triple_Buffer_Lease lease, std::shared_ptr state); void drain_committed_update_states(std::pmr::vector>& output); @@ -272,10 +240,4 @@ struct LIB_DECL Render_Edit_Guard { Render_Data* data{}; Triple_Buffer_Lease lease{}; }; -struct LIB_DECL Render_Input_Guard { - Render_Input_Guard(Render_Data* data, Triple_Buffer_Lease lease); - ~Render_Input_Guard(); - Render_Data* data{}; - Triple_Buffer_Lease lease{}; -}; } // namespace renderive diff --git a/Renderive/architecture/Render_Lease.h b/Renderive/architecture/Render_Lease.h index a3497eb..a96afb6 100644 --- a/Renderive/architecture/Render_Lease.h +++ b/Renderive/architecture/Render_Lease.h @@ -76,8 +76,6 @@ struct Typed_Render_Data_Base : Base { const Input_Buffer_Slot& render = this->input_slot_by_index(view[Input_Render]); return ready.pending && buffer_version_newer(ready.version, render.version); }); - if (!this->render_start) - this->render_start = true; } }; template @@ -102,6 +100,23 @@ struct Renderable_Binding { return make_render_object(); } }; +#define RENDERIVE_DEFINE_RENDERABLE_BINDING(Owner, Data, State, Input, Name) \ + using Owner##_Binding = ::renderive::Renderable_Binding; \ + Owner::Owner() { \ + Owner##_Binding::init(this, Name); \ + } \ + Data* Owner::d() { \ + return Owner##_Binding::d(this); \ + } \ + ::renderive::Render_Object_Owner Owner::create_render_data() { \ + return Owner##_Binding::create_render_data(); \ + } \ + ::renderive::Render_Object_Owner Owner::create_render_state() { \ + return Owner##_Binding::create_render_state(); \ + } \ + ::renderive::Render_Object_Owner Owner::create_input_data() { \ + return Owner##_Binding::create_input_data(); \ + } template struct Render_State_Lease : Immovable { explicit Render_State_Lease(Data* data) : data(data), lease(data->state_control.wait_mark_use_role(State_Edit)), state(reinterpret_cast(data->state_by_index(lease.index))) {} diff --git a/Renderive/architecture/Render_Pipeline.cpp b/Renderive/architecture/Render_Pipeline.cpp index b1da885..c147b72 100644 --- a/Renderive/architecture/Render_Pipeline.cpp +++ b/Renderive/architecture/Render_Pipeline.cpp @@ -3,14 +3,13 @@ namespace renderive { Renderable::Frame::Frame() : presented_update_states(memory_resource(Memory_Domain::Update_Completion)) {} Renderable::Render_Pipeline::Render_Pipeline() { - color_control.set_stats(&color_buffer_stats); color_control.reset(); } void Renderable::Render_Pipeline::mark_edit_state() { edit_state_version.fetch_add(1, std::memory_order_release); } bool Renderable::Render_Pipeline::has_new_state() const { - return Renderable::version_newer(edit_state_version.load(std::memory_order_acquire), render_state_version); + return buffer_version_newer(edit_state_version.load(std::memory_order_acquire), render_state_version); } Renderable::Frame* Renderable::Render_Pipeline::color_by_index(std::uint8_t index) { return &color_buffers[index]; @@ -41,7 +40,7 @@ Renderable::Render_Pipeline::Frame_Publish_Result Renderable::Render_Pipeline::p Frame* render = color_by_role(Color_Render); Frame* old_ready = color_by_role(Color_Ready); const Frame* front = color_by_role(Color_Front); - bool replace_ready = old_ready->state.load(std::memory_order_acquire) == Frame_State::Ready && Renderable::version_newer(old_ready->version.load(std::memory_order_acquire), front->version.load(std::memory_order_acquire)); + bool replace_ready = old_ready->state.load(std::memory_order_acquire) == Frame_State::Ready && buffer_version_newer(old_ready->version.load(std::memory_order_acquire), front->version.load(std::memory_order_acquire)); if (paint_request_pending.load(std::memory_order_acquire)) { render->metadata.update_request_id = pending_update_request_id.load(std::memory_order_acquire); render->metadata.update_request_time = pending_update_request_time.load(std::memory_order_acquire); @@ -52,7 +51,7 @@ Renderable::Render_Pipeline::Frame_Publish_Result Renderable::Render_Pipeline::p auto swap = color_control.wait_swap_role(Color_Ready, Color_Render, [this](const Triple_Buffer_View& view) { const Frame* render_buffer = color_by_index(view[Color_Render]); const Frame* ready_buffer = color_by_index(view[Color_Ready]); - return Renderable::version_newer(render_buffer->version.load(std::memory_order_acquire), ready_buffer->version.load(std::memory_order_acquire)); + return buffer_version_newer(render_buffer->version.load(std::memory_order_acquire), ready_buffer->version.load(std::memory_order_acquire)); }); if (replace_ready && swap.result == Triple_Buffer_Result::Success) result.superseded_ready = old_ready; @@ -66,7 +65,7 @@ Renderable::Render_Pipeline::Frame_Publish_Result Renderable::Render_Pipeline::r const Frame* front = color_by_role(Color_Front); if (ready->state.load(std::memory_order_acquire) != Frame_State::Ready) return result; - if (!Renderable::version_newer(ready->version.load(std::memory_order_acquire), front->version.load(std::memory_order_acquire))) + if (!buffer_version_newer(ready->version.load(std::memory_order_acquire), front->version.load(std::memory_order_acquire))) return result; if (paint_request_pending.load(std::memory_order_acquire)) { ready->metadata.update_request_id = pending_update_request_id.load(std::memory_order_acquire); @@ -80,7 +79,7 @@ Renderable::Render_Pipeline::Frame_Publish_Result Renderable::Render_Pipeline::r pending_update_request_id.store(result.update_request_id, std::memory_order_release); pending_update_request_time.store(result.update_request_time, std::memory_order_release); paint_request_pending.store(true, std::memory_order_release); - result.region = ready->dirty_region; + result.region = QRegion(QRect(QPoint(0, 0), ready->image.size())); result.request_update = true; return result; } @@ -90,22 +89,20 @@ Renderable::Render_Pipeline::Frame_Consume_Result Renderable::Render_Pipeline::c auto can_swap = [this](const Triple_Buffer_View& view) { const Frame* ready = color_by_index(view[Color_Ready]); const Frame* front = color_by_index(view[Color_Front]); - return ready->state.load(std::memory_order_acquire) == Frame_State::Ready && Renderable::version_newer(ready->version.load(std::memory_order_acquire), front->version.load(std::memory_order_acquire)); + return ready->state.load(std::memory_order_acquire) == Frame_State::Ready && buffer_version_newer(ready->version.load(std::memory_order_acquire), front->version.load(std::memory_order_acquire)); }; Triple_Buffer_Swap_Record swap = color_control.try_swap_role(Color_Front, Color_Ready, can_swap); result.new_frame = swap.result == Triple_Buffer_Result::Success; result.lease = try_front_color(); if (result.new_frame && result.lease) { result.lease.frame->state.store(Frame_State::Consuming, std::memory_order_release); - result.update_request_id = result.lease.frame->metadata.update_request_id; - result.update_request_time = result.lease.frame->metadata.update_request_time; } return result; } bool Renderable::Render_Pipeline::has_ready_frame() const { const Frame* ready = color_by_role(Color_Ready); const Frame* front = color_by_role(Color_Front); - return ready->state.load(std::memory_order_acquire) == Frame_State::Ready && Renderable::version_newer(ready->version.load(std::memory_order_acquire), front->version.load(std::memory_order_acquire)); + return ready->state.load(std::memory_order_acquire) == Frame_State::Ready && buffer_version_newer(ready->version.load(std::memory_order_acquire), front->version.load(std::memory_order_acquire)); } bool Renderable::Render_Pipeline::consumer_busy() const { return color_by_role(Color_Front)->state.load(std::memory_order_acquire) == Frame_State::Consuming; diff --git a/Renderive/architecture/Render_Time.h b/Renderive/architecture/Render_Time.h new file mode 100644 index 0000000..fb5bafe --- /dev/null +++ b/Renderive/architecture/Render_Time.h @@ -0,0 +1,8 @@ +#pragma once +#include +#include +namespace renderive { +inline std::uint64_t steady_now_ns() { + return static_cast(std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count()); +} +} // namespace renderive diff --git a/Renderive/architecture/Renderable.cpp b/Renderive/architecture/Renderable.cpp index 3cc3920..b267f2a 100644 --- a/Renderive/architecture/Renderable.cpp +++ b/Renderive/architecture/Renderable.cpp @@ -1,15 +1,10 @@ #include -#include #include #include "../base/Memory.h" #include "../plot/Plot.h" #include "Renderable.h" +#include "Render_Time.h" namespace renderive { -namespace { -std::uint64_t steady_now_ns() { - return static_cast(std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count()); -} -} Renderable::Frame_Lease::Frame_Lease(Frame* buffer, Triple_Role_Buffer_Control* control, Triple_Buffer_Lease lease) : frame(buffer), control(control), lease(lease) {} Renderable::Frame_Lease::Frame_Lease(Frame_Lease&& other) noexcept : frame(std::exchange(other.frame, nullptr)), control(std::exchange(other.control, nullptr)), lease(std::exchange(other.lease, Triple_Buffer_Lease{})) {} Renderable::Frame_Lease& Renderable::Frame_Lease::operator=(Frame_Lease&& other) noexcept { @@ -40,26 +35,6 @@ void Renderable::set_cache_mode(Renderable_Cache_Mode mode) { cache_dirty.store(true, std::memory_order_release); mark_render_dirty(); } -Renderable::Cache_Status Renderable::cache_status(const Plot_Render_Snapshot& snapshot) { - Cache_Status status; - QSize size = snapshot.size; - status.bounds = d_ptr ? d_ptr->pixel_bounds(size).intersected(QRect(QPoint(0, 0), size)) : QRect(QPoint(0, 0), size); - if (status.bounds.isEmpty()) - return status; - status.valid = true; - status.edit_version = cache_edit_version.load(std::memory_order_acquire); - status.ready_version = cache_ready_version.load(std::memory_order_acquire); - status.image_bytes = cache_image.isNull() ? 0 : static_cast(cache_image.sizeInBytes()); - status.image_area = static_cast(cache_bounds.width()) * static_cast(cache_bounds.height()); - bool shape_ready = cache_image.size() == status.bounds.size() && cache_image.format() == QImage::Format_ARGB32 && cache_bounds == status.bounds; - status.exact_hit = !cache_dirty.load(std::memory_order_acquire) && status.ready_version == status.edit_version && shape_ready; - status.stale_hit = !status.exact_hit && !cache_image.isNull() && cache_bounds == status.bounds; - status.miss = !status.exact_hit && !status.stale_hit; - return status; -} -void Renderable::rebuild_cache_image(const QRect& bounds, const Plot_Render_Snapshot& snapshot, std::uint64_t version) { - render_cache_image(bounds, snapshot, version); -} QString Renderable::cache_parent_object_name() const { std::shared_ptr parent = parent_renderable.lock(); while (parent) { @@ -79,12 +54,6 @@ int Renderable::cache_tree_depth() const { } return depth; } -std::uint64_t Renderable::cache_image_bytes() const { - return cache_image.isNull() ? 0 : static_cast(cache_image.sizeInBytes()); -} -std::uint64_t Renderable::cache_image_area() const { - return static_cast(cache_bounds.width()) * static_cast(cache_bounds.height()); -} QString Renderable::render_parent_object_name() const { if (auto parent = parent_renderable.lock()) return parent->object_name; @@ -146,9 +115,6 @@ void Renderable::init_common(Abs_Plot* plot) { d_ptr->input_buffers[Input_Edit].data = d_ptr->input_buffer_owners[Input_Edit].get(); d_ptr->input_buffers[Input_Ready].data = d_ptr->input_buffer_owners[Input_Ready].get(); d_ptr->input_buffers[Input_Render].data = d_ptr->input_buffer_owners[Input_Render].get(); - for (Render_State* state : d_ptr->state_buffers) { - state->d_ptr = d_ptr; - } d_ptr->q_ptr = this; d_ptr->state_buffers[State_Edit]->version = 1; plot->mark_render_state_dirty(); @@ -242,7 +208,7 @@ void Renderable::render_cached(QPainter* painter, const Plot_Render_Snapshot& sn std::uint64_t rebuild_begin_time = steady_now_ns(); render_cache_image(bounds, snapshot, edit_version); if (snapshot.frame_metadata) - snapshot.frame_metadata->record_renderable_cache_rebuild(object_name, parent_object_name, tree_depth, steady_now_ns() - rebuild_begin_time, cache_image.isNull() ? 0 : static_cast(cache_image.sizeInBytes()), static_cast(bounds.width()) * static_cast(bounds.height()), edit_version, cache_ready_version.load(std::memory_order_acquire), false, true); + snapshot.frame_metadata->record_renderable_cache_rebuild(object_name, parent_object_name, tree_depth, steady_now_ns() - rebuild_begin_time, cache_image.isNull() ? 0 : static_cast(cache_image.sizeInBytes()), static_cast(bounds.width()) * static_cast(bounds.height()), edit_version, cache_ready_version.load(std::memory_order_acquire)); if (!cache_image.isNull()) { std::uint64_t begin_time = steady_now_ns(); painter->drawImage(bounds.topLeft(), cache_image.image()); @@ -268,20 +234,6 @@ void Renderable::render_cache_image(const QRect& bounds, const Plot_Render_Snaps bool dirty = cache_edit_version.load(std::memory_order_acquire) != version; cache_dirty.store(dirty, std::memory_order_release); } -void Renderable::notify_parent_render_dirty() { - if (get_retiring()) - return; - auto context = plot_context.lock(); - if (!context || context->destroying.load(std::memory_order_acquire)) - return; - if (auto parent = parent_renderable.lock()) { - parent->mark_render_dirty(); - return; - } - Abs_Plot* target_plot = context->plot.load(std::memory_order_acquire); - if (!context->destroying.load(std::memory_order_acquire) && target_plot) - target_plot->mark_render_state_dirty(); -} void Renderable::render_self(QPainter* painter, const Plot_Render_Snapshot& snapshot) { if (!d_ptr) return; @@ -361,19 +313,6 @@ void Renderable::wheelEvent(QWheelEvent* event) { return; d_ptr->wheelEvent(event); } -bool Renderable::version_newer(std::uint64_t a, std::uint64_t b) { - return buffer_version_newer(a, b); -} -void Renderable::mark_state_dirty() { - if (get_retiring()) - return; - if (d_ptr) { - auto lease = d_ptr->state_control.wait_mark_use_role(State_Edit); - ++d_ptr->state_by_index(lease.index)->version; - d_ptr->state_control.unmark_use(lease); - } - mark_render_dirty(); -} void Renderable::mark_render_dirty() { if (get_retiring()) return; @@ -392,7 +331,7 @@ void Renderable::mark_render_dirty() { } bool Renderable::ok() const { auto context = plot_context.lock(); - return d_ptr && d_ptr->render_start && !get_retiring() && context && !context->destroying.load(std::memory_order_acquire) && !context->first_resize.load(std::memory_order_acquire) && !context->first_prepare_data.load(std::memory_order_acquire); + return d_ptr && initialized.load(std::memory_order_acquire) && !get_retiring() && context && !context->destroying.load(std::memory_order_acquire) && !context->first_resize.load(std::memory_order_acquire) && !context->first_prepare_data.load(std::memory_order_acquire); } bool Renderable::get_retiring() const { return retiring.load(std::memory_order_acquire); @@ -401,12 +340,12 @@ void Renderable::detach_from_plot_tree() { retiring.store(true, std::memory_order_release); if (d_ptr) d_ptr->cancel_pending_completions(); - std::vector> children = children_snapshot(); + std::vector> children_snapshot_value = children_snapshot(); { std::lock_guard lock(children_mutex); children.clear(); } - for (const auto& child : children) { + for (const auto& child : children_snapshot_value) { if (child) child->detach_from_plot_tree(); } diff --git a/Renderive/architecture/Renderable.h b/Renderive/architecture/Renderable.h index ec959f6..4641cde 100644 --- a/Renderive/architecture/Renderable.h +++ b/Renderive/architecture/Renderable.h @@ -28,10 +28,8 @@ struct Renderable : std::enable_shared_from_this { Frame(); std::atomic version{0}; Pmr_QImage_Buffer image{Memory_Domain::Plot_Frame}; - QRegion dirty_region; std::pmr::vector> presented_update_states; std::atomic state{Frame_State::Free}; - std::uint64_t generation{}; Frame_Lifecycle_Record metadata; }; /// 颜色缓冲占用租约,析构时自动释放底层 busy 标记。 @@ -62,13 +60,10 @@ struct Renderable : std::enable_shared_from_this { }; struct Frame_Consume_Result { Frame_Lease lease; - std::uint64_t update_request_id{}; - std::uint64_t update_request_time{}; bool new_frame{}; bool update_was_pending{}; }; Triple_Role_Buffer_Control color_control; - Triple_Buffer_Stats color_buffer_stats; std::array color_buffers; std::atomic edit_state_version{1}; std::uint64_t render_state_version = 0; @@ -94,17 +89,6 @@ struct Renderable : std::enable_shared_from_this { bool has_ready_frame() const; bool consumer_busy() const; }; - struct Cache_Status { - QRect bounds; - std::uint64_t edit_version{}; - std::uint64_t ready_version{}; - std::uint64_t image_bytes{}; - std::uint64_t image_area{}; - bool valid{}; - bool exact_hit{}; - bool stale_hit{}; - bool miss{}; - }; /// 创建派生对象的私有渲染数据。 virtual Render_Object_Owner create_render_data() { return make_render_object(); @@ -144,20 +128,14 @@ struct Renderable : std::enable_shared_from_this { virtual void resizeEvent(QResizeEvent* event); virtual void wheelEvent(QWheelEvent* event); /// 按三缓冲版本号环绕语义判断 a 是否比 b 新。 - static bool version_newer(std::uint64_t a, std::uint64_t b); /// 当前 Renderable 输出缓存策略。 Renderable_Cache_Mode get_cache_mode() const; void set_cache_mode(Renderable_Cache_Mode mode); - Cache_Status cache_status(const Plot_Render_Snapshot& snapshot); - void rebuild_cache_image(const QRect& bounds, const Plot_Render_Snapshot& snapshot, std::uint64_t version); QString cache_parent_object_name() const; int cache_tree_depth() const; - std::uint64_t cache_image_bytes() const; - std::uint64_t cache_image_area() const; QString render_parent_object_name() const; int render_tree_depth() const; /// 标记 State 缓冲有新版本。 - void mark_state_dirty(); /// 请求父 Plot 调度一次渲染。 void mark_render_dirty(); QString object_name; @@ -167,11 +145,7 @@ struct Renderable : std::enable_shared_from_this { std::weak_ptr parent_renderable; [[nodiscard]] bool ok() const; [[nodiscard]] bool get_retiring() const; - bool prepared = false; virtual ~Renderable(); - virtual bool select(QPointF pos) { - return false; - } bool visible = true; std::vector> children; mutable std::mutex children_mutex; @@ -190,7 +164,6 @@ struct Renderable : std::enable_shared_from_this { void render_self(QPainter* painter, const Plot_Render_Snapshot& snapshot); void render_children(QPainter* painter, const Plot_Render_Snapshot& snapshot); void render_cache_image(const QRect& bounds, const Plot_Render_Snapshot& snapshot, std::uint64_t version); - void notify_parent_render_dirty(); void append_hit_renderables(std::vector>& hits, const QPointF& pos); void detach_from_plot_tree(); }; diff --git a/Renderive/architecture/Timeline_Stream.cpp b/Renderive/architecture/Timeline_Stream.cpp index d55a20e..48a9814 100644 --- a/Renderive/architecture/Timeline_Stream.cpp +++ b/Renderive/architecture/Timeline_Stream.cpp @@ -81,7 +81,6 @@ Timeline_Stream_Snapshot Timeline_Stream::capture() const { snapshot.start_coord_to_end_coord = start_coord_to_end_coord_value; snapshot.lower = lower_value; snapshot.time_point_size = time_point_size_value; - snapshot.tick_space = tick_space_value; snapshot.times.assign(time_buffer.begin(), time_buffer.end()); snapshot.ticks.assign(tick_buffer.begin(), tick_buffer.end()); return snapshot; diff --git a/Renderive/architecture/Timeline_Stream.h b/Renderive/architecture/Timeline_Stream.h index 94c0686..07631cb 100644 --- a/Renderive/architecture/Timeline_Stream.h +++ b/Renderive/architecture/Timeline_Stream.h @@ -15,7 +15,6 @@ struct LIB_DECL Timeline_Stream_Snapshot { bool start_coord_to_end_coord = false; int lower{}; int time_point_size = 1; - int tick_space = 4; std::vector times; std::vector ticks; [[nodiscard]] int upper() const; diff --git a/Renderive/architecture/Triple_Buffer.h b/Renderive/architecture/Triple_Buffer.h index 913bc10..0e706d1 100644 --- a/Renderive/architecture/Triple_Buffer.h +++ b/Renderive/architecture/Triple_Buffer.h @@ -39,28 +39,14 @@ struct Triple_Buffer_Mark_Record { struct Triple_Buffer_Swap_Record { Triple_Buffer_Result result = Triple_Buffer_Result::Condition_Failed; Triple_Buffer_View old_view{}; - Triple_Buffer_View new_view{}; std::uint8_t busy_index = triple_buffer_invalid_index; }; struct alignas(64) Triple_Buffer_Busy { std::atomic_bool busy{false}; }; -struct Triple_Buffer_Stats { - std::atomic mark_success{0}; - std::atomic mark_busy{0}; - std::atomic mark_state_changed{0}; - std::atomic swap_success{0}; - std::atomic swap_busy{0}; - std::atomic swap_state_changed{0}; - std::atomic swap_condition_failed{0}; - std::atomic wait_count{0}; -}; class Triple_Role_Buffer_Control { public: /// 设置性能统计写入目标。 - void set_stats(Triple_Buffer_Stats* value) { - stats = value; - } /// 重置角色映射和全部 busy 标记。 void reset() { slot_state.store(0, std::memory_order_release); @@ -74,42 +60,22 @@ public: return decode_order(slot_state.load(std::memory_order_acquire)); } /// 尝试占用指定物理缓冲。 - Triple_Buffer_Mark_Record try_mark_use_index(std::uint8_t index) { - if (!try_mark_index(index)) { - record_mark(Triple_Buffer_Result::Busy); - return {Triple_Buffer_Result::Busy, {}, index}; - } - record_mark(Triple_Buffer_Result::Success); - return {Triple_Buffer_Result::Success, {index}, triple_buffer_invalid_index}; - } + /// 等待并占用指定物理缓冲。 - Triple_Buffer_Lease wait_mark_use_index(std::uint8_t index) { - for (;;) { - if (try_mark_index(index)) { - record_mark(Triple_Buffer_Result::Success); - return {index}; - } - record_mark(Triple_Buffer_Result::Busy); - record_wait(); - wait_index_free(index); - } - } + /// 尝试占用指定角色当前对应的物理缓冲。 Triple_Buffer_Mark_Record try_mark_use_role(std::uint8_t role) { auto order = slot_state.load(std::memory_order_acquire); auto view = decode_order(order); auto index = view[role]; if (!try_mark_index(index)) { - record_mark(Triple_Buffer_Result::Busy); return {Triple_Buffer_Result::Busy, {}, index}; } auto cur_order = slot_state.load(std::memory_order_acquire); if (cur_order != order) { unmark_index(index); - record_mark(Triple_Buffer_Result::State_Changed); return {Triple_Buffer_Result::State_Changed, {}, triple_buffer_invalid_index}; } - record_mark(Triple_Buffer_Result::Success); return {Triple_Buffer_Result::Success, {index}, triple_buffer_invalid_index}; } /// 等待并占用指定角色当前对应的物理缓冲。 @@ -120,7 +86,6 @@ public: return record.lease; } if (record.result == Triple_Buffer_Result::Busy) { - record_wait(); wait_index_free(record.busy_index); } } @@ -145,11 +110,9 @@ public: return record; } if (record.result == Triple_Buffer_Result::Busy) { - record_wait(); wait_index_free(busy_index); } else { - record_wait(); slot_state.wait(encode_order(record.old_view), std::memory_order_acquire); } } @@ -157,46 +120,6 @@ public: private: std::atomic slot_state{0}; std::array buffer_busy{}; - Triple_Buffer_Stats* stats{}; - void record_mark(Triple_Buffer_Result result) { - if (!stats) - return; - switch (result) { - case Triple_Buffer_Result::Success: - stats->mark_success.fetch_add(1, std::memory_order_relaxed); - break; - case Triple_Buffer_Result::Busy: - stats->mark_busy.fetch_add(1, std::memory_order_relaxed); - break; - case Triple_Buffer_Result::State_Changed: - stats->mark_state_changed.fetch_add(1, std::memory_order_relaxed); - break; - case Triple_Buffer_Result::Condition_Failed: - break; - } - } - void record_swap(Triple_Buffer_Result result) { - if (!stats) - return; - switch (result) { - case Triple_Buffer_Result::Success: - stats->swap_success.fetch_add(1, std::memory_order_relaxed); - break; - case Triple_Buffer_Result::Busy: - stats->swap_busy.fetch_add(1, std::memory_order_relaxed); - break; - case Triple_Buffer_Result::State_Changed: - stats->swap_state_changed.fetch_add(1, std::memory_order_relaxed); - break; - case Triple_Buffer_Result::Condition_Failed: - stats->swap_condition_failed.fetch_add(1, std::memory_order_relaxed); - break; - } - } - void record_wait() { - if (stats) - stats->wait_count.fetch_add(1, std::memory_order_relaxed); - } static Triple_Buffer_View decode_order(std::uint8_t order) { switch (order) { case 0: @@ -279,34 +202,26 @@ private: auto left_index = old_view[left_role]; auto right_index = old_view[right_role]; if (!try_mark_two_indices(left_index, right_index, busy_index)) { - record_swap(Triple_Buffer_Result::Busy); - return {Triple_Buffer_Result::Busy, old_view, old_view, busy_index}; + return {Triple_Buffer_Result::Busy, old_view, busy_index}; } auto cur_order = slot_state.load(std::memory_order_acquire); if (cur_order != old_order) { - auto cur_view = decode_order(cur_order); unmark_two_indices(left_index, right_index); - record_swap(Triple_Buffer_Result::State_Changed); - return {Triple_Buffer_Result::State_Changed, old_view, cur_view, triple_buffer_invalid_index}; + return {Triple_Buffer_Result::State_Changed, old_view, triple_buffer_invalid_index}; } if (!can_swap(old_view)) { unmark_two_indices(left_index, right_index); - record_swap(Triple_Buffer_Result::Condition_Failed); - return {Triple_Buffer_Result::Condition_Failed, old_view, old_view, triple_buffer_invalid_index}; + return {Triple_Buffer_Result::Condition_Failed, old_view, triple_buffer_invalid_index}; } auto new_order = swap_order(old_order, left_role, right_role); - auto new_view = decode_order(new_order); auto expected = old_order; if (!slot_state.compare_exchange_strong(expected, new_order, std::memory_order_acq_rel, std::memory_order_acquire)) { - auto cur_view = decode_order(expected); unmark_two_indices(left_index, right_index); - record_swap(Triple_Buffer_Result::State_Changed); - return {Triple_Buffer_Result::State_Changed, old_view, cur_view, triple_buffer_invalid_index}; + return {Triple_Buffer_Result::State_Changed, old_view, triple_buffer_invalid_index}; } unmark_two_indices(left_index, right_index); slot_state.notify_all(); - record_swap(Triple_Buffer_Result::Success); - return {Triple_Buffer_Result::Success, old_view, new_view, triple_buffer_invalid_index}; + return {Triple_Buffer_Result::Success, old_view, triple_buffer_invalid_index}; } }; } // namespace renderive diff --git a/Renderive/architecture/Update_Completion.h b/Renderive/architecture/Update_Completion.h index e9f3737..15465c4 100644 --- a/Renderive/architecture/Update_Completion.h +++ b/Renderive/architecture/Update_Completion.h @@ -26,7 +26,6 @@ enum class Update_Outcome : std::uint8_t { Cancelled }; using Update_Id = std::uint64_t; -struct Submit_Options {}; class Update_Waiter : Move_Only { public: Update_Waiter() noexcept = default; diff --git a/Renderive/architecture/global.h b/Renderive/architecture/global.h index 6900ab8..fde00ff 100644 --- a/Renderive/architecture/global.h +++ b/Renderive/architecture/global.h @@ -1,5 +1,4 @@ #pragma once -#pragma once #include #include #include @@ -12,6 +11,7 @@ #include #include #include +#include // Q_DECL_IMPORT #ifdef NDEBUG #define ASSERT(condition, message) ((void)0) // 在发布模式下什么都不做 @@ -49,9 +49,6 @@ class Plot; struct LIB_DECL Range { double origin; double target; - double center() { - return (origin + target) / 2.0; - } [[nodiscard]] double size() const { return qAbs(target - origin); } @@ -86,6 +83,20 @@ enum class LIB_DECL SRC : std::uint8_t { #define PROP(Type, Name) \ Type Name(SRC src = SRC::Edit); \ void set_##Name(Type); +#define RENDERIVE_DEFINE_STATE_PROP(Owner, State, Type, Field) \ + Type Owner::Field(SRC src) { \ + return d()->state_value(&State::Field, src); \ + } \ + void Owner::set_##Field(Type value) { \ + d()->set_state_value(&State::Field, std::move(value)); \ + } +#define RENDERIVE_DEFINE_WEAK_STATE_PROP(Owner, State, Pointee, Field) \ + std::shared_ptr Owner::Field(SRC src) { \ + return d()->state_value(&State::Field, src).lock(); \ + } \ + void Owner::set_##Field(std::shared_ptr value) { \ + d()->set_state_value(&State::Field, std::weak_ptr(value)); \ + } #define PROP_B(TYPE, FIELD) \ public: \ Builder& set_##FIELD(TYPE value) { \ @@ -100,36 +111,6 @@ public: \ } #define PROP_R(TYPE, FIELD) sc->FIELD = this->FIELD; #define PROP_RT(TYPE, FIELD) sc->FIELD = static_cast(this)->FIELD; -#define SETTER_T(TYPE, FIELD, DEFAULT) \ -private: \ - TYPE FIELD = DEFAULT; \ -public: \ - That& set_##FIELD(TYPE value) { \ - static_cast(this)->FIELD = value; \ - return *static_cast(this); \ - } -#define SETTER_2_RANGE_T(bits, FIELD, DEFAULT) \ -private: \ - int FIELD = DEFAULT; \ -public: \ - T& set_##FIELD(int value) { \ - if (value < 0 || value >= (1 << bits)) { \ - throw std::out_of_range("Value out of range: " #FIELD); \ - } \ - static_cast(this)->FIELD = value; \ - return *static_cast(this); \ - } -#define SETTER_RANGE_T(lower, upper, FIELD, DEFAULT) \ -private: \ - int FIELD = DEFAULT; \ -public: \ - Builder& set_##FIELD(int value) { \ - if (value < lower || value > upper) { \ - throw std::out_of_range("Value out of range: " #FIELD); \ - } \ - static_cast(this)->FIELD = value; \ - return *static_cast(this); \ - } #define SETTER(TYPE, FIELD, DEFAULT) \ \ TYPE FIELD = DEFAULT; \ @@ -138,15 +119,5 @@ public: \ this->FIELD = std::move(value); \ return *this; \ } -namespace renderive { -template -constexpr const T& clamp(const T& v, const T& lo, const T& hi) { - return (v < lo) - ? lo - : (v > hi) - ? hi - : v; -} -} // namespace renderive #undef min #undef max diff --git a/Renderive/base/Frame_Memory.cpp b/Renderive/base/Frame_Memory.cpp index 6b583b4..08d0ca5 100644 --- a/Renderive/base/Frame_Memory.cpp +++ b/Renderive/base/Frame_Memory.cpp @@ -1,26 +1,12 @@ #include "Frame_Memory.h" #include "Memory.h" #include -#include #include #include namespace renderive { namespace { constexpr std::size_t Frame_Arena_Min_Size = 64 * 1024; constexpr std::size_t Frame_Arena_Max_Retained_Size = 64 * 1024 * 1024; -struct Frame_Global_Stats { - std::atomic frame_count{}; - std::atomic overflow_count{}; - std::atomic overflow_bytes{}; - std::atomic high_water_bytes{}; - std::atomic scratch_grow_count{}; - std::atomic scratch_bytes{}; -}; -Frame_Global_Stats frame_global_stats; -void update_peak(std::atomic& target, std::uint64_t value) { - std::uint64_t peak = target.load(std::memory_order_relaxed); - while (peak < value && !target.compare_exchange_weak(peak, value, std::memory_order_relaxed)) {} -} } struct Thread_Frame_Scratch; class Frame_Overflow_Resource final : public std::pmr::memory_resource { @@ -38,7 +24,6 @@ struct Thread_Frame_Scratch { Thread_Frame_Scratch() { storage.resize(Frame_Arena_Min_Size); desired_size = Frame_Arena_Min_Size; - frame_global_stats.scratch_bytes.fetch_add(storage.size(), std::memory_order_relaxed); } std::pmr::memory_resource* overflow_upstream() { if (!overflow_pool) @@ -52,16 +37,11 @@ struct Thread_Frame_Scratch { target_size = std::max(target_size, Frame_Arena_Min_Size); target_size = std::min(target_size, Frame_Arena_Max_Retained_Size); if (storage.size() < target_size) { - std::size_t old_size = storage.size(); storage.resize(target_size); - frame_global_stats.scratch_bytes.fetch_add(storage.size() - old_size, std::memory_order_relaxed); - frame_global_stats.scratch_grow_count.fetch_add(1, std::memory_order_relaxed); } } void finish_frame() { - frame_global_stats.frame_count.fetch_add(1, std::memory_order_relaxed); std::uint64_t frame_bytes = static_cast(storage.size() + frame_overflow_bytes); - update_peak(frame_global_stats.high_water_bytes, frame_bytes); #if RENDERIVE_FRAME_ARENA_GROW if (frame_overflow_bytes) { std::size_t next_size = static_cast(frame_bytes + frame_bytes / 8 + 4096); @@ -82,8 +62,6 @@ struct Thread_Frame_Scratch { void* Frame_Overflow_Resource::do_allocate(std::size_t size, std::size_t alignment) { scratch->frame_overflow_count += 1; scratch->frame_overflow_bytes += size; - frame_global_stats.overflow_count.fetch_add(1, std::memory_order_relaxed); - frame_global_stats.overflow_bytes.fetch_add(size, std::memory_order_relaxed); return scratch->overflow_upstream()->allocate(size, alignment); } void Frame_Overflow_Resource::do_deallocate(void* address, std::size_t size, std::size_t alignment) { @@ -123,14 +101,4 @@ std::pmr::memory_resource* Frame_Arena::resource() noexcept { std::pmr::memory_resource* frame_memory_resource() { return current_frame_resource ? current_frame_resource : memory_resource(); } -Frame_Memory_Stats frame_memory_stats() noexcept { - Frame_Memory_Stats result; - result.frame_count = frame_global_stats.frame_count.load(std::memory_order_relaxed); - result.overflow_count = frame_global_stats.overflow_count.load(std::memory_order_relaxed); - result.overflow_bytes = frame_global_stats.overflow_bytes.load(std::memory_order_relaxed); - result.high_water_bytes = frame_global_stats.high_water_bytes.load(std::memory_order_relaxed); - result.scratch_grow_count = frame_global_stats.scratch_grow_count.load(std::memory_order_relaxed); - result.scratch_bytes = frame_global_stats.scratch_bytes.load(std::memory_order_relaxed); - return result; -} } diff --git a/Renderive/base/Frame_Memory.h b/Renderive/base/Frame_Memory.h index f830889..2e5180a 100644 --- a/Renderive/base/Frame_Memory.h +++ b/Renderive/base/Frame_Memory.h @@ -9,14 +9,6 @@ #define RENDERIVE_FRAME_ARENA_GROW 1 #endif namespace renderive { -struct Frame_Memory_Stats { - std::uint64_t frame_count{}; - std::uint64_t overflow_count{}; - std::uint64_t overflow_bytes{}; - std::uint64_t high_water_bytes{}; - std::uint64_t scratch_grow_count{}; - std::uint64_t scratch_bytes{}; -}; struct Thread_Frame_Scratch; class LIB_DECL Frame_Arena : Immovable { public: @@ -29,5 +21,4 @@ private: std::optional arena; }; LIB_DECL std::pmr::memory_resource* frame_memory_resource(); -LIB_DECL Frame_Memory_Stats frame_memory_stats() noexcept; } diff --git a/Renderive/base/Object_Semantics.h b/Renderive/base/Object_Semantics.h index 31ca971..7ae82ea 100644 --- a/Renderive/base/Object_Semantics.h +++ b/Renderive/base/Object_Semantics.h @@ -1,14 +1,5 @@ #pragma once namespace renderive { -class Copyable_Movable { -protected: - Copyable_Movable() = default; - Copyable_Movable(const Copyable_Movable&) = default; - Copyable_Movable& operator=(const Copyable_Movable&) = default; - Copyable_Movable(Copyable_Movable&&) noexcept = default; - Copyable_Movable& operator=(Copyable_Movable&&) noexcept = default; - ~Copyable_Movable() = default; -}; class Move_Only { protected: Move_Only() = default; @@ -27,13 +18,4 @@ protected: Immovable& operator=(Immovable&&) = delete; ~Immovable() = default; }; -class Copy_Only { -protected: - Copy_Only() = default; - Copy_Only(const Copy_Only&) = default; - Copy_Only& operator=(const Copy_Only&) = default; - Copy_Only(Copy_Only&&) = delete; - Copy_Only& operator=(Copy_Only&&) = delete; - ~Copy_Only() = default; -}; } diff --git a/Renderive/base/Pmr_QImage_Buffer.h b/Renderive/base/Pmr_QImage_Buffer.h index 16e2439..f63376d 100644 --- a/Renderive/base/Pmr_QImage_Buffer.h +++ b/Renderive/base/Pmr_QImage_Buffer.h @@ -12,18 +12,6 @@ #include #include "Memory.h" namespace renderive { -struct Pmr_QImage_Stats { - std::uint64_t reset_count{}; - std::uint64_t allocated_bytes{}; - std::uint64_t detach_count{}; - std::uint64_t detach_bytes{}; -}; -namespace pmr_qimage_detail { -inline std::atomic reset_count{}; -inline std::atomic allocated_bytes{}; -inline std::atomic detach_count{}; -inline std::atomic detach_bytes{}; -} class Pmr_QImage_Buffer { public: explicit Pmr_QImage_Buffer(Memory_Domain domain = Memory_Domain::Image) : domain(domain) {} @@ -154,10 +142,6 @@ private: auto* cleanup_owner = create_pixel_buffer_owner(domain, buffer); image_data = QImage(buffer->data, width, height, bytes_per_line, format, cleanup_pixel_buffer, cleanup_owner); pixel_buffer = std::move(buffer); -#if RENDERIVE_MEMORY_DOMAIN_STATS - pmr_qimage_detail::reset_count.fetch_add(1, std::memory_order_relaxed); - pmr_qimage_detail::allocated_bytes.fetch_add(bytes, std::memory_order_relaxed); -#endif } void detach_for_write() { if (image_data.isNull() || image_data.isDetached()) @@ -166,23 +150,9 @@ private: std::size_t bytes = static_cast(old_image.sizeInBytes()); reset_image(old_image.width(), old_image.height(), old_image.format()); std::memcpy(image_data.bits(), old_image.constBits(), bytes); -#if RENDERIVE_MEMORY_DOMAIN_STATS - pmr_qimage_detail::detach_count.fetch_add(1, std::memory_order_relaxed); - pmr_qimage_detail::detach_bytes.fetch_add(bytes, std::memory_order_relaxed); -#endif } std::shared_ptr pixel_buffer; QImage image_data; Memory_Domain domain; }; -inline Pmr_QImage_Stats pmr_qimage_stats() noexcept { - Pmr_QImage_Stats result; -#if RENDERIVE_MEMORY_DOMAIN_STATS - result.reset_count = pmr_qimage_detail::reset_count.load(std::memory_order_relaxed); - result.allocated_bytes = pmr_qimage_detail::allocated_bytes.load(std::memory_order_relaxed); - result.detach_count = pmr_qimage_detail::detach_count.load(std::memory_order_relaxed); - result.detach_bytes = pmr_qimage_detail::detach_bytes.load(std::memory_order_relaxed); -#endif - return result; -} } diff --git a/Renderive/base/Task.h b/Renderive/base/Task.h index 3aaa528..e0ffb6d 100644 --- a/Renderive/base/Task.h +++ b/Renderive/base/Task.h @@ -9,20 +9,6 @@ #include "Memory.h" #include "Object_Semantics.h" namespace renderive { -struct Task_Stats { - std::uint64_t sizeof_task{}; - std::uint64_t inline_size{}; - std::uint64_t total_count{}; - std::uint64_t inline_count{}; - std::uint64_t heap_count{}; - std::uint64_t heap_bytes{}; -}; -namespace task_detail { -inline std::atomic total_count{}; -inline std::atomic inline_count{}; -inline std::atomic heap_count{}; -inline std::atomic heap_bytes{}; -} class Task : Move_Only { public: static constexpr std::size_t Inline_Size = 64; @@ -37,9 +23,6 @@ public: object = inline_storage(); std::construct_at(static_cast(object), std::forward(callable)); inline_object = true; -#if RENDERIVE_MEMORY_DOMAIN_STATS - task_detail::inline_count.fetch_add(1, std::memory_order_relaxed); -#endif } else { resource = memory_resource(Memory_Domain::Scheduler_Task); @@ -54,14 +37,7 @@ public: resource = nullptr; throw; } -#if RENDERIVE_MEMORY_DOMAIN_STATS - task_detail::heap_count.fetch_add(1, std::memory_order_relaxed); - task_detail::heap_bytes.fetch_add(sizeof(Model), std::memory_order_relaxed); -#endif } -#if RENDERIVE_MEMORY_DOMAIN_STATS - task_detail::total_count.fetch_add(1, std::memory_order_relaxed); -#endif invoke_function = &invoke; destroy_function = &destroy; move_function = &move; @@ -152,16 +128,4 @@ private: void (*move_function)(void*, void*){}; bool inline_object{}; }; -inline Task_Stats task_stats() noexcept { - Task_Stats result; - result.sizeof_task = sizeof(Task); - result.inline_size = Task::Inline_Size; -#if RENDERIVE_MEMORY_DOMAIN_STATS - result.total_count = task_detail::total_count.load(std::memory_order_relaxed); - result.inline_count = task_detail::inline_count.load(std::memory_order_relaxed); - result.heap_count = task_detail::heap_count.load(std::memory_order_relaxed); - result.heap_bytes = task_detail::heap_bytes.load(std::memory_order_relaxed); -#endif - return result; -} } diff --git a/Renderive/base/global.cpp b/Renderive/base/global.cpp index e4e6cf1..05e2034 100644 --- a/Renderive/base/global.cpp +++ b/Renderive/base/global.cpp @@ -20,6 +20,9 @@ Render_Scheduler::Render_Scheduler() : d(std::make_uniqued; - data->render_context->render_width.store(data->pending_render_width.load(std::memory_order_acquire), std::memory_order_release); - data->render_context->render_height.store(data->pending_render_height.load(std::memory_order_acquire), std::memory_order_release); + data->render_context->render_width.store(plot->size().width(), std::memory_order_release); + data->render_context->render_height.store(plot->size().height(), std::memory_order_release); if (plot->isVisible()) { data->render_enabled.store(true, std::memory_order_release); data->on_render_started(); diff --git a/Renderive/base/global.h b/Renderive/base/global.h index 80d658a..94ba043 100644 --- a/Renderive/base/global.h +++ b/Renderive/base/global.h @@ -33,11 +33,9 @@ private: }; class LIB_DECL Global : public QObject, public Psc::Singleton { public: - int r = qInitResources_resource(); - int interval = 10; + Global(); Render_Scheduler& render_scheduler(); void start_render_scheduler(); - std::vector color_map = get_turbo_color_gradient(); private: Render_Scheduler render_scheduler_value; }; diff --git a/Renderive/export.cpp b/Renderive/export.cpp deleted file mode 100644 index 2991100..0000000 --- a/Renderive/export.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "export.h" -#include -#include -Screen_Info get_screen_info() { - Screen_Info info; -#if QT_VERSION >= QT_VERSION_CHECK(5, 3, 0) - // Qt5.3+ / Qt6 - QScreen* screen = QGuiApplication::primaryScreen(); - if (!screen) - return info; - info.full_size = screen->geometry().size(); - info.available_size = screen->availableGeometry().size(); -#elif QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) - // Qt5 早期版本 - QDesktopWidget* desktop = QApplication::desktop(); - if (!desktop) - return info; - info.full_size = desktop->screenGeometry().size(); - info.available_size = desktop->availableGeometry().size(); -#else - // Qt4 - QDesktopWidget* desktop = QApplication::desktop(); - if (!desktop) - return info; - info.full_size = desktop->screenGeometry().size(); - info.available_size = desktop->availableGeometry().size(); -#endif - return info; -} diff --git a/Renderive/export.h b/Renderive/export.h index 2b1ec16..373db98 100644 --- a/Renderive/export.h +++ b/Renderive/export.h @@ -1,12 +1,6 @@ #pragma once #include "Axis/export.h" -#include "Generate_Mock_Data.h" #include "architecture/export.h" #include "base/Memory.h" #include "plottable/export.h" #include "primitive/export.h" -struct Screen_Info { - QSize full_size; - QSize available_size; -}; -Screen_Info get_screen_info(); diff --git a/Renderive/main.cpp b/Renderive/main.cpp deleted file mode 100644 index 61fc3fa..0000000 --- a/Renderive/main.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include -#include -#ifdef _WINDOWS -#include -#include -#include -#endif -#include -#include -#include -#include "../Demo_Gallery/export.h" -#include "Generate_Mock_Data.h" -#include "base/Graphic.h" -#include "base/Select_Color_Dialog/Select_Color_Dialog.h" -#include "component/Button.h" -#include "component/simple_widget.h" -#include "plottable/Afterglow.h" -#include "plottable/Planisphere.h" -#include "plottable/Planisphere_p.h" -#include "plottable/Spectrum.h" -#include "plottable/Spectrum_p.h" -#include "plottable/Waterfall.h" -#include "plottable/Waterfall_p.h" -class Temp : public QWidget { -public: - Temp() { - setFixedSize(400, 400); - image.load("D:/wyc/projects/CLionProjects/plantSunCat/mainProjects/YSGraphic/src/img.png"); - } - QImage image; -public: - void paintEvent(QPaintEvent* event) override { - QPainter painter(this); - double w = width(); - double h = height(); - painter.scale(1.5, 1); - painter.drawImage(QRectF(100, 100, 100, 100), image); - painter.end(); - } -}; -#ifdef _build_exe -int main(int argc, char* argv[]) { - QApplication app(argc, argv); - QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8")); -#ifdef _WINDOWS - SetConsoleOutputCP(CP_UTF8); - system("chcp 65001"); -#endif - Button btn; - btn.show(); - return QApplication::exec(); -} -#endif diff --git a/Renderive/plot/Explicit_Plot.cpp b/Renderive/plot/Explicit_Plot.cpp index 8f05a50..04d4d7f 100644 --- a/Renderive/plot/Explicit_Plot.cpp +++ b/Renderive/plot/Explicit_Plot.cpp @@ -1,12 +1,7 @@ #include "Explicit_Plot_p.h" -#include +#include "../architecture/Render_Time.h" #include "Plot_p.h" namespace renderive { -namespace { -std::uint64_t steady_now_ns() { - return static_cast(std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count()); -} -} Explicit_Plot::Explicit_Plot() : Abs_Plot(new Explicit_Plot_Private(this)) {} void Explicit_Plot::replot() { auto data = static_cast(d); diff --git a/Renderive/plot/Latency_Eager_Plot.cpp b/Renderive/plot/Latency_Eager_Plot.cpp index ab26148..b65c385 100644 --- a/Renderive/plot/Latency_Eager_Plot.cpp +++ b/Renderive/plot/Latency_Eager_Plot.cpp @@ -1,12 +1,8 @@ #include "Latency_Eager_Plot_p.h" #include +#include "../architecture/Render_Time.h" #include "../base/global.h" namespace renderive { -namespace { -std::uint64_t steady_now_ns() { - return static_cast(std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count()); -} -} Latency_Eager_Plot::Latency_Eager_Plot() : Abs_Plot(new Latency_Eager_Plot_Private(this)) {} double Latency_Eager_Plot::get_max_render_fps() const { auto data = static_cast(d); diff --git a/Renderive/plot/Plot.cpp b/Renderive/plot/Plot.cpp index dcedc8a..a8381a9 100644 --- a/Renderive/plot/Plot.cpp +++ b/Renderive/plot/Plot.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include @@ -16,22 +15,14 @@ #include "../base/Memory.h" #include "../base/Task.h" #include "../base/global.h" -#include "../plottable/Performance_Shower_p.h" +#include "../architecture/Render_Time.h" #include "Plot_p.h" #include "../architecture/Update_Completion.h" namespace renderive { namespace { -std::uint64_t steady_now_ns() { - return static_cast(std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count()); -} int renderable_prepare_priority(const std::shared_ptr& able) { return dynamic_cast(able.get()) ? 0 : 1; } -std::shared_ptr performance_shower_owner(Abs_Plot_Private* data) { - if (!data || !data->render_context) - return {}; - return std::atomic_load_explicit(&data->render_context->performance_shower_value, std::memory_order_acquire); -} std::size_t estimate_frame_memory(const std::vector>& snapshot, const Plot_Render_Snapshot& frame_snapshot) { std::size_t bytes = 64 * 1024; for (const auto& able : snapshot) { @@ -80,12 +71,9 @@ void Abs_Plot_Private::finish_render_task() { if (active_render_tasks.fetch_sub(1, std::memory_order_acq_rel) == 1) render_task_done.notify_all(); } -int Abs_Plot_Private_Access::active_render_tasks(const Abs_Plot& plot) { - return plot.d->active_render_tasks.load(std::memory_order_acquire); -} Abs_Plot::Abs_Plot(Abs_Plot_Private* private_data) : d(private_data) { d->render_context = renderive::make_shared(); - d->render_context->background_rgba.store(d->background.rgba(), std::memory_order_release); + d->render_context->background_rgba.store(QColor(Qt::black).rgba(), std::memory_order_release); d->render_context->plot.store(this, std::memory_order_release); setAttribute(Qt::WA_OpaquePaintEvent, true); setMouseTracking(true); @@ -111,7 +99,7 @@ Abs_Plot::~Abs_Plot() { if (d->root_renderable) d->root_renderable->detach_from_plot_tree(); d->root_renderable.reset(); - std::atomic_store_explicit(&d->render_context->performance_shower_value, std::shared_ptr{}, std::memory_order_release); + std::atomic_store_explicit(&d->render_context->frame_lifecycle_observer, std::shared_ptr{}, std::memory_order_release); d->render_context.reset(); delete d; } @@ -123,30 +111,15 @@ void Abs_Plot::init_renderable_tree() { d->root_renderable->object_name = "Root_Renderable"; d->root_renderable->init_root(this); } -bool Abs_Plot::get_use_performance_shower() { - auto shower = performance_shower_owner(d); - return shower && shower->enabled(); -} -void Abs_Plot::set_use_performance_shower(bool use) { - auto shower = performance_shower_owner(d); - if (!shower && use) { - auto created_shower = renderive::make_shared(); - created_shower->init(d->root_renderable); - std::atomic_store_explicit(&d->render_context->performance_shower_value, created_shower, std::memory_order_release); - } - shower = performance_shower_owner(d); - if (shower) - shower->setEnabled(use); -} void Abs_Plot::remove_renderable(const std::shared_ptr& able) { if (!able || able->plot != this || able == d->root_renderable) return; std::shared_ptr parent = able->parent_renderable.lock(); if (parent) parent->remove_child(able); - auto shower = std::atomic_load_explicit(&d->render_context->performance_shower_value, std::memory_order_acquire); - if (shower.get() == able.get()) - std::atomic_store_explicit(&d->render_context->performance_shower_value, std::shared_ptr{}, std::memory_order_release); + auto observer = std::atomic_load_explicit(&d->render_context->frame_lifecycle_observer, std::memory_order_acquire); + if (observer && observer->renderable() == able.get()) + std::atomic_store_explicit(&d->render_context->frame_lifecycle_observer, std::shared_ptr{}, std::memory_order_release); mark_render_state_dirty(); } std::shared_ptr Abs_Plot::get_render_context() const { @@ -168,13 +141,13 @@ std::shared_ptr Abs_Plot::create_renderable_node(const std::shared_p bool Abs_Plot::is_rendering() { return d->render_enabled.load(std::memory_order_acquire); } -void Abs_Plot::start_render() const { +void Abs_Plot::start_render() { if (d->destroying.load(std::memory_order_acquire)) return; d->render_enabled.store(true, std::memory_order_release); d->on_render_started(); } -void Abs_Plot::pause_render() const { +void Abs_Plot::pause_render() { d->render_enabled.store(false, std::memory_order_release); if (d->destroying.load(std::memory_order_acquire)) return; @@ -183,10 +156,9 @@ void Abs_Plot::pause_render() const { QColor Abs_Plot::background_color() { return QColor::fromRgba(d->render_context->background_rgba.load(std::memory_order_acquire)); } -void Abs_Plot::set_background_color(const QColor& color) const { - d->background = color; +void Abs_Plot::set_background_color(const QColor& color) { d->render_context->background_rgba.store(color.rgba(), std::memory_order_release); - const_cast(this)->mark_render_state_dirty(); + mark_render_state_dirty(); } void Abs_Plot::mark_render_state_dirty() { if (d->destroying.load(std::memory_order_acquire)) @@ -195,8 +167,6 @@ void Abs_Plot::mark_render_state_dirty() { d->pipeline.mark_edit_state(); d->latest_input_time_ns.store(now_ns, std::memory_order_release); d->pending_input_count.fetch_add(1, std::memory_order_relaxed); - std::uint64_t expected = 0; - d->pending_input_begin_time_ns.compare_exchange_strong(expected, now_ns, std::memory_order_acq_rel, std::memory_order_acquire); d->on_render_state_dirty(now_ns); } void Abs_Plot::paintEvent(QPaintEvent* event) { @@ -242,7 +212,7 @@ void Abs_Plot_Private::paint_event(QPaintEvent* event) { presented_update_states = std::move(consumed.lease.frame->presented_update_states); } else { - painter.fillRect(q->rect(), background); + painter.fillRect(q->rect(), QColor::fromRgba(render_context->background_rgba.load(std::memory_order_acquire))); } painter.end(); complete_update_states(presented_update_states, Update_Stage::Presented); @@ -313,23 +283,17 @@ bool Abs_Plot_Private::submit_render_once(std::uint64_t render_request_time) { return false; } supersede_update_states(color->presented_update_states); - ++color->generation; color->metadata = {}; Frame_Lifecycle_Record& frame = color->metadata; std::uint64_t submit_time = steady_now_ns(); frame.frame_id = ++next_frame_id; frame.input_version = pipeline.edit_state_version.load(std::memory_order_acquire); - frame.snapshot_version = frame.input_version; - frame.frame_slot_generation = color->generation; + frame.frame_slot_generation = frame.frame_id; frame.render_request_time = render_request_time; frame.core_data_time = latest_input_time_ns.load(std::memory_order_acquire); - frame.source_data_time_begin = pending_input_begin_time_ns.exchange(0, std::memory_order_acq_rel); - frame.source_data_time_end = frame.core_data_time; frame.raw_input_count = pending_input_count.exchange(0, std::memory_order_acq_rel); - frame.visible_input_count = frame.raw_input_count; frame.pixel_width = static_cast(frame_snapshot->size.width()); frame.pixel_height = static_cast(frame_snapshot->size.height()); - frame.snapshot_capture_begin_time = submit_time; color->state.store(Frame_State::Producing, std::memory_order_release); pipeline.job_state = Renderable::Job_State::Queued; pipeline.render_state_version = frame.input_version; @@ -338,7 +302,6 @@ bool Abs_Plot_Private::submit_render_once(std::uint64_t render_request_time) { std::stable_sort(snapshot.begin(), snapshot.end(), [](const auto& a, const auto& b) { return renderable_prepare_priority(a) < renderable_prepare_priority(b); }); - frame.snapshot_capture_end_time = steady_now_ns(); frame_snapshot->frame_metadata = &frame; std::pmr::vector> frame_update_states(memory_resource(Memory_Domain::Update_Completion)); frame.prepare_begin_time = steady_now_ns(); @@ -350,10 +313,7 @@ bool Abs_Plot_Private::submit_render_once(std::uint64_t render_request_time) { ++frame.prepared_output_count; } frame.prepare_end_time = steady_now_ns(); - if (q->first_prepare_data) { - q->first_prepare_data = false; - render_context->first_prepare_data.store(false, std::memory_order_release); - } + render_context->first_prepare_data.exchange(false, std::memory_order_acq_rel); std::size_t frame_memory_hint = estimate_frame_memory(snapshot, *frame_snapshot); struct Render_Color_Task_Context { Abs_Plot_Private* private_data{}; @@ -453,9 +413,11 @@ void Abs_Plot_Private::report_consumer_underrun() { }); } void Abs_Plot_Private::collect_returned_frame(Frame_Lifecycle_Record& frame) { - auto shower = performance_shower_owner(this); - if (shower && shower->enabled()) - shower->collect_frame(frame); + if (!render_context) + return; + auto observer = std::atomic_load_explicit(&render_context->frame_lifecycle_observer, std::memory_order_acquire); + if (observer && observer->enabled()) + observer->collect_frame(frame); } void Abs_Plot_Private::request_update(const QRegion& region) { QMetaObject::invokeMethod(q, [this, region]() { @@ -492,7 +454,6 @@ void Abs_Plot_Private::render_color(Renderable::Frame* color, const std::shared_ frame.draw_end_time = steady_now_ns(); frame.render_end_time = steady_now_ns(); color->version.store(frame.frame_id, std::memory_order_release); - color->dirty_region = QRegion(QRect(QPoint(0, 0), size)); for (auto& state : update_states) { if (state) state->complete_until(Update_Stage::Rendered); @@ -504,11 +465,9 @@ bool Abs_Plot_Private::event(QEvent* event, bool base_result) { case QEvent::Resize: { auto resize_event = static_cast(event); QSize new_render_size = resize_event->size(); - pending_render_width.store(new_render_size.width(), std::memory_order_release); - pending_render_height.store(new_render_size.height(), std::memory_order_release); render_context->render_width.store(new_render_size.width(), std::memory_order_release); render_context->render_height.store(new_render_size.height(), std::memory_order_release); - if (q->first_resize) { + if (render_context->first_resize.exchange(false, std::memory_order_acq_rel)) { auto snapshot = renderable_snapshot(); for (const auto& able : snapshot) able->first_resize_event(resize_event); @@ -518,9 +477,6 @@ bool Abs_Plot_Private::event(QEvent* event, bool base_result) { for (const auto& able : snapshot) able->resizeEvent(resize_event); } - if (q->first_resize) - q->first_resize = false; - render_context->first_resize.store(false, std::memory_order_release); q->mark_render_state_dirty(); break; } diff --git a/Renderive/plot/Plot.h b/Renderive/plot/Plot.h index cc9a76a..e364a80 100644 --- a/Renderive/plot/Plot.h +++ b/Renderive/plot/Plot.h @@ -13,23 +13,19 @@ class Explicit_Plot; class LIB_DECL Abs_Plot : public QWidget { Q_OBJECT public: - bool get_use_performance_shower(); - void set_use_performance_shower(bool use); virtual void init(); QColor background_color(); [[nodiscard]] std::shared_ptr get_render_context() const; [[nodiscard]] std::shared_ptr get_root_renderable() const; [[nodiscard]] std::shared_ptr create_renderable_node(const std::shared_ptr& parent, const QString& object_name = {}) const; - bool first_resize = true; - bool first_prepare_data = true; QString object_name; - void set_background_color(const QColor& color) const; + void set_background_color(const QColor& color); void mark_render_state_dirty(); void remove_renderable(const std::shared_ptr& able); virtual void init_renderable_tree(); bool is_rendering(); - void start_render() const; - void pause_render() const; + void start_render(); + void pause_render(); ~Abs_Plot() override; explicit Abs_Plot(Abs_Plot_Private* private_data); Abs_Plot_Private* d{}; diff --git a/Renderive/plot/Plot_p.h b/Renderive/plot/Plot_p.h index 1f984f1..c0ea279 100644 --- a/Renderive/plot/Plot_p.h +++ b/Renderive/plot/Plot_p.h @@ -24,13 +24,9 @@ struct Abs_Plot_Private { std::atomic_int active_render_tasks{0}; std::condition_variable render_task_done; std::mutex render_task_mutex; - std::atomic_int pending_render_width{0}; - std::atomic_int pending_render_height{0}; std::atomic latest_input_time_ns{0}; - std::atomic pending_input_begin_time_ns{0}; std::atomic pending_input_count{0}; Renderable::Render_Pipeline pipeline; - QColor background = Qt::black; std::uint64_t next_frame_id{}; void add_render_task(); void finish_render_task(); @@ -57,7 +53,4 @@ struct Abs_Plot_Private { virtual void try_schedule_render() = 0; static void render_color(Renderable::Frame* color, const std::shared_ptr& root, const Renderable_Snapshot& snapshot, const Plot_Render_Snapshot& render_snapshot_data, std::pmr::vector>&& update_states); }; -struct Abs_Plot_Private_Access { - static int active_render_tasks(const Abs_Plot& plot); -}; } // namespace renderive diff --git a/Renderive/plottable/Afterglow.cpp b/Renderive/plottable/Afterglow.cpp index 4d34a6f..3687c67 100644 --- a/Renderive/plottable/Afterglow.cpp +++ b/Renderive/plottable/Afterglow.cpp @@ -3,22 +3,7 @@ #include "../base/Frame_Memory.h" #include "../base/Memory.h" namespace renderive { -using Afterglow_Binding = Renderable_Binding; -Afterglow::Afterglow() { - Afterglow_Binding::init(this, "Afterglow"); -} -Afterglow_Private* Afterglow::d() { - return Afterglow_Binding::d(this); -} -Render_Object_Owner Afterglow::create_render_data() { - return Afterglow_Binding::create_render_data(); -} -Render_Object_Owner Afterglow::create_render_state() { - return Afterglow_Binding::create_render_state(); -} -Render_Object_Owner Afterglow::create_input_data() { - return Afterglow_Binding::create_input_data(); -} +RENDERIVE_DEFINE_RENDERABLE_BINDING(Afterglow, Afterglow_Private, Afterglow_Render_State, Afterglow_Input_Data, "Afterglow") std::shared_ptr Afterglow::frequency_axis(SRC src) { return d()->state_value(&Afterglow_Render_State::frequency_axis, src).lock(); } @@ -56,12 +41,6 @@ int Afterglow::frequency_point_size(SRC src) { int Afterglow::power_point_size(SRC src) { return d()->state_value(&Afterglow_Render_State::power_point_size, src); } -int Afterglow::buffer_size(SRC src) { - return d()->state_value(&Afterglow_Render_State::buffer_size, src); -} -void Afterglow::set_buffer_size(int value) { - d()->set_state_value(&Afterglow_Render_State::buffer_size, qMax(1, value)); -} bool Afterglow::interpolate(SRC src) { return d()->state_value(&Afterglow_Render_State::interpolate, src); } @@ -97,14 +76,12 @@ void Afterglow::set_frequency_point_size(int t) { Render_Edit_Lease edit(pd); edit->frequency_point_size = qMax(1, t); edit->power_point_size = qMax(1, edit->power_point_size); - edit->buffer_size = edit->frequency_point_size * edit->power_point_size; } void Afterglow::set_power_point_size(int t) { Afterglow_Private* pd = d(); Render_Edit_Lease edit(pd); edit->frequency_point_size = qMax(1, edit->frequency_point_size); edit->power_point_size = qMax(1, t); - edit->buffer_size = edit->frequency_point_size * edit->power_point_size; } Afterglow::Builder::Builder(std::shared_ptr parent, std::shared_ptr frequency_axis, std::shared_ptr power_axis) { init(parent, frequency_axis, power_axis); diff --git a/Renderive/plottable/Afterglow.h b/Renderive/plottable/Afterglow.h index 06ef596..f7df3a8 100644 --- a/Renderive/plottable/Afterglow.h +++ b/Renderive/plottable/Afterglow.h @@ -30,7 +30,6 @@ public: /// @brief 功率方向采样点数。 PROP(int, power_point_size) /// @brief 残影累计缓冲大小。 - PROP(int, buffer_size) /// @brief 是否在功率方向做线性补点。 PROP(bool, interpolate) /// @brief 历史残影衰减率。 @@ -69,7 +68,6 @@ struct Afterglow_Prop { Range power_range{0, 10}; int frequency_point_size{}; int power_point_size{}; - int buffer_size{}; bool interpolate = true; double attenuation_rate = 0.2; int init_strong_value = 100; @@ -84,7 +82,6 @@ struct Afterglow::Builder_T { PROP_BT(Range, power_range) PROP_BT(int, frequency_point_size) PROP_BT(int, power_point_size) - PROP_BT(int, buffer_size) PROP_BT(bool, interpolate) PROP_BT(double, attenuation_rate) PROP_BT(int, init_strong_value) diff --git a/Renderive/plottable/Afterglow_p.h b/Renderive/plottable/Afterglow_p.h index 8709ac5..e756dcf 100644 --- a/Renderive/plottable/Afterglow_p.h +++ b/Renderive/plottable/Afterglow_p.h @@ -19,24 +19,6 @@ struct Afterglow_Input_Data : Input_Data { void clear() override { data_list.clear(); } - std::uint64_t get_pending_count() const override { - return data_list.pending_count(); - } - std::uint64_t get_dropped_count() const override { - return data_list.dropped_count(); - } - std::uint64_t get_capacity_dropped_count() const override { - return data_list.capacity_dropped_count(); - } - std::uint64_t rebuild_dropped_count() const override { - return data_list.rebuild_dropped_count(); - } - std::uint64_t consumer_dropped_count() const override { - return data_list.consumer_dropped_count(); - } - std::uint64_t get_pushed_count() const override { - return data_list.pushed_count(); - } }; struct Afterglow_Private : Typed_Render_Data { Raster_Image_Buffer image; @@ -50,11 +32,6 @@ struct Afterglow_Private : Typed_Render_Data cached_power_data{memory_resource(Memory_Domain::Afterglow)}; std::pmr::vector old_cache_power_data{memory_resource(Memory_Domain::Afterglow)}; std::pmr::vector merged_power_data{memory_resource(Memory_Domain::Afterglow)}; - [[nodiscard]] int strength_value(const Afterglow_Render_State* s) const { - if (s->attenuation_rate == 1.0) - return std::numeric_limits::max(); - return (int)((double)s->init_strong_value / (1.0 - s->attenuation_rate)); - } void update_cache_size(int frequency_point_size, int power_point_size) { cache_frequency_point_size = frequency_point_size; cache_power_point_point_size = power_point_size; @@ -153,14 +130,12 @@ void Afterglow::Builder_T::set(Afterglow* ret) { PROP_RT(Range, power_range) PROP_RT(int, frequency_point_size) PROP_RT(int, power_point_size) - PROP_RT(int, buffer_size) PROP_RT(bool, interpolate) PROP_RT(double, attenuation_rate) PROP_RT(int, init_strong_value) PROP_RT(Color_Map, color_map) sc->frequency_point_size = qMax(1, sc->frequency_point_size); sc->power_point_size = qMax(1, sc->power_point_size); - sc->buffer_size = qMax(1, sc->frequency_point_size * sc->power_point_size); sc->attenuation_rate = std::clamp(sc->attenuation_rate, 0.0, 1.0); sc->init_strong_value = qMax(1, sc->init_strong_value); if (static_cast(this)->color_bar_enabled) { diff --git a/Renderive/plottable/Audio_Frequency.cpp b/Renderive/plottable/Audio_Frequency.cpp index e43d534..b458801 100644 --- a/Renderive/plottable/Audio_Frequency.cpp +++ b/Renderive/plottable/Audio_Frequency.cpp @@ -2,30 +2,15 @@ #include "Audio_Frequency_p.h" #include "../base/Memory.h" namespace renderive { -using Audio_Frequency_Binding = Renderable_Binding; -Audio_Frequency::Audio_Frequency() { - Audio_Frequency_Binding::init(this, "Audio_Frequency"); -} -Audio_Frequency_Private* Audio_Frequency::d() { - return Audio_Frequency_Binding::d(this); -} -Render_Object_Owner Audio_Frequency::create_render_data() { - return Audio_Frequency_Binding::create_render_data(); -} -Render_Object_Owner Audio_Frequency::create_render_state() { - return Audio_Frequency_Binding::create_render_state(); -} -Render_Object_Owner Audio_Frequency::create_input_data() { - return Audio_Frequency_Binding::create_input_data(); -} +RENDERIVE_DEFINE_RENDERABLE_BINDING(Audio_Frequency, Audio_Frequency_Private, Audio_Frequency_Render_State, Audio_Frequency_Input_Data, "Audio_Frequency") int Audio_Frequency::time_point_size(SRC src) { - return d()->state_value(&Audio_Frequency_Render_State::time_point_size, src); + auto axis = time_axis(src); + return axis ? axis->time_point_size(src) : 0; } void Audio_Frequency::set_time_point_size(int value) { value = qMax(1, value); if (auto axis = time_axis()) axis->set_time_point_size(value); - d()->set_state_value(&Audio_Frequency_Render_State::time_point_size, value); } std::shared_ptr Audio_Frequency::time_axis(SRC src) { return d()->state_value(&Audio_Frequency_Render_State::time_axis, src).lock(); @@ -43,16 +28,10 @@ void Audio_Frequency::set_value_axis(std::shared_ptr value) { if (auto curve = d()->curve_item.lock()) curve->set_y_axis(value); } -Range Audio_Frequency::key_range(SRC src) { - return d()->state_value(&Audio_Frequency_Render_State::key_range, src); -} -void Audio_Frequency::set_key_range(Range value) { - if (value.length() == 0.0) - return; - d()->set_state_value(&Audio_Frequency_Render_State::key_range, std::move(value)); -} QColor Audio_Frequency::color(SRC src) { - return d()->state_value(&Audio_Frequency_Render_State::color, src); + if (auto curve = d()->curve_item.lock()) + return curve->pen(src).color(); + return {}; } void Audio_Frequency::set_color(QColor value) { if (auto curve = d()->curve_item.lock()) { @@ -60,7 +39,6 @@ void Audio_Frequency::set_color(QColor value) { pen.setWidth(0); curve->set_pen(pen); } - d()->set_state_value(&Audio_Frequency_Render_State::color, std::move(value)); } Audio_Frequency::Builder::Builder(std::shared_ptr parent, std::shared_ptr time_axis, std::shared_ptr value_axis) { ASSERT(parent && parent->plot, "Audio_Frequency build error! parent invalid"); @@ -80,19 +58,13 @@ std::shared_ptr Audio_Frequency::Builder::build() { auto time_axis = this->time_axis.lock(); if (!time_point_size_set && time_axis) time_point_size = time_axis->time_point_size(); - PROP_R(int, time_point_size) PROP_R(std::weak_ptr, time_axis) PROP_R(std::weak_ptr, value_axis) - PROP_R(Range, key_range) - PROP_R(QColor, color) - sc->time_point_size = qMax(1, sc->time_point_size); - if (sc->key_range.length() == 0.0) - sc->key_range = {0.0, 1.0}; auto value_axis = this->value_axis.lock(); if (time_axis) - time_axis->set_time_point_size(sc->time_point_size); + time_axis->set_time_point_size(qMax(1, time_point_size)); if (time_axis && value_axis) { - QPen pen(sc->color); + QPen pen(color); pen.setWidth(0); auto curve = Curve::Builder(ret, time_axis, value_axis).set_pen(pen).build(); curve->object_name = "Audio_Frequency_Curve"; diff --git a/Renderive/plottable/Audio_Frequency.h b/Renderive/plottable/Audio_Frequency.h index 914eae2..7a6e539 100644 --- a/Renderive/plottable/Audio_Frequency.h +++ b/Renderive/plottable/Audio_Frequency.h @@ -14,15 +14,16 @@ public: /// @brief 写入指定时间对应的音频频率值。 void give_data(QTime time, double data); /// @brief 时间窗口内保留的点数。 - PROP(int, time_point_size) + int time_point_size(SRC src = SRC::Edit); + void set_time_point_size(int value); /// @brief 绑定时间轴。 PROP(std::shared_ptr, time_axis) /// @brief 绑定数值轴。 PROP(std::shared_ptr, value_axis) /// @brief 曲线数据值范围。 - PROP(Range, key_range) + QColor color(SRC src = SRC::Edit); + void set_color(QColor value); /// @brief 曲线颜色。 - PROP(QColor, color) struct Builder; private: Audio_Frequency_Private* d(); @@ -31,16 +32,12 @@ private: Render_Object_Owner create_input_data() override; }; struct Audio_Frequency_Prop { - int time_point_size = 100; std::weak_ptr time_axis; std::weak_ptr value_axis{}; - Range key_range = {0, 20}; - QColor color = Qt::yellow; }; struct LIB_DECL Audio_Frequency::Builder : Audio_Frequency_Prop { PROP_B(std::shared_ptr, time_axis) PROP_B(std::shared_ptr, value_axis) - PROP_B(Range, key_range) PROP_B(QColor, color) Builder& set_time_point_size(int value) { time_point_size = value; @@ -52,6 +49,8 @@ struct LIB_DECL Audio_Frequency::Builder : Audio_Frequency_Prop { /// 构建并返回音频频率对象。 std::shared_ptr build(); std::shared_ptr parent{}; + int time_point_size = 100; + QColor color = Qt::yellow; bool time_point_size_set{}; }; } // namespace renderive diff --git a/Renderive/plottable/Audio_Frequency_p.h b/Renderive/plottable/Audio_Frequency_p.h index 22683e6..0bd8963 100644 --- a/Renderive/plottable/Audio_Frequency_p.h +++ b/Renderive/plottable/Audio_Frequency_p.h @@ -35,24 +35,6 @@ struct Audio_Frequency_Input_Data : Input_Data { void clear() override { data_list.clear(); } - std::uint64_t get_pending_count() const override { - return data_list.get_pending_count(); - } - std::uint64_t get_dropped_count() const override { - return data_list.get_dropped_count(); - } - std::uint64_t get_capacity_dropped_count() const override { - return data_list.get_capacity_dropped_count(); - } - std::uint64_t rebuild_dropped_count() const override { - return data_list.get_rebuild_dropped_count(); - } - std::uint64_t consumer_dropped_count() const override { - return data_list.get_consumer_dropped_count(); - } - std::uint64_t get_pushed_count() const override { - return data_list.get_pushed_count(); - } }; struct Audio_Frequency_Render_State : Render_State, Audio_Frequency_Prop {}; struct Audio_Frequency_Private : Typed_Render_Data { @@ -115,9 +97,4 @@ struct Audio_Frequency_Private : Typed_Render_Data(audio->d_ptr); - } -}; } diff --git a/Renderive/plottable/Hover_Info.cpp b/Renderive/plottable/Hover_Info.cpp index f0f1dab..5d78d38 100644 --- a/Renderive/plottable/Hover_Info.cpp +++ b/Renderive/plottable/Hover_Info.cpp @@ -1,11 +1,7 @@ #include "Hover_Info.h" namespace renderive { -void Hover_Info_Render_State::draw_hover(QPainter* painter, Abs_Axis* h, Abs_Axis* v) { +void Hover_Info_Render_State::draw_hover(QPainter* painter, Abs_Axis* h, Abs_Axis* v, Hover_Info_Renderable_Interface* renderable) { QPoint pos = hover_info_pos; - if (!renderable) { - auto that = dynamic_cast(this); - renderable = dynamic_cast(that->d_ptr->q_ptr); - } std::vector lines = renderable->create_hover_string(h, v, pos); QFontMetrics fm(hover_info_font); int width = std::numeric_limits::min(); diff --git a/Renderive/plottable/Hover_Info.h b/Renderive/plottable/Hover_Info.h index 08f8da8..0f08d3f 100644 --- a/Renderive/plottable/Hover_Info.h +++ b/Renderive/plottable/Hover_Info.h @@ -1,12 +1,13 @@ -#pragma once +#pragma once +#include #include "../Axis/export.h" #include "../architecture/export.h" namespace renderive { struct Hover_Info_Render_State; struct Hover_Info_Renderable_Interface; -/// @brief 悬浮信息渲染状态。 +/// @brief 鎮诞淇℃伅娓叉煋鐘舵€併€? struct LIB_DECL Hover_Info_Render_State { - /// @brief 销毁悬浮信息状态。 + /// @brief 閿€姣佹偓娴俊鎭姸鎬併€? virtual ~Hover_Info_Render_State() = default; Hover_Info_Render_State() { hover_info_brush = QBrush(Qt::white); @@ -18,71 +19,103 @@ struct LIB_DECL Hover_Info_Render_State { bool use_hover_info = true; bool hover_info_active = false; QPoint hover_info_pos; - Hover_Info_Renderable_Interface* renderable{}; - /// @brief 绘制悬浮信息。 - void draw_hover(QPainter* painter, Abs_Axis* h, Abs_Axis* v); - /// @brief 判断当前对象是否允许显示悬浮信息。 + /// @brief 缁樺埗鎮诞淇℃伅銆? + void draw_hover(QPainter* painter, Abs_Axis* h, Abs_Axis* v, Hover_Info_Renderable_Interface* renderable); + /// @brief 鍒ゆ柇褰撳墠瀵硅薄鏄惁鍏佽鏄剧ず鎮诞淇℃伅銆? bool hover_ok(Renderable* able) const; }; -/// @brief 可提供悬浮信息的图元接口。 +/// @brief 鍙彁渚涙偓娴俊鎭殑鍥惧厓鎺ュ彛銆? struct LIB_DECL Hover_Info_Renderable_Interface { - /// @brief 根据坐标轴和鼠标位置生成悬浮文本。 + struct Hover_Edit { + Hover_Edit() = default; + Hover_Edit(Hover_Info_Render_State* state, Render_Data* data, Triple_Buffer_Lease lease) : state(state), data(data), lease(lease) {} + Hover_Edit(const Hover_Edit&) = delete; + Hover_Edit& operator=(const Hover_Edit&) = delete; + Hover_Edit(Hover_Edit&& other) noexcept : state(std::exchange(other.state, nullptr)), data(std::exchange(other.data, nullptr)), lease(std::exchange(other.lease, {})) {} + Hover_Edit& operator=(Hover_Edit&& other) noexcept { + if (this == &other) + return *this; + finish(); + state = std::exchange(other.state, nullptr); + data = std::exchange(other.data, nullptr); + lease = std::exchange(other.lease, {}); + return *this; + } + ~Hover_Edit() { + finish(); + } + Hover_Info_Render_State* operator->() const { + return state; + } + private: + void finish() { + if (!data) + return; + ++data->state_by_index(lease.index)->version; + if (data->q_ptr) + data->q_ptr->mark_render_dirty(); + data->state_control.unmark_use(lease); + state = nullptr; + data = nullptr; + lease = {}; + } + Hover_Info_Render_State* state{}; + Render_Data* data{}; + Triple_Buffer_Lease lease{}; + }; + /// @brief 鏍规嵁鍧愭爣杞村拰榧犳爣浣嶇疆鐢熸垚鎮诞鏂囨湰銆? virtual std::vector create_hover_string(Abs_Axis* h, Abs_Axis* v, QPoint pos); - /// @brief 销毁悬浮信息接口。 + /// @brief 閿€姣佹偓娴俊鎭帴鍙c€? virtual ~Hover_Info_Renderable_Interface() = default; - /// @brief 绘制悬浮信息。 + /// @brief 缁樺埗鎮诞淇℃伅銆? virtual void draw_hover(QPainter* painter, Abs_Axis* h, Abs_Axis* v) { - return hover_state(SRC::Render)->draw_hover(painter, h, v); + return hover_state(SRC::Render)->draw_hover(painter, h, v, this); } - /// @brief 判断指定图元是否允许显示悬浮信息。 + /// @brief 鍒ゆ柇鎸囧畾鍥惧厓鏄惁鍏佽鏄剧ず鎮诞淇℃伅銆? virtual bool hover_ok(Renderable* able) { return hover_state(SRC::Render)->hover_ok(able); } - /// @brief 判断鼠标位置是否命中悬浮信息区域。 + /// @brief 鍒ゆ柇榧犳爣浣嶇疆鏄惁鍛戒腑鎮诞淇℃伅鍖哄煙銆? virtual bool hover_test(QPoint pos) { return true; } - /// @brief 返回是否启用悬浮信息。 + /// @brief 杩斿洖鏄惁鍚敤鎮诞淇℃伅銆? bool use_hover_info(SRC src = SRC::Edit) { return hover_state(src)->use_hover_info; } - /// @brief 设置是否启用悬浮信息。 + /// @brief 璁剧疆鏄惁鍚敤鎮诞淇℃伅銆? void set_use_hover_info(bool use) { - Hover_Info_Render_State* sc = begin_hover_edit(); - sc->use_hover_info = use; - finish_hover_edit(); + auto edit = begin_hover_edit(); + edit->use_hover_info = use; } - /// @brief 设置悬浮信息字体。 + /// @brief 璁剧疆鎮诞淇℃伅瀛椾綋銆? void set_hover_info_font(const QFont& font) { - Hover_Info_Render_State* sc = begin_hover_edit(); - sc->hover_info_font = font; - finish_hover_edit(); + auto edit = begin_hover_edit(); + edit->hover_info_font = font; } - /// @brief 返回悬浮信息字体。 + /// @brief 杩斿洖鎮诞淇℃伅瀛椾綋銆? QFont hover_info_font(SRC src = SRC::Edit) { return hover_state(src)->hover_info_font; } - /// @brief 返回悬浮信息背景刷。 + /// @brief 杩斿洖鎮诞淇℃伅鑳屾櫙鍒枫€? QBrush hover_info_background_brush(SRC src = SRC::Edit) { return hover_state(src)->hover_info_brush; } - /// @brief 设置悬浮信息背景刷。 + /// @brief 璁剧疆鎮诞淇℃伅鑳屾櫙鍒枫€? void set_hover_info_background_brush(const QBrush& brush) { - Hover_Info_Render_State* sc = begin_hover_edit(); - sc->hover_info_brush = brush.color().isValid() ? brush : Qt::NoBrush; - finish_hover_edit(); + auto edit = begin_hover_edit(); + edit->hover_info_brush = brush.color().isValid() ? brush : Qt::NoBrush; } - /// @brief 返回悬浮信息文本画笔。 + /// @brief 杩斿洖鎮诞淇℃伅鏂囨湰鐢荤瑪銆? QPen hover_info_pen(SRC src = SRC::Edit) { return hover_state(src)->hover_info_pen; } - /// @brief 设置悬浮信息文本画笔。 + /// @brief 璁剧疆鎮诞淇℃伅鏂囨湰鐢荤瑪銆? void set_hover_info_pen(const QPen& pen) { - Hover_Info_Render_State* sc = begin_hover_edit(); - sc->hover_info_pen = pen.color().isValid() ? pen : Qt::NoPen; - finish_hover_edit(); + auto edit = begin_hover_edit(); + edit->hover_info_pen = pen.color().isValid() ? pen : Qt::NoPen; } - /// @brief 返回悬浮信息内容边距。 + /// @brief 杩斿洖鎮诞淇℃伅鍐呭杈硅窛銆? void get_hover_info_contents_margins(int& left, int& top, int& right, int& bottom, SRC src) { auto s = hover_state(src); left = s->hover_info_left; @@ -90,68 +123,36 @@ struct LIB_DECL Hover_Info_Renderable_Interface { right = s->hover_info_right; bottom = s->hover_info_bottom; } - /// @brief 设置悬浮信息内容边距。 + /// @brief 璁剧疆鎮诞淇℃伅鍐呭杈硅窛銆? void set_hover_info_contents_margins(int left, int top, int right, int bottom) { - Hover_Info_Render_State* sc = begin_hover_edit(); - sc->hover_info_left = left; - sc->hover_info_top = top; - sc->hover_info_right = right; - sc->hover_info_bottom = bottom; - finish_hover_edit(); + auto edit = begin_hover_edit(); + edit->hover_info_left = left; + edit->hover_info_top = top; + edit->hover_info_right = right; + edit->hover_info_bottom = bottom; } - /// @brief 返回指定角色的悬浮信息状态。 + /// @brief 杩斿洖鎸囧畾瑙掕壊鐨勬偓娴俊鎭姸鎬併€? virtual Hover_Info_Render_State* hover_state(SRC src) = 0; - /// @brief 开始编辑悬浮信息状态。 - virtual Hover_Info_Render_State* begin_hover_edit() = 0; - /// @brief 结束编辑悬浮信息状态。 - virtual void finish_hover_edit() = 0; + /// @brief 寮€濮嬬紪杈戞偓娴俊鎭姸鎬併€? + virtual Hover_Edit begin_hover_edit() = 0; + /// @brief 缁撴潫缂栬緫鎮诞淇℃伅鐘舵€併€? }; -/// @brief 独立保存悬浮信息状态的可渲染接口。 -struct LIB_DECL Hover_Info_Independent_Renderable : Hover_Info_Renderable_Interface { -private: - Hover_Info_Render_State s, sc; - Hover_Info_Render_State* hover_state(SRC src) override { - if (src == SRC::Edit) { - return ≻ - } - return &s; - } - Hover_Info_Render_State* begin_hover_edit() override { - return ≻ - } - void finish_hover_edit() override {} -public: - /// @brief 同步独立状态并绘制悬浮信息。 - void draw_hover(QPainter* painter, Abs_Axis* h, Abs_Axis* v) override { - s.renderable = this; - sc.renderable = this; - s = sc; - Hover_Info_Renderable_Interface::draw_hover(painter, h, v); - } -}; -/// @brief 使用派生图元三缓冲状态保存悬浮信息的 mixin。 +/// @brief 浣跨敤娲剧敓鍥惧厓涓夌紦鍐茬姸鎬佷繚瀛樻偓娴俊鎭殑 mixin銆? template struct LIB_DECL Hover_Info_Renderable : Hover_Info_Renderable_Interface { private: That* that() { return static_cast(this); } - Triple_Buffer_Lease hover_lease{}; Hover_Info_Render_State* hover_state(SRC src) override { auto t = that(); return dynamic_cast(t->d_ptr->state(src)); } - Hover_Info_Render_State* begin_hover_edit() override { + Hover_Edit begin_hover_edit() override { auto t = that(); - hover_lease = t->d_ptr->state_control.wait_mark_use_role(State_Edit); - return dynamic_cast(t->d_ptr->state_by_index(hover_lease.index)); - } - void finish_hover_edit() override { - auto t = that(); - ++t->d_ptr->state_by_index(hover_lease.index)->version; - t->mark_render_dirty(); - t->d_ptr->state_control.unmark_use(hover_lease); - hover_lease = {}; + auto lease = t->d_ptr->state_control.wait_mark_use_role(State_Edit); + return Hover_Edit(dynamic_cast(t->d_ptr->state_by_index(lease.index)), t->d_ptr, lease); } }; } // namespace renderive + diff --git a/Renderive/plottable/Multi_Select_Rect.cpp b/Renderive/plottable/Multi_Select_Rect.cpp index adf0e51..0341af4 100644 --- a/Renderive/plottable/Multi_Select_Rect.cpp +++ b/Renderive/plottable/Multi_Select_Rect.cpp @@ -1,22 +1,7 @@ #include "Multi_Select_Rect_p.h" #include "../base/Memory.h" namespace renderive { -using Multi_Select_Rect_Binding = Renderable_Binding; -Multi_Select_Rect::Multi_Select_Rect() { - Multi_Select_Rect_Binding::init(this, "Multi_Select_Rect"); -} -Multi_Select_Rect_Private* Multi_Select_Rect::d() { - return Multi_Select_Rect_Binding::d(this); -} -Render_Object_Owner Multi_Select_Rect::create_render_data() { - return Multi_Select_Rect_Binding::create_render_data(); -} -Render_Object_Owner Multi_Select_Rect::create_render_state() { - return Multi_Select_Rect_Binding::create_render_state(); -} -Render_Object_Owner Multi_Select_Rect::create_input_data() { - return Multi_Select_Rect_Binding::create_input_data(); -} +RENDERIVE_DEFINE_RENDERABLE_BINDING(Multi_Select_Rect, Multi_Select_Rect_Private, Multi_Select_Rect_Render_State, Multi_Select_Rect_Input_Data, "Multi_Select_Rect") Multi_Select_Rect::Builder::Builder(std::shared_ptr parent, std::shared_ptr key_axis, std::shared_ptr value_axis) { ASSERT(parent && parent->plot, "Multi_Select_Rect build error! parent invalid"); ASSERT(key_axis && value_axis, "Multi_Select_Rect build error! axis == nullptr"); @@ -76,4 +61,12 @@ void Multi_Select_Rect::set_border_pen(const QPen& pen) { Render_Edit_Lease edit(d()); edit->border_pen = pen.color().isValid() ? pen : Qt::NoPen; } +std::vector Multi_Select_Rect::selection_rects(SRC src) { + return d()->state_data(src)->rects; +} +void Multi_Select_Rect::clear_selection() { + Render_Edit_Lease edit(d()); + edit->rects.clear(); + d()->active.store(false, std::memory_order_release); +} } // namespace renderive diff --git a/Renderive/plottable/Multi_Select_Rect.h b/Renderive/plottable/Multi_Select_Rect.h index b02e348..9e02214 100644 --- a/Renderive/plottable/Multi_Select_Rect.h +++ b/Renderive/plottable/Multi_Select_Rect.h @@ -27,6 +27,8 @@ public: void set_rect_brush(const QBrush& brush); /// @brief 设置矩形边框画笔。 void set_border_pen(const QPen& pen); + std::vector selection_rects(SRC src = SRC::Edit); + void clear_selection(); struct Builder; private: Multi_Select_Rect_Private* d(); diff --git a/Renderive/plottable/Multi_Select_Rect_p.h b/Renderive/plottable/Multi_Select_Rect_p.h index 0d050be..e13691b 100644 --- a/Renderive/plottable/Multi_Select_Rect_p.h +++ b/Renderive/plottable/Multi_Select_Rect_p.h @@ -1,5 +1,7 @@ #pragma once #include +#include +#include #include "../Axis/Abs_Axis.h" #include "Multi_Select_Rect.h" namespace renderive { @@ -17,9 +19,21 @@ struct Multi_Select_Rect_Render_State : renderive::Render_State { struct Multi_Select_Rect_Input_Data : renderive::Input_Data {}; struct Multi_Select_Rect_Private : renderive::Typed_Render_Data { - bool active = false; + std::atomic_bool active{false}; bool select_test(const QPointF& pos) override { - return true; + auto s = render_state(); + auto horizontal_axis = s->horizontal_axis.lock(); + auto vertical_axis = s->vertical_axis.lock(); + if (!horizontal_axis || !vertical_axis) + return false; + Range h = horizontal_axis->coord_range(SRC::Render); + Range v = vertical_axis->coord_range(SRC::Render); + double left = horizontal_axis->coord_to_pixel(h.origin, SRC::Render); + double right = horizontal_axis->coord_to_pixel(h.target, SRC::Render); + double top = vertical_axis->coord_to_pixel(v.origin, SRC::Render); + double bottom = vertical_axis->coord_to_pixel(v.target, SRC::Render); + return QRectF(QPointF(std::min(left, right), std::min(top, bottom)), + QPointF(std::max(left, right), std::max(top, bottom))).contains(pos); } void mousePressEvent(QMouseEvent* event) override { if (event->button() != Qt::LeftButton) @@ -45,10 +59,10 @@ struct Multi_Select_Rect_Private : renderive::Typed_Render_Datapixel_to_coord(event->pos().x(), SRC::Render); double y = vertical_axis->pixel_to_coord(event->pos().y(), SRC::Render); rect_list.push_back(QRectF(QPointF(x, y), QPointF(x, y))); - active = true; + active.store(true, std::memory_order_release); } void mouseMoveEvent(QMouseEvent* event) override { - if (!active) + if (!active.load(std::memory_order_acquire)) return; if (!(event->buttons() & Qt::LeftButton)) return; @@ -60,40 +74,45 @@ struct Multi_Select_Rect_Private : renderive::Typed_Render_Data& rect_list = edit->rects; if (rect_list.empty()) return; - rect_list.back().setBottomRight(event->pos()); - QRectF& r = rect_list.back(); - r.setRight(horizontal_axis->pixel_to_coord(r.right(), SRC::Render)); - r.setBottom(vertical_axis->pixel_to_coord(r.bottom(), SRC::Render)); + double x = horizontal_axis->pixel_to_coord(event->pos().x(), SRC::Render); + double y = vertical_axis->pixel_to_coord(event->pos().y(), SRC::Render); + rect_list.back().setBottomRight(QPointF(x, y)); + } + void mouseReleaseEvent(QMouseEvent* event) override { + if (event->button() != Qt::LeftButton || !active.load(std::memory_order_acquire)) + return; + active.store(false, std::memory_order_release); + Render_Edit_Lease edit(this); + if (!edit->rects.empty() && (qFuzzyCompare(edit->rects.back().width(), 0.0) || qFuzzyCompare(edit->rects.back().height(), 0.0))) + edit->rects.pop_back(); } - void mouseReleaseEvent(QMouseEvent* event) override {} void keyPressEvent(QKeyEvent* event) override { - if (event->key() != Qt::Key_Escape || !active) + if (event->key() != Qt::Key_Escape || !active.load(std::memory_order_acquire)) return; Render_Edit_Lease edit(this); - active = false; + active.store(false, std::memory_order_release); std::vector& rect_list = edit->rects; if (rect_list.empty()) return; rect_list.pop_back(); } - void keyReleaseEvent(QKeyEvent* event) override {} void draw(QPainter* painter, const Plot_Render_Snapshot&) override { - if (!active) - return; Multi_Select_Rect_Render_State* s = render_state(); auto horizontal_axis = s->horizontal_axis.lock(); auto vertical_axis = s->vertical_axis.lock(); if (!horizontal_axis || !vertical_axis) return; std::vector draw_rect_list; + std::vector coord_rect_list; for (QRectF r : s->rects) { if (qFuzzyCompare(r.width(), 0.0) || qFuzzyCompare(r.height(), 0.0)) continue; + coord_rect_list.push_back(r.normalized()); r.setX(horizontal_axis->coord_to_pixel(r.x(), SRC::Render)); r.setY(vertical_axis->coord_to_pixel(r.y(), SRC::Render)); r.setRight(horizontal_axis->coord_to_pixel(r.right(), SRC::Render)); r.setBottom(vertical_axis->coord_to_pixel(r.bottom(), SRC::Render)); - draw_rect_list.push_back(r); + draw_rect_list.push_back(r.normalized()); } painter->save(); QFontMetrics xfm(horizontal_axis->unit_text_font()); @@ -108,7 +127,7 @@ struct Multi_Select_Rect_Private : renderive::Typed_Render_Datarects[i]; + QRectF& coord_rect = coord_rect_list[i]; double offset_x = coord_rect.right() - coord_rect.left(); double offset_y = coord_rect.bottom() - coord_rect.top(); QString text1 = "offset_x == " + QString::number(offset_x) + horizontal_axis->unit_text(); diff --git a/Renderive/plottable/Performance_Shower.cpp b/Renderive/plottable/Performance_Shower.cpp index 98ae53c..db9a6b4 100644 --- a/Renderive/plottable/Performance_Shower.cpp +++ b/Renderive/plottable/Performance_Shower.cpp @@ -4,14 +4,15 @@ #include #include #include "Core/spdlog/export.h" +#include "../plot/Plot_p.h" namespace renderive { namespace { double duration_ms(std::uint64_t begin_ns, std::uint64_t end_ns) { return end_ns > begin_ns ? static_cast(end_ns - begin_ns) / 1000000.0 : 0.0; } -double cache_ratio(std::uint64_t hit, std::uint64_t stale_hit, std::uint64_t miss) { - std::uint64_t total = hit + stale_hit + miss; - return total ? static_cast(hit + stale_hit) / static_cast(total) : 0.0; +double cache_ratio(std::uint64_t hit, std::uint64_t miss) { + std::uint64_t total = hit + miss; + return total ? static_cast(hit) / static_cast(total) : 0.0; } std::string csv_escape(const std::string& value) { std::string escaped; @@ -25,14 +26,6 @@ std::string csv_escape(const std::string& value) { escaped.push_back('"'); return escaped; } -std::uint64_t cache_subtree_compose_time(const std::vector& stats, const Renderable_Cache_Frame_Stat& node) { - std::uint64_t compose_time_ns = node.compose_time_ns; - for (const auto& stat : stats) { - if (stat.parent_object_name == node.object_name && stat.tree_depth == node.tree_depth + 1) - compose_time_ns += cache_subtree_compose_time(stats, stat); - } - return compose_time_ns; -} std::string renderable_cache_stats_text(const Frame_Lifecycle_Record& frame) { std::ostringstream stream; bool first = true; @@ -46,14 +39,11 @@ std::string renderable_cache_stats_text(const Frame_Lifecycle_Record& frame) { << ":parent=" << std::string(parent.constData(), static_cast(parent.size())) << ";depth=" << stat.tree_depth << ";hit=" << stat.hit_count - << ";stale=" << stat.stale_hit_count << ";miss=" << stat.miss_count << ";rebuild=" << stat.rebuild_count - << ";stale_rebuild=" << stat.stale_rebuild_count - << ";miss_rebuild=" << stat.miss_rebuild_count << ";rebuild_ns=" << stat.rebuild_time_ns << ";compose_ns=" << stat.compose_time_ns - << ";subtree_compose_ns=" << cache_subtree_compose_time(frame.renderable_cache_stats, stat) + << ";subtree_compose_ns=" << renderable_cache_subtree_compose_time(frame.renderable_cache_stats, stat) << ";last_rebuild_ns=" << stat.last_rebuild_time_ns << ";last_compose_ns=" << stat.last_compose_time_ns << ";image_bytes=" << stat.last_image_bytes @@ -94,7 +84,6 @@ public: stream << std::setprecision(9) << frame.frame_id << ',' << frame.input_version << ',' - << frame.snapshot_version << ',' << frame.frame_slot_generation << ',' << Psc::to_string(frame.frame_outcome) << ',' << Psc::to_string(feedback.bottleneck_state) << ',' @@ -152,21 +141,15 @@ public: << duration_ms(frame.core_data_time, frame.paint_end_time) << ',' << duration_ms(frame.render_request_time, frame.consumer_release_time ? frame.consumer_release_time : frame.superseded_time) << ',' << frame.raw_input_count << ',' - << frame.visible_input_count << ',' << frame.prepared_output_count << ',' - << frame.draw_point_count << ',' - << frame.draw_segment_count << ',' << frame.renderable_cache_hit_count << ',' - << frame.renderable_cache_stale_hit_count << ',' << frame.renderable_cache_miss_count << ',' << frame.renderable_cache_rebuild_count << ',' - << frame.renderable_cache_stale_rebuild_count << ',' - << frame.renderable_cache_miss_rebuild_count << ',' << frame.renderable_cache_rebuild_time_ns << ',' << frame.renderable_cache_compose_time_ns << ',' << frame.renderable_cache_image_bytes << ',' << frame.renderable_cache_image_area << ',' - << cache_ratio(frame.renderable_cache_hit_count, frame.renderable_cache_stale_hit_count, frame.renderable_cache_miss_count) << ',' + << cache_ratio(frame.renderable_cache_hit_count, frame.renderable_cache_miss_count) << ',' << frame.pixel_width << ',' << frame.pixel_height << ',' << frame.renderable_count << ',' @@ -208,29 +191,56 @@ private: return value; } static std::string header() { - return "frame_id,input_version,snapshot_version,slot_generation,outcome,bottleneck,input_fps,production_fps,producer_capacity_fps,display_fps,consumer_capacity_fps,manual_interval_ms,adaptive_interval_ms,effective_interval_ms,input_srtt_ms,input_jitter_ms,render_interval_srtt_ms,render_interval_jitter_ms,render_queue_srtt_ms,render_queue_jitter_ms,render_duration_srtt_ms,render_duration_jitter_ms,ready_wait_srtt_ms,ready_wait_jitter_ms,update_wait_srtt_ms,update_wait_jitter_ms,paint_srtt_ms,paint_jitter_ms,consume_interval_srtt_ms,consume_interval_jitter_ms,frame_age_srtt_ms,frame_age_jitter_ms,producer_busy_ratio,ready_occupancy_ratio,consumer_busy_ratio,input_pending_ratio,superseded_ratio,underrun_ratio,unique_consumed_ratio,display_efficiency,wasted_render_ms,latest_input_version,rendering_input_version,published_input_version,consumed_input_version,produced_frames,consumed_frames,superseded_frames,repeated_frames,request_wait_ms,render_queue_wait_ms,prepare_ms,draw_ms,render_ms,ready_wait_ms,update_wait_ms,paint_ms,frame_age_ms,frame_total_ms,raw_input_count,visible_input_count,prepared_output_count,draw_point_count,draw_segment_count,cache_hit_count,cache_stale_hit_count,cache_miss_count,cache_rebuild_count,cache_stale_rebuild_count,cache_miss_rebuild_count,cache_rebuild_time_ns,cache_compose_time_ns,cache_image_bytes,cache_image_area,cache_usable_ratio,pixel_width,pixel_height,renderable_count,visible_renderable_count,direct_draw_count,local_cache_count,core_data_time_ns,render_begin_time_ns,render_end_time_ns,publish_time_ns,paint_begin_time_ns,paint_end_time_ns,consumer_release_time_ns,superseded_time_ns,renderable_stats,renderable_cache_stats"; + return "frame_id,input_version,slot_generation,outcome,bottleneck,input_fps,production_fps,producer_capacity_fps,display_fps,consumer_capacity_fps,manual_interval_ms,adaptive_interval_ms,effective_interval_ms,input_srtt_ms,input_jitter_ms,render_interval_srtt_ms,render_interval_jitter_ms,render_queue_srtt_ms,render_queue_jitter_ms,render_duration_srtt_ms,render_duration_jitter_ms,ready_wait_srtt_ms,ready_wait_jitter_ms,update_wait_srtt_ms,update_wait_jitter_ms,paint_srtt_ms,paint_jitter_ms,consume_interval_srtt_ms,consume_interval_jitter_ms,frame_age_srtt_ms,frame_age_jitter_ms,producer_busy_ratio,ready_occupancy_ratio,consumer_busy_ratio,input_pending_ratio,superseded_ratio,underrun_ratio,unique_consumed_ratio,display_efficiency,wasted_render_ms,latest_input_version,rendering_input_version,published_input_version,consumed_input_version,produced_frames,consumed_frames,superseded_frames,repeated_frames,request_wait_ms,render_queue_wait_ms,prepare_ms,draw_ms,render_ms,ready_wait_ms,update_wait_ms,paint_ms,frame_age_ms,frame_total_ms,raw_input_count,prepared_output_count,cache_hit_count,cache_miss_count,cache_rebuild_count,cache_rebuild_time_ns,cache_compose_time_ns,cache_image_bytes,cache_image_area,cache_hit_ratio,pixel_width,pixel_height,renderable_count,visible_renderable_count,direct_draw_count,local_cache_count,core_data_time_ns,render_begin_time_ns,render_end_time_ns,publish_time_ns,paint_begin_time_ns,paint_end_time_ns,consumer_release_time_ns,superseded_time_ns,renderable_stats,renderable_cache_stats"; } }; Performance_Frame_Log& frame_log() { static Performance_Frame_Log value; return value; } +std::shared_ptr performance_shower_owner(Abs_Plot_Private* data) { + if (!data || !data->render_context) + return {}; + auto observer = std::atomic_load_explicit(&data->render_context->frame_lifecycle_observer, std::memory_order_acquire); + return std::dynamic_pointer_cast(observer); } -using Performance_Shower_Binding = Renderable_Binding; -Performance_Shower::Performance_Shower() { - Performance_Shower_Binding::init(this, "Performance_Shower"); } -Performance_Shower_Private* Performance_Shower::d() { - return Performance_Shower_Binding::d(this); +RENDERIVE_DEFINE_RENDERABLE_BINDING(Performance_Shower, Performance_Shower_Private, Performance_Shower_Render_State, Performance_Shower_Input_Data, "Performance_Shower") +std::shared_ptr attach_performance_shower(Abs_Plot& plot) { + auto* data = plot.d; + if (!data) + return {}; + auto shower = performance_shower_owner(data); + if (shower) + return shower; + auto created_shower = renderive::make_shared(); + created_shower->init(data->root_renderable); + std::atomic_store_explicit(&data->render_context->frame_lifecycle_observer, std::static_pointer_cast(created_shower), std::memory_order_release); + return created_shower; } -Render_Object_Owner Performance_Shower::create_render_data() { - return Performance_Shower_Binding::create_render_data(); +void detach_performance_shower(Abs_Plot& plot) { + auto* data = plot.d; + if (!data) + return; + auto shower = performance_shower_owner(data); + std::atomic_store_explicit(&data->render_context->frame_lifecycle_observer, std::shared_ptr{}, std::memory_order_release); + if (shower) { + shower->setEnabled(false); + plot.remove_renderable(shower); + } } -Render_Object_Owner Performance_Shower::create_render_state() { - return Performance_Shower_Binding::create_render_state(); +bool performance_shower_enabled(const Abs_Plot& plot) { + auto shower = performance_shower_owner(plot.d); + return shower && shower->enabled(); } -Render_Object_Owner Performance_Shower::create_input_data() { - return Performance_Shower_Binding::create_input_data(); +void set_performance_shower_enabled(Abs_Plot& plot, bool enabled) { + if (!enabled) { + detach_performance_shower(plot); + return; + } + auto shower = attach_performance_shower(plot); + if (shower) + shower->setEnabled(true); } void Performance_Shower::setEnabled(bool enabled) { d()->enabled_value.store(enabled, std::memory_order_release); diff --git a/Renderive/plottable/Performance_Shower_p.h b/Renderive/plottable/Performance_Shower_p.h index efc0a79..fe20ebe 100644 --- a/Renderive/plottable/Performance_Shower_p.h +++ b/Renderive/plottable/Performance_Shower_p.h @@ -61,29 +61,19 @@ struct Performance_Shower_Input_Data : Input_Data { capacity_dropped = 0; reset_pending = false; } - std::uint64_t get_pending_count() const override { - return count; - } - std::uint64_t get_capacity_dropped_count() const override { - return capacity_dropped; - } }; struct Renderable_Cache_Aggregate_Stat { QString object_name; QString parent_object_name; int tree_depth{}; std::uint64_t hit_count{}; - std::uint64_t stale_hit_count{}; std::uint64_t miss_count{}; std::uint64_t rebuild_count{}; - std::uint64_t stale_rebuild_count{}; - std::uint64_t miss_rebuild_count{}; std::uint64_t rebuild_time_ns{}; std::uint64_t compose_time_ns{}; std::uint64_t subtree_compose_time_ns{}; std::uint64_t last_rebuild_time_ns{}; std::uint64_t last_compose_time_ns{}; - std::uint64_t last_subtree_compose_time_ns{}; std::uint64_t last_image_bytes{}; std::uint64_t last_image_area{}; std::uint64_t last_edit_version{}; @@ -126,17 +116,12 @@ struct Frame_Performance_Aggregate { Frame_Lifecycle_Record latest; std::uint64_t observed_frame_count{}; std::uint64_t render_time_ns{}; - std::uint64_t produced_outcome_count{}; std::uint64_t consumed_outcome_count{}; std::uint64_t superseded_outcome_count{}; std::uint64_t cancelled_outcome_count{}; - std::uint64_t repeated_outcome_count{}; std::uint64_t cache_hit_count{}; - std::uint64_t cache_stale_hit_count{}; std::uint64_t cache_miss_count{}; std::uint64_t cache_rebuild_count{}; - std::uint64_t cache_stale_rebuild_count{}; - std::uint64_t cache_miss_rebuild_count{}; std::uint64_t cache_rebuild_time_ns{}; std::uint64_t cache_compose_time_ns{}; std::uint64_t input_capacity_dropped{}; @@ -163,11 +148,8 @@ struct Frame_Performance_Aggregate { update_duration(frame_age_ms, frame.core_data_time, frame.paint_end_time); update_duration(frame_total_ms, frame.render_request_time, frame.consumer_release_time ? frame.consumer_release_time : frame.superseded_time); cache_hit_count += frame.renderable_cache_hit_count; - cache_stale_hit_count += frame.renderable_cache_stale_hit_count; cache_miss_count += frame.renderable_cache_miss_count; cache_rebuild_count += frame.renderable_cache_rebuild_count; - cache_stale_rebuild_count += frame.renderable_cache_stale_rebuild_count; - cache_miss_rebuild_count += frame.renderable_cache_miss_rebuild_count; cache_rebuild_time_ns += frame.renderable_cache_rebuild_time_ns; cache_compose_time_ns += frame.renderable_cache_compose_time_ns; if (frame.renderable_cache_rebuild_time_ns) @@ -199,11 +181,8 @@ struct Frame_Performance_Aggregate { for (const auto& stat : frame.renderable_cache_stats) { Renderable_Cache_Aggregate_Stat& aggregate_stat = cache_stat(stat.object_name, stat.parent_object_name, stat.tree_depth); aggregate_stat.hit_count += stat.hit_count; - aggregate_stat.stale_hit_count += stat.stale_hit_count; aggregate_stat.miss_count += stat.miss_count; aggregate_stat.rebuild_count += stat.rebuild_count; - aggregate_stat.stale_rebuild_count += stat.stale_rebuild_count; - aggregate_stat.miss_rebuild_count += stat.miss_rebuild_count; aggregate_stat.rebuild_time_ns += stat.rebuild_time_ns; aggregate_stat.compose_time_ns += stat.compose_time_ns; aggregate_stat.last_rebuild_time_ns = stat.last_rebuild_time_ns ? stat.last_rebuild_time_ns : aggregate_stat.last_rebuild_time_ns; @@ -220,7 +199,6 @@ struct Frame_Performance_Aggregate { update_cache_subtree_compose(frame.renderable_cache_stats); switch (frame.frame_outcome) { case Frame_Outcome::Produced: - ++produced_outcome_count; break; case Frame_Outcome::Consumed: ++consumed_outcome_count; @@ -232,7 +210,6 @@ struct Frame_Performance_Aggregate { ++cancelled_outcome_count; break; case Frame_Outcome::Repeated: - ++repeated_outcome_count; break; } } @@ -251,23 +228,14 @@ private: } void update_cache_subtree_compose(const std::vector& frame_stats) { for (const auto& stat : frame_stats) { - std::uint64_t subtree_compose_time_ns = cache_subtree_compose_time(frame_stats, stat); + std::uint64_t subtree_compose_time_ns = renderable_cache_subtree_compose_time(frame_stats, stat); if (!subtree_compose_time_ns) continue; Renderable_Cache_Aggregate_Stat& aggregate_stat = cache_stat(stat.object_name, stat.parent_object_name, stat.tree_depth); aggregate_stat.subtree_compose_time_ns += subtree_compose_time_ns; - aggregate_stat.last_subtree_compose_time_ns = subtree_compose_time_ns; aggregate_stat.subtree_compose_ms.update(ns_to_ms(subtree_compose_time_ns)); } } - static std::uint64_t cache_subtree_compose_time(const std::vector& frame_stats, const Renderable_Cache_Frame_Stat& node) { - std::uint64_t compose_time_ns = node.compose_time_ns; - for (const auto& stat : frame_stats) { - if (stat.parent_object_name == node.object_name && stat.tree_depth == node.tree_depth + 1) - compose_time_ns += cache_subtree_compose_time(frame_stats, stat); - } - return compose_time_ns; - } Renderable_Cache_Aggregate_Stat& cache_stat(const QString& object_name, const QString& parent_object_name, int tree_depth) { for (auto& stat : renderable_cache_stats) { if (stat.object_name == object_name && stat.parent_object_name == parent_object_name) @@ -293,16 +261,19 @@ private: }; struct Performance_Shower_Private; /// @brief 后台渲染性能信息显示图元。 -class Performance_Shower : public Renderable { +class Performance_Shower : public Renderable, public Frame_Lifecycle_Observer { public: /// @brief 创建性能显示图元。 Performance_Shower(); /// @brief 设置性能显示是否启用。 void setEnabled(bool enabled); /// @brief 返回性能显示是否启用。 - bool enabled() const; + bool enabled() const override; /// @brief 收集一帧生命周期记录。 - void collect_frame(const Frame_Lifecycle_Record& frame); + void collect_frame(const Frame_Lifecycle_Record& frame) override; + Renderable* renderable() const override { + return const_cast(this); + } private: Performance_Shower_Private* d(); Render_Object_Owner create_render_data() override; @@ -511,13 +482,13 @@ private: .arg(number_text("manual_limit_ms", feedback.manual_min_render_interval_ms)); } static double cache_total(const Renderable_Cache_Aggregate_Stat& stat) { - return static_cast(stat.hit_count + stat.stale_hit_count + stat.miss_count); + return static_cast(stat.hit_count + stat.miss_count); } - QString cache_ratio_text(const QString& key, std::uint64_t hit, std::uint64_t stale_hit, std::uint64_t miss) { - std::uint64_t total = hit + stale_hit + miss; + QString cache_ratio_text(const QString& key, std::uint64_t hit, std::uint64_t miss) { + std::uint64_t total = hit + miss; if (!total) return stable_text(key, "0.00") + "%"; - return number_text(key, static_cast(hit + stale_hit) * 100.0 / static_cast(total)) + "%"; + return number_text(key, static_cast(hit) * 100.0 / static_cast(total)) + "%"; } QString ns_text(const QString& key, std::uint64_t ns) { return number_text(key, static_cast(ns) / 1000000.0); @@ -567,10 +538,9 @@ private: .arg(indent) .arg(name) .arg(count_text(key + "_cache_hit", stat.hit_count)) - .arg(count_text(key + "_cache_stale_hit", stat.stale_hit_count)) .arg(count_text(key + "_cache_miss", stat.miss_count)) .arg(count_text(key + "_cache_rebuild", stat.rebuild_count)) - .arg(cache_ratio_text(key + "_cache_ratio", stat.hit_count, stat.stale_hit_count, stat.miss_count))); + .arg(cache_ratio_text(key + "_cache_ratio", stat.hit_count, stat.miss_count))); lines.push_back(QString("缓存图像 %1%2 面积:%3 字节:%4 版本:%5/%6") .arg(indent) .arg(name) @@ -679,10 +649,9 @@ private: } const Frame_Lifecycle_Record& frame = aggregate.latest; const Frame_Feedback_Snapshot& feedback = frame.feedback; - std::uint64_t aggregate_cache_total = aggregate.cache_hit_count + aggregate.cache_stale_hit_count + aggregate.cache_miss_count; + std::uint64_t aggregate_cache_total = aggregate.cache_hit_count + aggregate.cache_miss_count; std::uint64_t latest_render_time = frame_render_time_ns(frame); - double exact_cache_ratio = aggregate_cache_total ? static_cast(aggregate.cache_hit_count) * 100.0 / static_cast(aggregate_cache_total) : 0.0; - double usable_cache_ratio = aggregate_cache_total ? static_cast(aggregate.cache_hit_count + aggregate.cache_stale_hit_count) * 100.0 / static_cast(aggregate_cache_total) : 0.0; + double cache_hit_ratio = aggregate_cache_total ? static_cast(aggregate.cache_hit_count) * 100.0 / static_cast(aggregate_cache_total) : 0.0; lines.clear(); lines.push_back(QString("帧:%1 输入版本:%2 结果:%3 当前状态:%4") .arg(count_text("frame_id", frame.frame_id)) @@ -735,14 +704,10 @@ private: lines.push_back(duration_line("frame_total", "生命周期 端到端总耗时", aggregate.frame_total_ms)); lines.push_back(QString("总缓存 命中:%1 过期可用:%2 未命中:%3 精确命中:%4% 可用命中:%5%") .arg(count_text("cache_hit_count", aggregate.cache_hit_count)) - .arg(count_text("cache_stale_hit_count", aggregate.cache_stale_hit_count)) .arg(count_text("cache_miss_count", aggregate.cache_miss_count)) - .arg(number_text("exact_cache_ratio", exact_cache_ratio)) - .arg(number_text("usable_cache_ratio", usable_cache_ratio))); + .arg(number_text("cache_hit_ratio", cache_hit_ratio))); lines.push_back(QString("缓存重建 次数:%1 过期重建:%2 未命中重建:%3 重建耗时:%4ms 合成耗时:%5ms") .arg(count_text("cache_rebuild_count", aggregate.cache_rebuild_count)) - .arg(count_text("cache_stale_rebuild_count", aggregate.cache_stale_rebuild_count)) - .arg(count_text("cache_miss_rebuild_count", aggregate.cache_miss_rebuild_count)) .arg(ns_text("cache_rebuild_time", aggregate.cache_rebuild_time_ns)) .arg(ns_text("cache_compose_time", aggregate.cache_compose_time_ns))); lines.push_back(duration_line("cache_rebuild_slide", "缓存总耗时 重建", aggregate.cache_rebuild_ms)); @@ -756,12 +721,9 @@ private: .arg(ns_ratio_text("cache_compose_aggregate_ratio", aggregate.cache_compose_time_ns, aggregate.render_time_ns))); append_renderable_tree_lines(); append_cache_tree_lines(); - lines.push_back(QString("工作量 原始输入:%1 可见输入:%2 准备输出:%3 点:%4 线段:%5") + lines.push_back(QString("工作量 原始输入:%1 准备输出:%2") .arg(count_text("raw_input_count", frame.raw_input_count)) - .arg(count_text("visible_input_count", frame.visible_input_count)) - .arg(count_text("prepared_output_count", frame.prepared_output_count)) - .arg(count_text("draw_point_count", frame.draw_point_count)) - .arg(count_text("draw_segment_count", frame.draw_segment_count))); + .arg(count_text("prepared_output_count", frame.prepared_output_count))); lines.push_back(QString("Renderable 总数:%1 可见:%2 直接绘制:%3 本地缓存:%4") .arg(count_text("renderable_count", frame.renderable_count)) .arg(count_text("visible_renderable_count", frame.visible_renderable_count)) diff --git a/Renderive/plottable/Planisphere.cpp b/Renderive/plottable/Planisphere.cpp index deade24..e6eb294 100644 --- a/Renderive/plottable/Planisphere.cpp +++ b/Renderive/plottable/Planisphere.cpp @@ -4,22 +4,7 @@ #include "../primitive/Grid.h" #include "Planisphere_p.h" namespace renderive { -using Planisphere_Binding = Renderable_Binding; -Planisphere::Planisphere() { - Planisphere_Binding::init(this, "Planisphere"); -} -Planisphere_Private* Planisphere::d() { - return Planisphere_Binding::d(this); -} -Render_Object_Owner Planisphere::create_render_data() { - return Planisphere_Binding::create_render_data(); -} -Render_Object_Owner Planisphere::create_render_state() { - return Planisphere_Binding::create_render_state(); -} -Render_Object_Owner Planisphere::create_input_data() { - return Planisphere_Binding::create_input_data(); -} +RENDERIVE_DEFINE_RENDERABLE_BINDING(Planisphere, Planisphere_Private, Planisphere_Render_State, Planisphere_Input_Data, "Planisphere") std::shared_ptr Planisphere::i_axis(SRC src) { return d()->state_value(&Planisphere_Render_State::i_axis, src).lock(); } diff --git a/Renderive/plottable/Planisphere_p.h b/Renderive/plottable/Planisphere_p.h index 448b9e0..a345942 100644 --- a/Renderive/plottable/Planisphere_p.h +++ b/Renderive/plottable/Planisphere_p.h @@ -38,24 +38,6 @@ struct Planisphere_Input_Data : Input_Data { void clear() override { data_list.clear(); } - std::uint64_t get_pending_count() const override { - return data_list.get_pending_count(); - } - std::uint64_t get_dropped_count() const override { - return data_list.get_dropped_count(); - } - std::uint64_t get_capacity_dropped_count() const override { - return data_list.get_capacity_dropped_count(); - } - std::uint64_t rebuild_dropped_count() const override { - return data_list.get_rebuild_dropped_count(); - } - std::uint64_t consumer_dropped_count() const override { - return data_list.get_consumer_dropped_count(); - } - std::uint64_t get_pushed_count() const override { - return data_list.get_pushed_count(); - } }; struct Planisphere_Render_State : Render_State, Planisphere_Prop {}; struct Planisphere_Private : Typed_Render_Data { @@ -122,15 +104,5 @@ struct Planisphere_Private : Typed_Render_Datatype() == QEvent::Resize) { - auto e = reinterpret_cast(event); - } - } -}; -struct Planisphere_Private_Access { - static Planisphere_Private* data(Planisphere* planisphere) { - return reinterpret_cast(planisphere->d_ptr); - } }; } // namespace renderive diff --git a/Renderive/plottable/Spectrum.cpp b/Renderive/plottable/Spectrum.cpp index f4cc346..5294c9e 100644 --- a/Renderive/plottable/Spectrum.cpp +++ b/Renderive/plottable/Spectrum.cpp @@ -7,22 +7,7 @@ #include "../primitive/Marker.h" #include "Spectrum_p.h" namespace renderive { -using Spectrum_Binding = Renderable_Binding; -Spectrum::Spectrum() { - Spectrum_Binding::init(this, "Spectrum"); -} -Spectrum_Private* Spectrum::d() { - return Spectrum_Binding::d(this); -} -Render_Object_Owner Spectrum::create_render_data() { - return Spectrum_Binding::create_render_data(); -} -Render_Object_Owner Spectrum::create_render_state() { - return Spectrum_Binding::create_render_state(); -} -Render_Object_Owner Spectrum::create_input_data() { - return Spectrum_Binding::create_input_data(); -} +RENDERIVE_DEFINE_RENDERABLE_BINDING(Spectrum, Spectrum_Private, Spectrum_Render_State, Spectrum_Input_Data, "Spectrum") std::shared_ptr Spectrum::frequency_axis(SRC src) { return d()->state_value(&Spectrum_Render_State::frequency_axis, src).lock(); } @@ -444,7 +429,7 @@ void Spectrum::give_data(std::pmr::vector&& line_data) { Render_Input_Lease input(pd); input->push(std::move(line_data), state->use_max_line, state->use_min_line); } -Update_Ticket Spectrum::submit_data(std::span line_data, const Submit_Options&) { +Update_Ticket Spectrum::submit_data(std::span line_data) { auto update_state = make_update_state(); if (!ok()) { update_state->complete_all(std::make_error_code(std::errc::operation_canceled), Update_Outcome::Cancelled); @@ -465,7 +450,7 @@ Update_Ticket Spectrum::submit_data(std::span line_data, const Sub update_state->complete_until(Update_Stage::Input_Released); return Update_Ticket(update_state); } -Update_Ticket Spectrum::submit_data(std::pmr::vector&& line_data, const Submit_Options&) { +Update_Ticket Spectrum::submit_data(std::pmr::vector&& line_data) { auto update_state = make_update_state(); if (!ok()) { update_state->complete_all(std::make_error_code(std::errc::operation_canceled), Update_Outcome::Cancelled); diff --git a/Renderive/plottable/Spectrum.h b/Renderive/plottable/Spectrum.h index b174718..be67fee 100644 --- a/Renderive/plottable/Spectrum.h +++ b/Renderive/plottable/Spectrum.h @@ -74,9 +74,9 @@ public: /// @brief 移动写入一帧频谱线数据。 void give_data(std::pmr::vector&& line_data); /// @brief 提交一帧频谱线数据并返回完成票据。 - Update_Ticket submit_data(std::span line_data, const Submit_Options& options = {}); + Update_Ticket submit_data(std::span line_data); /// @brief 移动提交一帧频谱线数据并返回完成票据。 - Update_Ticket submit_data(std::pmr::vector&& line_data, const Submit_Options& options = {}); + Update_Ticket submit_data(std::pmr::vector&& line_data); /// @brief 用 writer 填充并写入一帧频谱线数据。 template void write_data(std::size_t count, Writer&& writer) { diff --git a/Renderive/plottable/Spectrum_p.h b/Renderive/plottable/Spectrum_p.h index 6cdb0f0..ebea235 100644 --- a/Renderive/plottable/Spectrum_p.h +++ b/Renderive/plottable/Spectrum_p.h @@ -9,7 +9,6 @@ #include "../base/Memory.h" #include "Hover_Info.h" #include "Interpolation_p.h" -#include "Performance_Shower_p.h" #include "Spectrum.h" namespace renderive { struct Spectrum_Marker { @@ -21,22 +20,16 @@ struct Spectrum_Marker { return qFuzzyCompare(frequency, other.frequency) && draw_line == other.draw_line; } }; -struct Spectrum_Input_Data : Input_Data { +struct Spectrum_Input_Data : Latest_Input_Data { std::pmr::vector cur_data{memory_resource(Memory_Domain::Spectrum)}; std::pmr::vector max_data{memory_resource(Memory_Domain::Spectrum)}; std::pmr::vector min_data{memory_resource(Memory_Domain::Spectrum)}; bool has_data = false; bool has_max_data = false; bool has_min_data = false; - std::atomic pending_count{}; - std::atomic dropped_count{}; - std::atomic pushed_count{}; void push(std::span data, bool use_max, bool use_min) { - if (has_data) - dropped_count.fetch_add(1, std::memory_order_relaxed); cur_data.assign(data.begin(), data.end()); has_data = true; - pending_count.store(1, std::memory_order_relaxed); if (use_max) { if (!has_max_data || max_data.size() != data.size()) { max_data.assign(data.begin(), data.end()); @@ -61,14 +54,11 @@ struct Spectrum_Input_Data : Input_Data { } } } - pushed_count.fetch_add(1, std::memory_order_relaxed); + mark_latest_pushed(); } void push(std::pmr::vector&& data, bool use_max, bool use_min) { - if (has_data) - dropped_count.fetch_add(1, std::memory_order_relaxed); cur_data = std::move(data); has_data = true; - pending_count.store(1, std::memory_order_relaxed); if (use_max) { if (!has_max_data || max_data.size() != cur_data.size()) { max_data.assign(cur_data.begin(), cur_data.end()); @@ -93,7 +83,7 @@ struct Spectrum_Input_Data : Input_Data { } } } - pushed_count.fetch_add(1, std::memory_order_relaxed); + mark_latest_pushed(); } template void read_all(Handler handler) { @@ -108,19 +98,7 @@ struct Spectrum_Input_Data : Input_Data { has_data = false; has_max_data = false; has_min_data = false; - pending_count.store(0, std::memory_order_relaxed); - } - std::uint64_t get_pending_count() const override { - return pending_count.load(std::memory_order_relaxed); - } - std::uint64_t get_dropped_count() const override { - return dropped_count.load(std::memory_order_relaxed); - } - std::uint64_t get_capacity_dropped_count() const override { - return dropped_count.load(std::memory_order_relaxed); - } - std::uint64_t get_pushed_count() const override { - return pushed_count.load(std::memory_order_relaxed); + clear_latest(); } }; struct Spectrum_Render_State : Render_State, Hover_Info_Render_State, Spectrum_PROP { diff --git a/Renderive/plottable/Sweep_Frequency.cpp b/Renderive/plottable/Sweep_Frequency.cpp index c186a98..6d1fb36 100644 --- a/Renderive/plottable/Sweep_Frequency.cpp +++ b/Renderive/plottable/Sweep_Frequency.cpp @@ -3,22 +3,7 @@ #include "../base/Memory.h" #include "Sweep_Frequency_p.h" namespace renderive { -using Sweep_Frequency_Binding = Renderable_Binding; -Sweep_Frequency::Sweep_Frequency() { - Sweep_Frequency_Binding::init(this, "Sweep_Frequency"); -} -Sweep_Frequency_Private* Sweep_Frequency::d() { - return Sweep_Frequency_Binding::d(this); -} -Render_Object_Owner Sweep_Frequency::create_render_data() { - return Sweep_Frequency_Binding::create_render_data(); -} -Render_Object_Owner Sweep_Frequency::create_render_state() { - return Sweep_Frequency_Binding::create_render_state(); -} -Render_Object_Owner Sweep_Frequency::create_input_data() { - return Sweep_Frequency_Binding::create_input_data(); -} +RENDERIVE_DEFINE_RENDERABLE_BINDING(Sweep_Frequency, Sweep_Frequency_Private, Sweep_Frequency_Render_State, Sweep_Frequency_Input_Data, "Sweep_Frequency") std::shared_ptr Sweep_Frequency::frequency_axis(SRC src) { return d()->state_value(&Sweep_Frequency_Render_State::frequency_axis, src).lock(); } diff --git a/Renderive/plottable/Sweep_Frequency_p.h b/Renderive/plottable/Sweep_Frequency_p.h index 740f87a..574c788 100644 --- a/Renderive/plottable/Sweep_Frequency_p.h +++ b/Renderive/plottable/Sweep_Frequency_p.h @@ -14,24 +14,6 @@ struct Sweep_Frequency_Input_Data : renderive::Input_Data { void clear() override { data.clear(); } - std::uint64_t get_pending_count() const override { - return data.pending_count(); - } - std::uint64_t get_dropped_count() const override { - return data.dropped_count(); - } - std::uint64_t get_capacity_dropped_count() const override { - return data.capacity_dropped_count(); - } - std::uint64_t rebuild_dropped_count() const override { - return data.rebuild_dropped_count(); - } - std::uint64_t consumer_dropped_count() const override { - return data.consumer_dropped_count(); - } - std::uint64_t get_pushed_count() const override { - return data.pushed_count(); - } }; struct Sweep_Frequency_Private : renderive::Typed_Render_Data { std::vector frequency_list; diff --git a/Renderive/plottable/Waterfall.cpp b/Renderive/plottable/Waterfall.cpp index 0fc161d..4f17e2d 100644 --- a/Renderive/plottable/Waterfall.cpp +++ b/Renderive/plottable/Waterfall.cpp @@ -2,22 +2,7 @@ #include "../base/Memory.h" #include "Waterfall_p.h" namespace renderive { -using Waterfall_Binding = Renderable_Binding; -Waterfall::Waterfall() { - Waterfall_Binding::init(this, "Waterfall"); -} -Waterfall_Private* Waterfall::d() { - return Waterfall_Binding::d(this); -} -Render_Object_Owner Waterfall::create_render_data() { - return Waterfall_Binding::create_render_data(); -} -Render_Object_Owner Waterfall::create_render_state() { - return Waterfall_Binding::create_render_state(); -} -Render_Object_Owner Waterfall::create_input_data() { - return Waterfall_Binding::create_input_data(); -} +RENDERIVE_DEFINE_RENDERABLE_BINDING(Waterfall, Waterfall_Private, Waterfall_Render_State, Waterfall_Input_Data, "Waterfall") std::shared_ptr Waterfall::frequency_axis(SRC src) { return d()->state_value(&Waterfall_Render_State::frequency_axis, src).lock(); } @@ -129,7 +114,7 @@ void Waterfall::give_data(QTime time, std::pmr::vector&& data) { Render_Input_Lease input(d()); input->push(tick, std::move(data)); } -Update_Ticket Waterfall::submit_data(int tick, std::span data, const Submit_Options&) { +Update_Ticket Waterfall::submit_data(int tick, std::span data) { auto state = make_update_state(); if (!ok()) { state->complete_all(std::make_error_code(std::errc::operation_canceled), Update_Outcome::Cancelled); @@ -143,7 +128,7 @@ Update_Ticket Waterfall::submit_data(int tick, std::span data, con state->complete_until(Update_Stage::Input_Released); return Update_Ticket(state); } -Update_Ticket Waterfall::submit_data(int tick, std::pmr::vector&& data, const Submit_Options&) { +Update_Ticket Waterfall::submit_data(int tick, std::pmr::vector&& data) { auto state = make_update_state(); if (!ok()) { state->complete_all(std::make_error_code(std::errc::operation_canceled), Update_Outcome::Cancelled); diff --git a/Renderive/plottable/Waterfall.h b/Renderive/plottable/Waterfall.h index b62cda2..17f1ccf 100644 --- a/Renderive/plottable/Waterfall.h +++ b/Renderive/plottable/Waterfall.h @@ -34,9 +34,9 @@ public: /// @brief 移动写入指定时间对应的一行频谱数据。 void give_data(QTime time, std::pmr::vector&& data); /// @brief 提交指定 tick 对应的一行频谱数据并返回完成票据。 - Update_Ticket submit_data(int tick, std::span data, const Submit_Options& options = {}); + Update_Ticket submit_data(int tick, std::span data); /// @brief 移动提交指定 tick 对应的一行频谱数据并返回完成票据。 - Update_Ticket submit_data(int tick, std::pmr::vector&& data, const Submit_Options& options = {}); + Update_Ticket submit_data(int tick, std::pmr::vector&& data); /// @brief 用 writer 填充并写入指定 tick 对应的一行频谱数据。 template void write_data(int tick, std::size_t count, Writer&& writer) { @@ -80,7 +80,6 @@ struct Waterfall_Prop { Range frequency_range{0, 10}; Range power_range{0, 10}; int frequency_point_size{}; - int tick_space = 50; bool visible_range_only = true; Image_Interpolation_Mode interpolation_mode = Image_Interpolation_Mode::Nearest; Waterfall_Update_Mode update_mode = Waterfall_Update_Mode::Batch; diff --git a/Renderive/plottable/Waterfall_p.h b/Renderive/plottable/Waterfall_p.h index 77cb643..94c9236 100644 --- a/Renderive/plottable/Waterfall_p.h +++ b/Renderive/plottable/Waterfall_p.h @@ -1,7 +1,6 @@ #pragma once #include #include -#include #include #include #include @@ -12,7 +11,7 @@ #include #include "../Axis/Frequency_Axis_p.h" #include "../Axis/Time_Axis_p.h" -#include "../architecture/Bounded_Input_Buffer.h" +#include "../architecture/Render_Time.h" #include "../plot/Plot_p.h" #include "../architecture/Renderable.h" #include "../base/Memory.h" @@ -22,88 +21,53 @@ #include "Interpolation_p.h" #include "Waterfall.h" namespace renderive { -inline std::uint64_t waterfall_now_ns() { - return static_cast(std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count()); -} struct Waterfall_Data { int tick; std::pmr::vector frequency{memory_resource(Memory_Domain::Waterfall)}; }; struct Waterfall_Input_Data : Input_Data { static constexpr std::size_t Max_Pending_Row_Count = 256; - Bounded_Input_Buffer data_list; - std::pmr::vector write_buffer{memory_resource(Memory_Domain::Waterfall)}; - std::pmr::vector read_frequency{memory_resource(Memory_Domain::Waterfall)}; - std::array, Max_Pending_Row_Count> owned_rows; - std::size_t owned_row_count{}; - std::atomic owned_pending_count{}; - std::atomic owned_dropped_count{}; - std::atomic owned_pushed_count{}; + std::array, Max_Pending_Row_Count> rows; + std::size_t row_count{}; void push(int tick, std::span data) { - std::size_t data_size = static_cast(data.size()) * sizeof(double); - write_buffer.resize(sizeof(tick) + data_size); - std::memcpy(write_buffer.data(), &tick, sizeof(tick)); - std::memcpy(write_buffer.data() + sizeof(tick), data.data(), data_size); - data_list.push(write_buffer.data(), write_buffer.size(), Max_Pending_Row_Count); + while (row_count >= Max_Pending_Row_Count) + drop_front(); + rows[row_count].emplace(); + rows[row_count]->tick = tick; + rows[row_count]->frequency.assign(data.begin(), data.end()); + ++row_count; } void push(int tick, std::pmr::vector&& data) { - while (owned_row_count >= Max_Pending_Row_Count) - drop_owned_front(); - owned_rows[owned_row_count].emplace(); - owned_rows[owned_row_count]->tick = tick; - owned_rows[owned_row_count]->frequency = std::move(data); - ++owned_row_count; - owned_pending_count.store(owned_row_count, std::memory_order_relaxed); - owned_pushed_count.fetch_add(1, std::memory_order_relaxed); + while (row_count >= Max_Pending_Row_Count) + drop_front(); + rows[row_count].emplace(); + rows[row_count]->tick = tick; + rows[row_count]->frequency = std::move(data); + ++row_count; } template void read_all(Handler handler) { - data_list.read_all([this, &handler](const void* data, std::size_t size) { - int tick; - std::memcpy(&tick, data, sizeof(tick)); - std::size_t data_size = size - sizeof(tick); - read_frequency.resize(static_cast(data_size / sizeof(double))); - std::memcpy(read_frequency.data(), static_cast(data) + sizeof(tick), data_size); - handler(tick, read_frequency); - }); - for (std::size_t i = 0; i < owned_row_count; ++i) - handler(owned_rows[i]->tick, owned_rows[i]->frequency); - owned_row_count = 0; - owned_pending_count.store(0, std::memory_order_relaxed); + for (std::size_t i = 0; i < row_count; ++i) + handler(rows[i]->tick, rows[i]->frequency); + clear_rows(); } void clear() override { - data_list.clear(); - owned_row_count = 0; - owned_pending_count.store(0, std::memory_order_relaxed); - } - std::uint64_t get_pending_count() const override { - return data_list.get_pending_count() + owned_pending_count.load(std::memory_order_relaxed); - } - std::uint64_t get_dropped_count() const override { - return data_list.get_dropped_count() + owned_dropped_count.load(std::memory_order_relaxed); - } - std::uint64_t get_capacity_dropped_count() const override { - return data_list.get_capacity_dropped_count() + owned_dropped_count.load(std::memory_order_relaxed); - } - std::uint64_t rebuild_dropped_count() const override { - return data_list.get_rebuild_dropped_count(); - } - std::uint64_t consumer_dropped_count() const override { - return data_list.get_consumer_dropped_count(); - } - std::uint64_t get_pushed_count() const override { - return data_list.get_pushed_count() + owned_pushed_count.load(std::memory_order_relaxed); + clear_rows(); } + void record_consumer_dropped() {} private: - void drop_owned_front() { - owned_rows[0].reset(); - for (std::size_t i = 1; i < owned_row_count; ++i) { - owned_rows[i - 1].emplace(std::move(*owned_rows[i])); - owned_rows[i].reset(); + void clear_rows() { + for (std::size_t i = 0; i < row_count; ++i) + rows[i].reset(); + row_count = 0; + } + void drop_front() { + rows[0].reset(); + for (std::size_t i = 1; i < row_count; ++i) { + rows[i - 1].emplace(std::move(*rows[i])); + rows[i].reset(); } - --owned_row_count; - owned_pending_count.store(owned_row_count, std::memory_order_relaxed); - owned_dropped_count.fetch_add(1, std::memory_order_relaxed); + --row_count; } }; struct Waterfall_Render_State : Render_State, Hover_Info_Render_State, Waterfall_Prop {}; @@ -187,7 +151,7 @@ struct Waterfall_Private : Typed_Render_Data frequency_data, int tick, int col_count) { if (frequency_data.size() != col_count) { - data->data_list.record_consumer_dropped(); + data->record_consumer_dropped(); return false; } ring_buffer.push_data(frequency_data.data(), tick); @@ -195,7 +159,7 @@ struct Waterfall_Private : Typed_Render_Data& frequency_data, int tick, int col_count, Waterfall_Update_Mode update_mode) { if (frequency_data.size() != col_count) { - data->data_list.record_consumer_dropped(); + data->record_consumer_dropped(); return false; } ring_buffer.push_data(frequency_data.data(), tick); @@ -209,7 +173,7 @@ struct Waterfall_Private : Typed_Render_Datadata_list.record_consumer_dropped(); + data->record_consumer_dropped(); } } void prepare_data(const Plot_Render_Snapshot& snapshot) override { @@ -240,7 +204,7 @@ struct Waterfall_Private : Typed_Render_Dataread_all([data, col_count, &latest, &has_latest, &valid_rows](int tick, std::pmr::vector& frequency_data) { if (frequency_data.size() != col_count) { - data->data_list.record_consumer_dropped(); + data->record_consumer_dropped(); return; } latest.tick = tick; @@ -250,7 +214,7 @@ struct Waterfall_Private : Typed_Render_Dataupdate_mode == Waterfall_Update_Mode::Timed_Latest && last_line_commit_ns != 0) { std::uint64_t interval_ns = static_cast(qMax(1, s->update_interval_ms)) * 1000000ull; allow_commit = now_ns - last_line_commit_ns >= interval_ns; @@ -375,9 +339,4 @@ struct Waterfall_Private : Typed_Render_Data(waterfall->d_ptr); - } -}; } // namespace renderive diff --git a/Renderive/plottable/export.h b/Renderive/plottable/export.h index 90343fd..a584acc 100644 --- a/Renderive/plottable/export.h +++ b/Renderive/plottable/export.h @@ -8,3 +8,12 @@ #include "Spectrum.h" #include "Sweep_Frequency.h" #include "Waterfall.h" + +namespace renderive { +class Abs_Plot; +class Performance_Shower; +LIB_DECL std::shared_ptr attach_performance_shower(Abs_Plot& plot); +LIB_DECL void detach_performance_shower(Abs_Plot& plot); +LIB_DECL bool performance_shower_enabled(const Abs_Plot& plot); +LIB_DECL void set_performance_shower_enabled(Abs_Plot& plot, bool enabled); +} // namespace renderive diff --git a/Renderive/primitive/Band_Region.cpp b/Renderive/primitive/Band_Region.cpp index b8e358f..e1456f4 100644 --- a/Renderive/primitive/Band_Region.cpp +++ b/Renderive/primitive/Band_Region.cpp @@ -34,34 +34,9 @@ struct Band_Region_Private : Typed_Render_Datarestore(); } }; -using Band_Region_Binding = Renderable_Binding; -Band_Region::Band_Region() { - Band_Region_Binding::init(this, "BandRegion"); -} -Band_Region_Private* Band_Region::d() { - return Band_Region_Binding::d(this); -} -Render_Object_Owner Band_Region::create_render_data() { - return Band_Region_Binding::create_render_data(); -} -Render_Object_Owner Band_Region::create_render_state() { - return Band_Region_Binding::create_render_state(); -} -Render_Object_Owner Band_Region::create_input_data() { - return Band_Region_Binding::create_input_data(); -} -std::shared_ptr Band_Region::x_axis(SRC src) { - return d()->state_value(&Band_Region_Render_State::x_axis, src).lock(); -} -void Band_Region::set_x_axis(std::shared_ptr value) { - d()->set_state_value(&Band_Region_Render_State::x_axis, std::weak_ptr(value)); -} -std::shared_ptr Band_Region::y_axis(SRC src) { - return d()->state_value(&Band_Region_Render_State::y_axis, src).lock(); -} -void Band_Region::set_y_axis(std::shared_ptr value) { - d()->set_state_value(&Band_Region_Render_State::y_axis, std::weak_ptr(value)); -} +RENDERIVE_DEFINE_RENDERABLE_BINDING(Band_Region, Band_Region_Private, Band_Region_Render_State, Input_Data, "BandRegion") +RENDERIVE_DEFINE_WEAK_STATE_PROP(Band_Region, Band_Region_Render_State, Abs_Axis, x_axis) +RENDERIVE_DEFINE_WEAK_STATE_PROP(Band_Region, Band_Region_Render_State, Abs_Axis, y_axis) Range Band_Region::range(SRC src) { return d()->state_value(&Band_Region_Render_State::range, src); } @@ -70,24 +45,9 @@ void Band_Region::set_range(Range value) { return; d()->set_state_value(&Band_Region_Render_State::range, value); } -Band_Region_Orientation Band_Region::orientation(SRC src) { - return d()->state_value(&Band_Region_Render_State::orientation, src); -} -void Band_Region::set_orientation(Band_Region_Orientation value) { - d()->set_state_value(&Band_Region_Render_State::orientation, value); -} -QBrush Band_Region::brush(SRC src) { - return d()->state_value(&Band_Region_Render_State::brush, src); -} -void Band_Region::set_brush(QBrush value) { - d()->set_state_value(&Band_Region_Render_State::brush, std::move(value)); -} -QPen Band_Region::pen(SRC src) { - return d()->state_value(&Band_Region_Render_State::pen, src); -} -void Band_Region::set_pen(QPen value) { - d()->set_state_value(&Band_Region_Render_State::pen, std::move(value)); -} +RENDERIVE_DEFINE_STATE_PROP(Band_Region, Band_Region_Render_State, Band_Region_Orientation, orientation) +RENDERIVE_DEFINE_STATE_PROP(Band_Region, Band_Region_Render_State, QBrush, brush) +RENDERIVE_DEFINE_STATE_PROP(Band_Region, Band_Region_Render_State, QPen, pen) Band_Region::Builder::Builder(std::shared_ptr parent, std::shared_ptr x_axis, std::shared_ptr y_axis) { ASSERT(parent, "Band_Region build error! parent == nullptr"); ASSERT(x_axis && y_axis, "Band_Region build error! axis == nullptr"); diff --git a/Renderive/primitive/Color_Bar.cpp b/Renderive/primitive/Color_Bar.cpp index e3de545..993d203 100644 --- a/Renderive/primitive/Color_Bar.cpp +++ b/Renderive/primitive/Color_Bar.cpp @@ -71,28 +71,8 @@ struct Color_Bar_Private : Typed_Render_Datarestore(); } }; -using Color_Bar_Binding = Renderable_Binding; -Color_Bar::Color_Bar() { - Color_Bar_Binding::init(this, "ColorBar"); -} -Color_Bar_Private* Color_Bar::d() { - return Color_Bar_Binding::d(this); -} -Render_Object_Owner Color_Bar::create_render_data() { - return Color_Bar_Binding::create_render_data(); -} -Render_Object_Owner Color_Bar::create_render_state() { - return Color_Bar_Binding::create_render_state(); -} -Render_Object_Owner Color_Bar::create_input_data() { - return Color_Bar_Binding::create_input_data(); -} -Color_Map Color_Bar::color_map(SRC src) { - return d()->state_value(&Color_Bar_Render_State::color_map, src); -} -void Color_Bar::set_color_map(Color_Map value) { - d()->set_state_value(&Color_Bar_Render_State::color_map, std::move(value)); -} +RENDERIVE_DEFINE_RENDERABLE_BINDING(Color_Bar, Color_Bar_Private, Color_Bar_Render_State, Input_Data, "ColorBar") +RENDERIVE_DEFINE_STATE_PROP(Color_Bar, Color_Bar_Render_State, Color_Map, color_map) Range Color_Bar::range(SRC src) { return d()->state_value(&Color_Bar_Render_State::range, src); } @@ -101,48 +81,13 @@ void Color_Bar::set_range(Range value) { return; d()->set_state_value(&Color_Bar_Render_State::range, value); } -QString Color_Bar::name(SRC src) { - return d()->state_value(&Color_Bar_Render_State::name, src); -} -void Color_Bar::set_name(QString value) { - d()->set_state_value(&Color_Bar_Render_State::name, std::move(value)); -} -QString Color_Bar::unit(SRC src) { - return d()->state_value(&Color_Bar_Render_State::unit, src); -} -void Color_Bar::set_unit(QString value) { - d()->set_state_value(&Color_Bar_Render_State::unit, std::move(value)); -} -QRectF Color_Bar::pixel_rect(SRC src) { - return d()->state_value(&Color_Bar_Render_State::pixel_rect, src); -} -void Color_Bar::set_pixel_rect(QRectF value) { - d()->set_state_value(&Color_Bar_Render_State::pixel_rect, value); -} -Qt::Orientation Color_Bar::orientation(SRC src) { - return d()->state_value(&Color_Bar_Render_State::orientation, src); -} -void Color_Bar::set_orientation(Qt::Orientation value) { - d()->set_state_value(&Color_Bar_Render_State::orientation, value); -} -QFont Color_Bar::font(SRC src) { - return d()->state_value(&Color_Bar_Render_State::font, src); -} -void Color_Bar::set_font(QFont value) { - d()->set_state_value(&Color_Bar_Render_State::font, std::move(value)); -} -QPen Color_Bar::text_pen(SRC src) { - return d()->state_value(&Color_Bar_Render_State::text_pen, src); -} -void Color_Bar::set_text_pen(QPen value) { - d()->set_state_value(&Color_Bar_Render_State::text_pen, std::move(value)); -} -QPen Color_Bar::border_pen(SRC src) { - return d()->state_value(&Color_Bar_Render_State::border_pen, src); -} -void Color_Bar::set_border_pen(QPen value) { - d()->set_state_value(&Color_Bar_Render_State::border_pen, std::move(value)); -} +RENDERIVE_DEFINE_STATE_PROP(Color_Bar, Color_Bar_Render_State, QString, name) +RENDERIVE_DEFINE_STATE_PROP(Color_Bar, Color_Bar_Render_State, QString, unit) +RENDERIVE_DEFINE_STATE_PROP(Color_Bar, Color_Bar_Render_State, QRectF, pixel_rect) +RENDERIVE_DEFINE_STATE_PROP(Color_Bar, Color_Bar_Render_State, Qt::Orientation, orientation) +RENDERIVE_DEFINE_STATE_PROP(Color_Bar, Color_Bar_Render_State, QFont, font) +RENDERIVE_DEFINE_STATE_PROP(Color_Bar, Color_Bar_Render_State, QPen, text_pen) +RENDERIVE_DEFINE_STATE_PROP(Color_Bar, Color_Bar_Render_State, QPen, border_pen) Color_Bar::Builder::Builder(std::shared_ptr parent) { ASSERT(parent && parent->plot, "Color_Bar build error! parent invalid"); this->parent = parent; diff --git a/Renderive/primitive/Curve.cpp b/Renderive/primitive/Curve.cpp index 8050f0c..a931ba7 100644 --- a/Renderive/primitive/Curve.cpp +++ b/Renderive/primitive/Curve.cpp @@ -6,53 +6,33 @@ enum class Curve_Input_Mode : std::uint8_t { Samples, Points }; -struct Curve_Input_Data : Input_Data { +struct Curve_Input_Data : Latest_Input_Data { std::pmr::vector samples{memory_resource(Memory_Domain::Curve)}; std::pmr::vector points{memory_resource(Memory_Domain::Curve)}; Curve_Input_Mode mode = Curve_Input_Mode::None; - bool pending = false; - std::atomic pending_count{}; - std::atomic dropped_count{}; - std::atomic pushed_count{}; void push_samples(std::span values) { - if (pending) - dropped_count.fetch_add(1, std::memory_order_relaxed); samples.assign(values.begin(), values.end()); points.clear(); mode = Curve_Input_Mode::Samples; - pending = true; - pending_count.store(1, std::memory_order_relaxed); - pushed_count.fetch_add(1, std::memory_order_relaxed); + mark_latest_pushed(); } void push_samples(std::pmr::vector&& values) { - if (pending) - dropped_count.fetch_add(1, std::memory_order_relaxed); samples = std::move(values); points.clear(); mode = Curve_Input_Mode::Samples; - pending = true; - pending_count.store(1, std::memory_order_relaxed); - pushed_count.fetch_add(1, std::memory_order_relaxed); + mark_latest_pushed(); } void push_points(std::span values) { - if (pending) - dropped_count.fetch_add(1, std::memory_order_relaxed); points.assign(values.begin(), values.end()); samples.clear(); mode = Curve_Input_Mode::Points; - pending = true; - pending_count.store(1, std::memory_order_relaxed); - pushed_count.fetch_add(1, std::memory_order_relaxed); + mark_latest_pushed(); } void push_points(std::pmr::vector&& values) { - if (pending) - dropped_count.fetch_add(1, std::memory_order_relaxed); points = std::move(values); samples.clear(); mode = Curve_Input_Mode::Points; - pending = true; - pending_count.store(1, std::memory_order_relaxed); - pushed_count.fetch_add(1, std::memory_order_relaxed); + mark_latest_pushed(); } template void read_all(Handler handler) { @@ -64,20 +44,7 @@ struct Curve_Input_Data : Input_Data { samples.clear(); points.clear(); mode = Curve_Input_Mode::None; - pending = false; - pending_count.store(0, std::memory_order_relaxed); - } - std::uint64_t get_pending_count() const override { - return pending_count.load(std::memory_order_relaxed); - } - std::uint64_t get_dropped_count() const override { - return dropped_count.load(std::memory_order_relaxed); - } - std::uint64_t get_capacity_dropped_count() const override { - return dropped_count.load(std::memory_order_relaxed); - } - std::uint64_t get_pushed_count() const override { - return pushed_count.load(std::memory_order_relaxed); + clear_latest(); } }; struct Curve_Render_State : Render_State, Curve_Prop {}; @@ -136,22 +103,7 @@ struct Curve_Private : Typed_Render_Data; -Curve::Curve() { - Curve_Binding::init(this, "Curve"); -} -Curve_Private* Curve::d() { - return Curve_Binding::d(this); -} -Render_Object_Owner Curve::create_render_data() { - return Curve_Binding::create_render_data(); -} -Render_Object_Owner Curve::create_render_state() { - return Curve_Binding::create_render_state(); -} -Render_Object_Owner Curve::create_input_data() { - return Curve_Binding::create_input_data(); -} +RENDERIVE_DEFINE_RENDERABLE_BINDING(Curve, Curve_Private, Curve_Render_State, Curve_Input_Data, "Curve") void Curve::give_samples(std::span values, bool notify_render) { if (notify_render && !ok()) return; @@ -170,7 +122,7 @@ void Curve::give_samples(std::pmr::vector&& values, bool notify_render) Render_Input_Lease input(d(), notify_render); input->push_samples(std::move(values)); } -Update_Ticket Curve::submit_samples(std::span values, const Submit_Options&) { +Update_Ticket Curve::submit_samples(std::span values) { auto state = make_update_state(); if (!ok()) { state->complete_all(std::make_error_code(std::errc::operation_canceled), Update_Outcome::Cancelled); @@ -184,7 +136,7 @@ Update_Ticket Curve::submit_samples(std::span values, const Submit state->complete_until(Update_Stage::Input_Released); return Update_Ticket(state); } -Update_Ticket Curve::submit_samples(std::pmr::vector&& values, const Submit_Options&) { +Update_Ticket Curve::submit_samples(std::pmr::vector&& values) { auto state = make_update_state(); if (!ok()) { state->complete_all(std::make_error_code(std::errc::operation_canceled), Update_Outcome::Cancelled); @@ -216,7 +168,7 @@ void Curve::give_points(std::pmr::vector&& points, bool notify_render) Render_Input_Lease input(d(), notify_render); input->push_points(std::move(points)); } -Update_Ticket Curve::submit_points(std::span points, const Submit_Options&) { +Update_Ticket Curve::submit_points(std::span points) { auto state = make_update_state(); if (!ok()) { state->complete_all(std::make_error_code(std::errc::operation_canceled), Update_Outcome::Cancelled); @@ -230,7 +182,7 @@ Update_Ticket Curve::submit_points(std::span points, const Submit state->complete_until(Update_Stage::Input_Released); return Update_Ticket(state); } -Update_Ticket Curve::submit_points(std::pmr::vector&& points, const Submit_Options&) { +Update_Ticket Curve::submit_points(std::pmr::vector&& points) { auto state = make_update_state(); if (!ok()) { state->complete_all(std::make_error_code(std::errc::operation_canceled), Update_Outcome::Cancelled); @@ -244,18 +196,8 @@ Update_Ticket Curve::submit_points(std::pmr::vector&& points, const Sub state->complete_until(Update_Stage::Input_Released); return Update_Ticket(state); } -std::shared_ptr Curve::x_axis(SRC src) { - return d()->state_value(&Curve_Render_State::x_axis, src).lock(); -} -void Curve::set_x_axis(std::shared_ptr value) { - d()->set_state_value(&Curve_Render_State::x_axis, std::weak_ptr(value)); -} -std::shared_ptr Curve::y_axis(SRC src) { - return d()->state_value(&Curve_Render_State::y_axis, src).lock(); -} -void Curve::set_y_axis(std::shared_ptr value) { - d()->set_state_value(&Curve_Render_State::y_axis, std::weak_ptr(value)); -} +RENDERIVE_DEFINE_WEAK_STATE_PROP(Curve, Curve_Render_State, Abs_Axis, x_axis) +RENDERIVE_DEFINE_WEAK_STATE_PROP(Curve, Curve_Render_State, Abs_Axis, y_axis) Range Curve::data_range(SRC src) { return d()->state_value(&Curve_Render_State::data_range, src); } @@ -264,42 +206,12 @@ void Curve::set_data_range(Range value) { return; d()->set_state_value(&Curve_Render_State::data_range, value); } -QPen Curve::pen(SRC src) { - return d()->state_value(&Curve_Render_State::pen, src); -} -void Curve::set_pen(QPen value) { - d()->set_state_value(&Curve_Render_State::pen, std::move(value)); -} -QBrush Curve::fill_brush(SRC src) { - return d()->state_value(&Curve_Render_State::fill_brush, src); -} -void Curve::set_fill_brush(QBrush value) { - d()->set_state_value(&Curve_Render_State::fill_brush, std::move(value)); -} -bool Curve::visible_range_only(SRC src) { - return d()->state_value(&Curve_Render_State::visible_range_only, src); -} -void Curve::set_visible_range_only(bool value) { - d()->set_state_value(&Curve_Render_State::visible_range_only, value); -} -bool Curve::antialias(SRC src) { - return d()->state_value(&Curve_Render_State::antialias, src); -} -void Curve::set_antialias(bool value) { - d()->set_state_value(&Curve_Render_State::antialias, value); -} -Line_Interpolation_Mode Curve::interpolation_mode(SRC src) { - return d()->state_value(&Curve_Render_State::interpolation_mode, src); -} -void Curve::set_interpolation_mode(Line_Interpolation_Mode value) { - d()->set_state_value(&Curve_Render_State::interpolation_mode, value); -} -Curve_Sample_Mode Curve::sample_mode(SRC src) { - return d()->state_value(&Curve_Render_State::sample_mode, src); -} -void Curve::set_sample_mode(Curve_Sample_Mode value) { - d()->set_state_value(&Curve_Render_State::sample_mode, value); -} +RENDERIVE_DEFINE_STATE_PROP(Curve, Curve_Render_State, QPen, pen) +RENDERIVE_DEFINE_STATE_PROP(Curve, Curve_Render_State, QBrush, fill_brush) +RENDERIVE_DEFINE_STATE_PROP(Curve, Curve_Render_State, bool, visible_range_only) +RENDERIVE_DEFINE_STATE_PROP(Curve, Curve_Render_State, bool, antialias) +RENDERIVE_DEFINE_STATE_PROP(Curve, Curve_Render_State, Line_Interpolation_Mode, interpolation_mode) +RENDERIVE_DEFINE_STATE_PROP(Curve, Curve_Render_State, Curve_Sample_Mode, sample_mode) Curve::Builder::Builder(std::shared_ptr parent, std::shared_ptr x_axis, std::shared_ptr y_axis) { ASSERT(parent, "Curve build error! parent == nullptr"); ASSERT(x_axis && y_axis, "Curve build error! axis == nullptr"); diff --git a/Renderive/primitive/Curve.h b/Renderive/primitive/Curve.h index 4d729f9..bf169e4 100644 --- a/Renderive/primitive/Curve.h +++ b/Renderive/primitive/Curve.h @@ -54,9 +54,9 @@ public: /// @brief 移动写入按 data_range 均匀分布的采样值。 void give_samples(std::pmr::vector&& values, bool notify_render = true); /// @brief 提交采样值并返回完成票据。 - Update_Ticket submit_samples(std::span values, const Submit_Options& options = {}); + Update_Ticket submit_samples(std::span values); /// @brief 移动提交采样值并返回完成票据。 - Update_Ticket submit_samples(std::pmr::vector&& values, const Submit_Options& options = {}); + Update_Ticket submit_samples(std::pmr::vector&& values); /// @brief 写入容器中的采样值。 template void give_samples(const Values& values, bool notify_render = true) { @@ -75,9 +75,9 @@ public: /// @brief 移动写入显式坐标点。 void give_points(std::pmr::vector&& points, bool notify_render = true); /// @brief 提交显式坐标点并返回完成票据。 - Update_Ticket submit_points(std::span points, const Submit_Options& options = {}); + Update_Ticket submit_points(std::span points); /// @brief 移动提交显式坐标点并返回完成票据。 - Update_Ticket submit_points(std::pmr::vector&& points, const Submit_Options& options = {}); + Update_Ticket submit_points(std::pmr::vector&& points); /// @brief 写入容器中的显式坐标点。 template void give_points(const Points& points, bool notify_render = true) { diff --git a/Renderive/primitive/Fill_Area.cpp b/Renderive/primitive/Fill_Area.cpp index ace3a3e..23c7184 100644 --- a/Renderive/primitive/Fill_Area.cpp +++ b/Renderive/primitive/Fill_Area.cpp @@ -3,27 +3,15 @@ #include "../base/Frame_Memory.h" #include "../base/Memory.h" namespace renderive { -struct Fill_Area_Input_Data : Input_Data { +struct Fill_Area_Input_Data : Latest_Input_Data { std::pmr::vector points{memory_resource(Memory_Domain::Curve)}; - bool pending = false; - std::atomic pending_count{}; - std::atomic dropped_count{}; - std::atomic pushed_count{}; void push(std::span values) { - if (pending) - dropped_count.fetch_add(1, std::memory_order_relaxed); points.assign(values.begin(), values.end()); - pending = true; - pending_count.store(1, std::memory_order_relaxed); - pushed_count.fetch_add(1, std::memory_order_relaxed); + mark_latest_pushed(); } void push(std::pmr::vector&& values) { - if (pending) - dropped_count.fetch_add(1, std::memory_order_relaxed); points = std::move(values); - pending = true; - pending_count.store(1, std::memory_order_relaxed); - pushed_count.fetch_add(1, std::memory_order_relaxed); + mark_latest_pushed(); } template void read_all(Handler handler) { @@ -32,20 +20,7 @@ struct Fill_Area_Input_Data : Input_Data { } void clear() override { points.clear(); - pending = false; - pending_count.store(0, std::memory_order_relaxed); - } - std::uint64_t get_pending_count() const override { - return pending_count.load(std::memory_order_relaxed); - } - std::uint64_t get_dropped_count() const override { - return dropped_count.load(std::memory_order_relaxed); - } - std::uint64_t get_capacity_dropped_count() const override { - return dropped_count.load(std::memory_order_relaxed); - } - std::uint64_t get_pushed_count() const override { - return pushed_count.load(std::memory_order_relaxed); + clear_latest(); } }; struct Fill_Area_Render_State : Render_State, Fill_Area_Prop {}; @@ -96,22 +71,7 @@ struct Fill_Area_Private : Typed_Render_Data; -Fill_Area::Fill_Area() { - Fill_Area_Binding::init(this, "FillArea"); -} -Fill_Area_Private* Fill_Area::d() { - return Fill_Area_Binding::d(this); -} -Render_Object_Owner Fill_Area::create_render_data() { - return Fill_Area_Binding::create_render_data(); -} -Render_Object_Owner Fill_Area::create_render_state() { - return Fill_Area_Binding::create_render_state(); -} -Render_Object_Owner Fill_Area::create_input_data() { - return Fill_Area_Binding::create_input_data(); -} +RENDERIVE_DEFINE_RENDERABLE_BINDING(Fill_Area, Fill_Area_Private, Fill_Area_Render_State, Fill_Area_Input_Data, "FillArea") void Fill_Area::give_points(std::span points) { if (!ok()) return; @@ -124,48 +84,13 @@ void Fill_Area::give_points(std::pmr::vector&& points) { Render_Input_Lease input(d()); input->push(std::move(points)); } -std::shared_ptr Fill_Area::x_axis(SRC src) { - return d()->state_value(&Fill_Area_Render_State::x_axis, src).lock(); -} -void Fill_Area::set_x_axis(std::shared_ptr value) { - d()->set_state_value(&Fill_Area_Render_State::x_axis, std::weak_ptr(value)); -} -std::shared_ptr Fill_Area::y_axis(SRC src) { - return d()->state_value(&Fill_Area_Render_State::y_axis, src).lock(); -} -void Fill_Area::set_y_axis(std::shared_ptr value) { - d()->set_state_value(&Fill_Area_Render_State::y_axis, std::weak_ptr(value)); -} -double Fill_Area::baseline(SRC src) { - return d()->state_value(&Fill_Area_Render_State::baseline, src); -} -void Fill_Area::set_baseline(double value) { - d()->set_state_value(&Fill_Area_Render_State::baseline, value); -} -QBrush Fill_Area::brush(SRC src) { - return d()->state_value(&Fill_Area_Render_State::brush, src); -} -void Fill_Area::set_brush(QBrush value) { - d()->set_state_value(&Fill_Area_Render_State::brush, std::move(value)); -} -QPen Fill_Area::pen(SRC src) { - return d()->state_value(&Fill_Area_Render_State::pen, src); -} -void Fill_Area::set_pen(QPen value) { - d()->set_state_value(&Fill_Area_Render_State::pen, std::move(value)); -} -bool Fill_Area::antialias(SRC src) { - return d()->state_value(&Fill_Area_Render_State::antialias, src); -} -void Fill_Area::set_antialias(bool value) { - d()->set_state_value(&Fill_Area_Render_State::antialias, value); -} -Fill_Area_Mode Fill_Area::mode(SRC src) { - return d()->state_value(&Fill_Area_Render_State::mode, src); -} -void Fill_Area::set_mode(Fill_Area_Mode value) { - d()->set_state_value(&Fill_Area_Render_State::mode, value); -} +RENDERIVE_DEFINE_WEAK_STATE_PROP(Fill_Area, Fill_Area_Render_State, Abs_Axis, x_axis) +RENDERIVE_DEFINE_WEAK_STATE_PROP(Fill_Area, Fill_Area_Render_State, Abs_Axis, y_axis) +RENDERIVE_DEFINE_STATE_PROP(Fill_Area, Fill_Area_Render_State, double, baseline) +RENDERIVE_DEFINE_STATE_PROP(Fill_Area, Fill_Area_Render_State, QBrush, brush) +RENDERIVE_DEFINE_STATE_PROP(Fill_Area, Fill_Area_Render_State, QPen, pen) +RENDERIVE_DEFINE_STATE_PROP(Fill_Area, Fill_Area_Render_State, bool, antialias) +RENDERIVE_DEFINE_STATE_PROP(Fill_Area, Fill_Area_Render_State, Fill_Area_Mode, mode) Fill_Area::Builder::Builder(std::shared_ptr parent, std::shared_ptr x_axis, std::shared_ptr y_axis) { ASSERT(parent, "Fill_Area build error! parent == nullptr"); ASSERT(x_axis && y_axis, "Fill_Area build error! axis == nullptr"); diff --git a/Renderive/primitive/Grid.cpp b/Renderive/primitive/Grid.cpp index 1890f52..270e2f0 100644 --- a/Renderive/primitive/Grid.cpp +++ b/Renderive/primitive/Grid.cpp @@ -78,22 +78,7 @@ struct Grid_Private : Typed_Render_Data { painter->restore(); } }; -using Grid_Binding = Renderable_Binding; -Grid::Grid() { - Grid_Binding::init(this, "Grid"); -} -Grid_Private* Grid::d() { - return Grid_Binding::d(this); -} -Render_Object_Owner Grid::create_render_data() { - return Grid_Binding::create_render_data(); -} -Render_Object_Owner Grid::create_render_state() { - return Grid_Binding::create_render_state(); -} -Render_Object_Owner Grid::create_input_data() { - return Grid_Binding::create_input_data(); -} +RENDERIVE_DEFINE_RENDERABLE_BINDING(Grid, Grid_Private, Grid_Render_State, Input_Data, "Grid") std::shared_ptr Grid::x_axis(SRC src) { return d()->state_value(&Grid_Render_State::x_axis, src).lock(); } diff --git a/Renderive/primitive/Label.cpp b/Renderive/primitive/Label.cpp index 395cc62..6eeab58 100644 --- a/Renderive/primitive/Label.cpp +++ b/Renderive/primitive/Label.cpp @@ -3,33 +3,19 @@ #include "../base/Memory.h" namespace renderive { struct Label_Render_State : Render_State, Label_Prop {}; -struct Label_Input_Data : Input_Data { +struct Label_Input_Data : Latest_Input_Data { std::pmr::vector items{memory_resource(Memory_Domain::Other)}; - bool has_frame = false; - std::atomic pending_count{}; - std::atomic pushed_count{}; void push(std::span value) { items.assign(value.begin(), value.end()); - has_frame = true; - pending_count.store(1, std::memory_order_relaxed); - pushed_count.fetch_add(1, std::memory_order_relaxed); + mark_latest_pushed(); } void push(std::pmr::vector&& value) { items = std::move(value); - has_frame = true; - pending_count.store(1, std::memory_order_relaxed); - pushed_count.fetch_add(1, std::memory_order_relaxed); + mark_latest_pushed(); } void clear() override { items.clear(); - has_frame = false; - pending_count.store(0, std::memory_order_relaxed); - } - std::uint64_t get_pending_count() const override { - return pending_count.load(std::memory_order_relaxed); - } - std::uint64_t get_pushed_count() const override { - return pushed_count.load(std::memory_order_relaxed); + clear_latest(); } }; struct Label_Private : Typed_Render_Data { @@ -38,7 +24,7 @@ struct Label_Private : Typed_Render_Datahas_frame) + if (!input->pending) return; prepared_items.swap(input->items); use_prepared_items = true; @@ -96,22 +82,7 @@ struct Label_Private : Typed_Render_Data; -Label::Label() { - Label_Binding::init(this, "Label"); -} -Label_Private* Label::d() { - return Label_Binding::d(this); -} -Render_Object_Owner Label::create_render_data() { - return Label_Binding::create_render_data(); -} -Render_Object_Owner Label::create_render_state() { - return Label_Binding::create_render_state(); -} -Render_Object_Owner Label::create_input_data() { - return Label_Binding::create_input_data(); -} +RENDERIVE_DEFINE_RENDERABLE_BINDING(Label, Label_Private, Label_Render_State, Label_Input_Data, "Label") void Label::give_items(std::span items, bool notify_render) { if (notify_render && !ok()) return; @@ -130,66 +101,16 @@ void Label::give_items(std::pmr::vector&& items, bool notify_render) Render_Input_Lease input(d(), notify_render); input->push(std::move(items)); } -std::shared_ptr Label::x_axis(SRC src) { - return d()->state_value(&Label_Render_State::x_axis, src).lock(); -} -void Label::set_x_axis(std::shared_ptr value) { - d()->set_state_value(&Label_Render_State::x_axis, std::weak_ptr(value)); -} -std::shared_ptr Label::y_axis(SRC src) { - return d()->state_value(&Label_Render_State::y_axis, src).lock(); -} -void Label::set_y_axis(std::shared_ptr value) { - d()->set_state_value(&Label_Render_State::y_axis, std::weak_ptr(value)); -} -QPointF Label::position(SRC src) { - return d()->state_value(&Label_Render_State::position, src); -} -void Label::set_position(QPointF value) { - d()->set_state_value(&Label_Render_State::position, value); -} -QPointF Label::offset(SRC src) { - return d()->state_value(&Label_Render_State::offset, src); -} -void Label::set_offset(QPointF value) { - d()->set_state_value(&Label_Render_State::offset, value); -} -QString Label::text(SRC src) { - return d()->state_value(&Label_Render_State::text, src); -} -void Label::set_text(QString value) { - d()->set_state_value(&Label_Render_State::text, std::move(value)); -} -Qt::Alignment Label::alignment(SRC src) { - return d()->state_value(&Label_Render_State::alignment, src); -} -void Label::set_alignment(Qt::Alignment value) { - d()->set_state_value(&Label_Render_State::alignment, value); -} -QFont Label::font(SRC src) { - return d()->state_value(&Label_Render_State::font, src); -} -void Label::set_font(QFont value) { - d()->set_state_value(&Label_Render_State::font, std::move(value)); -} -QPen Label::text_pen(SRC src) { - return d()->state_value(&Label_Render_State::text_pen, src); -} -void Label::set_text_pen(QPen value) { - d()->set_state_value(&Label_Render_State::text_pen, std::move(value)); -} -QBrush Label::background_brush(SRC src) { - return d()->state_value(&Label_Render_State::background_brush, src); -} -void Label::set_background_brush(QBrush value) { - d()->set_state_value(&Label_Render_State::background_brush, std::move(value)); -} -QPen Label::border_pen(SRC src) { - return d()->state_value(&Label_Render_State::border_pen, src); -} -void Label::set_border_pen(QPen value) { - d()->set_state_value(&Label_Render_State::border_pen, std::move(value)); -} +RENDERIVE_DEFINE_WEAK_STATE_PROP(Label, Label_Render_State, Abs_Axis, x_axis) +RENDERIVE_DEFINE_WEAK_STATE_PROP(Label, Label_Render_State, Abs_Axis, y_axis) +RENDERIVE_DEFINE_STATE_PROP(Label, Label_Render_State, QPointF, position) +RENDERIVE_DEFINE_STATE_PROP(Label, Label_Render_State, QPointF, offset) +RENDERIVE_DEFINE_STATE_PROP(Label, Label_Render_State, QString, text) +RENDERIVE_DEFINE_STATE_PROP(Label, Label_Render_State, Qt::Alignment, alignment) +RENDERIVE_DEFINE_STATE_PROP(Label, Label_Render_State, QFont, font) +RENDERIVE_DEFINE_STATE_PROP(Label, Label_Render_State, QPen, text_pen) +RENDERIVE_DEFINE_STATE_PROP(Label, Label_Render_State, QBrush, background_brush) +RENDERIVE_DEFINE_STATE_PROP(Label, Label_Render_State, QPen, border_pen) Label::Builder::Builder(std::shared_ptr parent, std::shared_ptr x_axis, std::shared_ptr y_axis) { ASSERT(parent, "Label build error! parent == nullptr"); ASSERT(x_axis && y_axis, "Label build error! axis == nullptr"); diff --git a/Renderive/primitive/Marker.cpp b/Renderive/primitive/Marker.cpp index f52897e..52cb0df 100644 --- a/Renderive/primitive/Marker.cpp +++ b/Renderive/primitive/Marker.cpp @@ -2,33 +2,19 @@ #include "../base/Memory.h" namespace renderive { struct Marker_Render_State : Render_State, Marker_Prop {}; -struct Marker_Input_Data : Input_Data { +struct Marker_Input_Data : Latest_Input_Data { std::pmr::vector items{memory_resource(Memory_Domain::Other)}; - bool has_frame = false; - std::atomic pending_count{}; - std::atomic pushed_count{}; void push(std::span value) { items.assign(value.begin(), value.end()); - has_frame = true; - pending_count.store(1, std::memory_order_relaxed); - pushed_count.fetch_add(1, std::memory_order_relaxed); + mark_latest_pushed(); } void push(std::pmr::vector&& value) { items = std::move(value); - has_frame = true; - pending_count.store(1, std::memory_order_relaxed); - pushed_count.fetch_add(1, std::memory_order_relaxed); + mark_latest_pushed(); } void clear() override { items.clear(); - has_frame = false; - pending_count.store(0, std::memory_order_relaxed); - } - std::uint64_t get_pending_count() const override { - return pending_count.load(std::memory_order_relaxed); - } - std::uint64_t get_pushed_count() const override { - return pushed_count.load(std::memory_order_relaxed); + clear_latest(); } }; struct Marker_Private : Typed_Render_Data { @@ -62,7 +48,7 @@ struct Marker_Private : Typed_Render_Datahas_frame) + if (!input->pending) return; prepared_items.swap(input->items); use_prepared_items = true; @@ -91,22 +77,7 @@ struct Marker_Private : Typed_Render_Datarestore(); } }; -using Marker_Binding = Renderable_Binding; -Marker::Marker() { - Marker_Binding::init(this, "Marker"); -} -Marker_Private* Marker::d() { - return Marker_Binding::d(this); -} -Render_Object_Owner Marker::create_render_data() { - return Marker_Binding::create_render_data(); -} -Render_Object_Owner Marker::create_render_state() { - return Marker_Binding::create_render_state(); -} -Render_Object_Owner Marker::create_input_data() { - return Marker_Binding::create_input_data(); -} +RENDERIVE_DEFINE_RENDERABLE_BINDING(Marker, Marker_Private, Marker_Render_State, Marker_Input_Data, "Marker") void Marker::give_items(std::span items, bool notify_render) { if (notify_render && !ok()) return; @@ -125,48 +96,18 @@ void Marker::give_items(std::pmr::vector&& items, bool notify_rende Render_Input_Lease input(d(), notify_render); input->push(std::move(items)); } -std::shared_ptr Marker::x_axis(SRC src) { - return d()->state_value(&Marker_Render_State::x_axis, src).lock(); -} -void Marker::set_x_axis(std::shared_ptr value) { - d()->set_state_value(&Marker_Render_State::x_axis, std::weak_ptr(value)); -} -std::shared_ptr Marker::y_axis(SRC src) { - return d()->state_value(&Marker_Render_State::y_axis, src).lock(); -} -void Marker::set_y_axis(std::shared_ptr value) { - d()->set_state_value(&Marker_Render_State::y_axis, std::weak_ptr(value)); -} -QPointF Marker::position(SRC src) { - return d()->state_value(&Marker_Render_State::position, src); -} -void Marker::set_position(QPointF value) { - d()->set_state_value(&Marker_Render_State::position, value); -} +RENDERIVE_DEFINE_WEAK_STATE_PROP(Marker, Marker_Render_State, Abs_Axis, x_axis) +RENDERIVE_DEFINE_WEAK_STATE_PROP(Marker, Marker_Render_State, Abs_Axis, y_axis) +RENDERIVE_DEFINE_STATE_PROP(Marker, Marker_Render_State, QPointF, position) double Marker::radius(SRC src) { return d()->state_value(&Marker_Render_State::radius, src); } void Marker::set_radius(double value) { d()->set_state_value(&Marker_Render_State::radius, qMax(0.0, value)); } -QPen Marker::pen(SRC src) { - return d()->state_value(&Marker_Render_State::pen, src); -} -void Marker::set_pen(QPen value) { - d()->set_state_value(&Marker_Render_State::pen, std::move(value)); -} -QBrush Marker::brush(SRC src) { - return d()->state_value(&Marker_Render_State::brush, src); -} -void Marker::set_brush(QBrush value) { - d()->set_state_value(&Marker_Render_State::brush, std::move(value)); -} -Marker_Mode Marker::mode(SRC src) { - return d()->state_value(&Marker_Render_State::mode, src); -} -void Marker::set_mode(Marker_Mode value) { - d()->set_state_value(&Marker_Render_State::mode, value); -} +RENDERIVE_DEFINE_STATE_PROP(Marker, Marker_Render_State, QPen, pen) +RENDERIVE_DEFINE_STATE_PROP(Marker, Marker_Render_State, QBrush, brush) +RENDERIVE_DEFINE_STATE_PROP(Marker, Marker_Render_State, Marker_Mode, mode) Marker::Builder::Builder(std::shared_ptr parent, std::shared_ptr x_axis, std::shared_ptr y_axis) { ASSERT(parent, "Marker build error! parent == nullptr"); ASSERT(x_axis && y_axis, "Marker build error! axis == nullptr"); diff --git a/Renderive/primitive/Point_Set.cpp b/Renderive/primitive/Point_Set.cpp index ec23cd2..7478914 100644 --- a/Renderive/primitive/Point_Set.cpp +++ b/Renderive/primitive/Point_Set.cpp @@ -3,48 +3,28 @@ #include "../base/Frame_Memory.h" #include "../base/Memory.h" namespace renderive { -struct Point_Set_Input_Data : Input_Data { +struct Point_Set_Input_Data : Latest_Input_Data { std::pmr::vector points{memory_resource(Memory_Domain::Point_Set)}; std::pmr::vector colors{memory_resource(Memory_Domain::Point_Set)}; - bool pending = false; - std::atomic pending_count{}; - std::atomic dropped_count{}; - std::atomic pushed_count{}; void push(std::span values) { - if (pending) - dropped_count.fetch_add(1, std::memory_order_relaxed); points.assign(values.begin(), values.end()); colors.clear(); - pending = true; - pending_count.store(1, std::memory_order_relaxed); - pushed_count.fetch_add(1, std::memory_order_relaxed); + mark_latest_pushed(); } void push(std::pmr::vector&& values) { - if (pending) - dropped_count.fetch_add(1, std::memory_order_relaxed); points = std::move(values); colors.clear(); - pending = true; - pending_count.store(1, std::memory_order_relaxed); - pushed_count.fetch_add(1, std::memory_order_relaxed); + mark_latest_pushed(); } void push(std::span values, std::span color_values) { - if (pending) - dropped_count.fetch_add(1, std::memory_order_relaxed); points.assign(values.begin(), values.end()); colors.assign(color_values.begin(), color_values.end()); - pending = true; - pending_count.store(1, std::memory_order_relaxed); - pushed_count.fetch_add(1, std::memory_order_relaxed); + mark_latest_pushed(); } void push(std::pmr::vector&& values, std::pmr::vector&& color_values) { - if (pending) - dropped_count.fetch_add(1, std::memory_order_relaxed); points = std::move(values); colors = std::move(color_values); - pending = true; - pending_count.store(1, std::memory_order_relaxed); - pushed_count.fetch_add(1, std::memory_order_relaxed); + mark_latest_pushed(); } template void read_all(Handler handler) { @@ -54,20 +34,7 @@ struct Point_Set_Input_Data : Input_Data { void clear() override { points.clear(); colors.clear(); - pending = false; - pending_count.store(0, std::memory_order_relaxed); - } - std::uint64_t get_pending_count() const override { - return pending_count.load(std::memory_order_relaxed); - } - std::uint64_t get_dropped_count() const override { - return dropped_count.load(std::memory_order_relaxed); - } - std::uint64_t get_capacity_dropped_count() const override { - return dropped_count.load(std::memory_order_relaxed); - } - std::uint64_t get_pushed_count() const override { - return pushed_count.load(std::memory_order_relaxed); + clear_latest(); } }; struct Point_Set_Render_State : Render_State, Point_Set_Prop {}; @@ -140,22 +107,7 @@ struct Point_Set_Private : Typed_Render_Data; -Point_Set::Point_Set() { - Point_Set_Binding::init(this, "point_set"); -} -Point_Set_Private* Point_Set::d() { - return Point_Set_Binding::d(this); -} -Render_Object_Owner Point_Set::create_render_data() { - return Point_Set_Binding::create_render_data(); -} -Render_Object_Owner Point_Set::create_render_state() { - return Point_Set_Binding::create_render_state(); -} -Render_Object_Owner Point_Set::create_input_data() { - return Point_Set_Binding::create_input_data(); -} +RENDERIVE_DEFINE_RENDERABLE_BINDING(Point_Set, Point_Set_Private, Point_Set_Render_State, Point_Set_Input_Data, "point_set") void Point_Set::give_points(std::span points, bool notify_render) { if (notify_render && !ok()) return; @@ -196,48 +148,18 @@ void Point_Set::give_colored_points(std::pmr::vector&& points, std::pmr Render_Input_Lease input(d(), notify_render); input->push(std::move(points), std::move(colors)); } -std::shared_ptr Point_Set::x_axis(SRC src) { - return d()->state_value(&Point_Set_Render_State::x_axis, src).lock(); -} -void Point_Set::set_x_axis(std::shared_ptr value) { - d()->set_state_value(&Point_Set_Render_State::x_axis, std::weak_ptr(value)); -} -std::shared_ptr Point_Set::y_axis(SRC src) { - return d()->state_value(&Point_Set_Render_State::y_axis, src).lock(); -} -void Point_Set::set_y_axis(std::shared_ptr value) { - d()->set_state_value(&Point_Set_Render_State::y_axis, std::weak_ptr(value)); -} +RENDERIVE_DEFINE_WEAK_STATE_PROP(Point_Set, Point_Set_Render_State, Abs_Axis, x_axis) +RENDERIVE_DEFINE_WEAK_STATE_PROP(Point_Set, Point_Set_Render_State, Abs_Axis, y_axis) double Point_Set::size(SRC src) { return d()->state_value(&Point_Set_Render_State::size, src); } void Point_Set::set_size(double value) { d()->set_state_value(&Point_Set_Render_State::size, qMax(1.0, value)); } -QPen Point_Set::pen(SRC src) { - return d()->state_value(&Point_Set_Render_State::pen, src); -} -void Point_Set::set_pen(QPen value) { - d()->set_state_value(&Point_Set_Render_State::pen, std::move(value)); -} -QBrush Point_Set::brush(SRC src) { - return d()->state_value(&Point_Set_Render_State::brush, src); -} -void Point_Set::set_brush(QBrush value) { - d()->set_state_value(&Point_Set_Render_State::brush, std::move(value)); -} -bool Point_Set::antialias(SRC src) { - return d()->state_value(&Point_Set_Render_State::antialias, src); -} -void Point_Set::set_antialias(bool value) { - d()->set_state_value(&Point_Set_Render_State::antialias, value); -} -Point_Set_Shape Point_Set::shape(SRC src) { - return d()->state_value(&Point_Set_Render_State::shape, src); -} -void Point_Set::set_shape(Point_Set_Shape value) { - d()->set_state_value(&Point_Set_Render_State::shape, value); -} +RENDERIVE_DEFINE_STATE_PROP(Point_Set, Point_Set_Render_State, QPen, pen) +RENDERIVE_DEFINE_STATE_PROP(Point_Set, Point_Set_Render_State, QBrush, brush) +RENDERIVE_DEFINE_STATE_PROP(Point_Set, Point_Set_Render_State, bool, antialias) +RENDERIVE_DEFINE_STATE_PROP(Point_Set, Point_Set_Render_State, Point_Set_Shape, shape) Point_Set::Builder::Builder(std::shared_ptr parent, std::shared_ptr x_axis, std::shared_ptr y_axis) { ASSERT(parent, "Point_Set build error! parent == nullptr"); ASSERT(x_axis && y_axis, "Point_Set build error! axis == nullptr"); diff --git a/Renderive/primitive/Raster_Image.cpp b/Renderive/primitive/Raster_Image.cpp index 1004410..5878bc4 100644 --- a/Renderive/primitive/Raster_Image.cpp +++ b/Renderive/primitive/Raster_Image.cpp @@ -1,19 +1,11 @@ #include "Raster_Image_p.h" #include "../base/Memory.h" namespace renderive { -struct Raster_Image_Input_Data : Input_Data { +struct Raster_Image_Input_Data : Latest_Input_Data { QImage image; - bool pending = false; - std::atomic pending_count{}; - std::atomic dropped_count{}; - std::atomic pushed_count{}; void push(const QImage& value) { - if (pending) - dropped_count.fetch_add(1, std::memory_order_relaxed); image = value; - pending = true; - pending_count.store(1, std::memory_order_relaxed); - pushed_count.fetch_add(1, std::memory_order_relaxed); + mark_latest_pushed(); } template void read_all(Handler handler) { @@ -22,20 +14,7 @@ struct Raster_Image_Input_Data : Input_Data { } void clear() override { image = QImage(); - pending = false; - pending_count.store(0, std::memory_order_relaxed); - } - std::uint64_t get_pending_count() const override { - return pending_count.load(std::memory_order_relaxed); - } - std::uint64_t get_dropped_count() const override { - return dropped_count.load(std::memory_order_relaxed); - } - std::uint64_t get_capacity_dropped_count() const override { - return dropped_count.load(std::memory_order_relaxed); - } - std::uint64_t get_pushed_count() const override { - return pushed_count.load(std::memory_order_relaxed); + clear_latest(); } }; struct Raster_Image_Render_State : Render_State, Raster_Image_Prop {}; @@ -72,22 +51,7 @@ struct Raster_Image_Private : Typed_Render_Datarestore(); } }; -using Raster_Image_Binding = Renderable_Binding; -Raster_Image::Raster_Image() { - Raster_Image_Binding::init(this, "RasterImage"); -} -Raster_Image_Private* Raster_Image::d() { - return Raster_Image_Binding::d(this); -} -Render_Object_Owner Raster_Image::create_render_data() { - return Raster_Image_Binding::create_render_data(); -} -Render_Object_Owner Raster_Image::create_render_state() { - return Raster_Image_Binding::create_render_state(); -} -Render_Object_Owner Raster_Image::create_input_data() { - return Raster_Image_Binding::create_input_data(); -} +RENDERIVE_DEFINE_RENDERABLE_BINDING(Raster_Image, Raster_Image_Private, Raster_Image_Render_State, Raster_Image_Input_Data, "RasterImage") void Raster_Image::give_image(const QImage& image, bool notify_render) { if (notify_render && !ok()) return; @@ -117,18 +81,8 @@ void Raster_Image::give_image_frame(const QImage& image, Range x_range, Range y_ Render_Input_Lease input(pd, notify_render); input->push(image); } -std::shared_ptr Raster_Image::x_axis(SRC src) { - return d()->state_value(&Raster_Image_Render_State::x_axis, src).lock(); -} -void Raster_Image::set_x_axis(std::shared_ptr value) { - d()->set_state_value(&Raster_Image_Render_State::x_axis, std::weak_ptr(value)); -} -std::shared_ptr Raster_Image::y_axis(SRC src) { - return d()->state_value(&Raster_Image_Render_State::y_axis, src).lock(); -} -void Raster_Image::set_y_axis(std::shared_ptr value) { - d()->set_state_value(&Raster_Image_Render_State::y_axis, std::weak_ptr(value)); -} +RENDERIVE_DEFINE_WEAK_STATE_PROP(Raster_Image, Raster_Image_Render_State, Abs_Axis, x_axis) +RENDERIVE_DEFINE_WEAK_STATE_PROP(Raster_Image, Raster_Image_Render_State, Abs_Axis, y_axis) Range Raster_Image::x_range(SRC src) { return d()->state_value(&Raster_Image_Render_State::x_range, src); } @@ -145,18 +99,8 @@ void Raster_Image::set_y_range(Range value) { return; d()->set_state_value(&Raster_Image_Render_State::y_range, value); } -QRectF Raster_Image::source_rect(SRC src) { - return d()->state_value(&Raster_Image_Render_State::source_rect, src); -} -void Raster_Image::set_source_rect(QRectF value) { - d()->set_state_value(&Raster_Image_Render_State::source_rect, value); -} -Image_Interpolation_Mode Raster_Image::interpolation_mode(SRC src) { - return d()->state_value(&Raster_Image_Render_State::interpolation_mode, src); -} -void Raster_Image::set_interpolation_mode(Image_Interpolation_Mode value) { - d()->set_state_value(&Raster_Image_Render_State::interpolation_mode, value); -} +RENDERIVE_DEFINE_STATE_PROP(Raster_Image, Raster_Image_Render_State, QRectF, source_rect) +RENDERIVE_DEFINE_STATE_PROP(Raster_Image, Raster_Image_Render_State, Image_Interpolation_Mode, interpolation_mode) Raster_Image::Builder::Builder(std::shared_ptr parent, std::shared_ptr x_axis, std::shared_ptr y_axis) { ASSERT(parent, "Raster_Image build error! parent == nullptr"); ASSERT(x_axis && y_axis, "Raster_Image build error! axis == nullptr"); diff --git a/Renderive/Generate_Mock_Data.cpp b/Widget/base/Generate_Mock_Data.cpp similarity index 80% rename from Renderive/Generate_Mock_Data.cpp rename to Widget/base/Generate_Mock_Data.cpp index 56a8230..92959dd 100644 --- a/Renderive/Generate_Mock_Data.cpp +++ b/Widget/base/Generate_Mock_Data.cpp @@ -1,15 +1,19 @@ #include "Generate_Mock_Data.h" #include namespace renderive { -std::random_device rd; -std::default_random_engine eng(rd()); +namespace { +std::default_random_engine& mock_data_random_engine() { + static thread_local std::default_random_engine engine(std::random_device{}()); + return engine; +} +} void fill_data(Range value_range, std::span output) { if (value_range.origin > value_range.target) { std::swap(value_range.origin, value_range.target); } std::uniform_real_distribution dist(value_range.origin, value_range.target); for (auto& value : output) { - value = dist(eng); + value = dist(mock_data_random_engine()); } } std::vector get_data(Range value_range, int size) { @@ -22,7 +26,7 @@ double get_data(Range value_range) { std::swap(value_range.origin, value_range.target); } std::uniform_real_distribution dist(value_range.origin, value_range.target); - return dist(eng); + return dist(mock_data_random_engine()); } std::vector get_data(int value, int size) { std::vector ret(size); diff --git a/Renderive/Generate_Mock_Data.h b/Widget/base/Generate_Mock_Data.h similarity index 90% rename from Renderive/Generate_Mock_Data.h rename to Widget/base/Generate_Mock_Data.h index 27bc4f6..335586c 100644 --- a/Renderive/Generate_Mock_Data.h +++ b/Widget/base/Generate_Mock_Data.h @@ -1,7 +1,7 @@ #pragma once #include #include -#include "architecture/global.h" +#include "Renderive/architecture/global.h" namespace renderive { void LIB_DECL fill_data(Range value_range, std::span output); std::vector LIB_DECL get_data(Range value_range, int size); diff --git a/Widget/component/Table/Base_Info.cpp b/Widget/component/Table/Base_Info.cpp index e71c65d..30ea1df 100644 --- a/Widget/component/Table/Base_Info.cpp +++ b/Widget/component/Table/Base_Info.cpp @@ -1,5 +1,5 @@ #include "Base_Info.h" -#include "Renderive/Generate_Mock_Data.h" +#include "Widget/base/Generate_Mock_Data.h" #include "Renderive/architecture/global.h" namespace Psc { Base_Info::Base_Info(int len, QString content) : len(len), content(std::move(content)) { diff --git a/Widget/component/Table/Base_Table_Data.cpp b/Widget/component/Table/Base_Table_Data.cpp index eb50271..f7e7822 100644 --- a/Widget/component/Table/Base_Table_Data.cpp +++ b/Widget/component/Table/Base_Table_Data.cpp @@ -1,6 +1,6 @@ #include "Base_Table_Data.h" #include "Table_View.h" -#include "Renderive/Generate_Mock_Data.h" +#include "Widget/base/Generate_Mock_Data.h" namespace Psc { Base_Table_Data::Base_Table_Data() { parent = this; diff --git a/Widget/component/Table/Base_Table_Model.cpp b/Widget/component/Table/Base_Table_Model.cpp index 70892af..5c2ee29 100644 --- a/Widget/component/Table/Base_Table_Model.cpp +++ b/Widget/component/Table/Base_Table_Model.cpp @@ -1,5 +1,5 @@ #include "Base_Table_Model.h" -#include "Renderive/Generate_Mock_Data.h" +#include "Widget/base/Generate_Mock_Data.h" #include "Renderive/base/global.h" #include "Base_Info.h" #include "Base_Table_Data.h" diff --git a/Widget/component/Table/Table_View.cpp b/Widget/component/Table/Table_View.cpp index 85daee9..08a4424 100644 --- a/Widget/component/Table/Table_View.cpp +++ b/Widget/component/Table/Table_View.cpp @@ -1,7 +1,7 @@ #include "Table_View.h" #include #include -#include "Renderive/Generate_Mock_Data.h" +#include "Widget/base/Generate_Mock_Data.h" #include "Base_Info.h" #include "Base_Table_Data.h" namespace Psc { diff --git a/main.cmake b/main.cmake index 718d708..45af7f3 100644 --- a/main.cmake +++ b/main.cmake @@ -75,6 +75,7 @@ endif () set(dir "${CMAKE_CURRENT_LIST_DIR}/Renderive") file(GLOB_RECURSE srcs CONFIGURE_DEPENDS "${dir}/*.c" "${dir}/*.cpp" "${dir}/*.h" "${dir}/*.qrc") list(FILTER srcs EXCLUDE REGEX "main\\.cpp$") +list(FILTER srcs EXCLUDE REGEX "Performance_Shower(_p)?\\.(cpp|h)$") add_library(Renderive STATIC "${srcs}") target_include_directories(Renderive PUBLIC "${CMAKE_CURRENT_LIST_DIR}") set(Core Core_Static) @@ -99,6 +100,18 @@ set_property(TARGET Renderive PROPERTY AUTOUIC ON) set_property(TARGET Renderive PROPERTY AUTORCC ON) target_link_libraries(Renderive PUBLIC ${Core}) ysgraphic_core_apply_sanitizer(Renderive) + +set(renderive_diagnostics_srcs + "${dir}/plottable/Performance_Shower.cpp" + "${dir}/plottable/Performance_Shower_p.h" +) +add_library(Renderive_Diagnostics STATIC "${renderive_diagnostics_srcs}") +target_include_directories(Renderive_Diagnostics PUBLIC "${CMAKE_CURRENT_LIST_DIR}") +target_link_libraries(Renderive_Diagnostics PUBLIC Renderive) +set_property(TARGET Renderive_Diagnostics PROPERTY AUTOMOC ON) +set_property(TARGET Renderive_Diagnostics PROPERTY AUTOUIC ON) +set_property(TARGET Renderive_Diagnostics PROPERTY AUTORCC ON) +ysgraphic_core_apply_sanitizer(Renderive_Diagnostics) if (YSGRAPHIC_CORE_BUILD_TESTS) enable_testing() function(renderive_add_gtest target test_name source) @@ -120,9 +133,9 @@ if (YSGRAPHIC_CORE_BUILD_TESTS) set_tests_properties(Renderive.Memory_Data_Path_Stress PROPERTIES ENVIRONMENT "QT_QPA_PLATFORM=offscreen;RENDERIVE_PERFORMANCE_LOG=0" TIMEOUT 20) renderive_add_gtest(Renderive_Renderable_Lifecycle_Stress Renderable_Lifecycle_Stress Renderable_Lifecycle_Stress.cpp) set_tests_properties(Renderive.Renderable_Lifecycle_Stress PROPERTIES ENVIRONMENT "QT_QPA_PLATFORM=offscreen;RENDERIVE_PERFORMANCE_LOG=0" TIMEOUT 20) - renderive_add_gtest(Renderive_Frame_Scheduler_Feedback Frame_Scheduler_Feedback Frame_Scheduler_Feedback.cpp) + renderive_add_gtest(Renderive_Frame_Scheduler_Feedback Frame_Scheduler_Feedback Frame_Scheduler_Feedback.cpp Renderive_Diagnostics) set_tests_properties(Renderive.Frame_Scheduler_Feedback PROPERTIES ENVIRONMENT "RENDERIVE_PERFORMANCE_LOG=1;RENDERIVE_PERFORMANCE_LOG_PATH=${CMAKE_BINARY_DIR}/renderive_feedback_test_log.csv") - renderive_add_gtest(Renderive_Performance_Shower_Interaction Performance_Shower_Interaction Performance_Shower_Interaction.cpp Renderive_Widget) + renderive_add_gtest(Renderive_Performance_Shower_Interaction Performance_Shower_Interaction Performance_Shower_Interaction.cpp Renderive_Diagnostics Renderive_Widget) set_tests_properties(Renderive.Performance_Shower_Interaction PROPERTIES ENVIRONMENT "QT_QPA_PLATFORM=offscreen;RENDERIVE_PERFORMANCE_LOG=0" TIMEOUT 12) renderive_add_gtest(Renderive_Multithread_Input_Stress Multithread_Input_Stress Multithread_Input_Stress.cpp) set_tests_properties(Renderive.Multithread_Input_Stress PROPERTIES ENVIRONMENT "QT_QPA_PLATFORM=offscreen;RENDERIVE_PERFORMANCE_LOG=0" TIMEOUT 15) @@ -141,7 +154,10 @@ ysgraphic_core_apply_sanitizer(Renderive_Widget) set(dir "${CMAKE_CURRENT_LIST_DIR}/Demo_Gallery") file(GLOB_RECURSE srcs "${dir}/*.c" "${dir}/*.cpp" "${dir}/*.h" "${dir}/*.hpp") add_library(Demo_Gallery_Lib ${srcs}) -target_link_libraries(Demo_Gallery_Lib PUBLIC Renderive Renderive_Widget) +target_link_libraries(Demo_Gallery_Lib PUBLIC Renderive Renderive_Diagnostics Renderive_Widget) add_executable(Demo_Gallery ${CMAKE_CURRENT_LIST_DIR}/demo_gallery_main.cpp) target_link_libraries(Demo_Gallery PUBLIC Demo_Gallery_Lib) + + + diff --git a/tests/Frame_Scheduler_Feedback.cpp b/tests/Frame_Scheduler_Feedback.cpp index 77d1857..c2a6acb 100644 --- a/tests/Frame_Scheduler_Feedback.cpp +++ b/tests/Frame_Scheduler_Feedback.cpp @@ -85,14 +85,9 @@ private: renderive::Frame_Lifecycle_Record frame; frame.frame_id = config.id * 1000000 + ++next_frame_id; frame.input_version = latest_input_version; - frame.snapshot_version = latest_input_version; frame.frame_slot_generation = next_frame_id; frame.core_data_time = latest_input_time; - frame.source_data_time_begin = latest_input_time; - frame.source_data_time_end = latest_input_time; frame.render_request_time = latest_input_time; - frame.snapshot_capture_begin_time = now; - frame.snapshot_capture_end_time = now; frame.render_queue_enter_time = now; frame.prepare_begin_time = now; frame.prepare_end_time = now; @@ -229,7 +224,7 @@ void validate_performance_log(const QString& log_path) { std::vector lines = wait_log_lines(log_path, 8); ASSERT_GT(lines.size(), 1); const QString& header = lines.front(); - EXPECT_TRUE(header.startsWith("frame_id,input_version,snapshot_version,slot_generation,outcome,bottleneck")); + EXPECT_TRUE(header.startsWith("frame_id,input_version,slot_generation,outcome,bottleneck")); EXPECT_FALSE(header.contains("policy")); expect_header_field(header, "production_fps"); expect_header_field(header, "display_fps"); @@ -254,8 +249,8 @@ TEST(Frame_Scheduler_Feedback, KeepsPerformanceShowerInputRingBounded) { frame.frame_id = frame_id; input.push(frame); } - EXPECT_EQ(input.get_pending_count(), renderive::Performance_Shower_Input_Data::Capacity); - EXPECT_EQ(input.get_capacity_dropped_count(), 8); + EXPECT_EQ(input.count, renderive::Performance_Shower_Input_Data::Capacity); + EXPECT_EQ(input.capacity_dropped, 8); std::vector frame_ids; input.read_all([&frame_ids](const renderive::Frame_Lifecycle_Record& frame) { frame_ids.push_back(frame.frame_id); @@ -264,7 +259,7 @@ TEST(Frame_Scheduler_Feedback, KeepsPerformanceShowerInputRingBounded) { EXPECT_EQ(frame_ids.front(), 9); EXPECT_EQ(frame_ids.back(), 72); input.request_reset(); - EXPECT_EQ(input.get_pending_count(), 0); + EXPECT_EQ(input.count, 0); EXPECT_TRUE(input.reset_pending); } TEST(Frame_Scheduler_Feedback, AggregatesRenderableCacheStats) { @@ -275,18 +270,14 @@ TEST(Frame_Scheduler_Feedback, AggregatesRenderableCacheStats) { frame.record_renderable_self_draw("root", {}, 0, renderive::Renderable_Cache_Mode::Direct, 300); frame.record_renderable_render("cache_b", "cache_a", 1, renderive::Renderable_Cache_Mode::Local_Pixel, 2000); frame.record_renderable_cache_hit("cache_a", {}, 0); - frame.record_renderable_cache_stale_hit("cache_a", {}, 0); frame.record_renderable_cache_miss("cache_b", "cache_a", 1); - frame.record_renderable_cache_rebuild("cache_b", "cache_a", 1, 1000, 4096, 1024, 3, 3, false, true); - frame.record_renderable_cache_rebuild("cache_a", {}, 0, 2000, 2048, 512, 4, 4, true, false); + frame.record_renderable_cache_rebuild("cache_b", "cache_a", 1, 1000, 4096, 1024, 3, 3); + frame.record_renderable_cache_rebuild("cache_a", {}, 0, 2000, 2048, 512, 4, 4); frame.record_renderable_cache_compose("cache_a", {}, 0, 300, 2048, 512, 4, 4); frame.record_renderable_cache_compose("cache_b", "cache_a", 1, 700, 4096, 1024, 3, 3); EXPECT_EQ(frame.renderable_cache_hit_count, 1); - EXPECT_EQ(frame.renderable_cache_stale_hit_count, 1); EXPECT_EQ(frame.renderable_cache_miss_count, 1); EXPECT_EQ(frame.renderable_cache_rebuild_count, 2); - EXPECT_EQ(frame.renderable_cache_stale_rebuild_count, 1); - EXPECT_EQ(frame.renderable_cache_miss_rebuild_count, 1); EXPECT_EQ(frame.renderable_cache_rebuild_time_ns, 3000); EXPECT_EQ(frame.renderable_cache_compose_time_ns, 1000); ASSERT_EQ(frame.renderable_stats.size(), 2); @@ -304,7 +295,6 @@ TEST(Frame_Scheduler_Feedback, AggregatesRenderableCacheStats) { EXPECT_GT(aggregate.renderable_stats[0].self_draw_ms.times, 0); EXPECT_GT(aggregate.renderable_stats[1].total_render_ratio.times, 0); EXPECT_EQ(aggregate.cache_hit_count, 1); - EXPECT_EQ(aggregate.cache_stale_hit_count, 1); EXPECT_EQ(aggregate.cache_miss_count, 1); EXPECT_EQ(aggregate.cache_rebuild_count, 2); EXPECT_EQ(aggregate.cache_rebuild_time_ns, 3000); @@ -318,8 +308,8 @@ TEST(Frame_Scheduler_Feedback, AggregatesRenderableCacheStats) { EXPECT_GT(aggregate.cache_compose_ms.times, 0); EXPECT_GT(aggregate.cache_rebuild_ratio.times, 0); EXPECT_GT(aggregate.cache_compose_ratio.times, 0); - EXPECT_EQ(aggregate.renderable_cache_stats[0].last_subtree_compose_time_ns, 1000); - EXPECT_EQ(aggregate.renderable_cache_stats[1].last_subtree_compose_time_ns, 700); + EXPECT_EQ(aggregate.renderable_cache_stats[0].subtree_compose_time_ns, 1000); + EXPECT_EQ(aggregate.renderable_cache_stats[1].subtree_compose_time_ns, 700); EXPECT_GT(aggregate.renderable_cache_stats[0].subtree_compose_ms.times, 0); } TEST(Frame_Scheduler_Feedback, ClassifiesFourBottlenecksAndWritesUsableLog) { diff --git a/tests/Memory_Data_Path_Stress.cpp b/tests/Memory_Data_Path_Stress.cpp index 318887f..ff49d4a 100644 --- a/tests/Memory_Data_Path_Stress.cpp +++ b/tests/Memory_Data_Path_Stress.cpp @@ -9,17 +9,13 @@ #include "../Renderive/Axis/Axis.h" #include "../Renderive/Axis/Frequency_Axis.h" #include "../Renderive/Axis/Time_Axis.h" -#include "../Renderive/Axis/Time_Axis_p.h" #include "../Renderive/plot/Latency_Eager_Plot.h" -#include "../Renderive/plot/Plot_p.h" #include "../Renderive/architecture/Timeline_Stream.h" #include "../Renderive/base/Memory.h" #include "../Renderive/plottable/Audio_Frequency.h" -#include "../Renderive/plottable/Audio_Frequency_p.h" #include "../Renderive/plottable/Planisphere.h" -#include "../Renderive/plottable/Planisphere_p.h" #include "../Renderive/plottable/Waterfall.h" -#include "../Renderive/plottable/Waterfall_p.h" +#include "internal/Renderive_Private_Access.h" namespace { void process_events(int milliseconds) { QElapsedTimer timer; @@ -80,7 +76,7 @@ void stress_data_paths() { auto i_axis = renderive::Axis::Builder(axis_node, Qt::Horizontal).set_pixel_size(700).set_coord_range({-2.0, 2.0}).build(); auto q_axis = renderive::Axis::Builder(axis_node, Qt::Vertical).set_pixel_size(400).set_coord_range({-2.0, 2.0}).build(); auto waterfall = renderive::Waterfall::Builder(data_node, frequency_axis, time_axis).set_frequency_range({0.0, 100.0}).set_power_range({-120.0, 0.0}).set_frequency_point_size(64).build(); - auto audio = renderive::Audio_Frequency::Builder(data_node, time_axis, value_axis).set_time_point_size(32).set_key_range({-120.0, 0.0}).build(); + auto audio = renderive::Audio_Frequency::Builder(data_node, time_axis, value_axis).set_time_point_size(32).build(); auto planisphere = renderive::Planisphere::Builder(data_node, i_axis, q_axis).set_i_range({-2.0, 2.0}).set_q_range({-2.0, 2.0}).set_continue_millisecond(500).build(); plot.show(); plot.start_render(240); @@ -139,13 +135,15 @@ void stress_data_paths() { previous_tick = tick; } auto* time_data = time_axis->d(); - ASSERT_EQ(time_data->timeline_snapshot.time_point_size, time_sizes[stage]); - ASSERT_EQ(time_data->time_snapshot.size(), static_cast(time_sizes[stage])); - ASSERT_NE(time_data->time_data_count, 0); - EXPECT_EQ(time_data->time_snapshot[time_data->time_data_count - 1], expected_time); - int lower = qMin(time_data->timeline_snapshot.lower, time_data->timeline_snapshot.upper()); - int upper = qMax(time_data->timeline_snapshot.lower, time_data->timeline_snapshot.upper()); - for (const renderive::Timeline_Tick& tick : time_data->data) { + ASSERT_TRUE(time_data->timeline_snapshot); + ASSERT_EQ(time_data->timeline_snapshot->time_point_size, time_sizes[stage]); + ASSERT_EQ(time_data->timeline_snapshot->times.size(), static_cast(time_sizes[stage])); + ASSERT_FALSE(time_data->timeline_snapshot->times.empty()); + EXPECT_EQ(time_data->timeline_snapshot->times.back(), expected_time); + int lower = qMin(time_data->timeline_snapshot->lower, time_data->timeline_snapshot->upper()); + int upper = qMax(time_data->timeline_snapshot->lower, time_data->timeline_snapshot->upper()); + ASSERT_EQ(time_data->ticks.size(), time_data->timeline_snapshot->ticks.size()); + for (const renderive::Timeline_Tick& tick : time_data->timeline_snapshot->ticks) { EXPECT_GE(tick.tick, lower); EXPECT_LE(tick.tick, upper); } diff --git a/tests/Multithread_Input_Stress.cpp b/tests/Multithread_Input_Stress.cpp index 0edd163..c459c2e 100644 --- a/tests/Multithread_Input_Stress.cpp +++ b/tests/Multithread_Input_Stress.cpp @@ -13,11 +13,11 @@ #include "../Renderive/Axis/Time_Axis.h" #include "../Renderive/architecture/Timeline_Stream.h" #include "../Renderive/plot/Latency_Eager_Plot.h" -#include "../Renderive/plot/Plot_p.h" #include "../Renderive/base/Memory.h" #include "../Renderive/plottable/Audio_Frequency.h" #include "../Renderive/plottable/Spectrum.h" #include "../Renderive/plottable/Waterfall.h" +#include "internal/Renderive_Private_Access.h" namespace { std::pmr::vector make_data(int size, int seed, renderive::Memory_Domain domain) { std::pmr::vector data(renderive::memory_resource(domain)); @@ -68,7 +68,7 @@ void run_stress() { auto power_axis = renderive::Axis::Builder(axis_node, Qt::Vertical).set_pixel_size(360).set_coord_range({0.0, -120.0}).build(); auto waterfall = renderive::Waterfall::Builder(data_node, frequency_axis, time_axis).set_frequency_range({0.0, 100.0}).set_power_range({-120.0, 0.0}).set_frequency_point_size(256).build(); auto spectrum = renderive::Spectrum::Builder(data_node, frequency_axis, power_axis).set_frequency_range({0.0, 100.0}).set_frequency_point_size(256).build(); - auto audio = renderive::Audio_Frequency::Builder(data_node, time_axis, power_axis).set_time_point_size(128).set_key_range({-120.0, 0.0}).build(); + auto audio = renderive::Audio_Frequency::Builder(data_node, time_axis, power_axis).set_time_point_size(128).build(); plot.show(); plot.start_render(1000); ASSERT_TRUE(wait_ready(waterfall, spectrum, audio, time_axis)); diff --git a/tests/Performance_Shower_Interaction.cpp b/tests/Performance_Shower_Interaction.cpp index 8529f1c..fc5b2c3 100644 --- a/tests/Performance_Shower_Interaction.cpp +++ b/tests/Performance_Shower_Interaction.cpp @@ -1,4 +1,4 @@ -#include "../Renderive/base/Tool.h" +#include "../Demo_Gallery/base/Tool.h" #include #include #include @@ -75,7 +75,7 @@ TEST(Performance_Shower_Interaction, RepeatedToggleDoubleClickAndWheelStayRespon } double_click_button(performance_button); pump(app, plot, 200); - plot.set_use_performance_shower(true); + renderive::set_performance_shower_enabled(plot, true); pump(app, plot, 200); click_plot(&plot, QPoint(8, 8), QEvent::MouseButtonPress); click_plot(&plot, QPoint(8, 8), QEvent::MouseButtonRelease); @@ -90,7 +90,7 @@ TEST(Performance_Shower_Interaction, RepeatedToggleDoubleClickAndWheelStayRespon pump(app, plot, 10); } pump(app, plot, 200); - EXPECT_TRUE(plot.get_use_performance_shower()); + EXPECT_TRUE(renderive::performance_shower_enabled(plot)); plot.pause_render(); } int main(int argc, char** argv) { diff --git a/tests/internal/Renderive_Private_Access.h b/tests/internal/Renderive_Private_Access.h new file mode 100644 index 0000000..64cf733 --- /dev/null +++ b/tests/internal/Renderive_Private_Access.h @@ -0,0 +1,30 @@ +#pragma once + +#include "../../Renderive/Axis/Time_Axis_p.h" +#include "../../Renderive/plot/Plot_p.h" +#include "../../Renderive/plottable/Audio_Frequency_p.h" +#include "../../Renderive/plottable/Planisphere_p.h" +#include "../../Renderive/plottable/Waterfall_p.h" + +namespace renderive { +struct Abs_Plot_Private_Access { + static int active_render_tasks(const Abs_Plot& plot) { + return plot.d->active_render_tasks.load(std::memory_order_acquire); + } +}; +struct Audio_Frequency_Private_Access { + static Audio_Frequency_Private* data(Audio_Frequency* audio) { + return reinterpret_cast(audio->d_ptr); + } +}; +struct Planisphere_Private_Access { + static Planisphere_Private* data(Planisphere* planisphere) { + return reinterpret_cast(planisphere->d_ptr); + } +}; +struct Waterfall_Private_Access { + static Waterfall_Private* data(Waterfall* waterfall) { + return reinterpret_cast(waterfall->d_ptr); + } +}; +} // namespace renderive