The open source OpenXR runtime
1// Copyright 2019-2022, Collabora, Ltd.
2// SPDX-License-Identifier: BSL-1.0
3/*!
4 * @file
5 * @brief D3D12 client side glue to compositor implementation.
6 * @author Rylie Pavlik <rylie.pavlik@collabora.com>
7 * @author Jakob Bornecrantz <jakob@collabora.com>
8 * @ingroup comp_client
9 */
10
11#include "comp_d3d_common.hpp"
12
13#include "util/u_logging.h"
14#include "util/u_time.h"
15
16
17
18#define D3D_COMMON_SPEW(log_level, ...) U_LOG_IFL_T(log_level, __VA_ARGS__);
19
20#define D3D_COMMON_DEBUG(log_level, ...) U_LOG_IFL_D(log_level, __VA_ARGS__);
21
22#define D3D_COMMON_INFO(log_level, ...) U_LOG_IFL_I(log_level, __VA_ARGS__);
23
24#define D3D_COMMON_WARN(log_level, ...) U_LOG_IFL_W(log_level, __VA_ARGS__);
25
26#define D3D_COMMON_ERROR(log_level, ...) U_LOG_IFL_E(log_level, __VA_ARGS__);
27
28namespace xrt::compositor::client {
29
30static inline DWORD
31convertTimeoutToWindowsMilliseconds(uint64_t timeout_ns)
32{
33 return (timeout_ns == XRT_INFINITE_DURATION) ? INFINITE : (DWORD)(timeout_ns / (uint64_t)U_TIME_1MS_IN_NS);
34}
35
36KeyedMutexCollection::KeyedMutexCollection(u_logging_level log_level) noexcept : log_level(log_level) {}
37
38xrt_result_t
39KeyedMutexCollection::init(const std::vector<wil::com_ptr<ID3D11Texture2D1>> &images) noexcept
40try {
41 keyed_mutex_collection.clear();
42 keyed_mutex_collection.reserve(images.size());
43 for (const auto &image : images) {
44 keyed_mutex_collection.emplace_back(image.query<IDXGIKeyedMutex>());
45 }
46
47 keyed_mutex_acquired.clear();
48 keyed_mutex_acquired.resize(keyed_mutex_collection.size());
49 return XRT_SUCCESS;
50} catch (wil::ResultException const &e) {
51 U_LOG_E("Error getting keyed mutex collection for swapchain: %s", e.what());
52 return XRT_ERROR_D3D;
53} catch (std::exception const &e) {
54 U_LOG_E("Error getting keyed mutex collection for swapchain: %s", e.what());
55 return XRT_ERROR_D3D;
56} catch (...) {
57 U_LOG_E("Error getting keyed mutex collection for swapchain");
58 return XRT_ERROR_D3D;
59}
60
61xrt_result_t
62KeyedMutexCollection::waitKeyedMutex(uint32_t index, uint64_t timeout_ns) noexcept
63
64try {
65
66 if (keyed_mutex_acquired[index]) {
67
68 D3D_COMMON_WARN(log_level,
69 "Will not acquire the keyed mutex for image %" PRId32 " - it was already acquired!",
70 index);
71 return XRT_ERROR_NO_IMAGE_AVAILABLE;
72 }
73
74 auto hr =
75 keyed_mutex_collection[index]->AcquireSync(kKeyedMutexKey, convertTimeoutToWindowsMilliseconds(timeout_ns));
76 if (hr == WAIT_ABANDONED) {
77 D3D_COMMON_ERROR(log_level,
78 "Could not acquire the keyed mutex for image %" PRId32
79 " due to it being in an inconsistent state",
80 index);
81 return XRT_ERROR_D3D;
82 }
83 if (hr == WAIT_TIMEOUT) {
84 return XRT_TIMEOUT;
85 }
86 if (FAILED(hr)) {
87 D3D_COMMON_ERROR(log_level, "Could not acquire the keyed mutex for image %" PRId32, index);
88 return XRT_ERROR_D3D;
89 }
90 keyed_mutex_acquired[index] = true;
91 return XRT_SUCCESS;
92} catch (wil::ResultException const &e) {
93 U_LOG_E("Error acquiring keyed mutex for image %" PRId32 ": %s", index, e.what());
94 return XRT_ERROR_D3D;
95} catch (std::exception const &e) {
96 U_LOG_E("Error acquiring keyed mutex for image %" PRId32 ": %s", index, e.what());
97 return XRT_ERROR_D3D;
98} catch (...) {
99 U_LOG_E("Error acquiring keyed mutex for image %" PRId32, index);
100 return XRT_ERROR_D3D;
101}
102
103
104xrt_result_t
105KeyedMutexCollection::releaseKeyedMutex(uint32_t index) noexcept
106
107try {
108
109 if (!keyed_mutex_acquired[index]) {
110
111 D3D_COMMON_WARN(log_level,
112 "Will not release the keyed mutex for image %" PRId32 " - it was not acquired!", index);
113 return XRT_ERROR_D3D;
114 }
115 auto hr = LOG_IF_FAILED(keyed_mutex_collection[index]->ReleaseSync(kKeyedMutexKey));
116 if (FAILED(hr)) {
117 D3D_COMMON_ERROR(log_level, "Could not release the keyed mutex for image %" PRId32, index);
118 return XRT_ERROR_D3D;
119 }
120 keyed_mutex_acquired[index] = false;
121 return XRT_SUCCESS;
122
123} catch (wil::ResultException const &e) {
124 U_LOG_E("Error releasing keyed mutex %" PRId32 ": %s", index, e.what());
125 return XRT_ERROR_D3D;
126} catch (std::exception const &e) {
127 U_LOG_E("Error releasing keyed mutex %" PRId32 ": %s", index, e.what());
128 return XRT_ERROR_D3D;
129} catch (...) {
130 U_LOG_E("Error releasing keyed mutex %" PRId32, index);
131 return XRT_ERROR_D3D;
132}
133
134
135} // namespace xrt::compositor::client