补充测试
This commit is contained in:
@@ -1,195 +1,54 @@
|
||||
#include "render_3D/Render_Scene_3D.h"
|
||||
#include <renderive/scene/base/Scene_Base.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <exception>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace renderive::render_3d {
|
||||
namespace {
|
||||
struct Test_Point_Scene {
|
||||
std::shared_ptr<Point_Visual> visual;
|
||||
std::unique_ptr<Render_Scene_3D> scene;
|
||||
};
|
||||
Test_Point_Scene make_test_scene(Scene_Options options) {
|
||||
std::vector<Point> points{
|
||||
{{-0.72F, -0.38F, 0.15F}, {245, 70, 78, 255}, 42.0F},
|
||||
{{0.00F, 0.48F, -0.05F}, {65, 220, 132, 255}, 48.0F},
|
||||
{{0.72F, 0.0F, 0.30F}, {75, 135, 255, 255}, 54.0F},
|
||||
{{-0.35F, 0.10F, -0.45F}, {250, 205, 75, 255}, 30.0F},
|
||||
{{0.38F, -0.12F, -0.25F}, {205, 95, 245, 255}, 34.0F},
|
||||
};
|
||||
Point_State state;
|
||||
state.style = {{12, 16, 24, 255}, 2.0F, Point_Aspect::Outline};
|
||||
auto visual = Point_Visual::Builder{state}.build(std::move(points));
|
||||
auto scene = std::make_unique<Render_Scene_3D>(options, visual);
|
||||
return {std::move(visual), std::move(scene)};
|
||||
|
||||
std::unique_ptr<Render_Scene_3D> make_scene(
|
||||
Render_Scene_3D::State state,
|
||||
const std::shared_ptr<Point_Visual>& visual) {
|
||||
return Render_Scene_3D::Builder{state}.build(
|
||||
visual, std::make_shared<Low_Latency_Render_Scene_3D_Strategy>());
|
||||
}
|
||||
struct Event_Point {
|
||||
float x{};
|
||||
float y{};
|
||||
};
|
||||
std::size_t colored_pixel_count(const Pixel_Frame& frame) {
|
||||
if (frame.rgba8.size() < 4) return 0;
|
||||
const auto* bytes = reinterpret_cast<const std::uint8_t*>(frame.rgba8.data());
|
||||
const std::array<std::uint8_t, 4> background{
|
||||
bytes[0], bytes[1], bytes[2], bytes[3]
|
||||
};
|
||||
std::size_t result{};
|
||||
for (std::size_t offset = 0; offset + 3 < frame.rgba8.size(); offset += 4) {
|
||||
result += bytes[offset] != background[0] ||
|
||||
bytes[offset + 1] != background[1] ||
|
||||
bytes[offset + 2] != background[2] ||
|
||||
bytes[offset + 3] != background[3];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
TEST(PointRenderIntegration, RendersRealRgbaAndResizes) {
|
||||
|
||||
TEST(PointRenderIntegration, BuilderConstructsSceneFromStateAndStrategy) {
|
||||
auto visual = Point_Visual::Builder{}.build(std::vector<Point>{
|
||||
{{0.0F, 0.0F, 0.0F}, {255, 0, 0, 255}, 8.0F}});
|
||||
Render_Scene_3D::State state;
|
||||
state.viewport = {320, 200};
|
||||
try {
|
||||
auto demo = make_test_scene(Scene_Options{.viewport = {320, 200}});
|
||||
ASSERT_EQ(demo.scene->request_frame(), Frame_Request_Result::none);
|
||||
ASSERT_EQ(demo.scene->render_scene().wait_for_render(),
|
||||
Scene_Render_Result::none);
|
||||
auto first = demo.scene->latest_frame();
|
||||
ASSERT_NE(first, nullptr);
|
||||
EXPECT_EQ(first->extent, (Extent{320, 200}));
|
||||
EXPECT_EQ(first->rgba8.size(), 320U * 200U * 4U);
|
||||
EXPECT_GT(colored_pixel_count(*first), 100U);
|
||||
demo.scene->resize({480, 270});
|
||||
ASSERT_EQ(demo.scene->request_frame(), Frame_Request_Result::none);
|
||||
ASSERT_EQ(demo.scene->render_scene().wait_for_render(),
|
||||
Scene_Render_Result::none);
|
||||
auto resized = demo.scene->latest_frame();
|
||||
ASSERT_NE(resized, nullptr);
|
||||
EXPECT_EQ(resized->extent, (Extent{480, 270}));
|
||||
EXPECT_EQ(resized->rgba8.size(), 480U * 270U * 4U);
|
||||
EXPECT_GT(colored_pixel_count(*resized), 100U);
|
||||
auto scene = make_scene(state, visual);
|
||||
ASSERT_TRUE(scene);
|
||||
EXPECT_EQ(scene->renderable_count(), 1U);
|
||||
}
|
||||
catch (const std::exception& error) {
|
||||
GTEST_SKIP() << "Vulkan/Datoviz unavailable: " << error.what();
|
||||
}
|
||||
}
|
||||
TEST(PointRenderIntegration, KernelEventsReachDatovizArcballOnItsDomain) {
|
||||
|
||||
TEST(PointRenderIntegration, ObserverPublishesSceneAndVisualState) {
|
||||
std::vector<Point> points(3);
|
||||
for (auto& point : points) point.diameter_px = 1.0F;
|
||||
auto visual = Point_Visual::Builder{}.build(std::move(points));
|
||||
Render_Scene_3D::State state;
|
||||
state.viewport = {160, 90};
|
||||
try {
|
||||
auto demo = make_test_scene(Scene_Options{.viewport = {320, 200}});
|
||||
ASSERT_EQ(demo.scene->request_frame(), Frame_Request_Result::none);
|
||||
ASSERT_EQ(demo.scene->render_scene().wait_for_render(),
|
||||
Scene_Render_Result::none);
|
||||
const auto before = demo.scene->latest_frame()->rgba8;
|
||||
::renderive::Basic_Pointer_Event<Event_Point> press(
|
||||
::renderive::Event_Type::Pointer_Press);
|
||||
press.position = {120.0F, 90.0F};
|
||||
press.button = ::renderive::Mouse_Button::Left;
|
||||
demo.scene->dispatch(press);
|
||||
::renderive::Basic_Pointer_Event<Event_Point> move(
|
||||
::renderive::Event_Type::Pointer_Move);
|
||||
move.position = {210.0F, 125.0F};
|
||||
move.buttons = 1;
|
||||
demo.scene->dispatch(move);
|
||||
move.position = {245.0F, 145.0F};
|
||||
demo.scene->dispatch(move);
|
||||
::renderive::Basic_Pointer_Event<Event_Point> release(
|
||||
::renderive::Event_Type::Pointer_Release);
|
||||
release.position = move.position;
|
||||
release.button = ::renderive::Mouse_Button::Left;
|
||||
demo.scene->dispatch(release);
|
||||
ASSERT_EQ(demo.scene->request_frame(), Frame_Request_Result::none);
|
||||
ASSERT_EQ(demo.scene->render_scene().wait_for_render(),
|
||||
Scene_Render_Result::none);
|
||||
const auto after_drag = demo.scene->latest_frame();
|
||||
ASSERT_NE(after_drag, nullptr);
|
||||
EXPECT_NE(after_drag->rgba8, before);
|
||||
::renderive::Basic_Wheel_Event<Event_Point> wheel;
|
||||
wheel.position = {160.0F, 100.0F};
|
||||
wheel.pixel_delta_y = 180.0;
|
||||
wheel.angle_delta_y = -216.0;
|
||||
demo.scene->dispatch(wheel);
|
||||
ASSERT_EQ(demo.scene->request_frame(), Frame_Request_Result::none);
|
||||
ASSERT_EQ(demo.scene->render_scene().wait_for_render(),
|
||||
Scene_Render_Result::none);
|
||||
const auto after_wheel = demo.scene->latest_frame();
|
||||
ASSERT_NE(after_wheel, nullptr);
|
||||
EXPECT_GT(colored_pixel_count(*after_wheel), 100U);
|
||||
EXPECT_NE(after_wheel->rgba8, after_drag->rgba8);
|
||||
}
|
||||
catch (const std::exception& error) {
|
||||
GTEST_SKIP() << "Vulkan/Datoviz unavailable: " << error.what();
|
||||
}
|
||||
}
|
||||
TEST(PointRenderIntegration,
|
||||
CapturesExternalGpuLifetimeAndSeparatedBackendPhases) {
|
||||
try {
|
||||
auto demo = make_test_scene(Scene_Options{.viewport = {320, 200}});
|
||||
auto& kernel_scene = demo.scene->render_scene();
|
||||
const auto request = kernel_scene.capture_next_frame();
|
||||
ASSERT_TRUE(request);
|
||||
const Capture_Session_Id capture = request.session_id;
|
||||
ASSERT_EQ(demo.scene->request_frame(), Frame_Request_Result::none);
|
||||
ASSERT_EQ(kernel_scene.wait_for_render(), Scene_Render_Result::none);
|
||||
const auto session = kernel_scene.capture_session(capture);
|
||||
ASSERT_TRUE(session);
|
||||
ASSERT_EQ(session->captured_count(), 1U);
|
||||
const auto& snapshot = *session->frames.front().snapshot;
|
||||
const auto plan = kernel_scene.find_render_plan(
|
||||
snapshot.render_plan_version);
|
||||
ASSERT_TRUE(plan);
|
||||
const auto render_node = std::find_if(
|
||||
plan->graph.nodes.begin(), plan->graph.nodes.end(),
|
||||
[](const Render_Node& node) {
|
||||
return node.kind == Render_Node_Kind::render;
|
||||
});
|
||||
ASSERT_NE(render_node, plan->graph.nodes.end());
|
||||
const auto& execution = snapshot.node_executions.at(
|
||||
render_node->execution_index);
|
||||
EXPECT_EQ(execution.status, Node_Execution_Status::complete);
|
||||
EXPECT_GT(execution.external_start_time_ns, 0U);
|
||||
EXPECT_GE(execution.external_end_time_ns,
|
||||
execution.external_start_time_ns);
|
||||
EXPECT_GE(execution.duration_ns(), execution.cpu_duration_ns());
|
||||
EXPECT_TRUE(execution.metrics.contains(
|
||||
Node_Metric_Kind::queue_wait_ns));
|
||||
EXPECT_TRUE(execution.metrics.contains(
|
||||
Node_Metric_Kind::backend_execute_duration_ns));
|
||||
EXPECT_TRUE(execution.metrics.contains(
|
||||
Node_Metric_Kind::gpu_fence_wait_ns));
|
||||
EXPECT_TRUE(execution.metrics.contains(
|
||||
Node_Metric_Kind::readback_duration_ns));
|
||||
const auto artifact_bytes = execution.metrics.get(
|
||||
Node_Metric_Kind::backend_artifact_json_bytes);
|
||||
EXPECT_GT(artifact_bytes, 0U);
|
||||
const auto artifact = std::find_if(
|
||||
execution.attachments.begin(), execution.attachments.end(),
|
||||
[](const Node_Diagnostic_Attachment& attachment) {
|
||||
return attachment.type == "datoviz.drp2.artifact.json";
|
||||
});
|
||||
ASSERT_NE(artifact, execution.attachments.end());
|
||||
EXPECT_EQ(artifact->content.size(), artifact_bytes);
|
||||
EXPECT_FALSE(artifact->content.empty());
|
||||
const bool gpu_timing = execution.metrics.contains(
|
||||
Node_Metric_Kind::gpu_render_duration_ns);
|
||||
EXPECT_EQ(gpu_timing, execution.metrics.contains(
|
||||
Node_Metric_Kind::gpu_transition_duration_ns));
|
||||
EXPECT_EQ(gpu_timing, execution.metrics.contains(
|
||||
Node_Metric_Kind::gpu_copy_duration_ns));
|
||||
EXPECT_EQ(gpu_timing, execution.metrics.contains(
|
||||
Node_Metric_Kind::gpu_total_duration_ns));
|
||||
if (gpu_timing) {
|
||||
const auto total = execution.metrics.get(
|
||||
Node_Metric_Kind::gpu_total_duration_ns);
|
||||
EXPECT_GE(total, execution.metrics.get(
|
||||
Node_Metric_Kind::gpu_render_duration_ns));
|
||||
EXPECT_GE(total, execution.metrics.get(
|
||||
Node_Metric_Kind::gpu_transition_duration_ns));
|
||||
EXPECT_GE(total, execution.metrics.get(
|
||||
Node_Metric_Kind::gpu_copy_duration_ns));
|
||||
}
|
||||
auto scene = make_scene(state, visual);
|
||||
scene->publish_frame_state();
|
||||
ASSERT_EQ(scene->render(), Scene_Render_Result::none);
|
||||
ASSERT_EQ(scene->wait_for_render(), Scene_Render_Result::none);
|
||||
const auto observation = scene->observer();
|
||||
EXPECT_EQ(observation.state, state);
|
||||
EXPECT_EQ(observation.renderable_count, 1U);
|
||||
EXPECT_EQ(observation.point_count, visual->point_count());
|
||||
EXPECT_EQ(observation.point_count, 3U);
|
||||
}
|
||||
catch (const std::exception& error) {
|
||||
GTEST_SKIP() << "Vulkan/Datoviz unavailable: " << error.what();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace renderive::render_3d
|
||||
|
||||
Reference in New Issue
Block a user