The open source OpenXR runtime
at prediction-2 194 lines 6.1 kB view raw
1// Copyright 2019-2024, Collabora, Ltd. 2// SPDX-License-Identifier: BSL-1.0 3/*! 4 * @file 5 * @brief Functionality common to D3D11 and D3D12 for client side compositor implementation. 6 * @author Rylie Pavlik <rylie.pavlik@collabora.com> 7 * @author Jakob Bornecrantz <jakob@collabora.com> 8 * @author Fernando Velazquez Innella <finnella@magicleap.com> 9 * @author Korcan Hussein <korcan.hussein@collabora.com> 10 * @ingroup comp_client 11 */ 12#pragma once 13 14#include "xrt/xrt_compositor.h" 15#include "xrt/xrt_deleters.hpp" 16#include "xrt/xrt_results.h" 17 18#include "util/u_handles.h" 19#include "util/u_logging.h" 20 21#include <wil/com.h> 22#include <wil/resource.h> 23#include <wil/result_macros.h> 24 25#include <d3d11_3.h> 26 27#include <memory> 28#include <vector> 29#include <stdint.h> 30 31 32namespace xrt::compositor::client { 33 34using unique_swapchain_ref = 35 std::unique_ptr<struct xrt_swapchain, 36 xrt::deleters::reference_deleter<struct xrt_swapchain, xrt_swapchain_reference>>; 37 38 39/** 40 * Import the provided handles into a native compositor, without consuming them. 41 * 42 * @param xcn The native compositor 43 * @param handles A vector of uniquely-owned handles. These will be duplicated, not consumed, by this import. 44 * @param vkinfo The swapchain create info, with format as a Vulkan constant 45 * @param image_mem_size The image memory allocation size in bytes 46 * @param use_dedicated_allocation Passed through to @ref xrt_image_native 47 * @param[out] out_xsc The swapchain to populate 48 * @return XRT_SUCCESS if everything went well, otherwise whatever error a call internally returned. 49 */ 50static inline xrt_result_t 51importFromHandleDuplicates(xrt_compositor_native &xcn, 52 std::vector<wil::unique_handle> const &handles, 53 const struct xrt_swapchain_create_info &vkinfo, 54 const std::uint64_t image_mem_size, 55 bool use_dedicated_allocation, 56 unique_swapchain_ref &out_xsc) 57{ 58 uint32_t image_count = static_cast<uint32_t>(handles.size()); 59 // Populate for import 60 std::vector<xrt_image_native> xins; 61 xins.reserve(image_count); 62 63 // Keep this around until after successful import, then detach all. 64 std::vector<wil::unique_handle> handlesForImport; 65 handlesForImport.reserve(image_count); 66 67 for (const wil::unique_handle &handle : handles) { 68 wil::unique_handle duped{u_graphics_buffer_ref(handle.get())}; 69 xrt_image_native xin{}; 70 xin.handle = duped.get(); 71 xin.size = image_mem_size; 72 xin.use_dedicated_allocation = use_dedicated_allocation; 73 74 handlesForImport.emplace_back(std::move(duped)); 75 xins.emplace_back(xin); 76 } 77 78 // Import into the native compositor, to create the corresponding swapchain which we wrap. 79 xrt_swapchain *xsc = nullptr; 80 xrt_result_t xret = xrt_comp_import_swapchain(&(xcn.base), &vkinfo, xins.data(), image_count, &xsc); 81 if (xret != XRT_SUCCESS) { 82 return xret; 83 } 84 // Let unique_ptr manage the lifetime of xsc now 85 out_xsc.reset(xsc); 86 87 // The imported swapchain took ownership of them now, release them from ownership here. 88 for (auto &h : handlesForImport) { 89 h.release(); 90 } 91 return XRT_SUCCESS; 92} 93 94 95/** 96 * Import the provided handles into a native compositor. 97 * 98 * @param xcn The native compositor 99 * @param handles A vector of DXGI handles. 100 * @param vkinfo The swapchain create info, with format as a Vulkan constant 101 * @param use_dedicated_allocation Passed through to @ref xrt_image_native 102 * @param[out] out_xsc The swapchain to populate 103 * @return XRT_SUCCESS if everything went well, otherwise whatever error a call internally returned. 104 */ 105static inline xrt_result_t 106importFromDxgiHandles(xrt_compositor_native &xcn, 107 std::vector<HANDLE> const &handles, 108 const struct xrt_swapchain_create_info &vkinfo, 109 bool use_dedicated_allocation, 110 unique_swapchain_ref &out_xsc) 111{ 112 uint32_t image_count = static_cast<uint32_t>(handles.size()); 113 // Populate for import 114 std::vector<xrt_image_native> xins; 115 xins.reserve(image_count); 116 117 for (HANDLE handle : handles) { 118 xrt_image_native xin{}; 119 xin.handle = handle; 120 xin.size = 0; 121 xin.use_dedicated_allocation = use_dedicated_allocation; 122 xin.is_dxgi_handle = true; 123 124 xins.emplace_back(xin); 125 } 126 127 // Import into the native compositor, to create the corresponding swapchain which we wrap. 128 xrt_swapchain *xsc = nullptr; 129 xrt_result_t xret = xrt_comp_import_swapchain(&(xcn.base), &vkinfo, xins.data(), image_count, &xsc); 130 if (xret != XRT_SUCCESS) { 131 return xret; 132 } 133 // Let unique_ptr manage the lifetime of xsc now 134 out_xsc.reset(xsc); 135 136 return XRT_SUCCESS; 137} 138 139/** 140 * A collection of DXGIKeyedMutex objects, one for each swapchain image in a swapchain. 141 * 142 */ 143class KeyedMutexCollection 144{ 145public: 146 // 0 is special 147 static constexpr uint64_t kKeyedMutexKey = 0; 148 149 /** 150 * @brief Construct a new Keyed Mutex Collection object 151 * 152 * @param log_level The compositor log level to use 153 */ 154 explicit KeyedMutexCollection(u_logging_level log_level) noexcept; 155 156 /** 157 * Make the keyed mutex vector before starting to use the images. 158 * 159 * @param images Your vector of textures to acquire keyed mutexes from. 160 */ 161 xrt_result_t 162 init(const std::vector<wil::com_ptr<ID3D11Texture2D1>> &images) noexcept; 163 164 /** 165 * Wait for acquisition of the keyed mutex. 166 * 167 * @param index Swapchain image index 168 * @param timeout_ns Timeout in nanoseconds or XRT_INFINITE_DURATION 169 * @return xrt_result_t: XRT_SUCCESS, XRT_TIMEOUT, or some error 170 */ 171 xrt_result_t 172 waitKeyedMutex(uint32_t index, uint64_t timeout_ns) noexcept; 173 174 /** 175 * Release the keyed mutex 176 * 177 * @param index Swapchain image index 178 * @return xrt_result_t 179 */ 180 xrt_result_t 181 releaseKeyedMutex(uint32_t index) noexcept; 182 183private: 184 //! Keyed mutex per image associated with client_d3d11_compositor::app_device 185 std::vector<wil::com_ptr<IDXGIKeyedMutex>> keyed_mutex_collection; 186 187 std::vector<bool> keyed_mutex_acquired; 188 189 //! Logging level. 190 u_logging_level log_level; 191}; 192 193 194} // namespace xrt::compositor::client