#include #include #include #include #include #include #include "renderive/base/property/Property.hpp" #include "renderive/real_time_data/Real_Time_Data.hpp" #include "renderive/renderable/Renderable.hpp" #include "renderive/renderable/Renderable_Test_Harness.hpp" #include "renderive/scene/Scene.hpp" #include "Scene_Test_Helpers.hpp" class Scene_Memory_Resource_Test_Resource : public std::pmr::memory_resource { public: std::size_t allocation_count() const noexcept { return allocation_count_.load(std::memory_order_acquire); } std::size_t deallocation_count() const noexcept { return deallocation_count_.load(std::memory_order_acquire); } private: void* do_allocate(std::size_t bytes, std::size_t alignment) override { allocation_count_.fetch_add(1, std::memory_order_release); return std::pmr::new_delete_resource()->allocate(bytes, alignment); } void do_deallocate(void* pointer, std::size_t bytes, std::size_t alignment) override { deallocation_count_.fetch_add(1, std::memory_order_release); std::pmr::new_delete_resource()->deallocate(pointer, bytes, alignment); } bool do_is_equal(const std::pmr::memory_resource& other) const noexcept override { return this == &other; } std::atomic allocation_count_{}; std::atomic deallocation_count_{}; }; struct Scene_Memory_Resource_Test_Renderable : Renderable_Test_Harness { explicit Scene_Memory_Resource_Test_Renderable(std::pmr::memory_resource& memory_resource = *std::pmr::get_default_resource()) : Renderable_Test_Harness({.cache_enabled = false}, memory_resource) {} void build_prepare_graph_for_test(Renderable_Graph_Builder& graph) override { auto first = graph.emplace("first", "prepare_memory_resource_test", [](const Prepare_Render_Context&) {}); auto second = graph.emplace("second", "render_memory_resource_test", [](const Prepare_Render_Context&) {}); graph.precede(first, second); } void build_graph_for_test() { static_cast(render_graph_for_test()); } }; struct Scene_Memory_Resource_Test_Product { explicit Scene_Memory_Resource_Test_Product(int value) : value(value) {} int value; }; struct Scene_Memory_Resource_Test_Properties { int value{}; }; struct Scene_Memory_Resource_Test_Property_Product { Scene_Memory_Resource_Test_Property_Product(const Scene_Memory_Resource_Test_Properties& properties, int offset) : value(properties.value + offset) {} int value; }; TEST(scene_memory_resource_test, renderable_builder_can_use_scene_memory_domain_explicitly) { Scene_Memory_Resource_Test_Resource upstream; Scene2D_Context<> scene(upstream); EXPECT_EQ(&scene.upstream_memory_resource(), &upstream); EXPECT_NE(&scene.memory_resource(), &upstream); auto renderable = renderive_Owner::make(scene.memory_resource()); EXPECT_EQ(&renderable->memory_resource_for_test(), &scene.memory_resource()); attach_initial(scene, renderable); scene.render(); scene.wait_for_render(); EXPECT_GT(upstream.allocation_count(), 0); } TEST(scene_memory_resource_test, explicit_scene_memory_domain_remains_valid_while_scene_is_alive) { Scene_Memory_Resource_Test_Resource upstream; Scene2D_Context<> scene(upstream); auto renderable = renderive_Owner::make(scene.memory_resource()); renderable->build_graph_for_test(); EXPECT_EQ(&renderable->memory_resource_for_test(), &scene.memory_resource()); } TEST(scene_memory_resource_test, supports_independent_resource_aware_components) { Scene_Memory_Resource_Test_Resource memory_resource; Flow_Refresh_Strategy flow(memory_resource); { auto painter = flow.acquire_painter(); EXPECT_TRUE(painter); } auto renderer = flow.acquire_renderer(); EXPECT_TRUE(renderer); History_Real_Time_Data> history(memory_resource); history.update(1); history.update(2); EXPECT_EQ(history.size(), 2); Property_Builder builder({3}); auto product = builder.build_with_resource(memory_resource, 4); auto unique_product = builder.build_unique_with_resource(memory_resource, 5); EXPECT_EQ(product->value, 7); EXPECT_EQ(unique_product->value, 8); EXPECT_GT(memory_resource.allocation_count(), 0); } TEST(scene_memory_resource_test, supports_explicit_independent_renderable_memory_resource) { Scene_Memory_Resource_Test_Resource memory_resource; auto renderable = renderive_Owner::make(memory_resource); renderable->build_graph_for_test(); EXPECT_EQ(&renderable->memory_resource_for_test(), &memory_resource); EXPECT_GT(memory_resource.allocation_count(), 0); }