From b23da43f05b59b249b5672f31ce0427a1e7ac0e6 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Fri, 24 Nov 2017 16:49:20 -1000 Subject: [PATCH] Windows and Vulkan fixes --- include/boo/graphicsdev/Vulkan.hpp | 12 +++- lib/graphicsdev/Vulkan.cpp | 43 ++++++------ lib/win/ApplicationWin32.cpp | 97 ++++++++++++++++----------- lib/win/Win32Common.hpp | 101 +++++++++++++++++++---------- lib/win/WindowWin32.cpp | 39 +++++------ 5 files changed, 171 insertions(+), 121 deletions(-) diff --git a/include/boo/graphicsdev/Vulkan.hpp b/include/boo/graphicsdev/Vulkan.hpp index 1452890..94019d3 100644 --- a/include/boo/graphicsdev/Vulkan.hpp +++ b/include/boo/graphicsdev/Vulkan.hpp @@ -31,6 +31,7 @@ struct VulkanContext VkInstance m_instance = VK_NULL_HANDLE; std::vector m_deviceExtensionNames; std::vector m_gpus; + VkPhysicalDeviceFeatures m_features; VkPhysicalDeviceProperties m_gpuProps; VkPhysicalDeviceMemoryProperties m_memoryProperties; VkDevice m_dev; @@ -72,10 +73,19 @@ struct VulkanContext } } m_swapChains[2]; uint32_t m_activeSwapChain = 0; + +#if _WIN32 + HWND m_hwnd = 0; + bool m_fs = false; + LONG m_fsStyle; + LONG m_fsExStyle; + RECT m_fsRect; + int m_fsCountDown = 0; +#endif }; std::unordered_map> m_windows; - void initVulkan(std::string_view appName); + bool initVulkan(std::string_view appName); bool enumerateDevices(); void initDevice(); void initSwapChain(Window& windowCtx, VkSurfaceKHR surface, VkFormat format, VkColorSpaceKHR colorspace); diff --git a/lib/graphicsdev/Vulkan.cpp b/lib/graphicsdev/Vulkan.cpp index 9373ea8..97f01fd 100644 --- a/lib/graphicsdev/Vulkan.cpp +++ b/lib/graphicsdev/Vulkan.cpp @@ -25,12 +25,11 @@ class VulkanDataFactoryImpl; struct VulkanShareableShader : IShareableShader { - VkDevice m_dev; VkShaderModule m_shader; VulkanShareableShader(VulkanDataFactoryImpl& fac, uint64_t srcKey, uint64_t binKey, - VkDevice dev, VkShaderModule s) - : IShareableShader(fac, srcKey, binKey), m_dev(dev), m_shader(s) {} - ~VulkanShareableShader() { vk::DestroyShaderModule(m_dev, m_shader, nullptr); } + VkShaderModule s) + : IShareableShader(fac, srcKey, binKey), m_shader(s) {} + ~VulkanShareableShader() { vk::DestroyShaderModule(g_VulkanContext.m_dev, m_shader, nullptr); } }; class VulkanDataFactoryImpl : public VulkanDataFactory, public GraphicsDataFactoryHead @@ -260,10 +259,13 @@ static void demo_check_layers(const std::vector& } } -void VulkanContext::initVulkan(std::string_view appName) +bool VulkanContext::initVulkan(std::string_view appName) { if (!glslang::InitializeProcess()) - Log.report(logvisor::Fatal, "unable to initialize glslang"); + { + Log.report(logvisor::Error, "unable to initialize glslang"); + return false; + } uint32_t instanceLayerCount; VkLayerProperties* vkProps = nullptr; @@ -367,16 +369,9 @@ void VulkanContext::initVulkan(std::string_view appName) VkResult instRes = vk::CreateInstance(&instInfo, nullptr, &m_instance); if (instRes != VK_SUCCESS) { -#ifdef _WIN32 - MessageBoxW(nullptr, L"Error creating Vulkan instance\n\n" - L"The Vulkan runtime is installed, but there are no supported " - L"hardware vendor interfaces present", - L"Vulkan Error", MB_OK | MB_ICONERROR); -#else - Log.report(logvisor::Fatal, "The Vulkan runtime is installed, but there are no supported " + Log.report(logvisor::Error, "The Vulkan runtime is installed, but there are no supported " "hardware vendor interfaces present"); -#endif - exit(1); + return false; } #ifndef NDEBUG @@ -395,6 +390,8 @@ void VulkanContext::initVulkan(std::string_view appName) debugCreateInfo.pUserData = nullptr; ThrowIfFailed(createDebugReportCallback(m_instance, &debugCreateInfo, nullptr, &debugReportCallback)); #endif + + return true; } bool VulkanContext::enumerateDevices() @@ -440,6 +437,11 @@ void VulkanContext::initDevice() queueInfo.pQueuePriorities = queuePriorities; queueInfo.queueFamilyIndex = m_graphicsQueueFamilyIndex; + vk::GetPhysicalDeviceFeatures(m_gpus[0], &m_features); + VkPhysicalDeviceFeatures features = {}; + if (m_features.samplerAnisotropy) + features.samplerAnisotropy = VK_TRUE; + VkDeviceCreateInfo deviceInfo = {}; deviceInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; deviceInfo.pNext = nullptr; @@ -451,7 +453,7 @@ void VulkanContext::initDevice() deviceInfo.enabledExtensionCount = m_deviceExtensionNames.size(); deviceInfo.ppEnabledExtensionNames = deviceInfo.enabledExtensionCount ? m_deviceExtensionNames.data() : nullptr; - deviceInfo.pEnabledFeatures = nullptr; + deviceInfo.pEnabledFeatures = &features; ThrowIfFailed(vk::CreateDevice(m_gpus[0], &deviceInfo, nullptr, &m_dev)); @@ -598,7 +600,8 @@ void VulkanContext::initSwapChain(VulkanContext::Window& windowCtx, VkSurfaceKHR samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; - samplerInfo.maxAnisotropy = 1.f; + samplerInfo.maxAnisotropy = m_features.samplerAnisotropy ? + m_gpuProps.limits.maxSamplerAnisotropy : 1.f; ThrowIfFailed(vk::CreateSampler(m_dev, &samplerInfo, nullptr, &m_linearSamplers[0])); /* Create shared white-clamped sampler */ @@ -3285,8 +3288,7 @@ boo::ObjToken VulkanDataFactory::Context::newShaderPipeline auto it = factory.m_sharedShaders.emplace(std::make_pair(binHashes[0], - std::make_unique(factory, srcHashes[0], binHashes[0], - factory.m_ctx->m_dev, vertModule))).first; + std::make_unique(factory, srcHashes[0], binHashes[0], vertModule))).first; vertShader = it->second->lock(); } auto fragFind = binHashes[1] ? factory.m_sharedShaders.find(binHashes[1]) : @@ -3316,8 +3318,7 @@ boo::ObjToken VulkanDataFactory::Context::newShaderPipeline auto it = factory.m_sharedShaders.emplace(std::make_pair(binHashes[1], - std::make_unique(factory, srcHashes[1], binHashes[1], - factory.m_ctx->m_dev, fragModule))).first; + std::make_unique(factory, srcHashes[1], binHashes[1], fragModule))).first; fragShader = it->second->lock(); } diff --git a/lib/win/ApplicationWin32.cpp b/lib/win/ApplicationWin32.cpp index 1c9ebbd..8d216c8 100644 --- a/lib/win/ApplicationWin32.cpp +++ b/lib/win/ApplicationWin32.cpp @@ -22,7 +22,7 @@ PFN_GetScaleFactorForMonitor MyGetScaleFactorForMonitor = nullptr; #include "logvisor/logvisor.hpp" #if BOO_HAS_VULKAN -#include +#include "boo/graphicsdev/Vulkan.hpp" #endif DWORD g_mainThreadId = 0; @@ -68,7 +68,7 @@ static logvisor::Module Log("boo::ApplicationWin32"); Win32Cursors WIN32_CURSORS; std::shared_ptr _WindowWin32New(SystemStringView title, Boo3DAppContextWin32& d3dCtx, - void* vulkanHandle, uint32_t sampleCount); + uint32_t sampleCount); class ApplicationWin32 final : public IApplication { @@ -114,32 +114,75 @@ public: if (!MyCreateDXGIFactory1) Log.report(logvisor::Fatal, "unable to find CreateDXGIFactory1 in DXGI.dll\n"); - bool no12 = false; + bool yes12 = false; bool noD3d = false; #if BOO_HAS_VULKAN bool useVulkan = true; #endif for (const SystemString& arg : args) { - if (!arg.compare(L"--d3d11")) - no12 = true; #if BOO_HAS_VULKAN - if (!arg.compare(L"--vulkan")) - noD3d = true; + if (!arg.compare(L"--d3d12")) + { + useVulkan = false; + yes12 = true; + } + if (!arg.compare(L"--d3d11")) + { + useVulkan = false; + } if (!arg.compare(L"--gl")) { noD3d = true; useVulkan = false; } #else + if (!arg.compare(L"--d3d12")) + yes12 = true; if (!arg.compare(L"--gl")) noD3d = true; #endif } +#if BOO_HAS_VULKAN + if (useVulkan) + { + HMODULE vulkanLib = LoadLibraryW(L"vulkan-1.dll"); + if (vulkanLib) + { + m_getVkProc = (PFN_vkGetInstanceProcAddr)GetProcAddress(vulkanLib, "vkGetInstanceProcAddr"); + if (m_getVkProc) + { + /* Check device support for vulkan */ + vk::init_dispatch_table_top(PFN_vkGetInstanceProcAddr(m_getVkProc)); + if (g_VulkanContext.m_instance == VK_NULL_HANDLE) + { + auto appName = getUniqueName(); + if (g_VulkanContext.initVulkan(WCSTMBS(appName.data()).c_str())) + { + vk::init_dispatch_table_middle(g_VulkanContext.m_instance, false); + if (g_VulkanContext.enumerateDevices()) + { + /* Obtain DXGI Factory */ + HRESULT hr = MyCreateDXGIFactory1(__uuidof(IDXGIFactory1), &m_3dCtx.m_vulkanDxFactory); + if (FAILED(hr)) + Log.report(logvisor::Fatal, "unable to create DXGI factory"); + + Log.report(logvisor::Info, "initialized Vulkan renderer"); + return; + } + } + } + } + } + } +#endif + #if _WIN32_WINNT_WIN10 - HMODULE d3d12lib = LoadLibraryW(L"D3D12.dll"); - if (!no12 && !noD3d && d3d12lib) + HMODULE d3d12lib = nullptr; + if (yes12 && !noD3d) + d3d12lib = LoadLibraryW(L"D3D12.dll"); + if (d3d12lib) { #if _DEBUG { @@ -223,8 +266,10 @@ public: } } #endif - HMODULE d3d11lib = LoadLibraryW(L"D3D11.dll"); - if (d3d11lib && !noD3d) + HMODULE d3d11lib = nullptr; + if (!noD3d) + d3d11lib = LoadLibraryW(L"D3D11.dll"); + if (d3d11lib) { if (!FindBestD3DCompile()) Log.report(logvisor::Fatal, "unable to find D3DCompile_[43-47].dll"); @@ -279,27 +324,6 @@ public: return; } -#if BOO_HAS_VULKAN - if (useVulkan) - { - HMODULE vulkanLib = LoadLibraryW(L"vulkan-1.dll"); - if (vulkanLib) - { - m_getVkProc = (PFN_vkGetInstanceProcAddr)GetProcAddress(vulkanLib, "vkGetInstanceProcAddr"); - if (m_getVkProc) - { - /* Obtain DXGI Factory */ - HRESULT hr = MyCreateDXGIFactory1(__uuidof(IDXGIFactory1), &m_3dCtx.m_vulkanDxFactory); - if (FAILED(hr)) - Log.report(logvisor::Fatal, "unable to create DXGI factory"); - - Log.report(logvisor::Info, "initialized Vulkan renderer"); - return; - } - } - } -#endif - /* Finally try OpenGL */ { /* Obtain DXGI Factory */ @@ -311,7 +335,7 @@ public: return; } - Log.report(logvisor::Fatal, "system doesn't support OGL, D3D11 or D3D12"); + Log.report(logvisor::Fatal, "system doesn't support Vulkan, D3D11, or OpenGL"); } EPlatformType getPlatformType() const @@ -470,12 +494,7 @@ public: return ret; } -#if BOO_HAS_VULKAN - std::shared_ptr window = _WindowWin32New(title, m_3dCtx, m_getVkProc, sampleCount); -#else - std::shared_ptr window = _WindowWin32New(title, m_3dCtx, nullptr, sampleCount); -#endif - + std::shared_ptr window = _WindowWin32New(title, m_3dCtx, sampleCount); HWND hwnd = HWND(window->getPlatformHandle()); m_allWindows[hwnd] = window; return window; diff --git a/lib/win/Win32Common.hpp b/lib/win/Win32Common.hpp index 7e678dc..8c5adb8 100644 --- a/lib/win/Win32Common.hpp +++ b/lib/win/Win32Common.hpp @@ -10,6 +10,10 @@ #include "WinCommon.hpp" #include +#if BOO_HAS_VULKAN +#include "boo/graphicsdev/Vulkan.hpp" +#endif + extern DWORD g_mainThreadId; #if _WIN32_WINNT_WINBLUE @@ -41,6 +45,45 @@ struct OGLContext std::unordered_map m_windows; }; +template +static inline void SetFullscreen(W& win, bool fs) +{ + if (fs) + { + win.m_fsStyle = GetWindowLong(win.m_hwnd, GWL_STYLE); + win.m_fsExStyle = GetWindowLong(win.m_hwnd, GWL_EXSTYLE); + GetWindowRect(win.m_hwnd, &win.m_fsRect); + + SetWindowLong(win.m_hwnd, GWL_STYLE, + win.m_fsStyle & ~(WS_CAPTION | WS_THICKFRAME)); + SetWindowLong(win.m_hwnd, GWL_EXSTYLE, + win.m_fsExStyle & ~(WS_EX_DLGMODALFRAME | + WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE)); + + MONITORINFO monitor_info; + monitor_info.cbSize = sizeof(monitor_info); + GetMonitorInfo(MonitorFromWindow(win.m_hwnd, MONITOR_DEFAULTTONEAREST), + &monitor_info); + SetWindowPos(win.m_hwnd, NULL, monitor_info.rcMonitor.left, monitor_info.rcMonitor.top, + monitor_info.rcMonitor.right - monitor_info.rcMonitor.left, + monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top, + SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_ASYNCWINDOWPOS); + + win.m_fs = true; + } + else + { + SetWindowLong(win.m_hwnd, GWL_STYLE, win.m_fsStyle); + SetWindowLong(win.m_hwnd, GWL_EXSTYLE, win.m_fsExStyle); + + SetWindowPos(win.m_hwnd, NULL, win.m_fsRect.left, win.m_fsRect.top, + win.m_fsRect.right - win.m_fsRect.left, win.m_fsRect.bottom - win.m_fsRect.top, + SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_ASYNCWINDOWPOS); + + win.m_fs = false; + } +} + struct Boo3DAppContextWin32 : Boo3DAppContext { OGLContext m_ctxOgl; @@ -48,6 +91,14 @@ struct Boo3DAppContextWin32 : Boo3DAppContext bool isFullscreen(const boo::IWindow* window) { +#if BOO_HAS_VULKAN + if (m_vulkanDxFactory) + { + boo::VulkanContext::Window& win = *boo::g_VulkanContext.m_windows[window]; + return win.m_fs; + } +#endif + #if _WIN32_WINNT_WIN10 if (m_ctx12.m_dev) { @@ -70,6 +121,19 @@ struct Boo3DAppContextWin32 : Boo3DAppContext bool setFullscreen(boo::IWindow* window, bool fs) { +#if BOO_HAS_VULKAN + if (m_vulkanDxFactory) + { + boo::VulkanContext::Window& win = *boo::g_VulkanContext.m_windows[window]; + if (fs && win.m_fs) + return false; + else if (!fs && !win.m_fs) + return false; + SetFullscreen(win, fs); + return true; + } +#endif + #if _WIN32_WINNT_WIN10 if (m_ctx12.m_dev) { @@ -128,42 +192,7 @@ struct Boo3DAppContextWin32 : Boo3DAppContext return false; else if (!fs && !win.m_fs) return false; - - if (fs) - { - win.m_fsStyle = GetWindowLong(win.m_hwnd, GWL_STYLE); - win.m_fsExStyle = GetWindowLong(win.m_hwnd, GWL_EXSTYLE); - GetWindowRect(win.m_hwnd, &win.m_fsRect); - - SetWindowLong(win.m_hwnd, GWL_STYLE, - win.m_fsStyle & ~(WS_CAPTION | WS_THICKFRAME)); - SetWindowLong(win.m_hwnd, GWL_EXSTYLE, - win.m_fsExStyle & ~(WS_EX_DLGMODALFRAME | - WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE)); - - MONITORINFO monitor_info; - monitor_info.cbSize = sizeof(monitor_info); - GetMonitorInfo(MonitorFromWindow(win.m_hwnd, MONITOR_DEFAULTTONEAREST), - &monitor_info); - SetWindowPos(win.m_hwnd, NULL, monitor_info.rcMonitor.left, monitor_info.rcMonitor.top, - monitor_info.rcMonitor.right - monitor_info.rcMonitor.left, - monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top, - SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_ASYNCWINDOWPOS); - - win.m_fs = true; - } - else - { - SetWindowLong(win.m_hwnd, GWL_STYLE, win.m_fsStyle); - SetWindowLong(win.m_hwnd, GWL_EXSTYLE, win.m_fsExStyle); - - SetWindowPos(win.m_hwnd, NULL, win.m_fsRect.left, win.m_fsRect.top, - win.m_fsRect.right - win.m_fsRect.left, win.m_fsRect.bottom - win.m_fsRect.top, - SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_ASYNCWINDOWPOS); - - win.m_fs = false; - } - + SetFullscreen(win, fs); return true; } }; diff --git a/lib/win/WindowWin32.cpp b/lib/win/WindowWin32.cpp index d760499..b6dfeed 100644 --- a/lib/win/WindowWin32.cpp +++ b/lib/win/WindowWin32.cpp @@ -497,22 +497,12 @@ public: m_pf = pf; } - bool initializeContext(void* getVkProc) + bool initializeContext(void*) { - vk::init_dispatch_table_top(PFN_vkGetInstanceProcAddr(getVkProc)); - if (m_ctx->m_instance == VK_NULL_HANDLE) - { - auto appName = APP->getUniqueName(); - m_ctx->initVulkan(WCSTMBS(appName.data()).c_str()); - } - - vk::init_dispatch_table_middle(m_ctx->m_instance, false); - if (!m_ctx->enumerateDevices()) - return false; - m_windowCtx = m_ctx->m_windows.emplace(std::make_pair(m_parentWindow, std::make_unique())).first->second.get(); + m_windowCtx->m_hwnd = m_hwnd; VkWin32SurfaceCreateInfoKHR surfaceInfo = {}; surfaceInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; @@ -970,13 +960,23 @@ class WindowWin32 : public IWindow public: - WindowWin32(SystemStringView title, Boo3DAppContextWin32& b3dCtx, void* vulkanHandle, uint32_t sampleCount) + WindowWin32(SystemStringView title, Boo3DAppContextWin32& b3dCtx, uint32_t sampleCount) { m_hwnd = CreateWindowW(L"BooWindow", title.data(), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL); HINSTANCE wndInstance = HINSTANCE(GetWindowLongPtr(m_hwnd, GWLP_HINSTANCE)); m_imc = ImmGetContext(m_hwnd); + +#if BOO_HAS_VULKAN + if (b3dCtx.m_vulkanDxFactory) + { + m_gfxCtx.reset(new GraphicsContextWin32Vulkan(this, wndInstance, m_hwnd, &g_VulkanContext, + b3dCtx, sampleCount)); + if (m_gfxCtx->initializeContext(nullptr)) + return; + } +#endif IGraphicsContext::EGraphicsAPI api = IGraphicsContext::EGraphicsAPI::D3D11; #if _WIN32_WINNT_WIN10 if (b3dCtx.m_ctx12.m_dev) @@ -989,15 +989,6 @@ public: m_openGL = true; return; } -#if BOO_HAS_VULKAN - else if (b3dCtx.m_vulkanDxFactory) - { - m_gfxCtx.reset(new GraphicsContextWin32Vulkan(this, wndInstance, m_hwnd, &g_VulkanContext, - b3dCtx, sampleCount)); - if (m_gfxCtx->initializeContext(vulkanHandle)) - return; - } -#endif m_gfxCtx.reset(new GraphicsContextWin32D3D(api, this, m_hwnd, b3dCtx, sampleCount)); } @@ -1583,9 +1574,9 @@ public: }; std::shared_ptr _WindowWin32New(SystemStringView title, Boo3DAppContextWin32& d3dCtx, - void* vulkanHandle, uint32_t sampleCount) + uint32_t sampleCount) { - return std::make_shared(title, d3dCtx, vulkanHandle, sampleCount); + return std::make_shared(title, d3dCtx, sampleCount); } }