diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 662512d07..8263c2f76 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -107,3 +107,7 @@ if(_have_opengl_test) ) target_include_directories(tests_comp_client_opengl PRIVATE ${SDL2_INCLUDE_DIRS}) endif() + +if(XRT_HAVE_VULKAN AND XRT_HAVE_D3D11) + target_link_libraries(tests_aux_d3d_d3d11 PRIVATE comp_util aux_vk) +endif() diff --git a/tests/aux_d3d_dxgi_formats.hpp b/tests/aux_d3d_dxgi_formats.hpp index 591174d89..19ccc49ba 100644 --- a/tests/aux_d3d_dxgi_formats.hpp +++ b/tests/aux_d3d_dxgi_formats.hpp @@ -12,11 +12,16 @@ #include #include - -static constexpr std::initializer_list colorFormats = { - DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_R16G16B16A16_FLOAT, - DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R32_FLOAT +#define MAKE_PAIR(ENUM) \ + { \ +#ENUM, ENUM \ + } +static constexpr std::initializer_list> colorNamesAndFormats = { + MAKE_PAIR(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB), MAKE_PAIR(DXGI_FORMAT_B8G8R8A8_UNORM), + MAKE_PAIR(DXGI_FORMAT_R16G16B16A16_FLOAT), MAKE_PAIR(DXGI_FORMAT_R16G16B16A16_UNORM), + MAKE_PAIR(DXGI_FORMAT_R16G16B16A16_FLOAT), MAKE_PAIR(DXGI_FORMAT_R16G16B16A16_UNORM), + MAKE_PAIR(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB), MAKE_PAIR(DXGI_FORMAT_R8G8B8A8_UNORM), + MAKE_PAIR(DXGI_FORMAT_R32_FLOAT), }; static constexpr std::initializer_list depthStencilFormats = { @@ -25,12 +30,20 @@ static constexpr std::initializer_list depthStencilFormats = { DXGI_FORMAT_D32_FLOAT_S8X24_UINT, DXGI_FORMAT_D32_FLOAT, }; -static constexpr std::initializer_list formats = { - DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_R16G16B16A16_FLOAT, - DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R32_FLOAT, - DXGI_FORMAT_D16_UNORM, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, - DXGI_FORMAT_D32_FLOAT, +static constexpr std::initializer_list> namesAndFormats = { + MAKE_PAIR(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB), + MAKE_PAIR(DXGI_FORMAT_B8G8R8A8_UNORM), + MAKE_PAIR(DXGI_FORMAT_R16G16B16A16_FLOAT), + MAKE_PAIR(DXGI_FORMAT_R16G16B16A16_UNORM), + MAKE_PAIR(DXGI_FORMAT_R16G16B16A16_FLOAT), + MAKE_PAIR(DXGI_FORMAT_R16G16B16A16_UNORM), + MAKE_PAIR(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB), + MAKE_PAIR(DXGI_FORMAT_R8G8B8A8_UNORM), + MAKE_PAIR(DXGI_FORMAT_R32_FLOAT), + MAKE_PAIR(DXGI_FORMAT_D16_UNORM), + MAKE_PAIR(DXGI_FORMAT_D24_UNORM_S8_UINT), + MAKE_PAIR(DXGI_FORMAT_D32_FLOAT_S8X24_UINT), + MAKE_PAIR(DXGI_FORMAT_D32_FLOAT), }; static inline bool diff --git a/tests/tests_aux_d3d_d3d11.cpp b/tests/tests_aux_d3d_d3d11.cpp index 7fe387654..d0f97ece0 100644 --- a/tests/tests_aux_d3d_d3d11.cpp +++ b/tests/tests_aux_d3d_d3d11.cpp @@ -11,17 +11,26 @@ #include "catch/catch.hpp" +#include #include #include #include #include +#ifdef XRT_HAVE_VULKAN +#include "vktest_init_bundle.hpp" +#include +#include +#include +#endif + #include using namespace xrt::auxiliary::d3d; using namespace xrt::auxiliary::d3d::d3d11; using namespace xrt::auxiliary::util; + TEST_CASE("dxgi_adapter", "[.][needgpu]") { ComGuard comGuard; @@ -56,8 +65,77 @@ TEST_CASE("d3d11_device", "[.][needgpu]") CHECK(context); } +#ifdef XRT_HAVE_VULKAN + +static inline bool +tryImport(struct vk_bundle *vk, + std::vector const &handles, + const struct xrt_swapchain_create_info &xsci) +{ + + INFO("Testing import into Vulkan"); + + static constexpr bool use_dedicated_allocation = false; + xrt_swapchain_create_info vk_info = xsci; + vk_info.format = d3d_dxgi_format_to_vk((DXGI_FORMAT)xsci.format); + const auto free_vk_ic = [&](struct vk_image_collection *vkic) { + vk_ic_destroy(vk, vkic); + delete vkic; + }; + + std::shared_ptr vkic{new vk_image_collection, free_vk_ic}; + + uint32_t image_count = static_cast(handles.size()); + // Populate for import + std::vector xins; + xins.reserve(image_count); + + // Keep this around until after successful import, then detach all. + std::vector handlesForImport; + handlesForImport.reserve(image_count); + + for (const wil::unique_handle &handle : handles) { + wil::unique_handle duped{u_graphics_buffer_ref(handle.get())}; + xrt_image_native xin; + xin.handle = duped.get(); + xin.size = 0; + xin.use_dedicated_allocation = use_dedicated_allocation; + + handlesForImport.emplace_back(std::move(duped)); + xins.emplace_back(xin); + } + + // Import into a vulkan image collection + bool result = VK_SUCCESS == vk_ic_from_natives(vk, &vk_info, xins.data(), (uint32_t)xins.size(), vkic.get()); + + if (result) { + // The imported swapchain took ownership of them now, release them from ownership here. + for (auto &h : handlesForImport) { + h.release(); + } + } + return result; +} +#else + +static inline bool +tryImport(struct vk_bundle * /* vk */, + std::vector const & /* handles */, + const struct xrt_swapchain_create_info & /* xsci */) +{ + return true; +} + +#endif + TEST_CASE("d3d11_allocate", "[.][needgpu]") { + unique_vk_bundle vk = makeVkBundle(); + +#ifdef XRT_HAVE_VULKAN + REQUIRE(vktest_init_bundle(vk.get())); +#endif + ComGuard comGuard; wil::com_ptr device; wil::com_ptr context; @@ -70,64 +148,74 @@ TEST_CASE("d3d11_allocate", "[.][needgpu]") size_t imageCount = 3; xrt_swapchain_create_info xsci{}; - xsci.sample_count = 1; - xsci.width = 800; - xsci.height = 600; + CAPTURE(xsci.sample_count = 1); + CAPTURE(xsci.width = 800); + CAPTURE(xsci.height = 600); + + CAPTURE(xsci.mip_count = 1); xsci.face_count = 1; xsci.array_size = 1; - xsci.mip_count = 1; SECTION("create images") { - auto format = GENERATE(values(colorFormats)); - if (isDepthStencilFormat(format)) { + auto nameAndFormat = GENERATE(values(namesAndFormats)); + DYNAMIC_SECTION("Texture format " << nameAndFormat.first) + { + auto format = nameAndFormat.second; + CAPTURE(isDepthStencilFormat(format)); + xsci.format = format; + if (isDepthStencilFormat(format)) { - xsci.bits = XRT_SWAPCHAIN_USAGE_DEPTH_STENCIL; - } else { - xsci.bits = XRT_SWAPCHAIN_USAGE_COLOR; - } - xsci.bits = (xrt_swapchain_usage_bits)(xsci.bits | XRT_SWAPCHAIN_USAGE_SAMPLED); - - INFO("Format: " << format) xsci.format = format; - images.clear(); - handles.clear(); - SECTION("invalid array size 0") - { - xsci.array_size = 0; - CHECK(XRT_SUCCESS != - allocateSharedImages(*device5, xsci, imageCount, kKeyedMutex, images, handles)); - CHECK(images.empty()); - CHECK(handles.empty()); - } - SECTION("not array") - { - CHECK(XRT_SUCCESS == - allocateSharedImages(*device5, xsci, imageCount, kKeyedMutex, images, handles)); - CHECK(images.size() == imageCount); - CHECK(handles.size() == imageCount); - } - SECTION("array of 2") - { - xsci.array_size = 2; - CHECK(XRT_SUCCESS == - allocateSharedImages(*device5, xsci, imageCount, kKeyedMutex, images, handles)); - CHECK(images.size() == imageCount); - CHECK(handles.size() == imageCount); - } - SECTION("cubemaps not implemented") - { - xsci.face_count = 6; - CHECK(XRT_ERROR_ALLOCATION == - allocateSharedImages(*device5, xsci, imageCount, kKeyedMutex, images, handles)); - CHECK(images.empty()); - CHECK(handles.empty()); - } - SECTION("protected content not implemented") - { - xsci.create = XRT_SWAPCHAIN_CREATE_PROTECTED_CONTENT; - CHECK(XRT_ERROR_SWAPCHAIN_FLAG_VALID_BUT_UNSUPPORTED == - allocateSharedImages(*device5, xsci, imageCount, kKeyedMutex, images, handles)); - CHECK(images.empty()); - CHECK(handles.empty()); + xsci.bits = XRT_SWAPCHAIN_USAGE_DEPTH_STENCIL; + } else { + xsci.bits = XRT_SWAPCHAIN_USAGE_COLOR; + } + xsci.bits = (xrt_swapchain_usage_bits)(xsci.bits | XRT_SWAPCHAIN_USAGE_SAMPLED); + images.clear(); + handles.clear(); + SECTION("invalid array size 0") + { + CAPTURE(xsci.array_size = 0); + REQUIRE(XRT_SUCCESS != + allocateSharedImages(*device5, xsci, imageCount, kKeyedMutex, images, handles)); + CHECK(images.empty()); + CHECK(handles.empty()); + } + SECTION("not array") + { + CAPTURE(xsci.array_size); + REQUIRE(XRT_SUCCESS == + allocateSharedImages(*device5, xsci, imageCount, kKeyedMutex, images, handles)); + CHECK(images.size() == imageCount); + CHECK(handles.size() == imageCount); + CHECK(tryImport(vk.get(), handles, xsci)); + } + SECTION("array of 2") + { + CAPTURE(xsci.array_size = 2); + REQUIRE(XRT_SUCCESS == + allocateSharedImages(*device5, xsci, imageCount, kKeyedMutex, images, handles)); + CHECK(images.size() == imageCount); + CHECK(handles.size() == imageCount); + CHECK(tryImport(vk.get(), handles, xsci)); + } + SECTION("cubemaps not implemented") + { + CAPTURE(xsci.array_size); + CAPTURE(xsci.face_count = 6); + REQUIRE(XRT_ERROR_ALLOCATION == + allocateSharedImages(*device5, xsci, imageCount, kKeyedMutex, images, handles)); + CHECK(images.empty()); + CHECK(handles.empty()); + } + SECTION("protected content not implemented") + { + CAPTURE(xsci.array_size); + CAPTURE(xsci.create = XRT_SWAPCHAIN_CREATE_PROTECTED_CONTENT); + REQUIRE(XRT_ERROR_SWAPCHAIN_FLAG_VALID_BUT_UNSUPPORTED == + allocateSharedImages(*device5, xsci, imageCount, kKeyedMutex, images, handles)); + CHECK(images.empty()); + CHECK(handles.empty()); + } } } } diff --git a/tests/vktest_init_bundle.hpp b/tests/vktest_init_bundle.hpp new file mode 100644 index 000000000..03676f297 --- /dev/null +++ b/tests/vktest_init_bundle.hpp @@ -0,0 +1,162 @@ +// Copyright 2019-2022, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Vulkan code for tests. + * + * @author Jakob Bornecrantz + * @author Lubosz Sarnecki + * @author Ryan Pavlik + */ +#pragma once + +#include +#include + +#ifdef XRT_HAVE_VULKAN +#include +#include +#include +#include +#include + + +static const char *instance_extensions_common[] = { + 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, // +}; + +static const char *required_device_extensions[] = { + 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, + +#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 +}; + +static const char *optional_device_extensions[] = { +#ifdef VK_KHR_timeline_semaphore + VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME, +#endif +}; +using unique_string_list = + std::unique_ptr>; + +struct VkBundleDestroyer +{ + void + operator()(struct vk_bundle *vk) const + { + if (!vk) { + return; + } + if (vk->device != VK_NULL_HANDLE) { + vk->vkDestroyDevice(vk->device, NULL); + vk->device = VK_NULL_HANDLE; + } + if (vk->instance != VK_NULL_HANDLE) { + vk->vkDestroyInstance(vk->instance, NULL); + vk->instance = VK_NULL_HANDLE; + } + delete vk; + } +}; + +static void +vk_bundle_destroy(struct vk_bundle *vk) +{ + if (!vk) { + return; + } + if (vk->device != VK_NULL_HANDLE) { + vk->vkDestroyDevice(vk->device, NULL); + vk->device = VK_NULL_HANDLE; + } + if (vk->instance != VK_NULL_HANDLE) { + vk->vkDestroyInstance(vk->instance, NULL); + vk->instance = VK_NULL_HANDLE; + } + vk_deinit_mutex(vk); + delete vk; +} +// using unique_vk_bundle = std::unique_ptr; +using unique_vk_bundle = + std::unique_ptr>; + +static inline bool +vktest_init_bundle(struct vk_bundle *vk) +{ + // 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_from_array(optional_device_extensions, ARRAY_SIZE(optional_device_extensions))}; + + U_ZERO(vk); + 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}; + comp_vulkan_results results{}; + bool success = comp_vulkan_init_bundle(vk, &args, &results); + + // success = success && VK_SUCCESS == vk_init_mutex(vk); + return success; +} + +#else + +struct vk_bundle +{ +}; + +using unique_vk_bundle = std::unique_ptr; + +#endif + +static unique_vk_bundle +makeVkBundle() +{ + unique_vk_bundle ret{new vk_bundle}; + return ret; +}