Bicameral Engine
GPU-resident engine for a magic-research open-world game
Loading...
Searching...
No Matches
device.cpp
Go to the documentation of this file.
1// device.cpp — D3D12 のデバイスを作る(T-0013)と、検証・デバイス喪失の記録(T-0003、docs/design/16-debug-test.md §1)。
2// アダプタの選び方: ソフトウェアのアダプタを除き、描画する画面を持つアダプタ → 高性能の順(T-0004。device.h の presentMonitor)。
3// 最低機の条件(D-210・D-211・ADR-0009)を満たさないデバイスは使わない: SM 6.8・Work Graphs 1.0・Int64ShaderOps。
4// raw / structured バッファへの 64bit atomic は SM 6.6 以上で必須なので、SM 6.8 の確認に含まれる。
5// debug layer の d3d12SDKLayers.dll は Agility SDK のもの(exe の横の D3D12\。engine/CMakeLists.txt がコピーする)。
6#include "gpu/device.h"
7
8#include "core/aliases.h"
9#include "core/hresult.h"
10#include "core/log.h"
11#include "core/unicode.h"
12#include "gpu/com_ptr.h"
13
14namespace bicameral::gpu {
15 namespace {
16
17 using DeviceResult = std::expected<ComPtr<ID3D12Device5>, std::string>;
18
19 // WARP は版によって FL 12_2 に届かない(Windows 11 build 26200 の WARP は 12_1。2026-09-30 の --caps)。
20 // Work Graphs と SM 6.8 は FL と別に問い合わせる機能なので、WARP は作れる一番低い FL で作る
21 constexpr D3D_FEATURE_LEVEL HARDWARE_FEATURE_LEVEL = D3D_FEATURE_LEVEL_12_2;
22 constexpr D3D_FEATURE_LEVEL WARP_FEATURE_LEVEL = D3D_FEATURE_LEVEL_11_0;
23
24 // DRED の記録をログに出すとき、止まったコマンドの前後いくつを見せるか
25 constexpr uint32_t BREADCRUMB_CONTEXT_BEFORE = 3;
26 constexpr uint32_t BREADCRUMB_CONTEXT_AFTER = 3;
27 constexpr int MAX_LOGGED_ALLOCATIONS = 8;
28
29 // --- アダプタとデバイス ---
30
31 // 足りない機能の名前を返す(全部あれば空)
32 std::string FindMissingFeatures(ID3D12Device* device) {
33 std::string missing;
34 D3D12_FEATURE_DATA_SHADER_MODEL shaderModel{D3D_SHADER_MODEL_6_8};
35 if (FAILED(device->CheckFeatureSupport(D3D12_FEATURE_SHADER_MODEL, &shaderModel, sizeof(shaderModel))) ||
36 shaderModel.HighestShaderModel < D3D_SHADER_MODEL_6_8) {
37 missing += " SM6.8";
38 }
39
40 // NOLINTNEXTLINE(bugprone-invalid-enum-default-initialization) 0 で埋めて渡す(caps.cpp と同じ)
41 D3D12_FEATURE_DATA_D3D12_OPTIONS21 options21{};
42 if (FAILED(device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS21, &options21, sizeof(options21))) ||
43 options21.WorkGraphsTier == D3D12_WORK_GRAPHS_TIER_NOT_SUPPORTED) {
44 missing += " WorkGraphs";
45 }
46
47 D3D12_FEATURE_DATA_D3D12_OPTIONS1 options1{};
48 if (FAILED(device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS1, &options1, sizeof(options1))) ||
49 !options1.Int64ShaderOps) {
50 missing += " Int64ShaderOps";
51 }
52
53 return missing;
54 }
55
56 // ソフトウェアでなく、FL 12_2 のデバイスを作れて最低機の機能がそろうならデバイスを返す(だめなら nullptr)
57 ComPtr<ID3D12Device5> TryCreateHardwareDevice(IDXGIAdapter1* adapter) {
58 DXGI_ADAPTER_DESC1 desc{};
59 if (FAILED(adapter->GetDesc1(&desc)) || (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) != 0)
60 return nullptr;
61
62 ComPtr<ID3D12Device5> device;
63 if (FAILED(D3D12CreateDevice(adapter, HARDWARE_FEATURE_LEVEL, IID_PPV_ARGS(&device))))
64 return nullptr;
65
66 const std::string missing = FindMissingFeatures(device.Get());
67 if (!missing.empty()) {
68 Log(Channel::Gpu, Level::Warning, "アダプタ {} は使わない(足りない機能:{})", ToUtf8(desc.Description),
69 missing);
70 return nullptr;
71 }
72
73 Log(Channel::Gpu, Level::Info, "アダプタ: {} LUID {:08x}:{:08x}", ToUtf8(desc.Description),
74 static_cast<unsigned long>(desc.AdapterLuid.HighPart), desc.AdapterLuid.LowPart);
75
76 return device;
77 }
78
79 // アダプタが monitor をつないでいるか(画面の一覧に含むか)
80 bool AdapterOwnsMonitor(IDXGIAdapter1* adapter, HMONITOR monitor) {
81 for (UINT outputIndex = 0;; ++outputIndex) {
82 ComPtr<IDXGIOutput> output;
83 if (adapter->EnumOutputs(outputIndex, &output) == DXGI_ERROR_NOT_FOUND)
84 return false;
85
86 DXGI_OUTPUT_DESC outputDesc{};
87 if (SUCCEEDED(output->GetDesc(&outputDesc)) && outputDesc.Monitor == monitor)
88 return true;
89 }
90 }
91
92 // 高性能の順に見て、最初に条件を満たすアダプタでデバイスを作る。monitor が nullptr でなければ、その画面を持つものだけ
93 ComPtr<ID3D12Device5> CreateFirstHardwareDevice(IDXGIFactory6* factory, HMONITOR monitor) {
94 for (UINT index = 0;; ++index) {
95 ComPtr<IDXGIAdapter1> adapter;
96 if (factory->EnumAdapterByGpuPreference(index, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE,
97 IID_PPV_ARGS(&adapter)) == DXGI_ERROR_NOT_FOUND) {
98 return nullptr;
99 }
100
101 if (monitor != nullptr && !AdapterOwnsMonitor(adapter.Get(), monitor))
102 continue;
103
104 if (ComPtr<ID3D12Device5> device = TryCreateHardwareDevice(adapter.Get()))
105 return device;
106 }
107 }
108
109 // 窓の画面を持つアダプタ → 無ければ(使えなければ)全部を高性能の順に
110 DeviceResult CreateHardwareDevice(IDXGIFactory6* factory, HMONITOR presentMonitor) {
111 if (presentMonitor != nullptr) {
112 if (ComPtr<ID3D12Device5> device = CreateFirstHardwareDevice(factory, presentMonitor))
113 return device;
114
115 Log(Channel::Gpu, Level::Warning, "窓の画面を持つアダプタが使えないので、高性能の順で選ぶ");
116 }
117
118 if (ComPtr<ID3D12Device5> device = CreateFirstHardwareDevice(factory, nullptr))
119 return device;
120
121 return std::unexpected("最低機の条件(FL 12_2・SM 6.8・Work Graphs・Int64ShaderOps)を満たすアダプタが無い");
122 }
123
124 // 読み込まれている d3d10warp.dll の場所と版。exe の横の NuGet の版(T-0097)か OS の版かを見分けるため
125 struct WarpModule {
126 std::string description;
127 bool besideExecutable = false;
128 };
129
131 HMODULE warpModule = GetModuleHandleW(L"d3d10warp.dll");
132 if (warpModule == nullptr)
133 return {.description = "d3d10warp.dll が読み込まれていない"};
134
135 std::wstring warpPath(MAX_PATH * 4, L'\0');
136 warpPath.resize(GetModuleFileNameW(warpModule, warpPath.data(), static_cast<DWORD>(warpPath.size())));
137 std::wstring executablePath(MAX_PATH * 4, L'\0');
138 executablePath.resize(
139 GetModuleFileNameW(nullptr, executablePath.data(), static_cast<DWORD>(executablePath.size())));
140
141 WarpModule result{
142 .description = ToUtf8(warpPath),
143 .besideExecutable = fs::path(warpPath).parent_path() == fs::path(executablePath).parent_path(),
144 };
145
146 // --- 版(VS_FIXEDFILEINFO の FileVersion)---
147 const DWORD infoSize = GetFileVersionInfoSizeW(warpPath.c_str(), nullptr);
148 std::vector<std::byte> info(infoSize);
149 void* fixedInfoPointer = nullptr;
150 UINT fixedInfoSize = 0;
151 const bool hasVersion = infoSize != 0 && GetFileVersionInfoW(warpPath.c_str(), 0, infoSize, info.data()) &&
152 VerQueryValueW(info.data(), L"\\", &fixedInfoPointer, &fixedInfoSize) &&
153 fixedInfoSize >= sizeof(VS_FIXEDFILEINFO);
154 if (!hasVersion) {
155 result.description += "(版は不明)";
156 return result;
157 }
158
159 const auto* fixedInfo = static_cast<const VS_FIXEDFILEINFO*>(fixedInfoPointer);
160 result.description += std::format("(版 {}.{}.{}.{})", HIWORD(fixedInfo->dwFileVersionMS),
161 LOWORD(fixedInfo->dwFileVersionMS), HIWORD(fixedInfo->dwFileVersionLS),
162 LOWORD(fixedInfo->dwFileVersionLS));
163
164 return result;
165 }
166
167 DeviceResult CreateWarpDevice(IDXGIFactory6* factory) {
168 ComPtr<IDXGIAdapter1> adapter;
169 HRESULT result = factory->EnumWarpAdapter(IID_PPV_ARGS(&adapter));
170 if (FAILED(result))
171 return std::unexpected("WARP のアダプタを取れない: " + DescribeHresult(result));
172
173 ComPtr<ID3D12Device5> device;
174 result = D3D12CreateDevice(adapter.Get(), WARP_FEATURE_LEVEL, IID_PPV_ARGS(&device));
175 if (FAILED(result))
176 return std::unexpected("WARP のデバイスを作れない: " + DescribeHresult(result));
177
178 const std::string missing = FindMissingFeatures(device.Get());
179 if (!missing.empty())
180 return std::unexpected("WARP に足りない機能:" + missing);
181
182 Log(Channel::Gpu, Level::Info, "アダプタ: WARP");
183
184 // OS の WARP は Work Graph の複雑なノードで落ちる(ADR-0013)。exe の横の NuGet の版を使っているかを残す
185 const WarpModule warpModule = DescribeWarpModule();
186 if (warpModule.besideExecutable)
187 Log(Channel::Gpu, Level::Info, "WARP: {}", warpModule.description);
188 else
190 "WARP が exe の横の版ではない(Work Graph が落ちることがある。ADR-0013): {}",
191 warpModule.description);
192
193 return device;
194 }
195
196 // --- 検証と DRED(プロセス全体の設定)---
197
198 // デバイスを作る前に呼ぶ。debug layer はデバイスを作った後に有効にすると、そのデバイスが失われる(D3D12 の仕様)
199 void EnableDebugFeatures(const DeviceOptions& options) {
200 if (options.debugLayer || options.gpuBasedValidation) {
201 ComPtr<ID3D12Debug1> debug;
202 if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debug)))) {
203 debug->EnableDebugLayer();
204 debug->SetEnableGPUBasedValidation(options.gpuBasedValidation ? TRUE : FALSE);
205 } else
206 Log(Channel::Gpu, Level::Warning, "debug layer を使えない(D3D12\\d3d12SDKLayers.dll が無い?)");
207 }
208
209 if (options.dred) {
210 ComPtr<ID3D12DeviceRemovedExtendedDataSettings1> dred;
211 if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&dred)))) {
212 dred->SetAutoBreadcrumbsEnablement(D3D12_DRED_ENABLEMENT_FORCED_ON);
213 dred->SetPageFaultEnablement(D3D12_DRED_ENABLEMENT_FORCED_ON);
214 dred->SetBreadcrumbContextEnablement(D3D12_DRED_ENABLEMENT_FORCED_ON);
215 } else
216 Log(Channel::Gpu, Level::Warning, "DRED の設定を取れない");
217 }
218
219 Log(Channel::Gpu, Level::Info, "検証: debug layer {}・GPU-based validation {}・DRED {}",
220 options.debugLayer || options.gpuBasedValidation ? "on" : "off",
221 options.gpuBasedValidation ? "on" : "off", options.dred ? "on" : "off");
222 }
223
224 Level LevelOfSeverity(D3D12_MESSAGE_SEVERITY severity) {
225 switch (severity) {
226 case D3D12_MESSAGE_SEVERITY_CORRUPTION:
227 case D3D12_MESSAGE_SEVERITY_ERROR: return Level::Error;
228 case D3D12_MESSAGE_SEVERITY_WARNING: return Level::Warning;
229 case D3D12_MESSAGE_SEVERITY_INFO: return Level::Debug;
230 default: return Level::Trace;
231 }
232 }
233
234 // --- DRED の記録を読む ---
235
236 std::string BreadcrumbOpName(D3D12_AUTO_BREADCRUMB_OP op) {
237 switch (op) {
238 case D3D12_AUTO_BREADCRUMB_OP_SETMARKER: return "SetMarker";
239 case D3D12_AUTO_BREADCRUMB_OP_BEGINEVENT: return "BeginEvent";
240 case D3D12_AUTO_BREADCRUMB_OP_ENDEVENT: return "EndEvent";
241 case D3D12_AUTO_BREADCRUMB_OP_DRAWINSTANCED: return "DrawInstanced";
242 case D3D12_AUTO_BREADCRUMB_OP_DRAWINDEXEDINSTANCED: return "DrawIndexedInstanced";
243 case D3D12_AUTO_BREADCRUMB_OP_EXECUTEINDIRECT: return "ExecuteIndirect";
244 case D3D12_AUTO_BREADCRUMB_OP_DISPATCH: return "Dispatch";
245 case D3D12_AUTO_BREADCRUMB_OP_COPYBUFFERREGION: return "CopyBufferRegion";
246 case D3D12_AUTO_BREADCRUMB_OP_COPYTEXTUREREGION: return "CopyTextureRegion";
247 case D3D12_AUTO_BREADCRUMB_OP_COPYRESOURCE: return "CopyResource";
248 case D3D12_AUTO_BREADCRUMB_OP_CLEARUNORDEREDACCESSVIEW: return "ClearUnorderedAccessView";
249 case D3D12_AUTO_BREADCRUMB_OP_RESOURCEBARRIER: return "ResourceBarrier";
250 case D3D12_AUTO_BREADCRUMB_OP_PRESENT: return "Present";
251 case D3D12_AUTO_BREADCRUMB_OP_RESOLVEQUERYDATA: return "ResolveQueryData";
252 case D3D12_AUTO_BREADCRUMB_OP_WRITEBUFFERIMMEDIATE: return "WriteBufferImmediate";
253 case D3D12_AUTO_BREADCRUMB_OP_DISPATCHRAYS: return "DispatchRays";
254 case D3D12_AUTO_BREADCRUMB_OP_DISPATCHMESH: return "DispatchMesh";
255 case D3D12_AUTO_BREADCRUMB_OP_BARRIER: return "Barrier";
256 case D3D12_AUTO_BREADCRUMB_OP_BEGIN_COMMAND_LIST: return "BeginCommandList";
257 case D3D12_AUTO_BREADCRUMB_OP_DISPATCHGRAPH: return "DispatchGraph";
258 case D3D12_AUTO_BREADCRUMB_OP_SETPROGRAM: return "SetProgram";
259 default: return std::format("op {}", static_cast<int>(op));
260 }
261 }
262
263 std::string DebugNameOf(const wchar_t* name) {
264 return name != nullptr ? ToUtf8(name) : std::string("(名前なし)");
265 }
266
267 // 1 本のコマンドリストの記録: どこまで終わったか、止まった所の前後に何があったか
268 void LogBreadcrumbNode(const D3D12_AUTO_BREADCRUMB_NODE1& node) {
269 const uint32_t completed = node.pLastBreadcrumbValue != nullptr ? *node.pLastBreadcrumbValue : 0;
270 const std::string where = std::format("リスト {}(キュー {})", DebugNameOf(node.pCommandListDebugNameW),
271 DebugNameOf(node.pCommandQueueDebugNameW));
272
273 if (completed >= node.BreadcrumbCount) {
274 Log(Channel::Gpu, Level::Info, "DRED: {}: {} 個のコマンドを全部終えている", where,
275 node.BreadcrumbCount);
276 return;
277 }
278
279 Log(Channel::Gpu, Level::Error, "DRED: {}: {} 個中 {} 個まで終えた。次のコマンドで止まった", where,
280 node.BreadcrumbCount, completed);
281 const uint32_t first = completed > BREADCRUMB_CONTEXT_BEFORE ? completed - BREADCRUMB_CONTEXT_BEFORE : 0;
282 const uint32_t last = std::min(node.BreadcrumbCount, completed + BREADCRUMB_CONTEXT_AFTER + 1);
283
284 for (uint32_t index = first; index < last; ++index) {
285 Log(Channel::Gpu, Level::Error, "DRED: {} [{}] {}", index == completed ? "→" : " ", index,
286 BreadcrumbOpName(node.pCommandHistory[index]));
287 }
288 }
289
290 void LogAllocations(std::string_view title, const D3D12_DRED_ALLOCATION_NODE1* node) {
291 for (int count = 0; node != nullptr && count < MAX_LOGGED_ALLOCATIONS; node = node->pNext, ++count) {
292 Log(Channel::Gpu, Level::Error, "DRED: {}: {}(種類 {})", title, DebugNameOf(node->ObjectNameW),
293 static_cast<int>(node->AllocationType));
294 }
295 }
296
297 } // namespace
298
299 const char* AdapterKindName(AdapterKind kind) {
300 return kind == AdapterKind::Warp ? "WARP" : "hardware";
301 }
302
304#ifdef BICAMERAL_GPU_VALIDATION
305 return {.debugLayer = true, .gpuBasedValidation = true, .dred = true};
306#else
307 return {};
308#endif
309 }
310
311 // --- Device ---
312
313 std::expected<Device, std::string> Device::Create(AdapterKind kind, const DeviceOptions& options) {
314 EnableDebugFeatures(options);
315 ComPtr<IDXGIFactory6> factory;
316 const HRESULT result = CreateDXGIFactory2(0, IID_PPV_ARGS(&factory));
317 if (FAILED(result))
318 return std::unexpected("DXGI のファクトリを作れない: " + DescribeHresult(result));
319
320 DeviceResult created = kind == AdapterKind::Warp ? CreateWarpDevice(factory.Get())
321 : CreateHardwareDevice(factory.Get(), options.presentMonitor);
322 if (!created)
323 return std::unexpected(created.error());
324
325 Device device;
326 device.m_factory = std::move(factory);
327 device.m_device = std::move(*created);
328 device.m_options = options;
329 if (options.debugLayer || options.gpuBasedValidation)
330 device.m_messageSink = AttachMessageSink(device.Get());
331
332 return device;
333 }
334
335 std::unique_ptr<Device::MessageSink> Device::AttachMessageSink(ID3D12Device5* device) {
336 auto sink = std::make_unique<MessageSink>();
337 if (FAILED(device->QueryInterface(IID_PPV_ARGS(&sink->infoQueue)))) {
338 Log(Channel::Gpu, Level::Warning, "ID3D12InfoQueue1 が無いので、debug layer の報告はログに出ない");
339 return sink; // 数は 0 のまま
340 }
341
342 if (!BICAMERAL_CHECK_HR(Channel::Gpu, sink->infoQueue->RegisterMessageCallback(
343 &Device::OnDebugMessage, D3D12_MESSAGE_CALLBACK_FLAG_NONE, sink.get(),
344 &sink->callbackCookie))) {
345 sink->infoQueue.Reset();
346 }
347
348 return sink;
349 }
350
352 if (infoQueue)
353 infoQueue->UnregisterMessageCallback(callbackCookie);
354 }
355
356 void __stdcall Device::OnDebugMessage(D3D12_MESSAGE_CATEGORY /*category*/, D3D12_MESSAGE_SEVERITY severity,
357 D3D12_MESSAGE_ID id, LPCSTR description, void* context) {
358 auto* sink = static_cast<MessageSink*>(context);
359 const Level level = LevelOfSeverity(severity);
360 if (level == Level::Error)
361 sink->errorCount.fetch_add(1, std::memory_order_relaxed);
362
363 if (level == Level::Warning)
364 sink->warningCount.fetch_add(1, std::memory_order_relaxed);
365
366 Log(Channel::Gpu, level, "D3D12 [{}] {}", static_cast<int>(id), description != nullptr ? description : "");
367 }
368
370 return m_messageSink ? m_messageSink->errorCount.load(std::memory_order_relaxed) : 0;
371 }
372
374 return m_messageSink ? m_messageSink->warningCount.load(std::memory_order_relaxed) : 0;
375 }
376
377 // --- デバイスの喪失 ---
378
379 DeviceRemovedReport LogDeviceRemoved(ID3D12Device* device) {
380 DeviceRemovedReport report;
381 Log(Channel::Gpu, Level::Error, "デバイスが失われた: {}", DescribeHresult(device->GetDeviceRemovedReason()));
382
383 ComPtr<ID3D12DeviceRemovedExtendedData1> dred;
384 if (FAILED(device->QueryInterface(IID_PPV_ARGS(&dred))))
385 return report;
386
387 D3D12_DRED_AUTO_BREADCRUMBS_OUTPUT1 breadcrumbs{};
388 const HRESULT breadcrumbResult = dred->GetAutoBreadcrumbsOutput1(&breadcrumbs);
389 if (FAILED(breadcrumbResult)) {
390 Log(Channel::Gpu, Level::Warning, "DRED の記録が無い(debug プリセットで有効になる): {}",
391 DescribeHresult(breadcrumbResult));
392 return report;
393 }
394
395 report.dredAvailable = true;
396 for (const D3D12_AUTO_BREADCRUMB_NODE1* node = breadcrumbs.pHeadAutoBreadcrumbNode; node != nullptr;
397 node = node->pNext) {
398 ++report.breadcrumbListCount;
399 LogBreadcrumbNode(*node);
400 }
401
402 D3D12_DRED_PAGE_FAULT_OUTPUT1 pageFault{};
403 if (SUCCEEDED(dred->GetPageFaultAllocationOutput1(&pageFault)) && pageFault.PageFaultVA != 0) {
404 report.pageFaultAddress = pageFault.PageFaultVA;
405 Log(Channel::Gpu, Level::Error, "DRED: ページフォールト: GPU の仮想アドレス {:#x}", pageFault.PageFaultVA);
406 LogAllocations("そこにあるもの", pageFault.pHeadExistingAllocationNode);
407 LogAllocations("最近解放したもの", pageFault.pHeadRecentFreedAllocationNode);
408 }
409
410 return report;
411 }
412
413} // namespace bicameral::gpu
uint32_t ValidationErrorCount() const
Definition device.cpp:369
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
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
#define BICAMERAL_CHECK_HR(channel, expression)
Definition hresult.h:32
std::expected< ComPtr< ID3D12Device5 >, std::string > DeviceResult
Definition device.cpp:17
std::string DebugNameOf(const wchar_t *name)
Definition device.cpp:263
std::string BreadcrumbOpName(D3D12_AUTO_BREADCRUMB_OP op)
Definition device.cpp:236
ComPtr< ID3D12Device5 > TryCreateHardwareDevice(IDXGIAdapter1 *adapter)
Definition device.cpp:57
void EnableDebugFeatures(const DeviceOptions &options)
Definition device.cpp:199
constexpr D3D_FEATURE_LEVEL WARP_FEATURE_LEVEL
Definition device.cpp:22
ComPtr< ID3D12Device5 > CreateFirstHardwareDevice(IDXGIFactory6 *factory, HMONITOR monitor)
Definition device.cpp:93
std::string FindMissingFeatures(ID3D12Device *device)
Definition device.cpp:32
constexpr D3D_FEATURE_LEVEL HARDWARE_FEATURE_LEVEL
Definition device.cpp:21
Level LevelOfSeverity(D3D12_MESSAGE_SEVERITY severity)
Definition device.cpp:224
DeviceResult CreateWarpDevice(IDXGIFactory6 *factory)
Definition device.cpp:167
void LogBreadcrumbNode(const D3D12_AUTO_BREADCRUMB_NODE1 &node)
Definition device.cpp:268
void LogAllocations(std::string_view title, const D3D12_DRED_ALLOCATION_NODE1 *node)
Definition device.cpp:290
bool AdapterOwnsMonitor(IDXGIAdapter1 *adapter, HMONITOR monitor)
Definition device.cpp:80
DeviceResult CreateHardwareDevice(IDXGIFactory6 *factory, HMONITOR presentMonitor)
Definition device.cpp:110
DeviceRemovedReport LogDeviceRemoved(ID3D12Device *device)
Definition device.cpp:379
const char * AdapterKindName(AdapterKind kind)
Definition device.cpp:299
DeviceOptions DefaultDeviceOptions()
Definition device.cpp:303
std::string DescribeHresult(HResult result)
Definition hresult.cpp:88
void Log(Channel channel, Level level, FormatWithLocation< std::type_identity_t< Args >... > pattern, Args &&... args)
Definition log.h:140
std::string ToUtf8(std::wstring_view text)
Definition unicode.cpp:10
Level
Definition log.h:53
ComPtr< ID3D12InfoQueue1 > infoQueue
Definition device.h:63