载入中...
搜索中...
未找到
PointGraphPlan.cpp
浏览该文件的文档.
2
3#include <algorithm>
4#include <functional>
5
6namespace eve::procgen {
7
8void PointGraph::invalidateTopology(const std::string& changedNode) {
9 for (auto it = executionPlans_.begin(); it != executionPlans_.end();) {
10 const auto& nodes = it->second->topologicalOrder;
11 if (std::find(nodes.begin(), nodes.end(), changedNode) == nodes.end()) {
12 ++it;
13 continue;
14 }
15 if (executionPlan_ == it->second) executionPlan_.reset();
16 std::erase(executionPlanRecency_, it->first);
17 it = executionPlans_.erase(it);
18 }
19}
20
21Result<void> PointGraph::compileExecutionPlan(const std::string& outputId) {
22 if (const auto found = executionPlans_.find(outputId); found != executionPlans_.end()) {
23 executionPlan_ = found->second;
24 std::erase(executionPlanRecency_, outputId);
25 executionPlanRecency_.push_back(outputId);
26 return Result<void>::success();
27 }
28 executionPlan_.reset();
29
30 ExecutionPlan plan;
31 std::unordered_map<std::string, int> states;
32 std::function<Result<void>(const std::string&)> visit = [&](const std::string& id) -> Result<void> {
33 if (states[id] == 2) return Result<void>::success();
34 if (states[id] == 1) {
36 Diagnostic::error(DiagnosticCode::Conflict, "cycle at node: " + id, id, {}, "procgen.pointGraph"));
37 }
38 const auto found = nodes_.find(id);
39 if (found == nodes_.end()) {
41 Diagnostic::error(DiagnosticCode::NotFound, "unknown node: " + id, id, {}, "procgen.pointGraph"));
42 }
43 states[id] = 1;
44 const int inputCount = getOperationInputCount(found->second.operation);
45 for (int input = 0; input < inputCount; ++input) {
46 if (found->second.inputs[input].empty()) {
49 found->second.operation + " requires input " + std::to_string(input) + ": " + id,
50 id, {}, "procgen.pointGraph"));
51 }
52 auto result = visit(found->second.inputs[input]);
53 if (!result.ok()) return result;
54 }
55 states[id] = 2;
56 plan.topologicalOrder.push_back(id);
57 return Result<void>::success();
58 };
59 auto visited = visit(outputId);
60 if (!visited.ok()) return visited;
61
62 std::unordered_map<std::string, std::vector<std::string>> consumers;
63 for (const std::string& id : plan.topologicalOrder) {
64 const Node& node = nodes_.at(id);
65 for (const std::string& input : node.inputs)
66 if (!input.empty() && states[input] == 2) consumers[input].push_back(id);
67 }
68 std::unordered_map<std::string, bool> assigned;
69 for (const std::string& id : plan.topologicalOrder) {
70 if (assigned[id]) continue;
71 ExecutionSegment segment;
72 segment.nodes.push_back(id);
73 assigned[id] = true;
74 std::string cursor = id;
75 while (segment.nodes.size() < 4 && nodes_.at(cursor).operation == "transform" &&
76 consumers[cursor].size() == 1) {
77 const std::string& next = consumers[cursor].front();
78 if (assigned[next] || nodes_.at(next).operation != "transform") break;
79 segment.nodes.push_back(next);
80 assigned[next] = true;
81 cursor = next;
82 }
83 segment.gpuTransformChain = segment.nodes.size() >= 2 && nodes_.at(id).operation == "transform";
84 const std::size_t segmentIndex = plan.segments.size();
85 if (segment.gpuTransformChain) plan.segmentByOutput.emplace(segment.nodes.back(), segmentIndex);
86 plan.segments.push_back(std::move(segment));
87 }
88 executionPlan_ = std::make_shared<const ExecutionPlan>(std::move(plan));
89 executionPlans_.emplace(outputId, executionPlan_);
90 executionPlanRecency_.push_back(outputId);
91 constexpr std::size_t maximumCachedPlans = 16;
92 if (executionPlanRecency_.size() > maximumCachedPlans) {
93 executionPlans_.erase(executionPlanRecency_.front());
94 executionPlanRecency_.erase(executionPlanRecency_.begin());
95 }
96 ++executionPlanBuildCount_;
97 return Result<void>::success();
98}
99
100} // namespace eve::procgen
EvpackChunkInput input
Definition Evpack.cpp:170
int inputs
Definition GridGraph.cpp:23
std::vector< BvhNode > nodes
std::string id
Definition PlayHost.cpp:108
const RoadNode * node
bool found
std::size_t cursor
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
Definition Diagnostic.h:125
static Result success(T value)
Construct a successful result owning value.
Definition Result.h:164
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
static int getOperationInputCount(const std::string &operation)
Returns the operation input count.
constexpr HexDirection next(HexDirection d) noexcept
The next direction clockwise (NW wraps to NE).
Definition HexMetrics.h:76