Bicameral Engine
GPU-resident engine for a magic-research open-world game
Loading...
Searching...
No Matches
device.h
Go to the documentation of this file.
1// device.h — D3D12 のデバイスを作る(T-0013)。検証とデバイス喪失の調べ方(debug layer・GPU-based validation・DRED)も付ける(T-0003)。
2// 本物の GPU(一番速いハードウェアのアダプタ)か WARP(ソフトウェアの D3D12)を選べる。
3// WARP は GPU の無い機械(CI)でも GPU のテストを回すため(docs/design/16-debug-test.md §4)。
4//
5// 検証(docs/design/16-debug-test.md §1):
6// debug layer の報告は ID3D12InfoQueue1 のコールバックでログ(Channel::Gpu)へ流し、エラーの数を数える(テストはこれが 0 であることも見る)。
7// DRED(自動のブレッドクラムとページフォールト)は、デバイスが失われたとき LogDeviceRemoved() がログに出す。
8// どれも debug プリセット(BICAMERAL_GPU_VALIDATION)で既定で有効。プロセス全体の設定なので、最初のデバイスを作る前に決まる。
9// d3d12.h などは pch.h から来る(このヘッダを include する .cpp は pch.h を使う)。
10#pragma once
11
12#include <atomic>
13#include <cstdint>
14#include <expected>
15#include <memory>
16#include <string>
17
18#include "gpu/com_ptr.h"
19
20namespace bicameral::gpu {
21
22 enum class AdapterKind : uint8_t {
23 Hardware, // 描画する画面を持つアダプタ → 無ければ高性能の順に並べて最初の、条件を満たすアダプタ
24 Warp, // ソフトウェアの D3D12(OS の d3d10warp.dll)
25 };
26
27 [[nodiscard]] const char* AdapterKindName(AdapterKind kind);
28
30 bool debugLayer = false; // D3D12 の debug layer。報告をログへ流す
31 bool gpuBasedValidation = false; // GPU で走る検証(遅い)。debugLayer が要る
32 bool dred = false; // デバイス喪失の記録(自動のブレッドクラム・ページフォールト)
33 // 描画する画面(窓がある画面。MonitorFromWindow)。この画面をつないでいるアダプタを優先する。
34 // 同じ GPU が別の LUID で 2 回列挙されることがあり(片方は画面を持たない)、画面を持たない方で描くと
35 // Present のたびにアダプタをまたぐ写しが入るため(T-0004)。nullptr なら高性能の順だけで選ぶ(テスト)
36 HMONITOR presentMonitor = nullptr;
37 };
38
39 // ビルドの既定: BICAMERAL_GPU_VALIDATION(debug プリセット)なら全部有効、それ以外は全部無効
40 [[nodiscard]] DeviceOptions DefaultDeviceOptions();
41
42 class Device {
43 public:
44 // 失敗の理由は文字列で返す(Error として出すか、テストの失敗にするかは呼ぶ側が決める)
45 [[nodiscard]] static std::expected<Device, std::string> Create(
46 AdapterKind kind, const DeviceOptions& options = DefaultDeviceOptions());
47
48 [[nodiscard]] ID3D12Device5* Get() const { return m_device.Get(); }
49 [[nodiscard]] IDXGIFactory6* Factory() const { return m_factory.Get(); } // スワップチェインを作るとき
50 [[nodiscard]] const DeviceOptions& Options() const { return m_options; }
51
52 // debug layer が出したエラー(ERROR と CORRUPTION)と警告の数。debug layer が無効なら常に 0
53 [[nodiscard]] uint32_t ValidationErrorCount() const;
54 [[nodiscard]] uint32_t ValidationWarningCount() const;
55
56 private:
57 // debug layer のコールバックに渡す数え先。コールバックが登録されている間は動かさない(Device を動かしても同じ場所)
58 struct MessageSink {
59 std::atomic<uint32_t> errorCount = 0;
60 std::atomic<uint32_t> warningCount = 0;
61
62 // コールバックの登録(破棄で外す)
63 ComPtr<ID3D12InfoQueue1> infoQueue;
64 DWORD callbackCookie = 0;
65
67 };
68
69 Device() = default;
70
71 // debug layer の 1 件の報告をログへ流して数える(ID3D12InfoQueue1::RegisterMessageCallback に渡す)
72 static void __stdcall OnDebugMessage(D3D12_MESSAGE_CATEGORY category, D3D12_MESSAGE_SEVERITY severity,
73 D3D12_MESSAGE_ID id, LPCSTR description, void* context);
74 [[nodiscard]] static std::unique_ptr<MessageSink> AttachMessageSink(ID3D12Device5* device);
75
76 ComPtr<IDXGIFactory6> m_factory;
77 ComPtr<ID3D12Device5> m_device;
79 std::unique_ptr<MessageSink> m_messageSink; // debug layer が無効なら空
80 };
81
82 // DRED が記録したもの(LogDeviceRemoved の結果。テストが DRED が効いているかを見る)
84 bool dredAvailable = false; // DRED の記録を読めた(DRED が無効・デバイスが失われていないなら false)
85 uint32_t breadcrumbListCount = 0; // 記録のあるコマンドリストの数
86 uint64_t pageFaultAddress = 0; // ページフォールトした GPU の仮想アドレス(無ければ 0)
87 };
88
89 // デバイスが失われた理由と、DRED が有効なら最後に走っていたコマンドとページフォールトの場所をログ(Error)に出す
90 DeviceRemovedReport LogDeviceRemoved(ID3D12Device* device);
91
92} // namespace bicameral::gpu
uint32_t ValidationErrorCount() const
Definition device.cpp:369
IDXGIFactory6 * Factory() const
Definition device.h:49
static std::unique_ptr< MessageSink > AttachMessageSink(ID3D12Device5 *device)
Definition device.cpp:335
static std::expected< Device, std::string > Create(AdapterKind kind, const DeviceOptions &options=DefaultDeviceOptions())
Definition device.cpp:313
ComPtr< IDXGIFactory6 > m_factory
Definition device.h:76
uint32_t ValidationWarningCount() const
Definition device.cpp:373
const DeviceOptions & Options() const
Definition device.h:50
ID3D12Device5 * Get() const
Definition device.h:48
static void __stdcall OnDebugMessage(D3D12_MESSAGE_CATEGORY category, D3D12_MESSAGE_SEVERITY severity, D3D12_MESSAGE_ID id, LPCSTR description, void *context)
Definition device.cpp:356
ComPtr< ID3D12Device5 > m_device
Definition device.h:77
DeviceOptions m_options
Definition device.h:78
std::unique_ptr< MessageSink > m_messageSink
Definition device.h:79
DeviceRemovedReport LogDeviceRemoved(ID3D12Device *device)
Definition device.cpp:379
const char * AdapterKindName(AdapterKind kind)
Definition device.cpp:299
DeviceOptions DefaultDeviceOptions()
Definition device.cpp:303
std::atomic< uint32_t > errorCount
Definition device.h:59
std::atomic< uint32_t > warningCount
Definition device.h:60
ComPtr< ID3D12InfoQueue1 > infoQueue
Definition device.h:63