aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Giessen <charles@lunarg.com>2021-06-18 16:30:10 -0600
committerCharles Giessen <46324611+charles-lunarg@users.noreply.github.com>2021-11-29 13:03:31 -0700
commitb991aa399063a9f2388dadfd2f425754d20f747f (patch)
tree6209e8f4ac76d786a8e992937efa600b1fef3265
parented290a0f0ac7bd364aed9937a842af39031c49fa (diff)
downloadusermoji-b991aa399063a9f2388dadfd2f425754d20f747f.tar.xz
vulkaninfo: Refactor Win32 function loading
The only reason there were global booleans to decide which output to use was due to the macro WAIT_FOR_CONSOLE_DESTROY. This commit restructures how the win32 function loading operates so that such globals are no longer necessary. It introduces an OutputCategory enum to declare which output format to use.
-rw-r--r--vulkaninfo/vulkaninfo.cpp169
-rw-r--r--vulkaninfo/vulkaninfo.h160
2 files changed, 153 insertions, 176 deletions
diff --git a/vulkaninfo/vulkaninfo.cpp b/vulkaninfo/vulkaninfo.cpp
index 79acf5f4..2a681b42 100644
--- a/vulkaninfo/vulkaninfo.cpp
+++ b/vulkaninfo/vulkaninfo.cpp
@@ -29,19 +29,6 @@
#include "vulkaninfo.hpp"
-#ifdef _WIN32
-// Initialize User32 pointers
-PFN_AdjustWindowRect User32Handles::pfnAdjustWindowRect = nullptr;
-PFN_CreateWindowExA User32Handles::pfnCreateWindowExA = nullptr;
-PFN_DefWindowProcA User32Handles::pfnDefWindowProcA = nullptr;
-PFN_DestroyWindow User32Handles::pfnDestroyWindow = nullptr;
-PFN_LoadIconA User32Handles::pfnLoadIconA = nullptr;
-PFN_RegisterClassExA User32Handles::pfnRegisterClassExA = nullptr;
-
-HMODULE User32Handles::user32DllHandle = nullptr;
-
-#endif
-
// =========== Dump Functions ========= //
void DumpExtensions(Printer &p, std::string layer_name, std::vector<VkExtensionProperties> extensions, bool do_indent) {
@@ -812,6 +799,18 @@ static void ConsoleEnlarge() {
}
#endif
+// Global configuration
+enum class OutputCategory {
+ text,
+ html,
+ devsim_json,
+ vkconfig_output,
+#if defined(VK_ENABLE_BETA_EXTENSIONS)
+ portability_json,
+#endif
+ summary
+};
+
void print_usage(const char *argv0) {
std::cout << "\nvulkaninfo - Summarize Vulkan information in relation to the current environment.\n\n";
std::cout << "USAGE: " << argv0 << " [options]\n\n";
@@ -846,51 +845,47 @@ int vulkanInfoMain(int argc, char **argv) {
#else
int main(int argc, char **argv) {
#endif
+ OutputCategory output_category = OutputCategory::text;
+ uint32_t selected_gpu = 0;
+ bool show_tool_props = false;
+ bool show_formats = false;
+ char *output_path = nullptr;
#ifdef _WIN32
if (ConsoleIsExclusive()) ConsoleEnlarge();
- if (!LoadUser32Dll()) {
+ User32Handles local_user32_handles;
+ user32_handles = &local_user32_handles;
+ if (local_user32_handles.load()) {
fprintf(stderr, "Failed to load user32.dll library!\n");
- WAIT_FOR_CONSOLE_DESTROY;
+ if (output_category == OutputCategory::text) wait_for_console_destroy();
exit(1);
}
#endif
- uint32_t selected_gpu = 0;
- bool show_tool_props = false;
- bool show_formats = false;
- char *output_path = nullptr;
-
// Combinations of output: html only, html AND json, json only, human readable only
for (int i = 1; i < argc; ++i) {
// A internal-use-only format for communication with the Vulkan Configurator tool
// Usage "--vkconfig_output <path>"
if (0 == strcmp("--vkconfig_output", argv[i]) && argc > (i + 1)) {
- human_readable_output = false;
- vkconfig_output = true;
+ output_category = OutputCategory::vkconfig_output;
output_path = argv[i + 1];
++i;
} else if (strncmp("--json", argv[i], 6) == 0 || strcmp(argv[i], "-j") == 0) {
if (strlen(argv[i]) > 7 && strncmp("--json=", argv[i], 7) == 0) {
selected_gpu = static_cast<uint32_t>(strtol(argv[i] + 7, nullptr, 10));
}
- human_readable_output = false;
- json_output = true;
- portability_json = false;
+ output_category = OutputCategory::devsim_json;
#if defined(VK_ENABLE_BETA_EXTENSIONS)
} else if (strncmp("--portability", argv[i], 13) == 0) {
if (strlen(argv[i]) > 14 && strncmp("--portability=", argv[i], 14) == 0) {
selected_gpu = static_cast<uint32_t>(strtol(argv[i] + 14, nullptr, 10));
}
- human_readable_output = false;
- portability_json = true;
- json_output = false;
+ output_category = OutputCategory::portability_json;
#endif // defined(VK_ENABLE_BETA_EXTENSIONS)
} else if (strcmp(argv[i], "--summary") == 0) {
- summary = true;
+ output_category = OutputCategory::summary;
} else if (strcmp(argv[i], "--html") == 0) {
- human_readable_output = false;
- html_output = true;
+ output_category = OutputCategory::html;
} else if (strcmp(argv[i], "--show-tool-props") == 0) {
show_tool_props = true;
} else if (strcmp(argv[i], "--show-formats") == 0) {
@@ -905,10 +900,7 @@ int main(int argc, char **argv) {
}
std::vector<std::unique_ptr<Printer>> printers;
std::ostream out(std::cout.rdbuf());
- std::ofstream json_out;
- std::ofstream portability_out;
- std::ofstream html_out;
- std::ofstream vkconfig_out;
+ std::ofstream file_out;
// if any essential vulkan call fails, it throws an exception
try {
@@ -950,73 +942,77 @@ int main(int argc, char **argv) {
std::cout << "The available GPUs are in the range of 0 to " << gpus.size() - 1 << ".\n";
return 0;
}
-
- if (human_readable_output) {
- printers.push_back(std::unique_ptr<Printer>(new Printer(OutputType::text, out, selected_gpu, instance.vk_version)));
- }
- if (html_output) {
- html_out = std::ofstream("vulkaninfo.html");
- printers.push_back(
- std::unique_ptr<Printer>(new Printer(OutputType::html, html_out, selected_gpu, instance.vk_version)));
- }
- if (json_output) {
- std::string start_string =
- std::string("{\n\t\"$schema\": \"https://schema.khronos.org/vulkan/devsim_1_0_0.json#\",\n") +
- "\t\"comments\": {\n\t\t\"desc\": \"JSON configuration file describing GPU " + std::to_string(selected_gpu) + " (" +
- gpus.at(selected_gpu)->props.deviceName +
- "). Generated using the vulkaninfo program.\",\n\t\t\"vulkanApiVersion\": \"" +
- VkVersionString(instance.vk_version) + "\"\n" + "\t}";
-#ifdef VK_USE_PLATFORM_IOS_MVK
- json_out = std::ofstream("vulkaninfo.json");
- printers.push_back(
- std::unique_ptr<Printer>(new Printer(OutputType::json, json_out, selected_gpu, instance.vk_version, start_string)));
-#else
- printers.push_back(
- std::unique_ptr<Printer>(new Printer(OutputType::json, out, selected_gpu, instance.vk_version, start_string)));
-#endif
- }
-#if defined(VK_ENABLE_BETA_EXTENSIONS)
- if (portability_json) {
- if (!gpus.at(selected_gpu)->CheckPhysicalDeviceExtensionIncluded(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME)) {
- std::cerr << "Cannot create a json because the current selected GPU (" << selected_gpu
- << ") does not support the VK_KHR_portability_subset extension.\n";
- } else {
+ switch (output_category) {
+ default:
+ case (OutputCategory::text):
+ printers.push_back(std::unique_ptr<Printer>(new Printer(OutputType::text, out, selected_gpu, instance.vk_version)));
+ break;
+ case (OutputCategory::html):
+ file_out = std::ofstream("vulkaninfo.html");
+ printers.push_back(
+ std::unique_ptr<Printer>(new Printer(OutputType::html, file_out, selected_gpu, instance.vk_version)));
+ break;
+ case (OutputCategory::devsim_json): {
std::string start_string =
- std::string(
- "{\n\t\"$schema\": "
- "\"https://schema.khronos.org/vulkan/devsim_VK_KHR_portability_subset-provisional-1.json#\",\n") +
+ std::string("{\n\t\"$schema\": \"https://schema.khronos.org/vulkan/devsim_1_0_0.json#\",\n") +
"\t\"comments\": {\n\t\t\"desc\": \"JSON configuration file describing GPU " + std::to_string(selected_gpu) +
- "'s (" + gpus.at(selected_gpu)->props.deviceName +
- "( portability features and properties. Generated using the vulkaninfo program.\",\n\t\t\"vulkanApiVersion\": "
- "\"" +
+ " (" + gpus.at(selected_gpu)->props.deviceName +
+ "). Generated using the vulkaninfo program.\",\n\t\t\"vulkanApiVersion\": \"" +
VkVersionString(instance.vk_version) + "\"\n" + "\t}";
#ifdef VK_USE_PLATFORM_IOS_MVK
- portability_out = std::ofstream("portability.json");
+ file_out = std::ofstream("vulkaninfo.json");
printers.push_back(std::unique_ptr<Printer>(
- new Printer(OutputType::json, portability_out, selected_gpu, instance.vk_version, start_string)));
+ new Printer(OutputType::json, file_out, selected_gpu, instance.vk_version, start_string)));
#else
printers.push_back(
std::unique_ptr<Printer>(new Printer(OutputType::json, out, selected_gpu, instance.vk_version, start_string)));
#endif
- }
- }
+ } break;
+#if defined(VK_ENABLE_BETA_EXTENSIONS)
+ case (OutputCategory::portability_json):
+ if (!gpus.at(selected_gpu)->CheckPhysicalDeviceExtensionIncluded(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME)) {
+ std::cerr << "Cannot create a json because the current selected GPU (" << selected_gpu
+ << ") does not support the VK_KHR_portability_subset extension.\n";
+ } else {
+ std::string start_string =
+ std::string(
+ "{\n\t\"$schema\": "
+ "\"https://schema.khronos.org/vulkan/devsim_VK_KHR_portability_subset-provisional-1.json#\",\n") +
+ "\t\"comments\": {\n\t\t\"desc\": \"JSON configuration file describing GPU " +
+ std::to_string(selected_gpu) + "'s (" + gpus.at(selected_gpu)->props.deviceName +
+ "( portability features and properties. Generated using the vulkaninfo "
+ "program.\",\n\t\t\"vulkanApiVersion\": "
+ "\"" +
+ VkVersionString(instance.vk_version) + "\"\n" + "\t}";
+#ifdef VK_USE_PLATFORM_IOS_MVK
+ portability_out = std::ofstream("portability.json");
+ printers.push_back(std::unique_ptr<Printer>(
+ new Printer(OutputType::json, portability_out, selected_gpu, instance.vk_version, start_string)));
+#else
+ printers.push_back(std::unique_ptr<Printer>(
+ new Printer(OutputType::json, out, selected_gpu, instance.vk_version, start_string)));
+#endif
+ }
+ break;
#endif // defined(VK_ENABLE_BETA_EXTENSIONS)
- if (vkconfig_output) {
+ case (OutputCategory::vkconfig_output): {
#ifdef WIN32
- vkconfig_out = std::ofstream(std::string(output_path) + "\\vulkaninfo.json");
+ file_out = std::ofstream(std::string(output_path) + "\\vulkaninfo.json");
#else
- vkconfig_out = std::ofstream(std::string(output_path) + "/vulkaninfo.json");
+ file_out = std::ofstream(std::string(output_path) + "/vulkaninfo.json");
#endif
- std::string start_string = "{\n\t\"Vulkan Instance Version\": \"" + VkVersionString(instance.vk_version) + "\"";
- printers.push_back(std::unique_ptr<Printer>(
- new Printer(OutputType::vkconfig_output, vkconfig_out, selected_gpu, instance.vk_version, start_string)));
+ std::string start_string = "{\n\t\"Vulkan Instance Version\": \"" + VkVersionString(instance.vk_version) + "\"";
+ printers.push_back(std::unique_ptr<Printer>(
+ new Printer(OutputType::vkconfig_output, file_out, selected_gpu, instance.vk_version, start_string)));
+ break;
+ }
}
for (auto &p : printers) {
#ifdef VK_USE_PLATFORM_IOS_MVK
p->SetAlwaysOpenDetails(true);
#endif
- if (summary) {
+ if (output_category == OutputCategory::summary) {
DumpSummaryInstance(*p.get(), instance);
p->SetHeader();
ObjectWrapper obj(*p, "Devices");
@@ -1025,11 +1021,11 @@ int main(int argc, char **argv) {
DumpSummaryGPU(*p.get(), *gpu.get());
}
} else if (p->Type() == OutputType::json) {
- if (portability_json) {
+ if (output_category == OutputCategory::portability_json) {
#if defined(VK_ENABLE_BETA_EXTENSIONS)
DumpPortability(*p.get(), *gpus.at(selected_gpu).get());
#endif // defined(VK_ENABLE_BETA_EXTENSIONS)
- } else if (json_output) {
+ } else if (output_category == OutputCategory::devsim_json) {
DumpLayers(*p.get(), instance.global_layers, gpus);
DumpGpuJson(*p.get(), *gpus.at(selected_gpu).get());
}
@@ -1081,9 +1077,8 @@ int main(int argc, char **argv) {
p.reset(nullptr);
}
- WAIT_FOR_CONSOLE_DESTROY;
#ifdef _WIN32
- FreeUser32Dll();
+ if (output_category == OutputCategory::text) wait_for_console_destroy();
#endif
return 0;
diff --git a/vulkaninfo/vulkaninfo.h b/vulkaninfo/vulkaninfo.h
index 6dcb9f1c..31f8c594 100644
--- a/vulkaninfo/vulkaninfo.h
+++ b/vulkaninfo/vulkaninfo.h
@@ -108,14 +108,6 @@ struct VulkanException : std::runtime_error {
};
#define THROW_VK_ERR(func_name, err) throw VulkanException(func_name, __FILE__, __LINE__, err);
-// Global configuration (Used by Windows WAIT_FOR_CONSOLE_DESTROY MACRO)
-bool human_readable_output = true;
-bool html_output = false;
-bool json_output = false;
-bool vkconfig_output = false;
-bool portability_json = false;
-bool summary = false;
-
#ifdef _WIN32
#define strdup _strdup
@@ -127,80 +119,70 @@ static int ConsoleIsExclusive(void) {
DWORD num_pids = GetConsoleProcessList(pids, ARRAYSIZE(pids));
return num_pids <= 1;
}
-
-#define WAIT_FOR_CONSOLE_DESTROY \
- do { \
- if (ConsoleIsExclusive() && human_readable_output) Sleep(INFINITE); \
- } while (0)
-#else
-#define WAIT_FOR_CONSOLE_DESTROY
-#endif
-
-#ifdef _WIN32
-
-#define _CALL_PFN(pfn, ...) (pfn)
-#define CALL_PFN(fncName) _CALL_PFN(User32Handles::pfn##fncName)
-
-#define _CHECK_PFN(pfn, fncName) \
- do { \
- if (pfn == nullptr) { \
- fprintf(stderr, "Failed to get %s function address!\n", fncName); \
- WAIT_FOR_CONSOLE_DESTROY; \
- exit(1); \
- } \
- } while (false)
-
-#define _SET_PFN(dllHandle, pfnType, pfn, fncName) \
- do { \
- pfn = reinterpret_cast<pfnType>(GetProcAddress(dllHandle, fncName)); \
- _CHECK_PFN(pfn, fncName); \
- } while (false)
-
-#define SET_PFN(dllHandle, fncName) _SET_PFN(User32Handles::dllHandle, PFN_##fncName, User32Handles::pfn##fncName, #fncName)
+void wait_for_console_destroy() {
+ if (ConsoleIsExclusive()) Sleep(INFINITE);
+}
// User32 function declarations
-typedef WINUSERAPI BOOL(WINAPI *PFN_AdjustWindowRect)(_Inout_ LPRECT, _In_ DWORD, _In_ BOOL);
-typedef WINUSERAPI HWND(WINAPI *PFN_CreateWindowExA)(_In_ DWORD, _In_opt_ LPCSTR, _In_opt_ LPCSTR, _In_ DWORD, _In_ int, _In_ int,
- _In_ int, _In_ int, _In_opt_ HWND, _In_opt_ HMENU, _In_opt_ HINSTANCE,
- _In_opt_ LPVOID);
-typedef WINUSERAPI LRESULT(WINAPI *PFN_DefWindowProcA)(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM);
-typedef WINUSERAPI BOOL(WINAPI *PFN_DestroyWindow)(_In_ HWND);
-typedef WINUSERAPI HICON(WINAPI *PFN_LoadIconA)(_In_opt_ HINSTANCE, _In_ LPCSTR);
-typedef WINUSERAPI ATOM(WINAPI *PFN_RegisterClassExA)(_In_ CONST WNDCLASSEXA *);
+using PFN_AdjustWindowRect = WINUSERAPI BOOL(WINAPI *)(_Inout_ LPRECT, _In_ DWORD, _In_ BOOL);
+using PFN_CreateWindowExA = WINUSERAPI HWND(WINAPI *)(_In_ DWORD, _In_opt_ LPCSTR, _In_opt_ LPCSTR, _In_ DWORD, _In_ int, _In_ int,
+ _In_ int, _In_ int, _In_opt_ HWND, _In_opt_ HMENU, _In_opt_ HINSTANCE,
+ _In_opt_ LPVOID);
+using PFN_DefWindowProcA = WINUSERAPI LRESULT(WINAPI *)(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM);
+using PFN_DestroyWindow = WINUSERAPI BOOL(WINAPI *)(_In_ HWND);
+using PFN_LoadIconA = WINUSERAPI HICON(WINAPI *)(_In_opt_ HINSTANCE, _In_ LPCSTR);
+using PFN_RegisterClassExA = WINUSERAPI ATOM(WINAPI *)(_In_ CONST WNDCLASSEXA *);
struct User32Handles {
- // User32 function pointers
- static PFN_AdjustWindowRect pfnAdjustWindowRect;
- static PFN_CreateWindowExA pfnCreateWindowExA;
- static PFN_DefWindowProcA pfnDefWindowProcA;
- static PFN_DestroyWindow pfnDestroyWindow;
- static PFN_LoadIconA pfnLoadIconA;
- static PFN_RegisterClassExA pfnRegisterClassExA;
-
// User32 dll handle
- static HMODULE user32DllHandle;
-};
+ HMODULE user32DllHandle = nullptr;
-bool LoadUser32Dll() {
- User32Handles::user32DllHandle = LoadLibraryExA("user32.dll", nullptr, 0);
- if (User32Handles::user32DllHandle != NULL) {
- SET_PFN(user32DllHandle, AdjustWindowRect);
- SET_PFN(user32DllHandle, CreateWindowExA);
- SET_PFN(user32DllHandle, DefWindowProcA);
- SET_PFN(user32DllHandle, DestroyWindow);
- SET_PFN(user32DllHandle, LoadIconA);
- SET_PFN(user32DllHandle, RegisterClassExA);
+ // User32 function pointers
+ PFN_AdjustWindowRect pfnAdjustWindowRect = nullptr;
+ PFN_CreateWindowExA pfnCreateWindowExA = nullptr;
+ PFN_DefWindowProcA pfnDefWindowProcA = nullptr;
+ PFN_DestroyWindow pfnDestroyWindow = nullptr;
+ PFN_LoadIconA pfnLoadIconA = nullptr;
+ PFN_RegisterClassExA pfnRegisterClassExA = nullptr;
+
+ User32Handles() noexcept {}
+ ~User32Handles() noexcept {
+ if (user32DllHandle != nullptr) {
+ FreeLibrary(user32DllHandle);
+ }
+ }
+ // Don't allow moving of this class
+ User32Handles(User32Handles const &) = delete;
+ User32Handles &operator=(User32Handles const &) = delete;
+ User32Handles(User32Handles &&) = delete;
+ User32Handles &operator=(User32Handles &&) = delete;
+
+ bool load() {
+ user32DllHandle = LoadLibraryExA("user32.dll", nullptr, 0);
+ if (user32DllHandle == nullptr) return false;
+ if (!load_function(pfnAdjustWindowRect, "AdjustWindowRect")) return false;
+ if (!load_function(pfnCreateWindowExA, "CreateWindowExA")) return false;
+ if (!load_function(pfnDefWindowProcA, "DefWindowProcA")) return false;
+ if (!load_function(pfnDestroyWindow, "DestroyWindow")) return false;
+ if (!load_function(pfnLoadIconA, "LoadIconA")) return false;
+ if (!load_function(pfnRegisterClassExA, "RegisterClassExA")) return false;
return true;
}
- return false;
-}
-void FreeUser32Dll() {
- if (User32Handles::user32DllHandle != nullptr) {
- FreeLibrary(User32Handles::user32DllHandle);
- User32Handles::user32DllHandle = nullptr;
+ private:
+ template <typename T>
+ bool load_function(T &function_pointer, const char *function_name) {
+ function_pointer = reinterpret_cast<T>(GetProcAddress(user32DllHandle, function_name));
+ if (function_pointer == nullptr) {
+ fprintf(stderr, "Failed to load function: %s\n", function_name);
+ return false;
+ }
+ return true;
}
-}
+};
+
+// Global user handles function used in windows callback and code
+User32Handles *user32_handles;
#endif // _WIN32
const char *app_short_name = "vulkaninfo";
@@ -756,7 +738,7 @@ struct AppInstance {
// MS-Windows event handling function:
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
- return (CALL_PFN(DefWindowProcA)(hWnd, uMsg, wParam, lParam));
+ return user32_handles->pfnDefWindowProcA(hWnd, uMsg, wParam, lParam);
}
static void AppCreateWin32Window(AppInstance &inst) {
@@ -771,33 +753,33 @@ static void AppCreateWin32Window(AppInstance &inst) {
win_class.cbClsExtra = 0;
win_class.cbWndExtra = 0;
win_class.hInstance = inst.h_instance;
- win_class.hIcon = CALL_PFN(LoadIconA)(nullptr, IDI_APPLICATION);
+ win_class.hIcon = user32_handles->pfnLoadIconA(nullptr, IDI_APPLICATION);
win_class.hCursor = LoadCursor(nullptr, IDC_ARROW);
win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
win_class.lpszMenuName = nullptr;
win_class.lpszClassName = app_short_name;
win_class.hInstance = inst.h_instance;
- win_class.hIconSm = CALL_PFN(LoadIconA)(nullptr, IDI_WINLOGO);
+ win_class.hIconSm = user32_handles->pfnLoadIconA(nullptr, IDI_WINLOGO);
// Register window class:
- if (!CALL_PFN(RegisterClassExA)(&win_class)) {
+ if (!user32_handles->pfnRegisterClassExA(&win_class)) {
// It didn't work, so try to give a useful error:
THROW_ERR("Failed to register the window class!");
}
// Create window with the registered class:
RECT wr = {0, 0, inst.width, inst.height};
- CALL_PFN(AdjustWindowRect)(&wr, WS_OVERLAPPEDWINDOW, FALSE);
- inst.h_wnd = CALL_PFN(CreateWindowExA)(0,
- app_short_name, // class name
- app_short_name, // app name
- // WS_VISIBLE | WS_SYSMENU |
- WS_OVERLAPPEDWINDOW, // window style
- 100, 100, // x/y coords
- wr.right - wr.left, // width
- wr.bottom - wr.top, // height
- nullptr, // handle to parent
- nullptr, // handle to menu
- inst.h_instance, // hInstance
- nullptr); // no extra parameters
+ user32_handles->pfnAdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
+ inst.h_wnd = user32_handles->pfnCreateWindowExA(0,
+ app_short_name, // class name
+ app_short_name, // app name
+ // WS_VISIBLE | WS_SYSMENU |
+ WS_OVERLAPPEDWINDOW, // window style
+ 100, 100, // x/y coords
+ wr.right - wr.left, // width
+ wr.bottom - wr.top, // height
+ nullptr, // handle to parent
+ nullptr, // handle to menu
+ inst.h_instance, // hInstance
+ nullptr); // no extra parameters
if (!inst.h_wnd) {
// It didn't work, so try to give a useful error:
THROW_ERR("Failed to create a window!");