a/d3d: Add some d3d12 features

This commit is contained in:
Ryan Pavlik 2022-05-24 18:02:31 -05:00
parent 2dc5083543
commit 576b158a83
16 changed files with 654 additions and 108 deletions

View file

@ -18,7 +18,7 @@ if(XRT_HAVE_OPENGL OR XRT_HAVE_OPENGLES)
endif() endif()
# Direct3D library # Direct3D library
if(XRT_HAVE_D3D11 AND XRT_HAVE_VULKAN) if(XRT_HAVE_D3D11 OR XRT_HAVE_D3D12)
add_subdirectory(d3d) add_subdirectory(d3d)
endif() endif()

View file

@ -1,7 +1,7 @@
# Copyright 2019-2022, Collabora, Ltd. # Copyright 2019-2022, Collabora, Ltd.
# SPDX-License-Identifier: BSL-1.0 # SPDX-License-Identifier: BSL-1.0
add_library(aux_d3d STATIC d3d_dxgi_formats.h d3d_helpers.cpp d3d_helpers.hpp) add_library(aux_d3d STATIC d3d_dxgi_formats.h d3d_dxgi_helpers.cpp d3d_dxgi_helpers.hpp)
target_link_libraries(aux_d3d PUBLIC aux-includes xrt-interfaces ${DXGI_LIBRARY} WIL::WIL) target_link_libraries(aux_d3d PUBLIC aux-includes xrt-interfaces ${DXGI_LIBRARY} WIL::WIL)
# needed for format includes # needed for format includes
@ -11,12 +11,29 @@ if(XRT_HAVE_D3D11)
target_sources( target_sources(
aux_d3d aux_d3d
PRIVATE PRIVATE
d3d_d3d11_bits.h
d3d_d3d11_allocator.cpp d3d_d3d11_allocator.cpp
d3d_d3d11_allocator.h d3d_d3d11_allocator.h
d3d_d3d11_allocator.hpp d3d_d3d11_allocator.hpp
d3d_d3d11_bits.h
d3d_d3d11_fence.cpp d3d_d3d11_fence.cpp
d3d_d3d11_fence.hpp d3d_d3d11_fence.hpp
d3d_d3d11_helpers.cpp
d3d_d3d11_helpers.hpp
) )
target_link_libraries(aux_d3d PUBLIC ${D3D11_LIBRARY}) target_link_libraries(aux_d3d PUBLIC ${D3D11_LIBRARY})
endif() endif()
if(XRT_HAVE_D3D12)
target_sources(
aux_d3d
PRIVATE
d3d_d3d12_bits.h
# d3d_d3d12_allocator.cpp
# d3d_d3d12_allocator.hpp
d3d_d3d12_fence.cpp
d3d_d3d12_fence.hpp
d3d_d3d12_helpers.cpp
d3d_d3d12_helpers.hpp
)
target_link_libraries(aux_d3d PUBLIC ${D3D12_LIBRARY})
endif()

View 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
*/
#include "d3d_d3d11_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::d3d11 {
HRESULT
tryCreateDevice(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>>
createDevice(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 = tryCreateDevice(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 = tryCreateDevice(adapter, driver_type, creation_flags, feature_levels, device, context);
}
#endif
THROW_IF_FAILED(hr);
return {device, context};
}
} // namespace xrt::auxiliary::d3d::d3d11

View file

@ -0,0 +1,39 @@
// Copyright 2022, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief Misc D3D11/12 helper routines.
* @author Ryan Pavlik <ryan.pavlik@collabora.com>
* @ingroup aux_d3d
*/
#pragma once
#include "xrt/xrt_defines.h"
#include "util/u_logging.h"
#include <dxgi.h>
#include <d3d11.h>
#include <wil/com.h>
#include <utility>
namespace xrt::auxiliary::d3d::d3d11 {
/**
* @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>>
createDevice(const wil::com_ptr<IDXGIAdapter> &adapter = nullptr, u_logging_level log_level = U_LOGGING_INFO);
} // namespace xrt::auxiliary::d3d::d3d11

View file

@ -0,0 +1,104 @@
// Copyright 2020-2022, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief Usage bits for D3D12.
* @author Ryan Pavlik <ryan.pavlik@collabora.com>
* @ingroup aux_d3d
*/
#pragma once
#include "xrt/xrt_compositor.h"
#include "xrt/xrt_windows.h"
#include "xrt/xrt_config_have.h"
#include "d3d12.h"
#include <assert.h>
#ifdef XRT_HAVE_D3D12
#ifdef __cplusplus
extern "C" {
#endif
static inline D3D12_RESOURCE_FLAGS
d3d_convert_usage_bits_to_d3d12_resource_flags(enum xrt_swapchain_usage_bits xsub)
{
int ret = 0;
if ((xsub & XRT_SWAPCHAIN_USAGE_COLOR) != 0) {
ret |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
}
if ((xsub & XRT_SWAPCHAIN_USAGE_DEPTH_STENCIL) != 0) {
ret |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
}
if ((xsub & XRT_SWAPCHAIN_USAGE_UNORDERED_ACCESS) != 0) {
ret |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
}
// if this is omitted, D3D12 asks to add a bit to **deny** shader access.
// it's a bold api design strategy Cotton, let's see if it pays off for them. ;)
if ((xsub & XRT_SWAPCHAIN_USAGE_SAMPLED) == 0) {
// per https://docs.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_resource_flags
// this also depends on depth stencil
assert((xsub & XRT_SWAPCHAIN_USAGE_DEPTH_STENCIL) != 0);
ret |= D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE;
}
return (D3D12_RESOURCE_FLAGS)ret;
}
/**
* Given swapchain usage bits, determine the resource usage state expected by the app
*
* @param xsub
* @return D3D12_RESOURCE_STATES
*/
static inline D3D12_RESOURCE_STATES
d3d_convert_usage_bits_to_d3d12_app_resource_state(enum xrt_swapchain_usage_bits xsub)
{
D3D12_RESOURCE_STATES state = D3D12_RESOURCE_STATES(0);
if ((xsub & XRT_SWAPCHAIN_USAGE_UNORDERED_ACCESS) != 0) {
state |= D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
}
if ((xsub & XRT_SWAPCHAIN_USAGE_COLOR) != 0) {
// since we are treating these as mutually exclusive
assert((xsub & XRT_SWAPCHAIN_USAGE_DEPTH_STENCIL) == 0);
state |= D3D12_RESOURCE_STATE_RENDER_TARGET;
}
if ((xsub & XRT_SWAPCHAIN_USAGE_DEPTH_STENCIL) != 0) {
state |= D3D12_RESOURCE_STATE_DEPTH_WRITE;
}
return state;
}
/**
* Given swapchain usage bits, determine the resource usage state expected by the compositor
*
* @param xsub
* @return D3D12_RESOURCE_STATES
*/
static inline D3D12_RESOURCE_STATES
d3d_convert_usage_bits_to_d3d12_compositor_resource_state(enum xrt_swapchain_usage_bits xsub)
{
D3D12_RESOURCE_STATES state = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
if ((xsub & XRT_SWAPCHAIN_USAGE_UNORDERED_ACCESS) != 0) {
state |= D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
}
// if ((xsub & XRT_SWAPCHAIN_USAGE_COLOR) != 0) {
// // since we are treating these as mutually exclusive
// assert((xsub & XRT_SWAPCHAIN_USAGE_DEPTH_STENCIL) == 0);
// state |= D3D12_RESOURCE_STATE_RENDER_TARGET;
// }
if ((xsub & XRT_SWAPCHAIN_USAGE_DEPTH_STENCIL) != 0) {
state |= D3D12_RESOURCE_STATE_DEPTH_READ;
}
return state;
}
#ifdef __cplusplus
}
#endif
#endif // XRT_HAVE_D3D12

View file

@ -0,0 +1,117 @@
// Copyright 2020-2022, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief D3D12-backed fence (timeline semaphore) creation routine
* @author Ryan Pavlik <ryan.pavlik@collabora.com>
* @ingroup aux_d3d
*/
#include "d3d_d3d12_fence.hpp"
#include "util/u_misc.h"
#include "util/u_logging.h"
#include "util/u_debug.h"
#include "util/u_handles.h"
#include "util/u_time.h"
#include "xrt/xrt_windows.h"
#include <Unknwn.h>
#include <d3d12.h>
#include <dxgi1_2.h>
#include <wil/com.h>
#include <wil/result.h>
#include <inttypes.h>
#include <memory>
using namespace std::chrono;
#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__; \
}
namespace xrt::auxiliary::d3d::d3d12 {
xrt_result_t
createSharedFence(ID3D12Device &device,
bool share_cross_adapter,
xrt_graphics_sync_handle_t *out_handle,
wil::com_ptr<ID3D12Fence> &out_d3dfence)
try {
/*
* Create the fence.
*/
D3D12_FENCE_FLAGS flags = share_cross_adapter ? D3D12_FENCE_FLAG_SHARED_CROSS_ADAPTER : D3D12_FENCE_FLAG_SHARED;
wil::com_ptr<ID3D12Fence> fence;
THROW_IF_FAILED(device.CreateFence( //
0, // InitialValue
flags, // Flags
__uuidof(ID3D12Fence), // ReturnedInterface
fence.put_void())); // ppFence
/*
* Create the handle to be shared.
*/
DWORD access_flags = DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE;
wil::unique_handle handle;
THROW_IF_FAILED(device.CreateSharedHandle( //
fence.get(), // pOjbect
nullptr, // pAttributes
access_flags, // dwAccess
nullptr, // lpName
handle.put())); // pHandle
/*
* Done.
*/
*out_handle = handle.release();
out_d3dfence = std::move(fence);
return XRT_SUCCESS;
}
DEFAULT_CATCH(XRT_ERROR_ALLOCATION)
xrt_result_t
waitOnFenceWithTimeout(wil::com_ptr<ID3D12Fence> fence,
wil::unique_event_nothrow &event,
uint64_t value,
std::chrono::milliseconds timeout_ms)
{
DWORD dwTimeout = duration_cast<duration<DWORD, std::milli>>(timeout_ms).count();
// Have to use this instead of ID3D12DeviceContext4::Wait because the latter has no timeout
// parameter.
fence->SetEventOnCompletion(value, event.get());
if (value <= fence->GetCompletedValue()) {
// oh we already reached this value.
return XRT_SUCCESS;
}
if (event.wait(dwTimeout)) {
return XRT_SUCCESS;
}
return XRT_TIMEOUT;
}
} // namespace xrt::auxiliary::d3d::d3d12

View file

@ -0,0 +1,59 @@
// Copyright 2020-2022, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief D3D12-backed fence (timeline semaphore) creation routine.
* @author Ryan Pavlik <ryan.pavlik@collabora.com>
* @ingroup aux_d3d
*/
#pragma once
#include "xrt/xrt_compositor.h"
#include <Unknwn.h>
#include <d3d12.h>
#include <wil/com.h>
#include <chrono>
namespace xrt::auxiliary::d3d::d3d12 {
/**
* Allocate a fence (ID3D12Fence) that has a corresponding native handle.
*
* D3D fences are roughly equivalent to Vulkan timeline semaphores.
*
* @param device A D3D device to allocate with.
* @param share_cross_adapter True if the fence should be shared across adapters, not only across ID3D12Device
* instances.
* @param[out] out_handle A graphics sync handle to populate
* @param[out] out_d3dfence A COM pointer to the D3D12 fence to populate
*
* @return xrt_result_t, one of:
* - @ref XRT_SUCCESS
* - @ref XRT_ERROR_ALLOCATION
* - @ref XRT_ERROR_D3D12
*/
xrt_result_t
createSharedFence(ID3D12Device &device,
bool share_cross_adapter,
xrt_graphics_sync_handle_t *out_handle,
wil::com_ptr<ID3D12Fence> &out_d3dfence);
/*!
* Wait for a fence to be signaled with value equal or greater than @p value within @p timeout_ns nanoseconds.
*
* @param fence The fence to wait on.
* @param event An event to use to wait. Please use a dedicated event for a single thread's calls to this function.
* @param value The desired fence value
* @param timeout_ms After this long, we may return early with @ref XRT_TIMEOUT even before the fence
* reaches the value.
*/
xrt_result_t
waitOnFenceWithTimeout(wil::com_ptr<ID3D12Fence> fence,
wil::unique_event_nothrow &event,
uint64_t value,
std::chrono::milliseconds timeout_ms);
}; // namespace xrt::auxiliary::d3d::d3d12

View file

@ -0,0 +1,108 @@
// Copyright 2022, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief Misc D3D12 helper routines.
* @author Ryan Pavlik <ryan.pavlik@collabora.com>
* @ingroup aux_d3d
*/
#include "d3d_d3d12_helpers.hpp"
#include "d3d_d3d12_bits.h"
#include "util/u_logging.h"
#include <d3d12.h>
#include <wil/com.h>
#include <wil/result.h>
#include <vector>
#include <stdexcept>
namespace xrt::auxiliary::d3d::d3d12 {
wil::com_ptr<ID3D12Device>
createDevice(const wil::com_ptr<IDXGIAdapter> &adapter, u_logging_level log_level)
{
if (adapter) {
U_LOG_IFL_D(log_level, "Adapter provided.");
}
wil::com_ptr<ID3D12Device> device;
THROW_IF_FAILED(
D3D12CreateDevice(wil::com_raw_ptr(adapter), D3D_FEATURE_LEVEL_11_1, IID_PPV_ARGS(device.put())));
return device;
}
HRESULT
createCommandLists(ID3D12Device &device,
ID3D12CommandAllocator &command_allocator,
ID3D12Resource &resource,
enum xrt_swapchain_usage_bits bits,
wil::com_ptr<ID3D12CommandList> out_acquire_command_list,
wil::com_ptr<ID3D12CommandList> out_release_command_list)
{
//! @todo do we need to set queue access somehow?
wil::com_ptr<ID3D12GraphicsCommandList> acquireCommandList;
RETURN_IF_FAILED(device.CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, &command_allocator, nullptr,
IID_PPV_ARGS(acquireCommandList.put())));
D3D12_RESOURCE_STATES appResourceState = d3d_convert_usage_bits_to_d3d12_app_resource_state(bits);
/// @todo No idea if this is right, might depend on whether it's the compute or graphics compositor!
D3D12_RESOURCE_STATES compositorResourceState = D3D12_RESOURCE_STATE_GENERIC_READ;
D3D12_RESOURCE_BARRIER barrier{};
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier.Transition.pResource = &resource;
barrier.Transition.StateBefore = compositorResourceState;
barrier.Transition.StateAfter = appResourceState;
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
acquireCommandList->ResourceBarrier(1, &barrier);
RETURN_IF_FAILED(acquireCommandList->Close());
wil::com_ptr<ID3D12GraphicsCommandList> releaseCommandList;
RETURN_IF_FAILED(device.CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, &command_allocator, nullptr,
IID_PPV_ARGS(releaseCommandList.put())));
barrier.Transition.StateBefore = appResourceState;
barrier.Transition.StateAfter = compositorResourceState;
releaseCommandList->ResourceBarrier(1, &barrier);
RETURN_IF_FAILED(releaseCommandList->Close());
out_acquire_command_list = std::move(acquireCommandList);
out_release_command_list = std::move(releaseCommandList);
return S_OK;
}
wil::com_ptr<ID3D12Resource>
importImage(ID3D12Device &device, HANDLE h)
{
wil::com_ptr<ID3D12Resource> tex;
if (h == nullptr) {
throw std::logic_error("Cannot import empty handle");
}
THROW_IF_FAILED(device.OpenSharedHandle(h, IID_PPV_ARGS(tex.put())));
return tex;
}
wil::com_ptr<ID3D12Fence1>
importFence(ID3D12Device &device, HANDLE h)
{
wil::com_ptr<ID3D12Fence1> fence;
if (h == nullptr) {
throw std::logic_error("Cannot import empty handle");
}
THROW_IF_FAILED(device.OpenSharedHandle(h, IID_PPV_ARGS(fence.put())));
return fence;
}
} // namespace xrt::auxiliary::d3d::d3d12

View file

@ -0,0 +1,81 @@
// Copyright 2022, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief Misc D3D12 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 <d3d12.h>
#include <wil/com.h>
#include <utility>
namespace xrt::auxiliary::d3d::d3d12 {
/**
* @brief Create a D3D12 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 wil::com_ptr<ID3D12Device>
*/
wil::com_ptr<ID3D12Device>
createDevice(const wil::com_ptr<IDXGIAdapter> &adapter = nullptr, u_logging_level log_level = U_LOGGING_INFO);
/**
* @brief Create command lists for a resource transitioning to/from app control
*
* @param device D3D12 device
* @param command_allocator
* @param resource image
* @param[out] out_acquire_command_list Command list to populate for xrAcquireSwapchainImage
* @param[out] out_release_command_list Command list to populate for xrReleaseSwapchainImage
* @return HRESULT
*/
HRESULT
createCommandLists(ID3D12Device &device,
ID3D12CommandAllocator &command_allocator,
ID3D12Resource &resource,
enum xrt_swapchain_usage_bits bits,
wil::com_ptr<ID3D12CommandList> out_acquire_command_list,
wil::com_ptr<ID3D12CommandList> out_release_command_list);
/**
* Imports an image into D3D12 from a handle.
*
* @param device D3D12 device
* @param h handle corresponding to a shared image
*
* @throw std::logic_error if the handle is invalid, wil exceptions if the operation failed.
*/
wil::com_ptr<ID3D12Resource>
importImage(ID3D12Device &device, HANDLE h);
/**
* Imports a fence into D3D12 from a handle.
*
* @param device D3D12 device
* @param h handle corresponding to a shared fence
*
* @throw std::logic_error if the handle is invalid, wil exceptions if the operation failed.
*/
wil::com_ptr<ID3D12Fence1>
importFence(ID3D12Device &device, HANDLE h);
} // namespace xrt::auxiliary::d3d::d3d12

View file

@ -7,12 +7,11 @@
* @ingroup aux_d3d * @ingroup aux_d3d
*/ */
#include "d3d_helpers.hpp" #include "d3d_d3d11_helpers.hpp"
#include "util/u_logging.h" #include "util/u_logging.h"
#include <dxgi1_6.h> #include <dxgi1_6.h>
#include <d3d11_4.h>
#include <wil/com.h> #include <wil/com.h>
#include <wil/result.h> #include <wil/result.h>
@ -98,50 +97,4 @@ getAdapterByLUID(const xrt_luid_t &luid, u_logging_level log_level)
} }
return ret; return ret;
} }
#ifdef XRT_HAVE_D3D11
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};
}
#endif // XRT_HAVE_D3D11
} // namespace xrt::auxiliary::d3d } // namespace xrt::auxiliary::d3d

View file

@ -2,7 +2,7 @@
// SPDX-License-Identifier: BSL-1.0 // SPDX-License-Identifier: BSL-1.0
/*! /*!
* @file * @file
* @brief Misc D3D11 helper routines. * @brief Misc D3D11/12 helper routines.
* @author Ryan Pavlik <ryan.pavlik@collabora.com> * @author Ryan Pavlik <ryan.pavlik@collabora.com>
* @ingroup aux_d3d * @ingroup aux_d3d
*/ */
@ -10,17 +10,10 @@
#pragma once #pragma once
#include "xrt/xrt_defines.h" #include "xrt/xrt_defines.h"
#include "xrt/xrt_compositor.h"
#include "xrt/xrt_config_have.h"
#include "util/u_logging.h" #include "util/u_logging.h"
#include <dxgi.h> #include <dxgi.h>
#ifdef XRT_HAVE_D3D11
#include <d3d11.h>
#endif
#include <wil/com.h> #include <wil/com.h>
#include <utility> #include <utility>
@ -55,19 +48,4 @@ getAdapterByIndex(uint16_t index, u_logging_level log_level = U_LOGGING_INFO);
wil::com_ptr<IDXGIAdapter> wil::com_ptr<IDXGIAdapter>
getAdapterByLUID(const xrt_luid_t &luid, u_logging_level log_level = U_LOGGING_INFO); getAdapterByLUID(const xrt_luid_t &luid, u_logging_level log_level = U_LOGGING_INFO);
#ifdef XRT_HAVE_D3D11
/**
* @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);
#endif // XRT_HAVE_D3D11
} // namespace xrt::auxiliary::d3d } // namespace xrt::auxiliary::d3d

View file

@ -863,7 +863,7 @@ try {
// Now, try to get an equivalent device of our own // Now, try to get an equivalent device of our own
wil::com_ptr<ID3D11Device> our_dev; wil::com_ptr<ID3D11Device> our_dev;
wil::com_ptr<ID3D11DeviceContext> our_context; wil::com_ptr<ID3D11DeviceContext> our_context;
std::tie(our_dev, our_context) = xrt::auxiliary::d3d::createD3D11Device(adapter, c->log_level); std::tie(our_dev, our_context) = xrt::auxiliary::d3d::d3d11::createDevice(adapter, c->log_level);
our_dev.query_to(c->comp_device.put()); our_dev.query_to(c->comp_device.put());
our_context.query_to(c->comp_context.put()); our_context.query_to(c->comp_context.put());
} }

View file

@ -27,8 +27,10 @@ set(tests
tests_pose tests_pose
) )
if(XRT_HAVE_D3D11) if(XRT_HAVE_D3D11)
list(APPEND tests tests_aux_d3d tests_comp_client_d3d11) list(APPEND tests tests_aux_d3d_d3d11 tests_comp_client_d3d11)
endif() endif()
# if(XRT_HAVE_D3D12)
# endif()
if(XRT_HAVE_VULKAN) if(XRT_HAVE_VULKAN)
list(APPEND tests tests_comp_client_vulkan) list(APPEND tests tests_comp_client_vulkan)
endif() endif()
@ -59,10 +61,14 @@ if(XRT_BUILD_DRIVER_HANDTRACKING)
endif() endif()
if(XRT_HAVE_D3D11) if(XRT_HAVE_D3D11)
target_link_libraries(tests_aux_d3d PRIVATE aux_d3d) target_link_libraries(tests_aux_d3d_d3d11 PRIVATE aux_d3d)
target_link_libraries(tests_comp_client_d3d11 PRIVATE comp_client comp_mock) target_link_libraries(tests_comp_client_d3d11 PRIVATE comp_client comp_mock)
endif() endif()
if(XRT_HAVE_D3D12)
# target_link_libraries(tests_comp_client_d3d12 PRIVATE comp_client comp_mock)
endif()
if(XRT_HAVE_VULKAN) if(XRT_HAVE_VULKAN)
target_link_libraries(tests_comp_client_vulkan PRIVATE comp_client comp_mock comp_util aux_vk) target_link_libraries(tests_comp_client_vulkan PRIVATE comp_client comp_mock comp_util aux_vk)
endif() endif()

View file

@ -0,0 +1,42 @@
// Copyright 2022, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief DXGI formats shared between D3D11 and D3D12 tests.
* @author Ryan Pavlik <ryan.pavlik@collabora.com>
*/
#pragma once
#include <dxgi.h>
#include <initializer_list>
#include <algorithm>
static constexpr std::initializer_list<DXGI_FORMAT> colorFormats = {
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_R16G16B16A16_FLOAT,
DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_UNORM,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM,
};
static constexpr std::initializer_list<DXGI_FORMAT> depthStencilFormats = {
DXGI_FORMAT_D16_UNORM,
DXGI_FORMAT_D24_UNORM_S8_UINT,
DXGI_FORMAT_D32_FLOAT_S8X24_UINT,
DXGI_FORMAT_D32_FLOAT,
};
static constexpr std::initializer_list<DXGI_FORMAT> formats = {
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_R16G16B16A16_FLOAT,
DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_UNORM,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_D16_UNORM,
DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, DXGI_FORMAT_D32_FLOAT,
};
static inline bool
isDepthStencilFormat(DXGI_FORMAT format)
{
const auto b = depthStencilFormats.begin();
const auto e = depthStencilFormats.end();
auto it = std::find(b, e, format);
return it != e;
}

View file

@ -5,12 +5,14 @@
* @brief Direct3D 11 tests. * @brief Direct3D 11 tests.
* @author Ryan Pavlik <ryan.pavlik@collabora.com> * @author Ryan Pavlik <ryan.pavlik@collabora.com>
*/ */
#include "aux_d3d_dxgi_formats.hpp"
#include <iostream> #include <iostream>
#include "catch/catch.hpp" #include "catch/catch.hpp"
#include <d3d/d3d_helpers.hpp> #include <d3d/d3d_dxgi_helpers.hpp>
#include <d3d/d3d_d3d11_helpers.hpp>
#include <d3d/d3d_d3d11_allocator.hpp> #include <d3d/d3d_d3d11_allocator.hpp>
#include <util/u_win32_com_guard.hpp> #include <util/u_win32_com_guard.hpp>
@ -49,43 +51,17 @@ TEST_CASE("d3d11_device", "[.][needgpu]")
CHECK(adapter); CHECK(adapter);
wil::com_ptr<ID3D11Device> device; wil::com_ptr<ID3D11Device> device;
wil::com_ptr<ID3D11DeviceContext> context; wil::com_ptr<ID3D11DeviceContext> context;
CHECK_NOTHROW(std::tie(device, context) = createD3D11Device(adapter, U_LOGGING_TRACE)); CHECK_NOTHROW(std::tie(device, context) = createDevice(adapter, U_LOGGING_TRACE));
CHECK(device); CHECK(device);
CHECK(context); CHECK(context);
} }
static constexpr std::initializer_list<DXGI_FORMAT> colorFormats = {
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_R16G16B16A16_FLOAT,
DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_UNORM,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM,
};
static constexpr std::initializer_list<DXGI_FORMAT> depthStencilFormats = {
DXGI_FORMAT_D16_UNORM,
DXGI_FORMAT_D24_UNORM_S8_UINT,
DXGI_FORMAT_D32_FLOAT_S8X24_UINT,
DXGI_FORMAT_D32_FLOAT,
};
static constexpr std::initializer_list<DXGI_FORMAT> formats = {
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_R16G16B16A16_FLOAT,
DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_UNORM,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_D16_UNORM,
DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, DXGI_FORMAT_D32_FLOAT,
};
static inline bool
isDepthStencilFormat(DXGI_FORMAT format)
{
const auto b = depthStencilFormats.begin();
const auto e = depthStencilFormats.end();
auto it = std::find(b, e, format);
return it != e;
}
TEST_CASE("d3d11_allocate", "[.][needgpu]") TEST_CASE("d3d11_allocate", "[.][needgpu]")
{ {
ComGuard comGuard; ComGuard comGuard;
wil::com_ptr<ID3D11Device> device; wil::com_ptr<ID3D11Device> device;
wil::com_ptr<ID3D11DeviceContext> context; wil::com_ptr<ID3D11DeviceContext> context;
std::tie(device, context) = createD3D11Device(); std::tie(device, context) = createDevice();
auto device5 = device.query<ID3D11Device5>(); auto device5 = device.query<ID3D11Device5>();
std::vector<wil::com_ptr<ID3D11Texture2D1>> images; std::vector<wil::com_ptr<ID3D11Texture2D1>> images;
std::vector<wil::unique_handle> handles; std::vector<wil::unique_handle> handles;

View file

@ -13,7 +13,8 @@
#include "catch/catch.hpp" #include "catch/catch.hpp"
#include "util/u_handles.h" #include "util/u_handles.h"
#include <d3d/d3d_helpers.hpp> #include <d3d/d3d_dxgi_helpers.hpp>
#include <d3d/d3d_d3d11_helpers.hpp>
#include <stdint.h> #include <stdint.h>
#include <util/u_win32_com_guard.hpp> #include <util/u_win32_com_guard.hpp>
@ -21,6 +22,7 @@
using namespace xrt::auxiliary::d3d; using namespace xrt::auxiliary::d3d;
using namespace xrt::auxiliary::d3d::d3d11;
using namespace xrt::auxiliary::util; using namespace xrt::auxiliary::util;
TEST_CASE("client_compositor", "[.][needgpu]") TEST_CASE("client_compositor", "[.][needgpu]")
@ -32,7 +34,7 @@ TEST_CASE("client_compositor", "[.][needgpu]")
wil::com_ptr<ID3D11Device> device; wil::com_ptr<ID3D11Device> device;
wil::com_ptr<ID3D11DeviceContext> context; wil::com_ptr<ID3D11DeviceContext> context;
std::tie(device, context) = createD3D11Device(); std::tie(device, context) = createDevice();
struct xrt_compositor_d3d11 *xcd3d = client_d3d11_compositor_create(xcn, device.get()); struct xrt_compositor_d3d11 *xcd3d = client_d3d11_compositor_create(xcn, device.get());
struct xrt_compositor *xc = &xcd3d->base; struct xrt_compositor *xc = &xcd3d->base;