内核优化
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include "renderive/real_time_data/Real_Time_Data.hpp"
|
||||
#include "renderive/renderable/Renderable.hpp"
|
||||
@@ -45,15 +46,15 @@ TEST(history_real_time_data_test, retains_all_values_until_explicit_discard) {
|
||||
}
|
||||
TEST(real_time_data_attachment_test, binds_updates_to_renderable_frame_strategy) {
|
||||
Scene2D_Context<> scene;
|
||||
Real_Time_Data_Test_Latest latest;
|
||||
Real_Time_Data_Test_History history;
|
||||
auto latest = std::make_shared<Real_Time_Data_Test_Latest>();
|
||||
auto history = std::make_shared<Real_Time_Data_Test_History>();
|
||||
auto renderable = std::make_shared<Real_Time_Data_Test_Attachment>(With_Real_Time_Data(latest, history), scene);
|
||||
renderable->discard_stale_frame_on_latest_data_update = true;
|
||||
{
|
||||
auto frame = scene.frame_control.acquire_painter();
|
||||
ASSERT_TRUE(frame);
|
||||
}
|
||||
latest.update(1);
|
||||
latest->update(1);
|
||||
EXPECT_EQ(scene.frame_control.counter_statistics().manually_discarded_frame_count, 1);
|
||||
auto frame = scene.frame_control.acquire_renderer();
|
||||
EXPECT_FALSE(frame);
|
||||
@@ -61,16 +62,130 @@ TEST(real_time_data_attachment_test, binds_updates_to_renderable_frame_strategy)
|
||||
TEST(real_time_data_attachment_test, discards_history_older_than_one_frame_interval) {
|
||||
using Strategy = Low_Latency_Strategy<Scene2D_Frame_Data>;
|
||||
Scene2D_Context<Strategy> scene(Observer_State<>{}, Strategy::Configuration{100'000'000.0});
|
||||
Real_Time_Data_Test_Latest latest;
|
||||
Real_Time_Data_Test_History history;
|
||||
auto latest = std::make_shared<Real_Time_Data_Test_Latest>();
|
||||
auto history = std::make_shared<Real_Time_Data_Test_History>();
|
||||
auto renderable = std::make_shared<Real_Time_Data_Test_Attachment>(With_Real_Time_Data(latest, history), scene);
|
||||
renderable->real_time_data_discard_mode = Real_Time_Data_Discard_Mode::retain_frame_interval;
|
||||
history.update(1);
|
||||
history.update(2);
|
||||
history.update(3);
|
||||
history->update(1);
|
||||
history->update(2);
|
||||
history->update(3);
|
||||
scene.attach_renderable(renderable);
|
||||
scene.render();
|
||||
scene.wait_for_render();
|
||||
EXPECT_EQ(history.snapshot(), (std::vector<int>{2, 3}));
|
||||
EXPECT_EQ(history->snapshot(), (std::vector<int>{2, 3}));
|
||||
EXPECT_EQ(renderable->render_count.load(), 1);
|
||||
}
|
||||
using Real_Time_Data_Test_Latest_Attachment = Attach_Real_Time_Data<Real_Time_Data_Test_Renderable, Real_Time_Data_Test_Latest>;
|
||||
TEST(real_time_data_attachment_test, supports_multiple_renderables_and_unbinds_destroyed_renderable) {
|
||||
Scene2D_Context<> first_scene;
|
||||
Scene2D_Context<> second_scene;
|
||||
auto latest = std::make_shared<Real_Time_Data_Test_Latest>();
|
||||
auto first = std::make_shared<Real_Time_Data_Test_Latest_Attachment>(With_Real_Time_Data(latest), first_scene);
|
||||
auto second = std::make_shared<Real_Time_Data_Test_Latest_Attachment>(With_Real_Time_Data(latest), second_scene);
|
||||
first->discard_stale_frame_on_latest_data_update = true;
|
||||
second->discard_stale_frame_on_latest_data_update = true;
|
||||
{
|
||||
auto frame = first_scene.frame_control.acquire_painter();
|
||||
ASSERT_TRUE(frame);
|
||||
}
|
||||
{
|
||||
auto frame = second_scene.frame_control.acquire_painter();
|
||||
ASSERT_TRUE(frame);
|
||||
}
|
||||
latest->update(1);
|
||||
EXPECT_EQ(first_scene.frame_control.counter_statistics().manually_discarded_frame_count, 1);
|
||||
EXPECT_EQ(second_scene.frame_control.counter_statistics().manually_discarded_frame_count, 1);
|
||||
first.reset();
|
||||
{
|
||||
auto frame = second_scene.frame_control.acquire_painter();
|
||||
ASSERT_TRUE(frame);
|
||||
}
|
||||
latest->update(2);
|
||||
EXPECT_EQ(first_scene.frame_control.counter_statistics().manually_discarded_frame_count, 1);
|
||||
EXPECT_EQ(second_scene.frame_control.counter_statistics().manually_discarded_frame_count, 2);
|
||||
}
|
||||
TEST(real_time_data_attachment_test, unbind_is_synchronized_with_concurrent_updates) {
|
||||
Scene2D_Context<> scene;
|
||||
auto latest = std::make_shared<Real_Time_Data_Test_Latest>();
|
||||
auto renderable = std::make_shared<Real_Time_Data_Test_Latest_Attachment>(With_Real_Time_Data(latest), scene);
|
||||
std::atomic<bool> running{true};
|
||||
std::atomic<bool> updated{};
|
||||
std::thread updater([&] {
|
||||
int value{};
|
||||
while (running.load(std::memory_order_acquire)) {
|
||||
latest->update(++value);
|
||||
updated.store(true, std::memory_order_release);
|
||||
}
|
||||
});
|
||||
while (!updated.load(std::memory_order_acquire)) {
|
||||
std::this_thread::yield();
|
||||
}
|
||||
renderable.reset();
|
||||
running.store(false, std::memory_order_release);
|
||||
updater.join();
|
||||
EXPECT_TRUE(latest->revision() > 0);
|
||||
}
|
||||
TEST(real_time_data_attachment_test, runtime_discard_configuration_is_safe_during_updates_and_rendering) {
|
||||
Scene2D_Context<> scene;
|
||||
auto latest = std::make_shared<Real_Time_Data_Test_Latest>();
|
||||
auto history = std::make_shared<Real_Time_Data_Test_History>();
|
||||
auto renderable = std::make_shared<Real_Time_Data_Test_Attachment>(With_Real_Time_Data(latest, history), scene);
|
||||
scene.attach_renderable(renderable);
|
||||
std::thread updater([&] {
|
||||
for (int value = 0; value < 1000; ++value) {
|
||||
latest->update(value);
|
||||
}
|
||||
});
|
||||
std::thread configurator([&] {
|
||||
for (int index = 0; index < 1000; ++index) {
|
||||
renderable->discard_stale_frame_on_latest_data_update = index % 2 != 0;
|
||||
renderable->real_time_data_discard_mode = index % 2 == 0 ? Real_Time_Data_Discard_Mode::retain_all : Real_Time_Data_Discard_Mode::retain_frame_interval;
|
||||
}
|
||||
});
|
||||
for (int index = 0; index < 20; ++index) {
|
||||
scene.render();
|
||||
scene.wait_for_render();
|
||||
}
|
||||
updater.join();
|
||||
configurator.join();
|
||||
EXPECT_EQ(latest->revision(), 1000);
|
||||
}
|
||||
TEST(real_time_data_attachment_test, ignores_updates_after_bound_scene_is_destroyed) {
|
||||
auto latest = std::make_shared<Real_Time_Data_Test_Latest>();
|
||||
std::shared_ptr<Real_Time_Data_Test_Latest_Attachment> renderable;
|
||||
{
|
||||
Scene2D_Context<> scene;
|
||||
renderable = std::make_shared<Real_Time_Data_Test_Latest_Attachment>(With_Real_Time_Data(latest), scene);
|
||||
latest->update(1);
|
||||
EXPECT_EQ(scene.frame_control.state().real_time_data_update_sequence, 1);
|
||||
}
|
||||
EXPECT_NO_THROW(latest->update(2));
|
||||
EXPECT_THROW(renderable->scene(), std::logic_error);
|
||||
renderable.reset();
|
||||
}
|
||||
TEST(real_time_data_attachment_test, notifies_each_scene_once_for_one_source_update) {
|
||||
Scene2D_Context<> scene;
|
||||
auto latest = std::make_shared<Real_Time_Data_Test_Latest>();
|
||||
auto first = std::make_shared<Real_Time_Data_Test_Latest_Attachment>(With_Real_Time_Data(latest), scene);
|
||||
auto second = std::make_shared<Real_Time_Data_Test_Latest_Attachment>(With_Real_Time_Data(latest), scene);
|
||||
first->discard_stale_frame_on_latest_data_update = true;
|
||||
second->discard_stale_frame_on_latest_data_update = true;
|
||||
{
|
||||
auto frame = scene.frame_control.acquire_painter();
|
||||
ASSERT_TRUE(frame);
|
||||
}
|
||||
latest->update(1);
|
||||
EXPECT_EQ(scene.frame_control.state().real_time_data_update_sequence, 1);
|
||||
EXPECT_EQ(scene.frame_control.counter_statistics().manually_discarded_frame_count, 1);
|
||||
}
|
||||
TEST(real_time_data_attachment_test, attachment_owns_real_time_data_sources) {
|
||||
Scene2D_Context<> scene;
|
||||
auto latest = std::make_shared<Real_Time_Data_Test_Latest>();
|
||||
std::weak_ptr<Real_Time_Data_Test_Latest> weak = latest;
|
||||
auto renderable = std::make_shared<Real_Time_Data_Test_Latest_Attachment>(With_Real_Time_Data(latest), scene);
|
||||
latest.reset();
|
||||
EXPECT_FALSE(weak.expired());
|
||||
renderable->real_time_data<Real_Time_Data_Test_Latest>().update(1);
|
||||
renderable.reset();
|
||||
EXPECT_TRUE(weak.expired());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user