109 lines
4.3 KiB
C++
109 lines
4.3 KiB
C++
#include <render_2D/axis/Axis.hpp>
|
|
#include <render_2D/base/Frame_2D.hpp>
|
|
#include <render_2D/plottable/Spectrum.hpp>
|
|
#include <render_2D/scene/Render_Scene_2D.hpp>
|
|
#include <process.h>
|
|
#include <atomic>
|
|
#include <cstdlib>
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
namespace {
|
|
using namespace aethera;
|
|
using namespace aethera::render_2d;
|
|
|
|
template <typename Object, typename... Arguments>
|
|
Object* build_object(Arguments&&... arguments) {
|
|
typename Object::Builder 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 + static_cast<std::ptrdiff_t>(y) * view.stride);
|
|
for (int x = 0; x < view.width; ++x)
|
|
if (row[x] != 0) return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
int main() {
|
|
using Frequency = Impl<Frequency_Axis>;
|
|
using Power = Impl<Numeric_Axis>;
|
|
using Spectrum_Object = Impl<Spectrum>;
|
|
using Scene_Object = Impl<Render_Scene_2D>;
|
|
|
|
initialize_runtime({.workers = 4});
|
|
auto* frequency = build_object<Frequency>();
|
|
auto* power = build_object<Power>();
|
|
auto* spectrum = build_object<Spectrum_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_Tag>() =
|
|
Spectrum_Frame{std::vector<Spectrum_Power>(512, -50.0)};
|
|
spectrum->mark_dirty<Prepare_Data_Tag>();
|
|
|
|
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<Renderable::Base_Tag>();
|
|
const bool valid = completed == frame &&
|
|
state.prepare_executed && state.paint_executed &&
|
|
spectrum->read_state<Spectrum::Base_Tag>().sample_count ==
|
|
512 &&
|
|
frequency->read_state<Renderable::Base_Tag>().paint_executed &&
|
|
power->read_state<Renderable::Base_Tag>().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);
|
|
}
|