Bicameral Engine
GPU-resident engine for a magic-research open-world game
Loading...
Searching...
No Matches
table_hot_reload.h
Go to the documentation of this file.
1// table_hot_reload.h — 反応表のホットリロードを、世界の刻みの境界へつなぐ(T-0139・ADR-0047・13 §2)。
2//
3// データの流れ(フレームのループ frame/frame_loop が毎フレーム呼ぶ):
4// Poll(数フレームごと): script::ReactionTableHotReload がファイルの変更を見て読み直す(型検査 → ベイク → 物質の一覧が同じか)
5// → 読めたら「当てたい表」として待つ。落ちたら古い表のまま、誤りをエディタに出す(LastMessage)
6// → TakeSwaps(シミュのリストを記録するフレーム): 適用の単位があるフレームなら、その刻みに差し替えの印のコマンド
7// (sim::MakeTableCommand。版を持つ)を足し、表を sim::ProbeFrameInput::tableSwaps で渡す
8// → 記録(--record)はコマンドの列に印が入る。再生(--replay)は印の版の表を、知っている表(起動時の表と読み直した表)から探して
9// 同じ刻みに当てる(持っていなければ止まる。表の中身を再生ファイルに入れるのは T-0193)。
10// CPU は表(法則のデータ)をベイクして渡すだけで、世界の状態は GPU が新しい表で作り直す(原則 1・ADR-0047)。
11#pragma once
12
13#include <cstdint>
14#include <expected>
15#include <map>
16#include <memory>
17#include <optional>
18#include <span>
19#include <string>
20#include <vector>
21
24#include "sim/probe_sim.h"
25
26namespace bicameral::frame {
27
29 public:
30 // watch: ファイルを見るか(エディタ。再生中は見ない)。initial は起動時に読んだ表
31 TableHotReload(script::ReactionTableSource source, std::shared_ptr<const script::LoadedReactionTable> initial,
32 bool watch);
33
34 // 数フレームごとにファイルを見る(読み直しはこのスレッドで同期。エディタのフレームが 1 回止まる)
35 void Poll(uint64_t frameNumber);
36
37 // このフレームの単位 [firstUnit, firstUnit + unitCount)(通しの単位の番号)で当てる差し替え。
38 // 生の操作(再生でない): 待っている表があり、このフレームに適用の単位 applyTick があれば、印のコマンドを commands に足す
39 // (sequence は nextSequence から。commands は (targetTick, sequence) の順に並べ直す。canAddCommand でなければ次のフレームへ)。
40 // 再生: commands の中の印を予定に積む(版を知らなければ error)。返す差し替えはこのフレームの分だけ
41 [[nodiscard]] std::expected<std::vector<sim::ProbeTableSwap>, std::string> TakeSwaps(
42 uint64_t firstUnit, uint32_t unitCount, uint32_t unitsPerTick, bool replaying, bool canAddCommand,
43 uint32_t& nextSequence, std::vector<sim::ProbeCommand>& commands);
44
45 // 当てた表(差し替えの後に GPU が使っている表。表示用)と、最後の読み直しの結果
46 [[nodiscard]] uint64_t AppliedVersion() const { return m_appliedVersion; }
47 [[nodiscard]] uint32_t AppliedCount() const { return m_appliedCount; }
48 [[nodiscard]] uint32_t FailedCount() const { return m_failedCount; }
49 [[nodiscard]] bool Watching() const { return m_reload.has_value(); }
50 [[nodiscard]] bool Waiting() const { return m_waiting != nullptr; }
51 [[nodiscard]] const std::string& LastMessage() const { return m_lastMessage; }
52 [[nodiscard]] bool LastFailed() const { return m_lastFailed; }
53
54 private:
55 struct Scheduled {
56 uint64_t tick = 0;
57 std::shared_ptr<const script::LoadedReactionTable> table;
58 };
59
60 void Remember(const std::shared_ptr<const script::LoadedReactionTable>& table);
61 [[nodiscard]] std::expected<void, std::string> ScheduleReplayed(std::span<const sim::ProbeCommand> commands);
62
63 std::optional<script::ReactionTableHotReload> m_reload; // watch のときだけ
64 std::map<uint64_t, std::shared_ptr<const script::LoadedReactionTable>> m_known; // 版 → 表(再生が探す)
65 std::shared_ptr<const script::LoadedReactionTable> m_waiting; // 読めて、まだ当てていない表
66 std::vector<Scheduled> m_scheduled; // 印を GPU のキューへ足した、まだ記録していない差し替え(刻みの順)
67 std::vector<std::shared_ptr<const script::LoadedReactionTable>>
68 m_inFlight; // 返した差し替えの表(RecordFrame が写すまで)
69
70 uint64_t m_appliedVersion = 0;
71 uint32_t m_appliedCount = 0;
72 uint32_t m_failedCount = 0;
73 std::string m_lastMessage;
74 bool m_lastFailed = false;
75 };
76
77} // namespace bicameral::frame
const std::string & LastMessage() const
std::vector< Scheduled > m_scheduled
std::map< uint64_t, std::shared_ptr< const script::LoadedReactionTable > > m_known
void Poll(uint64_t frameNumber)
std::expected< std::vector< sim::ProbeTableSwap >, std::string > TakeSwaps(uint64_t firstUnit, uint32_t unitCount, uint32_t unitsPerTick, bool replaying, bool canAddCommand, uint32_t &nextSequence, std::vector< sim::ProbeCommand > &commands)
std::optional< script::ReactionTableHotReload > m_reload
void Remember(const std::shared_ptr< const script::LoadedReactionTable > &table)
TableHotReload(script::ReactionTableSource source, std::shared_ptr< const script::LoadedReactionTable > initial, bool watch)
std::shared_ptr< const script::LoadedReactionTable > m_waiting
std::expected< void, std::string > ScheduleReplayed(std::span< const sim::ProbeCommand > commands)
std::vector< std::shared_ptr< const script::LoadedReactionTable > > m_inFlight
std::shared_ptr< const script::LoadedReactionTable > table