builder 和 运行时修改隔离开
This commit is contained in:
@@ -3,18 +3,16 @@
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#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"
|
||||
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)) {}
|
||||
while (value != std::numeric_limits<std::uint64_t>::max() && !revision.compare_exchange_weak(value, value + 1, std::memory_order_release, std::memory_order_relaxed)) {}
|
||||
}
|
||||
}
|
||||
Renderable_Base::Renderable_Base(Scene_Base& scene, Renderable_Configuration configuration)
|
||||
: memory_domain_(scene.memory_domain_), real_time_data_state_(std::allocate_shared<Real_Time_Data_State>(Scene_Memory_Allocator<Real_Time_Data_State>{memory_domain_}, scene.scene_lifetime_)), discard_stale_frame_on_latest_data_update(real_time_data_state_->discard_stale_frame_on_latest_data_update), renderable_id_(scene.allocate_renderable_id()), composite_node_id_(scene.allocate_node_id()), configuration_(configuration) {}
|
||||
Renderable_Base::Renderable_Base(Renderable_Configuration configuration, std::pmr::memory_resource& memory_resource)
|
||||
: memory_resource_(&memory_resource), real_time_data_state_(std::make_shared<Real_Time_Data_State>()), discard_stale_frame_on_latest_data_update(real_time_data_state_->discard_stale_frame_on_latest_data_update), renderable_id_(allocate_renderive_renderable_id()), composite_node_id_(allocate_renderive_node_id()), configuration_(configuration) {}
|
||||
Renderable_Base::~Renderable_Base() {
|
||||
real_time_data_state_->attached.store(false, std::memory_order_release);
|
||||
real_time_data_state_->renderable_alive.store(false, std::memory_order_release);
|
||||
@@ -39,17 +37,23 @@ std::uint64_t Renderable_Base::painted_revision() const noexcept {
|
||||
}
|
||||
bool Renderable_Base::prepare_cache_valid() const noexcept {
|
||||
const std::uint64_t revision = prepare_revision();
|
||||
return revision != std::numeric_limits<std::uint64_t>::max() &&
|
||||
configuration().cache_enabled && prepared_revision() == revision;
|
||||
return revision != std::numeric_limits<std::uint64_t>::max() && configuration().cache_enabled && prepared_revision() == revision;
|
||||
}
|
||||
bool Renderable_Base::paint_cache_valid() const noexcept {
|
||||
const std::uint64_t revision = paint_revision();
|
||||
return revision != std::numeric_limits<std::uint64_t>::max() &&
|
||||
configuration().cache_enabled && prepare_cache_valid() &&
|
||||
painted_revision() == revision &&
|
||||
painted_prepare_revision_.load(std::memory_order_acquire) == prepared_revision();
|
||||
return revision != std::numeric_limits<std::uint64_t>::max() && configuration().cache_enabled && prepare_cache_valid() && painted_revision() == revision && painted_prepare_revision_.load(std::memory_order_acquire) == prepared_revision();
|
||||
}
|
||||
void Renderable_Base::bind_scene(Scene_Base& scene) {
|
||||
if (!real_time_data_state_->scene_lifetime)
|
||||
real_time_data_state_->scene_lifetime = scene.scene_lifetime_;
|
||||
else if (real_time_data_state_->scene_lifetime.get() != scene.scene_lifetime_.get())
|
||||
throw std::invalid_argument("renderable belongs to another scene");
|
||||
}
|
||||
void Renderable_Base::rebuild_render_graph() {
|
||||
if (!attached()) {
|
||||
reset_render_graph();
|
||||
return;
|
||||
}
|
||||
scene().request_render_graph_rebuild(*this);
|
||||
}
|
||||
void Renderable_Base::reset_render_graph() noexcept {
|
||||
@@ -63,15 +67,12 @@ std::shared_ptr<const Renderable_Graph> Renderable_Base::render_graph() {
|
||||
std::lock_guard lock(render_graph_mutex_);
|
||||
if (!render_graph_) {
|
||||
std::unordered_map<std::string, Render_Node_Id> next_identities;
|
||||
Renderable_Graph_Builder builder(renderable_id_, [this, &next_identities](
|
||||
std::string_view key) {
|
||||
Renderable_Graph_Builder builder(renderable_id_, [this, &next_identities](std::string_view key) {
|
||||
const std::string logical_key(key);
|
||||
if (next_identities.contains(logical_key))
|
||||
throw std::invalid_argument("duplicate render node logical key");
|
||||
const auto current = node_identities_.find(logical_key);
|
||||
const Render_Node_Id node_id = current == node_identities_.end()
|
||||
? scene().allocate_node_id()
|
||||
: current->second;
|
||||
const Render_Node_Id node_id = current == node_identities_.end() ? allocate_renderive_node_id() : current->second;
|
||||
next_identities.emplace(logical_key, node_id);
|
||||
return node_id;
|
||||
});
|
||||
@@ -87,19 +88,40 @@ Renderable_Id Renderable_Base::renderable_id() const noexcept {
|
||||
return renderable_id_;
|
||||
}
|
||||
std::pmr::memory_resource& Renderable_Base::memory_resource() const noexcept {
|
||||
return memory_domain_->resource();
|
||||
return *memory_resource_;
|
||||
}
|
||||
Scene_Base& Renderable_Base::scene() const {
|
||||
auto lease = real_time_data_state_->scene_lifetime->acquire();
|
||||
if (!lease) {
|
||||
const auto lifetime = real_time_data_state_->scene_lifetime;
|
||||
if (!lifetime)
|
||||
throw std::logic_error("renderable is not bound to a scene");
|
||||
auto lease = lifetime->acquire();
|
||||
if (!lease)
|
||||
throw std::logic_error("renderable scene is no longer alive");
|
||||
}
|
||||
return lease.scene();
|
||||
}
|
||||
bool Renderable_Base::has_scene() const noexcept {
|
||||
return static_cast<bool>(real_time_data_state_->scene_lifetime);
|
||||
}
|
||||
bool Renderable_Base::attached() const noexcept {
|
||||
return real_time_data_state_->attached.load(std::memory_order_acquire);
|
||||
}
|
||||
Renderable_Configuration Renderable_Base::configuration() const noexcept {
|
||||
std::lock_guard lock(configuration_mutex_);
|
||||
return configuration_;
|
||||
}
|
||||
void Renderable_Base::set_configuration(Renderable_Configuration configuration) {
|
||||
bool changed{};
|
||||
{
|
||||
std::lock_guard lock(configuration_mutex_);
|
||||
changed = configuration_ != configuration;
|
||||
if (changed)
|
||||
configuration_ = configuration;
|
||||
}
|
||||
if (!changed)
|
||||
return;
|
||||
invalidate_prepare();
|
||||
notify_scene_model_dirty();
|
||||
}
|
||||
bool Renderable_Base::is_visible() const noexcept {
|
||||
std::lock_guard lock(configuration_mutex_);
|
||||
return visible_;
|
||||
@@ -112,13 +134,22 @@ void Renderable_Base::set_visible(bool visible) {
|
||||
visible_ = visible;
|
||||
invalidate_prepare();
|
||||
}
|
||||
scene().notify_model_dirty();
|
||||
notify_scene_model_dirty();
|
||||
}
|
||||
void Renderable_Base::notify_scene_model_dirty() noexcept {
|
||||
if (!attached())
|
||||
return;
|
||||
const auto lifetime = real_time_data_state_->scene_lifetime;
|
||||
if (!lifetime)
|
||||
return;
|
||||
auto lease = lifetime->acquire();
|
||||
if (lease)
|
||||
lease.scene().notify_model_dirty();
|
||||
}
|
||||
void Renderable_Base::build_prepare_graph(Renderable_Graph_Builder& builder) {
|
||||
builder.emplace("prepare", "Prepare",
|
||||
[this](const Prepare_Render_Context& context) {
|
||||
prepare(context);
|
||||
});
|
||||
builder.emplace("prepare", "Prepare", [this](const Prepare_Render_Context& context) {
|
||||
prepare(context);
|
||||
});
|
||||
}
|
||||
void Renderable_Base::build_paint_graph(Renderable_Graph_Builder&) {}
|
||||
void Renderable_Base::prepare(const Prepare_Render_Context&) {}
|
||||
@@ -131,16 +162,14 @@ Real_Time_Data_Binding Renderable_Base::bind_real_time_data(Real_Time_Data_Base&
|
||||
void Renderable_Base::mark_prepared(std::uint64_t revision) noexcept {
|
||||
prepared_revision_.store(revision, std::memory_order_release);
|
||||
}
|
||||
void Renderable_Base::mark_painted(std::uint64_t paint_revision,
|
||||
std::uint64_t prepare_revision) noexcept {
|
||||
void Renderable_Base::mark_painted(std::uint64_t paint_revision, std::uint64_t prepare_revision) noexcept {
|
||||
painted_prepare_revision_.store(prepare_revision, std::memory_order_release);
|
||||
painted_revision_.store(paint_revision, std::memory_order_release);
|
||||
}
|
||||
void Renderable_Base::register_real_time_data(Real_Time_Data_Base& data) {
|
||||
std::lock_guard lock(real_time_data_mutex_);
|
||||
if (std::find(real_time_data_.begin(), real_time_data_.end(), &data) == real_time_data_.end()) {
|
||||
if (std::find(real_time_data_.begin(), real_time_data_.end(), &data) == real_time_data_.end())
|
||||
real_time_data_.push_back(&data);
|
||||
}
|
||||
}
|
||||
void Renderable_Base::unregister_real_time_data(Real_Time_Data_Base& data) noexcept {
|
||||
std::lock_guard lock(real_time_data_mutex_);
|
||||
@@ -148,7 +177,6 @@ void Renderable_Base::unregister_real_time_data(Real_Time_Data_Base& data) noexc
|
||||
}
|
||||
void Renderable_Base::publish_real_time_data() {
|
||||
std::lock_guard lock(real_time_data_mutex_);
|
||||
for (Real_Time_Data_Base* data : real_time_data_) {
|
||||
for (Real_Time_Data_Base* data : real_time_data_)
|
||||
data->publish_render_state();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user