Bicameral Engine
GPU-resident engine for a magic-research open-world game
Loading...
Searching...
No Matches
graph_trace.h
Go to the documentation of this file.
1// graph_trace.h — Work Graphs の連鎖のトレース(shaders/common/graph_trace.hlsli)を CPU 側で持つ(T-0087・T-0088、16 §1.3)。
2//
3// データの流れ: 範囲(刻み・場所の箱)を SetFilter で決める(作った時の範囲が最初)→ 次の RecordBegin() がそれを GPU のバッファの見出しへ写す
4// → ノードが GtRecord などで記録を追記する → RecordReadbackAndReset() が slot の読み戻しのバッファへ写して数を 0 に戻す
5// → その slot のリストが終わった後に Read() → 記録の列(atomic の順。比べる前に SortGraphTrace で並べる)。
6// 記録の種類・主・従の意味は使う側が決める(伝導は sim/probe_trace.h)。
7// 容量(1 フレームに書ける記録の数 = バッファの大きさ)は作った時に決め、変えない。範囲は実行中に何度でも変えられる(T-0088)。
8// 範囲が無効のフレームは、シェーダーが見出しの 1 語を読むだけで何も書かず、読み戻しも見出し(64 バイト)だけ。
9//
10// 1 本のコマンドリストの中での使い方:
11// trace.RecordBegin(list, slot); // (範囲が変わっていれば写す)COMMON → UAV
12// list->SetComputeRootUnorderedAccessView(layout.GraphTraceIndex(), trace.GpuAddress());
13// ... DispatchGraph / Dispatch ...
14// trace.RecordReadbackAndReset(list, slot);
15// (slot のリストが終わったら)auto frame = trace.Read(slot);
16#pragma once
17
18#include <array>
19#include <compare>
20#include <cstddef>
21#include <cstdint>
22#include <expected>
23#include <limits>
24#include <span>
25#include <string>
26#include <vector>
27
28#include "common/graph_trace.hlsli"
29#include "gpu/com_ptr.h"
30#include "gpu/readback_ring.h"
31
32namespace bicameral::gpu {
33
34 // 記録する範囲。刻みは [tickBegin, tickEnd)、場所は箱 [boxMin, boxMax)(場所の単位は使う側が決める)
36 bool enabled = false;
37 uint32_t capacity = 0; // 1 フレームに書ける記録の数(有効なときだけ使う。GraphTrace の容量までに切り詰める)
38
39 // --- 範囲 ---
40 uint64_t tickBegin = 0;
41 uint64_t tickEnd = std::numeric_limits<uint64_t>::max();
42 std::array<uint32_t, 3> boxMin = {0, 0, 0};
43 std::array<uint32_t, 3> boxMax = {std::numeric_limits<uint32_t>::max(), std::numeric_limits<uint32_t>::max(),
44 std::numeric_limits<uint32_t>::max()};
45 };
46
48 uint64_t tick = 0;
49 uint32_t kind = 0; // 種類(8bit)
50 uint32_t subject = 0; // 主(24bit)
51 uint32_t object = 0; // 従(32bit)
52
53 // 並べる順 = (刻み, 種類, 主, 従)。atomic の順によらない比べ方の基準
54 friend auto operator<=>(const GraphTraceRecord&, const GraphTraceRecord&) = default;
55 };
56
58 std::vector<GraphTraceRecord> records; // 書けた分(atomic の順)
59 uint32_t droppedCount = 0; // 容量を越えて書けなかった数(> 0 ならトレースは欠けている)
60 };
61
62 // (刻み, 種類, 主, 従)の順に並べる。重なり(同じ記録が複数)は残す
63 void SortGraphTrace(std::vector<GraphTraceRecord>& records);
64
65 class GraphTrace {
66 public:
67 // filter: 最初の範囲。capacity: 1 フレームに書ける記録の上限(バッファの大きさ)。
68 // 容量は max(capacity, 有効なら filter.capacity)。実行中に範囲を変えるなら、使いそうな上限ぶんを capacity に渡す
69 [[nodiscard]] static std::expected<GraphTrace, std::string> Create(ID3D12Device* device,
70 const GraphTraceFilter& filter,
71 uint32_t slotCount = 1,
72 uint32_t capacity = 0);
73
74 // ルートの UAV(u2 space1)に渡すアドレス
75 [[nodiscard]] D3D12_GPU_VIRTUAL_ADDRESS GpuAddress() const { return m_ring.GpuAddress(); }
76 [[nodiscard]] const GraphTraceFilter& Filter() const { return m_filter; } // 次の RecordBegin から使う範囲
77 [[nodiscard]] bool Enabled() const { return m_filter.enabled; }
78 [[nodiscard]] uint32_t Capacity() const { return m_capacity; }
79
80 // 範囲を変える。次の RecordBegin で GPU へ写し、そのリストから効く(容量は Capacity() までに切り詰める)
81 void SetFilter(const GraphTraceFilter& filter);
82
83 // シェーダーが書く前に: (範囲が変わっていれば見出しへ写す)COMMON → UNORDERED_ACCESS。slot は RecordReadbackAndReset と同じ
84 void RecordBegin(ID3D12GraphicsCommandList* list, uint32_t slot = 0);
85
86 // 書いた後に: slot の読み戻しのバッファへ写し(範囲が無効なら見出しだけ)、書こうとした数を 0 に戻す(範囲は残す)。
87 // 最後は COMMON に戻す
88 void RecordReadbackAndReset(ID3D12GraphicsCommandList* list, uint32_t slot = 0) const;
89
90 // slot のリストを GPU が終えた後に呼ぶ(そのリストを記録した時の範囲で読む)
91 [[nodiscard]] std::expected<GraphTraceFrame, std::string> Read(uint32_t slot = 0) const;
92
93 private:
94 GraphTrace(ReadbackRing&& ring, ComPtr<ID3D12Resource> filterUpload, std::byte* filterMapped, uint32_t capacity,
95 uint32_t slotCount)
96 : m_ring(std::move(ring)),
97 m_filterUpload(std::move(filterUpload)),
98 m_filterMapped(filterMapped),
99 m_capacity(capacity),
100 m_slotFilters(slotCount) {}
101
102 // --- GPU ---
104 ComPtr<ID3D12Resource> m_filterUpload; // 範囲の写し元(slot ごとに GT_FILTER_BYTES。Map したまま)
105 std::byte* m_filterMapped = nullptr;
106 uint32_t m_capacity = 0; // 1 フレームに書ける記録の数(作った時に決める)
107
108 // --- 範囲 ---
109 GraphTraceFilter m_filter; // 次の RecordBegin から使う範囲(容量は切り詰め済み)
110 bool m_filterDirty = true; // m_filter をまだ GPU のバッファへ写していない
111 std::vector<GraphTraceFilter> m_slotFilters; // slot のリストを記録した時の範囲(Read と読み戻しの大きさ)
112 };
113
114} // namespace bicameral::gpu
GraphTraceFilter m_filter
const GraphTraceFilter & Filter() const
Definition graph_trace.h:76
void RecordReadbackAndReset(ID3D12GraphicsCommandList *list, uint32_t slot=0) const
void RecordBegin(ID3D12GraphicsCommandList *list, uint32_t slot=0)
D3D12_GPU_VIRTUAL_ADDRESS GpuAddress() const
Definition graph_trace.h:75
uint32_t Capacity() const
Definition graph_trace.h:78
void SetFilter(const GraphTraceFilter &filter)
static std::expected< GraphTrace, std::string > Create(ID3D12Device *device, const GraphTraceFilter &filter, uint32_t slotCount=1, uint32_t capacity=0)
GraphTrace(ReadbackRing &&ring, ComPtr< ID3D12Resource > filterUpload, std::byte *filterMapped, uint32_t capacity, uint32_t slotCount)
Definition graph_trace.h:94
ComPtr< ID3D12Resource > m_filterUpload
std::vector< GraphTraceFilter > m_slotFilters
std::expected< GraphTraceFrame, std::string > Read(uint32_t slot=0) const
void SortGraphTrace(std::vector< GraphTraceRecord > &records)
std::array< uint32_t, 3 > boxMax
Definition graph_trace.h:43
std::array< uint32_t, 3 > boxMin
Definition graph_trace.h:42
std::vector< GraphTraceRecord > records
Definition graph_trace.h:58
friend auto operator<=>(const GraphTraceRecord &, const GraphTraceRecord &)=default