|
#include <algorithm> |
|
#include <array> |
|
#include <exception> |
|
#include <iostream> |
|
#include <fstream> |
|
#include <memory> |
|
#include <ostream> |
|
#include <set> |
|
#include <string> |
|
#include <unordered_map> |
|
#include <vector> |
|
#include <utility> |
|
|
|
#include <assert.h> |
|
#include <stdint.h> |
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include <time.h> |
|
#include <cstring> |
|
|
|
#include <dlfcn.h> |
|
|
|
|
|
#include <vulkan/vulkan.h> |
|
|
|
#include <cassert> |
|
#include <bitset> |
|
#define LOG(s) std::cout << "Line:" << std::to_string(__LINE__) << ": " << s << std::endl |
|
static VKAPI_ATTR VkBool32 VKAPI_CALL DbgCallback(VkDebugReportFlagsEXT msgFlags, VkDebugReportObjectTypeEXT objType, |
|
uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix, |
|
const char *pMsg, void *pUserData) { |
|
std::bitset<8> bs(msgFlags); |
|
std::cerr << bs << ": [" << pLayerPrefix << "] Code " << msgCode << " : " << pMsg << "\n"; |
|
|
|
// True is reserved for layer developers, and MAY mean calls are not distributed down the layer chain after validation |
|
// error. False SHOULD always be returned by apps: |
|
return VK_FALSE; |
|
} |
|
|
|
int main(int argc, char **argv) { |
|
/////////////////////////////////////////////////////// |
|
/// Get Wayland Vulkan DLL Symbols |
|
void *library; |
|
library = dlopen("libvulkan.so", RTLD_NOW | RTLD_LOCAL); |
|
auto vkEnumeratePhysicalDevices = |
|
reinterpret_cast<PFN_vkEnumeratePhysicalDevices>(dlsym(library, "vkEnumeratePhysicalDevices")); |
|
auto vkCreateWaylandSurfaceKHR = reinterpret_cast<PFN_vkCreateWaylandSurfaceKHR>(dlsym(library, "vkCreateWaylandSurfaceKHR")); |
|
auto vkEnumerateInstanceExtensionProperties = |
|
reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(dlsym(library, "vkEnumerateInstanceExtensionProperties")); |
|
auto vkCreateInstance = reinterpret_cast<PFN_vkCreateInstance>(dlsym(library, "vkCreateInstance")); |
|
auto vkEnumerateInstanceVersion = |
|
reinterpret_cast<PFN_vkEnumerateInstanceVersion>(dlsym(library, "vkEnumerateInstanceVersion")); |
|
auto vkGetInstanceProcAddr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(dlsym(library, "vkGetInstanceProcAddr")); |
|
|
|
/// |
|
/////////////////////////////////////////////////////// |
|
|
|
/////////////////////////////////////////////////////// |
|
/// Get Global Layer Extensions |
|
VkExtensionProperties init; |
|
uint32_t count = 0; |
|
std::vector<VkExtensionProperties> global_extensions; |
|
VkResult err = vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr); |
|
assert(err == VK_SUCCESS); |
|
global_extensions.resize(count, init); |
|
err = vkEnumerateInstanceExtensionProperties(nullptr, &count, global_extensions.data()); |
|
assert(err == VK_SUCCESS); |
|
global_extensions.resize(count); |
|
std::vector<const char *> inst_exts; |
|
bool has_portability_extension = false; |
|
for (const auto &ext : global_extensions) { |
|
std::cout << ext.extensionName << std::endl; |
|
inst_exts.push_back(ext.extensionName); |
|
if (0 == strcmp(ext.extensionName, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME)) has_portability_extension = true; |
|
} |
|
assert(has_portability_extension == true); |
|
/// |
|
/////////////////////////////////////////////////////// |
|
|
|
/////////////////////////////////////////////////////// |
|
/// Make Vulkan Instance |
|
VkInstance instance; |
|
const VkDebugReportCallbackCreateInfoEXT dbg_info = {VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT, nullptr, |
|
VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT, |
|
DbgCallback}; |
|
|
|
uint32_t instance_version; |
|
err = vkEnumerateInstanceVersion(&instance_version); |
|
assert(err == VK_SUCCESS); |
|
const VkApplicationInfo app_info = { |
|
VK_STRUCTURE_TYPE_APPLICATION_INFO, nullptr, "vulkan_wayland_virtio_test", 1, nullptr, 0, instance_version}; |
|
|
|
const VkInstanceCreateInfo inst_info = {VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, |
|
&dbg_info, |
|
static_cast<VkInstanceCreateFlags>(VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR), |
|
&app_info, |
|
0, |
|
nullptr, |
|
static_cast<uint32_t>(inst_exts.size()), |
|
inst_exts.data()}; |
|
err = vkCreateInstance(&inst_info, nullptr, &instance); |
|
assert(err == VK_SUCCESS); |
|
VkDebugReportCallbackEXT debug_callback = VK_NULL_HANDLE; |
|
auto vkCreateDebugReportCallbackEXT = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>( |
|
vkGetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT")); |
|
err = vkCreateDebugReportCallbackEXT(instance, &dbg_info, nullptr, &debug_callback); |
|
assert(err == VK_SUCCESS); |
|
/// |
|
/////////////////////////////////////////////////////// |
|
|
|
/////////////////////////////////////////////////////// |
|
/// Get Physical Device |
|
VkPhysicalDevice init_physical_device{}; |
|
count = 0; |
|
err = vkEnumeratePhysicalDevices(instance, &count, nullptr); |
|
assert(err == VK_SUCCESS); |
|
std::vector<VkPhysicalDevice> phys_devices; |
|
phys_devices.resize(count, init_physical_device); |
|
err = vkEnumeratePhysicalDevices(instance, &count, phys_devices.data()); |
|
phys_devices.resize(count); |
|
assert(err == VK_SUCCESS); |
|
if (phys_devices.size() != 1) { |
|
LOG("Unexpected size of phys_devices array: " << phys_devices.size()); |
|
} |
|
auto &phys_device = phys_devices[0]; |
|
/// |
|
/////////////////////////////////////////////////////// |
|
|
|
/////////////////////////////////////////////////////// |
|
/// Create a Wayland Window |
|
wl_display *wayland_display = wl_display_connect(nullptr); |
|
wl_surface *wayland_surface; |
|
struct wl_registry *registry = wl_display_get_registry(wayland_display); |
|
auto wayland_registry_global = [](void *data, struct wl_registry *registry, uint32_t id, const char *interface, |
|
uint32_t version) -> void { |
|
auto wayland_surface = static_cast<wl_surface **>(data); |
|
if (strcmp(interface, "wl_compositor") == 0) { |
|
struct wl_compositor *compositor = (struct wl_compositor *)wl_registry_bind(registry, id, &wl_compositor_interface, 1); |
|
*wayland_surface = wl_compositor_create_surface(compositor); |
|
} |
|
}; |
|
auto wayland_registry_global_remove = [](void *data, struct wl_registry *registry, uint32_t id) -> void {}; |
|
const struct wl_registry_listener wayland_registry_listener = {wayland_registry_global, wayland_registry_global_remove}; |
|
wl_registry_add_listener(wl_display_get_registry(wayland_display), &wayland_registry_listener, &wayland_surface); |
|
wl_display_roundtrip(wayland_display); |
|
wl_registry_destroy(registry); |
|
|
|
/////////////////////////////////////////////////////// |
|
/// Create a Wayland Surface |
|
VkWaylandSurfaceCreateInfoKHR createInfo; |
|
createInfo.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR; |
|
createInfo.pNext = nullptr; |
|
createInfo.flags = 0; |
|
createInfo.display = wayland_display; |
|
createInfo.surface = wayland_surface; |
|
|
|
VkSurfaceKHR surface; |
|
err = vkCreateWaylandSurfaceKHR(instance, &createInfo, nullptr, &surface); |
|
assert(err == VK_SUCCESS); |
|
/// |
|
/////////////////////////////////////////////////////// |
|
|
|
/////////////////////////////////////////////////////// |
|
/// Get Wayland Surface Formats |
|
auto vkGetPhysicalDeviceSurfaceFormats2KHR = |
|
reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceFormats2KHR>(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceFormats2KHR")); |
|
const VkPhysicalDeviceSurfaceInfo2KHR surface_info2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR, nullptr, surface}; |
|
VkSurfaceFormat2KHR init_surface_format{}; |
|
init_surface_format.sType = VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR; |
|
std::vector<VkSurfaceFormat2KHR> surf_formats2; |
|
err = vkGetPhysicalDeviceSurfaceFormats2KHR(phys_device, &surface_info2, &count, nullptr); |
|
assert(err == VK_ERROR_SURFACE_LOST_KHR); |
|
assert(err == VK_SUCCESS); |
|
surf_formats2.resize(count, init_surface_format); |
|
err = vkGetPhysicalDeviceSurfaceFormats2KHR(phys_device, &surface_info2, &count, surf_formats2.data()); |
|
surf_formats2.resize(count); |
|
assert(err == VK_SUCCESS); |
|
/// |
|
/////////////////////////////////////////////////////// |
|
|
|
return 0; |
|
} |