diff --git a/src/xrt/auxiliary/CMakeLists.txt b/src/xrt/auxiliary/CMakeLists.txt index c12316159..b408ee1f7 100644 --- a/src/xrt/auxiliary/CMakeLists.txt +++ b/src/xrt/auxiliary/CMakeLists.txt @@ -18,7 +18,7 @@ if(XRT_HAVE_OPENGL OR XRT_HAVE_OPENGLES) endif() # Direct3D library -if(XRT_HAVE_D3D11 AND XRT_HAVE_VULKAN) +if(XRT_HAVE_D3D11 OR XRT_HAVE_D3D12) add_subdirectory(d3d) endif() diff --git a/src/xrt/auxiliary/d3d/CMakeLists.txt b/src/xrt/auxiliary/d3d/CMakeLists.txt index 82d1514cf..8acabe44c 100644 --- a/src/xrt/auxiliary/d3d/CMakeLists.txt +++ b/src/xrt/auxiliary/d3d/CMakeLists.txt @@ -1,7 +1,7 @@ # Copyright 2019-2022, Collabora, Ltd. # 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) # needed for format includes @@ -11,12 +11,29 @@ if(XRT_HAVE_D3D11) target_sources( aux_d3d PRIVATE - d3d_d3d11_bits.h d3d_d3d11_allocator.cpp d3d_d3d11_allocator.h d3d_d3d11_allocator.hpp + d3d_d3d11_bits.h d3d_d3d11_fence.cpp d3d_d3d11_fence.hpp + d3d_d3d11_helpers.cpp + d3d_d3d11_helpers.hpp ) target_link_libraries(aux_d3d PUBLIC ${D3D11_LIBRARY}) 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() diff --git a/src/xrt/auxiliary/d3d/d3d_d3d11_helpers.cpp b/src/xrt/auxiliary/d3d/d3d_d3d11_helpers.cpp new file mode 100644 index 000000000..c9c56ab2d --- /dev/null +++ b/src/xrt/auxiliary/d3d/d3d_d3d11_helpers.cpp @@ -0,0 +1,64 @@ +// Copyright 2022, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Misc D3D11 helper routines. + * @author Ryan Pavlik + * @ingroup aux_d3d + */ + +#include "d3d_d3d11_helpers.hpp" + +#include "util/u_logging.h" + +#include +#include +#include +#include + +#include + +namespace xrt::auxiliary::d3d::d3d11 { +HRESULT +tryCreateDevice(const wil::com_ptr &adapter, + D3D_DRIVER_TYPE driver_type, + unsigned int creation_flags, + const std::vector &feature_levels, + wil::com_ptr &out_device, + wil::com_ptr &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> +createDevice(const wil::com_ptr &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 feature_levels{D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0}; + wil::com_ptr device; + wil::com_ptr 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 diff --git a/src/xrt/auxiliary/d3d/d3d_d3d11_helpers.hpp b/src/xrt/auxiliary/d3d/d3d_d3d11_helpers.hpp new file mode 100644 index 000000000..7f2941e7f --- /dev/null +++ b/src/xrt/auxiliary/d3d/d3d_d3d11_helpers.hpp @@ -0,0 +1,39 @@ +// Copyright 2022, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Misc D3D11/12 helper routines. + * @author Ryan Pavlik + * @ingroup aux_d3d + */ + +#pragma once + +#include "xrt/xrt_defines.h" + +#include "util/u_logging.h" + +#include +#include + +#include + +#include + + +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> + */ +std::pair, wil::com_ptr> +createDevice(const wil::com_ptr &adapter = nullptr, u_logging_level log_level = U_LOGGING_INFO); + +} // namespace xrt::auxiliary::d3d::d3d11 diff --git a/src/xrt/auxiliary/d3d/d3d_d3d12_bits.h b/src/xrt/auxiliary/d3d/d3d_d3d12_bits.h new file mode 100644 index 000000000..37aba89da --- /dev/null +++ b/src/xrt/auxiliary/d3d/d3d_d3d12_bits.h @@ -0,0 +1,104 @@ +// Copyright 2020-2022, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Usage bits for D3D12. + * @author Ryan Pavlik + * @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 + +#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 diff --git a/src/xrt/auxiliary/d3d/d3d_d3d12_fence.cpp b/src/xrt/auxiliary/d3d/d3d_d3d12_fence.cpp new file mode 100644 index 000000000..303198cf8 --- /dev/null +++ b/src/xrt/auxiliary/d3d/d3d_d3d12_fence.cpp @@ -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 + * @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 +#include +#include +#include +#include + +#include +#include + +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 &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 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 fence, + wil::unique_event_nothrow &event, + uint64_t value, + std::chrono::milliseconds timeout_ms) +{ + DWORD dwTimeout = duration_cast>(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 diff --git a/src/xrt/auxiliary/d3d/d3d_d3d12_fence.hpp b/src/xrt/auxiliary/d3d/d3d_d3d12_fence.hpp new file mode 100644 index 000000000..ecf02c2a3 --- /dev/null +++ b/src/xrt/auxiliary/d3d/d3d_d3d12_fence.hpp @@ -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 + * @ingroup aux_d3d + */ + +#pragma once + +#include "xrt/xrt_compositor.h" + +#include +#include +#include + +#include + +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 &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 fence, + wil::unique_event_nothrow &event, + uint64_t value, + std::chrono::milliseconds timeout_ms); + +}; // namespace xrt::auxiliary::d3d::d3d12 diff --git a/src/xrt/auxiliary/d3d/d3d_d3d12_helpers.cpp b/src/xrt/auxiliary/d3d/d3d_d3d12_helpers.cpp new file mode 100644 index 000000000..4628dc71a --- /dev/null +++ b/src/xrt/auxiliary/d3d/d3d_d3d12_helpers.cpp @@ -0,0 +1,108 @@ +// Copyright 2022, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Misc D3D12 helper routines. + * @author Ryan Pavlik + * @ingroup aux_d3d + */ + +#include "d3d_d3d12_helpers.hpp" +#include "d3d_d3d12_bits.h" + +#include "util/u_logging.h" + +#include +#include +#include + +#include +#include + +namespace xrt::auxiliary::d3d::d3d12 { + +wil::com_ptr +createDevice(const wil::com_ptr &adapter, u_logging_level log_level) +{ + if (adapter) { + U_LOG_IFL_D(log_level, "Adapter provided."); + } + + wil::com_ptr 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 out_acquire_command_list, + wil::com_ptr out_release_command_list) +{ + + //! @todo do we need to set queue access somehow? + wil::com_ptr 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 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 +importImage(ID3D12Device &device, HANDLE h) +{ + wil::com_ptr 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 +importFence(ID3D12Device &device, HANDLE h) +{ + wil::com_ptr 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 diff --git a/src/xrt/auxiliary/d3d/d3d_d3d12_helpers.hpp b/src/xrt/auxiliary/d3d/d3d_d3d12_helpers.hpp new file mode 100644 index 000000000..6ac1db834 --- /dev/null +++ b/src/xrt/auxiliary/d3d/d3d_d3d12_helpers.hpp @@ -0,0 +1,81 @@ +// Copyright 2022, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Misc D3D12 helper routines. + * @author Ryan Pavlik + * @ingroup aux_d3d + */ + +#pragma once + +#include "xrt/xrt_defines.h" +#include "xrt/xrt_compositor.h" + +#include "util/u_logging.h" + +#include +#include + +#include + +#include + + +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 + */ +wil::com_ptr +createDevice(const wil::com_ptr &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 out_acquire_command_list, + wil::com_ptr 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 +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 +importFence(ID3D12Device &device, HANDLE h); + +} // namespace xrt::auxiliary::d3d::d3d12 diff --git a/src/xrt/auxiliary/d3d/d3d_helpers.cpp b/src/xrt/auxiliary/d3d/d3d_dxgi_helpers.cpp similarity index 59% rename from src/xrt/auxiliary/d3d/d3d_helpers.cpp rename to src/xrt/auxiliary/d3d/d3d_dxgi_helpers.cpp index 76dd9f75a..d27fe34f1 100644 --- a/src/xrt/auxiliary/d3d/d3d_helpers.cpp +++ b/src/xrt/auxiliary/d3d/d3d_dxgi_helpers.cpp @@ -7,12 +7,11 @@ * @ingroup aux_d3d */ -#include "d3d_helpers.hpp" +#include "d3d_d3d11_helpers.hpp" #include "util/u_logging.h" #include -#include #include #include @@ -98,50 +97,4 @@ getAdapterByLUID(const xrt_luid_t &luid, u_logging_level log_level) } return ret; } - -#ifdef XRT_HAVE_D3D11 -HRESULT -tryCreateD3D11Device(const wil::com_ptr &adapter, - D3D_DRIVER_TYPE driver_type, - unsigned int creation_flags, - const std::vector &feature_levels, - wil::com_ptr &out_device, - wil::com_ptr &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> -createD3D11Device(const wil::com_ptr &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 feature_levels{D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0}; - wil::com_ptr device; - wil::com_ptr 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 diff --git a/src/xrt/auxiliary/d3d/d3d_helpers.hpp b/src/xrt/auxiliary/d3d/d3d_dxgi_helpers.hpp similarity index 63% rename from src/xrt/auxiliary/d3d/d3d_helpers.hpp rename to src/xrt/auxiliary/d3d/d3d_dxgi_helpers.hpp index 6efe62d31..32b441156 100644 --- a/src/xrt/auxiliary/d3d/d3d_helpers.hpp +++ b/src/xrt/auxiliary/d3d/d3d_dxgi_helpers.hpp @@ -2,7 +2,7 @@ // SPDX-License-Identifier: BSL-1.0 /*! * @file - * @brief Misc D3D11 helper routines. + * @brief Misc D3D11/12 helper routines. * @author Ryan Pavlik * @ingroup aux_d3d */ @@ -10,17 +10,10 @@ #pragma once #include "xrt/xrt_defines.h" -#include "xrt/xrt_compositor.h" -#include "xrt/xrt_config_have.h" #include "util/u_logging.h" #include - -#ifdef XRT_HAVE_D3D11 -#include -#endif - #include #include @@ -55,19 +48,4 @@ getAdapterByIndex(uint16_t index, u_logging_level log_level = U_LOGGING_INFO); wil::com_ptr 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> - */ -std::pair, wil::com_ptr> -createD3D11Device(const wil::com_ptr &adapter = nullptr, u_logging_level log_level = U_LOGGING_INFO); -#endif // XRT_HAVE_D3D11 - } // namespace xrt::auxiliary::d3d diff --git a/src/xrt/compositor/client/comp_d3d11_client.cpp b/src/xrt/compositor/client/comp_d3d11_client.cpp index 2fce86648..c2772609b 100644 --- a/src/xrt/compositor/client/comp_d3d11_client.cpp +++ b/src/xrt/compositor/client/comp_d3d11_client.cpp @@ -863,7 +863,7 @@ try { // Now, try to get an equivalent device of our own wil::com_ptr our_dev; wil::com_ptr 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_context.query_to(c->comp_context.put()); } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 848725659..61553657f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -27,8 +27,10 @@ set(tests tests_pose ) 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() +# if(XRT_HAVE_D3D12) +# endif() if(XRT_HAVE_VULKAN) list(APPEND tests tests_comp_client_vulkan) endif() @@ -59,10 +61,14 @@ if(XRT_BUILD_DRIVER_HANDTRACKING) endif() 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) endif() +if(XRT_HAVE_D3D12) + # target_link_libraries(tests_comp_client_d3d12 PRIVATE comp_client comp_mock) +endif() + if(XRT_HAVE_VULKAN) target_link_libraries(tests_comp_client_vulkan PRIVATE comp_client comp_mock comp_util aux_vk) endif() diff --git a/tests/aux_d3d_dxgi_formats.hpp b/tests/aux_d3d_dxgi_formats.hpp new file mode 100644 index 000000000..e632690be --- /dev/null +++ b/tests/aux_d3d_dxgi_formats.hpp @@ -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 + */ + +#pragma once + +#include +#include +#include + + +static constexpr std::initializer_list 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 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 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; +} diff --git a/tests/tests_aux_d3d.cpp b/tests/tests_aux_d3d_d3d11.cpp similarity index 71% rename from tests/tests_aux_d3d.cpp rename to tests/tests_aux_d3d_d3d11.cpp index 74c1c2558..7fe387654 100644 --- a/tests/tests_aux_d3d.cpp +++ b/tests/tests_aux_d3d_d3d11.cpp @@ -5,12 +5,14 @@ * @brief Direct3D 11 tests. * @author Ryan Pavlik */ +#include "aux_d3d_dxgi_formats.hpp" #include #include "catch/catch.hpp" -#include +#include +#include #include #include @@ -49,43 +51,17 @@ TEST_CASE("d3d11_device", "[.][needgpu]") CHECK(adapter); wil::com_ptr device; wil::com_ptr 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(context); } -static constexpr std::initializer_list 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 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 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]") { ComGuard comGuard; wil::com_ptr device; wil::com_ptr context; - std::tie(device, context) = createD3D11Device(); + std::tie(device, context) = createDevice(); auto device5 = device.query(); std::vector> images; std::vector handles; diff --git a/tests/tests_comp_client_d3d11.cpp b/tests/tests_comp_client_d3d11.cpp index 570c51618..0a3b996bd 100644 --- a/tests/tests_comp_client_d3d11.cpp +++ b/tests/tests_comp_client_d3d11.cpp @@ -13,7 +13,8 @@ #include "catch/catch.hpp" #include "util/u_handles.h" -#include +#include +#include #include #include @@ -21,6 +22,7 @@ using namespace xrt::auxiliary::d3d; +using namespace xrt::auxiliary::d3d::d3d11; using namespace xrt::auxiliary::util; TEST_CASE("client_compositor", "[.][needgpu]") @@ -32,7 +34,7 @@ TEST_CASE("client_compositor", "[.][needgpu]") wil::com_ptr device; wil::com_ptr 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 *xc = &xcd3d->base;