monado/tests/tests_comp_client_vulkan.cpp
Korcan Hussein 5fb1a02575 xrt: Fixes #411, KHR_vulkan_swapchain_format_list not enabled client-side
* Fixes VK_KHR_image_format_list not being added to
  extension lists or not enabling flags on
  client-side vk_bundle / vk client compositor.

* Fixes missing extension VK_KHR_image_format_list to
  the vulkan device extension list for XR_KHR_vulkan_enable

* Fixes format lists for KHR_vulkan_swapchain_format_list
  not be used/applied on client vk images.

* Fixes vulkan validation errors on client that attempt
  to use & chain format lists for image view creation
  outside of OpenXR / runtime

Part-of: <https://gitlab.freedesktop.org/monado/monado/-/merge_requests/2352>
2024-11-21 10:57:01 +00:00

193 lines
6.7 KiB
C++

// Copyright 2022-2024, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief Basic Vulkan compositor tests.
* @author Rylie Pavlik <rylie.pavlik@collabora.com>
* @author Korcan Hussein <korcan.hussein@collabora.com>
*/
#include "mock/mock_compositor.h"
#include "client/comp_vk_client.h"
#include "xrt/xrt_results.h"
#include <vulkan/vulkan_core.h>
#undef Always
#undef None
#undef Success
#include "catch_amalgamated.hpp"
#include "util/comp_vulkan.h"
#include "util/u_logging.h"
#include "util/u_string_list.h"
#include "vk/vk_helpers.h"
#include "xrt/xrt_compositor.h"
#include <xrt/xrt_deleters.hpp>
#include <memory>
#include <iostream>
using unique_native_compositor =
std::unique_ptr<xrt_compositor_native,
xrt::deleters::ptr_ptr_deleter<xrt_compositor_native, &xrt_comp_native_destroy>>;
// clang-format off
#define COMP_INSTANCE_EXTENSIONS_COMMON \
VK_EXT_DEBUG_REPORT_EXTENSION_NAME, \
VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME, \
VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, \
VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME, \
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, \
VK_KHR_SURFACE_EXTENSION_NAME
// clang-format on
static const char *instance_extensions_common[] = {
COMP_INSTANCE_EXTENSIONS_COMMON,
};
static const char *required_device_extensions[] = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME, //
VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, //
VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME, //
VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME, //
VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME, //
VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, //
// Platform version of "external_memory"
#if defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_FD)
VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
#elif defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_AHARDWAREBUFFER)
VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME,
VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME,
VK_KHR_MAINTENANCE_1_EXTENSION_NAME,
VK_KHR_BIND_MEMORY_2_EXTENSION_NAME,
VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME,
#elif defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_WIN32_HANDLE)
VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME,
#else
#error "Need port!"
#endif
// Platform version of "external_fence" and "external_semaphore"
#if defined(XRT_GRAPHICS_SYNC_HANDLE_IS_FD) // Optional
#elif defined(XRT_GRAPHICS_SYNC_HANDLE_IS_WIN32_HANDLE)
VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME,
VK_KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME,
#else
#error "Need port!"
#endif
};
using unique_string_list =
std::unique_ptr<u_string_list, xrt::deleters::ptr_ptr_deleter<u_string_list, &u_string_list_destroy>>;
static void
xrt_comp_vk_destroy(struct xrt_compositor_vk **ptr_xcvk)
{
if (!ptr_xcvk) {
return;
}
xrt_compositor *xc = &(*ptr_xcvk)->base;
xrt_comp_destroy(&xc);
}
using unique_compositor_vk =
std::unique_ptr<struct xrt_compositor_vk,
xrt::deleters::ptr_ptr_deleter<struct xrt_compositor_vk, &xrt_comp_vk_destroy>>;
TEST_CASE("client_compositor", "[.][needgpu]")
{
xrt_compositor_native *xcn = mock_create_native_compositor();
struct mock_compositor *mc = mock_compositor(&(xcn->base));
// every backend needs at least the common extensions
unique_string_list required_instance_ext_list{
u_string_list_create_from_array(instance_extensions_common, ARRAY_SIZE(instance_extensions_common))};
unique_string_list optional_instance_ext_list{u_string_list_create()};
unique_string_list required_device_extension_list{
u_string_list_create_from_array(required_device_extensions, ARRAY_SIZE(required_device_extensions))};
unique_string_list optional_device_extension_list{u_string_list_create()};
comp_vulkan_arguments args{VK_MAKE_VERSION(1, 0, 0),
vkGetInstanceProcAddr,
required_instance_ext_list.get(),
optional_instance_ext_list.get(),
required_device_extension_list.get(),
optional_device_extension_list.get(),
U_LOGGING_TRACE,
false /* only_compute_queue */,
true /*timeline_semaphore*/,
-1,
-1};
vk_bundle vk_bundle_storage{};
vk_bundle *vk = &vk_bundle_storage;
comp_vulkan_results results{};
REQUIRE(comp_vulkan_init_bundle(vk, &args, &results));
struct xrt_compositor_vk *xcvk = xrt_gfx_vk_provider_create( //
xcn, //
vk->instance, //
vkGetInstanceProcAddr, //
vk->physical_device, //
vk->device,
#if defined(XRT_GRAPHICS_SYNC_HANDLE_IS_FD) //
vk->external.fence_sync_fd, //
vk->external.binary_semaphore_sync_fd, //
vk->external.timeline_semaphore_sync_fd, //
#elif defined(XRT_GRAPHICS_SYNC_HANDLE_IS_WIN32_HANDLE)
vk->external.fence_win32_handle, //
vk->external.binary_semaphore_win32_handle, //
vk->external.timeline_semaphore_win32_handle, //
#else
#error "Need port for fence sync handles checkers"
#endif
vk->has_KHR_image_format_list, // image_format_list_enabled
false, // debug_utils_enabled
false, // renderdoc_enabled
vk->queue_family_index, //
vk->queue_index);
struct xrt_compositor *xc = &xcvk->base;
SECTION("CreateSwapchain calls native create")
{
bool nativeCreateCalled = false;
mc->userdata = &nativeCreateCalled;
mc->compositor_hooks.create_swapchain =
[](struct mock_compositor *mc, struct mock_compositor_swapchain *mcsc,
const struct xrt_swapchain_create_info *info, struct xrt_swapchain **out_xsc) {
*static_cast<bool *>(mc->userdata) = true;
return XRT_SUCCESS;
};
xrt_swapchain_create_info xsci{};
xsci.format = VK_FORMAT_B8G8R8A8_SRGB;
xsci.bits = (xrt_swapchain_usage_bits)(XRT_SWAPCHAIN_USAGE_COLOR | XRT_SWAPCHAIN_USAGE_SAMPLED);
xsci.sample_count = 1;
xsci.width = 800;
xsci.height = 600;
xsci.face_count = 1;
xsci.array_size = 1;
xsci.mip_count = 1;
struct xrt_swapchain *xsc = nullptr;
// This will fail because the mock compositor doesn't actually create images for Vulkan to import, but
// it will get far enough to trigger our hook and update the flag.
xrt_comp_create_swapchain(xc, &xsci, &xsc);
CHECK(nativeCreateCalled);
xrt_swapchain_reference(&xsc, nullptr);
}
xrt_comp_destroy(&xc);
vk_deinit_mutex(vk);
xrt_comp_native_destroy(&xcn);
}