mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-01-19 13:18:32 +00:00
auxiliary: Add new d3d helper library
This commit is contained in:
parent
e6d58cf451
commit
9337ea375c
|
@ -32,6 +32,30 @@ if(XRT_HAVE_OPENGL OR XRT_HAVE_OPENGLES)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Direct3D library
|
||||||
|
if(XRT_HAVE_D3D11 AND XRT_HAVE_VULKAN)
|
||||||
|
add_library(
|
||||||
|
aux_d3d STATIC
|
||||||
|
d3d/d3d_d3d11_allocator.cpp
|
||||||
|
d3d/d3d_d3d11_allocator.h
|
||||||
|
d3d/d3d_d3d11_allocator.hpp
|
||||||
|
d3d/d3d_dxgi_formats.h
|
||||||
|
d3d/d3d_helpers.cpp
|
||||||
|
d3d/d3d_helpers.hpp
|
||||||
|
)
|
||||||
|
target_link_libraries(
|
||||||
|
aux_d3d
|
||||||
|
PUBLIC
|
||||||
|
aux-includes
|
||||||
|
xrt-interfaces
|
||||||
|
${DXGI_LIBRARY}
|
||||||
|
${D3D11_LIBRARY}
|
||||||
|
WIL::WIL
|
||||||
|
)
|
||||||
|
# needed for format includes
|
||||||
|
target_include_directories(aux_d3d PUBLIC ${Vulkan_INCLUDE_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
# Math library.
|
# Math library.
|
||||||
add_library(
|
add_library(
|
||||||
aux_math STATIC
|
aux_math STATIC
|
||||||
|
|
188
src/xrt/auxiliary/d3d/d3d_d3d11_allocator.cpp
Normal file
188
src/xrt/auxiliary/d3d/d3d_d3d11_allocator.cpp
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
// Copyright 2020-2022, Collabora, Ltd.
|
||||||
|
// SPDX-License-Identifier: BSL-1.0
|
||||||
|
/*!
|
||||||
|
* @file
|
||||||
|
* @brief D3D backed image buffer allocator.
|
||||||
|
* @author Ryan Pavlik <ryan.pavlik@collabora.com>
|
||||||
|
* @ingroup aux_d3d
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "d3d_d3d11_allocator.h"
|
||||||
|
#include "d3d_d3d11_allocator.hpp"
|
||||||
|
|
||||||
|
#include "d3d_dxgi_formats.h"
|
||||||
|
|
||||||
|
#include "util/u_misc.h"
|
||||||
|
#include "util/u_logging.h"
|
||||||
|
#include "util/u_debug.h"
|
||||||
|
#include "util/u_handles.h"
|
||||||
|
|
||||||
|
#include "xrt/xrt_windows.h"
|
||||||
|
|
||||||
|
#include <Unknwn.h>
|
||||||
|
#include <d3d11_3.h>
|
||||||
|
#include <wil/com.h>
|
||||||
|
#include <wil/result.h>
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#define DEFAULT_CATCH(...) \
|
||||||
|
catch (wil::ResultException const &e) \
|
||||||
|
{ \
|
||||||
|
U_LOG_E("Caught exception: %s", e.what()); \
|
||||||
|
return __VA_ARGS__; \
|
||||||
|
} \
|
||||||
|
catch (std::exception const &e) \
|
||||||
|
{ \
|
||||||
|
U_LOG_E("Caught exception: %s", e.what()); \
|
||||||
|
return __VA_ARGS__; \
|
||||||
|
} \
|
||||||
|
catch (...) \
|
||||||
|
{ \
|
||||||
|
U_LOG_E("Caught exception"); \
|
||||||
|
return __VA_ARGS__; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DEBUG_GET_ONCE_LOG_OPTION(d3d11_log, "DXGI_LOG", U_LOGGING_WARN)
|
||||||
|
#define D3DA_TRACE(...) U_LOG_IFL_T(debug_get_log_option_d3d11_log(), __VA_ARGS__)
|
||||||
|
#define D3DA_DEBUG(...) U_LOG_IFL_D(debug_get_log_option_d3d11_log(), __VA_ARGS__)
|
||||||
|
#define D3DA_INFO(...) U_LOG_IFL_I(debug_get_log_option_d3d11_log(), __VA_ARGS__)
|
||||||
|
#define D3DA_WARN(...) U_LOG_IFL_W(debug_get_log_option_d3d11_log(), __VA_ARGS__)
|
||||||
|
#define D3DA_ERROR(...) U_LOG_IFL_E(debug_get_log_option_d3d11_log(), __VA_ARGS__)
|
||||||
|
|
||||||
|
namespace xrt::auxiliary::d3d {
|
||||||
|
|
||||||
|
wil::unique_handle
|
||||||
|
createSharedHandle(const wil::com_ptr<ID3D11Texture2D1> &image)
|
||||||
|
{
|
||||||
|
|
||||||
|
wil::com_ptr<IDXGIResource1> dxgiRes;
|
||||||
|
image.query_to(dxgiRes.put());
|
||||||
|
wil::unique_handle h;
|
||||||
|
THROW_IF_FAILED(dxgiRes->CreateSharedHandle( //
|
||||||
|
nullptr, // pAttributes
|
||||||
|
DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE, // dwAccess
|
||||||
|
nullptr, // lpName
|
||||||
|
h.put())); // pHandle
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
xrt_result_t
|
||||||
|
allocateSharedImages(ID3D11Device5 &device,
|
||||||
|
const xrt_swapchain_create_info &xsci,
|
||||||
|
size_t image_count,
|
||||||
|
bool keyed_mutex,
|
||||||
|
std::vector<wil::com_ptr<ID3D11Texture2D1>> &out_images,
|
||||||
|
std::vector<wil::unique_handle> &out_handles)
|
||||||
|
try {
|
||||||
|
if (0 != (xsci.create & XRT_SWAPCHAIN_CREATE_PROTECTED_CONTENT)) {
|
||||||
|
return XRT_ERROR_SWAPCHAIN_FLAG_VALID_BUT_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != (xsci.create & XRT_SWAPCHAIN_CREATE_STATIC_IMAGE) && image_count > 1) {
|
||||||
|
D3DA_ERROR("Got XRT_SWAPCHAIN_CREATE_STATIC_IMAGE but an image count greater than 1!");
|
||||||
|
return XRT_ERROR_ALLOCATION;
|
||||||
|
}
|
||||||
|
CD3D11_TEXTURE2D_DESC1 desc{d3d_dxgi_format_to_typeless_dxgi((DXGI_FORMAT)xsci.format),
|
||||||
|
xsci.width,
|
||||||
|
xsci.height,
|
||||||
|
xsci.array_size,
|
||||||
|
xsci.mip_count,
|
||||||
|
d3d_convert_usage_bits_to_bind_flags(xsci.bits)};
|
||||||
|
desc.SampleDesc.Count = xsci.sample_count;
|
||||||
|
desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_NTHANDLE;
|
||||||
|
if (keyed_mutex) {
|
||||||
|
desc.MiscFlags |= D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
|
||||||
|
} else {
|
||||||
|
desc.MiscFlags |= D3D11_RESOURCE_MISC_SHARED;
|
||||||
|
}
|
||||||
|
if (desc.Format == 0) {
|
||||||
|
D3DA_ERROR("Invalid format %04" PRIx64 "!", (uint64_t)xsci.format);
|
||||||
|
return XRT_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
if (xsci.face_count == 6) {
|
||||||
|
//! @todo implement instead of erroring out
|
||||||
|
D3DA_ERROR("No idea how to do cube maps in d3d11!");
|
||||||
|
return XRT_ERROR_ALLOCATION;
|
||||||
|
}
|
||||||
|
// Create textures
|
||||||
|
std::vector<wil::com_ptr<ID3D11Texture2D1>> images;
|
||||||
|
for (size_t i = 0; i < image_count; ++i) {
|
||||||
|
wil::com_ptr<ID3D11Texture2D1> tex;
|
||||||
|
THROW_IF_FAILED(device.CreateTexture2D1(&desc, nullptr, tex.put()));
|
||||||
|
images.emplace_back(std::move(tex));
|
||||||
|
}
|
||||||
|
std::vector<wil::unique_handle> handles;
|
||||||
|
handles.reserve(image_count);
|
||||||
|
for (const auto &tex : images) {
|
||||||
|
handles.emplace_back(createSharedHandle(tex));
|
||||||
|
}
|
||||||
|
out_images = std::move(images);
|
||||||
|
out_handles = std::move(handles);
|
||||||
|
return XRT_SUCCESS;
|
||||||
|
}
|
||||||
|
DEFAULT_CATCH(XRT_ERROR_ALLOCATION)
|
||||||
|
|
||||||
|
} // namespace xrt::auxiliary::d3d
|
||||||
|
|
||||||
|
struct d3d11_allocator
|
||||||
|
{
|
||||||
|
struct xrt_image_native_allocator base;
|
||||||
|
wil::com_ptr<ID3D11Device5> device;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static xrt_result_t
|
||||||
|
d3d11_images_allocate(struct xrt_image_native_allocator *xina,
|
||||||
|
const struct xrt_swapchain_create_info *xsci,
|
||||||
|
size_t image_count,
|
||||||
|
struct xrt_image_native *out_images)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
d3d11_allocator *d3da = reinterpret_cast<d3d11_allocator *>(xina);
|
||||||
|
|
||||||
|
std::vector<wil::com_ptr<ID3D11Texture2D1>> images;
|
||||||
|
std::vector<wil::unique_handle> handles;
|
||||||
|
auto result = xrt::auxiliary::d3d::allocateSharedImages(*(d3da->device), *xsci, image_count, false,
|
||||||
|
images, handles);
|
||||||
|
if (XRT_SUCCESS != result) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
// if we made it this far without exceptions, we can safely report back the output.
|
||||||
|
for (size_t i = 0; i < image_count; ++i) {
|
||||||
|
out_images[i].handle = handles[i].release();
|
||||||
|
}
|
||||||
|
return XRT_SUCCESS;
|
||||||
|
}
|
||||||
|
DEFAULT_CATCH(XRT_ERROR_ALLOCATION)
|
||||||
|
}
|
||||||
|
|
||||||
|
static xrt_result_t
|
||||||
|
d3d11_images_free(struct xrt_image_native_allocator *xina, size_t image_count, struct xrt_image_native *images)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < image_count; ++i) {
|
||||||
|
u_graphics_buffer_unref(&(images[i].handle));
|
||||||
|
}
|
||||||
|
return XRT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
d3d11_destroy(struct xrt_image_native_allocator *xina)
|
||||||
|
{
|
||||||
|
d3d11_allocator *d3da = reinterpret_cast<d3d11_allocator *>(xina);
|
||||||
|
delete d3da;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct xrt_image_native_allocator *
|
||||||
|
d3d11_allocator_create(ID3D11Device *device)
|
||||||
|
try {
|
||||||
|
auto ret = std::make_unique<d3d11_allocator>();
|
||||||
|
U_ZERO(&(ret->base));
|
||||||
|
ret->base.images_allocate = d3d11_images_allocate;
|
||||||
|
ret->base.images_free = d3d11_images_free;
|
||||||
|
ret->base.destroy = d3d11_destroy;
|
||||||
|
return &(ret.release()->base);
|
||||||
|
}
|
||||||
|
DEFAULT_CATCH(nullptr)
|
34
src/xrt/auxiliary/d3d/d3d_d3d11_allocator.h
Normal file
34
src/xrt/auxiliary/d3d/d3d_d3d11_allocator.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
// Copyright 2020-2022, Collabora, Ltd.
|
||||||
|
// SPDX-License-Identifier: BSL-1.0
|
||||||
|
/*!
|
||||||
|
* @file
|
||||||
|
* @brief Header exposing factory function for D3D11-backed image
|
||||||
|
buffer allocator.
|
||||||
|
* @author Ryan Pavlik <ryan.pavlik@collabora.com>
|
||||||
|
* @ingroup aux_d3d
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "xrt/xrt_compositor.h"
|
||||||
|
|
||||||
|
#include <d3d11.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a XINA that allocates D3D11 textures.
|
||||||
|
*
|
||||||
|
* @param device A device to allocate the textures with. Be sure it will not be used from other threads while this
|
||||||
|
* allocator allocates.
|
||||||
|
*
|
||||||
|
* @return struct xrt_image_native_allocator*
|
||||||
|
*/
|
||||||
|
struct xrt_image_native_allocator *
|
||||||
|
d3d11_allocator_create(ID3D11Device *device);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
49
src/xrt/auxiliary/d3d/d3d_d3d11_allocator.hpp
Normal file
49
src/xrt/auxiliary/d3d/d3d_d3d11_allocator.hpp
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
// Copyright 2020-2022, Collabora, Ltd.
|
||||||
|
// SPDX-License-Identifier: BSL-1.0
|
||||||
|
/*!
|
||||||
|
* @file
|
||||||
|
* @brief Higher-level D3D11-backed image buffer allocation routine
|
||||||
|
* @author Ryan Pavlik <ryan.pavlik@collabora.com>
|
||||||
|
* @ingroup aux_d3d
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "xrt/xrt_compositor.h"
|
||||||
|
|
||||||
|
#include <Unknwn.h>
|
||||||
|
#include <d3d11_3.h>
|
||||||
|
#include <d3d11_4.h>
|
||||||
|
#include <wil/com.h>
|
||||||
|
#include <wil/resource.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
namespace xrt::auxiliary::d3d {
|
||||||
|
/**
|
||||||
|
* Allocate images (ID3D11Texture2D1) that have a corresponding native handle.
|
||||||
|
*
|
||||||
|
* @param device A D3D device to allocate with.
|
||||||
|
* @param xsci Swapchain create info: note that the format is assumed to be a DXGI_FORMAT (conversion to typeless is
|
||||||
|
* automatic)
|
||||||
|
* @param image_count The number of images to create.
|
||||||
|
* @param keyed_mutex Whether to create images with a shared "keyed mutex" as well
|
||||||
|
* @param[out] out_images A vector that will be cleared and populated with the images.
|
||||||
|
* @param[out] out_handles A vector that will be cleared and populated with the corresponding native handles.
|
||||||
|
*
|
||||||
|
* @return xrt_result_t, one of:
|
||||||
|
* - @ref XRT_SUCCESS
|
||||||
|
* - @ref XRT_ERROR_ALLOCATION
|
||||||
|
* - @ref XRT_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED
|
||||||
|
* - @ref XRT_ERROR_SWAPCHAIN_FLAG_VALID_BUT_UNSUPPORTED
|
||||||
|
* - @ref XRT_ERROR_D3D11
|
||||||
|
*/
|
||||||
|
xrt_result_t
|
||||||
|
allocateSharedImages(ID3D11Device5 &device,
|
||||||
|
const xrt_swapchain_create_info &xsci,
|
||||||
|
size_t image_count,
|
||||||
|
bool keyed_mutex,
|
||||||
|
std::vector<wil::com_ptr<ID3D11Texture2D1>> &out_images,
|
||||||
|
std::vector<wil::unique_handle> &out_handles);
|
||||||
|
}; // namespace xrt::auxiliary::d3d
|
93
src/xrt/auxiliary/d3d/d3d_dxgi_formats.h
Normal file
93
src/xrt/auxiliary/d3d/d3d_dxgi_formats.h
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
// Copyright 2020-2022, Collabora, Ltd.
|
||||||
|
// SPDX-License-Identifier: BSL-1.0
|
||||||
|
/*!
|
||||||
|
* @file
|
||||||
|
* @brief Format conversion for DXGI/D3D.
|
||||||
|
* @author Ryan Pavlik <ryan.pavlik@collabora.com>
|
||||||
|
* @ingroup aux_d3d
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xrt/xrt_windows.h"
|
||||||
|
#include "xrt/xrt_vulkan_includes.h"
|
||||||
|
|
||||||
|
#include <dxgiformat.h>
|
||||||
|
|
||||||
|
static inline DXGI_FORMAT
|
||||||
|
d3d_vk_format_to_dxgi(int64_t format)
|
||||||
|
{
|
||||||
|
switch (format) {
|
||||||
|
case VK_FORMAT_B8G8R8A8_SRGB: return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
|
||||||
|
case VK_FORMAT_B8G8R8A8_UNORM: return DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||||
|
case VK_FORMAT_D16_UNORM: return DXGI_FORMAT_D16_UNORM;
|
||||||
|
case VK_FORMAT_D24_UNORM_S8_UINT: return DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||||
|
case VK_FORMAT_D32_SFLOAT_S8_UINT: return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
|
||||||
|
case VK_FORMAT_D32_SFLOAT: return DXGI_FORMAT_D32_FLOAT;
|
||||||
|
case VK_FORMAT_R16G16B16_SFLOAT: return DXGI_FORMAT_R16G16B16A16_FLOAT; /// @todo OK to just add A?
|
||||||
|
case VK_FORMAT_R16G16B16_UNORM: return DXGI_FORMAT_R16G16B16A16_UNORM; /// @todo OK to just add A?
|
||||||
|
case VK_FORMAT_R16G16B16A16_SFLOAT: return DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||||
|
case VK_FORMAT_R16G16B16A16_UNORM: return DXGI_FORMAT_R16G16B16A16_UNORM;
|
||||||
|
case VK_FORMAT_R8G8B8A8_SRGB: return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||||
|
case VK_FORMAT_R8G8B8A8_UNORM: return DXGI_FORMAT_R8G8B8A8_UNORM; // Should not be used, colour precision.
|
||||||
|
|
||||||
|
case VK_FORMAT_X8_D24_UNORM_PACK32: /// @todo DXGI_FORMAT_D24_UNORM_S8_UINT ?
|
||||||
|
return (DXGI_FORMAT)0;
|
||||||
|
case VK_FORMAT_A2B10G10R10_UNORM_PACK32: /// @todo DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM ?
|
||||||
|
return (DXGI_FORMAT)0;
|
||||||
|
|
||||||
|
default: return (DXGI_FORMAT)0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static inline DXGI_FORMAT
|
||||||
|
d3d_dxgi_format_to_typeless_dxgi(DXGI_FORMAT format)
|
||||||
|
{
|
||||||
|
switch (format) {
|
||||||
|
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8A8_TYPELESS;
|
||||||
|
case DXGI_FORMAT_B8G8R8A8_UNORM: return DXGI_FORMAT_B8G8R8A8_TYPELESS;
|
||||||
|
case DXGI_FORMAT_D16_UNORM: return DXGI_FORMAT_R16_TYPELESS;
|
||||||
|
// case DXGI_FORMAT_D24_UNORM_S8_UINT: return DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||||
|
// case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
|
||||||
|
case DXGI_FORMAT_D32_FLOAT: return DXGI_FORMAT_R32_TYPELESS;
|
||||||
|
case DXGI_FORMAT_R16G16B16A16_FLOAT: return DXGI_FORMAT_R16G16B16A16_TYPELESS;
|
||||||
|
case DXGI_FORMAT_R16G16B16A16_UNORM: return DXGI_FORMAT_R16G16B16A16_TYPELESS;
|
||||||
|
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: return DXGI_FORMAT_R8G8B8A8_TYPELESS;
|
||||||
|
case DXGI_FORMAT_R8G8B8A8_UNORM: return DXGI_FORMAT_R8G8B8A8_TYPELESS;
|
||||||
|
default: return format;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int64_t
|
||||||
|
d3d_dxgi_format_to_vk(DXGI_FORMAT format)
|
||||||
|
{
|
||||||
|
switch (format) {
|
||||||
|
case DXGI_FORMAT_R8G8B8A8_UNORM: return VK_FORMAT_R8G8B8A8_UNORM; // Should not be used, colour precision.
|
||||||
|
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: return VK_FORMAT_R8G8B8A8_SRGB;
|
||||||
|
case DXGI_FORMAT_B8G8R8A8_UNORM: return VK_FORMAT_B8G8R8A8_UNORM;
|
||||||
|
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: return VK_FORMAT_B8G8R8A8_SRGB;
|
||||||
|
case DXGI_FORMAT_R16G16B16A16_UNORM: return VK_FORMAT_R16G16B16A16_UNORM;
|
||||||
|
case DXGI_FORMAT_R16G16B16A16_SNORM: return VK_FORMAT_R16G16B16A16_SFLOAT;
|
||||||
|
case DXGI_FORMAT_D16_UNORM: return VK_FORMAT_D16_UNORM;
|
||||||
|
case DXGI_FORMAT_D32_FLOAT: return VK_FORMAT_D32_SFLOAT;
|
||||||
|
case DXGI_FORMAT_D24_UNORM_S8_UINT: return VK_FORMAT_D24_UNORM_S8_UINT;
|
||||||
|
case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: return VK_FORMAT_D32_SFLOAT_S8_UINT;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline UINT
|
||||||
|
d3d_convert_usage_bits_to_bind_flags(enum xrt_swapchain_usage_bits xsub)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
if ((xsub & XRT_SWAPCHAIN_USAGE_COLOR) != 0) {
|
||||||
|
ret |= D3D11_BIND_RENDER_TARGET;
|
||||||
|
}
|
||||||
|
if ((xsub & XRT_SWAPCHAIN_USAGE_DEPTH_STENCIL) != 0) {
|
||||||
|
ret |= D3D11_BIND_DEPTH_STENCIL;
|
||||||
|
}
|
||||||
|
if ((xsub & XRT_SWAPCHAIN_USAGE_UNORDERED_ACCESS) != 0) {
|
||||||
|
ret |= D3D11_BIND_UNORDERED_ACCESS;
|
||||||
|
}
|
||||||
|
if ((xsub & XRT_SWAPCHAIN_USAGE_SAMPLED) != 0) {
|
||||||
|
ret |= D3D11_BIND_SHADER_RESOURCE;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
144
src/xrt/auxiliary/d3d/d3d_helpers.cpp
Normal file
144
src/xrt/auxiliary/d3d/d3d_helpers.cpp
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
// Copyright 2022, Collabora, Ltd.
|
||||||
|
// SPDX-License-Identifier: BSL-1.0
|
||||||
|
/*!
|
||||||
|
* @file
|
||||||
|
* @brief Misc D3D11 helper routines.
|
||||||
|
* @author Ryan Pavlik <ryan.pavlik@collabora.com>
|
||||||
|
* @ingroup aux_d3d
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "d3d_helpers.hpp"
|
||||||
|
|
||||||
|
#include "util/u_logging.h"
|
||||||
|
|
||||||
|
#include <dxgi1_6.h>
|
||||||
|
#include <d3d11_4.h>
|
||||||
|
#include <wil/com.h>
|
||||||
|
#include <wil/result.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace xrt::auxiliary::d3d {
|
||||||
|
template <typename T>
|
||||||
|
static wil::com_ptr<T>
|
||||||
|
try_create_dxgi_factory()
|
||||||
|
{
|
||||||
|
|
||||||
|
wil::com_ptr<T> factory;
|
||||||
|
LOG_IF_FAILED(CreateDXGIFactory1(__uuidof(T), factory.put_void()));
|
||||||
|
|
||||||
|
return factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
wil::com_ptr<IDXGIAdapter>
|
||||||
|
getAdapterByIndex(uint16_t index, u_logging_level log_level)
|
||||||
|
{
|
||||||
|
|
||||||
|
wil::com_ptr<IDXGIAdapter> ret;
|
||||||
|
auto factory6 = try_create_dxgi_factory<IDXGIFactory6>();
|
||||||
|
if (factory6 != nullptr) {
|
||||||
|
U_LOG_IFL_I(log_level, "Using IDXGIFactory6::EnumAdapterByGpuPreference to select adapter to use.");
|
||||||
|
LOG_IF_FAILED(factory6->EnumAdapterByGpuPreference(index, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE,
|
||||||
|
__uuidof(IDXGIAdapter), ret.put_void()));
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
// Otherwise fall through to the other factory
|
||||||
|
}
|
||||||
|
|
||||||
|
auto factory = try_create_dxgi_factory<IDXGIFactory>();
|
||||||
|
if (factory != nullptr) {
|
||||||
|
U_LOG_IFL_I(log_level,
|
||||||
|
"IDXGIFactory6 unavailable, using IDXGIFactory::EnumAdapters to select adapter to use.");
|
||||||
|
LOG_IF_FAILED(factory->EnumAdapters(index, ret.put()));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
wil::com_ptr<IDXGIAdapter>
|
||||||
|
getAdapterByLUID(const xrt_luid_t &luid, u_logging_level log_level)
|
||||||
|
{
|
||||||
|
LUID realLuid = reinterpret_cast<const LUID &>(luid);
|
||||||
|
wil::com_ptr<IDXGIAdapter> ret;
|
||||||
|
auto factory4 = try_create_dxgi_factory<IDXGIFactory4>();
|
||||||
|
if (factory4 != nullptr) {
|
||||||
|
U_LOG_IFL_I(log_level, "Using IDXGIFactory4::EnumAdapterByLuid to select adapter to use.");
|
||||||
|
LOG_IF_FAILED(factory4->EnumAdapterByLuid(realLuid, __uuidof(IDXGIAdapter), ret.put_void()));
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
// Otherwise fall through to the other factory
|
||||||
|
}
|
||||||
|
|
||||||
|
// This basically is manual implementation of EnumAdapterByLuid
|
||||||
|
auto factory1 = try_create_dxgi_factory<IDXGIFactory1>();
|
||||||
|
if (factory1 != nullptr) {
|
||||||
|
U_LOG_IFL_I(log_level,
|
||||||
|
"IDXGIFactory6 unavailable, using IDXGIFactory1::EnumAdapters1 to select adapter to use.");
|
||||||
|
for (unsigned int i = 0;; ++i) {
|
||||||
|
|
||||||
|
wil::com_ptr<IDXGIAdapter1> adapter;
|
||||||
|
if (!SUCCEEDED(factory1->EnumAdapters1(i, adapter.put()))) {
|
||||||
|
U_LOG_IFL_W(log_level,
|
||||||
|
"Ran out of adapters using IDXGIFactory1::EnumAdapters1 before finding a "
|
||||||
|
"matching LUID.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DXGI_ADAPTER_DESC1 desc{};
|
||||||
|
if (!SUCCEEDED(adapter->GetDesc1(&desc))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (realLuid.HighPart == desc.AdapterLuid.HighPart &&
|
||||||
|
realLuid.LowPart == desc.AdapterLuid.LowPart) {
|
||||||
|
ret = adapter;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT
|
||||||
|
tryCreateD3D11Device(const wil::com_ptr<IDXGIAdapter> &adapter,
|
||||||
|
D3D_DRIVER_TYPE driver_type,
|
||||||
|
unsigned int creation_flags,
|
||||||
|
const std::vector<D3D_FEATURE_LEVEL> &feature_levels,
|
||||||
|
wil::com_ptr<ID3D11Device> &out_device,
|
||||||
|
wil::com_ptr<ID3D11DeviceContext> &out_context)
|
||||||
|
{
|
||||||
|
return D3D11CreateDevice(wil::com_raw_ptr(adapter), driver_type, nullptr, creation_flags, feature_levels.data(),
|
||||||
|
(UINT)feature_levels.size(), D3D11_SDK_VERSION, out_device.put(), nullptr,
|
||||||
|
out_context.put());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<wil::com_ptr<ID3D11Device>, wil::com_ptr<ID3D11DeviceContext>>
|
||||||
|
createD3D11Device(const wil::com_ptr<IDXGIAdapter> &adapter, u_logging_level log_level)
|
||||||
|
{
|
||||||
|
D3D_DRIVER_TYPE driver_type = D3D_DRIVER_TYPE_HARDWARE;
|
||||||
|
if (adapter) {
|
||||||
|
// needed if we pass an adapter.
|
||||||
|
U_LOG_IFL_D(log_level, "Adapter provided.");
|
||||||
|
driver_type = D3D_DRIVER_TYPE_UNKNOWN;
|
||||||
|
}
|
||||||
|
unsigned int creation_flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
|
||||||
|
#ifndef NDEBUG
|
||||||
|
U_LOG_IFL_D(log_level, "Will attempt to create our device using the debug layer.");
|
||||||
|
creation_flags |= D3D11_CREATE_DEVICE_DEBUG;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::vector<D3D_FEATURE_LEVEL> feature_levels{D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0};
|
||||||
|
wil::com_ptr<ID3D11Device> device;
|
||||||
|
wil::com_ptr<ID3D11DeviceContext> context;
|
||||||
|
HRESULT hr = tryCreateD3D11Device(adapter, driver_type, creation_flags, feature_levels, device, context);
|
||||||
|
#ifndef NDEBUG
|
||||||
|
if (hr == DXGI_ERROR_SDK_COMPONENT_MISSING) {
|
||||||
|
U_LOG_IFL_D(log_level, "Removing the debug layer flag: not successful.");
|
||||||
|
creation_flags &= ~D3D11_CREATE_DEVICE_DEBUG;
|
||||||
|
hr = tryCreateD3D11Device(adapter, driver_type, creation_flags, feature_levels, device, context);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
THROW_IF_FAILED(hr);
|
||||||
|
return {device, context};
|
||||||
|
}
|
||||||
|
} // namespace xrt::auxiliary::d3d
|
64
src/xrt/auxiliary/d3d/d3d_helpers.hpp
Normal file
64
src/xrt/auxiliary/d3d/d3d_helpers.hpp
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
// Copyright 2022, Collabora, Ltd.
|
||||||
|
// SPDX-License-Identifier: BSL-1.0
|
||||||
|
/*!
|
||||||
|
* @file
|
||||||
|
* @brief Misc D3D11 helper routines.
|
||||||
|
* @author Ryan Pavlik <ryan.pavlik@collabora.com>
|
||||||
|
* @ingroup aux_d3d
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "xrt/xrt_defines.h"
|
||||||
|
#include "xrt/xrt_compositor.h"
|
||||||
|
|
||||||
|
#include "util/u_logging.h"
|
||||||
|
|
||||||
|
#include <dxgi.h>
|
||||||
|
#include <d3d11.h>
|
||||||
|
#include <wil/com.h>
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace xrt::auxiliary::d3d {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a DXGI Adapter, using our priorities.
|
||||||
|
*
|
||||||
|
* We try to use IDXGIFactory6::EnumAdapterByGpuPreference preferring HIGH_PERFORMANCE, if it's available
|
||||||
|
*
|
||||||
|
* @param index The requested adapter index
|
||||||
|
* @param log_level The level to compare against for internal log messages
|
||||||
|
*
|
||||||
|
* @throws wil::ResultException in case of error
|
||||||
|
*
|
||||||
|
* @return wil::com_ptr<IDXGIAdapter>
|
||||||
|
*/
|
||||||
|
wil::com_ptr<IDXGIAdapter>
|
||||||
|
getAdapterByIndex(uint16_t index, u_logging_level log_level = U_LOGGING_INFO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a DXGI Adapter, for the provided LUID.
|
||||||
|
*
|
||||||
|
* @param luid The requested adapter luid
|
||||||
|
* @param log_level The level to compare against for internal log messages
|
||||||
|
* @throws wil::ResultException in case of error
|
||||||
|
*
|
||||||
|
* @return wil::com_ptr<IDXGIAdapter>
|
||||||
|
*/
|
||||||
|
wil::com_ptr<IDXGIAdapter>
|
||||||
|
getAdapterByLUID(const xrt_luid_t &luid, u_logging_level log_level = U_LOGGING_INFO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a D3D11 Device object
|
||||||
|
*
|
||||||
|
* @param adapter optional: adapter to create on.
|
||||||
|
* @param log_level The level to compare against for internal log messages
|
||||||
|
*
|
||||||
|
* @throws wil::ResultException in case of error
|
||||||
|
*
|
||||||
|
* @return std::pair<wil::com_ptr<ID3D11Device>, wil::com_ptr<ID3D11DeviceContext>>
|
||||||
|
*/
|
||||||
|
std::pair<wil::com_ptr<ID3D11Device>, wil::com_ptr<ID3D11DeviceContext>>
|
||||||
|
createD3D11Device(const wil::com_ptr<IDXGIAdapter> &adapter = nullptr, u_logging_level log_level = U_LOGGING_INFO);
|
||||||
|
} // namespace xrt::auxiliary::d3d
|
Loading…
Reference in a new issue