Bicameral Engine
GPU-resident engine for a magic-research open-world game
Loading...
Searching...
No Matches
queue.h
Go to the documentation of this file.
1// queue.h — コマンドキューと、そのキューが進めるフェンス(T-0004)。
2// フレームのループはこれで「投げる」「別のキューを GPU の上で待たせる」「終わったかを待たずに見る」だけをする(06 §4)。
3// CPU が GPU を待つ WaitCpu() は、起動・終了・窓の大きさの変更のときだけ使う。
4//
5// auto compute = Queue::Create(device, D3D12_COMMAND_LIST_TYPE_COMPUTE, L"Sim");
6// const uint64_t done = compute->Submit(list); // 終わるとフェンスが done になる
7// direct->GpuWait(*compute, done); // direct キューは compute の done まで先へ進まない(CPU は待たない)
8// if (compute->IsComplete(done)) ... // 待たずに見る
9#pragma once
10
11#include <cstdint>
12#include <expected>
13#include <span>
14#include <string>
15#include <string_view>
16
17#include "gpu/com_ptr.h"
18
19namespace bicameral::gpu {
20
21 class Queue {
22 public:
23 // priority: 描画のキューは HIGH にする(重いシミュと並ぶときに描画が先に進みやすい。docs/perf.md 2026-09-30 T-0004)
24 [[nodiscard]] static std::expected<Queue, std::string> Create(
25 ID3D12Device* device, D3D12_COMMAND_LIST_TYPE type, std::wstring_view name,
26 D3D12_COMMAND_QUEUE_PRIORITY priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL);
27
28 [[nodiscard]] ID3D12CommandQueue* Native() const { return m_queue.Get(); }
29
30 // リストを投げてフェンスを進める。返り値はこれらのリストが終わったときのフェンスの値
31 uint64_t Submit(std::span<ID3D12CommandList* const> lists);
32 uint64_t Submit(ID3D12CommandList* list) { return Submit(std::span(&list, 1)); }
33
34 // フェンスを進めずに投げる(1 つの仕事を何回かの投入に分けるとき。最後の 1 回を Submit にすれば、その値で全部の終わりが分かる)
35 void Execute(ID3D12CommandList* list) const;
36
37 // このキューは other のフェンスが value になるまで先へ進まない(GPU の上で待つ。CPU は待たない)
38 void GpuWait(const Queue& other, uint64_t value) const;
39
40 // 最後に Submit() したときの値と、GPU が終えた値(待たない)
41 [[nodiscard]] uint64_t LastSubmitted() const { return m_lastSubmitted; }
42 [[nodiscard]] uint64_t CompletedValue() const { return m_fence->GetCompletedValue(); }
43 [[nodiscard]] bool IsComplete(uint64_t value) const { return CompletedValue() >= value; }
44
45 // デバイスが失われるとフェンスは UINT64_MAX を返す
46 [[nodiscard]] bool IsDeviceLost() const { return CompletedValue() == UINT64_MAX; }
47
48 // CPU で value まで待つ(起動・終了・大きさの変更のときだけ)。デバイスが失われたら false
49 bool WaitCpu(uint64_t value) const;
50 bool WaitIdle() const { return WaitCpu(m_lastSubmitted); }
51
52 // Present のようにフェンスの後ろに積まれた仕事も含めて、今までに投げた全部を待つ(フェンスを 1 つ進めてから待つ)。
53 // バックバッファを作り直す前・終わる前に使う
54 bool Flush() { return WaitCpu(Submit(std::span<ID3D12CommandList* const>{})); }
55
56 // タイムスタンプの 1 秒あたりの刻み。取れなければ 0
57 [[nodiscard]] uint64_t TimestampFrequency() const;
58
59 private:
60 Queue() = default;
61
62 ComPtr<ID3D12CommandQueue> m_queue;
63 ComPtr<ID3D12Fence> m_fence;
64 uint64_t m_lastSubmitted = 0;
65 };
66
67} // namespace bicameral::gpu
bool WaitCpu(uint64_t value) const
Definition queue.cpp:49
ComPtr< ID3D12CommandQueue > m_queue
Definition queue.h:62
uint64_t LastSubmitted() const
Definition queue.h:41
uint64_t TimestampFrequency() const
Definition queue.cpp:63
bool IsComplete(uint64_t value) const
Definition queue.h:43
static std::expected< Queue, std::string > Create(ID3D12Device *device, D3D12_COMMAND_LIST_TYPE type, std::wstring_view name, D3D12_COMMAND_QUEUE_PRIORITY priority=D3D12_COMMAND_QUEUE_PRIORITY_NORMAL)
Definition queue.cpp:10
void Execute(ID3D12CommandList *list) const
Definition queue.cpp:38
void GpuWait(const Queue &other, uint64_t value) const
Definition queue.cpp:42
bool WaitIdle() const
Definition queue.h:50
uint64_t CompletedValue() const
Definition queue.h:42
ID3D12CommandQueue * Native() const
Definition queue.h:28
uint64_t Submit(std::span< ID3D12CommandList *const > lists)
Definition queue.cpp:28
ComPtr< ID3D12Fence > m_fence
Definition queue.h:63
uint64_t Submit(ID3D12CommandList *list)
Definition queue.h:32
bool IsDeviceLost() const
Definition queue.h:46
uint64_t m_lastSubmitted
Definition queue.h:64