Skip to content

Commit

Permalink
Statically link a vulkan loader on Linux. Use to to init vulkan on X1…
Browse files Browse the repository at this point in the history
…1. Unfortunately, it's broken.
  • Loading branch information
hrydgard committed Dec 21, 2017
1 parent 6d6ad3e commit 7f758d5
Show file tree
Hide file tree
Showing 7 changed files with 381 additions and 297 deletions.
21 changes: 20 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,25 @@ else()
add_definitions(-DNO_VULKAN)
endif()

if(NOT ANDROID)
# Use FindVulkan module added with CMAKE 3.7
if (NOT CMAKE_VERSION VERSION_LESS 3.7.0)
message(STATUS "Using module to find Vulkan")
find_package(Vulkan)
endif()
endif()

if(NOT WIN32 AND VULKAN)
IF (NOT Vulkan_FOUND)
find_library(Vulkan_LIBRARY NAMES vulkan HINTS "$ENV{VULKAN_SDK}/lib" "${CMAKE_SOURCE_DIR}/ext/vulkan" REQUIRED)
IF (Vulkan_LIBRARY)
set(Vulkan_FOUND ON)
MESSAGE("Using bundled Vulkan library version")
add_definitions(-DVULKAN_STATIC)
ENDIF()
ENDIF()
endif()

if(NOT DEFINED HEADLESS)
set(HEADLESS OFF)
endif()
Expand Down Expand Up @@ -1653,7 +1672,7 @@ set(CoreExtraLibs ${CoreExtraLibs} armips)
set(GlslangLibs glslang OGLCompiler OSDependent SPIRV SPVRemapper spirv-cross-glsl)

target_link_libraries(${CoreLibName} Common native kirk cityhash sfmt19937 xbrz xxhash ${GlslangLibs}
${CoreExtraLibs} ${OPENGL_LIBRARIES} ${X11_LIBRARIES} ${CMAKE_DL_LIBS})
${CoreExtraLibs} ${OPENGL_LIBRARIES} ${X11_LIBRARIES} ${CMAKE_DL_LIBS} ${Vulkan_LIBRARY})

if(FFmpeg_FOUND)
target_compile_definitions(${CoreLibName} PRIVATE USE_FFMPEG=1)
Expand Down
23 changes: 13 additions & 10 deletions Common/Vulkan/VulkanContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ VkResult VulkanContext::CreateInstance(const CreateInfo &info) {
instance_extensions_enabled_.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
#elif defined(VK_USE_PLATFORM_XCB_KHR)
instance_extensions_enabled_.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
#elif defined(VK_USE_PLATFORM_MIR_KHR)
instance_extensions_enabled_.push_back(VK_KHR_MIR_SURFACE_EXTENSION_NAME);
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
instance_extensions.enabled_.push_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
#else
Expand Down Expand Up @@ -432,6 +434,7 @@ int VulkanContext::GetBestPhysicalDevice() {

void VulkanContext::ChooseDevice(int physical_device) {
physical_device_ = physical_device;
ILOG("Chose physical device %d: %p", physical_device, physical_devices_[physical_device]);

GetDeviceLayerProperties();
if (!CheckLayers(device_layer_properties_, device_layer_names_)) {
Expand Down Expand Up @@ -553,6 +556,7 @@ VkResult VulkanContext::CreateDevice() {
} else {
VulkanLoadDeviceFunctions(device_);
}
ILOG("Device created.\n");
return res;
}

Expand All @@ -571,7 +575,7 @@ VkResult VulkanContext::InitDebugMsgCallback(PFN_vkDebugReportCallbackEXT dbgFun
cb.flags = bits;
cb.pfnCallback = dbgFunc;
cb.pUserData = userdata;
VkResult res = vkCreateDebugReportCallbackEXT(instance_, &cb, nullptr, &msg_callback);
VkResult res = dyn_vkCreateDebugReportCallbackEXT(instance_, &cb, nullptr, &msg_callback);
switch (res) {
case VK_SUCCESS:
msg_callbacks.push_back(msg_callback);
Expand All @@ -586,7 +590,7 @@ VkResult VulkanContext::InitDebugMsgCallback(PFN_vkDebugReportCallbackEXT dbgFun

void VulkanContext::DestroyDebugMsgCallback() {
while (msg_callbacks.size() > 0) {
vkDestroyDebugReportCallbackEXT(instance_, msg_callbacks.back(), nullptr);
dyn_vkDestroyDebugReportCallbackEXT(instance_, msg_callbacks.back(), nullptr);
msg_callbacks.pop_back();
}
}
Expand Down Expand Up @@ -650,7 +654,6 @@ void VulkanContext::ReinitSurface(int width, int height) {
assert(res == VK_SUCCESS);
break;
}

#endif
#if defined(VK_USE_PLATFORM_XCB_KHR)
case WINDOWSYSTEM_XCB:
Expand Down Expand Up @@ -718,16 +721,17 @@ bool VulkanContext::InitQueue() {
graphics_queue_family_index_ = graphicsQueueNodeIndex;

// Get the list of VkFormats that are supported:
uint32_t formatCount;
uint32_t formatCount = 0;
VkResult res = vkGetPhysicalDeviceSurfaceFormatsKHR(physical_devices_[physical_device_], surface_, &formatCount, nullptr);
assert(res == VK_SUCCESS);
if (res != VK_SUCCESS)
_assert_msg_(G3D, res == VK_SUCCESS, "Failed to get formats for device %p: %d surface: %p", physical_devices_[physical_device_], (int)res, surface_);
if (res != VK_SUCCESS) {
return false;
VkSurfaceFormatKHR *surfFormats = new VkSurfaceFormatKHR[formatCount];
res = vkGetPhysicalDeviceSurfaceFormatsKHR(physical_devices_[physical_device_], surface_, &formatCount, surfFormats);
}

std::vector<VkSurfaceFormatKHR> surfFormats(formatCount);
res = vkGetPhysicalDeviceSurfaceFormatsKHR(physical_devices_[physical_device_], surface_, &formatCount, surfFormats.data());
assert(res == VK_SUCCESS);
if (res != VK_SUCCESS) {
delete[] surfFormats;
return false;
}
// If the format list includes just one entry of VK_FORMAT_UNDEFINED,
Expand All @@ -754,7 +758,6 @@ bool VulkanContext::InitQueue() {
}
ILOG("swapchain_format: %d (/%d)", swapchainFormat_, formatCount);
}
delete[] surfFormats;

vkGetDeviceQueue(device_, graphics_queue_family_index_, 0, &gfx_queue_);
ILOG("gfx_queue_: %p", gfx_queue_);
Expand Down
49 changes: 39 additions & 10 deletions Common/Vulkan/VulkanLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@

#include "Common/Vulkan/VulkanLoader.h"
#include "base/logging.h"
#include "base/basictypes.h"

#ifndef _WIN32
#include <dlfcn.h>
#endif

#ifndef VULKAN_STATIC

PFN_vkCreateInstance vkCreateInstance;
PFN_vkDestroyInstance vkDestroyInstance;
Expand Down Expand Up @@ -181,10 +183,12 @@ PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR;
PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR;
PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR;
PFN_vkQueuePresentKHR vkQueuePresentKHR;
#endif

// And the DEBUG_REPORT extension. We dynamically load this.
PFN_vkCreateDebugReportCallbackEXT dyn_vkCreateDebugReportCallbackEXT;
PFN_vkDestroyDebugReportCallbackEXT dyn_vkDestroyDebugReportCallbackEXT;

// And the DEBUG_REPORT extension.
PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT;
PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT;

#ifdef _WIN32
static HINSTANCE vulkanLibrary;
Expand All @@ -197,15 +201,26 @@ static void *vulkanLibrary;
#define LOAD_DEVICE_FUNC(instance, x) x = (PFN_ ## x)vkGetDeviceProcAddr(instance, #x); if (!x) {ILOG("Missing (device): %s", #x);}
#define LOAD_GLOBAL_FUNC(x) x = (PFN_ ## x)dlsym(vulkanLibrary, #x); if (!x) {ILOG("Missing (global): %s", #x);}

static const char *so_names[] = {
"libvulkan.so",
"libvulkan.so.1",
};

bool VulkanMayBeAvailable() {
#ifdef VULKAN_STATIC
return true;
#else
if (vulkanLibrary)
return true;
bool available = false;
#ifndef _WIN32
void *lib = dlopen("libvulkan.so", RTLD_NOW | RTLD_LOCAL);
available = lib != nullptr;
if (lib) {
dlclose(lib);
for (int i = 0; i < ARRAY_SIZE(so_names); i++) {
void *lib = dlopen(so_names[i], RTLD_NOW | RTLD_LOCAL);
if (lib) {
available = true;
dlclose(lib);
break;
}
}
#else
// LoadLibrary etc
Expand All @@ -216,12 +231,18 @@ bool VulkanMayBeAvailable() {
}
#endif
return available;
#endif
}

bool VulkanLoad() {
#ifndef VULKAN_STATIC
if (!vulkanLibrary) {
#ifndef _WIN32
vulkanLibrary = dlopen("libvulkan.so", RTLD_NOW | RTLD_LOCAL);
for (int i = 0; i < ARRAY_SIZE(so_names); i++) {
vulkanLibrary = dlopen(so_names[i], RTLD_NOW | RTLD_LOCAL);
if (vulkanLibrary)
break;
}
#else
// LoadLibrary etc
vulkanLibrary = LoadLibrary(L"vulkan-1.dll");
Expand All @@ -239,10 +260,12 @@ bool VulkanLoad() {
LOAD_GLOBAL_FUNC(vkEnumerateInstanceLayerProperties);

WLOG("Vulkan base functions loaded.");
#endif
return true;
}

void VulkanLoadInstanceFunctions(VkInstance instance) {
#ifndef VULKAN_STATIC
// OK, let's use the above functions to get the rest.
LOAD_INSTANCE_FUNC(instance, vkDestroyInstance);
LOAD_INSTANCE_FUNC(instance, vkEnumeratePhysicalDevices);
Expand Down Expand Up @@ -397,9 +420,11 @@ void VulkanLoadInstanceFunctions(VkInstance instance) {
#endif

LOAD_INSTANCE_FUNC(instance, vkDestroySurfaceKHR);
#endif

dyn_vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT");
dyn_vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT");

LOAD_INSTANCE_FUNC(instance, vkCreateDebugReportCallbackEXT);
LOAD_INSTANCE_FUNC(instance, vkDestroyDebugReportCallbackEXT);
WLOG("Vulkan instance functions loaded.");
}

Expand All @@ -408,15 +433,18 @@ void VulkanLoadInstanceFunctions(VkInstance instance) {
// good for multi-device.
void VulkanLoadDeviceFunctions(VkDevice device) {
WLOG("Vulkan device functions loaded.");
#ifndef VULKAN_STATIC
// TODO: Move more functions VulkanLoadInstanceFunctions to here.
LOAD_DEVICE_FUNC(device, vkCreateSwapchainKHR);
LOAD_DEVICE_FUNC(device, vkDestroySwapchainKHR);
LOAD_DEVICE_FUNC(device, vkGetSwapchainImagesKHR);
LOAD_DEVICE_FUNC(device, vkAcquireNextImageKHR);
LOAD_DEVICE_FUNC(device, vkQueuePresentKHR);
#endif
}

void VulkanFree() {
#ifndef VULKAN_STATIC
if (vulkanLibrary) {
#ifdef _WIN32
FreeLibrary(vulkanLibrary);
Expand All @@ -425,4 +453,5 @@ void VulkanFree() {
#endif
vulkanLibrary = nullptr;
}
#endif
}
14 changes: 10 additions & 4 deletions Common/Vulkan/VulkanLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,13 @@
#define NOMINMAX
#endif

#ifndef VULKAN_STATIC
#define VK_NO_PROTOTYPES
#endif

#include "ext/vulkan/vulkan.h"

#ifndef VULKAN_STATIC
extern PFN_vkCreateInstance vkCreateInstance;
extern PFN_vkDestroyInstance vkDestroyInstance;
extern PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices;
Expand Down Expand Up @@ -189,9 +192,13 @@ extern PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR;
extern PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR;
extern PFN_vkQueuePresentKHR vkQueuePresentKHR;

// And the DEBUG_REPORT extension.
extern PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT;
extern PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT;
#endif

// And the DEBUG_REPORT extension. Since we load this dynamically even in static
// linked mode, we have to rename it :(
extern PFN_vkCreateDebugReportCallbackEXT dyn_vkCreateDebugReportCallbackEXT;
extern PFN_vkDestroyDebugReportCallbackEXT dyn_vkDestroyDebugReportCallbackEXT;


// Way to do a quick check before even attempting to load.
bool VulkanMayBeAvailable();
Expand All @@ -200,4 +207,3 @@ bool VulkanLoad();
void VulkanLoadInstanceFunctions(VkInstance instance);
void VulkanLoadDeviceFunctions(VkDevice device);
void VulkanFree();

14 changes: 7 additions & 7 deletions GPU/Vulkan/VertexShaderGeneratorVulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,27 +169,27 @@ bool GenerateVulkanGLSLVertexShader(const VShaderID &id, char *buffer, bool *use
}

if (useHWTransform)
WRITE(p, "layout (location = %d) in vec3 position;\n", PspAttributeLocation::POSITION);
WRITE(p, "layout (location = %d) in vec3 position;\n", (int)PspAttributeLocation::POSITION);
else
// we pass the fog coord in w
WRITE(p, "layout (location = %d) in vec4 position;\n", PspAttributeLocation::POSITION);
WRITE(p, "layout (location = %d) in vec4 position;\n", (int)PspAttributeLocation::POSITION);

if (useHWTransform && hasNormal)
WRITE(p, "layout (location = %d) in vec3 normal;\n", PspAttributeLocation::NORMAL);
WRITE(p, "layout (location = %d) in vec3 normal;\n", (int)PspAttributeLocation::NORMAL);

bool texcoordInVec3 = false;
if (doTexture && hasTexcoord) {
if (!useHWTransform && doTextureTransform && !throughmode) {
WRITE(p, "layout (location = %d) in vec3 texcoord;\n", PspAttributeLocation::TEXCOORD);
WRITE(p, "layout (location = %d) in vec3 texcoord;\n", (int)PspAttributeLocation::TEXCOORD);
texcoordInVec3 = true;
}
else
WRITE(p, "layout (location = %d) in vec2 texcoord;\n", PspAttributeLocation::TEXCOORD);
WRITE(p, "layout (location = %d) in vec2 texcoord;\n", (int)PspAttributeLocation::TEXCOORD);
}
if (hasColor) {
WRITE(p, "layout (location = %d) in vec4 color0;\n", PspAttributeLocation::COLOR0);
WRITE(p, "layout (location = %d) in vec4 color0;\n", (int)PspAttributeLocation::COLOR0);
if (lmode && !useHWTransform) // only software transform supplies color1 as vertex data
WRITE(p, "layout (location = %d) in vec3 color1;\n", PspAttributeLocation::COLOR1);
WRITE(p, "layout (location = %d) in vec3 color1;\n", (int)PspAttributeLocation::COLOR1);
}

WRITE(p, "layout (location = 1) %sout vec4 v_color0;\n", shading);
Expand Down
Loading

0 comments on commit 7f758d5

Please sign in to comment.