From cdb8d54ca11b616581e800a8b8aab1863e5ef915 Mon Sep 17 00:00:00 2001 From: Ryan Pavlik <ryan.pavlik@collabora.com> Date: Mon, 16 May 2022 10:44:47 -0500 Subject: [PATCH] st/oxr: Work on D3D11 --- doc/changes/compositor/mr.943.md | 2 +- src/xrt/state_trackers/oxr/CMakeLists.txt | 6 ++ src/xrt/state_trackers/oxr/oxr_api_funcs.h | 8 ++ .../state_trackers/oxr/oxr_api_negotiate.c | 4 + src/xrt/state_trackers/oxr/oxr_api_system.c | 27 ++++++ src/xrt/state_trackers/oxr/oxr_api_verify.h | 4 + src/xrt/state_trackers/oxr/oxr_d3d11.cpp | 92 +++++++++++++++++++ src/xrt/state_trackers/oxr/oxr_objects.h | 41 +++++++++ src/xrt/state_trackers/oxr/oxr_session.c | 22 +++++ .../oxr/oxr_session_gfx_d3d11.c | 44 +++++++++ .../state_trackers/oxr/oxr_swapchain_d3d11.c | 78 ++++++++++++++++ src/xrt/state_trackers/oxr/oxr_system.c | 4 + src/xrt/state_trackers/oxr/oxr_verify.c | 23 +++++ 13 files changed, 354 insertions(+), 1 deletion(-) create mode 100644 src/xrt/state_trackers/oxr/oxr_d3d11.cpp create mode 100644 src/xrt/state_trackers/oxr/oxr_session_gfx_d3d11.c create mode 100644 src/xrt/state_trackers/oxr/oxr_swapchain_d3d11.c diff --git a/doc/changes/compositor/mr.943.md b/doc/changes/compositor/mr.943.md index 1dde801d7..8668fa51f 100644 --- a/doc/changes/compositor/mr.943.md +++ b/doc/changes/compositor/mr.943.md @@ -2,4 +2,4 @@ - mr.1263 - mr.1295 --- -Work toward support for D3D11 client applications on Windows. +Initial support for D3D11 client applications on Windows. diff --git a/src/xrt/state_trackers/oxr/CMakeLists.txt b/src/xrt/state_trackers/oxr/CMakeLists.txt index 7987e1d60..5d0bc54b8 100644 --- a/src/xrt/state_trackers/oxr/CMakeLists.txt +++ b/src/xrt/state_trackers/oxr/CMakeLists.txt @@ -69,6 +69,12 @@ if(XRT_HAVE_EGL) target_sources(st_oxr PRIVATE oxr_session_gfx_egl.c) endif() +if(XRT_HAVE_D3D11) + target_compile_definitions(st_oxr PRIVATE XR_USE_GRAPHICS_API_D3D11) + target_sources(st_oxr PRIVATE oxr_session_gfx_d3d11.c oxr_swapchain_d3d11.c oxr_d3d11.cpp) + target_link_libraries(st_oxr PRIVATE aux_d3d) +endif() + if(ANDROID) target_compile_definitions(st_oxr PRIVATE XR_USE_PLATFORM_ANDROID) target_sources(st_oxr PRIVATE oxr_session_gfx_gles_android.c) diff --git a/src/xrt/state_trackers/oxr/oxr_api_funcs.h b/src/xrt/state_trackers/oxr/oxr_api_funcs.h index b5f2e2bd5..881c3ecec 100644 --- a/src/xrt/state_trackers/oxr/oxr_api_funcs.h +++ b/src/xrt/state_trackers/oxr/oxr_api_funcs.h @@ -224,6 +224,14 @@ oxr_xrCreateVulkanDeviceKHR(XrInstance instance, VkResult *vulkanResult); #endif +#ifdef XR_USE_GRAPHICS_API_D3D11 + +//! OpenXR API function @ep{xrGetD3D11GraphicsRequirementsKHR} +XRAPI_ATTR XrResult XRAPI_CALL +oxr_xrGetD3D11GraphicsRequirementsKHR(XrInstance instance, + XrSystemId systemId, + XrGraphicsRequirementsD3D11KHR *graphicsRequirements); +#endif // XR_USE_GRAPHICS_API_D3D11 /* * diff --git a/src/xrt/state_trackers/oxr/oxr_api_negotiate.c b/src/xrt/state_trackers/oxr/oxr_api_negotiate.c index b18663e0c..9c4ea45d5 100644 --- a/src/xrt/state_trackers/oxr/oxr_api_negotiate.c +++ b/src/xrt/state_trackers/oxr/oxr_api_negotiate.c @@ -265,6 +265,10 @@ handle_non_null(struct oxr_instance *inst, struct oxr_logger *log, const char *n ENTRY_IF_EXT(xrCreateVulkanInstanceKHR, KHR_vulkan_enable2); #endif // OXR_HAVE_KHR_vulkan_enable2 +#ifdef OXR_HAVE_KHR_D3D11_enable + ENTRY_IF_EXT(xrGetD3D11GraphicsRequirementsKHR, KHR_D3D11_enable); +#endif // OXR_HAVE_KHR_D3D11_enable + /* * Not logging here because there's no need to loudly advertise * which extensions the loader knows about (it calls this on diff --git a/src/xrt/state_trackers/oxr/oxr_api_system.c b/src/xrt/state_trackers/oxr/oxr_api_system.c index e7f712a72..70b43845d 100644 --- a/src/xrt/state_trackers/oxr/oxr_api_system.c +++ b/src/xrt/state_trackers/oxr/oxr_api_system.c @@ -417,3 +417,30 @@ oxr_xrCreateVulkanDeviceKHR(XrInstance instance, return oxr_vk_create_vulkan_device(&log, sys, createInfo, vulkanDevice, vulkanResult); } #endif + + +/* + * + * D3D11 + * + */ + +#ifdef XR_USE_GRAPHICS_API_D3D11 + +XrResult +oxr_xrGetD3D11GraphicsRequirementsKHR(XrInstance instance, + XrSystemId systemId, + XrGraphicsRequirementsD3D11KHR *graphicsRequirements) +{ + + struct oxr_instance *inst; + struct oxr_logger log; + OXR_VERIFY_INSTANCE_AND_INIT_LOG(&log, instance, inst, "xrGetD3D11GraphicsRequirementsKHR"); + OXR_VERIFY_ARG_TYPE_AND_NOT_NULL(&log, graphicsRequirements, XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR); + OXR_VERIFY_SYSTEM_AND_GET(&log, inst, systemId, sys); + + sys->gotten_requirements = true; + + return oxr_d3d11_get_requirements(&log, sys, graphicsRequirements); +} +#endif diff --git a/src/xrt/state_trackers/oxr/oxr_api_verify.h b/src/xrt/state_trackers/oxr/oxr_api_verify.h index ab7a1cc24..bd6cc5da3 100644 --- a/src/xrt/state_trackers/oxr/oxr_api_verify.h +++ b/src/xrt/state_trackers/oxr/oxr_api_verify.h @@ -276,6 +276,10 @@ oxr_verify_XrGraphicsBindingOpenGLESAndroidKHR(struct oxr_logger *, const XrGrap #endif // defined(XR_USE_PLATFORM_ANDROID) && // defined(XR_USE_GRAPHICS_API_OPENGL_ES) +#if defined(XR_USE_GRAPHICS_API_D3D11) +XrResult +oxr_verify_XrGraphicsBindingD3D11KHR(struct oxr_logger *, const XrGraphicsBindingD3D11KHR *); +#endif // defined(XR_USE_GRAPHICS_API_D3D11) /*! * @} */ diff --git a/src/xrt/state_trackers/oxr/oxr_d3d11.cpp b/src/xrt/state_trackers/oxr/oxr_d3d11.cpp new file mode 100644 index 000000000..32cb37e35 --- /dev/null +++ b/src/xrt/state_trackers/oxr/oxr_d3d11.cpp @@ -0,0 +1,92 @@ +// Copyright 2021, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Holds D3D11 related functions that didn't fit somewhere else. + * @author Ryan Pavlik <ryan.pavlik@collabora.com> + * @ingroup oxr_main + */ + +#include "xrt/xrt_gfx_d3d11.h" + +#include "util/u_misc.h" +#include "util/u_debug.h" +#include "d3d/d3d_helpers.hpp" + +#include "oxr_objects.h" +#include "oxr_logger.h" + +#include <dxgi1_6.h> +#include <d3d11_4.h> +#include <wil/com.h> +#include <wil/result.h> + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#define DEFAULT_CATCH(MSG) \ + catch (wil::ResultException const &e) \ + { \ + return oxr_error(log, XR_ERROR_RUNTIME_FAILURE, MSG ": %s", e.what()); \ + } \ + catch (std::exception const &e) \ + { \ + return oxr_error(log, XR_ERROR_RUNTIME_FAILURE, MSG ": %s", e.what()); \ + } \ + catch (...) \ + { \ + return oxr_error(log, XR_ERROR_RUNTIME_FAILURE, MSG); \ + } + +using namespace xrt::auxiliary::d3d; + +XrResult +oxr_d3d11_get_requirements(struct oxr_logger *log, + struct oxr_system *sys, + XrGraphicsRequirementsD3D11KHR *graphicsRequirements) +{ + try { + + if (sys->xsysc->info.client_d3d_deviceLUID_valid) { + sys->suggested_d3d_luid = + reinterpret_cast<const LUID &>(sys->xsysc->info.client_d3d_deviceLUID); + } else { + auto adapter = getAdapterByIndex(0, U_LOGGING_INFO); + if (adapter == nullptr) { + return oxr_error(log, XR_ERROR_RUNTIME_FAILURE, " failure enumerating adapter LUIDs."); + } + DXGI_ADAPTER_DESC desc{}; + THROW_IF_FAILED(adapter->GetDesc(&desc)); + sys->suggested_d3d_luid = desc.AdapterLuid; + } + sys->suggested_d3d_luid_valid = true; + graphicsRequirements->adapterLuid = sys->suggested_d3d_luid; + //! @todo implement better? + graphicsRequirements->minFeatureLevel = D3D_FEATURE_LEVEL_11_0; + + return XR_SUCCESS; + } + DEFAULT_CATCH(" failure determining adapter LUID") +} + +XrResult +oxr_d3d11_check_device(struct oxr_logger *log, struct oxr_system *sys, ID3D11Device *device) +{ + try { + wil::com_ptr<IDXGIDevice> dxgiDevice; + THROW_IF_FAILED(device->QueryInterface(dxgiDevice.put())); + wil::com_ptr<IDXGIAdapter> adapter; + THROW_IF_FAILED(dxgiDevice->GetAdapter(adapter.put())); + DXGI_ADAPTER_DESC desc{}; + adapter->GetDesc(&desc); + if (desc.AdapterLuid.HighPart != sys->suggested_d3d_luid.HighPart || + desc.AdapterLuid.LowPart != sys->suggested_d3d_luid.LowPart) { + + return oxr_error(log, XR_ERROR_GRAPHICS_DEVICE_INVALID, + " supplied device does not match required LUID."); + } + return XR_SUCCESS; + } + DEFAULT_CATCH(" failure checking adapter LUID") +} diff --git a/src/xrt/state_trackers/oxr/oxr_objects.h b/src/xrt/state_trackers/oxr/oxr_objects.h index 14fd65347..e5fc0d391 100644 --- a/src/xrt/state_trackers/oxr/oxr_objects.h +++ b/src/xrt/state_trackers/oxr/oxr_objects.h @@ -1110,6 +1110,42 @@ oxr_session_populate_egl(struct oxr_logger *log, #endif +/* + * + * D3D11, located in various files. + * + */ + +#ifdef XR_USE_GRAPHICS_API_D3D11 + +XrResult +oxr_d3d11_get_requirements(struct oxr_logger *log, + struct oxr_system *sys, + XrGraphicsRequirementsD3D11KHR *graphicsRequirements); + +/** + * @brief Check to ensure the device provided at session create matches the LUID we returned earlier. + * + * @return XR_SUCCESS if the device matches the LUID + */ +XrResult +oxr_d3d11_check_device(struct oxr_logger *log, struct oxr_system *sys, ID3D11Device *device); + + +XrResult +oxr_session_populate_d3d11(struct oxr_logger *log, + struct oxr_system *sys, + XrGraphicsBindingD3D11KHR const *next, + struct oxr_session *sess); + +XrResult +oxr_swapchain_d3d11_create(struct oxr_logger *, + struct oxr_session *sess, + const XrSwapchainCreateInfo *, + struct oxr_swapchain **out_swapchain); + +#endif + /* * * Structs @@ -1205,6 +1241,10 @@ struct oxr_system } vk; #endif +#ifdef XR_USE_GRAPHICS_API_D3D11 + LUID suggested_d3d_luid; + bool suggested_d3d_luid_valid; +#endif }; #define GET_XDEV_BY_ROLE(SYS, ROLE) ((SYS)->xsysd->roles.ROLE) @@ -1219,6 +1259,7 @@ struct oxr_extension_status { OXR_EXTENSION_SUPPORT_GENERATE(MAKE_EXT_STATUS) }; +#undef MAKE_EXT_STATUS /*! * Main object that ties everything together. diff --git a/src/xrt/state_trackers/oxr/oxr_session.c b/src/xrt/state_trackers/oxr/oxr_session.c index 4128fd45e..a3dce932c 100644 --- a/src/xrt/state_trackers/oxr/oxr_session.c +++ b/src/xrt/state_trackers/oxr/oxr_session.c @@ -734,6 +734,28 @@ oxr_session_create_impl(struct oxr_logger *log, } #endif +#ifdef XR_USE_GRAPHICS_API_D3D11 + XrGraphicsBindingD3D11KHR const *d3d11 = + OXR_GET_INPUT_FROM_CHAIN(createInfo, XR_TYPE_GRAPHICS_BINDING_D3D11_KHR, XrGraphicsBindingD3D11KHR); + if (d3d11 != NULL) { + OXR_VERIFY_ARG_NOT_NULL(log, d3d11->device); + + if (!sys->gotten_requirements) { + return oxr_error(log, XR_ERROR_GRAPHICS_REQUIREMENTS_CALL_MISSING, + "Has not called xrGetD3D11GraphicsRequirementsKHR"); + } + XrResult result = oxr_d3d11_check_device(log, sys, d3d11->device); + + if (!XR_SUCCEEDED(result)) { + return result; + } + + + OXR_SESSION_ALLOCATE(log, sys, *out_session); + OXR_ALLOCATE_NATIVE_COMPOSITOR(log, xsi, *out_session); + return oxr_session_populate_d3d11(log, sys, d3d11, *out_session); + } +#endif /* * Add any new graphics binding structs here - before the headless * check. (order for non-headless checks not specified in standard.) diff --git a/src/xrt/state_trackers/oxr/oxr_session_gfx_d3d11.c b/src/xrt/state_trackers/oxr/oxr_session_gfx_d3d11.c new file mode 100644 index 000000000..0b070a901 --- /dev/null +++ b/src/xrt/state_trackers/oxr/oxr_session_gfx_d3d11.c @@ -0,0 +1,44 @@ +// Copyright 2018-2021, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Holds D3D11 specific session functions. + * @author Ryan Pavlik <ryan.pavlik@collabora.com> + * @author Jakob Bornecrantz <jakob@collabora.com> + * @ingroup oxr_main + * @ingroup comp_client + */ + +#include <stdlib.h> + +#include "util/u_misc.h" + +#include "xrt/xrt_instance.h" +#include "xrt/xrt_gfx_d3d11.h" + +#include "oxr_objects.h" +#include "oxr_logger.h" +#include "oxr_two_call.h" +#include "oxr_handle.h" + + +XrResult +oxr_session_populate_d3d11(struct oxr_logger *log, + struct oxr_system *sys, + XrGraphicsBindingD3D11KHR const *next, + struct oxr_session *sess) +{ + struct xrt_compositor_native *xcn = sess->xcn; + struct xrt_compositor_d3d11 *xcd3d = xrt_gfx_d3d11_provider_create( // + xcn, // + next->device); // + + if (xcd3d == NULL) { + return oxr_error(log, XR_ERROR_INITIALIZATION_FAILED, "Failed to create a d3d11 client compositor"); + } + + sess->compositor = &xcd3d->base; + sess->create_swapchain = oxr_swapchain_d3d11_create; + + return XR_SUCCESS; +} diff --git a/src/xrt/state_trackers/oxr/oxr_swapchain_d3d11.c b/src/xrt/state_trackers/oxr/oxr_swapchain_d3d11.c new file mode 100644 index 000000000..9a68881d2 --- /dev/null +++ b/src/xrt/state_trackers/oxr/oxr_swapchain_d3d11.c @@ -0,0 +1,78 @@ +// Copyright 2019-2021, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Holds D3D11 swapchain related functions. + * @author Ryan Pavlik <ryan.pavlik@collabora.com> + * @author Jakob Bornecrantz <jakob@collabora.com> + * @ingroup oxr_main + * @ingroup comp_client + */ + +#include <stdlib.h> + +#include "xrt/xrt_gfx_d3d11.h" +#include "util/u_debug.h" + +#include "oxr_objects.h" +#include "oxr_logger.h" + + +static XrResult +oxr_swapchain_d3d11_destroy(struct oxr_logger *log, struct oxr_swapchain *sc) +{ + // Release any waited image. + if (sc->waited.yes) { + sc->release_image(log, sc, NULL); + } + + // Release any acquired images. + XrSwapchainImageWaitInfo waitInfo = {0}; + while (!u_index_fifo_is_empty(&sc->acquired.fifo)) { + sc->wait_image(log, sc, &waitInfo); + sc->release_image(log, sc, NULL); + } + + // Drop our reference, does NULL checking. + xrt_swapchain_reference(&sc->swapchain, NULL); + + return XR_SUCCESS; +} + +static XrResult +oxr_swapchain_d3d11_enumerate_images(struct oxr_logger *log, + struct oxr_swapchain *sc, + uint32_t count, + XrSwapchainImageBaseHeader *images) +{ + struct xrt_swapchain_d3d11 *xscd3d = (struct xrt_swapchain_d3d11 *)sc->swapchain; + XrSwapchainImageD3D11KHR *d3d_imgs = (XrSwapchainImageD3D11KHR *)images; + + for (uint32_t i = 0; i < count; i++) { + d3d_imgs[i].texture = xscd3d->images[i]; + } + + return oxr_session_success_result(sc->sess); +} + +XrResult +oxr_swapchain_d3d11_create(struct oxr_logger *log, + struct oxr_session *sess, + const XrSwapchainCreateInfo *createInfo, + struct oxr_swapchain **out_swapchain) +{ + struct oxr_swapchain *sc; + XrResult ret; + + ret = oxr_create_swapchain(log, sess, createInfo, &sc); + if (ret != XR_SUCCESS) { + return ret; + } + + sc->destroy = oxr_swapchain_d3d11_destroy; + sc->enumerate_images = oxr_swapchain_d3d11_enumerate_images; + + *out_swapchain = sc; + + return XR_SUCCESS; +} diff --git a/src/xrt/state_trackers/oxr/oxr_system.c b/src/xrt/state_trackers/oxr/oxr_system.c index 1b72b9327..1a77d8c0f 100644 --- a/src/xrt/state_trackers/oxr/oxr_system.c +++ b/src/xrt/state_trackers/oxr/oxr_system.c @@ -103,6 +103,10 @@ oxr_system_fill_in(struct oxr_logger *log, struct oxr_instance *inst, XrSystemId sys->vulkan_enable2_instance = VK_NULL_HANDLE; sys->suggested_vulkan_physical_device = VK_NULL_HANDLE; #endif +#ifdef XR_USE_GRAPHICS_API_D3D11 + U_ZERO(&(sys->suggested_d3d_luid)); + sys->suggested_d3d_luid_valid = false; +#endif // Headless. if (sys->xsysc == NULL) { diff --git a/src/xrt/state_trackers/oxr/oxr_verify.c b/src/xrt/state_trackers/oxr/oxr_verify.c index 4a026e7d9..689210dd2 100644 --- a/src/xrt/state_trackers/oxr/oxr_verify.c +++ b/src/xrt/state_trackers/oxr/oxr_verify.c @@ -494,6 +494,15 @@ oxr_verify_XrSessionCreateInfo(struct oxr_logger *log, } #endif // defined(XR_USE_PLATFORM_ANDROID) && defined(XR_USE_GRAPHICS_API_OPENGL_ES) +#if defined(XR_USE_GRAPHICS_API_D3D11) + XrGraphicsBindingD3D11KHR const *d3d11 = + OXR_GET_INPUT_FROM_CHAIN(createInfo, XR_TYPE_GRAPHICS_BINDING_D3D11_KHR, XrGraphicsBindingD3D11KHR); + if (d3d11 != NULL) { + OXR_VERIFY_EXTENSION(log, inst, KHR_D3D11_enable); + return oxr_verify_XrGraphicsBindingD3D11KHR(log, d3d11); + } +#endif // XR_USE_GRAPHICS_API_D3D11 + /* * Add any new graphics binding structs here - before the headless * check. (order for non-headless checks not specified in standard.) @@ -603,3 +612,17 @@ oxr_verify_XrGraphicsBindingOpenGLESAndroidKHR(struct oxr_logger *log, const XrG } #endif // defined(XR_USE_PLATFORM_ANDROID) && // defined(XR_USE_GRAPHICS_API_OPENGL_ES) + +#if defined(XR_USE_GRAPHICS_API_D3D11) +XrResult +oxr_verify_XrGraphicsBindingD3D11KHR(struct oxr_logger *log, const XrGraphicsBindingD3D11KHR *next) +{ + if (next->type != XR_TYPE_GRAPHICS_BINDING_D3D11_KHR) { + return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, "Graphics binding has invalid type"); + } + if (next->device == NULL) { + return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, "XrGraphicsBindingD3D11KHR::device cannot be NULL"); + } + return XR_SUCCESS; +} +#endif // defined(XR_USE_GRAPHICS_API_D3D11)