改进
This commit is contained in:
@@ -104,26 +104,20 @@ bool Render_Graph_Builder::reaches(std::size_t from, std::size_t target) const {
|
||||
std::shared_ptr<const Render_Plan> Render_Plan_History::publish(Render_Graph graph) {
|
||||
normalize(graph);
|
||||
std::lock_guard lock(mutex_);
|
||||
const auto existing = std::find_if(plans_.begin(), plans_.end(), [&graph](const auto& plan) {
|
||||
return same_topology(plan->graph, graph);
|
||||
});
|
||||
if (existing != plans_.end()) {
|
||||
current_ = *existing;
|
||||
return current_;
|
||||
}
|
||||
if (!plans_.empty() && same_topology(plans_.back()->graph, graph))
|
||||
return plans_.back();
|
||||
if (next_version_ == 0 || next_version_ == std::numeric_limits<Render_Plan_Version>::max())
|
||||
throw std::overflow_error("render plan version exhausted");
|
||||
auto plan = std::make_shared<Render_Plan>();
|
||||
plan->version = next_version_++;
|
||||
plan->graph = std::move(graph);
|
||||
plans_.push_back(plan);
|
||||
current_ = plan;
|
||||
return plan;
|
||||
}
|
||||
|
||||
std::shared_ptr<const Render_Plan> Render_Plan_History::current() const {
|
||||
std::lock_guard lock(mutex_);
|
||||
return current_;
|
||||
return plans_.empty() ? nullptr : plans_.back();
|
||||
}
|
||||
|
||||
std::shared_ptr<const Render_Plan> Render_Plan_History::find(Render_Plan_Version version) const {
|
||||
|
||||
@@ -68,7 +68,6 @@ public:
|
||||
private:
|
||||
mutable std::mutex mutex_;
|
||||
std::vector<std::shared_ptr<const Render_Plan>> plans_;
|
||||
std::shared_ptr<const Render_Plan> current_;
|
||||
Render_Plan_Version next_version_{1};
|
||||
};
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -89,8 +88,6 @@ struct Scene_Base::Compiled_Render_Plan {
|
||||
Renderable_Id id{};
|
||||
std::shared_ptr<const Renderable_Graph> graph;
|
||||
std::vector<Renderable_Id> dependency_parent_ids;
|
||||
bool prepare_required{};
|
||||
bool paint_required{};
|
||||
};
|
||||
std::vector<Renderable_Key> renderables;
|
||||
std::vector<Renderable_Id> display_order;
|
||||
@@ -978,9 +975,7 @@ std::shared_ptr<Scene_Base::Compiled_Render_Plan> Scene_Base::compile_render_pla
|
||||
const auto& state = snapshot.renderables[index];
|
||||
if (key.id != state.renderable_id ||
|
||||
key.graph != state.render_graph ||
|
||||
key.dependency_parent_ids != state.dependency_parent_ids ||
|
||||
key.prepare_required != state.prepare_required ||
|
||||
key.paint_required != state.paint_required)
|
||||
key.dependency_parent_ids != state.dependency_parent_ids)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -992,8 +987,7 @@ std::shared_ptr<Scene_Base::Compiled_Render_Plan> Scene_Base::compile_render_pla
|
||||
compiled.renderables.reserve(snapshot.renderables.size());
|
||||
for (const auto& state : snapshot.renderables) {
|
||||
compiled.renderables.push_back({
|
||||
state.renderable_id, state.render_graph, state.dependency_parent_ids,
|
||||
state.prepare_required, state.paint_required});
|
||||
state.renderable_id, state.render_graph, state.dependency_parent_ids});
|
||||
}
|
||||
compiled.display_order = snapshot.display_order;
|
||||
};
|
||||
@@ -1027,16 +1021,10 @@ std::shared_ptr<Scene_Base::Compiled_Render_Plan> Scene_Base::compile_render_pla
|
||||
const auto& state = snapshot.renderables[item.snapshot_index];
|
||||
if (!state.render_graph)
|
||||
throw std::logic_error("frame renderable has no graph snapshot");
|
||||
std::unordered_set<Render_Node_Id> selected;
|
||||
for (const auto& node : state.render_graph->graph.nodes) {
|
||||
if (node.kind == Render_Node_Kind::composite)
|
||||
throw std::logic_error(
|
||||
"renderable graph must not define composite nodes");
|
||||
const bool include = node.kind == Render_Node_Kind::prepare
|
||||
? state.prepare_required
|
||||
: state.paint_required;
|
||||
if (!include)
|
||||
continue;
|
||||
graph.nodes.push_back(node);
|
||||
const auto& render_function =
|
||||
state.render_graph->functions.at(node.execution_index);
|
||||
@@ -1044,30 +1032,22 @@ std::shared_ptr<Scene_Base::Compiled_Render_Plan> Scene_Base::compile_render_pla
|
||||
functions.emplace(node.node_id,
|
||||
Execution_Binding{item.snapshot_index, Execution_Function{function}});
|
||||
}, render_function);
|
||||
selected.insert(node.node_id);
|
||||
}
|
||||
for (const auto& edge : state.render_graph->graph.edges) {
|
||||
if (selected.contains(edge.from) && selected.contains(edge.to))
|
||||
append_edge(edge.from, edge.to);
|
||||
}
|
||||
for (const auto& edge : state.render_graph->graph.edges)
|
||||
append_edge(edge.from, edge.to);
|
||||
const auto stage_boundary = [&](Render_Node_Kind kind, bool roots) {
|
||||
std::vector<Render_Node_Id> result;
|
||||
if ((kind == Render_Node_Kind::prepare &&
|
||||
!state.prepare_required) ||
|
||||
(kind == Render_Node_Kind::paint && !state.paint_required))
|
||||
return result;
|
||||
for (const auto& node : state.render_graph->graph.nodes) {
|
||||
if (node.kind != kind || !selected.contains(node.node_id))
|
||||
if (node.kind != kind)
|
||||
continue;
|
||||
const bool connected = std::any_of(
|
||||
state.render_graph->graph.edges.begin(),
|
||||
state.render_graph->graph.edges.end(),
|
||||
[&](const Render_Edge& edge) {
|
||||
const Render_Node_Id adjacent =
|
||||
roots ? edge.from : edge.to;
|
||||
const Render_Node_Id adjacent = roots ? edge.from : edge.to;
|
||||
const bool matches = roots ? edge.to == node.node_id
|
||||
: edge.from == node.node_id;
|
||||
if (!matches || !selected.contains(adjacent))
|
||||
if (!matches)
|
||||
return false;
|
||||
return std::any_of(
|
||||
state.render_graph->graph.nodes.begin(),
|
||||
@@ -1169,12 +1149,9 @@ std::shared_ptr<Scene_Base::Compiled_Render_Plan> Scene_Base::compile_render_pla
|
||||
throw std::logic_error("render plan node has no execution binding");
|
||||
execution_bindings[node.execution_index] = std::move(function->second);
|
||||
}
|
||||
if (const auto existing = compiled_render_plans_.find(plan->version);
|
||||
existing != compiled_render_plans_.end()) {
|
||||
auto& compiled = *existing->second;
|
||||
update_key(compiled);
|
||||
compiled.execution_bindings = std::move(execution_bindings);
|
||||
compiled_render_plan_ = existing->second;
|
||||
if (compiled_render_plan_ && compiled_render_plan_->plan == plan) {
|
||||
update_key(*compiled_render_plan_);
|
||||
compiled_render_plan_->execution_bindings = std::move(execution_bindings);
|
||||
return compiled_render_plan_;
|
||||
}
|
||||
auto compiled = std::make_shared<Compiled_Render_Plan>();
|
||||
@@ -1183,7 +1160,6 @@ std::shared_ptr<Scene_Base::Compiled_Render_Plan> Scene_Base::compile_render_pla
|
||||
compiled->execution_bindings = std::move(execution_bindings);
|
||||
compiled->runtime = std::make_unique<
|
||||
renderive::render_graph::detail::Render_Graph_Runtime>(*compiled->plan);
|
||||
compiled_render_plans_.emplace(compiled->plan->version, compiled);
|
||||
compiled_render_plan_ = compiled;
|
||||
return compiled;
|
||||
}
|
||||
@@ -1234,6 +1210,8 @@ void Scene_Base::execute_render_graph(Render_Task& task) {
|
||||
case Render_Node_Kind::prepare: {
|
||||
const auto& state = snapshot.renderables.at(
|
||||
binding.renderable_index.value());
|
||||
if (!state.prepare_required)
|
||||
return Node_Execution_Result::completed();
|
||||
std::get<Prepare_Render_Node_Function>(binding.function)(
|
||||
Prepare_Render_Context{snapshot, state, metrics,
|
||||
diagnostics});
|
||||
@@ -1242,6 +1220,8 @@ void Scene_Base::execute_render_graph(Render_Task& task) {
|
||||
case Render_Node_Kind::paint: {
|
||||
const auto& state = snapshot.renderables.at(
|
||||
binding.renderable_index.value());
|
||||
if (!state.paint_required)
|
||||
return Node_Execution_Result::completed();
|
||||
if (!state.paint_buffer_)
|
||||
throw std::logic_error(
|
||||
"paint node has no frame color cache");
|
||||
|
||||
@@ -296,8 +296,6 @@ private:
|
||||
const Render_Node_Id composite_begin_node_id_;
|
||||
const Render_Node_Id scene_render_node_id_;
|
||||
Render_Plan_History render_plan_history_;
|
||||
std::unordered_map<Render_Plan_Version, std::shared_ptr<Compiled_Render_Plan>>
|
||||
compiled_render_plans_;
|
||||
std::shared_ptr<Compiled_Render_Plan> compiled_render_plan_;
|
||||
Capture_Controller capture_controller_;
|
||||
Capture_Repository capture_repository_;
|
||||
|
||||
@@ -54,11 +54,12 @@ TEST(render_dag_test, one_graph_assigns_dense_execution_slots_and_versions_only_
|
||||
changed_graph.edges.push_back({100, 101});
|
||||
const auto changed = history.publish(std::move(changed_graph));
|
||||
EXPECT_GT(changed->version, first->version);
|
||||
const auto reused = history.publish(make_parallel_graph());
|
||||
EXPECT_EQ(reused, first);
|
||||
EXPECT_EQ(history.current(), first);
|
||||
const auto restored = history.publish(make_parallel_graph());
|
||||
EXPECT_GT(restored->version, changed->version);
|
||||
EXPECT_EQ(history.current(), restored);
|
||||
EXPECT_EQ(history.find(first->version), first);
|
||||
EXPECT_EQ(history.find(changed->version), changed);
|
||||
EXPECT_EQ(history.find(restored->version), restored);
|
||||
}
|
||||
|
||||
TEST(render_dag_test, analysis_derives_wait_critical_path_and_parallel_overlap_from_frame_slots) {
|
||||
|
||||
@@ -191,7 +191,7 @@ TEST(render_plan_execution_test, dependent_prepare_does_not_wait_for_dependency_
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(render_plan_execution_test, prepare_and_paint_cache_validity_are_independent_and_prune_nodes) {
|
||||
TEST(render_plan_execution_test, prepare_and_paint_cache_validity_do_not_recompile_render_plan) {
|
||||
Scene2D_Context<> scene;
|
||||
auto renderable = renderive_Owner<Pipeline_Renderable>::make(true);
|
||||
attach_initial(scene, renderable);
|
||||
@@ -199,6 +199,8 @@ TEST(render_plan_execution_test, prepare_and_paint_cache_validity_are_independen
|
||||
scene.wait_for_render();
|
||||
EXPECT_TRUE(renderable->prepare_cache_valid_for_test());
|
||||
EXPECT_TRUE(renderable->paint_cache_valid_for_test());
|
||||
EXPECT_EQ(renderable->prepare_count.load(), 1);
|
||||
EXPECT_EQ(renderable->paint_count.load(), 1);
|
||||
const auto first_plan = scene.render_plan_snapshot();
|
||||
const Render_Node_Id prepare_id = node(*first_plan, renderable->renderable_id(),
|
||||
Render_Node_Kind::prepare).node_id;
|
||||
@@ -208,12 +210,13 @@ TEST(render_plan_execution_test, prepare_and_paint_cache_validity_are_independen
|
||||
scene.render();
|
||||
scene.wait_for_render();
|
||||
const auto cached_plan = scene.render_plan_snapshot();
|
||||
EXPECT_GT(cached_plan->version, first_plan->version);
|
||||
EXPECT_EQ(std::count_if(cached_plan->graph.nodes.begin(), cached_plan->graph.nodes.end(),
|
||||
[&](const Render_Node& value) {
|
||||
return value.owner_id == renderable->renderable_id() &&
|
||||
value.kind != Render_Node_Kind::composite;
|
||||
}), 0);
|
||||
EXPECT_EQ(cached_plan, first_plan);
|
||||
EXPECT_EQ(renderable->prepare_count.load(), 1);
|
||||
EXPECT_EQ(renderable->paint_count.load(), 1);
|
||||
EXPECT_EQ(node(*cached_plan, renderable->renderable_id(), Render_Node_Kind::prepare).node_id,
|
||||
prepare_id);
|
||||
EXPECT_EQ(node(*cached_plan, renderable->renderable_id(), Render_Node_Kind::paint).node_id,
|
||||
paint_id);
|
||||
|
||||
renderable->invalidate_paint_for_test();
|
||||
EXPECT_TRUE(renderable->prepare_cache_valid_for_test());
|
||||
@@ -221,14 +224,13 @@ TEST(render_plan_execution_test, prepare_and_paint_cache_validity_are_independen
|
||||
scene.render();
|
||||
scene.wait_for_render();
|
||||
const auto paint_plan = scene.render_plan_snapshot();
|
||||
EXPECT_GT(paint_plan->version, cached_plan->version);
|
||||
EXPECT_EQ(paint_plan, first_plan);
|
||||
EXPECT_EQ(renderable->prepare_count.load(), 1);
|
||||
EXPECT_EQ(renderable->paint_count.load(), 2);
|
||||
EXPECT_EQ(node(*paint_plan, renderable->renderable_id(), Render_Node_Kind::prepare).node_id,
|
||||
prepare_id);
|
||||
EXPECT_EQ(node(*paint_plan, renderable->renderable_id(), Render_Node_Kind::paint).node_id,
|
||||
paint_id);
|
||||
EXPECT_EQ(std::count_if(paint_plan->graph.nodes.begin(), paint_plan->graph.nodes.end(),
|
||||
[&](const Render_Node& value) {
|
||||
return value.owner_id == renderable->renderable_id() &&
|
||||
value.kind == Render_Node_Kind::prepare;
|
||||
}), 0);
|
||||
|
||||
renderable->invalidate_prepare_for_test();
|
||||
EXPECT_FALSE(renderable->prepare_cache_valid_for_test());
|
||||
@@ -236,7 +238,9 @@ TEST(render_plan_execution_test, prepare_and_paint_cache_validity_are_independen
|
||||
scene.render();
|
||||
scene.wait_for_render();
|
||||
const auto rebuilt_plan = scene.render_plan_snapshot();
|
||||
EXPECT_GT(rebuilt_plan->version, paint_plan->version);
|
||||
EXPECT_EQ(rebuilt_plan, first_plan);
|
||||
EXPECT_EQ(renderable->prepare_count.load(), 2);
|
||||
EXPECT_EQ(renderable->paint_count.load(), 3);
|
||||
EXPECT_EQ(node(*rebuilt_plan, renderable->renderable_id(), Render_Node_Kind::prepare).node_id,
|
||||
prepare_id);
|
||||
EXPECT_EQ(node(*rebuilt_plan, renderable->renderable_id(), Render_Node_Kind::paint).node_id,
|
||||
|
||||
Reference in New Issue
Block a user