补充测试
This commit is contained in:
@@ -1,114 +1,34 @@
|
||||
#include "render_3D/Point_Visual.h"
|
||||
#include "render_3D/detail/Point_Core.h"
|
||||
#include <renderive/frame_control/Frame_Control.hpp>
|
||||
#include "render_3D/Scene_Context.hpp"
|
||||
#include <renderive/scene/Scene.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
namespace renderive::render_3d {
|
||||
namespace {
|
||||
using Test_Frame_Control = Low_Latency_Strategy<Scene3D_Frame_Data>;
|
||||
struct Test_Scene final
|
||||
: Scene3D_Context<Test_Frame_Control, detail::Scene_State>,
|
||||
Scene_Renderer {
|
||||
explicit Test_Scene(const std::shared_ptr<Point_Visual>& visual) {
|
||||
Scene_State_Strategy::set<&detail::Scene_State::viewport>(
|
||||
Extent{320, 180});
|
||||
point_id = visual->renderable_id();
|
||||
auto builder = attach_builder();
|
||||
if (builder.attach(renderive_Owner<Point_Visual>(visual)) !=
|
||||
Scene_Edit_Error::none)
|
||||
throw std::logic_error("test visual attachment failed");
|
||||
}
|
||||
~Test_Scene() override {
|
||||
shutdown();
|
||||
}
|
||||
void render_frame() {
|
||||
{
|
||||
auto painter = frame_control.acquire_painter();
|
||||
ASSERT_TRUE(painter);
|
||||
publish_frame_state();
|
||||
}
|
||||
auto renderer = frame_control.acquire_renderer();
|
||||
ASSERT_TRUE(renderer);
|
||||
ASSERT_EQ(Scene_Base::render(*renderer), Scene_Render_Result::none);
|
||||
ASSERT_EQ(wait_for_render(), Scene_Render_Result::none);
|
||||
}
|
||||
Node_Execution_Result render_scene(
|
||||
const Scene_Render_Context& context) override {
|
||||
prepared = context.prepared<detail::Prepared_Point>(point_id);
|
||||
if (!prepared) throw std::logic_error("Point_Visual did not publish prepared data");
|
||||
EXPECT_EQ(context.frame.scene_state<detail::Scene_State>().viewport,
|
||||
(Extent{320, 180}));
|
||||
return Node_Execution_Result::completed();
|
||||
}
|
||||
Renderable_Id point_id{};
|
||||
std::shared_ptr<const detail::Prepared_Point> prepared;
|
||||
};
|
||||
static_assert(std::derived_from<Point_Visual, Renderable>);
|
||||
static_assert(std::derived_from<Point_Visual, ::Renderable_Base>);
|
||||
TEST(PointState, PublishesStateAndBulkDataIntoFrameLocalPreparedOutput) {
|
||||
auto visual = Point_Visual::Builder{}.build(
|
||||
|
||||
TEST(PointState, BuilderAndStateMutationShareOneAuthoritativeState) {
|
||||
Point_State initial;
|
||||
initial.style.stroke_width_px = 2.0F;
|
||||
auto visual = Point_Visual::Builder{initial}.build(
|
||||
std::vector<Point>{{{1.0F, 2.0F, 3.0F}, {1, 2, 3, 255}, 7.0F}});
|
||||
ASSERT_TRUE(visual);
|
||||
Point_State configured;
|
||||
configured.visible = false;
|
||||
configured.style.stroke_width_px = 3.0F;
|
||||
visual->set<&Point_State::visible>(configured.visible);
|
||||
visual->set<&Point_State::style>(configured.style);
|
||||
Test_Scene scene(visual);
|
||||
scene.render_frame();
|
||||
ASSERT_TRUE(scene.prepared);
|
||||
EXPECT_EQ(scene.prepared->state, configured);
|
||||
ASSERT_EQ(scene.prepared->positions.size(), 1U);
|
||||
EXPECT_EQ(scene.prepared->positions.front(),
|
||||
(std::array<float, 3>{1.0F, 2.0F, 3.0F}));
|
||||
EXPECT_EQ(scene.prepared->data_revision, 1U);
|
||||
EXPECT_EQ(visual->get<&Point_State::style>(), initial.style);
|
||||
auto changed = initial.style;
|
||||
changed.stroke_width_px = 3.0F;
|
||||
visual->set<&Point_State::style>(changed);
|
||||
EXPECT_EQ(visual->get<&Point_State::style>(), changed);
|
||||
}
|
||||
TEST(PointState, PublishesImmutableBulkPayloadsAcrossConcurrentUpdates) {
|
||||
|
||||
TEST(PointState, BulkUpdatesUseOwnedStorage) {
|
||||
auto visual = Point_Visual::Builder{}.build();
|
||||
ASSERT_TRUE(visual);
|
||||
Test_Scene scene(visual);
|
||||
constexpr int update_count = 200;
|
||||
std::atomic<bool> done{};
|
||||
std::thread writer([&] {
|
||||
for (int value = 1; value <= update_count; ++value) {
|
||||
std::vector<Point> points(static_cast<std::size_t>(value % 31 + 1));
|
||||
for (auto& point : points) {
|
||||
point.position.x = static_cast<float>(value);
|
||||
point.diameter_px = static_cast<float>(value % 12 + 1);
|
||||
}
|
||||
visual->update_points(std::move(points));
|
||||
}
|
||||
done.store(true, std::memory_order_release);
|
||||
});
|
||||
do {
|
||||
scene.render_frame();
|
||||
const auto prepared = scene.prepared;
|
||||
ASSERT_TRUE(prepared);
|
||||
if (!prepared->positions.empty()) {
|
||||
const float expected = prepared->positions.front()[0];
|
||||
for (const auto& point : prepared->positions)
|
||||
EXPECT_EQ(point[0], expected);
|
||||
}
|
||||
}
|
||||
while (!done.load(std::memory_order_acquire));
|
||||
writer.join();
|
||||
scene.render_frame();
|
||||
ASSERT_TRUE(scene.prepared);
|
||||
ASSERT_FALSE(scene.prepared->positions.empty());
|
||||
EXPECT_EQ(scene.prepared->positions.front()[0],
|
||||
static_cast<float>(update_count));
|
||||
EXPECT_EQ(visual->update_points(std::vector<Point>(4)),
|
||||
Visual_Data_Error::none);
|
||||
EXPECT_EQ(visual->point_count(), 4U);
|
||||
}
|
||||
TEST(PointState, RejectsInvalidStateAndPayloadAtTheOwningBoundary) {
|
||||
|
||||
TEST(PointState, RejectsInvalidStateAndPayloadAtOwningBoundary) {
|
||||
auto visual = Point_Visual::Builder{}.build();
|
||||
ASSERT_TRUE(visual);
|
||||
Point_State invalid;
|
||||
invalid.style.stroke_width_px = -1.0F;
|
||||
EXPECT_THROW(visual->set<&Point_State::style>(invalid.style),
|
||||
@@ -116,29 +36,6 @@ TEST(PointState, RejectsInvalidStateAndPayloadAtTheOwningBoundary) {
|
||||
EXPECT_EQ(visual->update_points(std::vector<Point>{{{}, {}, 0.0F}}),
|
||||
Visual_Data_Error::invalid_data);
|
||||
}
|
||||
TEST(PointRenderPlan, OrdersParallelPreparationBeforeSingleSceneRenderNode) {
|
||||
auto visual = Point_Visual::Builder{}.build(
|
||||
std::vector<Point>{{{}, {}, 8.0F}});
|
||||
Test_Scene scene(visual);
|
||||
scene.render_frame();
|
||||
const auto plan = scene.render_plan_snapshot();
|
||||
ASSERT_TRUE(plan);
|
||||
const auto prepare = std::find_if(
|
||||
plan->graph.nodes.begin(), plan->graph.nodes.end(),
|
||||
[&](const Render_Node& node) {
|
||||
return node.owner_id == visual->renderable_id() &&
|
||||
node.kind == Render_Node_Kind::prepare;
|
||||
});
|
||||
const auto render = std::find_if(
|
||||
plan->graph.nodes.begin(), plan->graph.nodes.end(),
|
||||
[](const Render_Node& node) {
|
||||
return node.kind == Render_Node_Kind::render;
|
||||
});
|
||||
ASSERT_NE(prepare, plan->graph.nodes.end());
|
||||
ASSERT_NE(render, plan->graph.nodes.end());
|
||||
EXPECT_NE(std::find(plan->graph.edges.begin(), plan->graph.edges.end(),
|
||||
Render_Edge{prepare->node_id, render->node_id}),
|
||||
plan->graph.edges.end());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace renderive::render_3d
|
||||
|
||||
Reference in New Issue
Block a user