diff --git a/gfx/common/vulkan_common.c b/gfx/common/vulkan_common.c index fe9a91a0a8..b90badcf7f 100644 --- a/gfx/common/vulkan_common.c +++ b/gfx/common/vulkan_common.c @@ -13,9 +13,31 @@ * If not, see . */ -#include "vulkan_common.h" #include +#include "vulkan_common.h" + +#ifdef HAVE_VULKAN +static VkInstance cached_instance; +static VkDevice cached_device; +#endif + +#define VK_GET_INSTANCE_PROC_ADDR(vk, inst, entrypoint) do { \ + vk->fp##entrypoint = (PFN_vk##entrypoint) vkGetInstanceProcAddr(inst, "vk"#entrypoint); \ + if (vk->fp##entrypoint == NULL) { \ + RARCH_ERR("vkGetInstanceProcAddr failed to find vk%s\n", #entrypoint); \ + return false; \ + } \ +} while(0) + +#define VK_GET_DEVICE_PROC_ADDR(vk, dev, entrypoint) do { \ + vk->fp##entrypoint = (PFN_vk##entrypoint) vkGetDeviceProcAddr(dev, "vk" #entrypoint); \ + if (vk->fp##entrypoint == NULL) { \ + RARCH_ERR("vkGetDeviceProcAddr failed to find vk%s\n", #entrypoint); \ + return false; \ + } \ +} while(0) + uint32_t vulkan_find_memory_type(const VkPhysicalDeviceMemoryProperties *mem_props, uint32_t device_reqs, uint32_t host_reqs) { @@ -774,3 +796,569 @@ void vulkan_buffer_chain_free(VkDevice device, struct vk_buffer_chain *chain) memset(chain, 0, sizeof(*chain)); } +bool vulkan_context_init(gfx_ctx_vulkan_data_t *vk, + enum vulkan_wsi_type type) +{ + unsigned i; + uint32_t queue_count; + VkQueueFamilyProperties queue_properties[32]; + VkInstanceCreateInfo info = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO }; + VkApplicationInfo app = { VK_STRUCTURE_TYPE_APPLICATION_INFO }; + VkPhysicalDeviceFeatures features = { false }; + VkDeviceQueueCreateInfo queue_info = { VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO }; + VkDeviceCreateInfo device_info = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO }; + uint32_t gpu_count = 1; + bool found_queue = false; + static const float one = 1.0f; + static const char *device_extensions[] = { + "VK_KHR_swapchain", + }; + static const char *instance_extensions[2]; + + instance_extensions[0] = "VK_KHR_surface"; + + switch (type) + { + case VULKAN_WSI_WAYLAND: + instance_extensions[1] = "VK_KHR_wayland_surface"; + break; + case VULKAN_WSI_ANDROID: + instance_extensions[1] = "VK_KHR_android_surface"; + break; + case VULKAN_WSI_WIN32: + instance_extensions[1] = "VK_KHR_win32_surface"; + break; + case VULKAN_WSI_XLIB: + instance_extensions[1] = "VK_KHR_xlib_surface"; + break; + case VULKAN_WSI_XCB: + instance_extensions[1] = "VK_KHR_xcb_surface"; + break; + case VULKAN_WSI_MIR: + instance_extensions[1] = "VK_KHR_mir_surface"; + break; + case VULKAN_WSI_NONE: + default: + break; + } + + app.pApplicationName = "RetroArch"; + app.applicationVersion = 0; + app.pEngineName = "RetroArch"; + app.engineVersion = 0; + app.apiVersion = VK_API_VERSION; + + info.pApplicationInfo = &app; + info.enabledExtensionCount = ARRAY_SIZE(instance_extensions); + info.ppEnabledExtensionNames = instance_extensions; + + if (cached_instance) + { + vk->context.instance = cached_instance; + cached_instance = NULL; + } + else if (vkCreateInstance(&info, NULL, &vk->context.instance) != VK_SUCCESS) + return false; + + if (vkEnumeratePhysicalDevices(vk->context.instance, + &gpu_count, &vk->context.gpu) != VK_SUCCESS) + return false; + + if (gpu_count != 1) + { + RARCH_ERR("[Vulkan]: Failed to enumerate Vulkan physical device.\n"); + return false; + } + + vkGetPhysicalDeviceProperties(vk->context.gpu, + &vk->context.gpu_properties); + vkGetPhysicalDeviceMemoryProperties(vk->context.gpu, + &vk->context.memory_properties); + vkGetPhysicalDeviceQueueFamilyProperties(vk->context.gpu, + &queue_count, NULL); + + if (queue_count < 1 || queue_count > 32) + return false; + + vkGetPhysicalDeviceQueueFamilyProperties(vk->context.gpu, + &queue_count, queue_properties); + + for (i = 0; i < queue_count; i++) + { + if (queue_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) + { + vk->context.graphics_queue_index = i; + RARCH_LOG("[Vulkan]: Device supports %u sub-queues.\n", + queue_properties[i].queueCount); + found_queue = true; + break; + } + } + + if (!found_queue) + { + RARCH_ERR("[Vulkan]: Did not find suitable graphics queue.\n"); + return false; + } + + queue_info.queueFamilyIndex = vk->context.graphics_queue_index; + queue_info.queueCount = 1; + queue_info.pQueuePriorities = &one; + + device_info.queueCreateInfoCount = 1; + device_info.pQueueCreateInfos = &queue_info; + device_info.enabledExtensionCount = ARRAY_SIZE(device_extensions); + device_info.ppEnabledExtensionNames = device_extensions; + device_info.pEnabledFeatures = &features; + + if (cached_device) + { + vk->context.device = cached_device; + cached_device = NULL; + video_driver_ctl(RARCH_DISPLAY_CTL_SET_VIDEO_CACHE_CONTEXT_ACK, NULL); + RARCH_LOG("[Vulkan]: Using cached Vulkan context.\n"); + } + else if (vkCreateDevice(vk->context.gpu, &device_info, + NULL, &vk->context.device) != VK_SUCCESS) + return false; + + vkGetDeviceQueue(vk->context.device, + vk->context.graphics_queue_index, 0, &vk->context.queue); + + VK_GET_INSTANCE_PROC_ADDR(vk, + vk->context.instance, GetPhysicalDeviceSurfaceSupportKHR); + VK_GET_INSTANCE_PROC_ADDR(vk, + vk->context.instance, GetPhysicalDeviceSurfaceCapabilitiesKHR); + VK_GET_INSTANCE_PROC_ADDR(vk, + vk->context.instance, GetPhysicalDeviceSurfaceFormatsKHR); + VK_GET_INSTANCE_PROC_ADDR(vk, + vk->context.instance, GetPhysicalDeviceSurfacePresentModesKHR); + VK_GET_INSTANCE_PROC_ADDR(vk, + vk->context.instance, DestroySurfaceKHR); + VK_GET_DEVICE_PROC_ADDR(vk, + vk->context.device, CreateSwapchainKHR); + VK_GET_DEVICE_PROC_ADDR(vk, + vk->context.device, DestroySwapchainKHR); + VK_GET_DEVICE_PROC_ADDR(vk, + vk->context.device, GetSwapchainImagesKHR); + VK_GET_DEVICE_PROC_ADDR(vk, + vk->context.device, AcquireNextImageKHR); + VK_GET_DEVICE_PROC_ADDR(vk, + vk->context.device, QueuePresentKHR); + + switch (type) + { + case VULKAN_WSI_WAYLAND: +#ifdef HAVE_WAYLAND + VK_GET_INSTANCE_PROC_ADDR(vk, + vk->context.instance, CreateWaylandSurfaceKHR); +#endif + break; + case VULKAN_WSI_ANDROID: +#ifdef ANDROID + VK_GET_INSTANCE_PROC_ADDR(vk, + vk->context.instance, CreateAndroidSurfaceKHR); +#endif + break; + case VULKAN_WSI_WIN32: +#ifdef _WIN32 + VK_GET_INSTANCE_PROC_ADDR(vk, + vk->context.instance, CreateWin32SurfaceKHR); +#endif + break; + case VULKAN_WSI_XLIB: +#ifdef HAVE_XLIB + VK_GET_INSTANCE_PROC_ADDR(vk, + vk->context.instance, CreateXlibSurfaceKHR); +#endif + break; + case VULKAN_WSI_XCB: +#ifdef HAVE_XCB + VK_GET_INSTANCE_PROC_ADDR(vk, + vk->context.instance, CreateXcbSurfaceKHR); +#endif + break; + case VULKAN_WSI_MIR: +#ifdef HAVE_MIR + VK_GET_INSTANCE_PROC_ADDR(vk, + vk->context.instance, CreateMirSurfaceKHR); +#endif + break; + case VULKAN_WSI_NONE: + default: + break; + } + + vk->context.queue_lock = slock_new(); + if (!vk->context.queue_lock) + return false; + + return true; +} + +bool vulkan_surface_create(gfx_ctx_vulkan_data_t *vk, + enum vulkan_wsi_type type, + void *display, void *surface, + unsigned width, unsigned height, + unsigned swap_interval) +{ + switch (type) + { + case VULKAN_WSI_WAYLAND: +#ifdef HAVE_WAYLAND + { + VkWaylandSurfaceCreateInfoKHR surf_info; + + memset(&surf_info, 0, sizeof(VkWaylandSurfaceCreateInfoKHR)); + + surf_info.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR; + surf_info.pNext = NULL; + surf_info.flags = 0; + surf_info.display = (struct wl_display*)display; + surf_info.surface = (struct wl_surface*)surface; + + if (vk->fpCreateWaylandSurfaceKHR(vk->context.instance, + &surf_info, NULL, &vk->vk_surface) != VK_SUCCESS) + return false; + } +#endif + break; + case VULKAN_WSI_ANDROID: +#ifdef ANDROID + { + VkAndroidSurfaceCreateInfoKHR surf_info; + + memset(&surf_info, 0, sizeof(VkAndroidSurfaceCreateInfoKHR)); + + surf_info.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR; + surf_info.flags = 0; + surf_info.window = (ANativeWindow*)surface; + + if (vk->fpCreateAndroidSurfaceKHR(vk->context.instance, + &surf_info, NULL, &vk->vk_surface) != VK_SUCCESS) + return false; + } +#endif + break; + case VULKAN_WSI_WIN32: +#ifdef _WIN32 + { + VkWin32SurfaceCreateInfoKHR surf_info; + + memset(&surf_info, 0, sizeof(VkWin32SurfaceCreateInfoKHR)); + + surf_info.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; + surf_info.flags = 0; + surf_info.hinstance = display; + surf_info.hwnd = surface; + + if (vk->fpCreateWin32SurfaceKHR(vk->context.instance, + &surf_info, NULL, &vk->vk_surface) != VK_SUCCESS) + return false; + } +#endif + break; + case VULKAN_WSI_XLIB: +#ifdef HAVE_XLIB + { + VkXlibSurfaceCreateInfoKHR surf_info; + + memset(&surf_info, 0, sizeof(VkXlibSurfaceCreateInfoKHR)); + + surf_info.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR; + surf_info.flags = 0; + surf_info.dpy = display; + surf_info.window = surface; + + if (vk->fpCreateXlibSurfaceKHR(vk->context.instance, + &surf_info, NULL, &vk->vk_surface) + != VK_SUCCESS) + return false; + } +#endif + break; + case VULKAN_WSI_XCB: +#ifdef HAVE_XCB + { + VkXcbSurfaceCreateInfoKHR surf_info; + + memset(&surf_info, 0, sizeof(VkXcbSurfaceCreateInfoKHR)); + + surf_info.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; + surf_info.flags = 0; + surf_info.connection = XGetXCBConnection(display); + surf_info.window = (xcb_window_t)surface; + + if (vk->fpCreateXcbSurfaceKHR(vk->context.instance, + &surf_info, NULL, &vk->vk_surface) + != VK_SUCCESS) + return false; + } +#endif + break; + case VULKAN_WSI_MIR: +#ifdef HAVE_MIR + { + VkMirSurfaceCreateInfoKHR surf_info; + + memset(&surf_info, 0, sizeof(VkMirSurfaceCreateInfoKHR)); + + surf_info.sType = VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR; + surf_info.connection = display; + surf_info.mirSurface = surface; + + if (vk->fpCreateMirSurfaceKHR(vk->context.instance, + &surf_info, NULL, &vk->vk_surface) + != VK_SUCCESS) + return false; + } +#endif + break; + case VULKAN_WSI_NONE: + default: + return false; + } + + if (!vulkan_create_swapchain( + vk, width, height, swap_interval)) + return false; + + return true; +} + +void vulkan_present(gfx_ctx_vulkan_data_t *vk, unsigned index) +{ + VkResult result = VK_SUCCESS; + VkResult err = VK_SUCCESS; + VkPresentInfoKHR present = { VK_STRUCTURE_TYPE_PRESENT_INFO_KHR }; + present.swapchainCount = 1; + present.pSwapchains = &vk->swapchain; + present.pImageIndices = &index; + present.pResults = &result; + present.waitSemaphoreCount = 1; + present.pWaitSemaphores = &vk->context.swapchain_semaphores[index]; + + /* Better hope QueuePresent doesn't block D: */ + slock_lock(vk->context.queue_lock); + err = vk->fpQueuePresentKHR(vk->context.queue, &present); + + if (err != VK_SUCCESS || result != VK_SUCCESS) + { + RARCH_LOG("[Vulkan]: QueuePresent failed, invalidating swapchain.\n"); + vk->context.invalid_swapchain = true; + } + slock_unlock(vk->context.queue_lock); +} + +void vulkan_context_destroy(gfx_ctx_vulkan_data_t *vk, + bool destroy_surface) +{ + unsigned i; + if (vk->context.queue) + vkQueueWaitIdle(vk->context.queue); + if (vk->swapchain) + vk->fpDestroySwapchainKHR(vk->context.device, + vk->swapchain, NULL); + + if (destroy_surface) + vk->fpDestroySurfaceKHR(vk->context.instance, + vk->vk_surface, NULL); + + for (i = 0; i < VULKAN_MAX_SWAPCHAIN_IMAGES; i++) + { + if (vk->context.swapchain_semaphores[i] != VK_NULL_HANDLE) + vkDestroySemaphore(vk->context.device, + vk->context.swapchain_semaphores[i], NULL); + if (vk->context.swapchain_fences[i] != VK_NULL_HANDLE) + vkDestroyFence(vk->context.device, + vk->context.swapchain_fences[i], NULL); + } + + if (video_driver_ctl(RARCH_DISPLAY_CTL_IS_VIDEO_CACHE_CONTEXT, NULL)) + { + cached_device = vk->context.device; + cached_instance = vk->context.instance; + } + else + { + if (vk->context.device) + vkDestroyDevice(vk->context.device, NULL); + if (vk->context.instance) + vkDestroyInstance(vk->context.instance, NULL); + } +} + +void vulkan_acquire_next_image(gfx_ctx_vulkan_data_t *vk) +{ + unsigned index; + VkResult err; + VkFence fence; + VkFence *next_fence; + VkSemaphoreCreateInfo sem_info = + { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO }; + VkFenceCreateInfo info = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO }; + + vkCreateFence(vk->context.device, &info, NULL, &fence); + + err = vk->fpAcquireNextImageKHR(vk->context.device, + vk->swapchain, UINT64_MAX, + VK_NULL_HANDLE, fence, &vk->context.current_swapchain_index); + + index = vk->context.current_swapchain_index; + if (vk->context.swapchain_semaphores[index] == VK_NULL_HANDLE) + vkCreateSemaphore(vk->context.device, &sem_info, + NULL, &vk->context.swapchain_semaphores[index]); + + vkWaitForFences(vk->context.device, 1, &fence, true, UINT64_MAX); + vkDestroyFence(vk->context.device, fence, NULL); + + next_fence = &vk->context.swapchain_fences[index]; + if (*next_fence != VK_NULL_HANDLE) + { + vkWaitForFences(vk->context.device, 1, next_fence, true, UINT64_MAX); + vkResetFences(vk->context.device, 1, next_fence); + } + else + vkCreateFence(vk->context.device, &info, NULL, next_fence); + + if (err != VK_SUCCESS) + { + RARCH_LOG("[Vulkan]: AcquireNextImage failed, invalidating swapchain.\n"); + vk->context.invalid_swapchain = true; + } +} + +bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk, + unsigned width, unsigned height, + unsigned swap_interval) +{ + unsigned i; + uint32_t format_count; + uint32_t desired_swapchain_images; + VkSurfaceCapabilitiesKHR surface_properties; + VkSurfaceFormatKHR formats[256]; + VkSurfaceFormatKHR format; + VkExtent2D swapchain_size; + VkSwapchainKHR old_swapchain; + VkSurfaceTransformFlagBitsKHR pre_transform; + VkPresentModeKHR swapchain_present_mode = swap_interval + ? VK_PRESENT_MODE_FIFO_KHR : VK_PRESENT_MODE_MAILBOX_KHR; + VkSwapchainCreateInfoKHR info = { VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR }; + + RARCH_LOG("[Vulkan]: Creating swapchain with present mode: %u\n", + (unsigned)swapchain_present_mode); + + vk->fpGetPhysicalDeviceSurfaceCapabilitiesKHR(vk->context.gpu, + vk->vk_surface, &surface_properties); + vk->fpGetPhysicalDeviceSurfaceFormatsKHR(vk->context.gpu, + vk->vk_surface, &format_count, NULL); + vk->fpGetPhysicalDeviceSurfaceFormatsKHR(vk->context.gpu, + vk->vk_surface, &format_count, formats); + + if (format_count == 1 && formats[0].format == VK_FORMAT_UNDEFINED) + { + format = formats[0]; + format.format = VK_FORMAT_B8G8R8A8_UNORM; + } + else + { + if (format_count == 0) + { + RARCH_ERR("[Vulkan]: Surface has no formats.\n"); + return false; + } + + format = formats[0]; + } + + if (surface_properties.currentExtent.width == -1) + { + swapchain_size.width = width; + swapchain_size.height = height; + } + else + swapchain_size = surface_properties.currentExtent; + + desired_swapchain_images = surface_properties.minImageCount + 1; + if ((surface_properties.maxImageCount > 0) + && (desired_swapchain_images > surface_properties.maxImageCount)) + desired_swapchain_images = surface_properties.maxImageCount; + + if (surface_properties.supportedTransforms + & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) + pre_transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + else + pre_transform = surface_properties.currentTransform; + + old_swapchain = vk->swapchain; + + info.surface = vk->vk_surface; + info.minImageCount = desired_swapchain_images; + info.imageFormat = format.format; + info.imageColorSpace = format.colorSpace; + info.imageExtent.width = swapchain_size.width; + info.imageExtent.height = swapchain_size.height; + info.imageArrayLayers = 1; + info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT + | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + info.preTransform = pre_transform; + info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + info.presentMode = swapchain_present_mode; + info.clipped = true; + info.oldSwapchain = old_swapchain; + + vk->fpCreateSwapchainKHR(vk->context.device, &info, NULL, &vk->swapchain); + if (old_swapchain != VK_NULL_HANDLE) + vk->fpDestroySwapchainKHR(vk->context.device, old_swapchain, NULL); + + vk->context.swapchain_width = swapchain_size.width; + vk->context.swapchain_height = swapchain_size.height; + + /* Make sure we create a backbuffer format that is as we expect. */ + switch (format.format) + { + case VK_FORMAT_B8G8R8A8_SRGB: + vk->context.swapchain_format = VK_FORMAT_B8G8R8A8_UNORM; + vk->context.swapchain_is_srgb = true; + break; + + case VK_FORMAT_R8G8B8A8_SRGB: + vk->context.swapchain_format = VK_FORMAT_R8G8B8A8_UNORM; + vk->context.swapchain_is_srgb = true; + break; + + case VK_FORMAT_R8G8B8_SRGB: + vk->context.swapchain_format = VK_FORMAT_R8G8B8_UNORM; + vk->context.swapchain_is_srgb = true; + break; + + case VK_FORMAT_B8G8R8_SRGB: + vk->context.swapchain_format = VK_FORMAT_B8G8R8_UNORM; + vk->context.swapchain_is_srgb = true; + break; + + default: + vk->context.swapchain_format = format.format; + break; + } + + vk->fpGetSwapchainImagesKHR(vk->context.device, vk->swapchain, + &vk->context.num_swapchain_images, NULL); + vk->fpGetSwapchainImagesKHR(vk->context.device, vk->swapchain, + &vk->context.num_swapchain_images, vk->context.swapchain_images); + + for (i = 0; i < vk->context.num_swapchain_images; i++) + { + if (vk->context.swapchain_fences[i]) + { + vkDestroyFence(vk->context.device, + vk->context.swapchain_fences[i], NULL); + vk->context.swapchain_fences[i] = VK_NULL_HANDLE; + } + } + + vulkan_acquire_next_image(vk); + + return true; +} diff --git a/gfx/common/vulkan_common.h b/gfx/common/vulkan_common.h index dc3f87cf6a..ee9ec03acb 100644 --- a/gfx/common/vulkan_common.h +++ b/gfx/common/vulkan_common.h @@ -20,6 +20,14 @@ #include "../../config.h" #endif +#define VULKAN_DESCRIPTOR_MANAGER_BLOCK_SETS 16 +#define VULKAN_MAX_DESCRIPTOR_POOL_SIZES 16 +#define VULKAN_BUFFER_BLOCK_SIZE (4 * 1024) + +#define VULKAN_MAX_SWAPCHAIN_IMAGES 8 + +#define VULKAN_DIRTY_DYNAMIC_BIT 0x0001 + #define VK_PROTOTYPES #ifdef HAVE_WAYLAND @@ -61,9 +69,12 @@ #include #include -#define VULKAN_MAX_SWAPCHAIN_IMAGES 8 - -#define VULKAN_DIRTY_DYNAMIC_BIT 0x0001 +enum vk_texture_type +{ + VULKAN_TEXTURE_STREAMED = 0, + VULKAN_TEXTURE_STATIC, + VULKAN_TEXTURE_READBACK +}; enum vulkan_wsi_type { @@ -215,14 +226,16 @@ struct vk_buffer_chain vulkan_buffer_chain_init( VkDeviceSize block_size, VkDeviceSize alignment, VkBufferUsageFlags usage); -void vulkan_buffer_chain_discard(struct vk_buffer_chain *chain); -bool vulkan_buffer_chain_alloc(const struct vulkan_context *context, - struct vk_buffer_chain *chain, size_t size, struct vk_buffer_range *range); -void vulkan_buffer_chain_free(VkDevice device, struct vk_buffer_chain *chain); -#define VULKAN_DESCRIPTOR_MANAGER_BLOCK_SETS 16 -#define VULKAN_BUFFER_BLOCK_SIZE (4 * 1024) -#define VULKAN_MAX_DESCRIPTOR_POOL_SIZES 16 +void vulkan_buffer_chain_discard(struct vk_buffer_chain *chain); + +bool vulkan_buffer_chain_alloc(const struct vulkan_context *context, + struct vk_buffer_chain *chain, size_t size, + struct vk_buffer_range *range); + +void vulkan_buffer_chain_free(VkDevice device, + struct vk_buffer_chain *chain); + struct vk_descriptor_pool { @@ -298,8 +311,10 @@ typedef struct vk struct vk_per_frame swapchain[VULKAN_MAX_SWAPCHAIN_IMAGES]; unsigned num_swapchain_images; - VkCommandBuffer cmd; /* Currently active command buffer. */ - VkCommandPool staging_pool; /* Staging pool for doing buffer transfers on GPU. */ + /* Currently active command buffer. */ + VkCommandBuffer cmd; + /* Staging pool for doing buffer transfers on GPU. */ + VkCommandPool staging_pool; struct { @@ -383,18 +398,14 @@ typedef struct vk vulkan_filter_chain_t *filter_chain; } vk_t; -uint32_t vulkan_find_memory_type(const VkPhysicalDeviceMemoryProperties *mem_props, +uint32_t vulkan_find_memory_type( + const VkPhysicalDeviceMemoryProperties *mem_props, uint32_t device_reqs, uint32_t host_reqs); -uint32_t vulkan_find_memory_type_fallback(const VkPhysicalDeviceMemoryProperties *mem_props, +uint32_t vulkan_find_memory_type_fallback( + const VkPhysicalDeviceMemoryProperties *mem_props, uint32_t device_reqs, uint32_t host_reqs); -enum vk_texture_type -{ - VULKAN_TEXTURE_STREAMED = 0, - VULKAN_TEXTURE_STATIC, - VULKAN_TEXTURE_READBACK -}; struct vk_texture vulkan_create_texture(vk_t *vk, struct vk_texture *old, @@ -421,7 +432,7 @@ void vulkan_image_layout_transition(vk_t *vk, VkCommandBuffer cmd, VkImage image VkAccessFlags srcAccess, VkAccessFlags dstAccess, VkPipelineStageFlags srcStages, VkPipelineStageFlags dstStages); -static inline unsigned vulkan_format_to_bpp(VkFormat format) +static INLINE unsigned vulkan_format_to_bpp(VkFormat format) { switch (format) { @@ -441,7 +452,7 @@ static inline unsigned vulkan_format_to_bpp(VkFormat format) } } -static inline void vulkan_write_quad_vbo(struct vk_vertex *pv, +static INLINE void vulkan_write_quad_vbo(struct vk_vertex *pv, float x, float y, float width, float height, float tex_x, float tex_y, float tex_width, float tex_height, const struct vk_color *color) @@ -470,12 +481,36 @@ struct vk_buffer vulkan_create_buffer(const struct vulkan_context *context, size_t size, VkBufferUsageFlags usage); void vulkan_destroy_buffer(VkDevice device, struct vk_buffer *buffer); -VkDescriptorSet vulkan_descriptor_manager_alloc(VkDevice device, struct vk_descriptor_manager *manager); +VkDescriptorSet vulkan_descriptor_manager_alloc(VkDevice device, + struct vk_descriptor_manager *manager); + void vulkan_descriptor_manager_restart(struct vk_descriptor_manager *manager); + struct vk_descriptor_manager vulkan_create_descriptor_manager(VkDevice device, const VkDescriptorPoolSize *sizes, unsigned num_sizes, VkDescriptorSetLayout set_layout); void vulkan_destroy_descriptor_manager(VkDevice device, struct vk_descriptor_manager *manager); + +bool vulkan_context_init(gfx_ctx_vulkan_data_t *vk, + enum vulkan_wsi_type type); + +void vulkan_context_destroy(gfx_ctx_vulkan_data_t *vk, + bool destroy_surface); + +bool vulkan_surface_create(gfx_ctx_vulkan_data_t *vk, + enum vulkan_wsi_type type, + void *display, void *surface, + unsigned width, unsigned height, + unsigned swap_interval); + +void vulkan_present(gfx_ctx_vulkan_data_t *vk, unsigned index); + +void vulkan_acquire_next_image(gfx_ctx_vulkan_data_t *vk); + +bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk, + unsigned width, unsigned height, + unsigned swap_interval); + #endif diff --git a/gfx/drivers_context/wayland_ctx.c b/gfx/drivers_context/wayland_ctx.c index cbe07a4a40..8a500814f9 100644 --- a/gfx/drivers_context/wayland_ctx.c +++ b/gfx/drivers_context/wayland_ctx.c @@ -45,11 +45,6 @@ static volatile sig_atomic_t g_quit = 0; -#ifdef HAVE_VULKAN -static VkInstance cached_instance; -static VkDevice cached_device; -#endif - typedef struct gfx_ctx_wayland_data { #ifdef HAVE_EGL @@ -77,7 +72,6 @@ typedef struct gfx_ctx_wayland_data #endif } gfx_ctx_wayland_data_t; - static enum gfx_ctx_api wl_api; #ifndef EGL_OPENGL_ES3_BIT_KHR @@ -169,7 +163,8 @@ static void registry_handle_global(void *data, struct wl_registry *reg, id, &wl_compositor_interface, num); } else if (string_is_equal(interface, "wl_shell")) - wl->shell = (struct wl_shell*)wl_registry_bind(reg, id, &wl_shell_interface, 1); + wl->shell = (struct wl_shell*) + wl_registry_bind(reg, id, &wl_shell_interface, 1); } static void registry_handle_global_remove(void *data, @@ -188,46 +183,6 @@ static const struct wl_registry_listener registry_listener = { static void gfx_ctx_wl_get_video_size(void *data, unsigned *width, unsigned *height); -#ifdef HAVE_VULKAN -static void vulkan_destroy_context(gfx_ctx_vulkan_data_t *vk, - bool destroy_surface) -{ - unsigned i; - if (vk->context.queue) - vkQueueWaitIdle(vk->context.queue); - if (vk->swapchain) - vk->fpDestroySwapchainKHR(vk->context.device, - vk->swapchain, NULL); - - if (destroy_surface) - vk->fpDestroySurfaceKHR(vk->context.instance, - vk->vk_surface, NULL); - - for (i = 0; i < VULKAN_MAX_SWAPCHAIN_IMAGES; i++) - { - if (vk->context.swapchain_semaphores[i] != VK_NULL_HANDLE) - vkDestroySemaphore(vk->context.device, - vk->context.swapchain_semaphores[i], NULL); - if (vk->context.swapchain_fences[i] != VK_NULL_HANDLE) - vkDestroyFence(vk->context.device, - vk->context.swapchain_fences[i], NULL); - } - - if (video_driver_ctl(RARCH_DISPLAY_CTL_IS_VIDEO_CACHE_CONTEXT, NULL)) - { - cached_device = vk->context.device; - cached_instance = vk->context.instance; - } - else - { - if (vk->context.device) - vkDestroyDevice(vk->context.device, NULL); - if (vk->context.instance) - vkDestroyInstance(vk->context.instance, NULL); - } -} -#endif - static void gfx_ctx_wl_destroy_resources(gfx_ctx_wayland_data_t *wl) { if (!wl) @@ -247,7 +202,7 @@ static void gfx_ctx_wl_destroy_resources(gfx_ctx_wayland_data_t *wl) break; case GFX_CTX_VULKAN_API: #ifdef HAVE_VULKAN - vulkan_destroy_context(&wl->vk, wl->surface); + vulkan_context_destroy(&wl->vk, wl->surface); if (wl->fd >= 0) close(wl->fd); @@ -352,183 +307,6 @@ static void gfx_ctx_wl_check_window(void *data, bool *quit, *quit = g_quit; } -#ifdef HAVE_VULKAN -static void vulkan_acquire_next_image(gfx_ctx_vulkan_data_t *vk) -{ - unsigned index; - VkResult err; - VkFence fence; - VkFence *next_fence; - VkSemaphoreCreateInfo sem_info = - { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO }; - VkFenceCreateInfo info = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO }; - - vkCreateFence(vk->context.device, &info, NULL, &fence); - - err = vk->fpAcquireNextImageKHR(vk->context.device, - vk->swapchain, UINT64_MAX, - VK_NULL_HANDLE, fence, &vk->context.current_swapchain_index); - - index = vk->context.current_swapchain_index; - if (vk->context.swapchain_semaphores[index] == VK_NULL_HANDLE) - vkCreateSemaphore(vk->context.device, &sem_info, - NULL, &vk->context.swapchain_semaphores[index]); - - vkWaitForFences(vk->context.device, 1, &fence, true, UINT64_MAX); - vkDestroyFence(vk->context.device, fence, NULL); - - next_fence = &vk->context.swapchain_fences[index]; - if (*next_fence != VK_NULL_HANDLE) - { - vkWaitForFences(vk->context.device, 1, next_fence, true, UINT64_MAX); - vkResetFences(vk->context.device, 1, next_fence); - } - else - vkCreateFence(vk->context.device, &info, NULL, next_fence); - - if (err != VK_SUCCESS) - { - RARCH_LOG("[Wayland/Vulkan]: AcquireNextImage failed, invalidating swapchain.\n"); - vk->context.invalid_swapchain = true; - } -} - -static bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk, - unsigned width, unsigned height, - unsigned swap_interval) -{ - unsigned i; - uint32_t format_count; - uint32_t desired_swapchain_images; - VkSurfaceCapabilitiesKHR surface_properties; - VkSurfaceFormatKHR formats[256]; - VkSurfaceFormatKHR format; - VkExtent2D swapchain_size; - VkSwapchainKHR old_swapchain; - VkSurfaceTransformFlagBitsKHR pre_transform; - VkPresentModeKHR swapchain_present_mode = swap_interval - ? VK_PRESENT_MODE_FIFO_KHR : VK_PRESENT_MODE_MAILBOX_KHR; - VkSwapchainCreateInfoKHR info = { VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR }; - - RARCH_LOG("[Wayland/Vulkan]: Creating swapchain with present mode: %u\n", - (unsigned)swapchain_present_mode); - - vk->fpGetPhysicalDeviceSurfaceCapabilitiesKHR(vk->context.gpu, - vk->vk_surface, &surface_properties); - vk->fpGetPhysicalDeviceSurfaceFormatsKHR(vk->context.gpu, - vk->vk_surface, &format_count, NULL); - vk->fpGetPhysicalDeviceSurfaceFormatsKHR(vk->context.gpu, - vk->vk_surface, &format_count, formats); - - if (format_count == 1 && formats[0].format == VK_FORMAT_UNDEFINED) - { - format = formats[0]; - format.format = VK_FORMAT_B8G8R8A8_UNORM; - } - else - { - if (format_count == 0) - { - RARCH_ERR("[Wayland Vulkan]: Surface has no formats.\n"); - return false; - } - - format = formats[0]; - } - - if (surface_properties.currentExtent.width == -1) - { - swapchain_size.width = width; - swapchain_size.height = height; - } - else - swapchain_size = surface_properties.currentExtent; - - desired_swapchain_images = surface_properties.minImageCount + 1; - if ((surface_properties.maxImageCount > 0) - && (desired_swapchain_images > surface_properties.maxImageCount)) - desired_swapchain_images = surface_properties.maxImageCount; - - if (surface_properties.supportedTransforms - & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) - pre_transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; - else - pre_transform = surface_properties.currentTransform; - - old_swapchain = vk->swapchain; - - info.surface = vk->vk_surface; - info.minImageCount = desired_swapchain_images; - info.imageFormat = format.format; - info.imageColorSpace = format.colorSpace; - info.imageExtent.width = swapchain_size.width; - info.imageExtent.height = swapchain_size.height; - info.imageArrayLayers = 1; - info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT - | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; - info.preTransform = pre_transform; - info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; - info.presentMode = swapchain_present_mode; - info.clipped = true; - info.oldSwapchain = old_swapchain; - - vk->fpCreateSwapchainKHR(vk->context.device, &info, NULL, &vk->swapchain); - if (old_swapchain != VK_NULL_HANDLE) - vk->fpDestroySwapchainKHR(vk->context.device, old_swapchain, NULL); - - vk->context.swapchain_width = swapchain_size.width; - vk->context.swapchain_height = swapchain_size.height; - - /* Make sure we create a backbuffer format that is as we expect. */ - switch (format.format) - { - case VK_FORMAT_B8G8R8A8_SRGB: - vk->context.swapchain_format = VK_FORMAT_B8G8R8A8_UNORM; - vk->context.swapchain_is_srgb = true; - break; - - case VK_FORMAT_R8G8B8A8_SRGB: - vk->context.swapchain_format = VK_FORMAT_R8G8B8A8_UNORM; - vk->context.swapchain_is_srgb = true; - break; - - case VK_FORMAT_R8G8B8_SRGB: - vk->context.swapchain_format = VK_FORMAT_R8G8B8_UNORM; - vk->context.swapchain_is_srgb = true; - break; - - case VK_FORMAT_B8G8R8_SRGB: - vk->context.swapchain_format = VK_FORMAT_B8G8R8_UNORM; - vk->context.swapchain_is_srgb = true; - break; - - default: - vk->context.swapchain_format = format.format; - break; - } - - vk->fpGetSwapchainImagesKHR(vk->context.device, vk->swapchain, - &vk->context.num_swapchain_images, NULL); - vk->fpGetSwapchainImagesKHR(vk->context.device, vk->swapchain, - &vk->context.num_swapchain_images, vk->context.swapchain_images); - - for (i = 0; i < vk->context.num_swapchain_images; i++) - { - if (vk->context.swapchain_fences[i]) - { - vkDestroyFence(vk->context.device, - vk->context.swapchain_fences[i], NULL); - vk->context.swapchain_fences[i] = VK_NULL_HANDLE; - } - } - - vulkan_acquire_next_image(vk); - - return true; -} -#endif - static bool gfx_ctx_wl_set_resize(void *data, unsigned width, unsigned height) { gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; @@ -603,225 +381,6 @@ static void gfx_ctx_wl_get_video_size(void *data, EGL_DEPTH_SIZE, 0 #endif -#ifdef HAVE_VULKAN - -#define VK_GET_INSTANCE_PROC_ADDR(vk, inst, entrypoint) do { \ - vk->fp##entrypoint = (PFN_vk##entrypoint) vkGetInstanceProcAddr(inst, "vk"#entrypoint); \ - if (vk->fp##entrypoint == NULL) { \ - RARCH_ERR("vkGetInstanceProcAddr failed to find vk%s\n", #entrypoint); \ - return false; \ - } \ -} while(0) - -#define VK_GET_DEVICE_PROC_ADDR(vk, dev, entrypoint) do { \ - vk->fp##entrypoint = (PFN_vk##entrypoint) vkGetDeviceProcAddr(dev, "vk" #entrypoint); \ - if (vk->fp##entrypoint == NULL) { \ - RARCH_ERR("vkGetDeviceProcAddr failed to find vk%s\n", #entrypoint); \ - return false; \ - } \ -} while(0) - -static bool vulkan_init_context(gfx_ctx_vulkan_data_t *vk, - enum vulkan_wsi_type type) -{ - unsigned i; - uint32_t queue_count; - VkQueueFamilyProperties queue_properties[32]; - VkInstanceCreateInfo info = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO }; - VkApplicationInfo app = { VK_STRUCTURE_TYPE_APPLICATION_INFO }; - VkPhysicalDeviceFeatures features = { false }; - VkDeviceQueueCreateInfo queue_info = { VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO }; - VkDeviceCreateInfo device_info = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO }; - uint32_t gpu_count = 1; - bool found_queue = false; - static const float one = 1.0f; - static const char *device_extensions[] = { - "VK_KHR_swapchain", - }; - static const char *instance_extensions[2]; - - instance_extensions[0] = "VK_KHR_surface"; - - switch (type) - { - case VULKAN_WSI_WAYLAND: - instance_extensions[1] = "VK_KHR_wayland_surface"; - break; - case VULKAN_WSI_ANDROID: - instance_extensions[1] = "VK_KHR_android_surface"; - break; - case VULKAN_WSI_WIN32: - instance_extensions[1] = "VK_KHR_win32_surface"; - break; - case VULKAN_WSI_XLIB: - instance_extensions[1] = "VK_KHR_xlib_surface"; - break; - case VULKAN_WSI_XCB: - instance_extensions[1] = "VK_KHR_xcb_surface"; - break; - case VULKAN_WSI_MIR: - instance_extensions[1] = "VK_KHR_mir_surface"; - break; - case VULKAN_WSI_NONE: - default: - break; - } - - app.pApplicationName = "RetroArch"; - app.applicationVersion = 0; - app.pEngineName = "RetroArch"; - app.engineVersion = 0; - app.apiVersion = VK_API_VERSION; - - info.pApplicationInfo = &app; - info.enabledExtensionCount = ARRAY_SIZE(instance_extensions); - info.ppEnabledExtensionNames = instance_extensions; - - if (cached_instance) - { - vk->context.instance = cached_instance; - cached_instance = NULL; - } - else if (vkCreateInstance(&info, NULL, &vk->context.instance) != VK_SUCCESS) - return false; - - if (vkEnumeratePhysicalDevices(vk->context.instance, - &gpu_count, &vk->context.gpu) != VK_SUCCESS) - return false; - - if (gpu_count != 1) - { - RARCH_ERR("[Wayland/Vulkan]: Failed to enumerate Vulkan physical device.\n"); - return false; - } - - vkGetPhysicalDeviceProperties(vk->context.gpu, - &vk->context.gpu_properties); - vkGetPhysicalDeviceMemoryProperties(vk->context.gpu, - &vk->context.memory_properties); - vkGetPhysicalDeviceQueueFamilyProperties(vk->context.gpu, - &queue_count, NULL); - - if (queue_count < 1 || queue_count > 32) - return false; - - vkGetPhysicalDeviceQueueFamilyProperties(vk->context.gpu, - &queue_count, queue_properties); - - for (i = 0; i < queue_count; i++) - { - if (queue_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) - { - vk->context.graphics_queue_index = i; - RARCH_LOG("[Wayland/Vulkan]: Device supports %u sub-queues.\n", - queue_properties[i].queueCount); - found_queue = true; - break; - } - } - - if (!found_queue) - { - RARCH_ERR("[Wayland/Vulkan]: Did not find suitable graphics queue.\n"); - return false; - } - - queue_info.queueFamilyIndex = vk->context.graphics_queue_index; - queue_info.queueCount = 1; - queue_info.pQueuePriorities = &one; - - device_info.queueCreateInfoCount = 1; - device_info.pQueueCreateInfos = &queue_info; - device_info.enabledExtensionCount = ARRAY_SIZE(device_extensions); - device_info.ppEnabledExtensionNames = device_extensions; - device_info.pEnabledFeatures = &features; - - if (cached_device) - { - vk->context.device = cached_device; - cached_device = NULL; - video_driver_ctl(RARCH_DISPLAY_CTL_SET_VIDEO_CACHE_CONTEXT_ACK, NULL); - RARCH_LOG("[Vulkan]: Using cached Vulkan context.\n"); - } - else if (vkCreateDevice(vk->context.gpu, &device_info, - NULL, &vk->context.device) != VK_SUCCESS) - return false; - - vkGetDeviceQueue(vk->context.device, - vk->context.graphics_queue_index, 0, &vk->context.queue); - - VK_GET_INSTANCE_PROC_ADDR(vk, - vk->context.instance, GetPhysicalDeviceSurfaceSupportKHR); - VK_GET_INSTANCE_PROC_ADDR(vk, - vk->context.instance, GetPhysicalDeviceSurfaceCapabilitiesKHR); - VK_GET_INSTANCE_PROC_ADDR(vk, - vk->context.instance, GetPhysicalDeviceSurfaceFormatsKHR); - VK_GET_INSTANCE_PROC_ADDR(vk, - vk->context.instance, GetPhysicalDeviceSurfacePresentModesKHR); - VK_GET_INSTANCE_PROC_ADDR(vk, - vk->context.instance, DestroySurfaceKHR); - VK_GET_DEVICE_PROC_ADDR(vk, - vk->context.device, CreateSwapchainKHR); - VK_GET_DEVICE_PROC_ADDR(vk, - vk->context.device, DestroySwapchainKHR); - VK_GET_DEVICE_PROC_ADDR(vk, - vk->context.device, GetSwapchainImagesKHR); - VK_GET_DEVICE_PROC_ADDR(vk, - vk->context.device, AcquireNextImageKHR); - VK_GET_DEVICE_PROC_ADDR(vk, - vk->context.device, QueuePresentKHR); - - switch (type) - { - case VULKAN_WSI_WAYLAND: -#ifdef HAVE_WAYLAND - VK_GET_INSTANCE_PROC_ADDR(vk, - vk->context.instance, CreateWaylandSurfaceKHR); -#endif - break; - case VULKAN_WSI_ANDROID: -#ifdef ANDROID - VK_GET_INSTANCE_PROC_ADDR(vk, - vk->context.instance, CreateAndroidSurfaceKHR); -#endif - break; - case VULKAN_WSI_WIN32: -#ifdef _WIN32 - VK_GET_INSTANCE_PROC_ADDR(vk, - vk->context.instance, CreateWin32SurfaceKHR); -#endif - break; - case VULKAN_WSI_XLIB: -#ifdef HAVE_XLIB - VK_GET_INSTANCE_PROC_ADDR(vk, - vk->context.instance, CreateXlibSurfaceKHR); -#endif - break; - case VULKAN_WSI_XCB: -#ifdef HAVE_XCB - VK_GET_INSTANCE_PROC_ADDR(vk, - vk->context.instance, CreateXcbSurfaceKHR); -#endif - break; - case VULKAN_WSI_MIR: -#ifdef HAVE_MIR - VK_GET_INSTANCE_PROC_ADDR(vk, - vk->context.instance, CreateMirSurfaceKHR); -#endif - break; - case VULKAN_WSI_NONE: - default: - break; - } - - vk->context.queue_lock = slock_new(); - if (!vk->context.queue_lock) - return false; - - return true; -} -#endif - static void *gfx_ctx_wl_init(void *video_driver) { @@ -965,7 +524,7 @@ static void *gfx_ctx_wl_init(void *video_driver) break; case GFX_CTX_VULKAN_API: #ifdef HAVE_VULKAN - if (!vulkan_init_context(&wl->vk, VULKAN_WSI_WAYLAND)) + if (!vulkan_context_init(&wl->vk, VULKAN_WSI_WAYLAND)) goto error; #endif break; @@ -1108,138 +667,6 @@ static void gfx_ctx_wl_set_swap_interval(void *data, unsigned swap_interval) } } -#ifdef HAVE_VULKAN -static bool vulkan_surface_create(gfx_ctx_vulkan_data_t *vk, - enum vulkan_wsi_type type, - void *display, void *surface, - unsigned width, unsigned height, - unsigned swap_interval) -{ - switch (type) - { - case VULKAN_WSI_WAYLAND: -#ifdef HAVE_WAYLAND - { - VkWaylandSurfaceCreateInfoKHR surf_info; - - memset(&surf_info, 0, sizeof(VkWaylandSurfaceCreateInfoKHR)); - - surf_info.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR; - surf_info.pNext = NULL; - surf_info.flags = 0; - surf_info.display = (struct wl_display*)display; - surf_info.surface = (struct wl_surface*)surface; - - if (vk->fpCreateWaylandSurfaceKHR(vk->context.instance, - &surf_info, NULL, &vk->vk_surface) != VK_SUCCESS) - return false; - } -#endif - break; - case VULKAN_WSI_ANDROID: -#ifdef ANDROID - { - VkAndroidSurfaceCreateInfoKHR surf_info; - - memset(&surf_info, 0, sizeof(VkAndroidSurfaceCreateInfoKHR)); - - surf_info.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR; - surf_info.flags = 0; - surf_info.window = (ANativeWindow*)surface; - - if (vk->fpCreateAndroidSurfaceKHR(vk->context.instance, - &surf_info, NULL, &vk->vk_surface) != VK_SUCCESS) - return false; - } -#endif - break; - case VULKAN_WSI_WIN32: -#ifdef _WIN32 - { - VkWin32SurfaceCreateInfoKHR surf_info; - - memset(&surf_info, 0, sizeof(VkWin32SurfaceCreateInfoKHR)); - - surf_info.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; - surf_info.flags = 0; - surf_info.hinstance = display; - surf_info.hwnd = surface; - - if (vk->fpCreateWin32SurfaceKHR(vk->context.instance, - &surf_info, NULL, &vk->vk_surface) != VK_SUCCESS) - return false; - } -#endif - break; - case VULKAN_WSI_XLIB: -#ifdef HAVE_XLIB - { - VkXlibSurfaceCreateInfoKHR surf_info; - - memset(&surf_info, 0, sizeof(VkXlibSurfaceCreateInfoKHR)); - - surf_info.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR; - surf_info.flags = 0; - surf_info.dpy = display; - surf_info.window = surface; - - if (vk->fpCreateXlibSurfaceKHR(vk->context.instance, - &surf_info, NULL, &vk->vk_surface) - != VK_SUCCESS) - return false; - } -#endif - break; - case VULKAN_WSI_XCB: -#ifdef HAVE_XCB - { - VkXcbSurfaceCreateInfoKHR surf_info; - - memset(&surf_info, 0, sizeof(VkXcbSurfaceCreateInfoKHR)); - - surf_info.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; - surf_info.flags = 0; - surf_info.connection = XGetXCBConnection(display); - surf_info.window = (xcb_window_t)surface; - - if (vk->fpCreateXcbSurfaceKHR(vk->context.instance, - &surf_info, NULL, &vk->vk_surface) - != VK_SUCCESS) - return false; - } -#endif - break; - case VULKAN_WSI_MIR: -#ifdef HAVE_MIR - { - VkMirSurfaceCreateInfoKHR surf_info; - - memset(&surf_info, 0, sizeof(VkMirSurfaceCreateInfoKHR)); - - surf_info.sType = VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR; - surf_info.connection = display; - surf_info.mirSurface = surface; - - if (vk->fpCreateMirSurfaceKHR(vk->context.instance, - &surf_info, NULL, &vk->vk_surface) - != VK_SUCCESS) - return false; - } -#endif - break; - case VULKAN_WSI_NONE: - default: - return false; - } - - if (!vulkan_create_swapchain( - vk, width, height, swap_interval)) - return false; - - return true; -} -#endif - static bool gfx_ctx_wl_set_video_mode(void *data, unsigned width, unsigned height, bool fullscreen) @@ -1559,37 +986,12 @@ static const struct wl_seat_listener seat_listener = { seat_handle_capabilities, }; - #ifdef HAVE_VULKAN static void *gfx_ctx_wl_get_context_data(void *data) { gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; return &wl->vk.context; } - -static void vulkan_present(gfx_ctx_vulkan_data_t *vk, unsigned index) -{ - VkResult result = VK_SUCCESS; - VkResult err = VK_SUCCESS; - VkPresentInfoKHR present = { VK_STRUCTURE_TYPE_PRESENT_INFO_KHR }; - present.swapchainCount = 1; - present.pSwapchains = &vk->swapchain; - present.pImageIndices = &index; - present.pResults = &result; - present.waitSemaphoreCount = 1; - present.pWaitSemaphores = &vk->context.swapchain_semaphores[index]; - - /* Better hope QueuePresent doesn't block D: */ - slock_lock(vk->context.queue_lock); - err = vk->fpQueuePresentKHR(vk->context.queue, &present); - - if (err != VK_SUCCESS || result != VK_SUCCESS) - { - RARCH_LOG("[Wayland/Vulkan]: QueuePresent failed, invalidating swapchain.\n"); - vk->context.invalid_swapchain = true; - } - slock_unlock(vk->context.queue_lock); -} #endif static void gfx_ctx_wl_swap_buffers(void *data)