Bicameral Engine
GPU-resident engine for a magic-research open-world game
Loading...
Searching...
No Matches
readback_ring.cpp
Go to the documentation of this file.
1// readback_ring.cpp — 待たない読み戻し(T-0004)。使い方は readback_ring.h。
2#include "gpu/readback_ring.h"
3
4#include <algorithm>
5
6#include "gpu/com_ptr.h"
7#include "gpu/resources.h"
8
9namespace bicameral::gpu {
10
11 std::expected<ReadbackRing, std::string> ReadbackRing::Create(ID3D12Device* device, uint64_t bytes,
12 uint64_t headerBytes, uint32_t slotCount,
13 std::wstring_view name) {
14 ReadbackRing ring;
15 ring.m_bytes = bytes;
16 ring.m_headerBytes = headerBytes;
18 ring.m_zeros = CreateBuffer(device, headerBytes, BufferKind::UnorderedAccess);
19 if (!ring.m_buffer || !ring.m_zeros)
20 return std::unexpected("読み戻しのリングのバッファを作れない");
21
22 ring.m_buffer->SetName(std::wstring(name).c_str());
23 ring.m_zeros->SetName((std::wstring(name) + L".zeros").c_str());
24 for (uint32_t slot = 0; slot < slotCount; ++slot) {
25 ComPtr<ID3D12Resource> readback = CreateBuffer(device, bytes, BufferKind::Readback);
26 if (!readback)
27 return std::unexpected("読み戻しのリングの読み戻しのバッファを作れない");
28
29 readback->SetName(std::format(L"{}.readback{}", name, slot).c_str());
30 ring.m_readbacks.push_back(std::move(readback));
31 }
32
33 return ring;
34 }
35
36 void ReadbackRing::RecordBegin(ID3D12GraphicsCommandList* list) const {
37 const D3D12_RESOURCE_BARRIER barrier = Transition(m_buffer.Get(), D3D12_RESOURCE_STATE_COMMON,
38 D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
39 list->ResourceBarrier(1, &barrier);
40 }
41
42 void ReadbackRing::RecordReadbackAndReset(ID3D12GraphicsCommandList* list, uint32_t slot,
43 uint64_t copyBytes) const {
44 ID3D12Resource* buffer = m_buffer.Get();
45 const D3D12_RESOURCE_BARRIER toCopySource = Transition(buffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
46 D3D12_RESOURCE_STATE_COPY_SOURCE);
47 list->ResourceBarrier(1, &toCopySource);
48 list->CopyBufferRegion(m_readbacks[slot].Get(), 0, buffer, 0, std::min(copyBytes, m_bytes));
49
50 const D3D12_RESOURCE_BARRIER toCopyDest = Transition(buffer, D3D12_RESOURCE_STATE_COPY_SOURCE,
51 D3D12_RESOURCE_STATE_COPY_DEST);
52 list->ResourceBarrier(1, &toCopyDest);
53 list->CopyBufferRegion(buffer, 0, m_zeros.Get(), 0, m_headerBytes); // 書こうとした数を 0 に
54
55 // COMMON に戻す: 次のリストが同じ ExecuteCommandLists の中でも RecordBegin() から始められるように
56 const D3D12_RESOURCE_BARRIER toCommon = Transition(buffer, D3D12_RESOURCE_STATE_COPY_DEST,
57 D3D12_RESOURCE_STATE_COMMON);
58 list->ResourceBarrier(1, &toCommon);
59 }
60
61 bool ReadbackRing::Read(uint32_t slot, std::span<std::byte> destination) const {
62 return ReadBuffer(m_readbacks[slot].Get(), destination);
63 }
64
65} // 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
std::vector< ComPtr< ID3D12Resource > > m_readbacks
bool ReadBuffer(ID3D12Resource *readback, std::span< std::byte > destination)
Definition resources.cpp:52
D3D12_RESOURCE_BARRIER Transition(ID3D12Resource *resource, D3D12_RESOURCE_STATES before, D3D12_RESOURCE_STATES after)
Definition resources.cpp:65
ComPtr< ID3D12Resource > CreateBuffer(ID3D12Device *device, uint64_t sizeBytes, BufferKind kind)
Definition resources.cpp:18