166 lines
9.4 KiB
C++
166 lines
9.4 KiB
C++
#pragma once
|
|
|
|
#include <datoviz/drp2/runtime.h>
|
|
#include <datoviz/input/router.h>
|
|
#include <datoviz/scene.h>
|
|
#include <datoviz/stream/frame_stream.h>
|
|
#include <datoviz/vk/gpu_ctx.h>
|
|
#include <datoviz/vklite.h>
|
|
#include <array>
|
|
#include <atomic>
|
|
#include <mutex>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
#include <utility>
|
|
|
|
namespace aethera::render_3d::detail {
|
|
|
|
struct Datoviz_Visual_Backend::Private : Prev_Private {
|
|
struct Frame_Target;
|
|
struct Frame_Targets;
|
|
|
|
struct External_Attribute {
|
|
std::string name{}; /* Datoviz attribute semantic owned by this binding. */
|
|
std::uint32_t stride{}; /* One planar attribute item in bytes. */
|
|
std::uint32_t capacity{}; /* Items per independently writable frame region. */
|
|
DvzSceneBuffer* scene_buffer{}; /* Scene-side stable resource label; Scene owns it. */
|
|
DvzBuffer* gpu_buffer{}; /* Three-region runtime buffer owned by this backend. */
|
|
std::uint8_t registered_targets{}; /* Runtime slots that have borrowed gpu_buffer. */
|
|
};
|
|
|
|
struct Visual_Instance {
|
|
Visual_Identity identity{}; /* Scene 注册的稳定身份。 */
|
|
Visual_Family family{Visual_Family::point}; /* 原生 Visual 的确定 family。 */
|
|
DvzVisual* visual{}; /* 由 Datoviz Scene 拥有。 */
|
|
DvzSampledField* field{}; /* 仅纹理和体数据 family 使用的 Scene 字段资源。 */
|
|
DvzFont* font{}; /* Glyph/Text 使用的 Scene 字体与可增长 atlas 来源。 */
|
|
DvzText* coordinate_text{}; /* Marker 的数据坐标 XYZ 标注。 */
|
|
std::array<std::uint32_t, 3> field_extent{}; /* field 当前样本尺寸。 */
|
|
std::uint64_t applied_revision{}; /* 此 Visual 已上传的 Prepare 版本。 */
|
|
std::array<std::uint64_t, 3> uploaded_data_revisions{}; /* 各物理帧区已写入的数据版本。 */
|
|
std::optional<Prepared_Visual> applied{}; /* 最近应用的元数据与不可变载荷所有权。 */
|
|
std::vector<External_Attribute> attributes{}; /* 每字段各自拥有三段动态载荷区域。 */
|
|
};
|
|
|
|
struct Runtime_Slot {
|
|
DvzDrp2Runtime* runtime{}; /* 只执行对应帧目标的命令流。 */
|
|
DvzFramePlanEmitter* emitter{}; /* 与 runtime 一一对应的保留语义状态。 */
|
|
};
|
|
|
|
Private();
|
|
~Private() override;
|
|
|
|
void initialize(std::uint32_t gpu_index, bool validation_enabled,
|
|
const std::vector<Visual_Registration>& visuals,
|
|
const Scene_3D_Parameters& initial_scene);
|
|
void create_scene(const std::vector<Visual_Registration>& visuals,
|
|
const Scene_3D_Parameters& initial_scene);
|
|
void apply_camera(const Camera_Descriptor& camera);
|
|
void apply_axes(const Scene_3D_Parameters& scene);
|
|
[[nodiscard]] bool matches_command_structure(
|
|
const Scene_3D_Parameters& scene,
|
|
const Prepared_Visual_Batch& visuals) const;
|
|
[[nodiscard]] std::uint64_t apply(
|
|
const Scene_3D_Parameters& scene,
|
|
const Prepared_Visual_Batch& visuals,
|
|
std::uint8_t target_index, bool bind_target);
|
|
[[nodiscard]] std::uint64_t apply_visual(
|
|
Visual_Instance& target, const Prepared_Visual& visual,
|
|
std::uint8_t target_index, bool bind_target);
|
|
void ensure_external_attributes(Visual_Instance& target,
|
|
const Prepared_Visual& visual);
|
|
[[nodiscard]] std::uint64_t upload_external_attributes(
|
|
Visual_Instance& target, const Prepared_Visual& visual,
|
|
std::uint8_t target_index);
|
|
void bind_external_attributes(Visual_Instance& target,
|
|
std::uint8_t target_index,
|
|
std::uint32_t item_count);
|
|
void register_external_attributes(const DvzDrp2CommandStream* stream,
|
|
std::uint8_t target_index);
|
|
[[nodiscard]] std::optional<Pending_Frame> reuse_recorded_target(
|
|
const Scene_3D_Parameters& scene,
|
|
const Prepared_Visual_Batch& visuals,
|
|
std::uint64_t frame_sequence, bool observe, bool readback);
|
|
[[nodiscard]] std::optional<Pending_Frame> prepare(
|
|
const Scene_3D_Parameters& scene,
|
|
const Prepared_Visual_Batch& visuals,
|
|
std::uint64_t frame_sequence, bool observe, bool readback);
|
|
[[nodiscard]] std::optional<Pending_Frame> try_prepare_reused(
|
|
const Scene_3D_Parameters& scene,
|
|
const Prepared_Visual_Batch& visuals,
|
|
std::uint64_t frame_sequence, bool observe, bool readback);
|
|
[[nodiscard]] DvzSceneFrameArtifact* emit(
|
|
const Scene_3D_Parameters& scene, std::uint8_t target_index);
|
|
[[nodiscard]] std::optional<std::uint8_t> acquire_target(Extent extent);
|
|
[[nodiscard]] Frame_Target& target(const Pending_Frame& pending);
|
|
void submit(Pending_Frame& pending);
|
|
[[nodiscard]] Completed_Frame collect(Pending_Frame pending);
|
|
void discard(Pending_Frame pending);
|
|
void quarantine(Pending_Frame pending) noexcept;
|
|
void dispatch_pointer(Event_Type type, float x, float y,
|
|
Mouse_Button button,
|
|
Keyboard_Modifier modifiers,
|
|
Extent viewport,
|
|
std::uint64_t occurred_at_ns);
|
|
void dispatch_wheel(float x, float y, float delta_x, float delta_y,
|
|
Keyboard_Modifier modifiers,
|
|
Extent viewport,
|
|
std::uint64_t occurred_at_ns);
|
|
void dispatch_key(const Key_Event& event);
|
|
void abandon_resources() noexcept;
|
|
void destroy();
|
|
|
|
std::shared_ptr<Datoviz_Render_Context> render_context_{}; /* 同一 GPU 上所有后端共享的 Device 与分配器。 */
|
|
mutable std::mutex target_mutex_{}; /* 当前 Scene 三个目标槽的唯一生命周期同步源。 */
|
|
std::array<Runtime_Slot, 3> runtime_slots_{}; /* 三套独立 runtime/emitter 状态机。 */
|
|
DvzScene* scene_{}; /* 本后端唯一拥有的 Datoviz Scene。 */
|
|
DvzFigure* figure_{}; /* 当前离屏 Figure。 */
|
|
DvzPanel* panel_{}; /* 承载全部业务 Visual 的全屏 Panel。 */
|
|
std::vector<Visual_Instance> visuals_{}; /* 按 Scene 稳定身份管理的原生 Visual。 */
|
|
std::vector<DvzBuffer*> external_buffers_{}; /* runtime 销毁前保持存活的借用缓冲。 */
|
|
DvzVisual* axes_visual_{}; /* 三维主轴、刻度和网格 Segment Visual。 */
|
|
DvzText* axes_text_{}; /* 随相机变换的三维刻度与轴标题。 */
|
|
DvzItemInteraction* item_interaction_{}; /* Datoviz 原生图元悬停与选择控制器。 */
|
|
DvzPinnedReadout* hover_readout_{}; /* 最近一次命中的 Datoviz 数据提示卡。 */
|
|
DvzController* camera_controller_{}; /* 当前绑定到 Panel 的原生相机控制器。 */
|
|
DvzInputRouter* input_router_{}; /* Scene 输入事件路由器。 */
|
|
DvzPointerGestureHandler* gesture_handler_{}; /* 指针手势解析器。 */
|
|
std::unique_ptr<Frame_Targets> targets_{}; /* 三个可并行处于准备、GPU、读回阶段的目标。 */
|
|
Extent figure_extent_{}; /* Figure 当前应用的像素尺寸。 */
|
|
std::uint64_t target_generation_{}; /* 每次重建目标时递增的资源代次。 */
|
|
std::uint64_t command_revision_{1}; /* 结构变化后递增的命令录制版本。 */
|
|
std::optional<Camera_Descriptor> applied_camera_{}; /* 已应用到 Panel 的 Camera 配置。 */
|
|
std::optional<std::array<plot::Axis_Descriptor, 3>> applied_axes_{}; /* 已应用到轴 Visual 的描述。 */
|
|
bool input_changed_{}; /* 输入是否产生尚未录入命令的资源变化。 */
|
|
std::atomic_bool quarantined_{}; /* GPU 异常后是否永久放弃销毁与复用。 */
|
|
};
|
|
|
|
template <typename Object>
|
|
Datoviz_Visual_Backend::Builder<Object>::Builder(
|
|
std::uint32_t gpu_index_value, bool validation_enabled_value,
|
|
std::vector<Visual_Registration> visuals_value,
|
|
Scene_3D_Parameters initial_scene_value)
|
|
: Base(),
|
|
gpu_index(gpu_index_value),
|
|
validation_enabled(validation_enabled_value),
|
|
visuals(std::move(visuals_value)),
|
|
initial_scene(std::move(initial_scene_value)) {}
|
|
|
|
template <typename Object>
|
|
std::expected<std::unique_ptr<Object>, Dependency_Graph_Error>
|
|
Datoviz_Visual_Backend::Builder<Object>::build() {
|
|
if (visuals.empty())
|
|
throw std::invalid_argument(
|
|
"Datoviz backend requires at least one Visual registration");
|
|
auto result = Base::build();
|
|
if (!result) return std::unexpected(result.error());
|
|
auto backend = std::move(result).value();
|
|
auto& private_data = Base::private_access(backend.get())
|
|
.template get<Datoviz_Visual_Backend::Base_Tag>();
|
|
private_data.initialize(gpu_index, validation_enabled, visuals,
|
|
initial_scene);
|
|
return backend;
|
|
}
|
|
|
|
} // namespace aethera::render_3d::detail
|