Bicameral Engine
GPU-resident engine for a magic-research open-world game
Loading...
Searching...
No Matches
probe_trace.h
Go to the documentation of this file.
1// probe_trace.h — 伝導の連鎖のトレース(GPU の記録。shaders/common/graph_trace.hlsli)を刻みごとの木に組む・CPU リファレンスの予想と比べる・
2// CPU リファレンスと食い違った最初の刻み・ブロック・セルを探す(T-0087、16 §1.3・§3)。
3//
4// データの流れ:
5// ProbeSim(範囲を ProbeSimOptions::trace に)→ ProbeFrameReadback::trace(atomic の順)→ 集めて gpu::SortGraphTrace
6// → FormatProbeTrace(刻みごとの木の文字列。ファイルへ)/ UniqueProbeTrace と ExpectedProbeTrace を比べる(CPU リファレンス)
7// ハッシュの列(ProbeTickHash)→ FirstDivergentTick → その刻みの GPU の状態(抽出)と CPU の状態 → FindCellDivergence
8//
9// 記録の種類は probe_sim.hlsli の PROBE_TRACE_*(つつき・起こす・計算した)。木の組み方:
10// 刻み t の根 = 活性の一覧のブロック(起こすの主)。つつき(刻み t)か、刻み t − 1 で値が変わったブロック
11// 根の子 = 起こされて計算したブロック。複数の根に起こされたブロックの親は「一番小さい番号の根」(GPU で誰が先に予定したかは
12// 毎回変わるので、決まった規則で選ぶ)。値が変わった子は、刻み t + 1 の根になる。
13// 浮動小数点は使わない(engine/src/sim は検査の対象。04 §4)。
14#pragma once
15
16#include <array>
17#include <cstdint>
18#include <expected>
19#include <optional>
20#include <span>
21#include <string>
22#include <vector>
23
24#include "core/aliases.h"
25#include "gpu/graph_trace.h"
26#include "sim/probe_sim.h"
27
28namespace bicameral::sim {
29
30 // --- 範囲 ---
31
32 // セルの箱 [cellMin, cellMax) と刻み [tickBegin, tickEnd) を、トレースの範囲(場所はブロックの座標。セルを含むブロックを全部)にする
33 [[nodiscard]] gpu::GraphTraceFilter ProbeTraceFilterForCells(uint64_t tickBegin, uint64_t tickEnd,
34 std::array<uint32_t, 3> cellMin,
35 std::array<uint32_t, 3> cellMax, uint32_t capacity);
36
37 // --- 木にする ---
38
39 // 並べた記録(gpu::SortGraphTrace の後)を刻みごとの木の文字列にする(1 刻み = 見出しの行 + 根ごとの行 + 子ごとの行)
40 [[nodiscard]] std::string FormatProbeTrace(std::span<const gpu::GraphTraceRecord> sorted);
41
42 // 集めた記録(順不同)を並べて木にし、範囲と落とした数の見出しを付けてファイル(UTF-8)に書く
43 [[nodiscard]] std::expected<void, std::string> WriteProbeTraceFile(const fs::path& path,
44 std::vector<gpu::GraphTraceRecord> records,
45 const gpu::GraphTraceFilter& filter,
46 uint64_t droppedCount);
47
48 // --- CPU リファレンスと比べる ---
49
50 // 並べて重なりを除く(活性の一覧には同じブロックが 2 度入りうる。CPU リファレンスは重なりを数えないので、比べるときはこの形)
51 [[nodiscard]] std::vector<gpu::GraphTraceRecord> UniqueProbeTrace(std::vector<gpu::GraphTraceRecord> records);
52
53 // CPU リファレンスが予想する刻み tick の記録(重なりなし)を expected に足す。
54 // flagsBefore = 刻み tick − 1 のブロックごとの結果(0 でなければ一覧に足された)、flagsAfter = 刻み tick の結果(計算の記録の値)。
55 // どちらも ProbeReference::BlockFlags(PROBE_BLOCK_FLAG_* の組み合わせ)
56 void AppendExpectedProbeTrace(const gpu::GraphTraceFilter& filter, uint64_t tick,
57 std::span<const ProbeCommand> commands, std::span<const uint8_t> flagsBefore,
58 std::span<const uint8_t> flagsAfter, std::vector<gpu::GraphTraceRecord>& expected);
59
60 // 並べた 2 つの列の最初の食い違い(無ければ nullopt)。「刻み t: GPU … / CPU …」の 1 行
61 [[nodiscard]] std::optional<std::string> FirstProbeTraceMismatch(std::span<const gpu::GraphTraceRecord> gpu,
62 std::span<const gpu::GraphTraceRecord> cpu);
63
64 // --- 食い違いの場所(16 §3 の道具の最初の形)---
65
66 // 刻みの順の 2 つの列で、同じ刻みのハッシュ(とエネルギーの合計)が違う最初の状態の刻み(S(t) の t)。無ければ nullopt
67 [[nodiscard]] std::optional<uint64_t> FirstDivergentTick(std::span<const ProbeTickHash> gpu,
68 std::span<const ProbeTickHash> cpu);
69
71 uint64_t tick = 0; // 状態 S(tick)
72
73 // --- 最初に食い違ったブロック(番号の小さい順)とその中の最初のセル(ブロックの中の z, y, x の順)---
74 uint32_t block = 0;
75 std::array<uint32_t, 3> cell = {0, 0, 0};
76 uint32_t gpuValue = 0; // そのセルの温度(mK)
77 uint32_t cpuValue = 0;
78
79 // --- 広がり ---
80 uint32_t differingCells = 0;
81 uint32_t differingBlocks = 0;
82 };
83
84 // 同じ刻みの全部のセルの抽出の語(PROBE_CELL_COUNT × PROBE_EXTRACTION_CELL_WORDS 個。温度と見る物質 3 つ。
85 // CPU は MakeProbeExtractionCells)を比べる。全部同じなら nullopt
86 [[nodiscard]] std::optional<ProbeDivergence> FindCellDivergence(uint64_t tick, std::span<const uint32_t> gpuCells,
87 std::span<const uint32_t> cpuCells);
88
89 // 「S(t) で CPU リファレンスと食い違った: ブロック … セル (x, y, z) GPU … CPU …(食い違ったセル n・ブロック m)」
90 [[nodiscard]] std::string FormatProbeDivergence(const ProbeDivergence& divergence);
91
92} // namespace bicameral::sim
std::optional< ProbeDivergence > FindCellDivergence(uint64_t tick, std::span< const uint32_t > gpuCells, std::span< const uint32_t > cpuCells)
std::optional< uint64_t > FirstDivergentTick(std::span< const ProbeTickHash > gpu, std::span< const ProbeTickHash > cpu)
void AppendExpectedProbeTrace(const gpu::GraphTraceFilter &filter, uint64_t tick, std::span< const ProbeCommand > commands, std::span< const uint8_t > flagsBefore, std::span< const uint8_t > flagsAfter, std::vector< gpu::GraphTraceRecord > &expected)
std::string FormatProbeDivergence(const ProbeDivergence &divergence)
std::vector< gpu::GraphTraceRecord > UniqueProbeTrace(std::vector< gpu::GraphTraceRecord > records)
std::string FormatProbeTrace(std::span< const gpu::GraphTraceRecord > sorted)
std::optional< std::string > FirstProbeTraceMismatch(std::span< const gpu::GraphTraceRecord > gpu, std::span< const gpu::GraphTraceRecord > cpu)
std::expected< void, std::string > WriteProbeTraceFile(const fs::path &path, std::vector< gpu::GraphTraceRecord > records, const gpu::GraphTraceFilter &filter, uint64_t droppedCount)
gpu::GraphTraceFilter ProbeTraceFilterForCells(uint64_t tickBegin, uint64_t tickEnd, std::array< uint32_t, 3 > cellMin, std::array< uint32_t, 3 > cellMax, uint32_t capacity)
std::array< uint32_t, 3 > cell
Definition probe_trace.h:75