#include #include #include #include #include #include #include #include #include namespace { using namespace aethera; using namespace aethera::render_2d; template Object* build_object(Arguments&&... arguments) { typename Object::Builder builder(std::forward(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( view.data + static_cast(y) * view.stride); for (int x = 0; x < view.width; ++x) if (row[x] != 0) return true; } return false; } } int main() { using Frequency = Impl; using Power = Impl; using Spectrum_Object = Impl; using Scene_Object = Impl; initialize_runtime({.workers = 4}); auto* frequency = build_object(); auto* power = build_object(); auto* spectrum = build_object(frequency, power); auto* spectrum_painted = new std::atomic_bool{}; auto* topology_valid = new std::atomic_bool{true}; spectrum->paint_taskflow().add("test.spectrum.paint.complete", [spectrum_painted] { spectrum_painted->store(true, std::memory_order_release); }); 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->paint_taskflow().add("test.frequency.paint.order", verify_spectrum_precedes_axis); power->paint_taskflow().add("test.power.paint.order", verify_spectrum_precedes_axis); typename Scene_Object::Builder scene_builder; scene_builder.add_renderable(spectrum); 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}); spectrum->set<&Spectrum::Prop::frequency_range>( Axis_Range{0.0, 100.0}); spectrum->set<&Spectrum::Prop::partition_mode>( Plot_Partition_Mode::fixed); spectrum->set<&Spectrum::Prop::partition_count>(4); spectrum->pending_buffer() = Spectrum_Frame{std::vector(512, -50.0)}; spectrum->mark_dirty(); scene->set<&Render_Scene_2D::Prop::viewport>(Size{160, 120}); scene->activate_view(); auto* frame = new Frame_2D(Frame_Identity{1, 0}); scene->set_frame_callback( [spectrum, frequency, power, frame, topology_valid](Frame_2D* completed) { const auto& state = spectrum->read_state(); const bool valid = completed == frame && state.prepare_executed && state.paint_executed && spectrum->read_state().sample_count == 512 && frequency->read_state().paint_executed && power->read_state().paint_executed && topology_valid->load(std::memory_order_relaxed) && contains_color(completed->image()); std::_Exit(valid ? 0 : 1); }); if (!scene->render(frame)) return 2; /* * render() 是异步入口。结束提交线程但保持 Taskflow worker 和进程存活, * 完成回调负责给出测试结果;此处没有轮询、future::get 或条件变量等待。 */ _endthreadex(3); }