Files
Renderive/Kernel/src/renderive/scene/base/Scene_Base.hpp
T
2026-08-18 08:49:09 +08:00

397 lines
17 KiB
C++

#pragma once
#include <atomic>
#include <condition_variable>
#include <concepts>
#include <cstddef>
#include <cstdint>
#include <exception>
#include <functional>
#include <future>
#include <memory>
#include <memory_resource>
#include <mutex>
#include <optional>
#include <unordered_map>
#include <typeindex>
#include <utility>
#include <variant>
#include <vector>
#include "renderive/base/memory/Memory_Resource.hpp"
#include "renderive/capture/Capture.hpp"
#include "renderive/frame_control/base/Frame_Control_Strategy_Base.hpp"
#include "renderive/renderable/Renderable_Graph_Builder.hpp"
#include "renderive/renderable/base/Renderable_Base.hpp"
#include "renderive/renderable/base/Renderive_Owner.hpp"
#include "renderive/render_graph/External_Operation.hpp"
#include "renderive/render_graph/Render_Plan.hpp"
#include "renderive/scene/Inheritance.hpp"
#include "renderive/scene/dependency/Dependency_Resolver.hpp"
#include "Abstract_Frame.hpp"
#include "Frame_Render_Snapshot.hpp"
#include "Frame_Viewport.hpp"
#include "Render_Contexts.hpp"
#include "Scene_Lifetime.hpp"
#include "renderive/base/Concepts.hpp"
namespace renderive::inheritance {
struct Observation_Source;
}
class Color_Cache;
enum class Scene_Render_Result : std::uint8_t {
none,
cancelled,
deadline_exceeded,
external_failure,
shutting_down
};
enum class Scene_Edit_Error : std::uint8_t {
none,
empty_edit,
null_renderable,
foreign_renderable,
renderable_not_attached,
dependency_self_reference,
dependency_cycle,
display_self_reference,
display_cycle,
dangling_dependency,
dangling_display,
shutting_down
};
struct Scene_Execution_Statistics {
std::size_t capacity{};
std::size_t queued{};
std::size_t peak_queued{};
std::uint64_t backpressure_count{};
std::uint64_t backpressure_wait_ns{};
};
class Scene_Base : public Non_Copyable {
public:
using Renderable = renderive_Owner<Renderable_Base>;
using Const_Renderable = renderive_Owner<const Renderable_Base>;
class Attach_Builder;
class Renderable_Editor
: public renderive::scene_inheritance::Editor_Root<Renderable_Editor> {
public:
template <class Next>
using next_Editor =
renderive::scene_inheritance::Editor_Node<Next, Renderable_Editor>;
[[nodiscard]] Scene_Edit_Error attach(Renderable renderable);
[[nodiscard]] Scene_Edit_Error detach(const Renderable& renderable);
[[nodiscard]] Scene_Edit_Error set_dependency_parent(const Renderable& child, const Renderable& parent);
[[nodiscard]] Scene_Edit_Error add_dependency_parent(const Renderable& child, const Renderable& parent);
[[nodiscard]] Scene_Edit_Error clear_dependency_parent(const Renderable& child);
void replace_frame_control_strategy(
std::shared_ptr<Frame_Control_Strategy_Base> strategy);
[[nodiscard]] Scene_Edit_Error error() const noexcept {
return error_;
}
protected:
explicit Renderable_Editor(Scene_Base& scene) : scene_(scene) {}
Scene_Base& scene_;
Scene_Edit_Error fail(Scene_Edit_Error error) noexcept;
private:
Scene_Edit_Error error_{};
friend class Scene_Base;
friend class Attach_Builder;
};
class Attach_Builder
: public renderive::scene_inheritance::Builder_Root<Attach_Builder> {
public:
template <class Next>
using next_Builder =
renderive::scene_inheritance::Builder_Node<Next, Attach_Builder>;
Attach_Builder(const Attach_Builder&) = delete;
Attach_Builder& operator=(const Attach_Builder&) = delete;
Attach_Builder(Attach_Builder&&) = delete;
Attach_Builder& operator=(Attach_Builder&&) = delete;
[[nodiscard]] Scene_Edit_Error attach(Renderable renderable);
[[nodiscard]] Scene_Edit_Error set_dependency_parent(const Renderable& child, const Renderable& parent);
[[nodiscard]] Scene_Edit_Error add_dependency_parent(const Renderable& child, const Renderable& parent);
[[nodiscard]] Scene_Edit_Error clear_dependency_parent(const Renderable& child);
protected:
explicit Attach_Builder(Scene_Base& scene);
Scene_Base& scene_;
std::unique_lock<std::recursive_mutex> task_lock_;
private:
friend class Scene_Base;
};
using Renderable_Edit = std::function<void(Renderable_Editor&)>;
class Edit_Operation {
public:
Edit_Operation() = default;
[[nodiscard]] Scene_Edit_Error wait() const;
private:
explicit Edit_Operation(std::shared_future<Scene_Edit_Error> result) : result_(std::move(result)) {}
std::shared_future<Scene_Edit_Error> result_;
friend class Scene_Base;
friend class Scene_2D_Base;
friend class Scene_3D_Base;
};
struct Topology_Relationship {
Const_Renderable child;
Const_Renderable parent;
};
struct Topology_Snapshot {
std::vector<Const_Renderable> renderables;
std::vector<Topology_Relationship> display;
std::vector<Topology_Relationship> dependency;
};
enum class Observation_Event {
render_submitted,
render_started,
render_completed,
render_cancelled,
render_failed
};
struct Observation {
Observation_Event event{};
std::uint64_t time_ns{};
std::uint64_t render_sequence{};
std::uint64_t scene_state_revision{};
std::size_t renderable_count{};
std::shared_ptr<const Topology_Snapshot> topology;
std::shared_ptr<const Frame_Render_Snapshot> frame_snapshot;
std::shared_ptr<const Render_Plan> render_plan;
};
Scene_Render_Result render();
Scene_Render_Result render(Abstract_Frame& frame);
Scene_Render_Result wait_for_render();
void publish_frame_state();
void publish_frame_state(Abstract_Frame& frame);
[[nodiscard]] Edit_Operation edit_renderables(Renderable_Edit edit);
[[nodiscard]] std::size_t renderable_count() const;
[[nodiscard]] Topology_Snapshot topology_snapshot() const;
[[nodiscard]] std::vector<Const_Renderable> paint_order_snapshot() const;
[[nodiscard]] std::shared_ptr<const Render_Plan> render_plan_snapshot() const;
[[nodiscard]] std::shared_ptr<const Render_Plan> find_render_plan(Render_Plan_Version version) const;
[[nodiscard]] Capture_Request_Result capture_next_frame();
[[nodiscard]] Capture_Request_Result capture_frames(std::size_t count);
[[nodiscard]] Capture_Controller_State capture_state() const noexcept;
[[nodiscard]] std::optional<Capture_Session> capture_session(Capture_Session_Id session_id) const;
[[nodiscard]] std::vector<Capture_Session_Id> capture_sessions() const;
[[nodiscard]] std::vector<Node_Statistics> node_statistics(Capture_Session_Id session_id) const;
[[nodiscard]] std::vector<Plan_Version_Statistics> plan_version_statistics(Capture_Session_Id session_id) const;
[[nodiscard]] Scene_Execution_Statistics execution_statistics() const noexcept;
[[nodiscard]] std::pmr::memory_resource& memory_resource() const noexcept;
[[nodiscard]] std::pmr::memory_resource& upstream_memory_resource() const noexcept;
[[nodiscard]] auto frame_control_strategy() -> std::shared_ptr<Frame_Control_Strategy_Base>;
[[nodiscard]] auto frame_control_strategy() const -> std::shared_ptr<const Frame_Control_Strategy_Base>;
struct Observer
: renderive::scene_inheritance::Observer_Root<Observer> {};
protected:
Scene_Base();
explicit Scene_Base(std::pmr::memory_resource& upstream_memory_resource);
virtual ~Scene_Base();
struct Builder
: renderive::scene_inheritance::Builder_Root<Builder> {};
struct State
: renderive::scene_inheritance::State_Root<State> {};
class Impl;
template <class Next>
using next_Builder =
renderive::scene_inheritance::Builder_Node<Next, Builder>;
template <class Next>
using next_State =
renderive::scene_inheritance::State_Node<Next, State>;
template <class Next>
using next_Impl =
renderive::scene_inheritance::Impl_Node<Next, Impl>;
template <class Next>
using next_Observer =
renderive::scene_inheritance::Observer_Node<Next, Observer>;
template <class Next>
using next_Editor =
renderive::scene_inheritance::Editor_Node<Next, Renderable_Editor>;
Scene_Base(std::pmr::memory_resource& upstream_memory_resource,
std::unique_ptr<Impl> impl);
void bind_observation_source(
std::unique_ptr<renderive::inheritance::Observation_Source> source);
void unbind_observation_source() noexcept;
[[nodiscard]] bool observation_snapshot(
std::type_index type, void* destination) const;
template <class Implementation = Impl>
Implementation& d_func() noexcept {
return static_cast<Implementation&>(*impl_);
}
template <class Implementation = Impl>
const Implementation& d_func() const noexcept {
return static_cast<const Implementation&>(*impl_);
}
private:
friend class Renderable_Base;
friend class Scene_2D_Base;
std::unique_ptr<Impl> impl_;
};
class Scene_2D_Base : public Scene_Base {
public:
class Renderable_Editor
: public Scene_Base::Renderable_Editor::next_Editor<Renderable_Editor> {
public:
template <class Next>
using next_Editor =
renderive::scene_inheritance::Editor_Node<Next, Renderable_Editor>;
[[nodiscard]] Scene_Edit_Error set_display_parent(const Renderable& child, const Renderable& parent);
[[nodiscard]] Scene_Edit_Error add_display_parent(const Renderable& child, const Renderable& parent);
[[nodiscard]] Scene_Edit_Error clear_display_parent(const Renderable& child);
private:
explicit Renderable_Editor(Scene_2D_Base& scene) : Scene_Base::Renderable_Editor::next_Editor<
Renderable_Editor>(scene),
scene_2d_(scene) {}
Scene_2D_Base& scene_2d_;
friend class Scene_2D_Base;
friend class Attach_Builder;
};
class Attach_Builder
: public Scene_Base::Attach_Builder::next_Builder<Attach_Builder> {
public:
template <class Next>
using next_Builder =
renderive::scene_inheritance::Builder_Node<Next, Attach_Builder>;
[[nodiscard]] Scene_Edit_Error set_display_parent(const Renderable& child, const Renderable& parent);
[[nodiscard]] Scene_Edit_Error add_display_parent(const Renderable& child, const Renderable& parent);
[[nodiscard]] Scene_Edit_Error clear_display_parent(const Renderable& child);
private:
explicit Attach_Builder(Scene_2D_Base& scene) : Scene_Base::Attach_Builder::next_Builder<
Attach_Builder>(scene),
scene_2d_(scene) {}
Scene_2D_Base& scene_2d_;
friend class Scene_2D_Base;
};
using Renderable_Edit = std::function<void(Renderable_Editor&)>;
Scene_2D_Base();
explicit Scene_2D_Base(std::pmr::memory_resource& memory_resource);
Attach_Builder attach_builder();
[[nodiscard]] static Attach_Builder attach_builder(const Renderable& anchor);
[[nodiscard]] Edit_Operation edit_renderables(Renderable_Edit edit);
struct Observer
: Scene_Base::next_Observer<Observer> {};
protected:
struct Builder : Scene_Base::next_Builder<Builder> {};
struct State : Scene_Base::next_State<State> {};
struct Impl;
template <class Next>
using next_Builder =
renderive::scene_inheritance::Builder_Node<Next, Builder>;
template <class Next>
using next_State =
renderive::scene_inheritance::State_Node<Next, State>;
template <class Next>
using next_Impl =
renderive::scene_inheritance::Impl_Node<Next, Impl>;
template <class Next>
using next_Observer =
renderive::scene_inheritance::Observer_Node<Next, Observer>;
template <class Next>
using next_Editor =
renderive::scene_inheritance::Editor_Node<Next, Renderable_Editor>;
static_assert(renderive::inheritance::Defines_Chain_Layer<
Builder, Scene_Base::next_Builder<Builder>,
next_Builder<renderive::inheritance::Chain_Probe>,
renderive::scene_inheritance::Builder_Node<
renderive::inheritance::Chain_Probe, Builder>>);
static_assert(renderive::inheritance::Defines_Chain_Layer<
State, Scene_Base::next_State<State>,
next_State<renderive::inheritance::Chain_Probe>,
renderive::scene_inheritance::State_Node<
renderive::inheritance::Chain_Probe, State>>);
static_assert(renderive::inheritance::Defines_Chain_Layer<
Observer, Scene_Base::next_Observer<Observer>,
next_Observer<renderive::inheritance::Chain_Probe>,
renderive::scene_inheritance::Observer_Node<
renderive::inheritance::Chain_Probe, Observer>>);
static_assert(renderive::inheritance::Defines_Chain_Layer<
Renderable_Editor,
Scene_Base::Renderable_Editor::next_Editor<Renderable_Editor>,
next_Editor<renderive::inheritance::Chain_Probe>,
renderive::scene_inheritance::Editor_Node<
renderive::inheritance::Chain_Probe, Renderable_Editor>>);
static_assert(renderive::inheritance::Defines_Chain_Layer<
Attach_Builder,
Scene_Base::Attach_Builder::next_Builder<Attach_Builder>,
Attach_Builder::next_Builder<renderive::inheritance::Chain_Probe>,
renderive::scene_inheritance::Builder_Node<
renderive::inheritance::Chain_Probe, Attach_Builder>>);
Scene_2D_Base(std::pmr::memory_resource& memory_resource,
std::unique_ptr<Scene_Base::Impl> impl);
private:
friend class Scene_Base;
};
class Scene_3D_Base : public Scene_Base {
public:
class Renderable_Editor : public Scene_Base::Renderable_Editor::next_Editor<Renderable_Editor> {
public:
template <class Next>
using next_Editor =
renderive::scene_inheritance::Editor_Node<Next, Renderable_Editor>;
private:
explicit Renderable_Editor(Scene_3D_Base& scene) : Scene_Base::Renderable_Editor::next_Editor<
Renderable_Editor>(scene) {}
friend class Scene_3D_Base;
};
class Attach_Builder : public Scene_Base::Attach_Builder::next_Builder<Attach_Builder> {
public:
template <class Next>
using next_Builder =
renderive::scene_inheritance::Builder_Node<Next, Attach_Builder>;
private:
explicit Attach_Builder(Scene_3D_Base& scene) : Scene_Base::Attach_Builder::next_Builder<
Attach_Builder>(scene) {}
friend class Scene_3D_Base;
};
using Renderable_Edit = std::function<void(Renderable_Editor&)>;
[[nodiscard]] Edit_Operation edit_renderables(Renderable_Edit edit);
struct Observer
: Scene_Base::next_Observer<Observer> {};
protected:
Scene_3D_Base();
explicit Scene_3D_Base(std::pmr::memory_resource& memory_resource);
struct Builder : Scene_Base::next_Builder<Builder> {};
struct State : Scene_Base::next_State<State> {};
struct Impl;
template <class Next>
using next_Builder =
renderive::scene_inheritance::Builder_Node<Next, Builder>;
template <class Next>
using next_State =
renderive::scene_inheritance::State_Node<Next, State>;
template <class Next>
using next_Impl =
renderive::scene_inheritance::Impl_Node<Next, Impl>;
template <class Next>
using next_Observer =
renderive::scene_inheritance::Observer_Node<Next, Observer>;
template <class Next>
using next_Editor =
renderive::scene_inheritance::Editor_Node<Next, Renderable_Editor>;
static_assert(renderive::inheritance::Defines_Chain_Layer<
Builder, Scene_Base::next_Builder<Builder>,
next_Builder<renderive::inheritance::Chain_Probe>,
renderive::scene_inheritance::Builder_Node<
renderive::inheritance::Chain_Probe, Builder>>);
static_assert(renderive::inheritance::Defines_Chain_Layer<
State, Scene_Base::next_State<State>,
next_State<renderive::inheritance::Chain_Probe>,
renderive::scene_inheritance::State_Node<
renderive::inheritance::Chain_Probe, State>>);
static_assert(renderive::inheritance::Defines_Chain_Layer<
Observer, Scene_Base::next_Observer<Observer>,
next_Observer<renderive::inheritance::Chain_Probe>,
renderive::scene_inheritance::Observer_Node<
renderive::inheritance::Chain_Probe, Observer>>);
static_assert(renderive::inheritance::Defines_Chain_Layer<
Renderable_Editor,
Scene_Base::Renderable_Editor::next_Editor<Renderable_Editor>,
next_Editor<renderive::inheritance::Chain_Probe>,
renderive::scene_inheritance::Editor_Node<
renderive::inheritance::Chain_Probe, Renderable_Editor>>);
static_assert(renderive::inheritance::Defines_Chain_Layer<
Attach_Builder,
Scene_Base::Attach_Builder::next_Builder<Attach_Builder>,
Attach_Builder::next_Builder<renderive::inheritance::Chain_Probe>,
renderive::scene_inheritance::Builder_Node<
renderive::inheritance::Chain_Probe, Attach_Builder>>);
Scene_3D_Base(std::pmr::memory_resource& memory_resource,
std::unique_ptr<Scene_Base::Impl> impl);
};
#include "Scene_Base.inl"