Bicameral Engine
GPU-resident engine for a magic-research open-world game
Loading...
Searching...
No Matches
gpu_multires_implicit.cpp
Go to the documentation of this file.
1// gpu_multires_implicit.cpp — GPU の伝導の段から呼ぶ陰解法(T-0132)。何をするかは gpu_multires_implicit.h。
2// 段の間は各段の記録が入れる UAV のバリア(GpuMultires・GpuImplicit とも全体の UAV のバリア)。
4
5#include <utility>
6
7using namespace bicameral::multires;
8
9namespace bicameral::sim {
10
11 namespace {
12
13 // 木の陰解法と同じ選択(multires_implicit_conduction.cpp の MakeImplicitOptions。ADR-0019): V(2,2)・新しい温度の誤差の見込み 1 mK で止める
15 ImplicitOptions implicit;
17 implicit.cycles = options.implicitMaxCycles;
18 implicit.toleranceMillikelvin = 1;
19
20 return implicit;
21 }
22
23 } // namespace
24
25 std::expected<GpuMultiresImplicit, std::string> GpuMultiresImplicit::Create(
26 ID3D12Device5* device, const GpuMultires& multires, const MultiresCapacity& capacity,
27 const GpuMultiresImplicitLimits& limits) {
28 if (limits.unknowns == 0 || limits.cells == 0 || limits.nodes == 0 || limits.links == 0)
29 return std::unexpected("陰解法の上限は全部の欄が要る(T-0178)");
30
31 // --- 系を作る段のバッファは予算の大きさ(未知数 ≤ 隣 / 12・セル ≤ 節。段 0 がいつも入る)---
33 auto build = GpuImplicitBuild::Create(device, multires, capacity,
34 {.unknowns = budget.unknowns, .cells = budget.cells});
35 if (!build)
36 return std::unexpected(build.error());
37
38 // 多重格子の段は既定の積み方(全部 Dispatch。LvTail は release の WARP でデバイスが失われる。T-0147)
39 GpuImplicitLevelLimits levelLimits;
40 levelLimits.nodes = limits.nodes;
41 levelLimits.links = limits.links;
42 auto levels = GpuImplicitLevels::Create(device, *build, levelLimits);
43 if (!levels)
44 return std::unexpected(levels.error());
45
46 const GpuImplicitLimits solveLimits{.cells = budget.cells,
47 .faces = MR_FACES * budget.unknowns,
48 .nodes = limits.nodes,
49 .links = limits.links,
50 .levels = levelLimits.levels};
51 auto implicit = GpuImplicit::Create(device, solveLimits);
52 if (!implicit)
53 return std::unexpected(implicit.error());
54
55 return GpuMultiresImplicit(std::move(*build), std::move(*levels), std::move(*implicit));
56 }
57
58 void GpuMultiresImplicit::RecordAdmit(ID3D12GraphicsCommandList10* list, D3D12_GPU_VIRTUAL_ADDRESS debugRing,
59 GpuMultires& multires, const MultiresStepOptions& options) {
60 FX_ASSERT(options.implicitOverflow == ImplicitOverflow::Explicit); // B・C は未実装(Q22)
61 m_build.RecordAdmit(list, debugRing, multires, options);
62 }
63
64 void GpuMultiresImplicit::Record(ID3D12GraphicsCommandList10* list, D3D12_GPU_VIRTUAL_ADDRESS debugRing,
65 GpuMultires& multires, const MultiresStepOptions& options) {
66 // --- 記録の形は前の刻みの数から(初めの刻みは上限まで積む)---
67 GpuImplicitCost previous;
68 const bool known = m_recorded && m_implicit.ReadCost(previous);
70
71 // --- 系を作る(凍った印を見る)→ 多重格子の段 → 写す ---
72 const auto stamp = [&](uint32_t phase) {
73 if (m_stampPhases)
74 multires.RecordTimestamp(list, PHASE_STAMP_FIRST + phase);
75 };
76 stamp(0);
77 m_build.RecordBuild(list, debugRing, multires, options, true, true);
78 stamp(1);
79 m_levels.RecordBuild(list, debugRing, m_build);
80 m_implicit.RecordReset(list);
81 m_build.RecordCopyTo(list, m_implicit);
82 m_levels.RecordCopyTo(list, m_implicit);
83
84 // --- 1 刻み解いて、解いた変化を伝導の表へ ---
85 stamp(2);
86 [[maybe_unused]] const bool recorded = m_implicit.RecordStep(list, debugRing, TreeImplicitOptions(options),
88 FX_ASSERT(recorded);
89 stamp(3);
90 m_build.RecordApply(list, debugRing, multires, options, m_implicit.CellsBuffer());
91 stamp(4);
92
93 // --- 次の刻みの形のための数を読み戻し、バッファを COMMON に戻す(同じリストの次の刻みが RecordReset できるように)---
94 m_implicit.RecordCostReadback(list);
95 m_implicit.RecordRelease(list);
96 m_recorded = true;
97 }
98
99} // namespace bicameral::sim
static std::expected< GpuImplicitBuild, std::string > Create(ID3D12Device5 *device, const GpuMultires &multires, const MultiresCapacity &capacity, const GpuImplicitBuildLimits &limits)
static std::expected< GpuImplicitLevels, std::string > Create(ID3D12Device5 *device, const GpuImplicitBuild &build, const GpuImplicitLevelLimits &limits)
static constexpr uint32_t DEFAULT_MAX_LIMIT_ROUNDS
static std::expected< GpuImplicit, std::string > Create(ID3D12Device5 *device, const GpuImplicitLimits &limits, const GpuImplicitTuning &tuning={})
static GpuImplicitRecordShape ShapeFrom(const GpuImplicitCost &previous)
void RecordAdmit(ID3D12GraphicsCommandList10 *list, D3D12_GPU_VIRTUAL_ADDRESS debugRing, GpuMultires &multires, const MultiresStepOptions &options)
static constexpr uint32_t PHASE_STAMP_FIRST
static std::expected< GpuMultiresImplicit, std::string > Create(ID3D12Device5 *device, const GpuMultires &multires, const MultiresCapacity &capacity, const GpuMultiresImplicitLimits &limits)
GpuMultiresImplicit(GpuImplicitBuild build, GpuImplicitLevels levels, GpuImplicit implicit)
void Record(ID3D12GraphicsCommandList10 *list, D3D12_GPU_VIRTUAL_ADDRESS debugRing, GpuMultires &multires, const MultiresStepOptions &options)
ImplicitOptions TreeImplicitOptions(const MultiresStepOptions &options)
constexpr MultiresImplicitBudget MakeMultiresImplicitBudget(const MultiresImplicitLimits &limits)
MultiresImplicitLimits GpuMultiresImplicitLimits