Bicameral Engine
GPU-resident engine for a magic-research open-world game
Loading...
Searching...
No Matches
gpu_implicit_levels.h
Go to the documentation of this file.
1// gpu_implicit_levels.h — 細かいレベルの熱の陰解法(方式②。ADR-0019)の多重格子の段と重みを GPU で作る(T-0134)。
2// 入力は GpuImplicitBuild(T-0129)が作った系(セル・面・セルの面の一覧)とセルの座標。CPU リファレンスは implicit_conduction.cpp の
3// BuildImplicitGrid(段 0 = セル → 最も細かいレベルの節を親のセルへ縮約 → 重み〔128bit の割り算〕→ 重み < 1/2 の節がある間は次の段)。
4// 作るもの(節 ImGpuNode・隣 ImGpuLink・子の一覧)は GpuImplicit の段の形と同じ並び・同じ番号なので、そのまま写して解ける(RecordCopyTo)。
5// 段の数は値で決まる: 回は limits.dispatchRounds 回だけ Dispatch で積み、要らない回は述語(SetPredication)で飛ばす。小さい段の回と残りの回は
6// 1 グループの LvTail が最後まで回す(T-0135)。段の中身は shaders/sim/implicit_levels.hlsl。
7// 見出し(段の数・段ごとの節の始まりと数)も GpuImplicit の計画へ写し、GpuImplicit はそこから V サイクルの形を決める(T-0136)。
8//
9// 使い方(テスト):
10// auto levels = GpuImplicitLevels::Create(device, build, limits);
11// build.RecordBuild(...); levels->RecordBuild(list, ring, build); → levels->RecordReadback(list) / levels->RecordCopyTo(list, implicit)
12#pragma once
13
14#include <cstdint>
15#include <expected>
16#include <string>
17#include <vector>
18
19#include "common/implicit_conduction.hlsli"
20#include "gpu/com_ptr.h"
21#include "sim/gpu_implicit.h"
23
24namespace bicameral::sim {
25
26 // 作る段の大きさの上限(バッファの大きさ。超えたら overflow が立つ)
28 uint32_t nodes = 0; // 全部の段の節
29 uint32_t links = 0; // 全部の段の隣
30 uint32_t levels = 64; // 段の数(CPU の MAX_GRID_LEVELS。回はこれ − 1 回まで)
31
32 // --- 回の積み方(T-0135。計測で選ぶ。docs/perf.md)---
33 // Dispatch で積む回の数。残りの回と、細かい段の節が tailMaxNodes 以下の回は 1 グループの LvTail が最後まで回す
34 // (段ごとの Dispatch とバリアが要らない)。既定(dispatchRounds ≥ levels − 1・tailMaxNodes = 0)は T-0134 と同じ積み方で、LvTail を積まない。
35 // LvTail は HW で CPU とビット一致するが、WARP で落ちる(デバイスが失われる。T-0135)ので、WARP で直すまで(T-0147)既定にしない
36 uint32_t dispatchRounds = 63;
37 uint32_t tailMaxNodes = 0;
38 };
39
40 // GpuImplicit の段の形の像(CPU の ImplicitGrid から。比べる用。gpu_implicit.cpp の MakeNodes と同じ)
42 std::vector<uint32_t> levelOffsets; // 段ごとの節の始まり(段の数 + 1)
43 std::vector<multires::ImGpuNode> nodes;
44 std::vector<multires::ImGpuLink> links;
45 std::vector<uint32_t> children; // 子の一覧(GpuImplicit の面の一覧の後ろの部分)
46 };
47
49
50 // GPU が作った段(読み戻し)
52 bool overflow = false;
54 std::vector<uint32_t> linkOffsets; // 段ごとの隣の始まり(段の数 + 1)
55 };
56
58 public:
59 static constexpr uint32_t MAX_TIMESTAMPS = 8;
60
61 [[nodiscard]] static std::expected<GpuImplicitLevels, std::string> Create(ID3D12Device5* device,
62 const GpuImplicitBuild& build,
63 const GpuImplicitLevelLimits& limits);
64
65 // build が作った系から段を作る(build.RecordBuild の後)
66 void RecordBuild(ID3D12GraphicsCommandList* list, D3D12_GPU_VIRTUAL_ADDRESS debugRing,
67 const GpuImplicitBuild& build);
68
69 // 作った節・隣・子の一覧を GpuImplicit へ写す(GpuImplicit の RecordUpload の後。形は GpuImplicit を作った系と同じこと)
70 void RecordCopyTo(ID3D12GraphicsCommandList* list, GpuImplicit& implicit);
71
72 void RecordTimestamp(ID3D12GraphicsCommandList* list, uint32_t index);
73 void RecordReadback(ID3D12GraphicsCommandList* list);
74 [[nodiscard]] std::expected<GpuImplicitLevelSystem, std::string> Read() const;
75 [[nodiscard]] std::vector<uint64_t> ReadTimestamps(uint32_t count) const;
76
77 // 1 回の RecordBuild に積む Dispatch の数(計測の表に使う)
78 [[nodiscard]] uint32_t DispatchCount() const;
79
80 private:
81 GpuImplicitLevels() = default;
82
83 struct Constants {
84 uint32_t maxCells = 0;
85 uint32_t maxNodes = 0;
86 uint32_t maxLinks = 0;
87 uint32_t levelLinks = 0;
88 uint32_t depth = 0;
89 uint32_t maxLevels = 0;
90 uint32_t nodeTableMask = 0;
91 uint32_t linkTableMask = 0;
92 uint32_t keysWord = 0;
93 uint32_t listCellsWord = 0;
94 uint32_t facesByte = 0;
95 uint32_t listsByte = 0;
96 uint32_t tailMaxNodes = 0;
97 };
98
99 void Dispatch(ID3D12GraphicsCommandList* list, uint32_t pass, uint32_t groups);
100 [[nodiscard]] bool UsesTail() const; // LvTail を積むか(Dispatch で積まない回があるか、小さい段を任せるか)
101 void BeginSkippable(ID3D12GraphicsCommandList* list, uint32_t coarsening);
102 void EndSkippable(ID3D12GraphicsCommandList* list);
103
105 uint32_t m_dispatchRounds = 0; // Dispatch で積む回の数(残りは LvTail)
106 uint64_t m_workBytes = 0;
107
108 ComPtr<ID3D12RootSignature> m_rootSignature;
109 std::vector<ComPtr<ID3D12PipelineState>> m_pipelines; // implicit_levels.hlsl の段の順
110 ComPtr<ID3D12Resource> m_work;
111 ComPtr<ID3D12Resource> m_nodes;
112 ComPtr<ID3D12Resource> m_links;
113 ComPtr<ID3D12Resource> m_children;
114 ComPtr<ID3D12Resource> m_predicate;
115 ComPtr<ID3D12Resource> m_headerReadback;
116 ComPtr<ID3D12Resource> m_nodesReadback;
117 ComPtr<ID3D12Resource> m_linksReadback;
118 ComPtr<ID3D12Resource> m_childrenReadback;
119 ComPtr<ID3D12QueryHeap> m_timestamps;
120 ComPtr<ID3D12Resource> m_timestampReadback;
121 uint32_t m_timestampCount = 0;
122 };
123
124} // namespace bicameral::sim
void BeginSkippable(ID3D12GraphicsCommandList *list, uint32_t coarsening)
static constexpr uint32_t MAX_TIMESTAMPS
ComPtr< ID3D12Resource > m_childrenReadback
void EndSkippable(ID3D12GraphicsCommandList *list)
void RecordCopyTo(ID3D12GraphicsCommandList *list, GpuImplicit &implicit)
static std::expected< GpuImplicitLevels, std::string > Create(ID3D12Device5 *device, const GpuImplicitBuild &build, const GpuImplicitLevelLimits &limits)
ComPtr< ID3D12Resource > m_timestampReadback
ComPtr< ID3D12Resource > m_linksReadback
ComPtr< ID3D12Resource > m_headerReadback
std::vector< ComPtr< ID3D12PipelineState > > m_pipelines
void RecordReadback(ID3D12GraphicsCommandList *list)
std::expected< GpuImplicitLevelSystem, std::string > Read() const
void RecordTimestamp(ID3D12GraphicsCommandList *list, uint32_t index)
void RecordBuild(ID3D12GraphicsCommandList *list, D3D12_GPU_VIRTUAL_ADDRESS debugRing, const GpuImplicitBuild &build)
ComPtr< ID3D12RootSignature > m_rootSignature
void Dispatch(ID3D12GraphicsCommandList *list, uint32_t pass, uint32_t groups)
ComPtr< ID3D12Resource > m_nodesReadback
ComPtr< ID3D12QueryHeap > m_timestamps
std::vector< uint64_t > ReadTimestamps(uint32_t count) const
GpuImplicitLevelImages MakeGpuImplicitLevelImages(const ImplicitGrid &grid)
std::vector< multires::ImGpuLink > links
std::vector< multires::ImGpuNode > nodes