四个方向 分块渲染
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
#include <thread>
|
||||
|
||||
namespace renderive::detail {
|
||||
|
||||
inline constexpr int maximum_render_partitions = 16;
|
||||
|
||||
struct Render_Partition_Range {
|
||||
std::size_t first{};
|
||||
std::size_t last{};
|
||||
};
|
||||
|
||||
inline Render_Partition_Range render_partition_range(std::size_t size,
|
||||
int index,
|
||||
int count) noexcept {
|
||||
if (size == 0 || count <= 0 || index < 0 || index >= count)
|
||||
return {};
|
||||
return {size * static_cast<std::size_t>(index) / static_cast<std::size_t>(count),
|
||||
size * static_cast<std::size_t>(index + 1) / static_cast<std::size_t>(count)};
|
||||
}
|
||||
|
||||
class Adaptive_Render_Partitioner {
|
||||
public:
|
||||
Adaptive_Render_Partitioner() noexcept
|
||||
: automatic_count_(std::clamp(
|
||||
static_cast<int>(std::thread::hardware_concurrency()), 1,
|
||||
maximum_render_partitions)) {}
|
||||
|
||||
int begin(int configured_count, std::size_t work_size) noexcept {
|
||||
automatic_ = configured_count == 0;
|
||||
const int requested = automatic_ ? automatic_count_ : configured_count;
|
||||
const int useful = static_cast<int>(
|
||||
std::min<std::size_t>(maximum_render_partitions,
|
||||
std::max<std::size_t>(1, work_size)));
|
||||
active_count_ = std::clamp(requested, 1,
|
||||
std::min(maximum_render_partitions, useful));
|
||||
started_at_ = Clock::now();
|
||||
return active_count_;
|
||||
}
|
||||
|
||||
void finish(std::size_t work_size) noexcept {
|
||||
if (!automatic_)
|
||||
return;
|
||||
const auto elapsed =
|
||||
std::chrono::duration_cast<std::chrono::microseconds>(Clock::now() - started_at_);
|
||||
constexpr auto target = std::chrono::microseconds(1500);
|
||||
if (elapsed > target * 2 && active_count_ < maximum_render_partitions &&
|
||||
work_size / static_cast<std::size_t>(active_count_) >= 512) {
|
||||
automatic_count_ = std::min(maximum_render_partitions, active_count_ + 1);
|
||||
} else if (elapsed < target / 2 && active_count_ > 1) {
|
||||
automatic_count_ = active_count_ - 1;
|
||||
} else {
|
||||
automatic_count_ = active_count_;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
using Clock = std::chrono::steady_clock;
|
||||
Clock::time_point started_at_{};
|
||||
int automatic_count_{1};
|
||||
int active_count_{1};
|
||||
bool automatic_{true};
|
||||
};
|
||||
|
||||
} // namespace renderive::detail
|
||||
@@ -54,6 +54,35 @@ void Renderable::render(const ::Scene_Render_Context& context) {
|
||||
}
|
||||
}
|
||||
|
||||
void Renderable::build_task_graph(Renderable_Task_Graph& graph) {
|
||||
build_paint_task_graph(graph);
|
||||
}
|
||||
|
||||
void Renderable::build_paint_task_graph(Renderable_Task_Graph& graph) {
|
||||
add_paint_task(graph, "paint", [this](detail::Painter& painter,
|
||||
const Render_State_View& state) {
|
||||
paint(painter, state);
|
||||
});
|
||||
}
|
||||
|
||||
Renderable_Task_Graph::Task Renderable::add_paint_task(
|
||||
Renderable_Task_Graph& graph,
|
||||
std::string name,
|
||||
Paint_Task_Function function) {
|
||||
return graph.emplace(
|
||||
[this, function = std::move(function)](const Scene_Render_Context& context) {
|
||||
if (!is_visible() || context.color_cache == nullptr)
|
||||
return;
|
||||
auto* cache = dynamic_cast<detail::Blend2D_Color_Cache*>(context.color_cache);
|
||||
if (!cache)
|
||||
return;
|
||||
detail::Painter painter(*cache, viewport_size());
|
||||
if (painter)
|
||||
function(painter, render_state_view());
|
||||
},
|
||||
std::move(name));
|
||||
}
|
||||
|
||||
void Renderable::changed() noexcept {
|
||||
invalidate_cache();
|
||||
plot_.notify_model_dirty();
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <renderive/renderable/base/Renderable_Base.hpp>
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
|
||||
@@ -40,11 +41,19 @@ public:
|
||||
void render(const ::Scene_Render_Context& context) final;
|
||||
|
||||
protected:
|
||||
using Paint_Task_Function =
|
||||
std::function<void(detail::Painter&, const Render_State_View&)>;
|
||||
|
||||
virtual void paint(detail::Painter& painter, const Render_State_View& state) = 0;
|
||||
virtual void build_paint_task_graph(Renderable_Task_Graph& graph);
|
||||
Renderable_Task_Graph::Task add_paint_task(Renderable_Task_Graph& graph,
|
||||
std::string name,
|
||||
Paint_Task_Function function);
|
||||
void changed() noexcept;
|
||||
[[nodiscard]] Size viewport_size() const noexcept;
|
||||
|
||||
private:
|
||||
void build_task_graph(Renderable_Task_Graph& graph) final;
|
||||
friend class detail::Renderable_State_Observer;
|
||||
Plot_Core& plot_;
|
||||
mutable std::mutex metadata_mutex_;
|
||||
|
||||
Reference in New Issue
Block a user