内核优化

This commit is contained in:
2026-08-10 13:50:17 +08:00
parent 2abdba699d
commit 302b1dcdfd
46 changed files with 1955 additions and 515 deletions
@@ -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());
}