secene 接入 多继承链
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <memory_resource>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "renderive/scene/dependency/Dependency_Resolver.hpp"
|
||||
|
||||
namespace {
|
||||
|
||||
enum class Preparation {
|
||||
acquire_source,
|
||||
transform_vertices,
|
||||
upload_visual
|
||||
};
|
||||
|
||||
using Resolver =
|
||||
renderive::scene::dependency::Dependency_Resolver<Preparation>;
|
||||
|
||||
TEST(dependency_resolver_test,
|
||||
resolves_declared_dependencies_in_deterministic_order) {
|
||||
std::pmr::unsynchronized_pool_resource memory;
|
||||
Resolver resolver(memory);
|
||||
resolver.attach(Preparation::upload_visual);
|
||||
resolver.attach(Preparation::acquire_source);
|
||||
resolver.attach(Preparation::transform_vertices);
|
||||
resolver.add_parent(Preparation::transform_vertices,
|
||||
Preparation::acquire_source);
|
||||
resolver.add_parent(Preparation::upload_visual,
|
||||
Preparation::transform_vertices);
|
||||
|
||||
const auto resolution = resolver.resolve();
|
||||
EXPECT_EQ(resolution.order,
|
||||
(std::vector{Preparation::acquire_source,
|
||||
Preparation::transform_vertices,
|
||||
Preparation::upload_visual}));
|
||||
}
|
||||
|
||||
TEST(dependency_resolver_test,
|
||||
rejected_cycle_preserves_the_previous_authoritative_relationships) {
|
||||
std::pmr::unsynchronized_pool_resource memory;
|
||||
Resolver resolver(memory);
|
||||
resolver.attach(Preparation::acquire_source);
|
||||
resolver.attach(Preparation::transform_vertices);
|
||||
resolver.attach(Preparation::upload_visual);
|
||||
resolver.add_parent(Preparation::transform_vertices,
|
||||
Preparation::acquire_source);
|
||||
resolver.add_parent(Preparation::upload_visual,
|
||||
Preparation::transform_vertices);
|
||||
|
||||
EXPECT_THROW(
|
||||
resolver.add_parent(Preparation::acquire_source,
|
||||
Preparation::upload_visual),
|
||||
std::logic_error);
|
||||
|
||||
EXPECT_TRUE(resolver.parents(Preparation::acquire_source).empty());
|
||||
EXPECT_EQ(resolver.resolve().order,
|
||||
(std::vector{Preparation::acquire_source,
|
||||
Preparation::transform_vertices,
|
||||
Preparation::upload_visual}));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -155,8 +155,6 @@ TEST(scene3d_context_test, runtime_edit_explicitly_reparents_children_before_det
|
||||
attach.attach(grandparent);
|
||||
attach.attach(parent);
|
||||
attach.attach(child);
|
||||
attach.set_display_parent(parent, grandparent);
|
||||
attach.set_display_parent(child, parent);
|
||||
attach.set_dependency_parent(parent, grandparent);
|
||||
attach.set_dependency_parent(child, parent);
|
||||
});
|
||||
@@ -164,28 +162,19 @@ TEST(scene3d_context_test, runtime_edit_explicitly_reparents_children_before_det
|
||||
scene.wait_for_render();
|
||||
EXPECT_EQ(child->render_count, 1);
|
||||
wait_renderable_edit(scene, [grandparent, parent, child](auto& editor) {
|
||||
editor.set_display_parent(child, grandparent);
|
||||
editor.set_dependency_parent(child, grandparent);
|
||||
editor.clear_display_parent(parent);
|
||||
editor.clear_dependency_parent(parent);
|
||||
editor.detach(parent);
|
||||
});
|
||||
const auto topology = scene.topology_snapshot();
|
||||
bool display_checked{};
|
||||
bool dependency_checked{};
|
||||
for (const auto& relation : topology.display) {
|
||||
if (relation.child.get() == child.get()) {
|
||||
EXPECT_EQ(relation.parent.get(), grandparent.get());
|
||||
display_checked = true;
|
||||
}
|
||||
}
|
||||
for (const auto& relation : topology.dependency) {
|
||||
if (relation.child.get() == child.get()) {
|
||||
EXPECT_EQ(relation.parent.get(), grandparent.get());
|
||||
dependency_checked = true;
|
||||
}
|
||||
}
|
||||
EXPECT_TRUE(display_checked);
|
||||
EXPECT_TRUE(topology.display.empty());
|
||||
EXPECT_TRUE(dependency_checked);
|
||||
scene.render();
|
||||
scene.wait_for_render();
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "renderive/inheritance/Registry.hpp"
|
||||
#include "renderive/scene/Inheritance.hpp"
|
||||
|
||||
namespace {
|
||||
|
||||
struct Lifecycle_Event {
|
||||
std::vector<std::string>& handled_by;
|
||||
};
|
||||
|
||||
struct Scene_Impl
|
||||
: renderive::scene_inheritance::Impl_Root<Scene_Impl,
|
||||
Lifecycle_Event> {
|
||||
struct Observer :
|
||||
renderive::scene_inheritance::Observer_Root<Scene_Impl> {
|
||||
static void handle(Scene_Impl&, const Lifecycle_Event& event) {
|
||||
event.handled_by.emplace_back("scene");
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
struct Scene2D_Impl
|
||||
: renderive::scene_inheritance::Impl_Node<Scene2D_Impl, Scene_Impl> {
|
||||
struct Observer
|
||||
: renderive::scene_inheritance::Observer_Node<
|
||||
Scene2D_Impl, Scene_Impl::Observer> {
|
||||
static void handle(Scene2D_Impl&, const Lifecycle_Event& event) {
|
||||
event.handled_by.emplace_back("scene_2d");
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
struct Plot_Scene_Impl
|
||||
: renderive::scene_inheritance::Impl_Node<Plot_Scene_Impl,
|
||||
Scene2D_Impl> {
|
||||
struct Observer
|
||||
: renderive::scene_inheritance::Observer_Node<
|
||||
Plot_Scene_Impl, Scene2D_Impl::Observer> {
|
||||
static void handle(Plot_Scene_Impl&, const Lifecycle_Event& event) {
|
||||
event.handled_by.emplace_back("plot_scene");
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
struct Scene_Editor
|
||||
: renderive::scene_inheritance::Editor_Root<Scene_Editor> {};
|
||||
struct Scene2D_Editor
|
||||
: renderive::scene_inheritance::Editor_Node<Scene2D_Editor,
|
||||
Scene_Editor> {};
|
||||
struct Plot_Scene_Editor
|
||||
: renderive::scene_inheritance::Editor_Node<Plot_Scene_Editor,
|
||||
Scene2D_Editor> {};
|
||||
|
||||
struct Scene_Builder
|
||||
: renderive::scene_inheritance::Builder_Root<Scene_Builder> {};
|
||||
struct Scene2D_Builder
|
||||
: renderive::scene_inheritance::Builder_Node<Scene2D_Builder,
|
||||
Scene_Builder> {};
|
||||
struct Plot_Scene_Builder
|
||||
: renderive::scene_inheritance::Builder_Node<Plot_Scene_Builder,
|
||||
Scene2D_Builder> {};
|
||||
|
||||
struct Scene_State
|
||||
: renderive::scene_inheritance::State_Root<Scene_State> {};
|
||||
struct Scene2D_State
|
||||
: renderive::scene_inheritance::State_Node<Scene2D_State,
|
||||
Scene_State> {};
|
||||
struct Plot_Scene_State
|
||||
: renderive::scene_inheritance::State_Node<Plot_Scene_State,
|
||||
Scene2D_State> {};
|
||||
|
||||
TEST(scene_inheritance_test,
|
||||
observer_dispatch_follows_the_scene_chain_parent_before_child) {
|
||||
Plot_Scene_Impl impl;
|
||||
std::vector<std::string> handled_by;
|
||||
impl.dispatch({handled_by});
|
||||
EXPECT_EQ(handled_by,
|
||||
(std::vector<std::string>{"scene", "scene_2d", "plot_scene"}));
|
||||
}
|
||||
|
||||
TEST(scene_inheritance_test,
|
||||
editor_chain_registers_each_semantic_layer_at_its_own_position) {
|
||||
using Registry = Plot_Scene_Editor::Inheritance_Registry;
|
||||
using Chain = renderive::scene_inheritance::Editor_Chain;
|
||||
static_assert(renderive::inheritance::Chain_Registration_Count_V<
|
||||
Registry, Chain> == 3);
|
||||
static_assert(std::same_as<
|
||||
renderive::inheritance::Type_At_Position_T<Registry, Chain,
|
||||
0>,
|
||||
Scene_Editor>);
|
||||
static_assert(std::same_as<
|
||||
renderive::inheritance::Type_At_Position_T<Registry, Chain,
|
||||
2>,
|
||||
Plot_Scene_Editor>);
|
||||
SUCCEED();
|
||||
}
|
||||
|
||||
TEST(scene_inheritance_test,
|
||||
builder_and_state_chains_extend_without_sharing_registrations) {
|
||||
using Builder_Registry = Plot_Scene_Builder::Inheritance_Registry;
|
||||
using State_Registry = Plot_Scene_State::Inheritance_Registry;
|
||||
using Builder_Chain = renderive::scene_inheritance::Builder_Chain;
|
||||
using State_Chain = renderive::scene_inheritance::State_Chain;
|
||||
static_assert(renderive::inheritance::Chain_Registration_Count_V<
|
||||
Builder_Registry, Builder_Chain> == 3);
|
||||
static_assert(renderive::inheritance::Chain_Registration_Count_V<
|
||||
Builder_Registry, State_Chain> == 0);
|
||||
static_assert(renderive::inheritance::Chain_Registration_Count_V<
|
||||
State_Registry, State_Chain> == 3);
|
||||
static_assert(renderive::inheritance::Chain_Registration_Count_V<
|
||||
State_Registry, Builder_Chain> == 0);
|
||||
static_assert(std::same_as<
|
||||
renderive::inheritance::Type_At_Position_T<
|
||||
Builder_Registry, Builder_Chain, 2>,
|
||||
Plot_Scene_Builder>);
|
||||
static_assert(std::same_as<
|
||||
renderive::inheritance::Type_At_Position_T<
|
||||
State_Registry, State_Chain, 2>,
|
||||
Plot_Scene_State>);
|
||||
SUCCEED();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -16,12 +16,17 @@ struct Scene_State_Observer_Test_Time_Source {
|
||||
};
|
||||
struct Scene_State_Observer_Test_Data {
|
||||
std::vector<Scene_Base::Observation_Event> events;
|
||||
std::atomic<int> complete_snapshot_count{};
|
||||
};
|
||||
struct Scene_State_Observer_Test_Recorder {
|
||||
static constexpr bool enabled = true;
|
||||
std::shared_ptr<Scene_State_Observer_Test_Data> data{std::make_shared<Scene_State_Observer_Test_Data>()};
|
||||
void observe(const Scene_Base::Observation& observation) noexcept {
|
||||
data->events.push_back(observation.event);
|
||||
if (observation.topology && observation.frame_snapshot &&
|
||||
observation.render_plan)
|
||||
data->complete_snapshot_count.fetch_add(1,
|
||||
std::memory_order_relaxed);
|
||||
}
|
||||
};
|
||||
using Scene_State_Observer_Test_Scene_Observer = Observer_State<Scene_State_Observer_Test_Recorder, Scene_State_Observer_Test_Time_Source>;
|
||||
@@ -37,6 +42,7 @@ TEST(scene_state_observer_test, scene_uses_double_state_and_observes_lifecycle)
|
||||
scene.wait_for_render();
|
||||
EXPECT_EQ(render.read(static_cast<const Scene::Scene_State_Strategy&>(scene)).value, 9);
|
||||
EXPECT_EQ(recorder.data->events, (std::vector<Scene_Base::Observation_Event>{Scene_Base::Observation_Event::render_submitted, Scene_Base::Observation_Event::render_started, Scene_Base::Observation_Event::render_completed}));
|
||||
EXPECT_EQ(recorder.data->complete_snapshot_count.load(), 3);
|
||||
}
|
||||
struct Scene_Reentrant_Observer_Data {
|
||||
std::function<void(Scene_Base::Observation_Event)> callback;
|
||||
|
||||
@@ -2,21 +2,21 @@
|
||||
#include <future>
|
||||
#include <utility>
|
||||
#include "renderive/scene/base/Scene_Base.hpp"
|
||||
template <class... Owners>
|
||||
void attach_initial(Scene_Base& scene, const Owners&... owners) {
|
||||
template <class Scene, class... Owners>
|
||||
void attach_initial(Scene& scene, const Owners&... owners) {
|
||||
auto builder = scene.attach_builder();
|
||||
(builder.attach(owners), ...);
|
||||
}
|
||||
template <class Edit>
|
||||
void with_attach_builder(Scene_Base& scene, Edit&& edit) {
|
||||
template <class Scene, class Edit>
|
||||
void with_attach_builder(Scene& scene, Edit&& edit) {
|
||||
auto builder = scene.attach_builder();
|
||||
edit(builder);
|
||||
}
|
||||
template <class Edit>
|
||||
void wait_renderable_edit(Scene_Base& scene, Edit&& edit) {
|
||||
template <class Scene, class Edit>
|
||||
void wait_renderable_edit(Scene& scene, Edit&& edit) {
|
||||
std::promise<void> completed;
|
||||
auto future = completed.get_future();
|
||||
scene.edit_renderables([edit = std::forward<Edit>(edit), &completed](Scene_Base::Renderable_Editor& editor) mutable {
|
||||
scene.edit_renderables([edit = std::forward<Edit>(edit), &completed](auto& editor) mutable {
|
||||
edit(editor);
|
||||
completed.set_value();
|
||||
});
|
||||
|
||||
@@ -473,7 +473,7 @@ TEST(scene_base_test, detached_topology_reference_fails_fast_after_callback) {
|
||||
});
|
||||
scene.render();
|
||||
},
|
||||
"dependency topology still references detached renderable");
|
||||
"dependency graph still references detached renderable");
|
||||
}
|
||||
TEST(scene_base_test, wait_for_render_propagates_background_render_failure) {
|
||||
Scene2D_Context<> scene;
|
||||
|
||||
Reference in New Issue
Block a user