Add support for rendering for the headless extension

This commit is contained in:
Per Inge Mathisen 2021-04-27 13:52:27 +02:00
parent a2a604be47
commit 45ba247b55
6 changed files with 68 additions and 5 deletions

View file

@ -18,6 +18,7 @@ include_directories(base)
OPTION(USE_D2D_WSI "Build the project using Direct to Display swapchain" OFF) OPTION(USE_D2D_WSI "Build the project using Direct to Display swapchain" OFF)
OPTION(USE_DIRECTFB_WSI "Build the project using DirectFB swapchain" OFF) OPTION(USE_DIRECTFB_WSI "Build the project using DirectFB swapchain" OFF)
OPTION(USE_WAYLAND_WSI "Build the project using Wayland swapchain" OFF) OPTION(USE_WAYLAND_WSI "Build the project using Wayland swapchain" OFF)
OPTION(USE_HEADLESS "Build the project using headless extension swapchain" OFF)
set(RESOURCE_INSTALL_DIR "" CACHE PATH "Path to install resources to (leave empty for running uninstalled)") set(RESOURCE_INSTALL_DIR "" CACHE PATH "Path to install resources to (leave empty for running uninstalled)")
@ -79,6 +80,8 @@ ELSEIF(LINUX)
execute_process(COMMAND ${WAYLAND_SCANNER} client-header ${protocol_dir}/stable/xdg-shell/xdg-shell.xml ${CMAKE_BINARY_DIR}/xdg-shell-client-protocol.h execute_process(COMMAND ${WAYLAND_SCANNER} client-header ${protocol_dir}/stable/xdg-shell/xdg-shell.xml ${CMAKE_BINARY_DIR}/xdg-shell-client-protocol.h
COMMAND ${WAYLAND_SCANNER} private-code ${protocol_dir}/stable/xdg-shell/xdg-shell.xml ${CMAKE_BINARY_DIR}/xdg-shell-protocol.c) COMMAND ${WAYLAND_SCANNER} private-code ${protocol_dir}/stable/xdg-shell/xdg-shell.xml ${CMAKE_BINARY_DIR}/xdg-shell-protocol.c)
include_directories(${CMAKE_BINARY_DIR}) include_directories(${CMAKE_BINARY_DIR})
ELSEIF(USE_HEADLESS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVK_USE_PLATFORM_HEADLESS_EXT")
ELSE(USE_D2D_WSI) ELSE(USE_D2D_WSI)
find_package(XCB REQUIRED) find_package(XCB REQUIRED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVK_USE_PLATFORM_XCB_KHR") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVK_USE_PLATFORM_XCB_KHR")

View file

@ -23,7 +23,7 @@ void VulkanSwapChain::initSurface(wl_display *display, wl_surface *window)
void VulkanSwapChain::initSurface(xcb_connection_t* connection, xcb_window_t window) void VulkanSwapChain::initSurface(xcb_connection_t* connection, xcb_window_t window)
#elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK)) #elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
void VulkanSwapChain::initSurface(void* view) void VulkanSwapChain::initSurface(void* view)
#elif defined(_DIRECT2DISPLAY) #elif (defined(_DIRECT2DISPLAY) || defined(VK_USE_PLATFORM_HEADLESS_EXT))
void VulkanSwapChain::initSurface(uint32_t width, uint32_t height) void VulkanSwapChain::initSurface(uint32_t width, uint32_t height)
#endif #endif
{ {
@ -75,6 +75,14 @@ void VulkanSwapChain::initSurface(uint32_t width, uint32_t height)
surfaceCreateInfo.connection = connection; surfaceCreateInfo.connection = connection;
surfaceCreateInfo.window = window; surfaceCreateInfo.window = window;
err = vkCreateXcbSurfaceKHR(instance, &surfaceCreateInfo, nullptr, &surface); err = vkCreateXcbSurfaceKHR(instance, &surfaceCreateInfo, nullptr, &surface);
#elif defined(VK_USE_PLATFORM_HEADLESS_EXT)
VkHeadlessSurfaceCreateInfoEXT surfaceCreateInfo = {};
surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT;
PFN_vkCreateHeadlessSurfaceEXT fpCreateHeadlessSurfaceEXT = (PFN_vkCreateHeadlessSurfaceEXT)vkGetInstanceProcAddr(instance, "vkCreateHeadlessSurfaceEXT");
if (!fpCreateHeadlessSurfaceEXT){
vks::tools::exitFatal("Could not fetch function pointer for the headless extension!", -1);
}
err = fpCreateHeadlessSurfaceEXT(instance, &surfaceCreateInfo, nullptr, &surface);
#endif #endif
if (err != VK_SUCCESS) { if (err != VK_SUCCESS) {

View file

@ -66,9 +66,11 @@ public:
void initSurface(xcb_connection_t* connection, xcb_window_t window); void initSurface(xcb_connection_t* connection, xcb_window_t window);
#elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK)) #elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
void initSurface(void* view); void initSurface(void* view);
#elif defined(_DIRECT2DISPLAY) #elif (defined(_DIRECT2DISPLAY) || defined(VK_USE_PLATFORM_HEADLESS_EXT))
void initSurface(uint32_t width, uint32_t height); void initSurface(uint32_t width, uint32_t height);
#if defined(_DIRECT2DISPLAY)
void createDirect2DisplaySurface(uint32_t width, uint32_t height); void createDirect2DisplaySurface(uint32_t width, uint32_t height);
#endif
#endif #endif
void connect(VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device); void connect(VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device);
void create(uint32_t* width, uint32_t* height, bool vsync = false); void create(uint32_t* width, uint32_t* height, bool vsync = false);

View file

@ -51,6 +51,8 @@ VkResult VulkanExampleBase::createInstance(bool enableValidation)
instanceExtensions.push_back(VK_MVK_IOS_SURFACE_EXTENSION_NAME); instanceExtensions.push_back(VK_MVK_IOS_SURFACE_EXTENSION_NAME);
#elif defined(VK_USE_PLATFORM_MACOS_MVK) #elif defined(VK_USE_PLATFORM_MACOS_MVK)
instanceExtensions.push_back(VK_MVK_MACOS_SURFACE_EXTENSION_NAME); instanceExtensions.push_back(VK_MVK_MACOS_SURFACE_EXTENSION_NAME);
#elif defined(VK_USE_PLATFORM_HEADLESS_EXT)
instanceExtensions.push_back(VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME);
#endif #endif
// Get extensions supported by the instance and store for later use // Get extensions supported by the instance and store for later use
@ -584,6 +586,40 @@ void VulkanExampleBase::renderLoop()
} }
updateOverlay(); updateOverlay();
} }
#elif defined(VK_USE_PLATFORM_HEADLESS_EXT)
while (!quit)
{
auto tStart = std::chrono::high_resolution_clock::now();
if (viewUpdated)
{
viewUpdated = false;
viewChanged();
}
render();
frameCounter++;
auto tEnd = std::chrono::high_resolution_clock::now();
auto tDiff = std::chrono::duration<double, std::milli>(tEnd - tStart).count();
frameTimer = tDiff / 1000.0f;
camera.update(frameTimer);
if (camera.moving())
{
viewUpdated = true;
}
// Convert to clamped timer value
timer += timerSpeed * frameTimer;
if (timer > 1.0)
{
timer -= 1.0f;
}
float fpsTimer = std::chrono::duration<double, std::milli>(tEnd - lastTimestamp).count();
if (fpsTimer > 1000.0f)
{
lastFPS = (float)frameCounter * (1000.0f / fpsTimer);
frameCounter = 0;
lastTimestamp = tEnd;
}
updateOverlay();
}
#elif (defined(VK_USE_PLATFORM_MACOS_MVK) && defined(VK_EXAMPLE_XCODE_GENERATED)) #elif (defined(VK_USE_PLATFORM_MACOS_MVK) && defined(VK_EXAMPLE_XCODE_GENERATED))
[NSApp run]; [NSApp run];
#endif #endif
@ -2425,6 +2461,10 @@ void VulkanExampleBase::handleEvent(const xcb_generic_event_t *event)
break; break;
} }
} }
#else
void VulkanExampleBase::setupWindow()
{
}
#endif #endif
void VulkanExampleBase::viewChanged() {} void VulkanExampleBase::viewChanged() {}
@ -2690,14 +2730,14 @@ void VulkanExampleBase::initSwapchain()
swapChain.initSurface(androidApp->window); swapChain.initSurface(androidApp->window);
#elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK)) #elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
swapChain.initSurface(view); swapChain.initSurface(view);
#elif defined(_DIRECT2DISPLAY)
swapChain.initSurface(width, height);
#elif defined(VK_USE_PLATFORM_DIRECTFB_EXT) #elif defined(VK_USE_PLATFORM_DIRECTFB_EXT)
swapChain.initSurface(dfb, surface); swapChain.initSurface(dfb, surface);
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR) #elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
swapChain.initSurface(display, surface); swapChain.initSurface(display, surface);
#elif defined(VK_USE_PLATFORM_XCB_KHR) #elif defined(VK_USE_PLATFORM_XCB_KHR)
swapChain.initSurface(connection, window); swapChain.initSurface(connection, window);
#elif (defined(_DIRECT2DISPLAY) || defined(VK_USE_PLATFORM_HEADLESS_EXT))
swapChain.initSurface(width, height);
#endif #endif
} }

View file

@ -283,6 +283,8 @@ public:
xcb_screen_t *screen; xcb_screen_t *screen;
xcb_window_t window; xcb_window_t window;
xcb_intern_atom_reply_t *atom_wm_delete_window; xcb_intern_atom_reply_t *atom_wm_delete_window;
#elif defined(VK_USE_PLATFORM_HEADLESS_EXT)
bool quit = false;
#endif #endif
VulkanExampleBase(bool enableValidation = false); VulkanExampleBase(bool enableValidation = false);
@ -356,6 +358,8 @@ public:
xcb_window_t setupWindow(); xcb_window_t setupWindow();
void initxcbConnection(); void initxcbConnection();
void handleEvent(const xcb_generic_event_t *event); void handleEvent(const xcb_generic_event_t *event);
#else
void setupWindow();
#endif #endif
/** @brief (Virtual) Creates the application wide Vulkan instance */ /** @brief (Virtual) Creates the application wide Vulkan instance */
virtual VkResult createInstance(bool enableValidation); virtual VkResult createInstance(bool enableValidation);
@ -480,7 +484,7 @@ int main(const int argc, const char *argv[]) \
delete(vulkanExample); \ delete(vulkanExample); \
return 0; \ return 0; \
} }
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR) #elif (defined(VK_USE_PLATFORM_WAYLAND_KHR) || defined(VK_USE_PLATFORM_HEADLESS_EXT))
#define VULKAN_EXAMPLE_MAIN() \ #define VULKAN_EXAMPLE_MAIN() \
VulkanExample *vulkanExample; \ VulkanExample *vulkanExample; \
int main(const int argc, const char *argv[]) \ int main(const int argc, const char *argv[]) \

View file

@ -1188,6 +1188,7 @@ int main(const int argc, const char *argv[])
// Linux entry point // Linux entry point
VulkanExample *vulkanExample; VulkanExample *vulkanExample;
#if defined(VK_USE_PLATFORM_XCB_KHR)
static void handleEvent(const xcb_generic_event_t *event) static void handleEvent(const xcb_generic_event_t *event)
{ {
if (vulkanExample != NULL) if (vulkanExample != NULL)
@ -1195,6 +1196,11 @@ static void handleEvent(const xcb_generic_event_t *event)
vulkanExample->handleEvent(event); vulkanExample->handleEvent(event);
} }
} }
#else
static void handleEvent()
{
}
#endif
int main(const int argc, const char *argv[]) int main(const int argc, const char *argv[])
{ {
for (size_t i = 0; i < argc; i++) { VulkanExample::args.push_back(argv[i]); }; for (size_t i = 0; i < argc; i++) { VulkanExample::args.push_back(argv[i]); };