核心模板架构
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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{};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,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;
|
||||
|
||||
Reference in New Issue
Block a user