2D移植完成
This commit is contained in:
@@ -1,213 +1,56 @@
|
||||
#include <render_2D/axis/Axis.hpp>
|
||||
#include <render_2D/base/Frame_2D.hpp>
|
||||
#include <render_2D/plottable/Constellation_Diagram.hpp>
|
||||
#include <render_2D/plottable/Afterglow.hpp>
|
||||
#include <render_2D/plottable/Spectrum.hpp>
|
||||
#include <render_2D/plottable/Waterfall.hpp>
|
||||
#include <render_2D/scene/Render_Scene_2D.hpp>
|
||||
#include <render_2D/module/plottable/Spectrum.hpp>
|
||||
#include <render_2D/module/scene/Render_Scene_2D.hpp>
|
||||
#include "task_flow/src/Task_Runtime.hpp"
|
||||
#include <process.h>
|
||||
#include <atomic>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
using namespace aethera;
|
||||
using namespace aethera::render_2d;
|
||||
|
||||
template <typename Object, typename... Arguments>
|
||||
owner<Object*> build_object(Arguments&&... arguments) {
|
||||
typename Object::template Builder<Object> builder(std::forward<Arguments>(arguments)...);
|
||||
auto result = builder.build();
|
||||
if (!result) std::_Exit(2);
|
||||
return std::move(result).value().release();
|
||||
}
|
||||
|
||||
bool contains_color(Image_View view) {
|
||||
for (int y = 0; y < view.height; ++y) {
|
||||
const auto* row = reinterpret_cast<const Pixel*>(
|
||||
view.data.data() + static_cast<std::ptrdiff_t>(y) * view.stride);
|
||||
for (int x = 0; x < view.width; ++x)
|
||||
if (row[x] != 0) return true;
|
||||
}
|
||||
bool contains_color(Image_View image) {
|
||||
for (const auto value : image.data)
|
||||
if (value != std::byte{}) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int main() {
|
||||
using Frequency = Frequency_Axis;
|
||||
using Power = Numeric_Axis;
|
||||
using Time = Time_Axis;
|
||||
using Spectrum_Object = Spectrum;
|
||||
using Constellation_Object = Constellation_Diagram;
|
||||
using Waterfall_Object = Waterfall;
|
||||
using Afterglow_Object = Afterglow;
|
||||
using Scene_Object = Render_Scene_2D;
|
||||
|
||||
initialize_runtime({.workers = 4});
|
||||
auto* frequency = build_object<Frequency>();
|
||||
auto* power = build_object<Power>();
|
||||
auto* spectrum = build_object<Spectrum_Object>(
|
||||
not_null{frequency}, not_null{power}, 4u);
|
||||
auto* time = build_object<Time>();
|
||||
auto* waterfall = build_object<Waterfall_Object>(
|
||||
not_null{frequency}, not_null{time}, Plot_Partition_Grid{2, 2});
|
||||
auto* afterglow = build_object<Afterglow_Object>(
|
||||
not_null{frequency}, not_null{power}, Plot_Partition_Grid{2, 2});
|
||||
auto* q_axis = build_object<Power>();
|
||||
auto* constellation = build_object<Constellation_Object>(
|
||||
not_null{power}, not_null{q_axis}, 3u);
|
||||
auto* spectrum_painted = new std::atomic_bool{};
|
||||
auto* topology_valid = new std::atomic_bool{true};
|
||||
auto* second_frame_valid = new std::atomic_bool{};
|
||||
auto* trace_valid = new std::atomic_bool{true};
|
||||
spectrum->taskflow().add("test.spectrum.render.complete", [spectrum_painted] {
|
||||
spectrum_painted->store(true, std::memory_order_release);
|
||||
if (initialize_task_runtime(2) != Initialize_Task_Runtime_Result::initialized) return 2;
|
||||
Frequency_Axis::Builder frequency_builder;
|
||||
frequency_builder
|
||||
.set<Prop_Tag>(&Abs_Axis::Prop::position, Point_F{10.0, 90.0})
|
||||
.set<Prop_Tag>(&Abs_Axis::Prop::pixel_length, 100.0)
|
||||
.set<Prop_Tag>(&Numeric_Axis::Prop::coordinate_range, Axis_Range{0.0, 100.0});
|
||||
Numeric_Axis::Builder power_builder;
|
||||
power_builder
|
||||
.set<Prop_Tag>(&Abs_Axis::Prop::position, Point_F{10.0, 90.0})
|
||||
.set<Prop_Tag>(&Abs_Axis::Prop::pixel_length, -80.0)
|
||||
.set<Prop_Tag>(&Abs_Axis::Prop::orientation, Axis_Orientation::vertical)
|
||||
.set<Prop_Tag>(&Numeric_Axis::Prop::coordinate_range, Axis_Range{-100.0, 0.0});
|
||||
auto* frequency = frequency_builder.build().release(); /* 进程测试独占拥有;completion 退出进程后由 OS 回收。 */
|
||||
auto* power = power_builder.build().release(); /* 进程测试独占拥有;completion 退出进程后由 OS 回收。 */
|
||||
Spectrum::Builder spectrum_builder(*frequency, *power);
|
||||
spectrum_builder
|
||||
.set<Prop_Tag>(&Spectrum::Prop::frequency_range, Axis_Range{0.0, 100.0})
|
||||
.set<Spectrum_Frame_Tag>([](Spectrum::Frame& frame) { frame.samples = {-100.0, -50.0, -10.0}; });
|
||||
auto spectrum = spectrum_builder.build();
|
||||
Dag_Relation<aethera::render_2d::scene::Renderable>::Builder dag_builder;
|
||||
dag_builder.add({1}, model_proxy<aethera::render_2d::scene::Renderable>(std::move(spectrum)));
|
||||
auto dag = dag_builder.build();
|
||||
if (!dag) return 2;
|
||||
Render_Scene_2D::Builder scene_builder;
|
||||
scene_builder
|
||||
.set<Prop_Tag>(&Render_Scene_2D::Prop::viewport, Size{120, 100})
|
||||
.set<Prop_Tag>(&Render_Scene_2D::Prop::background, Color::transparent())
|
||||
.set<Prop_Tag>(&Render_Scene_2D::Prop::view_active, true)
|
||||
.relation<aethera::render_2d::scene::Renderable>([graph = std::move(*dag)](auto& relation) mutable { relation = std::move(graph); });
|
||||
auto* scene = scene_builder.build().release(); /* completion 前保持存活;随后随进程退出回收。 */
|
||||
auto* frame = new Frame_2D{{1, 0}}; /* completion 前保持存活;随后随进程退出回收。 */
|
||||
const auto submitted = scene->render(frame, [frame](Frame_2D* completed, std::exception_ptr failure) {
|
||||
std::_Exit(!failure && completed == frame && contains_color(completed->image()) ? 0 : 1);
|
||||
});
|
||||
const auto verify_spectrum_precedes_axis =
|
||||
[spectrum_painted, topology_valid] {
|
||||
if (!spectrum_painted->load(std::memory_order_acquire))
|
||||
topology_valid->store(false, std::memory_order_relaxed);
|
||||
};
|
||||
frequency->taskflow().add("test.frequency.render.order",
|
||||
verify_spectrum_precedes_axis);
|
||||
power->taskflow().add("test.power.render.order",
|
||||
verify_spectrum_precedes_axis);
|
||||
|
||||
typename Scene_Object::template Builder<Scene_Object> scene_builder;
|
||||
scene_builder.add_renderable(not_null{spectrum});
|
||||
scene_builder.add_renderable(not_null{waterfall});
|
||||
scene_builder.add_renderable(not_null{afterglow});
|
||||
scene_builder.add_renderable(not_null{constellation});
|
||||
auto scene_result = scene_builder.build();
|
||||
if (!scene_result) return 2;
|
||||
auto* scene = std::move(scene_result).value().release();
|
||||
|
||||
frequency->set<&Abs_Axis::Prop::position>(Point_F{20.0, 100.0});
|
||||
frequency->set<&Abs_Axis::Prop::pixel_length>(120.0);
|
||||
frequency->set<&Numeric_Axis::Prop::coordinate_range>(
|
||||
Axis_Range{0.0, 100.0});
|
||||
power->set<&Abs_Axis::Prop::position>(Point_F{20.0, 100.0});
|
||||
power->set<&Abs_Axis::Prop::pixel_length>(-80.0);
|
||||
power->set<&Abs_Axis::Prop::orientation>(Axis_Orientation::vertical);
|
||||
power->set<&Numeric_Axis::Prop::coordinate_range>(
|
||||
Axis_Range{-100.0, 0.0});
|
||||
time->set<&Abs_Axis::Prop::position>(Point_F{20.0, 100.0});
|
||||
time->set<&Abs_Axis::Prop::pixel_length>(-80.0);
|
||||
time->set<&Abs_Axis::Prop::orientation>(Axis_Orientation::vertical);
|
||||
time->set<&Time_Axis::Prop::visible_count>(4);
|
||||
q_axis->set<&Abs_Axis::Prop::position>(Point_F{20.0, 100.0});
|
||||
q_axis->set<&Abs_Axis::Prop::pixel_length>(120.0);
|
||||
q_axis->set<&Numeric_Axis::Prop::coordinate_range>(
|
||||
Axis_Range{-1.0, 1.0});
|
||||
spectrum->set<&Spectrum::Prop::frequency_range>(
|
||||
Axis_Range{0.0, 100.0});
|
||||
spectrum->pending_buffer<Spectrum_Frame_Tag>() =
|
||||
Spectrum_Frame{std::vector<Spectrum_Power>(512, -50.0)};
|
||||
spectrum->mark_dirty<Render_Graph_Tag>();
|
||||
waterfall->set<&Waterfall::Prop::frequency_range>(
|
||||
Axis_Range{0.0, 100.0});
|
||||
waterfall->set<&Waterfall::Prop::power_range>(
|
||||
Axis_Range{-100.0, 0.0});
|
||||
const Plot_Time_Tick first_tick = time->append_time({1'000});
|
||||
const Plot_Time_Tick second_tick = time->append_time({2'000});
|
||||
waterfall->submit_stream<Waterfall_Stream_Tag>(
|
||||
std::make_shared<const Waterfall_Row>(Waterfall_Row{
|
||||
first_tick, std::vector<Plot_Value>(64, -70.0)}));
|
||||
waterfall->submit_stream<Waterfall_Stream_Tag>(
|
||||
std::make_shared<const Waterfall_Row>(Waterfall_Row{
|
||||
second_tick, std::vector<Plot_Value>(64, -30.0)}));
|
||||
waterfall->mark_dirty<Render_Graph_Tag>();
|
||||
afterglow->set<&Afterglow::Prop::frequency_range>(
|
||||
Axis_Range{0.0, 100.0});
|
||||
afterglow->set<&Afterglow::Prop::power_range>(Axis_Range{-100.0, 0.0});
|
||||
afterglow->set<&Afterglow::Prop::power_point_size>(32u);
|
||||
afterglow->submit_stream<Afterglow_Stream_Tag>(
|
||||
std::make_shared<const std::vector<Plot_Value>>(64, -40.0));
|
||||
afterglow->mark_dirty<Render_Graph_Tag>();
|
||||
constellation->set<&Constellation_Diagram::Prop::i_range>(
|
||||
Axis_Range{-1.0, 1.0});
|
||||
constellation->set<&Constellation_Diagram::Prop::q_range>(
|
||||
Axis_Range{-1.0, 1.0});
|
||||
constellation->submit_stream<Constellation_Stream_Tag>(
|
||||
Constellation_Point{{-50.0, 0.25}, monotonic_milliseconds()});
|
||||
constellation->mark_dirty<Render_Graph_Tag>();
|
||||
|
||||
scene->set<&Render_Scene_2D::Prop::viewport>(Size{160, 120});
|
||||
scene->activate_view();
|
||||
auto* frame = new Frame_2D(Frame_Identity{1, 0});
|
||||
auto* resized_partition_frame = new Frame_2D(Frame_Identity{2, 0});
|
||||
frame->request_taskflow_trace();
|
||||
resized_partition_frame->request_taskflow_trace();
|
||||
const auto validate_trace = [trace_valid](Frame_2D* completed) {
|
||||
const auto trace = completed->take_taskflow_trace();
|
||||
bool spectrum_hold{};
|
||||
bool afterglow_reduce{};
|
||||
bool afterglow_color_barrier{};
|
||||
for (const auto& graph : trace.graphs)
|
||||
for (const auto& node : graph.nodes) {
|
||||
spectrum_hold = spectrum_hold ||
|
||||
node.name == "prepare.hold.partition";
|
||||
afterglow_reduce = afterglow_reduce ||
|
||||
node.name == "prepare.normalize";
|
||||
afterglow_color_barrier = afterglow_color_barrier ||
|
||||
node.name == "prepare.color.complete";
|
||||
}
|
||||
if (!spectrum_hold || !afterglow_reduce ||
|
||||
!afterglow_color_barrier)
|
||||
trace_valid->store(false, std::memory_order_relaxed);
|
||||
};
|
||||
if (!scene->render(
|
||||
frame,
|
||||
[scene, spectrum, waterfall, afterglow, constellation, frame,
|
||||
resized_partition_frame, spectrum_painted,
|
||||
topology_valid, second_frame_valid, trace_valid,
|
||||
validate_trace](not_null<Frame_2D*> completed) {
|
||||
const bool valid = completed.get() == frame &&
|
||||
spectrum->read_state<Spectrum::Base_Tag>().sample_count ==
|
||||
512 &&
|
||||
topology_valid->load(std::memory_order_relaxed) &&
|
||||
contains_color(completed->image());
|
||||
if (!valid) std::_Exit(1);
|
||||
validate_trace(completed);
|
||||
|
||||
spectrum->set<&Spectrum::Prop::partition_count>(2u);
|
||||
waterfall->set<&Waterfall::Prop::partition_grid>(
|
||||
Plot_Partition_Grid{3, 2});
|
||||
afterglow->set<&Afterglow::Prop::partition_grid>(
|
||||
Plot_Partition_Grid{3, 2});
|
||||
afterglow->submit_stream<Afterglow_Stream_Tag>(
|
||||
std::make_shared<const std::vector<Plot_Value>>(64, -20.0));
|
||||
afterglow->mark_dirty<Render_Graph_Tag>();
|
||||
constellation->set<
|
||||
&Constellation_Diagram::Prop::partition_count>(2u);
|
||||
spectrum_painted->store(false, std::memory_order_relaxed);
|
||||
if (!scene->render(
|
||||
resized_partition_frame,
|
||||
[resized_partition_frame, second_frame_valid,
|
||||
topology_valid, trace_valid,
|
||||
validate_trace](not_null<Frame_2D*> next) {
|
||||
const bool resized_valid =
|
||||
next.get() == resized_partition_frame &&
|
||||
topology_valid->load(std::memory_order_relaxed) &&
|
||||
contains_color(next->image());
|
||||
second_frame_valid->store(resized_valid,
|
||||
std::memory_order_relaxed);
|
||||
validate_trace(next);
|
||||
std::_Exit(
|
||||
second_frame_valid->load(std::memory_order_relaxed) &&
|
||||
trace_valid->load(std::memory_order_relaxed)
|
||||
? 0
|
||||
: 1);
|
||||
}))
|
||||
std::_Exit(2);
|
||||
}))
|
||||
return 2;
|
||||
|
||||
/*
|
||||
* render() 是异步入口。结束提交线程但保持 Taskflow worker 和进程存活,
|
||||
* 完成回调负责给出测试结果;此处没有轮询、future::get 或条件变量等待。
|
||||
*/
|
||||
if (!submitted) return 2;
|
||||
_endthreadex(3);
|
||||
return 3;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user