内核优化
This commit is contained in:
@@ -15,6 +15,15 @@ public:
|
||||
return executor;
|
||||
}
|
||||
};
|
||||
class Scene_Base::Render_Execution_Scope {
|
||||
public:
|
||||
explicit Render_Execution_Scope(Scene_Base& scene) noexcept : previous_(std::exchange(active_execution_scene_, &scene)) {}
|
||||
~Render_Execution_Scope() {
|
||||
active_execution_scene_ = previous_;
|
||||
}
|
||||
private:
|
||||
Scene_Base* previous_{};
|
||||
};
|
||||
Scene_Base::Scene_Base() : Scene_Base(*std::pmr::get_default_resource()) {}
|
||||
Scene_Base::Scene_Base(std::pmr::memory_resource& upstream_memory_resource)
|
||||
: scene_lifetime_(std::make_shared<Scene_Lifetime>(*this)), memory_domain_(std::allocate_shared<Scene_Memory_Domain>(std::pmr::polymorphic_allocator<Scene_Memory_Domain>(&upstream_memory_resource), upstream_memory_resource)), renderable_states_{Renderable_List(&memory_domain_->resource()), Renderable_List(&memory_domain_->resource())}, render_renderables_(&renderable_states_[0]), cache_renderables_(&renderable_states_[1]), task_(memory_domain_->resource()) {
|
||||
@@ -26,7 +35,19 @@ Scene_Base::~Scene_Base() {
|
||||
shutdown();
|
||||
}
|
||||
void Scene_Base::render() {
|
||||
if (active_submitted_observer_scene_ == this) {
|
||||
std::lock_guard<std::recursive_mutex> lock(task_mutex_);
|
||||
++deferred_render_count_;
|
||||
return;
|
||||
}
|
||||
auto task_lock = lock_render_idle();
|
||||
if (pending_exception_observed_) {
|
||||
pending_exception_ = nullptr;
|
||||
pending_exception_observed_ = false;
|
||||
}
|
||||
if (!pending_exception_ && current_completion_ && current_completion_->completed && current_completion_->exception && !current_completion_->observed) {
|
||||
pending_exception_ = current_completion_->exception;
|
||||
}
|
||||
Render_Task task(memory_resource());
|
||||
{
|
||||
std::lock_guard<std::mutex> renderable_lock(renderable_mutex_);
|
||||
@@ -41,14 +62,25 @@ void Scene_Base::render() {
|
||||
task.render_sequence = ++render_sequence_;
|
||||
task.completion = std::make_shared<Render_Completion>();
|
||||
current_completion_ = task.completion;
|
||||
observe_scene({Observation_Event::render_submitted, observer_now_ns(), task.render_sequence, task.scene_state_revision, task.render_order.size()});
|
||||
const Observation submitted_observation{Observation_Event::render_submitted, observer_now_ns(), task.render_sequence, task.scene_state_revision, task.render_order.size()};
|
||||
task_ = std::move(task);
|
||||
task_pending_ = true;
|
||||
task_lock.unlock();
|
||||
Scene_Base* previous_observer_scene = std::exchange(active_submitted_observer_scene_, this);
|
||||
observe_scene(submitted_observation);
|
||||
active_submitted_observer_scene_ = previous_observer_scene;
|
||||
task_ready_.notify_one();
|
||||
std::size_t deferred_render_count{};
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(task_mutex_);
|
||||
deferred_render_count = std::exchange(deferred_render_count_, 0);
|
||||
}
|
||||
for (std::size_t index = 0; index < deferred_render_count; ++index) {
|
||||
render();
|
||||
}
|
||||
}
|
||||
void Scene_Base::wait_for_render() {
|
||||
if (is_render_worker_thread()) {
|
||||
if (is_render_worker_thread() || active_submitted_observer_scene_ == this) {
|
||||
return;
|
||||
}
|
||||
std::unique_lock<std::recursive_mutex> lock(task_mutex_);
|
||||
@@ -59,7 +91,17 @@ void Scene_Base::wait_for_render() {
|
||||
render_completed_.wait(lock, [&completion] {
|
||||
return completion->completed;
|
||||
});
|
||||
const auto exception = completion->exception;
|
||||
std::exception_ptr exception;
|
||||
if (pending_exception_) {
|
||||
exception = pending_exception_;
|
||||
pending_exception_observed_ = true;
|
||||
if (!completion->exception) {
|
||||
completion->observed = true;
|
||||
}
|
||||
} else {
|
||||
exception = completion->exception;
|
||||
completion->observed = true;
|
||||
}
|
||||
lock.unlock();
|
||||
if (exception) {
|
||||
std::rethrow_exception(exception);
|
||||
@@ -218,6 +260,12 @@ std::uint64_t Scene_Base::observer_now_ns() const noexcept {
|
||||
return 0;
|
||||
}
|
||||
std::unique_lock<std::recursive_mutex> Scene_Base::lock_render_idle() {
|
||||
if (is_render_worker_thread()) {
|
||||
throw std::logic_error("scene control mutation is not allowed during render execution");
|
||||
}
|
||||
if (active_submitted_observer_scene_ == this) {
|
||||
throw std::logic_error("scene control mutation is not allowed during render submission observation");
|
||||
}
|
||||
std::unique_lock<std::recursive_mutex> lock(task_mutex_);
|
||||
render_completed_.wait(lock, [this] {
|
||||
return !task_pending_ && !rendering_;
|
||||
@@ -225,7 +273,7 @@ std::unique_lock<std::recursive_mutex> Scene_Base::lock_render_idle() {
|
||||
return lock;
|
||||
}
|
||||
bool Scene_Base::is_render_worker_thread() const noexcept {
|
||||
return worker_.joinable() && std::this_thread::get_id() == worker_.get_id();
|
||||
return active_execution_scene_ == this || (worker_.joinable() && std::this_thread::get_id() == worker_.get_id());
|
||||
}
|
||||
void Scene_Base::shutdown() noexcept {
|
||||
{
|
||||
@@ -323,7 +371,8 @@ void Scene_Base::execute_taskflow(Render_Task& task) {
|
||||
std::pmr::vector<tf::Task> internal_tasks(&scratch_resource);
|
||||
internal_tasks.reserve(nodes.size());
|
||||
for (const auto& node : nodes) {
|
||||
internal_tasks.push_back(module.graph.emplace([function = node.function, context] {
|
||||
internal_tasks.push_back(module.graph.emplace([this, function = node.function, context] {
|
||||
Render_Execution_Scope scope(*this);
|
||||
function(context);
|
||||
}).name(std::string(node.name)));
|
||||
}
|
||||
@@ -359,6 +408,7 @@ void Scene_Base::execute_taskflow(Render_Task& task) {
|
||||
}
|
||||
const Scene_Render_Context final_context{this, task.frame_control_state, task.scene_state_revision, task.render_sequence, nullptr, nullptr};
|
||||
tf::Task final_task = scene_graph.emplace([this, final_context, &task] {
|
||||
Render_Execution_Scope scope(*this);
|
||||
generate_final_color_cache(final_context, task.display_order);
|
||||
}).name("final_color_cache");
|
||||
if (modules.empty()) {
|
||||
|
||||
Reference in New Issue
Block a user