Bicameral Engine
GPU-resident engine for a magic-research open-world game
Loading...
Searching...
No Matches
hresult.cpp
Go to the documentation of this file.
1// hresult.cpp — HRESULT の名前と説明(FormatMessageW)を作り、失敗をログに出す。
2//
3// 名前の表は D3D12・DXGI でよく出るものだけ。説明文は OS の言語で返る(日本語の Windows なら日本語)。
4#include "core/hresult.h"
5
6#include <windows.h>
7
8#include <array>
9#include <type_traits>
10
11#include "core/unicode.h"
12
13static_assert(std::is_same_v<HRESULT, bicameral::HResult>, "HResult は HRESULT と同じ型でなければならない");
14
15namespace bicameral {
16 namespace {
17
18 struct NamedResult {
19 HRESULT code;
20 std::string_view name;
21 };
22
23#define BICAMERAL_NAMED_RESULT(code) \
24 NamedResult { \
25 code, #code \
26 }
27 constexpr std::array NAMED_RESULTS = {
28 // --- 一般 ---
30 BICAMERAL_NAMED_RESULT(E_INVALIDARG),
31 BICAMERAL_NAMED_RESULT(E_OUTOFMEMORY),
32 BICAMERAL_NAMED_RESULT(E_NOTIMPL),
33 BICAMERAL_NAMED_RESULT(E_NOINTERFACE),
34 BICAMERAL_NAMED_RESULT(E_POINTER),
35 BICAMERAL_NAMED_RESULT(E_ACCESSDENIED),
37 BICAMERAL_NAMED_RESULT(E_UNEXPECTED),
38 // --- DXGI ---
39 BICAMERAL_NAMED_RESULT(DXGI_ERROR_ACCESS_LOST),
40 BICAMERAL_NAMED_RESULT(DXGI_ERROR_DEVICE_HUNG),
41 BICAMERAL_NAMED_RESULT(DXGI_ERROR_DEVICE_REMOVED),
42 BICAMERAL_NAMED_RESULT(DXGI_ERROR_DEVICE_RESET),
43 BICAMERAL_NAMED_RESULT(DXGI_ERROR_DRIVER_INTERNAL_ERROR),
44 BICAMERAL_NAMED_RESULT(DXGI_ERROR_INVALID_CALL),
45 BICAMERAL_NAMED_RESULT(DXGI_ERROR_MORE_DATA),
46 BICAMERAL_NAMED_RESULT(DXGI_ERROR_NOT_CURRENTLY_AVAILABLE),
47 BICAMERAL_NAMED_RESULT(DXGI_ERROR_NOT_FOUND),
48 BICAMERAL_NAMED_RESULT(DXGI_ERROR_SDK_COMPONENT_MISSING),
49 BICAMERAL_NAMED_RESULT(DXGI_ERROR_UNSUPPORTED),
50 BICAMERAL_NAMED_RESULT(DXGI_ERROR_WAS_STILL_DRAWING),
51 // --- D3D12 ---
52 BICAMERAL_NAMED_RESULT(D3D12_ERROR_ADAPTER_NOT_FOUND),
53 BICAMERAL_NAMED_RESULT(D3D12_ERROR_DRIVER_VERSION_MISMATCH),
54 };
55#undef BICAMERAL_NAMED_RESULT
56
57 std::string_view NameOf(HRESULT result) {
58 for (const NamedResult& named : NAMED_RESULTS) {
59 if (named.code == result)
60 return named.name;
61 }
62
63 return {};
64 }
65
66 // OS が持っている説明文。末尾の改行と句点の後の空白を落とす。無ければ空
67 std::string SystemMessageOf(HRESULT result) {
68 wchar_t* buffer = nullptr;
69 const DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
70 FORMAT_MESSAGE_IGNORE_INSERTS;
71 const DWORD length = FormatMessageW(flags, nullptr, static_cast<DWORD>(result), 0,
72 reinterpret_cast<wchar_t*>(&buffer), 0, nullptr);
73 if (length == 0 || buffer == nullptr)
74 return {};
75
76 std::wstring_view text(buffer, length);
77 while (!text.empty() && (text.back() == L'\r' || text.back() == L'\n' || text.back() == L' '))
78 text.remove_suffix(1);
79
80 std::string message = ToUtf8(text);
81 LocalFree(buffer);
82
83 return message;
84 }
85
86 } // namespace
87
88 std::string DescribeHresult(HResult result) {
89 const std::string_view name = NameOf(result);
90 const std::string message = SystemMessageOf(result);
91 std::string text = name.empty() ? std::format("0x{:08X}", static_cast<unsigned long>(result))
92 : std::format("{} (0x{:08X})", name, static_cast<unsigned long>(result));
93 if (!message.empty())
94 text += ": " + message;
95
96 return text;
97 }
98
99 bool CheckHresult(HResult result, Channel channel, std::string_view expression,
100 const std::source_location& location) {
101 if (SUCCEEDED(result))
102 return true;
103
104 Logger& logger = GetLogger();
105 if (logger.IsEnabled(Level::Error))
106 logger.Write(channel, Level::Error, std::format("{} が失敗: {}", expression, DescribeHresult(result)),
107 location);
108
109 return false;
110 }
111
112} // namespace bicameral
bool IsEnabled(Level level) const
Definition log.h:107
void Write(Channel channel, Level level, std::string_view message, const std::source_location &location)
Definition log.cpp:116
#define BICAMERAL_NAMED_RESULT(code)
Definition hresult.cpp:23
std::string_view NameOf(HRESULT result)
Definition hresult.cpp:57
std::string SystemMessageOf(HRESULT result)
Definition hresult.cpp:67
bool CheckHresult(HResult result, Channel channel, std::string_view expression, const std::source_location &location)
Definition hresult.cpp:99
long HResult
Definition hresult.h:20
Logger & GetLogger()
Definition log.h:120
Channel
Definition log.h:38
std::string DescribeHresult(HResult result)
Definition hresult.cpp:88
std::string ToUtf8(std::wstring_view text)
Definition unicode.cpp:10