From 31968d5d033c11f28e2fb4748c40cfcefe919087 Mon Sep 17 00:00:00 2001 From: Sean Purcell Date: Wed, 1 Aug 2018 14:06:49 -0400 Subject: [PATCH 1/6] Create Xcb patch for render to surface --- core/vulkan/vk_virtual_swapchain/cc/layer.cpp | 2 + core/vulkan/vk_virtual_swapchain/cc/layer.h | 2 + .../vk_virtual_swapchain/cc/platform.cpp | 11 ++++++ gapir/cc/BUILD.bazel | 4 +- gapir/cc/surface.cpp | 38 +++++++++++++++++-- gapir/cc/surface.h | 15 ++++++-- .../api/templates/vulkan_gfx_api_extras.tmpl | 11 +++++- 7 files changed, 74 insertions(+), 9 deletions(-) diff --git a/core/vulkan/vk_virtual_swapchain/cc/layer.cpp b/core/vulkan/vk_virtual_swapchain/cc/layer.cpp index 168789c088..0a989afd6f 100644 --- a/core/vulkan/vk_virtual_swapchain/cc/layer.cpp +++ b/core/vulkan/vk_virtual_swapchain/cc/layer.cpp @@ -137,6 +137,8 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance( #if defined(VK_USE_PLATFORM_ANDROID_KHR) GET_PROC(vkCreateAndroidSurfaceKHR); +#elif defined(VK_USE_PLATFORM_XCB_KHR) + GET_PROC(vkCreateXcbSurfaceKHR); #endif GET_PROC(vkDestroySurfaceKHR); diff --git a/core/vulkan/vk_virtual_swapchain/cc/layer.h b/core/vulkan/vk_virtual_swapchain/cc/layer.h index bf1e89bab4..bea56b977e 100644 --- a/core/vulkan/vk_virtual_swapchain/cc/layer.h +++ b/core/vulkan/vk_virtual_swapchain/cc/layer.h @@ -51,6 +51,8 @@ struct InstanceData { #if defined(VK_USE_PLATFORM_ANDROID_KHR) PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR; +#elif defined(VK_USE_PLATFORM_XCB_KHR) + PFN_vkCreateXcbSurfaceKHR vkCreateXcbSurfaceKHR; #endif PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR; diff --git a/core/vulkan/vk_virtual_swapchain/cc/platform.cpp b/core/vulkan/vk_virtual_swapchain/cc/platform.cpp index 1d93127e1c..4396b11b9e 100644 --- a/core/vulkan/vk_virtual_swapchain/cc/platform.cpp +++ b/core/vulkan/vk_virtual_swapchain/cc/platform.cpp @@ -33,6 +33,17 @@ void CreateSurface(const InstanceData* functions, VkInstance instance, } } } +#elif defined(VK_USE_PLATFORM_XCB_KHR) + { + auto pCreateInfo = static_cast(data); + if (pCreateInfo->sType == VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR) { + // Attempt to create Xcb surface + if (functions->vkCreateXcbSurfaceKHR(instance, pCreateInfo, pAllocator, + pSurface) != VK_SUCCESS) { + *pSurface = 0; + } + } + } #else *pSurface = 0; #endif diff --git a/gapir/cc/BUILD.bazel b/gapir/cc/BUILD.bazel index 037908e9b2..79c205a8de 100644 --- a/gapir/cc/BUILD.bazel +++ b/gapir/cc/BUILD.bazel @@ -86,7 +86,9 @@ cc_library( ], copts = cc_copts(), linkopts = select({ - "//tools/build:linux": [], + "//tools/build:linux": [ + "-lxcb", + ], "//tools/build:darwin": [ "-framework Cocoa", "-framework OpenGL", diff --git a/gapir/cc/surface.cpp b/gapir/cc/surface.cpp index f858f06bfa..f21ee0c4fc 100644 --- a/gapir/cc/surface.cpp +++ b/gapir/cc/surface.cpp @@ -22,15 +22,45 @@ namespace gapir { #if TARGET_OS == GAPID_OS_ANDROID ANativeWindow* android_window; +#elif TARGET_OS == GAPID_OS_LINUX +static XcbWindowInfo window_info; -#endif // TARGET_OS == GAPID_OS_ANDROID +bool createXcbWindow(uint32_t width, uint32_t height) { + window_info.connection = xcb_connect(nullptr, nullptr); + if (!window_info.connection) { + // Signal failure + return false; + } -void* SurfaceInfo() { + xcb_screen_t* screen = + xcb_setup_roots_iterator(xcb_get_setup(window_info.connection)).data; + if (!screen) { + return false; + } + + window_info.window = xcb_generate_id(window_info.connection); + + xcb_create_window(window_info.connection, XCB_COPY_FROM_PARENT, + window_info.window, screen->root, 0, 0, width, height, 1, + XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, 0, + nullptr); + xcb_map_window(window_info.connection, window_info.window); + xcb_flush(window_info.connection); + + return true; +} +#endif + +void* CreateSurface(uint32_t width, uint32_t height) { #if TARGET_OS == GAPID_OS_ANDROID return (void*)android_window; -#else - return nullptr; +#elif TARGET_OS == GAPID_OS_LINUX + // Create window + if (createXcbWindow(width, height)) { + return (void*)&window_info; + } #endif + return nullptr; } } // namespace gapir diff --git a/gapir/cc/surface.h b/gapir/cc/surface.h index 2fd9156cad..c241049b33 100644 --- a/gapir/cc/surface.h +++ b/gapir/cc/surface.h @@ -17,20 +17,29 @@ #ifndef GAPIR_SURFACE_H #define GAPIR_SURFACE_H +#include + #include "core/cc/target.h" #if TARGET_OS == GAPID_OS_ANDROID class ANativeWindow; -#endif // TARGET_OS == GAPID_OS_ANDROID +#elif TARGET_OS == GAPID_OS_LINUX +#include +#endif namespace gapir { #if TARGET_OS == GAPID_OS_ANDROID extern ANativeWindow* android_window; -#endif // TARGET_OS == GAPID_OS_ANDROID +#elif TARGET_OS == GAPID_OS_LINUX +struct XcbWindowInfo { + xcb_connection_t* connection; + xcb_window_t window; +}; +#endif // Get the platform-specific data pointer to create the surface -void* SurfaceInfo(); +void* CreateSurface(uint32_t width, uint32_t height); } // namespace gapir diff --git a/gapis/api/templates/vulkan_gfx_api_extras.tmpl b/gapis/api/templates/vulkan_gfx_api_extras.tmpl index a7900d31cd..6e390a2b5f 100644 --- a/gapis/api/templates/vulkan_gfx_api_extras.tmpl +++ b/gapis/api/templates/vulkan_gfx_api_extras.tmpl @@ -343,6 +343,8 @@ bool Vulkan::replayCreateVkDeviceImpl(Stack* stack, size_val physicalDevice, swapchain::CreateNext vsPNext; #if TARGET_OS == GAPID_OS_ANDROID VkAndroidSurfaceCreateInfoKHR surfaceInfo = {}; +#elif TARGET_OS == GAPID_OS_LINUX + VkXcbSurfaceCreateInfoKHR surfaceInfo = {}; #endif for (auto pNext = static_cast(newCreateInfo.pNext); pNext != nullptr; @@ -352,13 +354,20 @@ bool Vulkan::replayCreateVkDeviceImpl(Stack* stack, size_val physicalDevice, // Copy any extra fields vsPNext = *pNext; - void* data = SurfaceInfo(); + void* data = CreateSurface(newCreateInfo.imageExtent.Width, + newCreateInfo.imageExtent.Height); void* createInfo = nullptr; if (data != nullptr) { #if TARGET_OS == GAPID_OS_ANDROID createInfo = &surfaceInfo; surfaceInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR; surfaceInfo.window = (ANativeWindow*)data; +#elif TARGET_OS == GAPID_OS_LINUX + createInfo = &surfaceInfo; + auto info = (XcbWindowInfo*)data; + surfaceInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; + surfaceInfo.connection = info->connection; + surfaceInfo.window = info->window; #endif } vsPNext.surfaceCreateInfo = createInfo; From 4fd7179a72d16f102b195786c87be17a55e3d2dd Mon Sep 17 00:00:00 2001 From: Sean Purcell Date: Wed, 1 Aug 2018 15:06:50 -0400 Subject: [PATCH 2/6] Add Win32 support for displaytosurface --- cmd/gapir/cc/main.cpp | 2 + .../cc/base_swapchain.cpp | 7 +- .../vk_virtual_swapchain/cc/base_swapchain.h | 4 + core/vulkan/vk_virtual_swapchain/cc/layer.cpp | 2 + core/vulkan/vk_virtual_swapchain/cc/layer.h | 2 + .../vk_virtual_swapchain/cc/platform.cpp | 14 ++- .../cc/virtual_swapchain.cpp | 5 + gapir/cc/surface.cpp | 112 ++++++++++++++++-- gapir/cc/surface.h | 9 ++ .../api/templates/vulkan_gfx_api_extras.tmpl | 8 ++ 10 files changed, 153 insertions(+), 12 deletions(-) diff --git a/cmd/gapir/cc/main.cpp b/cmd/gapir/cc/main.cpp index cf99e547ec..6df458e408 100644 --- a/cmd/gapir/cc/main.cpp +++ b/cmd/gapir/cc/main.cpp @@ -328,6 +328,8 @@ int main(int argc, const char* argv[]) { fflush(stdout); server->wait(); + + gapir::WaitForWindowClose(); return EXIT_SUCCESS; } diff --git a/core/vulkan/vk_virtual_swapchain/cc/base_swapchain.cpp b/core/vulkan/vk_virtual_swapchain/cc/base_swapchain.cpp index 7f1913656f..a18cf0ec41 100644 --- a/core/vulkan/vk_virtual_swapchain/cc/base_swapchain.cpp +++ b/core/vulkan/vk_virtual_swapchain/cc/base_swapchain.cpp @@ -68,7 +68,8 @@ BaseSwapchain::BaseSwapchain(VkInstance instance, VkDevice device, device_(device), instance_functions_(instance_functions), device_functions_(device_functions), - swapchain_info_(*swapchain_info) { + swapchain_info_(*swapchain_info), + valid_(false) { if (platform_info == nullptr) { return; } @@ -149,6 +150,8 @@ BaseSwapchain::BaseSwapchain(VkInstance instance, VkDevice device, } is_pending_.resize(num_images); + + valid_ = true; } void BaseSwapchain::Destroy(const VkAllocationCallbacks *pAllocator) { @@ -172,6 +175,8 @@ void BaseSwapchain::Destroy(const VkAllocationCallbacks *pAllocator) { command_buffers_.clear(); } +bool BaseSwapchain::Valid() const { return valid_; } + VkResult BaseSwapchain::PresentFrom(VkQueue queue, size_t index, VkImage image) { std::unique_lock guard(present_lock_); diff --git a/core/vulkan/vk_virtual_swapchain/cc/base_swapchain.h b/core/vulkan/vk_virtual_swapchain/cc/base_swapchain.h index f187be8317..eb4ddb08fb 100644 --- a/core/vulkan/vk_virtual_swapchain/cc/base_swapchain.h +++ b/core/vulkan/vk_virtual_swapchain/cc/base_swapchain.h @@ -34,6 +34,8 @@ class BaseSwapchain { const VkAllocationCallbacks *pAllocator, const void *platform_info); void Destroy(const VkAllocationCallbacks *pAllocator); + bool Valid() const; + VkResult PresentFrom(VkQueue queue, size_t index, VkImage image); VkSemaphore BlitWaitSemaphore(size_t index); @@ -65,6 +67,8 @@ class BaseSwapchain { // The command buffers to use to blit. We need several in case someone // submits while a previous one is still pending. std::vector command_buffers_; + // Whether we completed construction successfully + bool valid_; }; } // namespace swapchain diff --git a/core/vulkan/vk_virtual_swapchain/cc/layer.cpp b/core/vulkan/vk_virtual_swapchain/cc/layer.cpp index 0a989afd6f..807109e9c8 100644 --- a/core/vulkan/vk_virtual_swapchain/cc/layer.cpp +++ b/core/vulkan/vk_virtual_swapchain/cc/layer.cpp @@ -139,6 +139,8 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance( GET_PROC(vkCreateAndroidSurfaceKHR); #elif defined(VK_USE_PLATFORM_XCB_KHR) GET_PROC(vkCreateXcbSurfaceKHR); +#elif defined(VK_USE_PLATFORM_WIN32_KHR) + GET_PROC(vkCreateWin32SurfaceKHR); #endif GET_PROC(vkDestroySurfaceKHR); diff --git a/core/vulkan/vk_virtual_swapchain/cc/layer.h b/core/vulkan/vk_virtual_swapchain/cc/layer.h index bea56b977e..d09915c02a 100644 --- a/core/vulkan/vk_virtual_swapchain/cc/layer.h +++ b/core/vulkan/vk_virtual_swapchain/cc/layer.h @@ -53,6 +53,8 @@ struct InstanceData { PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR; #elif defined(VK_USE_PLATFORM_XCB_KHR) PFN_vkCreateXcbSurfaceKHR vkCreateXcbSurfaceKHR; +#elif defined(VK_USE_PLATFORM_WIN32_KHR) + PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR; #endif PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR; diff --git a/core/vulkan/vk_virtual_swapchain/cc/platform.cpp b/core/vulkan/vk_virtual_swapchain/cc/platform.cpp index 4396b11b9e..77bde08e14 100644 --- a/core/vulkan/vk_virtual_swapchain/cc/platform.cpp +++ b/core/vulkan/vk_virtual_swapchain/cc/platform.cpp @@ -21,6 +21,7 @@ namespace swapchain { void CreateSurface(const InstanceData* functions, VkInstance instance, const void* data, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) { + *pSurface = 0; #if defined(VK_USE_PLATFORM_ANDROID_KHR) { auto pCreateInfo = static_cast(data); @@ -44,8 +45,17 @@ void CreateSurface(const InstanceData* functions, VkInstance instance, } } } -#else - *pSurface = 0; +#elif defined(VK_USE_PLATFORM_WIN32_KHR) + { + auto pCreateInfo = static_cast(data); + if (pCreateInfo->sType == VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR) { + // Attempt to create Win32 surface + if (functions->vkCreateWin32SurfaceKHR(instance, pCreateInfo, pAllocator, + pSurface) != VK_SUCCESS) { + *pSurface = 0; + } + } + } #endif } diff --git a/core/vulkan/vk_virtual_swapchain/cc/virtual_swapchain.cpp b/core/vulkan/vk_virtual_swapchain/cc/virtual_swapchain.cpp index 61cc0600cb..a9973b4c87 100644 --- a/core/vulkan/vk_virtual_swapchain/cc/virtual_swapchain.cpp +++ b/core/vulkan/vk_virtual_swapchain/cc/virtual_swapchain.cpp @@ -402,5 +402,10 @@ void VirtualSwapchain::CreateBaseSwapchain( base_swapchain_ = std::unique_ptr(new BaseSwapchain( instance, device_, queue_, command_pool_, num_images_, instance_functions, functions_, &swapchain_info_, pAllocator, platform_info)); + if (!base_swapchain_->Valid()) { + // Failed to create some aspect of the base surface + base_swapchain_->Destroy(pAllocator); + base_swapchain_.reset(); + } } } // namespace swapchain diff --git a/gapir/cc/surface.cpp b/gapir/cc/surface.cpp index f21ee0c4fc..040c7e797d 100644 --- a/gapir/cc/surface.cpp +++ b/gapir/cc/surface.cpp @@ -18,6 +18,14 @@ #include "surface.h" +#if TARGET_OS == GAPID_OS_WINDOWS +#include + +#include +#include +#include +#endif + namespace gapir { #if TARGET_OS == GAPID_OS_ANDROID @@ -25,17 +33,16 @@ ANativeWindow* android_window; #elif TARGET_OS == GAPID_OS_LINUX static XcbWindowInfo window_info; -bool createXcbWindow(uint32_t width, uint32_t height) { +void* createXcbWindow(uint32_t width, uint32_t height) { window_info.connection = xcb_connect(nullptr, nullptr); if (!window_info.connection) { - // Signal failure - return false; + return nullptr; } xcb_screen_t* screen = xcb_setup_roots_iterator(xcb_get_setup(window_info.connection)).data; if (!screen) { - return false; + return nullptr; } window_info.window = xcb_generate_id(window_info.connection); @@ -47,7 +54,84 @@ bool createXcbWindow(uint32_t width, uint32_t height) { xcb_map_window(window_info.connection, window_info.window); xcb_flush(window_info.connection); - return true; + return (void*)&window_info; +} +#elif TARGET_OS == GAPID_OS_WINDOWS +static Win32WindowInfo window_info; + +static HANDLE window_create_sem; +static std::mutex quit_lock; +static std::condition_variable quit_condition; +static bool quit; +static HANDLE thread; + +LRESULT windowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + switch (uMsg) { + case WM_CLOSE: + PostQuitMessage(0); + return 0; + break; + } + return DefWindowProc(hwnd, uMsg, wParam, lParam); +} + +bool createWindow(uint32_t width, uint32_t height) { + window_info.instance = GetModuleHandle(nullptr); + + WNDCLASS wndclass = { + CS_HREDRAW | CS_VREDRAW, // style + windowProc, // lpfnWindowProc + 0, // cbClsExtra + 0, // cbWndExtra + window_info.instance, // hInstance + LoadIcon(nullptr, IDI_APPLICATION), // hIcon + LoadCursor(nullptr, IDC_ARROW), // hCursor + (HBRUSH)(COLOR_BACKGROUND + 1), // hbrBackground + "", // lpszMenuName + "GAPID Replay", // lpszClassName + }; + ATOM cls = RegisterClass(&wndclass); + if (cls == 0) { + // Class registration failed + return false; + } + + window_info.window = CreateWindow( + MAKEINTATOM(cls), "GAPID Replay", + WS_BORDER | WS_CAPTION | WS_GROUP | WS_OVERLAPPED | WS_POPUP | + WS_SYSMENU | WS_TILED | WS_VISIBLE, + 0, 0, width, height, nullptr, nullptr, window_info.instance, nullptr); + return (bool)window_info.window; +} + +DWORD handleWindow(void* data) { + auto extent = (const uint32_t*)data; + bool res = createWindow(extent[0], extent[1]); + ReleaseSemaphore(window_create_sem, 1, nullptr); + if (!res) { + return 1; + } + + MSG msg; + while (GetMessage(&msg, window_info.window, 0, 0)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + { + std::unique_lock guard(quit_lock); + quit = true; + quit_condition.notify_all(); + } + return 0; +} + +void* createWin32Window(uint32_t width, uint32_t height) { + window_create_sem = CreateSemaphore(NULL, 0, 1, NULL); + + uint32_t extent[] = {width, height}; + thread = CreateThread(NULL, 0, handleWindow, (void*)extent, 0, nullptr); + WaitForSingleObject(window_create_sem, INFINITE); + return window_info.window ? (void*)&window_info : nullptr; } #endif @@ -55,12 +139,22 @@ void* CreateSurface(uint32_t width, uint32_t height) { #if TARGET_OS == GAPID_OS_ANDROID return (void*)android_window; #elif TARGET_OS == GAPID_OS_LINUX - // Create window - if (createXcbWindow(width, height)) { - return (void*)&window_info; - } + return createXcbWindow(width, height); +#elif TARGET_OS == GAPID_OS_WINDOWS + return createWin32Window(width, height); #endif return nullptr; } +void WaitForWindowClose() { +#if TARGET_OS == GAPID_OS_WINDOWS + { + std::unique_lock guard(quit_lock); + while (!quit) { + quit_condition.wait(guard); + } + } +#endif +} + } // namespace gapir diff --git a/gapir/cc/surface.h b/gapir/cc/surface.h index c241049b33..56f41c2bcd 100644 --- a/gapir/cc/surface.h +++ b/gapir/cc/surface.h @@ -25,6 +25,8 @@ class ANativeWindow; #elif TARGET_OS == GAPID_OS_LINUX #include +#elif TARGET_OS == GAPID_OS_WINDOWS +#include #endif namespace gapir { @@ -36,11 +38,18 @@ struct XcbWindowInfo { xcb_connection_t* connection; xcb_window_t window; }; +#elif TARGET_OS == GAPID_OS_WINDOWS +struct Win32WindowInfo { + HINSTANCE instance; + HWND window; +}; #endif // Get the platform-specific data pointer to create the surface void* CreateSurface(uint32_t width, uint32_t height); +void WaitForWindowClose(); + } // namespace gapir #endif // GAPIR_SURFACE_H diff --git a/gapis/api/templates/vulkan_gfx_api_extras.tmpl b/gapis/api/templates/vulkan_gfx_api_extras.tmpl index 6e390a2b5f..255bfa27c8 100644 --- a/gapis/api/templates/vulkan_gfx_api_extras.tmpl +++ b/gapis/api/templates/vulkan_gfx_api_extras.tmpl @@ -345,6 +345,8 @@ bool Vulkan::replayCreateVkDeviceImpl(Stack* stack, size_val physicalDevice, VkAndroidSurfaceCreateInfoKHR surfaceInfo = {}; #elif TARGET_OS == GAPID_OS_LINUX VkXcbSurfaceCreateInfoKHR surfaceInfo = {}; +#elif TARGET_OS == GAPID_OS_WINDOWS + VkWin32SurfaceCreateInfoKHR surfaceInfo = {}; #endif for (auto pNext = static_cast(newCreateInfo.pNext); pNext != nullptr; @@ -368,6 +370,12 @@ bool Vulkan::replayCreateVkDeviceImpl(Stack* stack, size_val physicalDevice, surfaceInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; surfaceInfo.connection = info->connection; surfaceInfo.window = info->window; +#elif TARGET_OS == GAPID_OS_WINDOWS + createInfo = &surfaceInfo; + auto info = (Win32WindowInfo*)data; + surfaceInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; + surfaceInfo.hinstance = (HINSTANCE)info->instance; + surfaceInfo.hwnd = (HWND)info->window; #endif } vsPNext.surfaceCreateInfo = createInfo; From 01706406c11d5da97ef23f2a2bbcff7e47c78183 Mon Sep 17 00:00:00 2001 From: Sean Purcell Date: Thu, 2 Aug 2018 15:36:33 -0400 Subject: [PATCH 3/6] Handle xcb events --- gapir/cc/surface.cpp | 106 +++++++++++++++++++++++++++++++------------ 1 file changed, 78 insertions(+), 28 deletions(-) diff --git a/gapir/cc/surface.cpp b/gapir/cc/surface.cpp index 040c7e797d..4569fcd2ae 100644 --- a/gapir/cc/surface.cpp +++ b/gapir/cc/surface.cpp @@ -14,35 +14,63 @@ * limitations under the License. */ +#include +#include +#include + #include "core/cc/target.h" #include "surface.h" #if TARGET_OS == GAPID_OS_WINDOWS #include - -#include -#include -#include #endif namespace gapir { +namespace { +class Flag { + public: + Flag() : set_(false) {} + + void Set() { + std::unique_lock guard(mutex_); + set_ = true; + condition_.notify_all(); + } + + void Wait() { + std::unique_lock guard(mutex_); + while (!set_) { + condition_.wait(guard); + } + } + + private: + bool set_; + std::mutex mutex_; + std::condition_variable condition_; +}; +} // namespace + #if TARGET_OS == GAPID_OS_ANDROID ANativeWindow* android_window; #elif TARGET_OS == GAPID_OS_LINUX static XcbWindowInfo window_info; -void* createXcbWindow(uint32_t width, uint32_t height) { +static Flag window_create_flag; +static std::thread window_thread; + +bool createWindow(uint32_t width, uint32_t height) { window_info.connection = xcb_connect(nullptr, nullptr); if (!window_info.connection) { - return nullptr; + return false; } xcb_screen_t* screen = xcb_setup_roots_iterator(xcb_get_setup(window_info.connection)).data; if (!screen) { - return nullptr; + return false; } window_info.window = xcb_generate_id(window_info.connection); @@ -54,16 +82,42 @@ void* createXcbWindow(uint32_t width, uint32_t height) { xcb_map_window(window_info.connection, window_info.window); xcb_flush(window_info.connection); - return (void*)&window_info; + return true; +} + +void handleWindow(uint32_t width, uint32_t height) { + bool res = createWindow(width, height); + window_create_flag.Set(); + if (!res) { + return; + } + + xcb_intern_atom_cookie_t delete_cookie = + xcb_intern_atom(window_info.connection, 0, 16, "WM_DELETE_WINDOW"); + xcb_intern_atom_reply_t* delete_reply = + xcb_intern_atom_reply(window_info.connection, delete_cookie, 0); + + xcb_generic_event_t* event; + while ((event = xcb_wait_for_event(window_info.connection))) { + if ((event->response_type & 0x7f) == XCB_CLIENT_MESSAGE) { + auto message = (xcb_client_message_event_t*)event; + if (message->data.data32[0] == delete_reply->atom) { + break; + } + } + } +} + +void* createXcbWindow(uint32_t width, uint32_t height) { + window_thread = std::thread(handleWindow, width, height); + window_create_flag.Wait(); + return window_info.window ? (void*)&window_info : nullptr; } #elif TARGET_OS == GAPID_OS_WINDOWS static Win32WindowInfo window_info; -static HANDLE window_create_sem; -static std::mutex quit_lock; -static std::condition_variable quit_condition; -static bool quit; -static HANDLE thread; +static Flag window_create_flag; +static HANDLE window_thread; LRESULT windowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { @@ -107,7 +161,7 @@ bool createWindow(uint32_t width, uint32_t height) { DWORD handleWindow(void* data) { auto extent = (const uint32_t*)data; bool res = createWindow(extent[0], extent[1]); - ReleaseSemaphore(window_create_sem, 1, nullptr); + window_create_flag.Set(); if (!res) { return 1; } @@ -117,20 +171,14 @@ DWORD handleWindow(void* data) { TranslateMessage(&msg); DispatchMessage(&msg); } - { - std::unique_lock guard(quit_lock); - quit = true; - quit_condition.notify_all(); - } return 0; } void* createWin32Window(uint32_t width, uint32_t height) { - window_create_sem = CreateSemaphore(NULL, 0, 1, NULL); - uint32_t extent[] = {width, height}; - thread = CreateThread(NULL, 0, handleWindow, (void*)extent, 0, nullptr); - WaitForSingleObject(window_create_sem, INFINITE); + window_thread = + CreateThread(NULL, 0, handleWindow, (void*)extent, 0, nullptr); + window_create_flag.Wait(); return window_info.window ? (void*)&window_info : nullptr; } #endif @@ -148,11 +196,13 @@ void* CreateSurface(uint32_t width, uint32_t height) { void WaitForWindowClose() { #if TARGET_OS == GAPID_OS_WINDOWS - { - std::unique_lock guard(quit_lock); - while (!quit) { - quit_condition.wait(guard); - } + if (window_thread) { + WaitForSingleObject(window_thread, INFINITE); + } +#endif +#if TARGET_OS == GAPID_OS_LINUX + if (window_thread.joinable()) { + window_thread.join(); } #endif } From fc2480e7d6195e7e2012d47b30428ec6e57c8627 Mon Sep 17 00:00:00 2001 From: Sean Purcell Date: Thu, 2 Aug 2018 15:58:30 -0400 Subject: [PATCH 4/6] Ignore sigpipe in gapir --- cmd/gapir/cc/main.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cmd/gapir/cc/main.cpp b/cmd/gapir/cc/main.cpp index 6df458e408..ee0c58a259 100644 --- a/cmd/gapir/cc/main.cpp +++ b/cmd/gapir/cc/main.cpp @@ -31,6 +31,7 @@ #include "core/cc/supported_abis.h" #include "core/cc/target.h" +#include #include #include #include @@ -272,6 +273,11 @@ int main(int argc, const char* argv[]) { } } +#if TARGET_OS == GAPID_OS_LINUX + // Ignore SIGPIPE so we can log after gapis closes. + signal(SIGPIPE, SIG_IGN); +#endif + if (wait_for_debugger) { GAPID_INFO("Waiting for debugger to attach"); core::Debugger::waitForAttach(); From b6a56e6b8103863b9dc793f4f67bd25ed99fa84f Mon Sep 17 00:00:00 2001 From: Sean Purcell Date: Thu, 2 Aug 2018 17:58:36 -0400 Subject: [PATCH 5/6] Use surface types created in trace as hint --- gapir/cc/surface.cpp | 22 +++++-- gapir/cc/surface.h | 9 ++- .../api/templates/vulkan_gfx_api_extras.tmpl | 60 ++++++++++++++----- gapis/api/vulkan/custom_replay.go | 8 ++- gapis/api/vulkan/replay.go | 39 ++++++++++-- gapis/api/vulkan/replay.proto | 1 + gapis/api/vulkan/synthetic.api | 4 +- 7 files changed, 115 insertions(+), 28 deletions(-) diff --git a/gapir/cc/surface.cpp b/gapir/cc/surface.cpp index 4569fcd2ae..93ac43fdbd 100644 --- a/gapir/cc/surface.cpp +++ b/gapir/cc/surface.cpp @@ -183,15 +183,27 @@ void* createWin32Window(uint32_t width, uint32_t height) { } #endif -void* CreateSurface(uint32_t width, uint32_t height) { +const void* CreateSurface(uint32_t width, uint32_t height, SurfaceType& type) { + switch (type) { #if TARGET_OS == GAPID_OS_ANDROID - return (void*)android_window; + case SurfaceType::Android: + case SurfaceType::Unknown: + type = SurfaceType::Android; + return (void*)android_window; #elif TARGET_OS == GAPID_OS_LINUX - return createXcbWindow(width, height); + case SurfaceType::Xcb: + case SurfaceType::Unknown: + type = SurfaceType::Xcb; + return createXcbWindow(width, height); #elif TARGET_OS == GAPID_OS_WINDOWS - return createWin32Window(width, height); + case SurfaceType::Win32: + case SurfaceType::Unknown: + type = SurfaceType::Win32; + return createWin32Window(width, height); #endif - return nullptr; + default: + return nullptr; + } } void WaitForWindowClose() { diff --git a/gapir/cc/surface.h b/gapir/cc/surface.h index 56f41c2bcd..701d127f75 100644 --- a/gapir/cc/surface.h +++ b/gapir/cc/surface.h @@ -45,8 +45,15 @@ struct Win32WindowInfo { }; #endif +enum SurfaceType { + Unknown, + Android, + Win32, + Xcb, +}; + // Get the platform-specific data pointer to create the surface -void* CreateSurface(uint32_t width, uint32_t height); +const void* CreateSurface(uint32_t width, uint32_t height, SurfaceType& type); void WaitForWindowClose(); diff --git a/gapis/api/templates/vulkan_gfx_api_extras.tmpl b/gapis/api/templates/vulkan_gfx_api_extras.tmpl index 255bfa27c8..9b6ad1c914 100644 --- a/gapis/api/templates/vulkan_gfx_api_extras.tmpl +++ b/gapis/api/templates/vulkan_gfx_api_extras.tmpl @@ -356,27 +356,57 @@ bool Vulkan::replayCreateVkDeviceImpl(Stack* stack, size_val physicalDevice, // Copy any extra fields vsPNext = *pNext; - void* data = CreateSurface(newCreateInfo.imageExtent.Width, - newCreateInfo.imageExtent.Height); + gapir::SurfaceType target = gapir::SurfaceType::Unknown; + switch (*(uint32_t*)pNext->surfaceCreateInfo) { + case VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR: + target = gapir::SurfaceType::Android; + break; + // These are all linux, so just make an Xcb surface + case VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR: + case VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR: + case VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR: + case VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR: + target = gapir::SurfaceType::Xcb; + break; + case VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR: + target = gapir::SurfaceType::Win32; + } + + const void* data = CreateSurface(newCreateInfo.imageExtent.Width, + newCreateInfo.imageExtent.Height, target); void* createInfo = nullptr; if (data != nullptr) { + switch (target) { #if TARGET_OS == GAPID_OS_ANDROID - createInfo = &surfaceInfo; - surfaceInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR; - surfaceInfo.window = (ANativeWindow*)data; + case gapir::SurfaceType::Android: + createInfo = &surfaceInfo; + surfaceInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR; + surfaceInfo.window = (ANativeWindow*)data; + break; #elif TARGET_OS == GAPID_OS_LINUX - createInfo = &surfaceInfo; - auto info = (XcbWindowInfo*)data; - surfaceInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; - surfaceInfo.connection = info->connection; - surfaceInfo.window = info->window; + case gapir::SurfaceType::Xcb: + createInfo = &surfaceInfo; + { + auto info = (XcbWindowInfo*)data; + surfaceInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; + surfaceInfo.connection = info->connection; + surfaceInfo.window = info->window; + } + break; #elif TARGET_OS == GAPID_OS_WINDOWS - createInfo = &surfaceInfo; - auto info = (Win32WindowInfo*)data; - surfaceInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; - surfaceInfo.hinstance = (HINSTANCE)info->instance; - surfaceInfo.hwnd = (HWND)info->window; + case gapir::SurfaceType::Win32: + createInfo = &surfaceInfo; + { + auto info = (Win32WindowInfo*)data; + surfaceInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; + surfaceInfo.hinstance = (HINSTANCE)info->instance; + surfaceInfo.hwnd = (HWND)info->window; + } + break; #endif + default: + break; + } } vsPNext.surfaceCreateInfo = createInfo; vsPNext.pNext = newCreateInfo.pNext; diff --git a/gapis/api/vulkan/custom_replay.go b/gapis/api/vulkan/custom_replay.go index 85960699c1..b64776262c 100644 --- a/gapis/api/vulkan/custom_replay.go +++ b/gapis/api/vulkan/custom_replay.go @@ -383,9 +383,13 @@ func (a *VkCreateSwapchainKHR) Mutate(ctx context.Context, id api.CmdID, s *api. 0, // surfaceCreateInfo ) for _, extra := range a.Extras().All() { - if _, ok := extra.(*DisplayToSurface); ok { + if d, ok := extra.(*DisplayToSurface); ok { log.D(ctx, "Activating display to surface") - pNext.SetSurfaceCreateInfo(1) + sType, _ := d.SurfaceTypes[uint64(info.Surface())] + sTypeData := s.AllocDataOrPanic(ctx, sType) + defer sTypeData.Free() + pNext.SetSurfaceCreateInfo(NewVoidᶜᵖ(sTypeData.Ptr())) + hijack.AddRead(sTypeData.Data()) } } pNextData := s.AllocDataOrPanic(ctx, pNext) diff --git a/gapis/api/vulkan/replay.go b/gapis/api/vulkan/replay.go index 5eccdb222d..005bff3d02 100644 --- a/gapis/api/vulkan/replay.go +++ b/gapis/api/vulkan/replay.go @@ -441,19 +441,50 @@ func (t *destroyResourcesAtEOS) Flush(ctx context.Context, out transform.Writer) } } +func newDisplayToSurface() *DisplayToSurface { + return &DisplayToSurface{ + SurfaceTypes: map[uint64]uint32{}, + } +} + // DisplayToSurface is a transformation that enables rendering during replay to // the original surface. func (t *DisplayToSurface) Transform(ctx context.Context, id api.CmdID, cmd api.Cmd, out transform.Writer) { - if c, ok := cmd.(*VkCreateSwapchainKHR); ok { + switch c := cmd.(type) { + case *VkCreateSwapchainKHR: newCmd := c.Clone(out.State().Arena) newCmd.extras = api.CmdExtras{} // Add an extra to indicate to custom_replay to add a flag to // the virtual swapchain pNext newCmd.extras = append(api.CmdExtras{t}, cmd.Extras().All()...) out.MutateAndWrite(ctx, id, newCmd) - } else { - out.MutateAndWrite(ctx, id, cmd) + return + case *VkCreateAndroidSurfaceKHR: + cmd.Extras().Observations().ApplyWrites(out.State().Memory.ApplicationPool()) + surface := c.PSurface().MustRead(ctx, cmd, out.State(), nil) + t.SurfaceTypes[uint64(surface)] = uint32(VkStructureType_VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR) + case *VkCreateMirSurfaceKHR: + cmd.Extras().Observations().ApplyWrites(out.State().Memory.ApplicationPool()) + surface := c.PSurface().MustRead(ctx, cmd, out.State(), nil) + t.SurfaceTypes[uint64(surface)] = uint32(VkStructureType_VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR) + case *VkCreateWaylandSurfaceKHR: + cmd.Extras().Observations().ApplyWrites(out.State().Memory.ApplicationPool()) + surface := c.PSurface().MustRead(ctx, cmd, out.State(), nil) + t.SurfaceTypes[uint64(surface)] = uint32(VkStructureType_VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR) + case *VkCreateWin32SurfaceKHR: + cmd.Extras().Observations().ApplyWrites(out.State().Memory.ApplicationPool()) + surface := c.PSurface().MustRead(ctx, cmd, out.State(), nil) + t.SurfaceTypes[uint64(surface)] = uint32(VkStructureType_VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR) + case *VkCreateXcbSurfaceKHR: + cmd.Extras().Observations().ApplyWrites(out.State().Memory.ApplicationPool()) + surface := c.PSurface().MustRead(ctx, cmd, out.State(), nil) + t.SurfaceTypes[uint64(surface)] = uint32(VkStructureType_VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR) + case *VkCreateXlibSurfaceKHR: + cmd.Extras().Observations().ApplyWrites(out.State().Memory.ApplicationPool()) + surface := c.PSurface().MustRead(ctx, cmd, out.State(), nil) + t.SurfaceTypes[uint64(surface)] = uint32(VkStructureType_VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR) } + out.MutateAndWrite(ctx, id, cmd) } func (t *DisplayToSurface) Flush(ctx context.Context, out transform.Writer) { @@ -630,7 +661,7 @@ func (a API) Replay( } if doDisplayToSurface { - transforms.Add(&DisplayToSurface{}) + transforms.Add(newDisplayToSurface()) } if issues != nil { diff --git a/gapis/api/vulkan/replay.proto b/gapis/api/vulkan/replay.proto index 4d1c5a460e..45dbc9ff37 100644 --- a/gapis/api/vulkan/replay.proto +++ b/gapis/api/vulkan/replay.proto @@ -20,4 +20,5 @@ option go_package = "github.com/google/gapid/gapis/api/vulkan"; // DisplayToSurface is an extra added to VkCreateSwapchainKHR to indicate the // replay should display to the original surface. message DisplayToSurface { + map surface_types = 1; } diff --git a/gapis/api/vulkan/synthetic.api b/gapis/api/vulkan/synthetic.api index 435089ab02..16b0ae0655 100644 --- a/gapis/api/vulkan/synthetic.api +++ b/gapis/api/vulkan/synthetic.api @@ -174,7 +174,9 @@ cmd VkResult ReplayCreateSwapchain( switch sType { case VK_STRUCTURE_TYPE_VIRTUAL_SWAPCHAIN_PNEXT: { ext := as!VirtualSwapchainPNext*(next.Ptr)[0:1][0] - _ = ext.surfaceCreateInfo + if ext.surfaceCreateInfo != null { + _ = as!VkStructureType*(ext.surfaceCreateInfo)[0:1][0] + } } } next.Ptr = as!VulkanStructHeader*(next.Ptr)[0:1][0].PNext From 842a767aadc0233e911e6030a3601cbfd92fc75e Mon Sep 17 00:00:00 2001 From: Sean Purcell Date: Fri, 3 Aug 2018 15:53:37 -0400 Subject: [PATCH 6/6] Clean up platform-specific handling --- core/vulkan/vk_virtual_swapchain/cc/layer.cpp | 8 ++++-- core/vulkan/vk_virtual_swapchain/cc/layer.h | 8 ++++-- .../vk_virtual_swapchain/cc/platform.cpp | 8 ++++-- .../api/templates/vulkan_gfx_api_extras.tmpl | 28 +++++++++---------- 4 files changed, 29 insertions(+), 23 deletions(-) diff --git a/core/vulkan/vk_virtual_swapchain/cc/layer.cpp b/core/vulkan/vk_virtual_swapchain/cc/layer.cpp index 807109e9c8..16d56df869 100644 --- a/core/vulkan/vk_virtual_swapchain/cc/layer.cpp +++ b/core/vulkan/vk_virtual_swapchain/cc/layer.cpp @@ -135,11 +135,13 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance( GET_PROC(vkGetPhysicalDeviceProperties); GET_PROC(vkGetPhysicalDeviceMemoryProperties); -#if defined(VK_USE_PLATFORM_ANDROID_KHR) +#ifdef VK_USE_PLATFORM_ANDROID_KHR GET_PROC(vkCreateAndroidSurfaceKHR); -#elif defined(VK_USE_PLATFORM_XCB_KHR) +#endif +#ifdef VK_USE_PLATFORM_XCB_KHR GET_PROC(vkCreateXcbSurfaceKHR); -#elif defined(VK_USE_PLATFORM_WIN32_KHR) +#endif +#ifdef VK_USE_PLATFORM_WIN32_KHR GET_PROC(vkCreateWin32SurfaceKHR); #endif GET_PROC(vkDestroySurfaceKHR); diff --git a/core/vulkan/vk_virtual_swapchain/cc/layer.h b/core/vulkan/vk_virtual_swapchain/cc/layer.h index d09915c02a..d32a7a4646 100644 --- a/core/vulkan/vk_virtual_swapchain/cc/layer.h +++ b/core/vulkan/vk_virtual_swapchain/cc/layer.h @@ -49,11 +49,13 @@ struct InstanceData { PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties; PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties; -#if defined(VK_USE_PLATFORM_ANDROID_KHR) +#ifdef VK_USE_PLATFORM_ANDROID_KHR PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR; -#elif defined(VK_USE_PLATFORM_XCB_KHR) +#endif +#ifdef VK_USE_PLATFORM_XCB_KHR PFN_vkCreateXcbSurfaceKHR vkCreateXcbSurfaceKHR; -#elif defined(VK_USE_PLATFORM_WIN32_KHR) +#endif +#ifdef VK_USE_PLATFORM_WIN32_KHR PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR; #endif PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR; diff --git a/core/vulkan/vk_virtual_swapchain/cc/platform.cpp b/core/vulkan/vk_virtual_swapchain/cc/platform.cpp index 77bde08e14..cf00c08c34 100644 --- a/core/vulkan/vk_virtual_swapchain/cc/platform.cpp +++ b/core/vulkan/vk_virtual_swapchain/cc/platform.cpp @@ -22,7 +22,7 @@ void CreateSurface(const InstanceData* functions, VkInstance instance, const void* data, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) { *pSurface = 0; -#if defined(VK_USE_PLATFORM_ANDROID_KHR) +#ifdef VK_USE_PLATFORM_ANDROID_KHR { auto pCreateInfo = static_cast(data); if (pCreateInfo->sType == @@ -34,7 +34,8 @@ void CreateSurface(const InstanceData* functions, VkInstance instance, } } } -#elif defined(VK_USE_PLATFORM_XCB_KHR) +#endif +#ifdef VK_USE_PLATFORM_XCB_KHR { auto pCreateInfo = static_cast(data); if (pCreateInfo->sType == VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR) { @@ -45,7 +46,8 @@ void CreateSurface(const InstanceData* functions, VkInstance instance, } } } -#elif defined(VK_USE_PLATFORM_WIN32_KHR) +#endif +#ifdef VK_USE_PLATFORM_WIN32_KHR { auto pCreateInfo = static_cast(data); if (pCreateInfo->sType == VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR) { diff --git a/gapis/api/templates/vulkan_gfx_api_extras.tmpl b/gapis/api/templates/vulkan_gfx_api_extras.tmpl index 9b6ad1c914..3f16709d56 100644 --- a/gapis/api/templates/vulkan_gfx_api_extras.tmpl +++ b/gapis/api/templates/vulkan_gfx_api_extras.tmpl @@ -342,11 +342,11 @@ bool Vulkan::replayCreateVkDeviceImpl(Stack* stack, size_val physicalDevice, swapchain::CreateNext vsPNext; #if TARGET_OS == GAPID_OS_ANDROID - VkAndroidSurfaceCreateInfoKHR surfaceInfo = {}; + VkAndroidSurfaceCreateInfoKHR androidInfo = {}; #elif TARGET_OS == GAPID_OS_LINUX - VkXcbSurfaceCreateInfoKHR surfaceInfo = {}; + VkXcbSurfaceCreateInfoKHR xcbInfo = {}; #elif TARGET_OS == GAPID_OS_WINDOWS - VkWin32SurfaceCreateInfoKHR surfaceInfo = {}; + VkWin32SurfaceCreateInfoKHR win32Info = {}; #endif for (auto pNext = static_cast(newCreateInfo.pNext); pNext != nullptr; @@ -379,28 +379,28 @@ bool Vulkan::replayCreateVkDeviceImpl(Stack* stack, size_val physicalDevice, switch (target) { #if TARGET_OS == GAPID_OS_ANDROID case gapir::SurfaceType::Android: - createInfo = &surfaceInfo; - surfaceInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR; - surfaceInfo.window = (ANativeWindow*)data; + createInfo = &androidInfo; + androidInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR; + androidInfo.window = (ANativeWindow*)data; break; #elif TARGET_OS == GAPID_OS_LINUX case gapir::SurfaceType::Xcb: - createInfo = &surfaceInfo; + createInfo = &xcbInfo; { auto info = (XcbWindowInfo*)data; - surfaceInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; - surfaceInfo.connection = info->connection; - surfaceInfo.window = info->window; + xcbInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; + xcbInfo.connection = info->connection; + xcbInfo.window = info->window; } break; #elif TARGET_OS == GAPID_OS_WINDOWS case gapir::SurfaceType::Win32: - createInfo = &surfaceInfo; + createInfo = &win32Info; { auto info = (Win32WindowInfo*)data; - surfaceInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; - surfaceInfo.hinstance = (HINSTANCE)info->instance; - surfaceInfo.hwnd = (HWND)info->window; + win32Info.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; + win32Info.hinstance = (HINSTANCE)info->instance; + win32Info.hwnd = (HWND)info->window; } break; #endif