修复若干bug
This commit is contained in:
@@ -16,6 +16,7 @@ struct LIB_DECL Hover_Info_Render_State {
|
||||
virtual ~Hover_Info_Render_State() = default;
|
||||
Hover_Info_Render_State() {
|
||||
hover_info_brush = Brush{Color::white(), Brush_Style::Solid};
|
||||
hover_info_pen = Pen{Color::black()};
|
||||
}
|
||||
int hover_info_left = 4;
|
||||
int hover_info_top = 4;
|
||||
|
||||
@@ -233,6 +233,18 @@ static std::function<void()> performance_update_callback(const std::shared_ptr<P
|
||||
std::lock_guard<std::mutex> lock(ctx->performance_update_callback_mutex);
|
||||
return ctx->performance_update_callback;
|
||||
}
|
||||
|
||||
static void request_performance_update(const std::shared_ptr<Performance_Metrics_Worker_State>& worker) {
|
||||
if (!worker)
|
||||
return;
|
||||
std::function<void()> callback;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(worker->update_callback_mutex);
|
||||
callback = worker->update_callback;
|
||||
}
|
||||
if (callback)
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
void schedule_performance_metrics_worker(const std::shared_ptr<Performance_Metrics_Worker_State>& state) {
|
||||
@@ -257,18 +269,36 @@ Performance_Shower_Private* Performance_Shower::d() {
|
||||
return private_data.get();
|
||||
}
|
||||
|
||||
std::shared_ptr<Performance_Shower> attach_performance_shower(Plot_Core& plot) {
|
||||
static std::shared_ptr<Performance_Shower> attach_performance_shower_impl(Plot_Core& plot, const Performance_Shower_Options* options) {
|
||||
auto ctx = plot.render_context();
|
||||
if (!ctx)
|
||||
return {};
|
||||
auto shower = performance_shower_owner(ctx);
|
||||
if (shower)
|
||||
if (shower) {
|
||||
if (options)
|
||||
shower->set_options(*options);
|
||||
return shower;
|
||||
}
|
||||
auto created_shower = renderive::make_shared<Performance_Shower>();
|
||||
if (options)
|
||||
created_shower->set_options(*options);
|
||||
created_shower->set_update_callback(performance_update_callback(ctx));
|
||||
std::atomic_store_explicit(&ctx->frame_lifecycle_observer, std::static_pointer_cast<Frame_Lifecycle_Observer>(created_shower), std::memory_order_release);
|
||||
return created_shower;
|
||||
}
|
||||
|
||||
std::shared_ptr<Performance_Shower> attach_performance_shower(Plot_Core& plot) {
|
||||
return attach_performance_shower_impl(plot, nullptr);
|
||||
}
|
||||
|
||||
std::shared_ptr<Performance_Shower> attach_performance_shower(Plot_Core& plot, const Performance_Shower_Options& options) {
|
||||
return attach_performance_shower_impl(plot, &options);
|
||||
}
|
||||
|
||||
std::shared_ptr<Performance_Shower> performance_shower(Plot_Core& plot) {
|
||||
return performance_shower_owner(plot.render_context());
|
||||
}
|
||||
|
||||
void detach_performance_shower(Plot_Core& plot) {
|
||||
auto ctx = plot.render_context();
|
||||
if (!ctx)
|
||||
@@ -284,7 +314,9 @@ bool performance_shower_enabled(const Plot_Core& plot) {
|
||||
}
|
||||
void set_performance_shower_enabled(Plot_Core& plot, bool enabled) {
|
||||
if (!enabled) {
|
||||
detach_performance_shower(plot);
|
||||
auto shower = performance_shower_owner(plot.render_context());
|
||||
if (shower)
|
||||
shower->setEnabled(false);
|
||||
return;
|
||||
}
|
||||
auto shower = attach_performance_shower(plot);
|
||||
@@ -335,12 +367,17 @@ bool performance_shower_handle_pointer_release(Plot_Core& plot, PointF position)
|
||||
return shower && shower->enabled() && shower->handle_pointer_release(position);
|
||||
}
|
||||
void Performance_Shower::setEnabled(bool enabled) {
|
||||
auto worker = d()->metrics_worker;
|
||||
d()->enabled_value.store(enabled, std::memory_order_release);
|
||||
if (enabled) {
|
||||
d()->metrics_worker->reset_requested.store(true, std::memory_order_release);
|
||||
d()->metrics_worker->snapshot_rebuild_requested.store(true, std::memory_order_release);
|
||||
schedule_performance_metrics_worker(d()->metrics_worker);
|
||||
worker->enabled.store(enabled, std::memory_order_release);
|
||||
if (!enabled) {
|
||||
worker->display_snapshot_slot.store({}, std::memory_order_release);
|
||||
request_performance_update(worker);
|
||||
return;
|
||||
}
|
||||
worker->reset_requested.store(true, std::memory_order_release);
|
||||
worker->snapshot_rebuild_requested.store(true, std::memory_order_release);
|
||||
schedule_performance_metrics_worker(worker);
|
||||
}
|
||||
bool Performance_Shower::enabled() const {
|
||||
return const_cast<Performance_Shower*>(this)->d()->enabled_value.load(std::memory_order_acquire);
|
||||
@@ -348,6 +385,36 @@ bool Performance_Shower::enabled() const {
|
||||
std::shared_ptr<const Performance_Display_Snapshot> Performance_Shower::display_snapshot() const {
|
||||
return const_cast<Performance_Shower*>(this)->d()->metrics_worker->display_snapshot_slot.load(std::memory_order_acquire);
|
||||
}
|
||||
void Performance_Shower::set_options(Performance_Shower_Options options) {
|
||||
auto worker = d()->metrics_worker;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(worker->options_mutex);
|
||||
worker->options = std::move(options);
|
||||
}
|
||||
worker->snapshot_rebuild_requested.store(true, std::memory_order_release);
|
||||
if (enabled())
|
||||
schedule_performance_metrics_worker(worker);
|
||||
}
|
||||
Performance_Shower_Options Performance_Shower::options() const {
|
||||
auto worker = const_cast<Performance_Shower*>(this)->d()->metrics_worker;
|
||||
std::lock_guard<std::mutex> lock(worker->options_mutex);
|
||||
return worker->options;
|
||||
}
|
||||
void Performance_Shower::set_font(Font font) {
|
||||
Performance_Shower_Options value = options();
|
||||
value.font = std::move(font);
|
||||
set_options(std::move(value));
|
||||
}
|
||||
void Performance_Shower::set_foreground(Color color) {
|
||||
Performance_Shower_Options value = options();
|
||||
value.foreground = color;
|
||||
set_options(std::move(value));
|
||||
}
|
||||
void Performance_Shower::set_background(Color color) {
|
||||
Performance_Shower_Options value = options();
|
||||
value.background = color;
|
||||
set_options(std::move(value));
|
||||
}
|
||||
void Performance_Shower::collect_frame(std::shared_ptr<const Frame_Lifecycle_Record> frame) {
|
||||
if (!enabled())
|
||||
return;
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include "../architecture/Frame_Scheduler.h"
|
||||
#include "../base/Color.h"
|
||||
#include "../base/Geometry.h"
|
||||
#include "../base/Text.h"
|
||||
#include "global.h"
|
||||
#include "Performance_Snapshot.h"
|
||||
|
||||
namespace renderive {
|
||||
|
||||
struct Performance_Shower_Private;
|
||||
|
||||
struct Performance_Shower_Options {
|
||||
Font font;
|
||||
int top_margin = 4;
|
||||
int left_margin = 6;
|
||||
int right_margin = 12;
|
||||
int bottom_margin = 6;
|
||||
int scroll_bar_width = 8;
|
||||
int scroll_bar_margin = 2;
|
||||
Color background = Color::white();
|
||||
Color foreground = Color::black();
|
||||
Color scroll_track = Color{220, 220, 220};
|
||||
Color scroll_thumb = Color{80, 80, 80};
|
||||
};
|
||||
|
||||
class LIB_DECL Performance_Shower : public Frame_Lifecycle_Observer {
|
||||
public:
|
||||
Performance_Shower();
|
||||
~Performance_Shower();
|
||||
|
||||
void setEnabled(bool enabled);
|
||||
bool enabled() const override;
|
||||
void collect_frame(std::shared_ptr<const Frame_Lifecycle_Record> frame) override;
|
||||
[[nodiscard]] std::shared_ptr<const Performance_Display_Snapshot> display_snapshot() const;
|
||||
|
||||
void set_options(Performance_Shower_Options options);
|
||||
[[nodiscard]] Performance_Shower_Options options() const;
|
||||
void set_font(Font font);
|
||||
void set_foreground(Color color);
|
||||
void set_background(Color color);
|
||||
|
||||
void set_viewport(Size viewport, std::uint64_t version);
|
||||
bool handle_wheel(PointF position, double angle_delta_y, double pixel_delta_y);
|
||||
bool handle_pointer_press(PointF position);
|
||||
bool handle_pointer_move(PointF position);
|
||||
bool handle_pointer_release(PointF position);
|
||||
void set_update_callback(std::function<void()> callback);
|
||||
|
||||
private:
|
||||
Performance_Shower_Private* d();
|
||||
std::unique_ptr<Performance_Shower_Private> private_data;
|
||||
};
|
||||
|
||||
} // namespace renderive
|
||||
@@ -24,23 +24,11 @@
|
||||
#include "../base/String_Format.h"
|
||||
#include "../base/Text.h"
|
||||
#include "../render/Canvas.h"
|
||||
#include "Performance_Snapshot.h"
|
||||
#include "Performance_Shower.h"
|
||||
#include "Psc_Cpp_Core/Statistics/Statistics.h"
|
||||
namespace renderive {
|
||||
void write_frame_performance_log(std::shared_ptr<const Frame_Lifecycle_Record> frame);
|
||||
struct Performance_Shower_Render_State : Render_State {
|
||||
Font font;
|
||||
int top_margin = 4;
|
||||
int left_margin = 6;
|
||||
int right_margin = 12;
|
||||
int bottom_margin = 6;
|
||||
int scroll_bar_width = 8;
|
||||
int scroll_bar_margin = 2;
|
||||
Color background = Color::white();
|
||||
Color foreground = Color::black();
|
||||
Color scroll_track = Color{220, 220, 220};
|
||||
Color scroll_thumb = Color{80, 80, 80};
|
||||
};
|
||||
struct Performance_Shower_Render_State : Render_State, Performance_Shower_Options {};
|
||||
struct Performance_Shower_Input_Data : Input_Data {};
|
||||
struct Renderable_Cache_Aggregate_Stat {
|
||||
std::string object_name;
|
||||
@@ -267,6 +255,7 @@ enum class Performance_Field_Id : std::uint16_t {
|
||||
Frame_Peak_Parallelism,
|
||||
Frame_Wait_Max,
|
||||
Frame_Run_Total,
|
||||
Outcome,
|
||||
Cache_Hit,
|
||||
Cache_Miss,
|
||||
Cache_Ratio,
|
||||
@@ -316,26 +305,6 @@ struct Performance_Render_Line {
|
||||
double width{};
|
||||
};
|
||||
|
||||
struct Performance_Shower_Private;
|
||||
class Performance_Shower : public Frame_Lifecycle_Observer {
|
||||
public:
|
||||
Performance_Shower();
|
||||
~Performance_Shower();
|
||||
void setEnabled(bool enabled);
|
||||
bool enabled() const override;
|
||||
void collect_frame(std::shared_ptr<const Frame_Lifecycle_Record> frame) override;
|
||||
[[nodiscard]] std::shared_ptr<const Performance_Display_Snapshot> display_snapshot() const;
|
||||
void set_viewport(Size viewport, std::uint64_t version);
|
||||
bool handle_wheel(PointF position, double angle_delta_y, double pixel_delta_y);
|
||||
bool handle_pointer_press(PointF position);
|
||||
bool handle_pointer_move(PointF position);
|
||||
bool handle_pointer_release(PointF position);
|
||||
void set_update_callback(std::function<void()> callback);
|
||||
private:
|
||||
Performance_Shower_Private* d();
|
||||
std::unique_ptr<Performance_Shower_Private> private_data;
|
||||
};
|
||||
|
||||
using Performance_Frame_Record = std::shared_ptr<const Frame_Lifecycle_Record>;
|
||||
|
||||
struct Performance_Metrics_Worker_State {
|
||||
@@ -344,6 +313,7 @@ struct Performance_Metrics_Worker_State {
|
||||
: metric_queue(Capacity) {}
|
||||
rigtorp::MPMCQueue<Performance_Frame_Record> metric_queue;
|
||||
std::atomic<std::uint64_t> metric_capacity_dropped{0};
|
||||
std::atomic_bool enabled{false};
|
||||
std::atomic_bool worker_active{false};
|
||||
std::atomic_bool work_requested{false};
|
||||
std::atomic_bool cancelled{false};
|
||||
@@ -368,6 +338,8 @@ struct Performance_Metrics_Worker_State {
|
||||
double last_line_height{1.0};
|
||||
double last_max_scroll_offset{};
|
||||
double held_content_width{};
|
||||
mutable std::mutex options_mutex;
|
||||
Performance_Shower_Options options;
|
||||
std::mutex update_callback_mutex;
|
||||
std::function<void()> update_callback;
|
||||
std::atomic<std::shared_ptr<const Performance_Display_Snapshot>> display_snapshot_slot;
|
||||
@@ -445,7 +417,7 @@ struct Performance_Shower_Private {
|
||||
state->aggregate.update(*frame);
|
||||
changed = true;
|
||||
}
|
||||
if (changed) {
|
||||
if (changed && state->enabled.load(std::memory_order_acquire)) {
|
||||
state->display_snapshot_slot.store(build_display_snapshot(*state), std::memory_order_release);
|
||||
invoke_update_callback(*state);
|
||||
}
|
||||
@@ -476,6 +448,10 @@ struct Performance_Shower_Private {
|
||||
}
|
||||
|
||||
Performance_Shower_Render_State state;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(worker_state.options_mutex);
|
||||
static_cast<Performance_Shower_Options&>(state) = worker_state.options;
|
||||
}
|
||||
Image measure_image(1, 1);
|
||||
measure_image.fill(Color::transparent());
|
||||
Text_Metrics metrics;
|
||||
@@ -485,6 +461,7 @@ struct Performance_Shower_Private {
|
||||
metrics = measure_canvas.measure_text("0123456789 ABC \xE4\xB8\xAD\xE6\x96\x87");
|
||||
if (metrics.line_height() <= 0.0)
|
||||
metrics = measure_canvas.measure_text("M");
|
||||
builder.seed_static_field_widths(measure_canvas);
|
||||
int available_text_width = viewport.width - state.left_margin - state.right_margin - state.scroll_bar_width - state.scroll_bar_margin * 2;
|
||||
builder.build_render_lines(measure_canvas, static_cast<double>(std::max(1, available_text_width)));
|
||||
}
|
||||
@@ -698,6 +675,8 @@ private:
|
||||
return Performance_Field_Id::Frame_Wait_Max;
|
||||
if (key == "frame_worker_run_total")
|
||||
return Performance_Field_Id::Frame_Run_Total;
|
||||
if (key == "frame_outcome")
|
||||
return Performance_Field_Id::Outcome;
|
||||
if (key == "cache_hit_count")
|
||||
return Performance_Field_Id::Cache_Hit;
|
||||
if (key == "cache_miss_count")
|
||||
@@ -763,6 +742,26 @@ private:
|
||||
return Performance_Field_Id::Generic_Count;
|
||||
return Performance_Field_Id::Generic_Number;
|
||||
}
|
||||
static constexpr std::array<Frame_Outcome, 7> outcome_values() {
|
||||
return {
|
||||
Frame_Outcome::Presented,
|
||||
Frame_Outcome::Superseded,
|
||||
Frame_Outcome::Render_Acquire_Dropped,
|
||||
Frame_Outcome::Publish_Dropped,
|
||||
Frame_Outcome::Paint_Acquire_Dropped,
|
||||
Frame_Outcome::Worker_Budget_Dropped,
|
||||
Frame_Outcome::Cancelled
|
||||
};
|
||||
}
|
||||
void seed_static_field_widths(Canvas& canvas) {
|
||||
for (Frame_Outcome outcome : outcome_values()) {
|
||||
Performance_Text_Run run;
|
||||
run.value = true;
|
||||
run.field_id = Performance_Field_Id::Outcome;
|
||||
run.text = outcome_text(outcome);
|
||||
measure_run(canvas, run);
|
||||
}
|
||||
}
|
||||
static std::string marked_value(Performance_Field_Id field_id, std::string text) {
|
||||
std::string result;
|
||||
result.reserve(text.size() + 12);
|
||||
@@ -959,7 +958,7 @@ private:
|
||||
std::uint64_t latest_render_time = frame_render_time_ns(frame);
|
||||
double cache_hit_ratio = aggregate_cache_total ? static_cast<double>(aggregate.cache_hit_count) * 100.0 / static_cast<double>(aggregate_cache_total) : 0.0;
|
||||
lines.clear();
|
||||
lines.push_back("frame:" + count_text("frame_id", frame.frame_id) + " input_ver:" + count_text("input_version", frame.input_version) + " outcome:" + outcome_text(frame.outcome) + " limit:" + limit_source_text(refresh.source));
|
||||
lines.push_back("frame:" + count_text("frame_id", frame.frame_id) + " input_ver:" + count_text("input_version", frame.input_version) + " outcome:" + marked_value(Performance_Field_Id::Outcome, outcome_text(frame.outcome)) + " limit:" + limit_source_text(refresh.source));
|
||||
lines.push_back("period render:" + period_text("render_period", refresh.render_period_ns) + " paint:" + period_text("paint_period", refresh.paint_period_ns) + " user:" + period_text("user_period", refresh.user_period_ns) + " target:" + period_text("target_period", refresh.target_period_ns));
|
||||
lines.push_back("wait 21:" + ns_text("wait_21", frame.wait_21_ns) + "ms 12:" + ns_text("wait_12", frame.wait_12_ns) + "ms 23:" + ns_text("wait_23", frame.wait_23_ns) + "ms 32:" + ns_text("wait_32", frame.wait_32_ns) + "ms");
|
||||
lines.push_back("taskflow workers:" + count_text("taskflow_workers", static_cast<std::uint64_t>(executor.worker_count)) + " active:" + count_text("taskflow_active", static_cast<std::uint64_t>(executor.active_workers)) + " queued_frames:" + count_text("taskflow_queued_frames", static_cast<std::uint64_t>(executor.queued_frame_jobs)) + " active_frames:" + count_text("taskflow_active_frames", static_cast<std::uint64_t>(executor.active_frame_jobs)));
|
||||
|
||||
@@ -7,15 +7,16 @@
|
||||
#include "Interpolation.h"
|
||||
#include "Multi_Select_Rect.h"
|
||||
#include "Planisphere.h"
|
||||
#include "Performance_Snapshot.h"
|
||||
#include "Performance_Shower.h"
|
||||
#include "Spectrum.h"
|
||||
#include "Sweep_Frequency.h"
|
||||
#include "Waterfall.h"
|
||||
|
||||
namespace renderive {
|
||||
class Plot_Core;
|
||||
class Performance_Shower;
|
||||
LIB_DECL std::shared_ptr<Performance_Shower> attach_performance_shower(Plot_Core& plot);
|
||||
LIB_DECL std::shared_ptr<Performance_Shower> attach_performance_shower(Plot_Core& plot, const Performance_Shower_Options& options);
|
||||
LIB_DECL std::shared_ptr<Performance_Shower> performance_shower(Plot_Core& plot);
|
||||
LIB_DECL void detach_performance_shower(Plot_Core& plot);
|
||||
LIB_DECL bool performance_shower_enabled(const Plot_Core& plot);
|
||||
LIB_DECL void set_performance_shower_enabled(Plot_Core& plot, bool enabled);
|
||||
|
||||
@@ -465,8 +465,38 @@ TEST(Renderive_Performance_Shower, ToggleDoesNotReenterRenderableTreeUnsafely) {
|
||||
EXPECT_TRUE(root->children_snapshot().empty());
|
||||
}
|
||||
|
||||
TEST(Renderive_Performance_Shower, TogglePreservesAttachedOptions) {
|
||||
Plot_Core plot(std::make_unique<Latency_Eager_Refresh_Strategy>());
|
||||
plot.init();
|
||||
Performance_Shower_Options options;
|
||||
options.font.size = 17.0;
|
||||
options.background = Color{10, 20, 30, 255};
|
||||
options.foreground = Color{240, 240, 240, 255};
|
||||
|
||||
auto original = attach_performance_shower(plot, options);
|
||||
ASSERT_TRUE(original);
|
||||
set_performance_shower_enabled(plot, true);
|
||||
EXPECT_TRUE(performance_shower_enabled(plot));
|
||||
set_performance_shower_enabled(plot, false);
|
||||
EXPECT_FALSE(performance_shower_enabled(plot));
|
||||
set_performance_shower_enabled(plot, true);
|
||||
|
||||
auto toggled = performance_shower(plot);
|
||||
ASSERT_EQ(toggled, original);
|
||||
EXPECT_EQ(toggled->options().font.size, options.font.size);
|
||||
EXPECT_EQ(toggled->options().background, options.background);
|
||||
EXPECT_EQ(toggled->options().foreground, options.foreground);
|
||||
}
|
||||
|
||||
TEST(Renderive_Hover_Info, DefaultTextPenContrastsWithDefaultBackground) {
|
||||
Hover_Info_Render_State state;
|
||||
EXPECT_EQ(state.hover_info_brush.color, Color::white());
|
||||
EXPECT_EQ(state.hover_info_pen.color, Color::black());
|
||||
}
|
||||
|
||||
TEST(Renderive_Performance_Shower, WorkerConsumesSharedFrameRecord) {
|
||||
auto state = std::make_shared<Performance_Metrics_Worker_State>();
|
||||
state->enabled.store(true, std::memory_order_release);
|
||||
auto frame = std::make_shared<Frame_Lifecycle_Record>();
|
||||
frame->frame_id = 7;
|
||||
frame->input_version = 3;
|
||||
@@ -499,8 +529,60 @@ TEST(Renderive_Performance_Shower, WorkerConsumesSharedFrameRecord) {
|
||||
EXPECT_EQ(state->aggregate.latest.frame_id, 7);
|
||||
}
|
||||
|
||||
TEST(Renderive_Performance_Shower, OptionsAffectSnapshotRendering) {
|
||||
Performance_Shower shower;
|
||||
Performance_Shower_Options options;
|
||||
options.font.size = 18.0;
|
||||
options.background = Color{10, 20, 30, 255};
|
||||
options.foreground = Color{240, 240, 240, 255};
|
||||
shower.set_options(options);
|
||||
shower.setEnabled(true);
|
||||
shower.set_viewport(Size{260, 120}, 1);
|
||||
shower.collect_frame(performance_frame(1, 260, 120));
|
||||
|
||||
ASSERT_TRUE(wait_until([&]() {
|
||||
auto snapshot = shower.display_snapshot();
|
||||
return snapshot && !snapshot->image.empty();
|
||||
}));
|
||||
auto snapshot = shower.display_snapshot();
|
||||
ASSERT_TRUE(snapshot);
|
||||
ASSERT_FALSE(snapshot->image.empty());
|
||||
EXPECT_EQ(shower.options().font.size, 18.0);
|
||||
EXPECT_GT(snapshot->line_height, 12.0);
|
||||
EXPECT_EQ(premultiplied_to_color(snapshot->image.row(1)[1]), options.background);
|
||||
}
|
||||
|
||||
TEST(Renderive_Performance_Shower, OutcomeWidthIsSeededWithLongestEnumText) {
|
||||
auto state = std::make_shared<Performance_Metrics_Worker_State>();
|
||||
state->enabled.store(true, std::memory_order_release);
|
||||
auto outcome_width = [&]() {
|
||||
return state->field_layout_states[static_cast<std::size_t>(Performance_Field_Id::Outcome)].max_value_width;
|
||||
};
|
||||
|
||||
auto presented = performance_frame(1, 260, 120);
|
||||
presented->outcome = Frame_Outcome::Presented;
|
||||
ASSERT_TRUE(state->metric_queue.try_push(Performance_Frame_Record{presented}));
|
||||
schedule_performance_metrics_worker(state);
|
||||
ASSERT_TRUE(wait_until([&]() {
|
||||
return state->aggregate.latest.frame_id == 1 && !state->worker_active.load(std::memory_order_acquire);
|
||||
}));
|
||||
double seeded_width = outcome_width();
|
||||
EXPECT_GT(seeded_width, 0.0);
|
||||
|
||||
auto dropped = performance_frame(2, 260, 120);
|
||||
dropped->outcome = Frame_Outcome::Worker_Budget_Dropped;
|
||||
ASSERT_TRUE(state->metric_queue.try_push(Performance_Frame_Record{dropped}));
|
||||
schedule_performance_metrics_worker(state);
|
||||
ASSERT_TRUE(wait_until([&]() {
|
||||
return state->aggregate.latest.frame_id == 2 && !state->worker_active.load(std::memory_order_acquire);
|
||||
}));
|
||||
EXPECT_EQ(outcome_width(), seeded_width);
|
||||
state->cancelled.store(true, std::memory_order_release);
|
||||
}
|
||||
|
||||
TEST(Renderive_Performance_Shower, NumericFieldWidthIsMonotonicAcrossResetAndResize) {
|
||||
auto state = std::make_shared<Performance_Metrics_Worker_State>();
|
||||
state->enabled.store(true, std::memory_order_release);
|
||||
auto frame_width = [&]() {
|
||||
return state->field_layout_states[static_cast<std::size_t>(Performance_Field_Id::Frame_Id)].max_value_width;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user