Skip to content

Commit

Permalink
Change flag name to headless_surface.
Browse files Browse the repository at this point in the history
Use offscreen when speaking about no swapchain
Add warning when using headless on multiple GPUs
  • Loading branch information
iagoCL committed Aug 29, 2024
1 parent d70d3c3 commit 68fe8fa
Show file tree
Hide file tree
Showing 13 changed files with 48 additions and 29 deletions.
8 changes: 6 additions & 2 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,12 @@ vulkan_samples sample swapchain_images
# Run AFBC sample in benchmark mode for 5000 frames
vulkan_samples sample afbc --benchmark --stop-after-frame 5000
# Run bonza test offscreen
vulkan_samples test bonza --headless
# Run compute nbody using headless_surface and take a screenshot of frame 5
# Note: headless_surface uses VK_EXT_headless_surface.
# This will create a surface and a Swapchain, but present will be a no op.
# The extension is supported by Swiftshader(https://github.com/google/swiftshader).
# It allows to quickly test content in environments without a GPU.
vulkan_samples sample compute_nbody --headless_surface -screenshot 5
# Run all the performance samples for 10 seconds in each configuration
vulkan_samples batch --category performance --duration 10
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ public void setArguments(String... args) {
arguments.add("--benchmark");
}
if (isHeadless) {
arguments.add("--headless");
arguments.add("--headless_surface");
}
String[] argArray = new String[arguments.size()];
sendArgumentsToPlatform(arguments.toArray(argArray));
Expand Down
4 changes: 2 additions & 2 deletions app/plugins/window_options/window_options.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (c) 2020-2022, Arm Limited and Contributors
/* Copyright (c) 2020-2024, Arm Limited and Contributors
*
* SPDX-License-Identifier: Apache-2.0
*
Expand Down Expand Up @@ -47,7 +47,7 @@ class WindowOptions : public WindowOptionsTags
vkb::FlagCommand width_flag = {vkb::FlagType::OneValue, "width", "", "Initial window width"};
vkb::FlagCommand height_flag = {vkb::FlagType::OneValue, "height", "", "Initial window height"};
vkb::FlagCommand fullscreen_flag = {vkb::FlagType::FlagOnly, "fullscreen", "", "Run in fullscreen mode"};
vkb::FlagCommand headless_flag = {vkb::FlagType::FlagOnly, "headless", "", "Run in headless mode"};
vkb::FlagCommand headless_flag = {vkb::FlagType::FlagOnly, "headless_surface", "", "Run in headless surface mode. A Surface and swap-chain is still created using VK_EXT_headless_surface."};
vkb::FlagCommand borderless_flag = {vkb::FlagType::FlagOnly, "borderless", "", "Run in borderless mode"};
vkb::FlagCommand stretch_flag = {vkb::FlagType::FlagOnly, "stretch", "", "Stretch window to fullscreen (direct-to-display only)"};
vkb::FlagCommand vsync_flag = {vkb::FlagType::OneValue, "vsync", "", "Force vsync {ON | OFF}. If not set samples decide how vsync is set"};
Expand Down
8 changes: 6 additions & 2 deletions framework/core/hpp_instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ HPPInstance::HPPInstance(const std::string &applicati
// Specific surface extensions are obtained from Window::get_required_surface_extensions
// They are already added to required_extensions by VulkanSample::prepare

// Even for a headless surface a swapchain is still required
// If using VK_EXT_headless_surface, we still create and use a surface
enabled_extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);

// VK_KHR_get_physical_device_properties2 is a prerequisite of VK_KHR_performance_query
Expand Down Expand Up @@ -436,7 +436,7 @@ vk::Instance HPPInstance::get_handle() const
return handle;
}

vkb::core::HPPPhysicalDevice &HPPInstance::get_suitable_gpu(vk::SurfaceKHR surface)
vkb::core::HPPPhysicalDevice &HPPInstance::get_suitable_gpu(vk::SurfaceKHR surface, bool headless_surface)
{
assert(!gpus.empty() && "No physical devices were found on the system.");

Expand All @@ -450,6 +450,10 @@ vkb::core::HPPPhysicalDevice &HPPInstance::get_suitable_gpu(vk::SurfaceKHR surfa
}
return *gpus[selected_gpu_index.value()];
}
if ( headless_surface )
{
LOGW("Using headless surface with multiple GPUs. Considered explicitly selecting the target GPU.")
}

// Find a discrete GPU
for (auto &gpu : gpus)
Expand Down
4 changes: 3 additions & 1 deletion framework/core/hpp_instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,11 @@ class HPPInstance
/**
* @brief Tries to find the first available discrete GPU that can render to the given surface
* @param surface to test against
* @param headless_surface Is surface created with VK_EXT_headless_surface
* @returns A valid physical device
*/
HPPPhysicalDevice &get_suitable_gpu(vk::SurfaceKHR);
HPPPhysicalDevice &get_suitable_gpu(vk::SurfaceKHR surface, bool headless_surface);

/**
* @brief Checks if the given extension is enabled in the vk::Instance
Expand Down
6 changes: 5 additions & 1 deletion framework/core/instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ PhysicalDevice &Instance::get_first_gpu()
return *gpus[0];
}

PhysicalDevice &Instance::get_suitable_gpu(VkSurfaceKHR surface)
PhysicalDevice &Instance::get_suitable_gpu(VkSurfaceKHR surface, bool headless_surface)
{
assert(!gpus.empty() && "No physical devices were found on the system.");

Expand All @@ -507,6 +507,10 @@ PhysicalDevice &Instance::get_suitable_gpu(VkSurfaceKHR surface)
}
return *gpus[selected_gpu_index.value()];
}
if (headless_surface)
{
LOGW("Using headless surface with multiple GPUs. Considered explicitly selecting the target GPU.")
}

// Find a discrete GPU
for (auto &gpu : gpus)
Expand Down
3 changes: 2 additions & 1 deletion framework/core/instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,10 @@ class Instance
/**
* @brief Tries to find the first available discrete GPU that can render to the given surface
* @param surface to test against
* @param headless_surface Is surface created with VK_EXT_headless_surface
* @returns A valid physical device
*/
PhysicalDevice &get_suitable_gpu(VkSurfaceKHR);
PhysicalDevice &get_suitable_gpu(VkSurfaceKHR surface, bool headless_surface);

/**
* @brief Tries to find the first available discrete GPU
Expand Down
6 changes: 4 additions & 2 deletions framework/platform/headless_window.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (c) 2018-2023, Arm Limited and Contributors
/* Copyright (c) 2018-2024, Arm Limited and Contributors
*
* SPDX-License-Identifier: Apache-2.0
*
Expand All @@ -22,7 +22,9 @@
namespace vkb
{
/**
* @brief Surface-less implementation of a Window, for use in headless rendering
* @brief Surface-less implementation of a Window using VK_EXT_headless_surface.
* A surface and swapchain are still created but the the present operation resolves to a no op.
* Useful for testing and benchmarking in CI environments.
*/
class HeadlessWindow : public Window
{
Expand Down
11 changes: 6 additions & 5 deletions framework/rendering/hpp_render_context.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* Copyright (c) 2023-2024, NVIDIA CORPORATION. All rights reserved.
* Copyright (c) 2024, Arm Limited and Contributors
*
* SPDX-License-Identifier: Apache-2.0
*
Expand Down Expand Up @@ -95,7 +96,7 @@ void HPPRenderContext::update_swapchain(const vk::Extent2D &extent)
{
if (!swapchain)
{
LOGW("Can't update the swapchains extent in headless mode, skipping.");
LOGW("Can't update the swapchains extent. No swapchain, offscreen rendering detected, skipping.");
return;
}

Expand All @@ -110,7 +111,7 @@ void HPPRenderContext::update_swapchain(const uint32_t image_count)
{
if (!swapchain)
{
LOGW("Can't update the swapchains image count in headless mode, skipping.");
LOGW("Can't update the swapchains image count. No swapchain, offscreen rendering detected, skipping.");
return;
}

Expand All @@ -127,7 +128,7 @@ void HPPRenderContext::update_swapchain(const std::set<vk::ImageUsageFlagBits> &
{
if (!swapchain)
{
LOGW("Can't update the swapchains image usage in headless mode, skipping.");
LOGW("Can't update the swapchains image usage. No swapchain, offscreen rendering detected, skipping.");
return;
}

Expand All @@ -142,7 +143,7 @@ void HPPRenderContext::update_swapchain(const vk::Extent2D &extent, const vk::Su
{
if (!swapchain)
{
LOGW("Can't update the swapchains extent and surface transform in headless mode, skipping.");
LOGW("Can't update the swapchains extent and surface transform. No swapchain, offscreen rendering detected, skipping.");
return;
}

Expand Down Expand Up @@ -199,7 +200,7 @@ bool HPPRenderContext::handle_surface_changes(bool force_update)
{
if (!swapchain)
{
LOGW("Can't handle surface changes in headless mode, skipping.");
LOGW("Can't handle surface changes. No swapchain, offscreen rendering detected, skipping.");
return false;
}

Expand Down
5 changes: 3 additions & 2 deletions framework/rendering/hpp_render_context.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* Copyright (c) 2022-2023, NVIDIA CORPORATION. All rights reserved.
/* Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved.
* Copyright (c) 2024, Arm Limited and Contributors
*
* SPDX-License-Identifier: Apache-2.0
*
Expand Down Expand Up @@ -40,7 +41,7 @@ class HPPRenderContext
/**
* @brief Constructor
* @param device A valid device
* @param surface A surface, nullptr if in headless mode
* @param surface A surface, nullptr if in offscreen mode
* @param window The window where the surface was created
* @param present_mode Requests to set the present mode of the swapchain
* @param present_mode_priority_list The order in which the swapchain prioritizes selecting its present mode
Expand Down
12 changes: 6 additions & 6 deletions framework/rendering/render_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ void RenderContext::update_swapchain(const VkExtent2D &extent)
{
if (!swapchain)
{
LOGW("Can't update the swapchains extent in headless mode, skipping.");
LOGW("Can't update the swapchains extent. No swapchain, offscreen rendering detected, skipping.");
return;
}

Expand All @@ -121,7 +121,7 @@ void RenderContext::update_swapchain(const uint32_t image_count)
{
if (!swapchain)
{
LOGW("Can't update the swapchains image count in headless mode, skipping.");
LOGW("Can't update the swapchains image count. No swapchain, offscreen rendering detected, skipping.");
return;
}

Expand All @@ -138,7 +138,7 @@ void RenderContext::update_swapchain(const std::set<VkImageUsageFlagBits> &image
{
if (!swapchain)
{
LOGW("Can't update the swapchains image usage in headless mode, skipping.");
LOGW("Can't update the swapchains image usage. No swapchain, offscreen rendering detected, skipping.");
return;
}

Expand All @@ -153,7 +153,7 @@ void RenderContext::update_swapchain(const VkExtent2D &extent, const VkSurfaceTr
{
if (!swapchain)
{
LOGW("Can't update the swapchains extent and surface transform in headless mode, skipping.");
LOGW("Can't update the swapchains extent and surface transform. No swapchain, offscreen rendering detected, skipping.");
return;
}

Expand All @@ -179,7 +179,7 @@ void RenderContext::update_swapchain(const VkImageCompressionFlagsEXT compressio
{
if (!swapchain)
{
LOGW("Can't update the swapchains compression in headless mode, skipping.");
LOGW("Can't update the swapchains compression. No swapchain, offscreen rendering detected, skipping.");
return;
}

Expand Down Expand Up @@ -228,7 +228,7 @@ bool RenderContext::handle_surface_changes(bool force_update)
{
if (!swapchain)
{
LOGW("Can't handle surface changes in headless mode, skipping.");
LOGW("Can't handle surface changes. No swapchain, offscreen rendering detected, skipping.");
return false;
}

Expand Down
4 changes: 2 additions & 2 deletions framework/rendering/render_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class Window;
* For normal rendering (using a swapchain), the RenderContext can be created by passing in a
* swapchain. A RenderFrame will then be created for each Swapchain image.
*
* For headless rendering (no swapchain), the RenderContext can be given a valid Device, and
* For offscreen rendering (no swapchain), the RenderContext can be given a valid Device, and
* a width and height. A single RenderFrame will then be created.
*/
class RenderContext
Expand All @@ -63,7 +63,7 @@ class RenderContext
/**
* @brief Constructor
* @param device A valid device
* @param surface A surface, VK_NULL_HANDLE if in headless mode
* @param surface A surface, VK_NULL_HANDLE if in offscreen mode
* @param window The window where the surface was created
* @param present_mode Requests to set the present mode of the swapchain
* @param present_mode_priority_list The order in which the swapchain prioritizes selecting its present mode
Expand Down
4 changes: 2 additions & 2 deletions framework/vulkan_sample.h
Original file line number Diff line number Diff line change
Expand Up @@ -1066,7 +1066,7 @@ inline bool VulkanSample<bindingType>::prepare(const ApplicationOptions &options
throw std::runtime_error("Failed to create window surface.");
}

auto &gpu = instance->get_suitable_gpu(surface);
auto &gpu = instance->get_suitable_gpu(surface, headless);
gpu.set_high_priority_graphics_queue_enable(high_priority_graphics_queue);

// Request to enable ASTC
Expand All @@ -1086,7 +1086,7 @@ inline bool VulkanSample<bindingType>::prepare(const ApplicationOptions &options
}

// Creating vulkan device, specifying the swapchain extension always
if (!headless || get_instance().is_enabled(VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME))
// If using VK_EXT_headless_surface, we still create and use a swap-chain
{
add_device_extension(VK_KHR_SWAPCHAIN_EXTENSION_NAME);

Expand Down

0 comments on commit 68fe8fa

Please sign in to comment.