Bicameral Engine
GPU-resident engine for a magic-research open-world game
Loading...
Searching...
No Matches
gpu_implicit_build.h
Go to the documentation of this file.
1// gpu_implicit_build.h — 細かいレベルの熱の陰解法(方式②。ADR-0019)の系を GPU の木から作る(T-0129)。
2// 作るもの: 未知数(基準より細かい本物のブロックのセル)・境のセル・面(係数・粗い側の端数の枠)・セルの面の一覧。
3// 番号の付け方は CPU リファレンス(multires_implicit_conduction.cpp の MakeSystem と gpu_implicit.cpp の MakeCellFaces)と同じなので、
4// 作った系は GpuImplicit の同じバッファの並びにそのまま写せる(RecordCopyTo)。段の中身は shaders/sim/implicit_build.hlsl。
5// 多重格子の段と重みは GpuImplicitLevels(T-0134)がこの系から作る。GPU の伝導の段から呼ぶ形は GpuMultiresImplicit(T-0132)。
6//
7// 使い方(テスト):
8// auto build = GpuImplicitBuild::Create(device, multires, nest.capacity, limits);
9// multires.RecordUpload(list, nest); // 系を作る時の木(陰解法を入れる刻みの、陽解法の流れの後)
10// build->RecordBuild(list, ring, multires, options); → build->RecordReadback(list) / build->RecordCopyTo(list, implicit)
11// GpuMultires のルート署名で投げる(外のバッファ u4・u5 を自分の作業場と系に結ぶ)。Dispatch の数は上限から決める(間接の引数は T-0135)。
12#pragma once
13
14#include <array>
15#include <cstdint>
16#include <expected>
17#include <string>
18#include <vector>
19
20#include "common/implicit_conduction.hlsli"
21#include "gpu/com_ptr.h"
22#include "sim/gpu_implicit.h"
23#include "sim/gpu_multires.h"
24#include "sim/multires_nest.h"
25
26namespace bicameral::sim {
27
28 // 作る系の大きさの上限(バッファの大きさ。超えたら作った系の overflow が立つ)
30 uint32_t unknowns = 0; // 未知数のセル(面は 6 倍まで)
31 uint32_t cells = 0; // 未知数 + 境のセル
32 };
33
34 // GPU が作った系(読み戻し。並びは GpuImplicit の BufferCells・BufferFaces・BufferLists の先頭と同じ)
36 uint32_t unknowns = 0;
37 uint32_t boundary = 0;
38 uint32_t faces = 0;
39 bool overflow = false;
40 std::vector<multires::ImGpuCell> cells;
41 std::vector<multires::ImGpuFace> faceList;
42 std::vector<uint32_t> lists; // セルの面の一覧(面の番号 × 2 + 粗い側なら 1)
43 };
44
46 public:
47 static constexpr uint32_t MAX_TIMESTAMPS = 32;
48
49 [[nodiscard]] static std::expected<GpuImplicitBuild, std::string> Create(ID3D12Device5* device,
50 const GpuMultires& multires,
51 const MultiresCapacity& capacity,
52 const GpuImplicitBuildLimits& limits);
53
54 // 系を作る。木は multires のバッファ(呼ぶ側が写すか刻んである)。凍った印(TreeExpand が付ける)を見るのは useFrozenMarks の時だけ
55 // (見る時は multires の刻みの印〔SetTick〕がその刻みのものであること。T-0132)
56 // afterAdmit: 同じ刻みに RecordAdmit を投げてある(Clear〜ScanBlocks を飛ばす。useFrozenMarks の時だけ)
57 void RecordBuild(ID3D12GraphicsCommandList10* list, D3D12_GPU_VIRTUAL_ADDRESS debugRing, GpuMultires& multires,
58 const MultiresStepOptions& options, bool useFrozenMarks = false, bool afterAdmit = false);
59
60 // 伝導の段の流れの前(T-0178): Clear → CountBlocks → ScanBlocks で、系に入れるブロックを枠の順に上限(作った時の limits =
61 // 予算)の中まで選び、陰解法の印を付ける。凍った印を見る。同じ刻みの後で RecordBuild(…, true, true)
62 void RecordAdmit(ID3D12GraphicsCommandList10* list, D3D12_GPU_VIRTUAL_ADDRESS debugRing, GpuMultires& multires,
63 const MultiresStepOptions& options);
64
65 // GpuImplicit が解いたセル(solvedCells = GpuImplicit::CellsBuffer。UAV の状態)の「足した後 − 刻みの初め」を multires の伝導の
66 // 変化の表へ足し、活性の刻みならそのブロックを伝導の一覧へ(T-0132。RecordBuild と同じ刻みの印・定数で、伝導の段の流れの後に)
67 void RecordApply(ID3D12GraphicsCommandList10* list, D3D12_GPU_VIRTUAL_ADDRESS debugRing, GpuMultires& multires,
68 const MultiresStepOptions& options, ID3D12Resource* solvedCells);
69
70 // 作った系を GpuImplicit のセル・面・面の一覧へ写す(GpuImplicit の RecordUpload の後。数は GpuImplicit を作った系と同じこと)
71 void RecordCopyTo(ID3D12GraphicsCommandList* list, GpuImplicit& implicit);
72
73 // 計測用: true なら RecordBuild が段ごとにタイムスタンプ(段 i の前に i、最後の段の後に段の数)を打つ
74 void StampPasses(bool stamp) { m_stampPasses = stamp; }
75 [[nodiscard]] static uint32_t StageCount();
76 [[nodiscard]] static const char* StageName(uint32_t pass);
77
78 void RecordTimestamp(ID3D12GraphicsCommandList* list, uint32_t index);
79 void RecordReadback(ID3D12GraphicsCommandList* list);
80 [[nodiscard]] std::expected<GpuImplicitSystem, std::string> Read() const;
81 [[nodiscard]] std::vector<uint64_t> ReadTimestamps(uint32_t count) const;
82
83 // --- 多重格子の段を作る段(GpuImplicitLevels。T-0134)が読むもの ---
84 [[nodiscard]] const GpuImplicitBuildLimits& Limits() const { return m_limits; }
85 [[nodiscard]] ID3D12Resource* WorkBuffer() const { return m_work.Get(); }
86 [[nodiscard]] ID3D12Resource* SystemBuffer() const { return m_system.Get(); }
87 [[nodiscard]] uint64_t FacesOffset() const;
88 [[nodiscard]] uint64_t ListsOffset() const;
89 [[nodiscard]] uint32_t ListCellsWord() const; // 作業場の「面の一覧の位置のセル」の始まり(語)
90 [[nodiscard]] uint32_t CellKeysWord() const; // 作業場のセルの座標の始まり(語。8 語 / セル)
91
92 private:
93 GpuImplicitBuild() = default;
94
95 // implicit_build.hlsl の段 [firstPass, endPass) を投げる
96 void RecordPasses(ID3D12GraphicsCommandList10* list, D3D12_GPU_VIRTUAL_ADDRESS debugRing, GpuMultires& multires,
97 const MultiresStepOptions& options, bool useFrozenMarks, uint32_t firstPass,
98 uint32_t endPass);
99 [[nodiscard]] std::array<uint32_t, 4> ExternalConstants(const MultiresStepOptions& options,
100 bool useFrozenMarks) const;
101
103 uint32_t m_worldBlocks = 0;
104 uint64_t m_workBytes = 0;
105 uint64_t m_systemBytes = 0;
106
107 std::vector<ComPtr<ID3D12PipelineState>> m_pipelines; // implicit_build.hlsl の段の順
108 ComPtr<ID3D12PipelineState> m_applyPipeline; // 解いた変化を伝導の表へ(BuildApply。T-0132)
109 ComPtr<ID3D12Resource> m_work; // u4 作業場
110 ComPtr<ID3D12Resource> m_system; // u5 系
111 ComPtr<ID3D12Resource> m_workReadback;
112 ComPtr<ID3D12Resource> m_systemReadback;
113 ComPtr<ID3D12QueryHeap> m_timestamps;
114 ComPtr<ID3D12Resource> m_timestampReadback;
115 uint32_t m_timestampCount = 0;
116 bool m_stampPasses = false;
117 };
118
119} // namespace bicameral::sim
ComPtr< ID3D12Resource > m_workReadback
static constexpr uint32_t MAX_TIMESTAMPS
void RecordAdmit(ID3D12GraphicsCommandList10 *list, D3D12_GPU_VIRTUAL_ADDRESS debugRing, GpuMultires &multires, const MultiresStepOptions &options)
ComPtr< ID3D12Resource > m_system
std::vector< uint64_t > ReadTimestamps(uint32_t count) const
ID3D12Resource * SystemBuffer() const
void RecordReadback(ID3D12GraphicsCommandList *list)
void RecordApply(ID3D12GraphicsCommandList10 *list, D3D12_GPU_VIRTUAL_ADDRESS debugRing, GpuMultires &multires, const MultiresStepOptions &options, ID3D12Resource *solvedCells)
ComPtr< ID3D12PipelineState > m_applyPipeline
ComPtr< ID3D12QueryHeap > m_timestamps
static std::expected< GpuImplicitBuild, std::string > Create(ID3D12Device5 *device, const GpuMultires &multires, const MultiresCapacity &capacity, const GpuImplicitBuildLimits &limits)
const GpuImplicitBuildLimits & Limits() const
void RecordPasses(ID3D12GraphicsCommandList10 *list, D3D12_GPU_VIRTUAL_ADDRESS debugRing, GpuMultires &multires, const MultiresStepOptions &options, bool useFrozenMarks, uint32_t firstPass, uint32_t endPass)
std::expected< GpuImplicitSystem, std::string > Read() const
static const char * StageName(uint32_t pass)
void RecordTimestamp(ID3D12GraphicsCommandList *list, uint32_t index)
ComPtr< ID3D12Resource > m_timestampReadback
void RecordCopyTo(ID3D12GraphicsCommandList *list, GpuImplicit &implicit)
std::vector< ComPtr< ID3D12PipelineState > > m_pipelines
ID3D12Resource * WorkBuffer() const
std::array< uint32_t, 4 > ExternalConstants(const MultiresStepOptions &options, bool useFrozenMarks) const
void RecordBuild(ID3D12GraphicsCommandList10 *list, D3D12_GPU_VIRTUAL_ADDRESS debugRing, GpuMultires &multires, const MultiresStepOptions &options, bool useFrozenMarks=false, bool afterAdmit=false)
ComPtr< ID3D12Resource > m_systemReadback
std::vector< multires::ImGpuCell > cells
std::vector< multires::ImGpuFace > faceList