mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-01-30 18:38:32 +00:00
c/client: Extract some utilities usable by D3D11 and 12
This commit is contained in:
parent
576b158a83
commit
a9facfe671
doc/changes/compositor
src/xrt/compositor
|
@ -5,6 +5,7 @@
|
||||||
- mr.1326
|
- mr.1326
|
||||||
- mr.1302
|
- mr.1302
|
||||||
- mr.1337
|
- mr.1337
|
||||||
|
- mr.1340
|
||||||
---
|
---
|
||||||
|
|
||||||
Full support for D3D11 client applications on Windows.
|
Full support for D3D11 client applications on Windows.
|
||||||
|
|
|
@ -58,6 +58,14 @@ if(XRT_HAVE_EGL)
|
||||||
target_sources(comp_client PRIVATE client/comp_egl_client.c client/comp_egl_client.h)
|
target_sources(comp_client PRIVATE client/comp_egl_client.c client/comp_egl_client.h)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(XRT_HAVE_D3D11 OR XRT_HAVE_D3D12)
|
||||||
|
target_link_libraries(comp_client PRIVATE aux_d3d)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(XRT_HAVE_D3D11 OR XRT_HAVE_D3D12)
|
||||||
|
target_sources(comp_client PRIVATE client/comp_d3d_common.cpp client/comp_d3d_common.hpp)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(XRT_HAVE_D3D11)
|
if(XRT_HAVE_D3D11)
|
||||||
target_sources(
|
target_sources(
|
||||||
comp_client PRIVATE client/comp_d3d11_client.cpp client/comp_d3d11_client.h
|
comp_client PRIVATE client/comp_d3d11_client.cpp client/comp_d3d11_client.h
|
||||||
|
@ -65,6 +73,7 @@ if(XRT_HAVE_D3D11)
|
||||||
)
|
)
|
||||||
target_link_libraries(comp_client PRIVATE aux_d3d)
|
target_link_libraries(comp_client PRIVATE aux_d3d)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
##
|
##
|
||||||
# Util library
|
# Util library
|
||||||
#
|
#
|
||||||
|
@ -259,7 +268,6 @@ if(XRT_FEATURE_COMPOSITOR_MAIN)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
# Null compositor
|
# Null compositor
|
||||||
#
|
#
|
||||||
|
@ -268,7 +276,6 @@ if(XRT_FEATURE_COMPOSITOR_NULL)
|
||||||
add_subdirectory(null)
|
add_subdirectory(null)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
# Multi client compositor library
|
# Multi client compositor library
|
||||||
#
|
#
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
|
|
||||||
#include "comp_d3d11_client.h"
|
#include "comp_d3d11_client.h"
|
||||||
|
|
||||||
|
#include "comp_d3d_common.hpp"
|
||||||
|
|
||||||
#include "xrt/xrt_compositor.h"
|
#include "xrt/xrt_compositor.h"
|
||||||
#include "xrt/xrt_config_os.h"
|
#include "xrt/xrt_config_os.h"
|
||||||
#include "xrt/xrt_handles.h"
|
#include "xrt/xrt_handles.h"
|
||||||
|
@ -45,6 +47,8 @@
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
|
|
||||||
|
using xrt::compositor::client::unique_swapchain_ref;
|
||||||
|
|
||||||
DEBUG_GET_ONCE_LOG_OPTION(log, "D3D_COMPOSITOR_LOG", U_LOGGING_INFO)
|
DEBUG_GET_ONCE_LOG_OPTION(log, "D3D_COMPOSITOR_LOG", U_LOGGING_INFO)
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -86,10 +90,6 @@ using unique_compositor_semaphore_ref = std::unique_ptr<
|
||||||
struct xrt_compositor_semaphore,
|
struct xrt_compositor_semaphore,
|
||||||
xrt::deleters::reference_deleter<struct xrt_compositor_semaphore, xrt_compositor_semaphore_reference>>;
|
xrt::deleters::reference_deleter<struct xrt_compositor_semaphore, xrt_compositor_semaphore_reference>>;
|
||||||
|
|
||||||
using unique_swapchain_ref =
|
|
||||||
std::unique_ptr<struct xrt_swapchain,
|
|
||||||
xrt::deleters::reference_deleter<struct xrt_swapchain, xrt_swapchain_reference>>;
|
|
||||||
|
|
||||||
// 0 is special
|
// 0 is special
|
||||||
static constexpr uint64_t kKeyedMutexKey = 0;
|
static constexpr uint64_t kKeyedMutexKey = 0;
|
||||||
|
|
||||||
|
@ -182,6 +182,10 @@ convertTimeoutToWindowsMilliseconds(uint64_t timeout_ns)
|
||||||
*/
|
*/
|
||||||
struct client_d3d11_swapchain_data
|
struct client_d3d11_swapchain_data
|
||||||
{
|
{
|
||||||
|
explicit client_d3d11_swapchain_data(enum u_logging_level log_level) : keyed_mutex_collection(log_level) {}
|
||||||
|
|
||||||
|
xrt::compositor::client::KeyedMutexCollection keyed_mutex_collection;
|
||||||
|
|
||||||
//! The shared handles for all our images
|
//! The shared handles for all our images
|
||||||
std::vector<wil::unique_handle> handles;
|
std::vector<wil::unique_handle> handles;
|
||||||
|
|
||||||
|
@ -190,16 +194,6 @@ struct client_d3d11_swapchain_data
|
||||||
|
|
||||||
//! Images associated with client_d3d11_compositor::comp_device
|
//! Images associated with client_d3d11_compositor::comp_device
|
||||||
std::vector<wil::com_ptr<ID3D11Texture2D1>> comp_images;
|
std::vector<wil::com_ptr<ID3D11Texture2D1>> comp_images;
|
||||||
|
|
||||||
//! Keyed mutex per image associated with client_d3d11_compositor::app_device
|
|
||||||
std::vector<wil::com_ptr<IDXGIKeyedMutex>> app_keyed_mutex_collection;
|
|
||||||
|
|
||||||
std::vector<bool> keyed_mutex_acquired;
|
|
||||||
|
|
||||||
xrt_result_t
|
|
||||||
waitImage(client_d3d11_swapchain *sc, uint32_t index, uint64_t timeout_ns);
|
|
||||||
xrt_result_t
|
|
||||||
releaseImage(client_d3d11_swapchain *sc, uint32_t index);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -265,63 +259,6 @@ formatMessage(DWORD err, char (&buf)[N])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Helpers for Swapchain
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
inline xrt_result_t
|
|
||||||
client_d3d11_swapchain_data::waitImage(client_d3d11_swapchain *sc, uint32_t index, uint64_t timeout_ns)
|
|
||||||
{
|
|
||||||
if (keyed_mutex_acquired[index]) {
|
|
||||||
|
|
||||||
D3D_WARN(sc->c, "Will not acquire the keyed mutex for image %" PRId32 " - it was already acquired!",
|
|
||||||
index);
|
|
||||||
return XRT_ERROR_NO_IMAGE_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto hr = app_keyed_mutex_collection[index]->AcquireSync(kKeyedMutexKey,
|
|
||||||
convertTimeoutToWindowsMilliseconds(timeout_ns));
|
|
||||||
if (hr == WAIT_ABANDONED) {
|
|
||||||
D3D_ERROR(sc->c,
|
|
||||||
"Could not acquire the keyed mutex for image %" PRId32
|
|
||||||
" due to it being in an inconsistent state",
|
|
||||||
index);
|
|
||||||
return XRT_ERROR_D3D11;
|
|
||||||
}
|
|
||||||
if (hr == WAIT_TIMEOUT) {
|
|
||||||
return XRT_TIMEOUT;
|
|
||||||
}
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
D3D_ERROR(sc->c, "Could not acquire the keyed mutex for image %" PRId32, index);
|
|
||||||
return XRT_ERROR_D3D11;
|
|
||||||
}
|
|
||||||
keyed_mutex_acquired[index] = true;
|
|
||||||
sc->c->app_context->Flush();
|
|
||||||
//! @todo this causes an error in the debug layer
|
|
||||||
// Discard old contents
|
|
||||||
// sc->c->app_context->DiscardResource(wil::com_raw_ptr(app_images[index]));
|
|
||||||
return XRT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline xrt_result_t
|
|
||||||
client_d3d11_swapchain_data::releaseImage(client_d3d11_swapchain *sc, uint32_t index)
|
|
||||||
{
|
|
||||||
if (!keyed_mutex_acquired[index]) {
|
|
||||||
|
|
||||||
D3D_WARN(sc->c, "Will not release the keyed mutex for image %" PRId32 " - it was not acquired!", index);
|
|
||||||
return XRT_ERROR_D3D11;
|
|
||||||
}
|
|
||||||
auto hr = LOG_IF_FAILED(app_keyed_mutex_collection[index]->ReleaseSync(kKeyedMutexKey));
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
D3D_ERROR(sc->c, "Could not release the keyed mutex for image %" PRId32, index);
|
|
||||||
return XRT_ERROR_D3D11;
|
|
||||||
}
|
|
||||||
sc->data->keyed_mutex_acquired[index] = false;
|
|
||||||
return XRT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Swapchain functions.
|
* Swapchain functions.
|
||||||
|
@ -347,8 +284,10 @@ client_d3d11_swapchain_wait_image(struct xrt_swapchain *xsc, uint64_t timeout_ns
|
||||||
|
|
||||||
if (xret == XRT_SUCCESS) {
|
if (xret == XRT_SUCCESS) {
|
||||||
// OK, we got the image in the native compositor, now need the keyed mutex in d3d11.
|
// OK, we got the image in the native compositor, now need the keyed mutex in d3d11.
|
||||||
return sc->data->waitImage(sc, index, timeout_ns);
|
xret = sc->data->keyed_mutex_collection.waitKeyedMutex(index, timeout_ns);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! @todo discard old contents?
|
||||||
return xret;
|
return xret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,7 +300,8 @@ client_d3d11_swapchain_release_image(struct xrt_swapchain *xsc, uint32_t index)
|
||||||
xrt_result_t xret = xrt_swapchain_release_image(sc->xsc.get(), index);
|
xrt_result_t xret = xrt_swapchain_release_image(sc->xsc.get(), index);
|
||||||
|
|
||||||
if (xret == XRT_SUCCESS) {
|
if (xret == XRT_SUCCESS) {
|
||||||
return sc->data->releaseImage(sc, index);
|
// Release the keyed mutex
|
||||||
|
xret = sc->data->keyed_mutex_collection.releaseKeyedMutex(index);
|
||||||
}
|
}
|
||||||
return xret;
|
return xret;
|
||||||
}
|
}
|
||||||
|
@ -439,15 +379,13 @@ try {
|
||||||
vkinfo.format = vk_format;
|
vkinfo.format = vk_format;
|
||||||
|
|
||||||
std::unique_ptr<struct client_d3d11_swapchain> sc = std::make_unique<struct client_d3d11_swapchain>();
|
std::unique_ptr<struct client_d3d11_swapchain> sc = std::make_unique<struct client_d3d11_swapchain>();
|
||||||
sc->data = std::make_unique<client_d3d11_swapchain_data>();
|
sc->data = std::make_unique<client_d3d11_swapchain_data>(c->log_level);
|
||||||
auto &data = sc->data;
|
auto &data = sc->data;
|
||||||
xret = xrt::auxiliary::d3d::d3d11::allocateSharedImages(*(c->comp_device), xinfo, image_count, true,
|
xret = xrt::auxiliary::d3d::d3d11::allocateSharedImages(*(c->comp_device), xinfo, image_count, true,
|
||||||
data->comp_images, data->handles);
|
data->comp_images, data->handles);
|
||||||
if (xret != XRT_SUCCESS) {
|
if (xret != XRT_SUCCESS) {
|
||||||
return xret;
|
return xret;
|
||||||
}
|
}
|
||||||
data->keyed_mutex_acquired.resize(image_count);
|
|
||||||
sc->data->app_keyed_mutex_collection.reserve(image_count);
|
|
||||||
data->app_images.reserve(image_count);
|
data->app_images.reserve(image_count);
|
||||||
|
|
||||||
// Import from the handle for the app.
|
// Import from the handle for the app.
|
||||||
|
@ -458,45 +396,24 @@ try {
|
||||||
// Put the image where the OpenXR state tracker can get it
|
// Put the image where the OpenXR state tracker can get it
|
||||||
sc->base.images[i] = image.get();
|
sc->base.images[i] = image.get();
|
||||||
|
|
||||||
// Cache the keyed mutex interface too
|
|
||||||
sc->data->app_keyed_mutex_collection.emplace_back(image.query<IDXGIKeyedMutex>());
|
|
||||||
|
|
||||||
// Store the owning pointer for lifetime management
|
// Store the owning pointer for lifetime management
|
||||||
data->app_images.emplace_back(std::move(image));
|
data->app_images.emplace_back(std::move(image));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Populate for import
|
// Cache the keyed mutex interface
|
||||||
std::vector<xrt_image_native> xins;
|
xret = data->keyed_mutex_collection.init(data->app_images);
|
||||||
xins.reserve(data->handles.size());
|
if (xret != XRT_SUCCESS) {
|
||||||
// Keep this around until after successful import, then detach all.
|
D3D_ERROR(c, "Error retrieving keyex mutex interfaces");
|
||||||
std::vector<wil::unique_handle> handlesForImport;
|
return xret;
|
||||||
handlesForImport.reserve(data->handles.size());
|
|
||||||
|
|
||||||
for (const wil::unique_handle &handle : data->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 = false; //! @todo not sure
|
|
||||||
|
|
||||||
handlesForImport.emplace_back(std::move(duped));
|
|
||||||
xins.emplace_back(xin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Import into the native compositor, to create the corresponding swapchain which we wrap.
|
// Import into the native compositor, to create the corresponding swapchain which we wrap.
|
||||||
xrt_swapchain *xsc = nullptr;
|
xret = xrt::compositor::client::importFromHandleDuplicates(
|
||||||
xret = xrt_comp_import_swapchain(&(c->xcn->base), &vkinfo, xins.data(), image_count, &xsc);
|
*(c->xcn), data->handles, vkinfo, false /** @todo not sure - dedicated allocation */, sc->xsc);
|
||||||
if (xret != XRT_SUCCESS) {
|
if (xret != XRT_SUCCESS) {
|
||||||
D3D_ERROR(c, "Error importing D3D11 swapchain into native compositor");
|
D3D_ERROR(c, "Error importing D3D11 swapchain into native compositor");
|
||||||
return xret;
|
return xret;
|
||||||
}
|
}
|
||||||
// The imported swapchain took ownership of them now, release them from ownership here.
|
|
||||||
for (auto &h : handlesForImport) {
|
|
||||||
h.release();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let unique_ptr manage the lifetime of xsc now
|
|
||||||
sc->xsc.reset(xsc);
|
|
||||||
|
|
||||||
sc->base.base.destroy = client_d3d11_swapchain_destroy;
|
sc->base.base.destroy = client_d3d11_swapchain_destroy;
|
||||||
sc->base.base.acquire_image = client_d3d11_swapchain_acquire_image;
|
sc->base.base.acquire_image = client_d3d11_swapchain_acquire_image;
|
||||||
|
|
144
src/xrt/compositor/client/comp_d3d_common.cpp
Normal file
144
src/xrt/compositor/client/comp_d3d_common.cpp
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
// Copyright 2019-2022, Collabora, Ltd.
|
||||||
|
// SPDX-License-Identifier: BSL-1.0
|
||||||
|
/*!
|
||||||
|
* @file
|
||||||
|
* @brief D3D12 client side glue to compositor implementation.
|
||||||
|
* @author Ryan Pavlik <ryan.pavlik@collabora.com>
|
||||||
|
* @author Jakob Bornecrantz <jakob@collabora.com>
|
||||||
|
* @ingroup comp_client
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "comp_d3d_common.hpp"
|
||||||
|
|
||||||
|
#include "util/u_logging.h"
|
||||||
|
#include "util/u_time.h"
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define D3D_COMMON_SPEW(log_level, ...) U_LOG_IFL_T(log_level, __VA_ARGS__);
|
||||||
|
|
||||||
|
#define D3D_COMMON_DEBUG(log_level, ...) U_LOG_IFL_D(log_level, __VA_ARGS__);
|
||||||
|
|
||||||
|
#define D3D_COMMON_INFO(log_level, ...) U_LOG_IFL_I(log_level, __VA_ARGS__);
|
||||||
|
|
||||||
|
#define D3D_COMMON_WARN(log_level, ...) U_LOG_IFL_W(log_level, __VA_ARGS__);
|
||||||
|
|
||||||
|
#define D3D_COMMON_ERROR(log_level, ...) U_LOG_IFL_E(log_level, __VA_ARGS__);
|
||||||
|
|
||||||
|
namespace xrt::compositor::client {
|
||||||
|
|
||||||
|
// xrt_result_t
|
||||||
|
// importFromHandleDuplicates(xrt_compositor_native &xcn,
|
||||||
|
// std::vector<wil::unique_handle> const &handles,
|
||||||
|
// const xrt_swapchain_create_info &vkinfo,
|
||||||
|
// bool use_dedicated_allocation,
|
||||||
|
// unique_swapchain_ref &out_xsc)
|
||||||
|
|
||||||
|
|
||||||
|
static inline DWORD
|
||||||
|
convertTimeoutToWindowsMilliseconds(uint64_t timeout_ns)
|
||||||
|
{
|
||||||
|
return (timeout_ns == XRT_INFINITE_DURATION) ? INFINITE : (DWORD)(timeout_ns / (uint64_t)U_TIME_1MS_IN_NS);
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyedMutexCollection::KeyedMutexCollection(u_logging_level log_level) noexcept : log_level(log_level) {}
|
||||||
|
|
||||||
|
xrt_result_t
|
||||||
|
KeyedMutexCollection::init(const std::vector<wil::com_ptr<ID3D11Texture2D1>> &images) noexcept
|
||||||
|
try {
|
||||||
|
keyed_mutex_collection.clear();
|
||||||
|
keyed_mutex_collection.reserve(images.size());
|
||||||
|
for (const auto &image : images) {
|
||||||
|
keyed_mutex_collection.emplace_back(image.query<IDXGIKeyedMutex>());
|
||||||
|
}
|
||||||
|
|
||||||
|
keyed_mutex_acquired.clear();
|
||||||
|
keyed_mutex_acquired.resize(keyed_mutex_collection.size());
|
||||||
|
return XRT_SUCCESS;
|
||||||
|
} catch (wil::ResultException const &e) {
|
||||||
|
U_LOG_E("Error getting keyed mutex collection for swapchain: %s", e.what());
|
||||||
|
return XRT_ERROR_D3D;
|
||||||
|
} catch (std::exception const &e) {
|
||||||
|
U_LOG_E("Error getting keyed mutex collection for swapchain: %s", e.what());
|
||||||
|
return XRT_ERROR_D3D;
|
||||||
|
} catch (...) {
|
||||||
|
U_LOG_E("Error getting keyed mutex collection for swapchain");
|
||||||
|
return XRT_ERROR_D3D;
|
||||||
|
}
|
||||||
|
|
||||||
|
xrt_result_t
|
||||||
|
KeyedMutexCollection::waitKeyedMutex(uint32_t index, uint64_t timeout_ns) noexcept
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
if (keyed_mutex_acquired[index]) {
|
||||||
|
|
||||||
|
D3D_COMMON_WARN(log_level,
|
||||||
|
"Will not acquire the keyed mutex for image %" PRId32 " - it was already acquired!",
|
||||||
|
index);
|
||||||
|
return XRT_ERROR_NO_IMAGE_AVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto hr =
|
||||||
|
keyed_mutex_collection[index]->AcquireSync(kKeyedMutexKey, convertTimeoutToWindowsMilliseconds(timeout_ns));
|
||||||
|
if (hr == WAIT_ABANDONED) {
|
||||||
|
D3D_COMMON_ERROR(log_level,
|
||||||
|
"Could not acquire the keyed mutex for image %" PRId32
|
||||||
|
" due to it being in an inconsistent state",
|
||||||
|
index);
|
||||||
|
return XRT_ERROR_D3D;
|
||||||
|
}
|
||||||
|
if (hr == WAIT_TIMEOUT) {
|
||||||
|
return XRT_TIMEOUT;
|
||||||
|
}
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
D3D_COMMON_ERROR(log_level, "Could not acquire the keyed mutex for image %" PRId32, index);
|
||||||
|
return XRT_ERROR_D3D;
|
||||||
|
}
|
||||||
|
keyed_mutex_acquired[index] = true;
|
||||||
|
return XRT_SUCCESS;
|
||||||
|
} catch (wil::ResultException const &e) {
|
||||||
|
U_LOG_E("Error acquiring keyed mutex for image %" PRId32 ": %s", index, e.what());
|
||||||
|
return XRT_ERROR_D3D;
|
||||||
|
} catch (std::exception const &e) {
|
||||||
|
U_LOG_E("Error acquiring keyed mutex for image %" PRId32 ": %s", index, e.what());
|
||||||
|
return XRT_ERROR_D3D;
|
||||||
|
} catch (...) {
|
||||||
|
U_LOG_E("Error acquiring keyed mutex for image %" PRId32, index);
|
||||||
|
return XRT_ERROR_D3D;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xrt_result_t
|
||||||
|
KeyedMutexCollection::releaseKeyedMutex(uint32_t index) noexcept
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
if (!keyed_mutex_acquired[index]) {
|
||||||
|
|
||||||
|
D3D_COMMON_WARN(log_level,
|
||||||
|
"Will not release the keyed mutex for image %" PRId32 " - it was not acquired!", index);
|
||||||
|
return XRT_ERROR_D3D;
|
||||||
|
}
|
||||||
|
auto hr = LOG_IF_FAILED(keyed_mutex_collection[index]->ReleaseSync(kKeyedMutexKey));
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
D3D_COMMON_ERROR(log_level, "Could not release the keyed mutex for image %" PRId32, index);
|
||||||
|
return XRT_ERROR_D3D;
|
||||||
|
}
|
||||||
|
keyed_mutex_acquired[index] = false;
|
||||||
|
return XRT_SUCCESS;
|
||||||
|
|
||||||
|
} catch (wil::ResultException const &e) {
|
||||||
|
U_LOG_E("Error releasing keyed mutex %" PRId32 ": %s", index, e.what());
|
||||||
|
return XRT_ERROR_D3D;
|
||||||
|
} catch (std::exception const &e) {
|
||||||
|
U_LOG_E("Error releasing keyed mutex %" PRId32 ": %s", index, e.what());
|
||||||
|
return XRT_ERROR_D3D;
|
||||||
|
} catch (...) {
|
||||||
|
U_LOG_E("Error releasing keyed mutex %" PRId32, index);
|
||||||
|
return XRT_ERROR_D3D;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace xrt::compositor::client
|
144
src/xrt/compositor/client/comp_d3d_common.hpp
Normal file
144
src/xrt/compositor/client/comp_d3d_common.hpp
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
// Copyright 2019-2022, Collabora, Ltd.
|
||||||
|
// SPDX-License-Identifier: BSL-1.0
|
||||||
|
/*!
|
||||||
|
* @file
|
||||||
|
* @brief Functionality common to D3D11 and D3D12 for client side compositor implementation.
|
||||||
|
* @author Ryan Pavlik <ryan.pavlik@collabora.com>
|
||||||
|
* @author Jakob Bornecrantz <jakob@collabora.com>
|
||||||
|
* @ingroup comp_client
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "xrt/xrt_compositor.h"
|
||||||
|
#include "xrt/xrt_deleters.hpp"
|
||||||
|
#include "xrt/xrt_results.h"
|
||||||
|
|
||||||
|
#include "util/u_handles.h"
|
||||||
|
#include "util/u_logging.h"
|
||||||
|
|
||||||
|
#include <wil/com.h>
|
||||||
|
#include <wil/resource.h>
|
||||||
|
#include <wil/result_macros.h>
|
||||||
|
|
||||||
|
#include <d3d11_3.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace xrt::compositor::client {
|
||||||
|
|
||||||
|
using unique_swapchain_ref =
|
||||||
|
std::unique_ptr<struct xrt_swapchain,
|
||||||
|
xrt::deleters::reference_deleter<struct xrt_swapchain, xrt_swapchain_reference>>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Import the provided handles into a native compositor, without consuming them.
|
||||||
|
*
|
||||||
|
* @param c The native compositor
|
||||||
|
* @param handles A vector of uniquely-owned handles. These will be duplicated, not consumed, by this import.
|
||||||
|
* @param vkinfo The swapchain create info, with format as a Vulkan constant
|
||||||
|
* @param use_dedicated_allocation Passed through to @ref xrt_image_native
|
||||||
|
* @param[out] out_xsc The swapchain to populate
|
||||||
|
* @return XRT_SUCCESS if everything went well, otherwise whatever error a call internally returned.
|
||||||
|
*/
|
||||||
|
static inline xrt_result_t
|
||||||
|
importFromHandleDuplicates(xrt_compositor_native &xcn,
|
||||||
|
std::vector<wil::unique_handle> const &handles,
|
||||||
|
const struct xrt_swapchain_create_info &vkinfo,
|
||||||
|
bool use_dedicated_allocation,
|
||||||
|
unique_swapchain_ref &out_xsc)
|
||||||
|
{
|
||||||
|
uint32_t image_count = static_cast<uint32_t>(handles.size());
|
||||||
|
// Populate for import
|
||||||
|
std::vector<xrt_image_native> xins;
|
||||||
|
xins.reserve(image_count);
|
||||||
|
|
||||||
|
// Keep this around until after successful import, then detach all.
|
||||||
|
std::vector<wil::unique_handle> 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 the native compositor, to create the corresponding swapchain which we wrap.
|
||||||
|
xrt_swapchain *xsc = nullptr;
|
||||||
|
xrt_result_t xret = xrt_comp_import_swapchain(&(xcn.base), &vkinfo, xins.data(), image_count, &xsc);
|
||||||
|
if (xret != XRT_SUCCESS) {
|
||||||
|
return xret;
|
||||||
|
}
|
||||||
|
// Let unique_ptr manage the lifetime of xsc now
|
||||||
|
out_xsc.reset(xsc);
|
||||||
|
|
||||||
|
// The imported swapchain took ownership of them now, release them from ownership here.
|
||||||
|
for (auto &h : handlesForImport) {
|
||||||
|
h.release();
|
||||||
|
}
|
||||||
|
return XRT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A collection of DXGIKeyedMutex objects, one for each swapchain image in a swapchain.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class KeyedMutexCollection
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// 0 is special
|
||||||
|
static constexpr uint64_t kKeyedMutexKey = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Construct a new Keyed Mutex Collection object
|
||||||
|
*
|
||||||
|
* @param log_level The compositor log level to use
|
||||||
|
*/
|
||||||
|
explicit KeyedMutexCollection(u_logging_level log_level) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Take the keyed mutex vector before starting to use the images.
|
||||||
|
*
|
||||||
|
* @param keyedMutexVector Your vector of objects to move from
|
||||||
|
*/
|
||||||
|
xrt_result_t
|
||||||
|
init(const std::vector<wil::com_ptr<ID3D11Texture2D1>> &images) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for acquisition of the keyed mutex.
|
||||||
|
*
|
||||||
|
* @param index Swapchain image index
|
||||||
|
* @param timeout_ns Timeout in nanoseconds or XRT_INFINITE_DURATION
|
||||||
|
* @return xrt_result_t: XRT_SUCCESS, XRT_TIMEOUT, or some error
|
||||||
|
*/
|
||||||
|
xrt_result_t
|
||||||
|
waitKeyedMutex(uint32_t index, uint64_t timeout_ns) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release the keyed mutex
|
||||||
|
*
|
||||||
|
* @param index Swapchain image index
|
||||||
|
* @return xrt_result_t
|
||||||
|
*/
|
||||||
|
xrt_result_t
|
||||||
|
releaseKeyedMutex(uint32_t index) noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
//! Keyed mutex per image associated with client_d3d11_compositor::app_device
|
||||||
|
std::vector<wil::com_ptr<IDXGIKeyedMutex>> keyed_mutex_collection;
|
||||||
|
|
||||||
|
std::vector<bool> keyed_mutex_acquired;
|
||||||
|
|
||||||
|
//! Logging level.
|
||||||
|
u_logging_level log_level;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace xrt::compositor::client
|
Loading…
Reference in a new issue