改结构
This commit is contained in:
@@ -1,62 +1,42 @@
|
||||
#include <renderive/error/Error_Policy.hpp>
|
||||
#include "Renderable_Base_p.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
#include "renderive/real_time_data/base/Real_Time_Data_Base.hpp"
|
||||
#include "renderive/renderable/Renderive_Id_Allocator.hpp"
|
||||
#include "renderive/scene/base/Scene_Base.hpp"
|
||||
|
||||
#include "renderive/scene/base/Scene_Base.inl"
|
||||
namespace {
|
||||
|
||||
void advance_revision(std::atomic<std::uint64_t>& revision) noexcept {
|
||||
std::uint64_t value = revision.load(std::memory_order_relaxed);
|
||||
while (value != std::numeric_limits<std::uint64_t>::max() &&
|
||||
!revision.compare_exchange_weak(value, value + 1,
|
||||
std::memory_order_release,
|
||||
std::memory_order_relaxed)) {}
|
||||
!revision.compare_exchange_weak(value, value + 1,
|
||||
std::memory_order_release,
|
||||
std::memory_order_relaxed)) {}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Renderable_Base::Impl::Impl()
|
||||
: renderable_id(allocate_renderive_renderable_id()),
|
||||
composite_node_id(allocate_renderive_node_id()) {}
|
||||
|
||||
Renderable_Base::Impl::~Impl() {
|
||||
real_time_data_state->attached.store(false, std::memory_order_release);
|
||||
real_time_data_state->renderable_alive.store(false,
|
||||
std::memory_order_release);
|
||||
}
|
||||
|
||||
void Renderable_Base::Impl::initialize(
|
||||
Renderable_Base& value,
|
||||
Renderable_Configuration initial_configuration,
|
||||
std::pmr::memory_resource& resource) noexcept {
|
||||
owner_ = &value;
|
||||
memory_resource_pointer = &resource;
|
||||
configuration.store(initial_configuration, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
Renderable_Base& Renderable_Base::Impl::owner() noexcept {
|
||||
return *owner_;
|
||||
}
|
||||
|
||||
const Renderable_Base& Renderable_Base::Impl::owner() const noexcept {
|
||||
return *owner_;
|
||||
}
|
||||
|
||||
void Renderable_Base::Impl::invalidate_prepare() noexcept {
|
||||
advance_revision(prepare_revision);
|
||||
}
|
||||
|
||||
void Renderable_Base::Impl::invalidate_paint() noexcept {
|
||||
advance_revision(paint_revision);
|
||||
}
|
||||
|
||||
void Renderable_Base::Impl::bind_scene(
|
||||
std::shared_ptr<Scene_Lifetime> lifetime) {
|
||||
auto& current = real_time_data_state->scene_lifetime;
|
||||
@@ -65,27 +45,25 @@ void Renderable_Base::Impl::bind_scene(
|
||||
else if (current != lifetime)
|
||||
::renderive::error::unexpected<std::invalid_argument>("renderable belongs to another scene");
|
||||
}
|
||||
|
||||
void Renderable_Base::Impl::rebuild_render_graph() {
|
||||
if (!attached()) {
|
||||
reset_render_graph();
|
||||
return;
|
||||
}
|
||||
scene().request_render_graph_rebuild(owner());
|
||||
scene().d_func().request_render_graph_rebuild(owner());
|
||||
}
|
||||
|
||||
void Renderable_Base::Impl::reset_render_graph() {
|
||||
std::lock_guard lock(render_graph_mutex);
|
||||
render_graph.reset();
|
||||
invalidate_prepare();
|
||||
}
|
||||
|
||||
std::shared_ptr<const Renderable_Graph>
|
||||
Renderable_Base::Impl::render_graph_snapshot() {
|
||||
std::lock_guard lock(render_graph_mutex);
|
||||
if (!render_graph) {
|
||||
std::pmr::unordered_map<std::string, Render_Node_Id> next_identities{
|
||||
&memory_resource()};
|
||||
&memory_resource()
|
||||
};
|
||||
Renderable_Graph_Builder builder(
|
||||
renderable_id,
|
||||
[this, &next_identities](std::string_view key) {
|
||||
@@ -95,9 +73,9 @@ Renderable_Base::Impl::render_graph_snapshot() {
|
||||
"duplicate render node logical key");
|
||||
const auto current = node_identities.find(logical_key);
|
||||
const Render_Node_Id node_id =
|
||||
current == node_identities.end()
|
||||
? allocate_renderive_node_id()
|
||||
: current->second;
|
||||
current == node_identities.end()
|
||||
? allocate_renderive_node_id()
|
||||
: current->second;
|
||||
next_identities.emplace(logical_key, node_id);
|
||||
return node_id;
|
||||
});
|
||||
@@ -110,12 +88,10 @@ Renderable_Base::Impl::render_graph_snapshot() {
|
||||
}
|
||||
return render_graph;
|
||||
}
|
||||
|
||||
std::pmr::memory_resource&
|
||||
Renderable_Base::Impl::memory_resource() const noexcept {
|
||||
return *memory_resource_pointer;
|
||||
}
|
||||
|
||||
Scene_Base& Renderable_Base::Impl::scene() const {
|
||||
const auto lifetime = real_time_data_state->scene_lifetime;
|
||||
if (!lifetime)
|
||||
@@ -125,35 +101,30 @@ Scene_Base& Renderable_Base::Impl::scene() const {
|
||||
::renderive::error::unexpected<std::logic_error>("renderable scene is no longer alive");
|
||||
return lease.scene();
|
||||
}
|
||||
|
||||
bool Renderable_Base::Impl::attached() const noexcept {
|
||||
return real_time_data_state->attached.load(std::memory_order_acquire);
|
||||
}
|
||||
|
||||
void Renderable_Base::Impl::set_configuration(
|
||||
Renderable_Configuration value) {
|
||||
const Renderable_Configuration previous =
|
||||
configuration.load(std::memory_order_acquire);
|
||||
configuration.load(std::memory_order_acquire);
|
||||
if (previous == value)
|
||||
return;
|
||||
configuration.store(value, std::memory_order_release);
|
||||
invalidate_prepare();
|
||||
notify_scene_model_dirty();
|
||||
}
|
||||
|
||||
void Renderable_Base::Impl::set_visible(bool value) {
|
||||
if (visible.exchange(value, std::memory_order_acq_rel) == value)
|
||||
return;
|
||||
invalidate_prepare();
|
||||
notify_scene_model_dirty();
|
||||
}
|
||||
|
||||
void Renderable_Base::Impl::discard_stale_frame_on_latest_data_update(
|
||||
bool enabled) noexcept {
|
||||
real_time_data_state->discard_stale_frame_on_latest_data_update.store(
|
||||
enabled, std::memory_order_release);
|
||||
}
|
||||
|
||||
void Renderable_Base::Impl::notify_scene_model_dirty() {
|
||||
const auto& state = real_time_data_state;
|
||||
if (!state->attached.load(std::memory_order_acquire) ||
|
||||
@@ -163,7 +134,6 @@ void Renderable_Base::Impl::notify_scene_model_dirty() {
|
||||
if (lease)
|
||||
lease.scene().notify_model_dirty();
|
||||
}
|
||||
|
||||
void Renderable_Base::Impl::build_prepare_graph(
|
||||
Renderable_Graph_Builder& builder) {
|
||||
builder.emplace("prepare", "Prepare",
|
||||
@@ -171,40 +141,31 @@ void Renderable_Base::Impl::build_prepare_graph(
|
||||
execute_prepare(context);
|
||||
});
|
||||
}
|
||||
|
||||
void Renderable_Base::Impl::build_paint_graph(
|
||||
Renderable_Graph_Builder&) {}
|
||||
|
||||
void Renderable_Base::Impl::prepare(const Prepare_Render_Context&) {}
|
||||
|
||||
void Renderable_Base::Impl::capture_frame_data(Frame_Render_Snapshot&) const {}
|
||||
|
||||
void Renderable_Base::Impl::add_prepare_action(Prepare_Action action) {
|
||||
if (!action)
|
||||
::renderive::error::unexpected<std::invalid_argument>("renderable prepare action is empty");
|
||||
prepare_actions.push_back(std::move(action));
|
||||
}
|
||||
|
||||
void Renderable_Base::Impl::execute_prepare(
|
||||
const Prepare_Render_Context& context) {
|
||||
for (const auto& action : prepare_actions)
|
||||
action();
|
||||
prepare(context);
|
||||
}
|
||||
|
||||
Render_State_View Renderable_Base::Impl::render_state_view() noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
Real_Time_Data_Binding Renderable_Base::Impl::bind_real_time_data(
|
||||
Real_Time_Data_Base& data) {
|
||||
return data.bind_renderable(owner());
|
||||
}
|
||||
|
||||
void Renderable_Base::Impl::mark_prepared(std::uint64_t revision) noexcept {
|
||||
prepared_revision.store(revision, std::memory_order_release);
|
||||
}
|
||||
|
||||
void Renderable_Base::Impl::mark_painted(
|
||||
std::uint64_t current_paint_revision,
|
||||
std::uint64_t current_prepare_revision) noexcept {
|
||||
@@ -212,7 +173,6 @@ void Renderable_Base::Impl::mark_painted(
|
||||
std::memory_order_release);
|
||||
painted_revision.store(current_paint_revision, std::memory_order_release);
|
||||
}
|
||||
|
||||
void Renderable_Base::Impl::register_real_time_data(
|
||||
Real_Time_Data_Base& data) {
|
||||
std::lock_guard lock(real_time_data_mutex);
|
||||
@@ -220,74 +180,62 @@ void Renderable_Base::Impl::register_real_time_data(
|
||||
real_time_data.end())
|
||||
real_time_data.push_back(&data);
|
||||
}
|
||||
|
||||
void Renderable_Base::Impl::unregister_real_time_data(
|
||||
Real_Time_Data_Base& data) {
|
||||
std::lock_guard lock(real_time_data_mutex);
|
||||
std::erase(real_time_data, &data);
|
||||
}
|
||||
|
||||
void Renderable_Base::Impl::publish_real_time_data() {
|
||||
std::lock_guard lock(real_time_data_mutex);
|
||||
for (Real_Time_Data_Base* data : real_time_data)
|
||||
data->publish_render_state();
|
||||
}
|
||||
|
||||
Renderable_Base::Renderable_Base(Renderable_Configuration configuration,
|
||||
std::pmr::memory_resource& memory_resource)
|
||||
: Renderable_Base(std::make_unique<Impl>(), configuration,
|
||||
memory_resource) {}
|
||||
|
||||
Renderable_Base::Renderable_Base(std::unique_ptr<Impl> implementation,
|
||||
Renderable_Configuration configuration,
|
||||
std::pmr::memory_resource& memory_resource)
|
||||
: d_ptr(std::move(implementation)) {
|
||||
if (!d_ptr)
|
||||
::renderive::error::unexpected<std::invalid_argument>("renderable implementation is null");
|
||||
d_ptr->initialize(*this, configuration, memory_resource);
|
||||
d_ptr->owner_ = this;
|
||||
d_ptr->memory_resource_pointer = &memory_resource;
|
||||
d_ptr->configuration.store(configuration, std::memory_order_release);
|
||||
}
|
||||
|
||||
Renderable_Base::~Renderable_Base() = default;
|
||||
|
||||
Renderable_Id Renderable_Base::renderable_id() const noexcept {
|
||||
return d_func().renderable_id;
|
||||
}
|
||||
|
||||
bool Renderable_Base::is_visible() const noexcept {
|
||||
return d_func().visible.load(std::memory_order_acquire);
|
||||
}
|
||||
|
||||
std::string Renderable_Base::object_name() const {
|
||||
const auto& implementation = d_func();
|
||||
std::lock_guard lock(implementation.metadata_mutex);
|
||||
return implementation.object_name;
|
||||
}
|
||||
|
||||
void Renderable_Base::set_object_name(std::string name) {
|
||||
auto& implementation = d_func();
|
||||
std::lock_guard lock(implementation.metadata_mutex);
|
||||
implementation.object_name = std::move(name);
|
||||
}
|
||||
|
||||
void Renderable_Base::set_visible(bool visible) {
|
||||
d_func().set_visible(visible);
|
||||
}
|
||||
|
||||
void Renderable_Base::discard_stale_frame_on_latest_data_update(
|
||||
bool enabled) noexcept {
|
||||
d_func().discard_stale_frame_on_latest_data_update(enabled);
|
||||
}
|
||||
|
||||
void Renderable_Base::Impl::changed() {
|
||||
invalidate_prepare();
|
||||
notify_scene_model_dirty();
|
||||
}
|
||||
|
||||
void Renderable_Base::Impl::paint_changed() {
|
||||
invalidate_paint();
|
||||
notify_scene_model_dirty();
|
||||
}
|
||||
|
||||
void Renderable_Base::Impl::render_graph_changed() {
|
||||
rebuild_render_graph();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user