Bicameral Engine
GPU-resident engine for a magic-research open-world game
Loading...
Searching...
No Matches
readback_ring.h
Go to the documentation of this file.
1// readback_ring.h — GPU が追記するバッファを、CPU が待たずに読む仕組み(T-0004、docs/design/06-simulation-loop.md §3)。
2//
3// データの流れ:
4// GPU のバッファ(既定のヒープ)の先頭に見出しがあり、[0] が「書こうとした数」。シェーダーは atomic で空きを取って追記する。
5// コマンドリストの終わりに RecordReadbackAndReset(list, slot) が、バッファを丸ごと読み戻しのバッファ[slot] へ写し、見出しを 0 に戻す。
6// CPU は slot のリストが終わったことをフェンスで知ってから Read(slot) する。終わっていなければ読まずに次のフレームへ(待たない)。
7// 読み戻しのバッファを slot(フレームやバッチの番号 % 数)ごとに持つので、GPU が次を書いている間に前の分を読める。
8// イベント(sim/probe_sim)とシェーダーの printf / assert(gpu/debug_ring)が使う。
9#pragma once
10
11#include <cstddef>
12#include <cstdint>
13#include <expected>
14#include <span>
15#include <string>
16#include <string_view>
17#include <vector>
18
19#include "gpu/com_ptr.h"
20
21namespace bicameral::gpu {
22
24 public:
25 // bytes: バッファ全体の大きさ。headerBytes: 見出しの大きさ(RecordReadbackAndReset がここだけ 0 に戻す)
26 [[nodiscard]] static std::expected<ReadbackRing, std::string> Create(ID3D12Device* device, uint64_t bytes,
27 uint64_t headerBytes, uint32_t slotCount,
28 std::wstring_view name);
29
30 [[nodiscard]] D3D12_GPU_VIRTUAL_ADDRESS GpuAddress() const { return m_buffer->GetGPUVirtualAddress(); }
31 [[nodiscard]] uint32_t SlotCount() const { return static_cast<uint32_t>(m_readbacks.size()); }
32 [[nodiscard]] uint64_t Bytes() const { return m_bytes; }
33 [[nodiscard]] ID3D12Resource* Buffer() const {
34 return m_buffer.Get();
35 } // シェーダーが書くバッファ(見出しの一部を別に書く人向け)
36
37 // シェーダーが書く前に: COMMON → UNORDERED_ACCESS
38 void RecordBegin(ID3D12GraphicsCommandList* list) const;
39
40 // シェーダーが書いた後に: 読み戻しのバッファ[slot] へ先頭から copyBytes(既定は全体)だけ写し、見出しを 0 に戻し、COMMON に戻す
41 void RecordReadbackAndReset(ID3D12GraphicsCommandList* list, uint32_t slot,
42 uint64_t copyBytes = UINT64_MAX) const;
43
44 // slot のリストを GPU が終えた後に呼ぶ。先頭から destination の大きさだけ写す
45 [[nodiscard]] bool Read(uint32_t slot, std::span<std::byte> destination) const;
46
47 private:
48 ReadbackRing() = default;
49
50 ComPtr<ID3D12Resource> m_buffer; // シェーダーが書く(作った時は 0)
51 ComPtr<ID3D12Resource> m_zeros; // 見出しを 0 に戻すための写し元(0 のまま使う)
52 std::vector<ComPtr<ID3D12Resource>> m_readbacks; // CPU が読む(slot ごと)
53 uint64_t m_bytes = 0;
54 uint64_t m_headerBytes = 0;
55 };
56
57} // namespace bicameral::gpu
bool Read(uint32_t slot, std::span< std::byte > destination) const
ComPtr< ID3D12Resource > m_buffer
void RecordBegin(ID3D12GraphicsCommandList *list) const
static std::expected< ReadbackRing, std::string > Create(ID3D12Device *device, uint64_t bytes, uint64_t headerBytes, uint32_t slotCount, std::wstring_view name)
ComPtr< ID3D12Resource > m_zeros
void RecordReadbackAndReset(ID3D12GraphicsCommandList *list, uint32_t slot, uint64_t copyBytes=UINT64_MAX) const
D3D12_GPU_VIRTUAL_ADDRESS GpuAddress() const
std::vector< ComPtr< ID3D12Resource > > m_readbacks
ID3D12Resource * Buffer() const