diff --git a/Makefile.am b/Makefile.am index 22850f358a36b5b8874aee49dec6b11e740b5300..24779e72a080d1a432a61f3f9574d30bbafbcba2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -320,6 +320,7 @@ vkd3d_demos = \ vkd3d_demos_headers = \ demos/demo.h \ + demos/demo_vkd3d.h \ demos/demo_win32.h \ demos/demo_xcb.h diff --git a/demos/demo.h b/demos/demo.h index 24302007b16abc66a3a3a7764a5b5bc1d2be174d..b2ae8ce146119d61deb9d09007cf7ab40f5fe899 100644 --- a/demos/demo.h +++ b/demos/demo.h @@ -178,5 +178,5 @@ static inline HRESULT demo_create_root_signature(ID3D12Device *device, #include "demo_win32.h" #else #define INFINITE VKD3D_INFINITE -#include "demo_xcb.h" +#include "demo_vkd3d.h" #endif diff --git a/demos/demo_vkd3d.h b/demos/demo_vkd3d.h new file mode 100644 index 0000000000000000000000000000000000000000..c7f82e9c935fea4c72a0e842566ee308920a06b2 --- /dev/null +++ b/demos/demo_vkd3d.h @@ -0,0 +1,508 @@ +/* + * Copyright 2016 Józef Kucia for CodeWeavers + * Copyright 2016 Henri Verbeet for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define VK_NO_PROTOTYPES +#define VK_USE_PLATFORM_XCB_KHR +#define VKD3D_UTILS_API_VERSION VKD3D_API_VERSION_1_15 +#include "config.h" +#include <vkd3d.h> +#include <vkd3d_utils.h> +#include <xcb/xcb_event.h> +#include <xcb/xcb_icccm.h> +#include <xcb/xcb_keysyms.h> +#include <dlfcn.h> +#include <limits.h> +#include <stdbool.h> +#include <stdio.h> + +#define DECLARE_VK_PFN(name) PFN_##name name; +DECLARE_VK_PFN(vkAcquireNextImageKHR) +DECLARE_VK_PFN(vkCreateFence) +DECLARE_VK_PFN(vkCreateSwapchainKHR) +DECLARE_VK_PFN(vkCreateXcbSurfaceKHR) +DECLARE_VK_PFN(vkDestroyFence) +DECLARE_VK_PFN(vkDestroySurfaceKHR) +DECLARE_VK_PFN(vkDestroySwapchainKHR) +DECLARE_VK_PFN(vkGetPhysicalDeviceSurfaceCapabilitiesKHR) +DECLARE_VK_PFN(vkGetPhysicalDeviceSurfaceFormatsKHR) +DECLARE_VK_PFN(vkGetPhysicalDeviceSurfaceSupportKHR) +DECLARE_VK_PFN(vkGetSwapchainImagesKHR) +DECLARE_VK_PFN(vkQueuePresentKHR) +DECLARE_VK_PFN(vkResetFences) +DECLARE_VK_PFN(vkWaitForFences) + +struct demo_xcb +{ + xcb_connection_t *connection; + xcb_atom_t wm_protocols_atom; + xcb_atom_t wm_delete_window_atom; + xcb_key_symbols_t *xcb_keysyms; + int screen; +}; + +struct demo +{ + struct demo_xcb xcb; + + struct demo_window **windows; + size_t windows_size; + size_t window_count; + + void *user_data; + void (*idle_func)(struct demo *demo, void *user_data); +}; + +struct demo_window +{ + struct demo *demo; + + void *user_data; + void (*expose_func)(struct demo_window *window, void *user_data); + void (*key_press_func)(struct demo_window *window, demo_key key, void *user_data); +}; + +static inline bool demo_add_window(struct demo *demo, struct demo_window *window) +{ + if (demo->window_count == demo->windows_size) + { + size_t new_capacity; + void *new_elements; + + new_capacity = max(demo->windows_size * 2, 4); + if (!(new_elements = realloc(demo->windows, new_capacity * sizeof(*demo->windows)))) + return false; + demo->windows = new_elements; + demo->windows_size = new_capacity; + } + + demo->windows[demo->window_count++] = window; + + return true; +} + +static inline void demo_remove_window(struct demo *demo, const struct demo_window *window) +{ + size_t i; + + for (i = 0; i < demo->window_count; ++i) + { + if (demo->windows[i] != window) + continue; + + --demo->window_count; + memmove(&demo->windows[i], &demo->windows[i + 1], (demo->window_count - i) * sizeof(*demo->windows)); + break; + } +} + +static inline bool demo_window_init(struct demo_window *window, struct demo *demo, void *user_data) +{ + if (!demo_add_window(demo, window)) + return false; + + window->demo = demo; + window->user_data = user_data; + window->expose_func = NULL; + window->key_press_func = NULL; + + return true; +} + +static inline void demo_window_cleanup(struct demo_window *window) +{ + demo_remove_window(window->demo, window); +} + +#include "demo_xcb.h" + +static void load_vulkan_procs(void) +{ + void *libvulkan; + + if (!(libvulkan = dlopen(SONAME_LIBVULKAN, RTLD_NOW))) + { + fprintf(stderr, "Failed to load %s: %s.\n", SONAME_LIBVULKAN, dlerror()); + exit(1); + } + +#define LOAD_VK_PFN(name) name = (void *)dlsym(libvulkan, #name); + LOAD_VK_PFN(vkAcquireNextImageKHR) + LOAD_VK_PFN(vkCreateFence) + LOAD_VK_PFN(vkCreateSwapchainKHR) + LOAD_VK_PFN(vkCreateXcbSurfaceKHR) + LOAD_VK_PFN(vkDestroyFence) + LOAD_VK_PFN(vkDestroySurfaceKHR) + LOAD_VK_PFN(vkDestroySwapchainKHR) + LOAD_VK_PFN(vkGetPhysicalDeviceSurfaceCapabilitiesKHR) + LOAD_VK_PFN(vkGetPhysicalDeviceSurfaceFormatsKHR) + LOAD_VK_PFN(vkGetPhysicalDeviceSurfaceSupportKHR) + LOAD_VK_PFN(vkGetSwapchainImagesKHR) + LOAD_VK_PFN(vkQueuePresentKHR) + LOAD_VK_PFN(vkResetFences) + LOAD_VK_PFN(vkWaitForFences) +} + +struct demo_swapchain +{ + VkSurfaceKHR vk_surface; + VkSwapchainKHR vk_swapchain; + VkFence vk_fence; + + VkInstance vk_instance; + VkDevice vk_device; + ID3D12CommandQueue *command_queue; + + ID3D12Fence *present_fence; + unsigned long long present_count; + + uint32_t current_buffer; + unsigned int buffer_count; + ID3D12Resource *buffers[1]; +}; + +static inline void demo_cleanup(struct demo *demo) +{ + free(demo->windows); + demo_xcb_cleanup(demo); +} + +static inline bool demo_init(struct demo *demo, void *user_data) +{ + if (!demo_xcb_init(&demo->xcb)) + return false; + + demo->windows = NULL; + demo->windows_size = 0; + demo->window_count = 0; + demo->user_data = user_data; + demo->idle_func = NULL; + + return true; +} + +static inline void demo_get_dpi(struct demo *demo, double *dpi_x, double *dpi_y) +{ + demo_xcb_get_dpi(demo, dpi_x, dpi_y); +} + +static inline void demo_process_events(struct demo *demo) +{ + demo_xcb_process_events(demo); +} + +static inline void demo_set_idle_func(struct demo *demo, + void (*idle_func)(struct demo *demo, void *user_data)) +{ + demo->idle_func = idle_func; +} + +static inline void demo_window_destroy(struct demo_window *window) +{ + demo_window_xcb_destroy(window); +} + +static inline struct demo_window *demo_window_create(struct demo *demo, const char *title, + unsigned int width, unsigned int height, void *user_data) +{ + return demo_window_xcb_create(demo, title, width, height, user_data); +} + +static inline void demo_window_set_expose_func(struct demo_window *window, + void (*expose_func)(struct demo_window *window, void *user_data)) +{ + window->expose_func = expose_func; +} + +static inline void demo_window_set_key_press_func(struct demo_window *window, + void (*key_press_func)(struct demo_window *window, demo_key key, void *user_data)) +{ + window->key_press_func = key_press_func; +} + +static inline struct demo_swapchain *demo_swapchain_create(ID3D12CommandQueue *command_queue, + struct demo_window *window, const struct demo_swapchain_desc *desc) +{ + struct vkd3d_image_resource_create_info resource_create_info; + struct VkSwapchainCreateInfoKHR vk_swapchain_desc; + VkSwapchainKHR vk_swapchain = VK_NULL_HANDLE; + uint32_t format_count, queue_family_index; + VkSurfaceCapabilitiesKHR surface_caps; + VkPhysicalDevice vk_physical_device; + VkFence vk_fence = VK_NULL_HANDLE; + struct demo_swapchain *swapchain; + unsigned int image_count, i, j; + VkFenceCreateInfo fence_desc; + VkSurfaceFormatKHR *formats; + ID3D12Device *d3d12_device; + VkSurfaceKHR vk_surface; + VkInstance vk_instance; + VkBool32 supported; + VkDevice vk_device; + VkImage *vk_images; + VkFormat format; + + load_vulkan_procs(); + + if ((format = vkd3d_get_vk_format(desc->format)) == VK_FORMAT_UNDEFINED) + return NULL; + + if (FAILED(ID3D12CommandQueue_GetDevice(command_queue, &IID_ID3D12Device, (void **)&d3d12_device))) + return NULL; + + vk_instance = vkd3d_instance_get_vk_instance(vkd3d_instance_from_device(d3d12_device)); + vk_physical_device = vkd3d_get_vk_physical_device(d3d12_device); + vk_device = vkd3d_get_vk_device(d3d12_device); + + if (!(vk_surface = demo_window_xcb_create_vk_surface(window, vk_instance))) + { + ID3D12Device_Release(d3d12_device); + return NULL; + } + + queue_family_index = vkd3d_get_vk_queue_family_index(command_queue); + if (vkGetPhysicalDeviceSurfaceSupportKHR(vk_physical_device, + queue_family_index, vk_surface, &supported) < 0 || !supported) + goto fail; + + if (vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vk_physical_device, vk_surface, &surface_caps) < 0) + goto fail; + + if ((surface_caps.maxImageCount && desc->buffer_count > surface_caps.maxImageCount) + || desc->buffer_count < surface_caps.minImageCount + || desc->width > surface_caps.maxImageExtent.width || desc->width < surface_caps.minImageExtent.width + || desc->height > surface_caps.maxImageExtent.height || desc->height < surface_caps.minImageExtent.height + || !(surface_caps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR)) + goto fail; + + if (vkGetPhysicalDeviceSurfaceFormatsKHR(vk_physical_device, vk_surface, &format_count, NULL) < 0 + || !format_count || !(formats = calloc(format_count, sizeof(*formats)))) + goto fail; + + if (vkGetPhysicalDeviceSurfaceFormatsKHR(vk_physical_device, vk_surface, &format_count, formats) < 0) + { + free(formats); + goto fail; + } + + if (format_count != 1 || formats->format != VK_FORMAT_UNDEFINED + || formats->colorSpace != VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) + { + for (i = 0; i < format_count; ++i) + { + if (formats[i].format == format && formats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) + break; + } + + if (i == format_count) + { + free(formats); + goto fail; + } + } + + free(formats); + formats = NULL; + + vk_swapchain_desc.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + vk_swapchain_desc.pNext = NULL; + vk_swapchain_desc.flags = 0; + vk_swapchain_desc.surface = vk_surface; + vk_swapchain_desc.minImageCount = desc->buffer_count; + vk_swapchain_desc.imageFormat = format; + vk_swapchain_desc.imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; + vk_swapchain_desc.imageExtent.width = desc->width; + vk_swapchain_desc.imageExtent.height = desc->height; + vk_swapchain_desc.imageArrayLayers = 1; + vk_swapchain_desc.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + vk_swapchain_desc.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + vk_swapchain_desc.queueFamilyIndexCount = 0; + vk_swapchain_desc.pQueueFamilyIndices = NULL; + vk_swapchain_desc.preTransform = surface_caps.currentTransform; + vk_swapchain_desc.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + vk_swapchain_desc.presentMode = VK_PRESENT_MODE_FIFO_KHR; + vk_swapchain_desc.clipped = VK_TRUE; + vk_swapchain_desc.oldSwapchain = VK_NULL_HANDLE; + if (vkCreateSwapchainKHR(vk_device, &vk_swapchain_desc, NULL, &vk_swapchain) < 0) + goto fail; + + fence_desc.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fence_desc.pNext = NULL; + fence_desc.flags = 0; + if (vkCreateFence(vk_device, &fence_desc, NULL, &vk_fence) < 0) + goto fail; + + if (vkGetSwapchainImagesKHR(vk_device, vk_swapchain, &image_count, NULL) < 0 + || !(vk_images = calloc(image_count, sizeof(*vk_images)))) + goto fail; + + if (vkGetSwapchainImagesKHR(vk_device, vk_swapchain, &image_count, vk_images) < 0) + { + free(vk_images); + goto fail; + } + + if (!(swapchain = malloc(offsetof(struct demo_swapchain, buffers[image_count])))) + { + free(vk_images); + goto fail; + } + swapchain->vk_surface = vk_surface; + swapchain->vk_swapchain = vk_swapchain; + swapchain->vk_fence = vk_fence; + swapchain->vk_instance = vk_instance; + swapchain->vk_device = vk_device; + + vkAcquireNextImageKHR(vk_device, vk_swapchain, UINT64_MAX, + VK_NULL_HANDLE, vk_fence, &swapchain->current_buffer); + vkWaitForFences(vk_device, 1, &vk_fence, VK_TRUE, UINT64_MAX); + vkResetFences(vk_device, 1, &vk_fence); + + resource_create_info.type = VKD3D_STRUCTURE_TYPE_IMAGE_RESOURCE_CREATE_INFO; + resource_create_info.next = NULL; + resource_create_info.desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + resource_create_info.desc.Alignment = 0; + resource_create_info.desc.Width = desc->width; + resource_create_info.desc.Height = desc->height; + resource_create_info.desc.DepthOrArraySize = 1; + resource_create_info.desc.MipLevels = 1; + resource_create_info.desc.Format = desc->format; + resource_create_info.desc.SampleDesc.Count = 1; + resource_create_info.desc.SampleDesc.Quality = 0; + resource_create_info.desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + resource_create_info.desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; + resource_create_info.flags = VKD3D_RESOURCE_INITIAL_STATE_TRANSITION | VKD3D_RESOURCE_PRESENT_STATE_TRANSITION; + resource_create_info.present_state = D3D12_RESOURCE_STATE_PRESENT; + for (i = 0; i < image_count; ++i) + { + resource_create_info.vk_image = vk_images[i]; + if (FAILED(vkd3d_create_image_resource(d3d12_device, &resource_create_info, &swapchain->buffers[i]))) + { + for (j = 0; j < i; ++j) + { + ID3D12Resource_Release(swapchain->buffers[j]); + } + free(swapchain); + free(vk_images); + goto fail; + } + } + swapchain->buffer_count = image_count; + free(vk_images); + + if (FAILED(ID3D12Device_CreateFence(d3d12_device, 0, 0, &IID_ID3D12Fence, (void **)&swapchain->present_fence))) + { + for (i = 0; i < image_count; ++i) + { + ID3D12Resource_Release(swapchain->buffers[i]); + } + free(swapchain); + goto fail; + } + swapchain->present_count = 0; + ID3D12Device_Release(d3d12_device); + + ID3D12CommandQueue_AddRef(swapchain->command_queue = command_queue); + + return swapchain; + +fail: + if (vk_fence != VK_NULL_HANDLE) + vkDestroyFence(vk_device, vk_fence, NULL); + if (vk_swapchain != VK_NULL_HANDLE) + vkDestroySwapchainKHR(vk_device, vk_swapchain, NULL); + vkDestroySurfaceKHR(vk_instance, vk_surface, NULL); + ID3D12Device_Release(d3d12_device); + return NULL; +} + +static inline unsigned int demo_swapchain_get_current_back_buffer_index(struct demo_swapchain *swapchain) +{ + return swapchain->current_buffer; +} + +static inline ID3D12Resource *demo_swapchain_get_back_buffer(struct demo_swapchain *swapchain, unsigned int index) +{ + ID3D12Resource *resource = NULL; + + if (index < swapchain->buffer_count && (resource = swapchain->buffers[index])) + ID3D12Resource_AddRef(resource); + + return resource; +} + +static inline void demo_swapchain_present(struct demo_swapchain *swapchain) +{ + VkPresentInfoKHR present_desc; + VkQueue vk_queue; + + present_desc.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + present_desc.pNext = NULL; + present_desc.waitSemaphoreCount = 0; + present_desc.pWaitSemaphores = NULL; + present_desc.swapchainCount = 1; + present_desc.pSwapchains = &swapchain->vk_swapchain; + present_desc.pImageIndices = &swapchain->current_buffer; + present_desc.pResults = NULL; + + /* Synchronize vkd3d_acquire_vk_queue() with the Direct3D 12 work + * already submitted to the command queue. */ + ++swapchain->present_count; + ID3D12CommandQueue_Signal(swapchain->command_queue, swapchain->present_fence, swapchain->present_count); + ID3D12Fence_SetEventOnCompletion(swapchain->present_fence, swapchain->present_count, NULL); + + vk_queue = vkd3d_acquire_vk_queue(swapchain->command_queue); + vkQueuePresentKHR(vk_queue, &present_desc); + vkd3d_release_vk_queue(swapchain->command_queue); + + vkAcquireNextImageKHR(swapchain->vk_device, swapchain->vk_swapchain, UINT64_MAX, + VK_NULL_HANDLE, swapchain->vk_fence, &swapchain->current_buffer); + vkWaitForFences(swapchain->vk_device, 1, &swapchain->vk_fence, VK_TRUE, UINT64_MAX); + vkResetFences(swapchain->vk_device, 1, &swapchain->vk_fence); +} + +static inline void demo_swapchain_destroy(struct demo_swapchain *swapchain) +{ + unsigned int i; + + ID3D12CommandQueue_Release(swapchain->command_queue); + ID3D12Fence_Release(swapchain->present_fence); + for (i = 0; i < swapchain->buffer_count; ++i) + { + ID3D12Resource_Release(swapchain->buffers[i]); + } + vkDestroyFence(swapchain->vk_device, swapchain->vk_fence, NULL); + vkDestroySwapchainKHR(swapchain->vk_device, swapchain->vk_swapchain, NULL); + vkDestroySurfaceKHR(swapchain->vk_instance, swapchain->vk_surface, NULL); + free(swapchain); +} + +static inline HANDLE demo_create_event(void) +{ + return vkd3d_create_event(); +} + +static inline unsigned int demo_wait_event(HANDLE event, unsigned int ms) +{ + return vkd3d_wait_event(event, ms); +} + +static inline void demo_destroy_event(HANDLE event) +{ + vkd3d_destroy_event(event); +} diff --git a/demos/demo_xcb.h b/demos/demo_xcb.h index b1f61212a5854a1d48b6ea03467a7c4220f4baf2..fa8046aa9a2f5b79984e70175371dd52767cd919 100644 --- a/demos/demo_xcb.h +++ b/demos/demo_xcb.h @@ -17,111 +17,28 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#define VK_NO_PROTOTYPES -#define VK_USE_PLATFORM_XCB_KHR -#define VKD3D_UTILS_API_VERSION VKD3D_API_VERSION_1_15 -#include "config.h" -#include <vkd3d.h> -#include <vkd3d_utils.h> -#include <xcb/xcb_event.h> -#include <xcb/xcb_icccm.h> -#include <xcb/xcb_keysyms.h> -#include <sys/stat.h> -#include <dlfcn.h> -#include <limits.h> -#include <unistd.h> -#include <fcntl.h> -#include <stdbool.h> -#include <stdio.h> - -#define DECLARE_VK_PFN(name) PFN_##name name; -DECLARE_VK_PFN(vkAcquireNextImageKHR) -DECLARE_VK_PFN(vkCreateFence) -DECLARE_VK_PFN(vkCreateSwapchainKHR) -DECLARE_VK_PFN(vkCreateXcbSurfaceKHR) -DECLARE_VK_PFN(vkDestroyFence) -DECLARE_VK_PFN(vkDestroySurfaceKHR) -DECLARE_VK_PFN(vkDestroySwapchainKHR) -DECLARE_VK_PFN(vkGetPhysicalDeviceSurfaceCapabilitiesKHR) -DECLARE_VK_PFN(vkGetPhysicalDeviceSurfaceFormatsKHR) -DECLARE_VK_PFN(vkGetPhysicalDeviceSurfaceSupportKHR) -DECLARE_VK_PFN(vkGetSwapchainImagesKHR) -DECLARE_VK_PFN(vkQueuePresentKHR) -DECLARE_VK_PFN(vkResetFences) -DECLARE_VK_PFN(vkWaitForFences) - -static void load_vulkan_procs(void) +struct demo_window_xcb { - void *libvulkan; + struct demo_window w; - if (!(libvulkan = dlopen(SONAME_LIBVULKAN, RTLD_NOW))) - { - fprintf(stderr, "Failed to load %s: %s.\n", SONAME_LIBVULKAN, dlerror()); - exit(1); - } - -#define LOAD_VK_PFN(name) name = (void *)dlsym(libvulkan, #name); - LOAD_VK_PFN(vkAcquireNextImageKHR) - LOAD_VK_PFN(vkCreateFence) - LOAD_VK_PFN(vkCreateSwapchainKHR) - LOAD_VK_PFN(vkCreateXcbSurfaceKHR) - LOAD_VK_PFN(vkDestroyFence) - LOAD_VK_PFN(vkDestroySurfaceKHR) - LOAD_VK_PFN(vkDestroySwapchainKHR) - LOAD_VK_PFN(vkGetPhysicalDeviceSurfaceCapabilitiesKHR) - LOAD_VK_PFN(vkGetPhysicalDeviceSurfaceFormatsKHR) - LOAD_VK_PFN(vkGetPhysicalDeviceSurfaceSupportKHR) - LOAD_VK_PFN(vkGetSwapchainImagesKHR) - LOAD_VK_PFN(vkQueuePresentKHR) - LOAD_VK_PFN(vkResetFences) - LOAD_VK_PFN(vkWaitForFences) -} - -struct demo -{ - xcb_connection_t *connection; - xcb_atom_t wm_protocols_atom; - xcb_atom_t wm_delete_window_atom; - xcb_key_symbols_t *xcb_keysyms; - int screen; - - struct demo_window **windows; - size_t windows_size; - size_t window_count; - - void *user_data; - void (*idle_func)(struct demo *demo, void *user_data); -}; - -struct demo_window -{ xcb_window_t window; - struct demo *demo; - - void *user_data; - void (*expose_func)(struct demo_window *window, void *user_data); - void (*key_press_func)(struct demo_window *window, demo_key key, void *user_data); }; -struct demo_swapchain +static xcb_screen_t *demo_xcb_get_screen(xcb_connection_t *c, int idx) { - VkSurfaceKHR vk_surface; - VkSwapchainKHR vk_swapchain; - VkFence vk_fence; - - VkInstance vk_instance; - VkDevice vk_device; - ID3D12CommandQueue *command_queue; + xcb_screen_iterator_t iter; - ID3D12Fence *present_fence; - unsigned long long present_count; + iter = xcb_setup_roots_iterator(xcb_get_setup(c)); + for (; iter.rem; xcb_screen_next(&iter), --idx) + { + if (!idx) + return iter.data; + } - uint32_t current_buffer; - unsigned int buffer_count; - ID3D12Resource *buffers[1]; -}; + return NULL; +} -static inline xcb_atom_t demo_get_atom(xcb_connection_t *c, const char *name) +static xcb_atom_t demo_xcb_get_atom(xcb_connection_t *c, const char *name) { xcb_intern_atom_cookie_t cookie; xcb_intern_atom_reply_t *reply; @@ -137,167 +54,128 @@ static inline xcb_atom_t demo_get_atom(xcb_connection_t *c, const char *name) return atom; } -static inline bool demo_add_window(struct demo *demo, struct demo_window *window) -{ - if (demo->window_count == demo->windows_size) - { - size_t new_capacity; - void *new_elements; - - new_capacity = max(demo->windows_size * 2, 4); - if (!(new_elements = realloc(demo->windows, new_capacity * sizeof(*demo->windows)))) - return false; - demo->windows = new_elements; - demo->windows_size = new_capacity; - } - - demo->windows[demo->window_count++] = window; - - return true; -} - -static inline void demo_remove_window(struct demo *demo, const struct demo_window *window) +static struct demo_window_xcb *demo_xcb_find_xcb_window(struct demo *demo, xcb_window_t window) { size_t i; for (i = 0; i < demo->window_count; ++i) { - if (demo->windows[i] != window) - continue; - - --demo->window_count; - memmove(&demo->windows[i], &demo->windows[i + 1], (demo->window_count - i) * sizeof(*demo->windows)); - break; - } -} + struct demo_window_xcb *window_xcb = CONTAINING_RECORD(demo->windows[i], struct demo_window_xcb, w); -static inline struct demo_window *demo_find_window(struct demo *demo, xcb_window_t window) -{ - size_t i; - - for (i = 0; i < demo->window_count; ++i) - { - if (demo->windows[i]->window == window) - return demo->windows[i]; + if (window_xcb->window == window) + return window_xcb; } return NULL; } -static inline xcb_screen_t *demo_get_screen(xcb_connection_t *c, int idx) +static VkSurfaceKHR demo_window_xcb_create_vk_surface(struct demo_window *window, VkInstance vk_instance) { - xcb_screen_iterator_t iter; + struct demo_window_xcb *window_xcb = CONTAINING_RECORD(window, struct demo_window_xcb, w); + struct VkXcbSurfaceCreateInfoKHR surface_desc; + VkSurfaceKHR vk_surface; - iter = xcb_setup_roots_iterator(xcb_get_setup(c)); - for (; iter.rem; xcb_screen_next(&iter), --idx) - { - if (!idx) - return iter.data; - } + surface_desc.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; + surface_desc.pNext = NULL; + surface_desc.flags = 0; + surface_desc.connection = window->demo->xcb.connection; + surface_desc.window = window_xcb->window; + if (vkCreateXcbSurfaceKHR(vk_instance, &surface_desc, NULL, &vk_surface) < 0) + return VK_NULL_HANDLE; - return NULL; + return vk_surface; } -static inline void demo_get_dpi(struct demo *demo, double *dpi_x, double *dpi_y) +static void demo_window_xcb_destroy(struct demo_window *window) { - xcb_screen_t *screen; + struct demo_window_xcb *window_xcb = CONTAINING_RECORD(window, struct demo_window_xcb, w); + struct demo_xcb *xcb = &window->demo->xcb; - if (!(screen = demo_get_screen(demo->connection, demo->screen))) - { - *dpi_x = *dpi_y = 96.0; - return; - } - - *dpi_x = screen->width_in_pixels * 25.4 / screen->width_in_millimeters; - *dpi_y = screen->height_in_pixels * 25.4 / screen->height_in_millimeters; + xcb_destroy_window(xcb->connection, window_xcb->window); + xcb_flush(xcb->connection); + demo_window_cleanup(&window_xcb->w); + free(window_xcb); } -static inline struct demo_window *demo_window_create(struct demo *demo, const char *title, +static struct demo_window *demo_window_xcb_create(struct demo *demo, const char *title, unsigned int width, unsigned int height, void *user_data) { - static const uint32_t window_events = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS; - - struct demo_window *window; + struct demo_window_xcb *window_xcb; + struct demo_xcb *xcb = &demo->xcb; xcb_size_hints_t hints; xcb_screen_t *screen; - if (!(screen = demo_get_screen(demo->connection, demo->screen))) + static const uint32_t window_events = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS; + + if (!(screen = demo_xcb_get_screen(xcb->connection, xcb->screen))) return NULL; - if (!(window = malloc(sizeof(*window)))) + if (!(window_xcb = malloc(sizeof(*window_xcb)))) return NULL; - if (!demo_add_window(demo, window)) + if (!demo_window_init(&window_xcb->w, demo, user_data)) { - free(window); + free(window_xcb); return NULL; } - window->window = xcb_generate_id(demo->connection); - window->demo = demo; - window->user_data = user_data; - window->expose_func = NULL; - window->key_press_func = NULL; - xcb_create_window(demo->connection, XCB_COPY_FROM_PARENT, window->window, screen->root, 0, 0, + window_xcb->window = xcb_generate_id(xcb->connection); + xcb_create_window(xcb->connection, XCB_COPY_FROM_PARENT, window_xcb->window, screen->root, 0, 0, width, height, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, XCB_CW_EVENT_MASK, &window_events); - xcb_change_property(demo->connection, XCB_PROP_MODE_REPLACE, window->window, XCB_ATOM_WM_NAME, + xcb_change_property(xcb->connection, XCB_PROP_MODE_REPLACE, window_xcb->window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, strlen(title), title); - xcb_change_property(demo->connection, XCB_PROP_MODE_REPLACE, window->window, demo->wm_protocols_atom, - XCB_ATOM_ATOM, 32, 1, &demo->wm_delete_window_atom); + xcb_change_property(xcb->connection, XCB_PROP_MODE_REPLACE, window_xcb->window, xcb->wm_protocols_atom, + XCB_ATOM_ATOM, 32, 1, &xcb->wm_delete_window_atom); hints.flags = XCB_ICCCM_SIZE_HINT_P_MIN_SIZE | XCB_ICCCM_SIZE_HINT_P_MAX_SIZE; hints.min_width = width; hints.min_height = height; hints.max_width = width; hints.max_height = height; - xcb_change_property(demo->connection, XCB_PROP_MODE_REPLACE, window->window, XCB_ATOM_WM_NORMAL_HINTS, + xcb_change_property(xcb->connection, XCB_PROP_MODE_REPLACE, window_xcb->window, XCB_ATOM_WM_NORMAL_HINTS, XCB_ATOM_WM_SIZE_HINTS, 32, sizeof(hints) >> 2, &hints); - xcb_map_window(demo->connection, window->window); + xcb_map_window(xcb->connection, window_xcb->window); - xcb_flush(demo->connection); + xcb_flush(xcb->connection); - return window; + return &window_xcb->w; } -static inline void demo_window_destroy(struct demo_window *window) +static void demo_xcb_get_dpi(struct demo *demo, double *dpi_x, double *dpi_y) { - xcb_destroy_window(window->demo->connection, window->window); - xcb_flush(window->demo->connection); - demo_remove_window(window->demo, window); - free(window); -} + struct demo_xcb *xcb = &demo->xcb; + xcb_screen_t *screen; -static inline void demo_window_set_key_press_func(struct demo_window *window, - void (*key_press_func)(struct demo_window *window, demo_key key, void *user_data)) -{ - window->key_press_func = key_press_func; -} + if (!(screen = demo_xcb_get_screen(xcb->connection, xcb->screen))) + { + *dpi_x = *dpi_y = 96.0; + return; + } -static inline void demo_window_set_expose_func(struct demo_window *window, - void (*expose_func)(struct demo_window *window, void *user_data)) -{ - window->expose_func = expose_func; + *dpi_x = screen->width_in_pixels * 25.4 / screen->width_in_millimeters; + *dpi_y = screen->height_in_pixels * 25.4 / screen->height_in_millimeters; } -static inline void demo_process_events(struct demo *demo) +static void demo_xcb_process_events(struct demo *demo) { const struct xcb_client_message_event_t *client_message; struct xcb_key_press_event_t *key_press; + struct demo_window_xcb *window_xcb; + struct demo_xcb *xcb = &demo->xcb; xcb_generic_event_t *event; - struct demo_window *window; xcb_keysym_t sym; - xcb_flush(demo->connection); + xcb_flush(xcb->connection); while (demo->window_count) { if (!demo->idle_func) { - if (!(event = xcb_wait_for_event(demo->connection))) + if (!(event = xcb_wait_for_event(xcb->connection))) break; } - else if (!(event = xcb_poll_for_event(demo->connection))) + else if (!(event = xcb_poll_for_event(xcb->connection))) { demo->idle_func(demo, demo->user_data); continue; @@ -306,25 +184,25 @@ static inline void demo_process_events(struct demo *demo) switch (XCB_EVENT_RESPONSE_TYPE(event)) { case XCB_EXPOSE: - if ((window = demo_find_window(demo, ((struct xcb_expose_event_t *)event)->window)) - && window->expose_func) - window->expose_func(window, window->user_data); + if ((window_xcb = demo_xcb_find_xcb_window(demo, ((struct xcb_expose_event_t *)event)->window)) + && window_xcb->w.expose_func) + window_xcb->w.expose_func(&window_xcb->w, window_xcb->w.user_data); break; case XCB_KEY_PRESS: key_press = (struct xcb_key_press_event_t *)event; - if (!(window = demo_find_window(demo, key_press->event)) || !window->key_press_func) + if (!(window_xcb = demo_xcb_find_xcb_window(demo, key_press->event)) || !window_xcb->w.key_press_func) break; - sym = xcb_key_press_lookup_keysym(demo->xcb_keysyms, key_press, 0); - window->key_press_func(window, sym, window->user_data); + sym = xcb_key_press_lookup_keysym(xcb->xcb_keysyms, key_press, 0); + window_xcb->w.key_press_func(&window_xcb->w, sym, window_xcb->w.user_data); break; case XCB_CLIENT_MESSAGE: client_message = (xcb_client_message_event_t *)event; - if (client_message->type == demo->wm_protocols_atom - && client_message->data.data32[0] == demo->wm_delete_window_atom - && (window = demo_find_window(demo, client_message->window))) - demo_window_destroy(window); + if (client_message->type == xcb->wm_protocols_atom + && client_message->data.data32[0] == xcb->wm_delete_window_atom + && (window_xcb = demo_xcb_find_xcb_window(demo, client_message->window))) + demo_window_xcb_destroy(&window_xcb->w); break; } @@ -332,319 +210,30 @@ static inline void demo_process_events(struct demo *demo) } } -static inline bool demo_init(struct demo *demo, void *user_data) -{ - if (!(demo->connection = xcb_connect(NULL, &demo->screen))) - return false; - if (xcb_connection_has_error(demo->connection) > 0) - goto fail; - if ((demo->wm_delete_window_atom = demo_get_atom(demo->connection, "WM_DELETE_WINDOW")) == XCB_NONE) - goto fail; - if ((demo->wm_protocols_atom = demo_get_atom(demo->connection, "WM_PROTOCOLS")) == XCB_NONE) - goto fail; - if (!(demo->xcb_keysyms = xcb_key_symbols_alloc(demo->connection))) - goto fail; - - demo->windows = NULL; - demo->windows_size = 0; - demo->window_count = 0; - demo->user_data = user_data; - demo->idle_func = NULL; - - return true; - -fail: - xcb_disconnect(demo->connection); - return false; -} - -static inline void demo_cleanup(struct demo *demo) +static void demo_xcb_cleanup(struct demo *demo) { - free(demo->windows); - xcb_key_symbols_free(demo->xcb_keysyms); - xcb_disconnect(demo->connection); -} + struct demo_xcb *xcb = &demo->xcb; -static inline void demo_set_idle_func(struct demo *demo, - void (*idle_func)(struct demo *demo, void *user_data)) -{ - demo->idle_func = idle_func; + xcb_key_symbols_free(xcb->xcb_keysyms); + xcb_disconnect(xcb->connection); } -static inline struct demo_swapchain *demo_swapchain_create(ID3D12CommandQueue *command_queue, - struct demo_window *window, const struct demo_swapchain_desc *desc) +static bool demo_xcb_init(struct demo_xcb *xcb) { - struct vkd3d_image_resource_create_info resource_create_info; - struct VkSwapchainCreateInfoKHR vk_swapchain_desc; - struct VkXcbSurfaceCreateInfoKHR surface_desc; - VkSwapchainKHR vk_swapchain = VK_NULL_HANDLE; - uint32_t format_count, queue_family_index; - VkSurfaceCapabilitiesKHR surface_caps; - VkPhysicalDevice vk_physical_device; - VkFence vk_fence = VK_NULL_HANDLE; - struct demo_swapchain *swapchain; - unsigned int image_count, i, j; - VkFenceCreateInfo fence_desc; - VkSurfaceFormatKHR *formats; - ID3D12Device *d3d12_device; - VkSurfaceKHR vk_surface; - VkInstance vk_instance; - VkBool32 supported; - VkDevice vk_device; - VkImage *vk_images; - VkFormat format; - - load_vulkan_procs(); - - if ((format = vkd3d_get_vk_format(desc->format)) == VK_FORMAT_UNDEFINED) - return NULL; - - if (FAILED(ID3D12CommandQueue_GetDevice(command_queue, &IID_ID3D12Device, (void **)&d3d12_device))) - return NULL; - - vk_instance = vkd3d_instance_get_vk_instance(vkd3d_instance_from_device(d3d12_device)); - vk_physical_device = vkd3d_get_vk_physical_device(d3d12_device); - vk_device = vkd3d_get_vk_device(d3d12_device); - - surface_desc.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; - surface_desc.pNext = NULL; - surface_desc.flags = 0; - surface_desc.connection = window->demo->connection; - surface_desc.window = window->window; - if (vkCreateXcbSurfaceKHR(vk_instance, &surface_desc, NULL, &vk_surface) < 0) - { - ID3D12Device_Release(d3d12_device); - return NULL; - } - - queue_family_index = vkd3d_get_vk_queue_family_index(command_queue); - if (vkGetPhysicalDeviceSurfaceSupportKHR(vk_physical_device, - queue_family_index, vk_surface, &supported) < 0 || !supported) - goto fail; - - if (vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vk_physical_device, vk_surface, &surface_caps) < 0) - goto fail; - - if ((surface_caps.maxImageCount && desc->buffer_count > surface_caps.maxImageCount) - || desc->buffer_count < surface_caps.minImageCount - || desc->width > surface_caps.maxImageExtent.width || desc->width < surface_caps.minImageExtent.width - || desc->height > surface_caps.maxImageExtent.height || desc->height < surface_caps.minImageExtent.height - || !(surface_caps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR)) - goto fail; - - if (vkGetPhysicalDeviceSurfaceFormatsKHR(vk_physical_device, vk_surface, &format_count, NULL) < 0 - || !format_count || !(formats = calloc(format_count, sizeof(*formats)))) - goto fail; - - if (vkGetPhysicalDeviceSurfaceFormatsKHR(vk_physical_device, vk_surface, &format_count, formats) < 0) - { - free(formats); - goto fail; - } - - if (format_count != 1 || formats->format != VK_FORMAT_UNDEFINED - || formats->colorSpace != VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) - { - for (i = 0; i < format_count; ++i) - { - if (formats[i].format == format && formats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) - break; - } - - if (i == format_count) - { - free(formats); - goto fail; - } - } - - free(formats); - formats = NULL; - - vk_swapchain_desc.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; - vk_swapchain_desc.pNext = NULL; - vk_swapchain_desc.flags = 0; - vk_swapchain_desc.surface = vk_surface; - vk_swapchain_desc.minImageCount = desc->buffer_count; - vk_swapchain_desc.imageFormat = format; - vk_swapchain_desc.imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; - vk_swapchain_desc.imageExtent.width = desc->width; - vk_swapchain_desc.imageExtent.height = desc->height; - vk_swapchain_desc.imageArrayLayers = 1; - vk_swapchain_desc.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - vk_swapchain_desc.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; - vk_swapchain_desc.queueFamilyIndexCount = 0; - vk_swapchain_desc.pQueueFamilyIndices = NULL; - vk_swapchain_desc.preTransform = surface_caps.currentTransform; - vk_swapchain_desc.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; - vk_swapchain_desc.presentMode = VK_PRESENT_MODE_FIFO_KHR; - vk_swapchain_desc.clipped = VK_TRUE; - vk_swapchain_desc.oldSwapchain = VK_NULL_HANDLE; - if (vkCreateSwapchainKHR(vk_device, &vk_swapchain_desc, NULL, &vk_swapchain) < 0) - goto fail; - - fence_desc.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - fence_desc.pNext = NULL; - fence_desc.flags = 0; - if (vkCreateFence(vk_device, &fence_desc, NULL, &vk_fence) < 0) - goto fail; - - if (vkGetSwapchainImagesKHR(vk_device, vk_swapchain, &image_count, NULL) < 0 - || !(vk_images = calloc(image_count, sizeof(*vk_images)))) + if (!(xcb->connection = xcb_connect(NULL, &xcb->screen))) + return false; + if (xcb_connection_has_error(xcb->connection) > 0) goto fail; - - if (vkGetSwapchainImagesKHR(vk_device, vk_swapchain, &image_count, vk_images) < 0) - { - free(vk_images); + if ((xcb->wm_delete_window_atom = demo_xcb_get_atom(xcb->connection, "WM_DELETE_WINDOW")) == XCB_NONE) goto fail; - } - - if (!(swapchain = malloc(offsetof(struct demo_swapchain, buffers[image_count])))) - { - free(vk_images); + if ((xcb->wm_protocols_atom = demo_xcb_get_atom(xcb->connection, "WM_PROTOCOLS")) == XCB_NONE) goto fail; - } - swapchain->vk_surface = vk_surface; - swapchain->vk_swapchain = vk_swapchain; - swapchain->vk_fence = vk_fence; - swapchain->vk_instance = vk_instance; - swapchain->vk_device = vk_device; - - vkAcquireNextImageKHR(vk_device, vk_swapchain, UINT64_MAX, - VK_NULL_HANDLE, vk_fence, &swapchain->current_buffer); - vkWaitForFences(vk_device, 1, &vk_fence, VK_TRUE, UINT64_MAX); - vkResetFences(vk_device, 1, &vk_fence); - - resource_create_info.type = VKD3D_STRUCTURE_TYPE_IMAGE_RESOURCE_CREATE_INFO; - resource_create_info.next = NULL; - resource_create_info.desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; - resource_create_info.desc.Alignment = 0; - resource_create_info.desc.Width = desc->width; - resource_create_info.desc.Height = desc->height; - resource_create_info.desc.DepthOrArraySize = 1; - resource_create_info.desc.MipLevels = 1; - resource_create_info.desc.Format = desc->format; - resource_create_info.desc.SampleDesc.Count = 1; - resource_create_info.desc.SampleDesc.Quality = 0; - resource_create_info.desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; - resource_create_info.desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; - resource_create_info.flags = VKD3D_RESOURCE_INITIAL_STATE_TRANSITION | VKD3D_RESOURCE_PRESENT_STATE_TRANSITION; - resource_create_info.present_state = D3D12_RESOURCE_STATE_PRESENT; - for (i = 0; i < image_count; ++i) - { - resource_create_info.vk_image = vk_images[i]; - if (FAILED(vkd3d_create_image_resource(d3d12_device, &resource_create_info, &swapchain->buffers[i]))) - { - for (j = 0; j < i; ++j) - { - ID3D12Resource_Release(swapchain->buffers[j]); - } - free(swapchain); - free(vk_images); - goto fail; - } - } - swapchain->buffer_count = image_count; - free(vk_images); - - if (FAILED(ID3D12Device_CreateFence(d3d12_device, 0, 0, &IID_ID3D12Fence, (void **)&swapchain->present_fence))) - { - for (i = 0; i < image_count; ++i) - { - ID3D12Resource_Release(swapchain->buffers[i]); - } - free(swapchain); + if (!(xcb->xcb_keysyms = xcb_key_symbols_alloc(xcb->connection))) goto fail; - } - swapchain->present_count = 0; - ID3D12Device_Release(d3d12_device); - ID3D12CommandQueue_AddRef(swapchain->command_queue = command_queue); - - return swapchain; + return true; fail: - if (vk_fence != VK_NULL_HANDLE) - vkDestroyFence(vk_device, vk_fence, NULL); - if (vk_swapchain != VK_NULL_HANDLE) - vkDestroySwapchainKHR(vk_device, vk_swapchain, NULL); - vkDestroySurfaceKHR(vk_instance, vk_surface, NULL); - ID3D12Device_Release(d3d12_device); - return NULL; -} - -static inline unsigned int demo_swapchain_get_current_back_buffer_index(struct demo_swapchain *swapchain) -{ - return swapchain->current_buffer; -} - -static inline ID3D12Resource *demo_swapchain_get_back_buffer(struct demo_swapchain *swapchain, unsigned int index) -{ - ID3D12Resource *resource = NULL; - - if (index < swapchain->buffer_count && (resource = swapchain->buffers[index])) - ID3D12Resource_AddRef(resource); - - return resource; -} - -static inline void demo_swapchain_present(struct demo_swapchain *swapchain) -{ - VkPresentInfoKHR present_desc; - VkQueue vk_queue; - - present_desc.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; - present_desc.pNext = NULL; - present_desc.waitSemaphoreCount = 0; - present_desc.pWaitSemaphores = NULL; - present_desc.swapchainCount = 1; - present_desc.pSwapchains = &swapchain->vk_swapchain; - present_desc.pImageIndices = &swapchain->current_buffer; - present_desc.pResults = NULL; - - /* Synchronize vkd3d_acquire_vk_queue() with the Direct3D 12 work - * already submitted to the command queue. */ - ++swapchain->present_count; - ID3D12CommandQueue_Signal(swapchain->command_queue, swapchain->present_fence, swapchain->present_count); - ID3D12Fence_SetEventOnCompletion(swapchain->present_fence, swapchain->present_count, NULL); - - vk_queue = vkd3d_acquire_vk_queue(swapchain->command_queue); - vkQueuePresentKHR(vk_queue, &present_desc); - vkd3d_release_vk_queue(swapchain->command_queue); - - vkAcquireNextImageKHR(swapchain->vk_device, swapchain->vk_swapchain, UINT64_MAX, - VK_NULL_HANDLE, swapchain->vk_fence, &swapchain->current_buffer); - vkWaitForFences(swapchain->vk_device, 1, &swapchain->vk_fence, VK_TRUE, UINT64_MAX); - vkResetFences(swapchain->vk_device, 1, &swapchain->vk_fence); -} - -static inline void demo_swapchain_destroy(struct demo_swapchain *swapchain) -{ - unsigned int i; - - ID3D12CommandQueue_Release(swapchain->command_queue); - ID3D12Fence_Release(swapchain->present_fence); - for (i = 0; i < swapchain->buffer_count; ++i) - { - ID3D12Resource_Release(swapchain->buffers[i]); - } - vkDestroyFence(swapchain->vk_device, swapchain->vk_fence, NULL); - vkDestroySwapchainKHR(swapchain->vk_device, swapchain->vk_swapchain, NULL); - vkDestroySurfaceKHR(swapchain->vk_instance, swapchain->vk_surface, NULL); - free(swapchain); -} - -static inline HANDLE demo_create_event(void) -{ - return vkd3d_create_event(); -} - -static inline unsigned int demo_wait_event(HANDLE event, unsigned int ms) -{ - return vkd3d_wait_event(event, ms); -} - -static inline void demo_destroy_event(HANDLE event) -{ - vkd3d_destroy_event(event); + xcb_disconnect(xcb->connection); + return false; }