内核优化
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "renderive/renderable/Renderable.hpp"
|
||||
@@ -25,14 +26,83 @@ TEST(renderable_task_graph_test, combines_internal_and_external_dependencies) {
|
||||
auto dependent = std::make_shared<Renderable_Task_Graph_Test_Renderable>(scene, order, 10);
|
||||
scene.attach_renderable(dependency);
|
||||
scene.attach_renderable(dependent);
|
||||
dependency->dependency_node.append_child(dependent->dependency_node);
|
||||
scene.set_dependency_parent(*dependent, dependency.get());
|
||||
scene.render();
|
||||
scene.wait_for_render();
|
||||
EXPECT_EQ(order, (std::vector<int>{1, 2, 11, 12}));
|
||||
}
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
struct Renderable_Task_Graph_Branch_Test_Renderable : Renderable_Base {
|
||||
Renderable_Task_Graph_Branch_Test_Renderable(Scene_Base& scene, std::atomic<unsigned>& state, std::atomic<bool>& invalid)
|
||||
: Renderable_Base(scene, {.cache_enabled = false}), state(&state), invalid(&invalid) {}
|
||||
void build_task_graph(Renderable_Task_Graph& graph) override {
|
||||
auto first = graph.emplace([this](const Scene_Render_Context&) {
|
||||
state->fetch_or(1u, std::memory_order_release);
|
||||
}, "first");
|
||||
auto second = graph.emplace([this](const Scene_Render_Context&) {
|
||||
state->fetch_or(2u, std::memory_order_release);
|
||||
}, "second");
|
||||
auto join = graph.emplace([this](const Scene_Render_Context&) {
|
||||
if ((state->load(std::memory_order_acquire) & 3u) != 3u) {
|
||||
invalid->store(true, std::memory_order_release);
|
||||
}
|
||||
state->fetch_or(4u, std::memory_order_release);
|
||||
}, "join");
|
||||
graph.precede(first, join);
|
||||
graph.precede(second, join);
|
||||
}
|
||||
std::atomic<unsigned>* state;
|
||||
std::atomic<bool>* invalid;
|
||||
};
|
||||
TEST(renderable_task_graph_test, preserves_internal_fan_in_dependencies) {
|
||||
Scene2D_Context<> scene;
|
||||
std::atomic<unsigned> state{};
|
||||
std::atomic<bool> invalid{};
|
||||
auto renderable = std::make_shared<Renderable_Task_Graph_Branch_Test_Renderable>(scene, state, invalid);
|
||||
scene.attach_renderable(renderable);
|
||||
scene.render();
|
||||
scene.wait_for_render();
|
||||
EXPECT_FALSE(invalid.load(std::memory_order_acquire));
|
||||
EXPECT_EQ(state.load(std::memory_order_acquire), 7u);
|
||||
}
|
||||
struct Renderable_Task_Graph_Parent_Test_Renderable : Renderable_Base {
|
||||
Renderable_Task_Graph_Parent_Test_Renderable(Scene_Base& scene, std::atomic<unsigned>& state)
|
||||
: Renderable_Base(scene, {.cache_enabled = false}), state(&state) {}
|
||||
void build_task_graph(Renderable_Task_Graph& graph) override {
|
||||
graph.emplace([this](const Scene_Render_Context&) {
|
||||
state->fetch_or(1u, std::memory_order_release);
|
||||
}, "parent_a");
|
||||
graph.emplace([this](const Scene_Render_Context&) {
|
||||
state->fetch_or(2u, std::memory_order_release);
|
||||
}, "parent_b");
|
||||
}
|
||||
std::atomic<unsigned>* state;
|
||||
};
|
||||
struct Renderable_Task_Graph_Child_Test_Renderable : Renderable_Base {
|
||||
Renderable_Task_Graph_Child_Test_Renderable(Scene_Base& scene, std::atomic<unsigned>& state, std::atomic<bool>& invalid)
|
||||
: Renderable_Base(scene, {.cache_enabled = false}), state(&state), invalid(&invalid) {}
|
||||
void render(const Scene_Render_Context&) override {
|
||||
if ((state->load(std::memory_order_acquire) & 3u) != 3u) {
|
||||
invalid->store(true, std::memory_order_release);
|
||||
}
|
||||
}
|
||||
std::atomic<unsigned>* state;
|
||||
std::atomic<bool>* invalid;
|
||||
};
|
||||
TEST(renderable_task_graph_test, waits_for_all_parent_terminal_tasks_before_dependent_module) {
|
||||
Scene2D_Context<> scene;
|
||||
std::atomic<unsigned> state{};
|
||||
std::atomic<bool> invalid{};
|
||||
auto parent = std::make_shared<Renderable_Task_Graph_Parent_Test_Renderable>(scene, state);
|
||||
auto child = std::make_shared<Renderable_Task_Graph_Child_Test_Renderable>(scene, state, invalid);
|
||||
scene.attach_renderable(parent);
|
||||
scene.attach_renderable(child);
|
||||
scene.set_dependency_parent(*child, parent.get());
|
||||
scene.render();
|
||||
scene.wait_for_render();
|
||||
EXPECT_FALSE(invalid.load(std::memory_order_acquire));
|
||||
EXPECT_EQ(state.load(std::memory_order_acquire), 3u);
|
||||
}
|
||||
#ifndef RENDERIVE_TASKFLOW_MOCK
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
struct Renderable_Task_Graph_Concurrency_Test_Renderable : Renderable_Base {
|
||||
@@ -52,7 +122,7 @@ struct Renderable_Task_Graph_Concurrency_Test_Renderable : Renderable_Base {
|
||||
std::atomic<int>* active;
|
||||
std::atomic<int>* maximum;
|
||||
};
|
||||
TEST(renderable_task_graph_concurrency_test, DISABLED_runs_independent_internal_tasks_concurrently) {
|
||||
TEST(renderable_task_graph_concurrency_test, runs_independent_internal_tasks_concurrently) {
|
||||
Scene2D_Context<> scene;
|
||||
std::atomic<int> active{};
|
||||
std::atomic<int> maximum{};
|
||||
@@ -62,3 +132,27 @@ TEST(renderable_task_graph_concurrency_test, DISABLED_runs_independent_internal_
|
||||
scene.wait_for_render();
|
||||
EXPECT_GE(maximum.load(std::memory_order_acquire), 2);
|
||||
}
|
||||
#endif
|
||||
TEST(renderable_task_graph_test, rejects_tasks_from_different_graphs) {
|
||||
Renderable_Task_Graph first;
|
||||
Renderable_Task_Graph second;
|
||||
auto first_task = first.emplace([](const Scene_Render_Context&) {});
|
||||
auto second_task = second.emplace([](const Scene_Render_Context&) {});
|
||||
EXPECT_THROW(first.precede(first_task, second_task), std::invalid_argument);
|
||||
}
|
||||
TEST(renderable_task_graph_test, rejects_stale_task_handles_after_clear) {
|
||||
Renderable_Task_Graph graph;
|
||||
auto stale = graph.emplace([](const Scene_Render_Context&) {});
|
||||
graph.clear();
|
||||
auto current = graph.emplace([](const Scene_Render_Context&) {});
|
||||
EXPECT_THROW(graph.precede(stale, current), std::invalid_argument);
|
||||
}
|
||||
TEST(renderable_task_graph_test, rejects_cycles_when_dependency_is_added) {
|
||||
Renderable_Task_Graph graph;
|
||||
auto first = graph.emplace([](const Scene_Render_Context&) {});
|
||||
auto second = graph.emplace([](const Scene_Render_Context&) {});
|
||||
auto third = graph.emplace([](const Scene_Render_Context&) {});
|
||||
graph.precede(first, second);
|
||||
graph.precede(second, third);
|
||||
EXPECT_THROW(graph.precede(third, first), std::invalid_argument);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user