升级
This commit is contained in:
@@ -67,7 +67,7 @@ void Afterglow_Control::publish() {
|
||||
void Afterglow_Control::build_paint_task_graph(Renderable_Task_Graph& graph) {
|
||||
auto& output = impl_->render_frame;
|
||||
const auto view = render_state_view();
|
||||
const auto& state = render_properties(view);
|
||||
const auto state = properties();
|
||||
const auto& history = view.get(impl_->history);
|
||||
const int width = history.empty()
|
||||
? 0
|
||||
@@ -84,7 +84,7 @@ void Afterglow_Control::build_paint_task_graph(Renderable_Task_Graph& graph) {
|
||||
static_cast<int>(Scene_Base::task_executor_worker_count()), work_size, 4096);
|
||||
const auto prepare = graph.emplace([this, partition_count](const Scene_Render_Context&) {
|
||||
prepare_render_frame(render_state_view(), partition_count);
|
||||
}, "prepare afterglow");
|
||||
}, "准备余晖图");
|
||||
std::vector<Renderable_Task_Graph::Task> accumulation;
|
||||
accumulation.reserve(static_cast<std::size_t>(partition_count));
|
||||
for (int index = 0; index < partition_count; ++index) {
|
||||
@@ -92,13 +92,13 @@ void Afterglow_Control::build_paint_task_graph(Renderable_Task_Graph& graph) {
|
||||
[this, index](const Scene_Render_Context&) {
|
||||
accumulate_partition(render_state_view(), index);
|
||||
},
|
||||
"accumulate afterglow partition " + std::to_string(index + 1));
|
||||
"累积余晖图分区 " + std::to_string(index + 1));
|
||||
graph.precede(prepare, task);
|
||||
accumulation.push_back(task);
|
||||
}
|
||||
const auto normalize = graph.emplace([this](const Scene_Render_Context&) {
|
||||
normalize_render_frame();
|
||||
}, "normalize afterglow");
|
||||
}, "归一化余晖图");
|
||||
for (const auto task : accumulation)
|
||||
graph.precede(task, normalize);
|
||||
std::vector<Renderable_Task_Graph::Task> coloring;
|
||||
@@ -108,12 +108,12 @@ void Afterglow_Control::build_paint_task_graph(Renderable_Task_Graph& graph) {
|
||||
[this, index](const Scene_Render_Context&) {
|
||||
color_partition(render_state_view(), index);
|
||||
},
|
||||
"color afterglow partition " + std::to_string(index + 1));
|
||||
"着色余晖图分区 " + std::to_string(index + 1));
|
||||
graph.precede(normalize, task);
|
||||
coloring.push_back(task);
|
||||
}
|
||||
const auto paint_image = add_paint_task(
|
||||
graph, "paint afterglow shared image",
|
||||
graph, "绘制余晖图共享图像",
|
||||
[this](Painter& painter, const Render_State_View& frame_view,
|
||||
const Scene_Render_Context& context) {
|
||||
paint_render_frame(painter, frame_view,
|
||||
|
||||
@@ -52,11 +52,19 @@ namespace detail {
|
||||
class Paint_Overlay {};
|
||||
|
||||
template <Property_Set Properties_Type>
|
||||
class Plottable_State : public Double_State_Strategy<Renderable, Properties_Type> {
|
||||
class Plottable_State
|
||||
: public Double_State_Strategy<Renderable, Properties_Type, Atomic_Spin_Mutex,
|
||||
Observer_State<Renderable_State_Observer>> {
|
||||
public:
|
||||
using Properties = Properties_Type;
|
||||
using Base = Double_State_Strategy<Renderable, Properties>;
|
||||
Plottable_State(Plot_Core& plot, const Properties& properties) : Base(properties, plot) {}
|
||||
using State_Observer = Observer_State<Renderable_State_Observer>;
|
||||
using Base = Double_State_Strategy<Renderable, Properties, Atomic_Spin_Mutex,
|
||||
State_Observer>;
|
||||
Plottable_State(Plot_Core& plot, const Properties& properties)
|
||||
: Base(properties,
|
||||
With_Observer<State_Observer>{
|
||||
State_Observer(Renderable_State_Observer(this))},
|
||||
plot) {}
|
||||
template <auto Member, Property_Member_Assignable<Properties, Member> Value>
|
||||
Plottable_State& set(Value&& value) {
|
||||
Base::template set<Member>(std::forward<Value>(value));
|
||||
@@ -76,7 +84,6 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
this->changed();
|
||||
return *this;
|
||||
}
|
||||
template <auto Member>
|
||||
|
||||
@@ -66,11 +66,20 @@ void draw_curve(Painter& painter, std::span<const double> values, Range domain,
|
||||
if(brush.enabled()) {
|
||||
std::vector<PointF> polygon;
|
||||
polygon.reserve(points.size() + 2);
|
||||
polygon.push_back(mapped_point(frequency_axis, domain.origin, power_axis,
|
||||
power_axis.coordinate_range.target));
|
||||
PointF first_baseline = points.front();
|
||||
PointF last_baseline = points.back();
|
||||
const double baseline =
|
||||
power_axis.coord_to_pixel(power_axis.coordinate_range.target);
|
||||
if (power_axis.orientation == Orientation::Horizontal) {
|
||||
first_baseline.x = baseline;
|
||||
last_baseline.x = baseline;
|
||||
} else {
|
||||
first_baseline.y = baseline;
|
||||
last_baseline.y = baseline;
|
||||
}
|
||||
polygon.push_back(first_baseline);
|
||||
polygon.insert(polygon.end(), points.begin(), points.end());
|
||||
polygon.push_back(mapped_point(frequency_axis, domain.target, power_axis,
|
||||
power_axis.coordinate_range.target));
|
||||
polygon.push_back(last_baseline);
|
||||
painter.polygon(polygon, Pen{.style = Line_Style::None}, brush);
|
||||
}
|
||||
painter.polyline(points, pen);
|
||||
@@ -244,14 +253,14 @@ void Spectrum_Control::publish() {
|
||||
void Spectrum_Control::build_paint_task_graph(Renderable_Task_Graph& graph) {
|
||||
auto& output = impl_->render_frame;
|
||||
const auto view = render_state_view();
|
||||
const auto& state = render_properties(view);
|
||||
const auto state = properties();
|
||||
const auto& published_frame = view.get(impl_->frame);
|
||||
const std::size_t work_size = published_frame ? published_frame->samples.size() : 0;
|
||||
const int partition_count = output.partitioner.graph_partition_count(
|
||||
state.partition_mode, state.partition_count.get(),
|
||||
static_cast<int>(Scene_Base::task_executor_worker_count()), work_size, 128);
|
||||
const auto prepare = add_paint_task(
|
||||
graph, "prepare spectrum and paint background",
|
||||
graph, "准备频谱并绘制背景",
|
||||
[this, partition_count](Painter& painter, const Render_State_View& frame_view,
|
||||
const Scene_Render_Context&) {
|
||||
prepare_render_frame(frame_view, partition_count);
|
||||
@@ -261,7 +270,7 @@ void Spectrum_Control::build_paint_task_graph(Renderable_Task_Graph& graph) {
|
||||
partitions.reserve(static_cast<std::size_t>(partition_count));
|
||||
for (int index = 0; index < partition_count; ++index) {
|
||||
const auto partition = add_paint_task(
|
||||
graph, "paint spectrum partition " + std::to_string(index + 1),
|
||||
graph, "绘制频谱分区 " + std::to_string(index + 1),
|
||||
[this, index](Painter& painter, const Render_State_View& frame_view,
|
||||
const Scene_Render_Context&) {
|
||||
render_partition(painter, frame_view, index);
|
||||
@@ -270,7 +279,7 @@ void Spectrum_Control::build_paint_task_graph(Renderable_Task_Graph& graph) {
|
||||
partitions.push_back(partition);
|
||||
}
|
||||
const auto overlay = add_paint_task(
|
||||
graph, "paint spectrum overlay",
|
||||
graph, "绘制频谱覆盖层",
|
||||
[this](Painter& painter, const Render_State_View& frame_view,
|
||||
const Scene_Render_Context& context) {
|
||||
paint_overlay(painter, frame_view,
|
||||
|
||||
@@ -99,7 +99,7 @@ void Waterfall_Control::publish() {
|
||||
void Waterfall_Control::build_paint_task_graph(Renderable_Task_Graph& graph) {
|
||||
auto& output = impl_->render_frame;
|
||||
const auto view = render_state_view();
|
||||
const auto& state = render_properties(view);
|
||||
const auto state = properties();
|
||||
const auto& rows = view.get(impl_->rows);
|
||||
std::size_t work_size{};
|
||||
if (!rows.empty()) {
|
||||
@@ -117,7 +117,7 @@ void Waterfall_Control::build_paint_task_graph(Renderable_Task_Graph& graph) {
|
||||
static_cast<int>(Scene_Base::task_executor_worker_count()), work_size, 4096);
|
||||
const auto prepare = graph.emplace([this, partition_count](const Scene_Render_Context&) {
|
||||
prepare_render_frame(render_state_view(), partition_count);
|
||||
}, "prepare waterfall");
|
||||
}, "准备瀑布图");
|
||||
std::vector<Renderable_Task_Graph::Task> partitions;
|
||||
partitions.reserve(static_cast<std::size_t>(partition_count));
|
||||
for (int index = 0; index < partition_count; ++index) {
|
||||
@@ -125,12 +125,12 @@ void Waterfall_Control::build_paint_task_graph(Renderable_Task_Graph& graph) {
|
||||
[this, index](const Scene_Render_Context&) {
|
||||
render_partition(render_state_view(), index);
|
||||
},
|
||||
"raster waterfall partition " + std::to_string(index + 1));
|
||||
"光栅化瀑布图分区 " + std::to_string(index + 1));
|
||||
graph.precede(prepare, partition);
|
||||
partitions.push_back(partition);
|
||||
}
|
||||
const auto paint_image = add_paint_task(
|
||||
graph, "paint waterfall shared image",
|
||||
graph, "绘制瀑布图共享图像",
|
||||
[this](Painter& painter, const Render_State_View& frame_view,
|
||||
const Scene_Render_Context& context) {
|
||||
paint_render_frame(painter, frame_view,
|
||||
|
||||
@@ -5,8 +5,156 @@
|
||||
|
||||
#include <renderive/scene/base/Scene_Render_Context.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
namespace renderive {
|
||||
|
||||
Renderable_Observation Renderable_Observer::observation() const noexcept {
|
||||
std::lock_guard lock(mutex_);
|
||||
auto result = observation_;
|
||||
const auto render = render_duration_statistics_.snapshot();
|
||||
const auto task = task_duration_statistics_.snapshot();
|
||||
const auto nanoseconds = [](double value) {
|
||||
return static_cast<std::uint64_t>(std::max(0.0, std::round(value)));
|
||||
};
|
||||
result.render_duration_sample_count = render.sample_count;
|
||||
result.render_duration_average_ns = nanoseconds(render.average);
|
||||
result.render_duration_deviation_ns = nanoseconds(render.deviation);
|
||||
result.render_duration_p50_ns = nanoseconds(render.p50);
|
||||
result.render_duration_p95_ns = nanoseconds(render.p95);
|
||||
result.render_duration_p99_ns = nanoseconds(render.p99);
|
||||
result.task_duration_sample_count = task.sample_count;
|
||||
result.task_duration_average_ns = nanoseconds(task.average);
|
||||
result.task_duration_deviation_ns = nanoseconds(task.deviation);
|
||||
result.task_duration_p50_ns = nanoseconds(task.p50);
|
||||
result.task_duration_p95_ns = nanoseconds(task.p95);
|
||||
result.task_duration_p99_ns = nanoseconds(task.p99);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Renderable_Observer::observe_state(Renderable_Observer_Event event,
|
||||
std::uint64_t time_ns,
|
||||
std::uint64_t cache_update_count,
|
||||
std::uint64_t publish_count) noexcept {
|
||||
std::lock_guard lock(mutex_);
|
||||
observation_.event = event;
|
||||
observation_.event_time_ns = time_ns;
|
||||
observation_.cache_update_count = cache_update_count;
|
||||
observation_.publish_count = publish_count;
|
||||
}
|
||||
|
||||
void Renderable_Observer::observe_task(
|
||||
const Renderable_Task_Observation& task) noexcept {
|
||||
std::lock_guard lock(mutex_);
|
||||
if (task.event == Renderable_Task_Observation_Event::started) {
|
||||
if (active_render_sequence_ != task.render_sequence) {
|
||||
active_render_sequence_ = task.render_sequence;
|
||||
active_render_started_ns_ = task.time_ns;
|
||||
active_task_count_ = task.task_count;
|
||||
completed_task_count_ = 0;
|
||||
running_task_count_ = 0;
|
||||
active_peak_parallelism_ = 0;
|
||||
active_render_failed_ = false;
|
||||
}
|
||||
++running_task_count_;
|
||||
++observation_.task_execution_count;
|
||||
active_peak_parallelism_ =
|
||||
std::max(active_peak_parallelism_, running_task_count_);
|
||||
if (!active_render_failed_) {
|
||||
observation_.event = Renderable_Observer_Event::Render_Started;
|
||||
observation_.event_time_ns = task.time_ns;
|
||||
}
|
||||
observation_.last_render_sequence = task.render_sequence;
|
||||
return;
|
||||
}
|
||||
|
||||
if (active_render_sequence_ != task.render_sequence)
|
||||
return;
|
||||
if (running_task_count_ != 0)
|
||||
--running_task_count_;
|
||||
++completed_task_count_;
|
||||
observation_.last_task_duration_ns = task.task_duration_ns;
|
||||
observation_.total_task_duration_ns += task.task_duration_ns;
|
||||
observation_.maximum_task_duration_ns =
|
||||
std::max(observation_.maximum_task_duration_ns, task.task_duration_ns);
|
||||
task_duration_statistics_.add(static_cast<double>(task.task_duration_ns));
|
||||
|
||||
const auto render_duration =
|
||||
task.time_ns >= active_render_started_ns_
|
||||
? task.time_ns - active_render_started_ns_
|
||||
: 0;
|
||||
const auto extend_failed_render_duration = [&] {
|
||||
if (render_duration > observation_.last_render_duration_ns) {
|
||||
observation_.total_render_duration_ns +=
|
||||
render_duration - observation_.last_render_duration_ns;
|
||||
observation_.last_render_duration_ns = render_duration;
|
||||
render_duration_statistics_.replace_latest(
|
||||
static_cast<double>(render_duration));
|
||||
observation_.maximum_render_duration_ns =
|
||||
std::max(observation_.maximum_render_duration_ns, render_duration);
|
||||
}
|
||||
};
|
||||
if (task.event == Renderable_Task_Observation_Event::failed) {
|
||||
++observation_.failed_task_count;
|
||||
if (!active_render_failed_) {
|
||||
active_render_failed_ = true;
|
||||
++observation_.failed_render_count;
|
||||
observation_.event = Renderable_Observer_Event::Render_Failed;
|
||||
observation_.event_time_ns = task.time_ns;
|
||||
observation_.last_render_duration_ns = render_duration;
|
||||
observation_.total_render_duration_ns += render_duration;
|
||||
render_duration_statistics_.add(static_cast<double>(render_duration));
|
||||
observation_.maximum_render_duration_ns =
|
||||
std::max(observation_.maximum_render_duration_ns, render_duration);
|
||||
observation_.last_task_count = active_task_count_;
|
||||
observation_.peak_parallelism = active_peak_parallelism_;
|
||||
} else
|
||||
extend_failed_render_duration();
|
||||
return;
|
||||
}
|
||||
|
||||
if (active_render_failed_) {
|
||||
extend_failed_render_duration();
|
||||
return;
|
||||
}
|
||||
|
||||
if (completed_task_count_ == active_task_count_) {
|
||||
++observation_.successful_render_count;
|
||||
observation_.event = Renderable_Observer_Event::Render_Completed;
|
||||
observation_.event_time_ns = task.time_ns;
|
||||
observation_.last_render_duration_ns = render_duration;
|
||||
observation_.total_render_duration_ns += render_duration;
|
||||
render_duration_statistics_.add(static_cast<double>(render_duration));
|
||||
observation_.maximum_render_duration_ns =
|
||||
std::max(observation_.maximum_render_duration_ns, render_duration);
|
||||
observation_.last_task_count = active_task_count_;
|
||||
observation_.peak_parallelism = active_peak_parallelism_;
|
||||
}
|
||||
}
|
||||
|
||||
void Renderable_Observer::reset_performance() noexcept {
|
||||
std::lock_guard lock(mutex_);
|
||||
Renderable_Observation reset;
|
||||
if (observation_.event == Renderable_Observer_Event::Cache_Updated ||
|
||||
observation_.event == Renderable_Observer_Event::Published) {
|
||||
reset.event = observation_.event;
|
||||
reset.event_time_ns = observation_.event_time_ns;
|
||||
}
|
||||
reset.cache_update_count = observation_.cache_update_count;
|
||||
reset.publish_count = observation_.publish_count;
|
||||
observation_ = reset;
|
||||
active_render_sequence_ = 0;
|
||||
active_render_started_ns_ = 0;
|
||||
active_task_count_ = 0;
|
||||
completed_task_count_ = 0;
|
||||
running_task_count_ = 0;
|
||||
active_peak_parallelism_ = 0;
|
||||
active_render_failed_ = false;
|
||||
render_duration_statistics_.clear();
|
||||
task_duration_statistics_.clear();
|
||||
}
|
||||
|
||||
Renderable::Renderable(Plot_Core& plot, bool cache_enabled)
|
||||
: ::Renderable_Base(plot.kernel_scene(), {.cache_enabled = cache_enabled}), plot_(plot) {}
|
||||
|
||||
@@ -41,6 +189,26 @@ void Renderable::set_visible(bool visible) {
|
||||
changed();
|
||||
}
|
||||
|
||||
Renderable_Observation Renderable::observation() const noexcept {
|
||||
return observer_.observation();
|
||||
}
|
||||
|
||||
void Renderable::observe_state(Renderable_Observer_Event event,
|
||||
std::uint64_t time_ns,
|
||||
std::uint64_t cache_update_count,
|
||||
std::uint64_t publish_count) noexcept {
|
||||
observer_.observe_state(event, time_ns, cache_update_count, publish_count);
|
||||
}
|
||||
|
||||
void Renderable::observe_task(
|
||||
const Renderable_Task_Observation& observation) noexcept {
|
||||
observer_.observe_task(observation);
|
||||
}
|
||||
|
||||
void Renderable::reset_task_observation() noexcept {
|
||||
observer_.reset_performance();
|
||||
}
|
||||
|
||||
void Renderable::render(const ::Scene_Render_Context& context) {
|
||||
if (!is_visible() || context.color_cache == nullptr)
|
||||
return;
|
||||
@@ -59,7 +227,7 @@ void Renderable::build_task_graph(Renderable_Task_Graph& graph) {
|
||||
}
|
||||
|
||||
void Renderable::build_paint_task_graph(Renderable_Task_Graph& graph) {
|
||||
add_paint_task(graph, "paint", [this](detail::Painter& painter,
|
||||
add_paint_task(graph, "绘制", [this](detail::Painter& painter,
|
||||
const Render_State_View& state,
|
||||
const Scene_Render_Context&) {
|
||||
paint(painter, state);
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include "../event/Event.h"
|
||||
|
||||
#include <renderive/renderable/base/Renderable_Base.hpp>
|
||||
#include <renderive/renderable/base/Renderable_Task_Observer.hpp>
|
||||
#include <renderive/base/statistics/Rolling_Statistics.hpp>
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
@@ -24,7 +26,72 @@ public:
|
||||
virtual void handle_event(const Event& event) = 0;
|
||||
};
|
||||
|
||||
class LIB_DECL Renderable : public ::Renderable_Base {
|
||||
enum class Renderable_Observer_Event {
|
||||
None,
|
||||
Cache_Updated,
|
||||
Published,
|
||||
Render_Started,
|
||||
Render_Completed,
|
||||
Render_Failed
|
||||
};
|
||||
|
||||
struct Renderable_Observation {
|
||||
Renderable_Observer_Event event{Renderable_Observer_Event::None};
|
||||
std::uint64_t event_time_ns{};
|
||||
std::uint64_t cache_update_count{};
|
||||
std::uint64_t publish_count{};
|
||||
std::uint64_t successful_render_count{};
|
||||
std::uint64_t failed_render_count{};
|
||||
std::uint64_t last_render_sequence{};
|
||||
std::uint64_t last_render_duration_ns{};
|
||||
std::uint64_t total_render_duration_ns{};
|
||||
std::uint64_t maximum_render_duration_ns{};
|
||||
std::size_t render_duration_sample_count{};
|
||||
std::uint64_t render_duration_average_ns{};
|
||||
std::uint64_t render_duration_deviation_ns{};
|
||||
std::uint64_t render_duration_p50_ns{};
|
||||
std::uint64_t render_duration_p95_ns{};
|
||||
std::uint64_t render_duration_p99_ns{};
|
||||
std::uint64_t task_execution_count{};
|
||||
std::uint64_t failed_task_count{};
|
||||
std::uint64_t last_task_duration_ns{};
|
||||
std::uint64_t total_task_duration_ns{};
|
||||
std::uint64_t maximum_task_duration_ns{};
|
||||
std::size_t task_duration_sample_count{};
|
||||
std::uint64_t task_duration_average_ns{};
|
||||
std::uint64_t task_duration_deviation_ns{};
|
||||
std::uint64_t task_duration_p50_ns{};
|
||||
std::uint64_t task_duration_p95_ns{};
|
||||
std::uint64_t task_duration_p99_ns{};
|
||||
std::size_t last_task_count{};
|
||||
std::size_t peak_parallelism{};
|
||||
};
|
||||
|
||||
class LIB_DECL Renderable_Observer final {
|
||||
public:
|
||||
[[nodiscard]] Renderable_Observation observation() const noexcept;
|
||||
void observe_state(Renderable_Observer_Event event, std::uint64_t time_ns,
|
||||
std::uint64_t cache_update_count,
|
||||
std::uint64_t publish_count) noexcept;
|
||||
void observe_task(const Renderable_Task_Observation& observation) noexcept;
|
||||
void reset_performance() noexcept;
|
||||
|
||||
private:
|
||||
mutable std::mutex mutex_;
|
||||
Renderable_Observation observation_;
|
||||
std::uint64_t active_render_sequence_{};
|
||||
std::uint64_t active_render_started_ns_{};
|
||||
std::size_t active_task_count_{};
|
||||
std::size_t completed_task_count_{};
|
||||
std::size_t running_task_count_{};
|
||||
std::size_t active_peak_parallelism_{};
|
||||
bool active_render_failed_{};
|
||||
Rolling_Statistics render_duration_statistics_{256};
|
||||
Rolling_Statistics task_duration_statistics_{1024};
|
||||
};
|
||||
|
||||
class LIB_DECL Renderable : public ::Renderable_Base,
|
||||
public ::Renderable_Task_Observer {
|
||||
public:
|
||||
explicit Renderable(Plot_Core& plot, bool cache_enabled = true);
|
||||
~Renderable() override;
|
||||
@@ -37,8 +104,10 @@ public:
|
||||
void set_object_name(std::string name);
|
||||
[[nodiscard]] bool is_visible() const noexcept;
|
||||
void set_visible(bool visible);
|
||||
[[nodiscard]] Renderable_Observation observation() const noexcept;
|
||||
|
||||
void render(const ::Scene_Render_Context& context) final;
|
||||
void observe_task(const Renderable_Task_Observation& observation) noexcept final;
|
||||
|
||||
protected:
|
||||
using Paint_Task_Function =
|
||||
@@ -56,11 +125,16 @@ protected:
|
||||
|
||||
private:
|
||||
void build_task_graph(Renderable_Task_Graph& graph) final;
|
||||
void reset_task_observation() noexcept final;
|
||||
void observe_state(Renderable_Observer_Event event, std::uint64_t time_ns,
|
||||
std::uint64_t cache_update_count,
|
||||
std::uint64_t publish_count) noexcept;
|
||||
friend class detail::Renderable_State_Observer;
|
||||
Plot_Core& plot_;
|
||||
mutable std::mutex metadata_mutex_;
|
||||
std::string object_name_;
|
||||
std::atomic<bool> visible_{true};
|
||||
Renderable_Observer observer_;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
@@ -73,7 +147,16 @@ public:
|
||||
|
||||
template <class Observation>
|
||||
void observe(const Observation& observation) noexcept {
|
||||
if (observation.event == decltype(observation.event)::cache_updated)
|
||||
const bool cache_updated =
|
||||
observation.event == decltype(observation.event)::cache_updated;
|
||||
renderable_->observe_state(
|
||||
cache_updated ? Renderable_Observer_Event::Cache_Updated
|
||||
: Renderable_Observer_Event::Published,
|
||||
observation.time_ns,
|
||||
observation.cache_update_count,
|
||||
observation.publish_count
|
||||
);
|
||||
if (cache_updated)
|
||||
renderable_->changed();
|
||||
}
|
||||
|
||||
|
||||
@@ -589,6 +589,88 @@ TEST(Renderive_Core2, PlottablePropertiesPublishOnlyAtFrameBoundary) {
|
||||
EXPECT_EQ(state->state_revision(), 1U);
|
||||
ASSERT_TRUE(plot.render_prepared_frame());
|
||||
}
|
||||
TEST(Renderive_Core2, EveryStatefulRenderableOwnsItsStateObserver) {
|
||||
Plot_Core plot;
|
||||
plot.init();
|
||||
const auto root = plot.root_renderable();
|
||||
const auto frequency = Frequency_Axis::Builder(root, Orientation::Horizontal).build();
|
||||
const auto power = Axis::Builder(root, Orientation::Vertical).build();
|
||||
const auto spectrum = Spectrum::Builder{}.build(root, frequency, power);
|
||||
ASSERT_TRUE(frequency);
|
||||
ASSERT_TRUE(power);
|
||||
ASSERT_TRUE(spectrum);
|
||||
|
||||
EXPECT_EQ(frequency->observation().event, Renderable_Observer_Event::None);
|
||||
EXPECT_EQ(power->observation().event, Renderable_Observer_Event::None);
|
||||
EXPECT_EQ(spectrum->observation().event, Renderable_Observer_Event::None);
|
||||
|
||||
frequency->set<&Axis_Properties::coordinates>(Range{88'000'000.0, 108'000'000.0});
|
||||
spectrum->set<&Spectrum::Properties::partition_count>(2);
|
||||
const auto frequency_update = frequency->observation();
|
||||
const auto spectrum_update = spectrum->observation();
|
||||
EXPECT_EQ(frequency_update.event, Renderable_Observer_Event::Cache_Updated);
|
||||
EXPECT_EQ(frequency_update.cache_update_count, 1U);
|
||||
EXPECT_EQ(spectrum_update.event, Renderable_Observer_Event::Cache_Updated);
|
||||
EXPECT_EQ(spectrum_update.cache_update_count, 1U);
|
||||
EXPECT_EQ(power->observation().event, Renderable_Observer_Event::None);
|
||||
|
||||
ASSERT_TRUE(plot.prepare_frame());
|
||||
const auto frequency_publish = frequency->observation();
|
||||
const auto power_publish = power->observation();
|
||||
const auto spectrum_publish = spectrum->observation();
|
||||
EXPECT_EQ(frequency_publish.event, Renderable_Observer_Event::Published);
|
||||
EXPECT_EQ(power_publish.event, Renderable_Observer_Event::Published);
|
||||
EXPECT_EQ(spectrum_publish.event, Renderable_Observer_Event::Published);
|
||||
EXPECT_EQ(frequency_publish.publish_count, 1U);
|
||||
EXPECT_EQ(power_publish.publish_count, 1U);
|
||||
EXPECT_EQ(spectrum_publish.publish_count, 1U);
|
||||
EXPECT_EQ(frequency_publish.cache_update_count, 1U);
|
||||
EXPECT_EQ(power_publish.cache_update_count, 0U);
|
||||
EXPECT_EQ(spectrum_publish.cache_update_count, 1U);
|
||||
|
||||
ASSERT_TRUE(plot.render_prepared_frame());
|
||||
const auto frequency_render = frequency->observation();
|
||||
const auto power_render = power->observation();
|
||||
const auto spectrum_render = spectrum->observation();
|
||||
EXPECT_EQ(frequency_render.event, Renderable_Observer_Event::Render_Completed);
|
||||
EXPECT_EQ(power_render.event, Renderable_Observer_Event::Render_Completed);
|
||||
EXPECT_EQ(spectrum_render.event, Renderable_Observer_Event::Render_Completed);
|
||||
EXPECT_GT(frequency_render.successful_render_count, 0U);
|
||||
EXPECT_GT(power_render.successful_render_count, 0U);
|
||||
EXPECT_GT(spectrum_render.successful_render_count, 0U);
|
||||
EXPECT_EQ(spectrum_render.last_task_count, spectrum->task_graph()->nodes().size());
|
||||
EXPECT_GE(spectrum_render.task_execution_count, spectrum_render.last_task_count);
|
||||
EXPECT_GE(spectrum_render.peak_parallelism, 1U);
|
||||
}
|
||||
TEST(Renderive_Core2, RenderableObserverKeepsFailureTerminalForTheRenderSequence) {
|
||||
Renderable_Observer observer;
|
||||
observer.observe_task({Renderable_Task_Observation_Event::started, 100, 7, 2, 0});
|
||||
observer.observe_task({Renderable_Task_Observation_Event::failed, 180, 7, 2, 80});
|
||||
observer.observe_task({Renderable_Task_Observation_Event::started, 190, 7, 2, 0});
|
||||
observer.observe_task({Renderable_Task_Observation_Event::completed, 240, 7, 2, 50});
|
||||
|
||||
const auto failed = observer.observation();
|
||||
EXPECT_EQ(failed.event, Renderable_Observer_Event::Render_Failed);
|
||||
EXPECT_EQ(failed.failed_render_count, 1U);
|
||||
EXPECT_EQ(failed.successful_render_count, 0U);
|
||||
EXPECT_EQ(failed.failed_task_count, 1U);
|
||||
EXPECT_EQ(failed.task_execution_count, 2U);
|
||||
EXPECT_EQ(failed.last_task_count, 2U);
|
||||
EXPECT_EQ(failed.last_render_duration_ns, 140U);
|
||||
EXPECT_EQ(failed.total_render_duration_ns, 140U);
|
||||
EXPECT_EQ(failed.render_duration_sample_count, 1U);
|
||||
EXPECT_EQ(failed.render_duration_p95_ns, 140U);
|
||||
EXPECT_EQ(failed.render_duration_p99_ns, 140U);
|
||||
EXPECT_EQ(failed.task_duration_sample_count, 2U);
|
||||
EXPECT_EQ(failed.task_duration_p95_ns, 80U);
|
||||
|
||||
observer.reset_performance();
|
||||
const auto reset = observer.observation();
|
||||
EXPECT_EQ(reset.failed_render_count, 0U);
|
||||
EXPECT_EQ(reset.task_execution_count, 0U);
|
||||
EXPECT_EQ(reset.render_duration_sample_count, 0U);
|
||||
EXPECT_EQ(reset.task_duration_sample_count, 0U);
|
||||
}
|
||||
TEST(Renderive_Core2, PlottableDataUpdatesReachKernelRealTimeDataStrategy) {
|
||||
Plot_Core plot;
|
||||
plot.init();
|
||||
|
||||
Reference in New Issue
Block a user