核心模板架构

This commit is contained in:
2026-08-04 16:24:41 +08:00
parent 68476882a3
commit f1b9cadd47
121 changed files with 4782 additions and 210 deletions
+9 -1
View File
@@ -28,6 +28,9 @@ class Renderable_Runtime;
struct Input_Data {
virtual ~Input_Data() = default;
virtual void clear() {}
virtual void consume() {
clear();
}
};
struct Latest_Input_Data : Input_Data {
@@ -165,7 +168,7 @@ struct Render_Input_Frame_Handle {
virtual ~Render_Input_Frame_Handle() = default;
virtual void consume_input(Input_Data* input) {
if (input)
input->clear();
input->consume();
}
};
@@ -293,6 +296,7 @@ public:
virtual Render_State_Read_Guard acquire_edit_state_read() = 0;
virtual Render_State_Write_Guard acquire_edit_state() = 0;
virtual Render_Input_Write_Guard acquire_edit_input(bool notify_render) = 0;
virtual Render_Input_Frame_Guard acquire_input_read(Renderable_Input_Role role) = 0;
virtual Renderable_Frame_View capture_frame_view() = 0;
virtual Render_State* state(Renderable_State_Role role) = 0;
virtual Input_Data* input_data(Renderable_Input_Role role) = 0;
@@ -310,6 +314,7 @@ struct Render_Data {
virtual Render_State_Read_Guard acquire_edit_state_read() = 0;
virtual Render_State_Write_Guard acquire_edit_state() = 0;
virtual Render_Input_Write_Guard acquire_edit_input(bool notify_render) = 0;
virtual Render_Input_Frame_Guard acquire_input_read(Renderable_Input_Role role) = 0;
virtual Renderable_Frame_View capture_frame_view() = 0;
virtual Render_State* state(Renderable_State_Role role) = 0;
virtual Render_State* render_state() = 0;
@@ -352,6 +357,9 @@ struct Base_Render_Data : Render_Data {
Render_Input_Write_Guard acquire_edit_input(bool) override {
return {};
}
Render_Input_Frame_Guard acquire_input_read(Renderable_Input_Role) override {
return {};
}
Render_State* state(Renderable_State_Role) override {
return nullptr;
}
+21
View File
@@ -188,4 +188,25 @@ struct Render_Input_Lease : Immovable {
Input* input{};
};
template <typename Data, Input_Data_Type Input>
requires std::derived_from<Data, Render_Data>
struct Render_Input_Read_Lease : Immovable {
explicit Render_Input_Read_Lease(Data* data, Renderable_Input_Role role = Renderable_Input_Role::Render) {
guard = data->acquire_input_read(role);
input = reinterpret_cast<Input*>(guard.input);
}
~Render_Input_Read_Lease() = default;
const Input* operator->() const {
return input;
}
const Input& operator*() const {
return *input;
}
explicit operator bool() const {
return input && guard;
}
Render_Input_Frame_Guard guard;
Input* input{};
};
} // namespace renderive
@@ -45,6 +45,10 @@ Render_Input_Write_Guard Strategy_Render_Data::acquire_edit_input(bool notify_re
return runtime ? runtime->acquire_edit_input(notify_render) : Render_Input_Write_Guard{};
}
Render_Input_Frame_Guard Strategy_Render_Data::acquire_input_read(Renderable_Input_Role role) {
return runtime ? runtime->acquire_input_read(role) : Render_Input_Frame_Guard{};
}
Renderable_Frame_View Strategy_Render_Data::capture_frame_view() {
return runtime ? runtime->capture_frame_view() : Renderable_Frame_View{};
}
+1
View File
@@ -23,6 +23,7 @@ struct LIB_DECL Strategy_Render_Data : Render_Data {
Render_State_Read_Guard acquire_edit_state_read() override;
Render_State_Write_Guard acquire_edit_state() override;
Render_Input_Write_Guard acquire_edit_input(bool notify_render) override;
Render_Input_Frame_Guard acquire_input_read(Renderable_Input_Role role) override;
Renderable_Frame_View capture_frame_view() override;
Render_State* state(Renderable_State_Role role) override;
Input_Data* input_data(Renderable_Input_Role role) override;
@@ -92,7 +92,7 @@ struct Explicit_Input_Frame_Handle final : Render_Input_Frame_Handle {
runtime->committed_update_states.push_back(std::move(runtime->input.completion_state));
}
if (input)
input->clear();
input->consume();
runtime->input.pending = false;
}
Explicit_Renderable_Runtime_Data* runtime{};
@@ -192,6 +192,13 @@ Render_Input_Write_Guard Explicit_Renderable_Runtime::acquire_edit_input(bool no
return Render_Input_Write_Guard(d->input.data, std::make_unique<Explicit_Input_Write_Handle>(d.get(), std::move(lock), notify_render));
}
Render_Input_Frame_Guard Explicit_Renderable_Runtime::acquire_input_read(Renderable_Input_Role) {
std::unique_lock<std::mutex> lock(d->input_mutex, std::try_to_lock);
if (!lock || !d->input.data)
return {};
return Render_Input_Frame_Guard(d->input.data, std::make_unique<Explicit_Input_Frame_Handle>(d.get(), std::move(lock)));
}
Renderable_Frame_View Explicit_Renderable_Runtime::capture_frame_view() {
std::unique_lock<std::mutex> state_lock(d->state_mutex);
if (!d->state)
@@ -21,6 +21,7 @@ public:
Render_State_Read_Guard acquire_edit_state_read() override;
Render_State_Write_Guard acquire_edit_state() override;
Render_Input_Write_Guard acquire_edit_input(bool notify_render) override;
Render_Input_Frame_Guard acquire_input_read(Renderable_Input_Role role) override;
Renderable_Frame_View capture_frame_view() override;
Render_State* state(Renderable_State_Role role) override;
Input_Data* input_data(Renderable_Input_Role role) override;
@@ -21,6 +21,7 @@ public:
Render_State_Read_Guard acquire_edit_state_read() override;
Render_State_Write_Guard acquire_edit_state() override;
Render_Input_Write_Guard acquire_edit_input(bool notify_render) override;
Render_Input_Frame_Guard acquire_input_read(Renderable_Input_Role role) override;
Renderable_Frame_View capture_frame_view() override;
Render_State* state(Renderable_State_Role role) override;
Input_Data* input_data(Renderable_Input_Role role) override;
+13 -1
View File
@@ -240,7 +240,7 @@ struct Low_Latency_Renderable_Runtime_Data {
committed_update_states.push_back(std::move(slot.completion_state));
}
if (slot.data)
slot.data->clear();
slot.data->consume();
slot.pending = false;
}
};
@@ -379,6 +379,18 @@ Render_Input_Write_Guard Low_Latency_Renderable_Runtime::acquire_edit_input(bool
return Render_Input_Write_Guard(input, std::make_unique<Low_Latency_Input_Write_Handle>(d.get(), record.lease, notify_render));
}
Render_Input_Frame_Guard Low_Latency_Renderable_Runtime::acquire_input_read(Renderable_Input_Role role) {
Triple_Buffer_Lease lease = d->try_mark_input_role(input_role_index(role));
if (!lease)
return {};
Input_Data* input = d->input_data_by_index(lease.index);
if (!input) {
d->input_control.unmark_use(lease);
return {};
}
return Render_Input_Frame_Guard(input, std::make_unique<Low_Latency_Input_Frame_Handle>(d.get(), lease));
}
Renderable_Frame_View Low_Latency_Renderable_Runtime::capture_frame_view() {
d->sync_state_pipeline();
Triple_Buffer_Lease state_lease = d->try_mark_state_role(State_Render);
+38 -7
View File
@@ -237,14 +237,14 @@ void Spectrum_Private::update_frequency_point_size(int frequency_point_size, Ran
frequency[i] = cur;
}
}
void Spectrum_Private::set_frequency_data(std::pmr::vector<double>& line_data, const std::pmr::vector<double>* max_data, const std::pmr::vector<double>* min_data, const Spectrum_Render_State* s) {
void Spectrum_Private::set_frequency_data(const std::pmr::vector<double>& line_data, const std::pmr::vector<double>* max_data, const std::pmr::vector<double>* min_data, const Spectrum_Render_State* s) {
if (s->frequency_point_size <= 0)
return;
if (line_data.size() != s->frequency_point_size)
return;
if ((max_data && max_data->size() != s->frequency_point_size) || (min_data && min_data->size() != s->frequency_point_size))
return;
cur_powers.swap(line_data);
cur_powers.assign(line_data.begin(), line_data.end());
if (!has_power_data) {
max_powers.assign(cur_powers.begin(), cur_powers.end());
min_powers.assign(cur_powers.begin(), cur_powers.end());
@@ -449,36 +449,44 @@ void Spectrum::update_samples(std::span<const double> line_data) {
return;
Spectrum_Private* pd = d();
int frequency_point_size{};
Range frequency_range{};
Line_Interpolation_Mode interpolation_mode{};
bool use_max_line{};
bool use_min_line{};
{
Render_State_Lease<Spectrum_Private, Spectrum_Render_State> state(pd);
frequency_point_size = state->frequency_point_size;
frequency_range = state->frequency_range;
interpolation_mode = state->interpolation_mode;
use_max_line = state->max_hold_visible;
use_min_line = state->min_hold_visible;
}
if (line_data.size() != frequency_point_size)
return;
Render_Input_Lease<Spectrum_Private, Spectrum_Input_Data> input(pd);
input->push(line_data, use_max_line, use_min_line);
input->push(line_data, frequency_range, interpolation_mode, use_max_line, use_min_line);
}
void Spectrum::update_samples(std::pmr::vector<double>&& line_data) {
if (!ok())
return;
Spectrum_Private* pd = d();
int frequency_point_size{};
Range frequency_range{};
Line_Interpolation_Mode interpolation_mode{};
bool use_max_line{};
bool use_min_line{};
{
Render_State_Lease<Spectrum_Private, Spectrum_Render_State> state(pd);
frequency_point_size = state->frequency_point_size;
frequency_range = state->frequency_range;
interpolation_mode = state->interpolation_mode;
use_max_line = state->max_hold_visible;
use_min_line = state->min_hold_visible;
}
if (line_data.size() != frequency_point_size)
return;
Render_Input_Lease<Spectrum_Private, Spectrum_Input_Data> input(pd);
input->push(std::move(line_data), use_max_line, use_min_line);
input->push(std::move(line_data), frequency_range, interpolation_mode, use_max_line, use_min_line);
}
Update_Ticket Spectrum::submit_data(std::span<const double> line_data) {
auto update_state = make_update_state();
@@ -488,11 +496,15 @@ Update_Ticket Spectrum::submit_data(std::span<const double> line_data) {
}
Spectrum_Private* pd = d();
int frequency_point_size{};
Range frequency_range{};
Line_Interpolation_Mode interpolation_mode{};
bool use_max_line{};
bool use_min_line{};
{
Render_State_Lease<Spectrum_Private, Spectrum_Render_State> state(pd);
frequency_point_size = state->frequency_point_size;
frequency_range = state->frequency_range;
interpolation_mode = state->interpolation_mode;
use_max_line = state->max_hold_visible;
use_min_line = state->min_hold_visible;
}
@@ -502,7 +514,7 @@ Update_Ticket Spectrum::submit_data(std::span<const double> line_data) {
}
{
Render_Input_Lease<Spectrum_Private, Spectrum_Input_Data> input(pd);
input->push(line_data, use_max_line, use_min_line);
input->push(line_data, frequency_range, interpolation_mode, use_max_line, use_min_line);
input.set_completion(update_state);
}
update_state->complete_until(Update_Stage::Input_Released);
@@ -516,11 +528,15 @@ Update_Ticket Spectrum::submit_data(std::pmr::vector<double>&& line_data) {
}
Spectrum_Private* pd = d();
int frequency_point_size{};
Range frequency_range{};
Line_Interpolation_Mode interpolation_mode{};
bool use_max_line{};
bool use_min_line{};
{
Render_State_Lease<Spectrum_Private, Spectrum_Render_State> state(pd);
frequency_point_size = state->frequency_point_size;
frequency_range = state->frequency_range;
interpolation_mode = state->interpolation_mode;
use_max_line = state->max_hold_visible;
use_min_line = state->min_hold_visible;
}
@@ -530,7 +546,7 @@ Update_Ticket Spectrum::submit_data(std::pmr::vector<double>&& line_data) {
}
{
Render_Input_Lease<Spectrum_Private, Spectrum_Input_Data> input(pd);
input->push(std::move(line_data), use_max_line, use_min_line);
input->push(std::move(line_data), frequency_range, interpolation_mode, use_max_line, use_min_line);
input.set_completion(update_state);
}
update_state->complete_until(Update_Stage::Input_Released);
@@ -605,6 +621,21 @@ void Spectrum::clear_marker_selection() {
edit->un_select();
}
double Spectrum::power_at(double frequency, bool& ok) {
return d()->get_y(frequency, ok, interpolation_mode());
Spectrum_Private* pd = d();
Render_Input_Read_Lease<Spectrum_Private, Spectrum_Input_Data> input(pd);
if (!input || !input->has_data) {
ok = false;
return -1.0;
}
const auto& powers = input->cur_data;
if (powers.size() < 2 || input->frequency_range.length() == 0.0 || !input->frequency_range.contains(frequency)) {
ok = false;
return -1.0;
}
double index = coordinate_to_source_index(input->frequency_range, powers.size(), frequency);
ok = true;
return interpolate_sample_value(index, powers.size(), input->interpolation_mode, [&powers](int i) {
return powers.at(i);
});
}
} // namespace renderive
+32 -7
View File
@@ -32,10 +32,20 @@ struct Spectrum_Input_Data : Latest_Input_Data {
std::pmr::vector<double> cur_data{memory_resource(Memory_Domain::Spectrum)};
std::pmr::vector<double> max_data{memory_resource(Memory_Domain::Spectrum)};
std::pmr::vector<double> min_data{memory_resource(Memory_Domain::Spectrum)};
Range frequency_range{};
Line_Interpolation_Mode interpolation_mode = Line_Interpolation_Mode::Nearest_Sample;
bool has_data = false;
bool has_max_data = false;
bool has_min_data = false;
void push(std::span<const double> data, bool use_max, bool use_min) {
void push(std::span<const double> data, Range range, Line_Interpolation_Mode mode, bool use_max, bool use_min) {
if (has_data && frequency_range != range) {
max_data.clear();
min_data.clear();
has_max_data = false;
has_min_data = false;
}
frequency_range = range;
interpolation_mode = mode;
cur_data.assign(data.begin(), data.end());
has_data = true;
if (use_max) {
@@ -64,7 +74,15 @@ struct Spectrum_Input_Data : Latest_Input_Data {
}
mark_latest_pushed();
}
void push(std::pmr::vector<double>&& data, bool use_max, bool use_min) {
void push(std::pmr::vector<double>&& data, Range range, Line_Interpolation_Mode mode, bool use_max, bool use_min) {
if (has_data && frequency_range != range) {
max_data.clear();
min_data.clear();
has_max_data = false;
has_min_data = false;
}
frequency_range = range;
interpolation_mode = mode;
cur_data = std::move(data);
has_data = true;
if (use_max) {
@@ -94,11 +112,18 @@ struct Spectrum_Input_Data : Latest_Input_Data {
mark_latest_pushed();
}
template <typename Handler>
void read_all(Handler handler) {
if (!has_data)
void read_all(Handler handler) const {
if (!pending || !has_data)
return;
handler(cur_data, has_max_data ? &max_data : nullptr, has_min_data ? &min_data : nullptr);
}
void consume() override {
max_data.clear();
min_data.clear();
has_max_data = false;
has_min_data = false;
clear_latest();
}
void clear() override {
cur_data.clear();
max_data.clear();
@@ -176,7 +201,7 @@ struct Spectrum_Private : Typed_Render_Data<Spectrum, Spectrum_Render_State, Spe
std::pmr::vector<Marker_Item> prepared_marker_items{memory_resource(Memory_Domain::Other)};
std::pmr::vector<Label_Item> prepared_label_items{memory_resource(Memory_Domain::Other)};
void update_frequency_point_size(int frequency_point_size, Range frequency_range);
void set_frequency_data(std::pmr::vector<double>& line_data, const std::pmr::vector<double>* max_data, const std::pmr::vector<double>* min_data, const Spectrum_Render_State* s);
void set_frequency_data(const std::pmr::vector<double>& line_data, const std::pmr::vector<double>* max_data, const std::pmr::vector<double>* min_data, const Spectrum_Render_State* s);
void update_marker_items(const Spectrum_Render_State* s, const Render_Frame_Snapshot& snapshot);
[[nodiscard]] double get_y(double x, bool& ok, Line_Interpolation_Mode mode);
void draw_power_curve(Canvas& canvas, const Render_Frame_Snapshot& snapshot, Spectrum_Render_State* s, const std::pmr::vector<double>& powers, const Pen& pen, const Brush& brush);
@@ -192,7 +217,7 @@ struct Spectrum_Private : Typed_Render_Data<Spectrum, Spectrum_Render_State, Spe
if (cache_frequency_point_size != s->frequency_point_size || cache_frequency_range != s->frequency_range) {
update_frequency_point_size(s->frequency_point_size, s->frequency_range);
}
input->read_all([this, s](std::pmr::vector<double>& data, const std::pmr::vector<double>* max_data, const std::pmr::vector<double>* min_data) {
input->read_all([this, s](const std::pmr::vector<double>& data, const std::pmr::vector<double>* max_data, const std::pmr::vector<double>* min_data) {
set_frequency_data(data, max_data, min_data, s);
});
if (has_power_data) {
@@ -209,7 +234,7 @@ struct Spectrum_Private : Typed_Render_Data<Spectrum, Spectrum_Render_State, Spe
Axis_Mapping_2D mapping = Axis_Render_Access::mapping(frequency_axis.get(), power_axis.get());
const double frequency_val = mapping.domain.pixel_to_coord(mapping.domain_pixel(pos));
bool ok;
const double power = get_y(frequency_val, ok, sc->interpolation_mode);
const double power = q()->power_at(frequency_val, ok);
if (!ok)
return false;
return std::abs(mapping.value.coord_to_pixel(power) - mapping.value_pixel(pos)) < 4.0;