#if YASL_HAS_WAYLAND #define VK_USE_PLATFORM_WAYLAND_KHR #endif #if YASL_HAS_X11 #define VK_USE_PLATFORM_XLIB_KHR #endif #if YASL_HAS_COCOA #define VK_USE_PLATFORM_METAL_EXT #endif #include "yasl/vulkan.h" #include "public_internal.h" #include #include #include #if YASL_HAS_WAYLAND #include "yasl/native/wayland.h" #endif #if YASL_HAS_X11 #include "yasl/native/x11.h" #endif static PFN_vkGetInstanceProcAddr get_proc; static bool portability; void yasl_private_vulkan_reset(void) { get_proc=NULL; portability=false; } bool yasl_vulkan_init(PFN_vkGetInstanceProcAddr loader) { if(!loader)return yasl_public_fail(EINVAL); get_proc=loader;portability=false; PFN_vkEnumerateInstanceExtensionProperties enumerate=(PFN_vkEnumerateInstanceExtensionProperties)get_proc(VK_NULL_HANDLE,"vkEnumerateInstanceExtensionProperties"); if(!enumerate)return yasl_public_fail(ENOTSUP); uint32_t count=0;VkResult r=enumerate(NULL,&count,NULL); if(r!=VK_SUCCESS)return yasl_public_fail(EIO); VkExtensionProperties *ext=count?calloc(count,sizeof(*ext)):NULL; if(count&&!ext)return yasl_public_fail(ENOMEM); r=enumerate(NULL,&count,ext); if(r==VK_SUCCESS)for(uint32_t i=0;ipresenter==YASL_PRIVATE_PRESENTER_CPU||s->presenter==YASL_PRIVATE_PRESENTER_GL){yasl_public_fail(EINVAL);return NULL;} switch(s->display->ops->type) { case YASL_PRIVATE_BACKEND_WAYLAND:*count=2;return wayland; case YASL_PRIVATE_BACKEND_X11:*count=2;return x11; case YASL_PRIVATE_BACKEND_COCOA:*count=portability?3:2;return metal; default:yasl_public_fail(ENOTSUP);return NULL; } } VkInstanceCreateFlags yasl_vulkan_instance_flags(const yasl_surface *s) { return s&&s->display->ops->type==YASL_PRIVATE_BACKEND_COCOA&&portability?VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR:0; } VkResult yasl_vulkan_create_surface(yasl_surface *s,VkInstance instance,const VkAllocationCallbacks *allocator,VkSurfaceKHR *out) { if(out)*out=VK_NULL_HANDLE; if(!yasl_public_surface(s,false)||!instance||!out||!get_proc){yasl_public_fail(EINVAL);return VK_ERROR_INITIALIZATION_FAILED;} if(s->presenter!=YASL_PRIVATE_PRESENTER_NONE){yasl_public_fail(EBUSY);return VK_ERROR_NATIVE_WINDOW_IN_USE_KHR;} VkResult result=VK_ERROR_EXTENSION_NOT_PRESENT; switch(s->display->ops->type) { #if YASL_HAS_WAYLAND case YASL_PRIVATE_BACKEND_WAYLAND: { PFN_vkCreateWaylandSurfaceKHR create=(PFN_vkCreateWaylandSurfaceKHR)get_proc(instance,"vkCreateWaylandSurfaceKHR"); if(create) { VkWaylandSurfaceCreateInfoKHR info={.sType=VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR, .display=yasl_wayland_display(s),.surface=yasl_wayland_surface(s)};result=create(instance,&info,allocator,out); }break; } #endif #if YASL_HAS_X11 case YASL_PRIVATE_BACKEND_X11: { PFN_vkCreateXlibSurfaceKHR create=(PFN_vkCreateXlibSurfaceKHR)get_proc(instance,"vkCreateXlibSurfaceKHR"); if(create) { VkXlibSurfaceCreateInfoKHR info={.sType=VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, .dpy=yasl_x11_display(s),.window=(Window)yasl_x11_window(s)};result=create(instance,&info,allocator,out); }break; } #endif #if YASL_HAS_COCOA case YASL_PRIVATE_BACKEND_COCOA: { PFN_vkCreateMetalSurfaceEXT create=(PFN_vkCreateMetalSurfaceEXT)get_proc(instance,"vkCreateMetalSurfaceEXT"); if(create&&s->display->ops->surface_get_metal_layer) { VkMetalSurfaceCreateInfoEXT info={.sType=VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT, .pLayer=s->display->ops->surface_get_metal_layer(s)};result=create(instance,&info,allocator,out); }break; } #endif default:break; } if(result==VK_SUCCESS)s->presenter=YASL_PRIVATE_PRESENTER_VULKAN; else yasl_public_fail(result==VK_ERROR_EXTENSION_NOT_PRESENT?ENOTSUP:EIO); return result; }