vkd3d: Remove dependency on linking directly against libvulkan.

There is no reason to not load Vulkan dynamically, otherwise, we must
have loader dev packages installed, which is not ideal.

Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
This commit is contained in:
Hans-Kristian Arntzen 2020-06-15 11:46:10 +02:00
parent 4cf8467b9d
commit cbdf6f88d2
6 changed files with 111 additions and 36 deletions

View File

@ -25,7 +25,8 @@ vkd3d_public_headers = \
include/vkd3d_shader.h \
include/vkd3d_types.h \
include/vkd3d_utils.h \
include/vkd3d_windows.h
include/vkd3d_windows.h \
include/vkd3d_sonames.h
vkd3d_demos_shaders = \
demos/gears.hlsl \
@ -156,14 +157,14 @@ AM_DEFAULT_SOURCE_EXT = .c
if BUILD_TESTS
check_PROGRAMS = $(vkd3d_tests) $(vkd3d_cross_tests)
TESTS = $(vkd3d_tests) $(vkd3d_cross_tests)
tests_d3d12_LDADD = $(LDADD) @PTHREAD_LIBS@ @VULKAN_LIBS@
tests_d3d12_invalid_usage_LDADD = $(LDADD) @VULKAN_LIBS@
tests_vkd3d_api_LDADD = libvkd3d.la @VULKAN_LIBS@
tests_d3d12_LDADD = $(LDADD) @PTHREAD_LIBS@
tests_d3d12_invalid_usage_LDADD = $(LDADD)
tests_vkd3d_api_LDADD = libvkd3d.la
tests_vkd3d_shader_api_LDADD = libvkd3d-shader.la
endif
if BUILD_DEMOS
DEMOS_LDADD = $(LDADD) libvkd3d-shader.la @XCB_LIBS@ @VULKAN_LIBS@
DEMOS_LDADD = $(LDADD) libvkd3d-shader.la @XCB_LIBS@ @DL_LIBS@
DEMOS_CFLAGS = $(AM_CFLAGS) @XCB_CFLAGS@
noinst_PROGRAMS += $(vkd3d_demos)

View File

@ -95,14 +95,6 @@ AC_CHECK_LIB([dl], [dlopen],
AC_ARG_VAR([PTHREAD_LIBS], [linker flags for pthreads])
VKD3D_CHECK_PTHREAD
AC_SUBST([VULKAN_LIBS])
VKD3D_CHECK_SONAME([vulkan], [vkGetInstanceProcAddr],
[VULKAN_LIBS="-lvulkan"],
[VKD3D_CHECK_SONAME([MoltenVK], [vkGetInstanceProcAddr],
[VULKAN_LIBS="-lMoltenVK"
AC_DEFINE_UNQUOTED([SONAME_LIBVULKAN],["$ac_cv_lib_soname_MoltenVK"])],
[AC_MSG_ERROR([libvulkan and libMoltenVK not found.])])])
AS_IF([test "x$with_spirv_tools" = "xyes"],
[PKG_CHECK_MODULES([SPIRV_TOOLS], [SPIRV-Tools-shared],
[AC_DEFINE([HAVE_SPIRV_TOOLS], [1], [Define to 1 if you have SPIRV-Tools.])])],

View File

@ -20,6 +20,7 @@
#define VK_USE_PLATFORM_XCB_KHR
#include <vkd3d.h>
#include <vkd3d_utils.h>
#include <vkd3d_sonames.h>
#include <xcb/xcb_event.h>
#include <xcb/xcb_icccm.h>
#include <xcb/xcb_keysyms.h>
@ -28,6 +29,24 @@
#include <unistd.h>
#include <fcntl.h>
#include <stdbool.h>
#include <dlfcn.h>
#define SYMBOL(x) static PFN_vk##x x
SYMBOL(CreateXcbSurfaceKHR);
SYMBOL(GetPhysicalDeviceSurfaceSupportKHR);
SYMBOL(GetPhysicalDeviceSurfaceCapabilitiesKHR);
SYMBOL(GetPhysicalDeviceSurfaceFormatsKHR);
SYMBOL(CreateSwapchainKHR);
SYMBOL(CreateFence);
SYMBOL(GetSwapchainImagesKHR);
SYMBOL(AcquireNextImageKHR);
SYMBOL(WaitForFences);
SYMBOL(ResetFences);
SYMBOL(DestroyFence);
SYMBOL(DestroySurfaceKHR);
SYMBOL(QueuePresentKHR);
SYMBOL(DestroySwapchainKHR);
#undef SYMBOL
struct demo
{
@ -43,6 +62,7 @@ struct demo
void *user_data;
void (*idle_func)(struct demo *demo, void *user_data);
};
struct demo_window
@ -70,6 +90,29 @@ struct demo_swapchain
ID3D12Resource *buffers[1];
};
static inline void init_symbols(VkInstance instance)
{
PFN_vkGetInstanceProcAddr gpa;
void *handle = dlopen(SONAME_LIBVULKAN, RTLD_LAZY);
gpa = (PFN_vkGetInstanceProcAddr)dlsym(handle, "vkGetInstanceProcAddr");
#define SYMBOL(x) x = (PFN_vk##x)gpa(instance, "vk" #x)
SYMBOL(CreateXcbSurfaceKHR);
SYMBOL(GetPhysicalDeviceSurfaceSupportKHR);
SYMBOL(GetPhysicalDeviceSurfaceCapabilitiesKHR);
SYMBOL(GetPhysicalDeviceSurfaceFormatsKHR);
SYMBOL(CreateSwapchainKHR);
SYMBOL(CreateFence);
SYMBOL(GetSwapchainImagesKHR);
SYMBOL(AcquireNextImageKHR);
SYMBOL(WaitForFences);
SYMBOL(ResetFences);
SYMBOL(DestroySurfaceKHR);
SYMBOL(DestroyFence);
SYMBOL(QueuePresentKHR);
SYMBOL(DestroySwapchainKHR);
#undef SYMBOL
}
static inline xcb_atom_t demo_get_atom(xcb_connection_t *c, const char *name)
{
xcb_intern_atom_cookie_t cookie;
@ -339,23 +382,25 @@ static inline struct demo_swapchain *demo_swapchain_create(ID3D12CommandQueue *c
vk_physical_device = vkd3d_get_vk_physical_device(d3d12_device);
vk_device = vkd3d_get_vk_device(d3d12_device);
init_symbols(vk_instance);
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)
if (CreateXcbSurfaceKHR(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,
if (GetPhysicalDeviceSurfaceSupportKHR(vk_physical_device,
queue_family_index, vk_surface, &supported) < 0 || !supported)
goto fail;
if (vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vk_physical_device, vk_surface, &surface_caps) < 0)
if (GetPhysicalDeviceSurfaceCapabilitiesKHR(vk_physical_device, vk_surface, &surface_caps) < 0)
goto fail;
if ((surface_caps.maxImageCount && desc->buffer_count > surface_caps.maxImageCount)
@ -365,11 +410,11 @@ static inline struct demo_swapchain *demo_swapchain_create(ID3D12CommandQueue *c
|| !(surface_caps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR))
goto fail;
if (vkGetPhysicalDeviceSurfaceFormatsKHR(vk_physical_device, vk_surface, &format_count, NULL) < 0
if (GetPhysicalDeviceSurfaceFormatsKHR(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)
if (GetPhysicalDeviceSurfaceFormatsKHR(vk_physical_device, vk_surface, &format_count, formats) < 0)
{
free(formats);
goto fail;
@ -413,20 +458,20 @@ static inline struct demo_swapchain *demo_swapchain_create(ID3D12CommandQueue *c
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)
if (CreateSwapchainKHR(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)
if (CreateFence(vk_device, &fence_desc, NULL, &vk_fence) < 0)
goto fail;
if (vkGetSwapchainImagesKHR(vk_device, vk_swapchain, &image_count, NULL) < 0
if (GetSwapchainImagesKHR(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)
if (GetSwapchainImagesKHR(vk_device, vk_swapchain, &image_count, vk_images) < 0)
{
free(vk_images);
goto fail;
@ -443,10 +488,10 @@ static inline struct demo_swapchain *demo_swapchain_create(ID3D12CommandQueue *c
swapchain->vk_instance = vk_instance;
swapchain->vk_device = vk_device;
vkAcquireNextImageKHR(vk_device, vk_swapchain, UINT64_MAX,
AcquireNextImageKHR(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);
WaitForFences(vk_device, 1, &vk_fence, VK_TRUE, UINT64_MAX);
ResetFences(vk_device, 1, &vk_fence);
resource_create_info.type = VKD3D_STRUCTURE_TYPE_IMAGE_RESOURCE_CREATE_INFO;
resource_create_info.next = NULL;
@ -487,10 +532,10 @@ static inline struct demo_swapchain *demo_swapchain_create(ID3D12CommandQueue *c
fail:
if (vk_fence != VK_NULL_HANDLE)
vkDestroyFence(vk_device, vk_fence, NULL);
DestroyFence(vk_device, vk_fence, NULL);
if (vk_swapchain != VK_NULL_HANDLE)
vkDestroySwapchainKHR(vk_device, vk_swapchain, NULL);
vkDestroySurfaceKHR(vk_instance, vk_surface, NULL);
DestroySwapchainKHR(vk_device, vk_swapchain, NULL);
DestroySurfaceKHR(vk_instance, vk_surface, NULL);
ID3D12Device_Release(d3d12_device);
return NULL;
}
@ -525,13 +570,13 @@ static inline void demo_swapchain_present(struct demo_swapchain *swapchain)
present_desc.pResults = NULL;
vk_queue = vkd3d_acquire_vk_queue(swapchain->command_queue);
vkQueuePresentKHR(vk_queue, &present_desc);
QueuePresentKHR(vk_queue, &present_desc);
vkd3d_release_vk_queue(swapchain->command_queue);
vkAcquireNextImageKHR(swapchain->vk_device, swapchain->vk_swapchain, UINT64_MAX,
AcquireNextImageKHR(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);
WaitForFences(swapchain->vk_device, 1, &swapchain->vk_fence, VK_TRUE, UINT64_MAX);
ResetFences(swapchain->vk_device, 1, &swapchain->vk_fence);
}
static inline void demo_swapchain_destroy(struct demo_swapchain *swapchain)
@ -543,9 +588,9 @@ static inline void demo_swapchain_destroy(struct demo_swapchain *swapchain)
{
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);
DestroyFence(swapchain->vk_device, swapchain->vk_fence, NULL);
DestroySwapchainKHR(swapchain->vk_device, swapchain->vk_swapchain, NULL);
DestroySurfaceKHR(swapchain->vk_instance, swapchain->vk_surface, NULL);
free(swapchain);
}

35
include/vkd3d_sonames.h Normal file
View File

@ -0,0 +1,35 @@
/*
* Copyright 2020 Hans-Kristian Arntzen for Valve Corporation
*
* 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
*/
#ifndef __VKD3D_SONAMES_H
#define __VKD3D_SONAMES_H
/* These sonames are defined by the loader ABI. */
#if defined(_WIN32)
#define SONAME_LIBVULKAN "vulkan-1.dll"
#elif defined(__linux__)
#define SONAME_LIBVULKAN "libvulkan.so.1"
#elif defined(__APPLE__)
#define SONAME_LIBVULKAN "libvulkan.1.dylib"
#else
#error "Unrecognized platform."
#endif
#endif

View File

@ -17,6 +17,7 @@
*/
#include "vkd3d_private.h"
#include "vkd3d_sonames.h"
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>

View File

@ -58,6 +58,7 @@ typedef int HRESULT;
# include "vkd3d_threads.h"
# include "vkd3d.h"
# include "vkd3d_utils.h"
# include "vkd3d_sonames.h"
#endif
#if !defined(_WIN32)
@ -418,7 +419,7 @@ static bool init_vulkan_loader(void)
return true;
#ifdef _WIN32
HMODULE mod = LoadLibrary(SONAME_LIBVULKAN);
HMODULE mod = LoadLibraryA(SONAME_LIBVULKAN);
if (!mod)
return false;