mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2024-12-28 02:26:16 +00:00
a/d3d: Add some d3d12 features
This commit is contained in:
parent
2dc5083543
commit
576b158a83
|
@ -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()
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
64
src/xrt/auxiliary/d3d/d3d_d3d11_helpers.cpp
Normal file
64
src/xrt/auxiliary/d3d/d3d_d3d11_helpers.cpp
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
|
||||
*/
|
||||
|
||||
#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
|
39
src/xrt/auxiliary/d3d/d3d_d3d11_helpers.hpp
Normal file
39
src/xrt/auxiliary/d3d/d3d_d3d11_helpers.hpp
Normal 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
|
104
src/xrt/auxiliary/d3d/d3d_d3d12_bits.h
Normal file
104
src/xrt/auxiliary/d3d/d3d_d3d12_bits.h
Normal 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
|
117
src/xrt/auxiliary/d3d/d3d_d3d12_fence.cpp
Normal file
117
src/xrt/auxiliary/d3d/d3d_d3d12_fence.cpp
Normal 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
|
59
src/xrt/auxiliary/d3d/d3d_d3d12_fence.hpp
Normal file
59
src/xrt/auxiliary/d3d/d3d_d3d12_fence.hpp
Normal 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
|
108
src/xrt/auxiliary/d3d/d3d_d3d12_helpers.cpp
Normal file
108
src/xrt/auxiliary/d3d/d3d_d3d12_helpers.cpp
Normal 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
|
81
src/xrt/auxiliary/d3d/d3d_d3d12_helpers.hpp
Normal file
81
src/xrt/auxiliary/d3d/d3d_d3d12_helpers.hpp
Normal 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
|
|
@ -7,12 +7,11 @@
|
|||
* @ingroup aux_d3d
|
||||
*/
|
||||
|
||||
#include "d3d_helpers.hpp"
|
||||
#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>
|
||||
|
||||
|
@ -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<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
|
|
@ -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 <ryan.pavlik@collabora.com>
|
||||
* @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 <dxgi.h>
|
||||
|
||||
#ifdef XRT_HAVE_D3D11
|
||||
#include <d3d11.h>
|
||||
#endif
|
||||
|
||||
#include <wil/com.h>
|
||||
|
||||
#include <utility>
|
||||
|
@ -55,19 +48,4 @@ getAdapterByIndex(uint16_t index, u_logging_level log_level = U_LOGGING_INFO);
|
|||
wil::com_ptr<IDXGIAdapter>
|
||||
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
|
|
@ -863,7 +863,7 @@ try {
|
|||
// Now, try to get an equivalent device of our own
|
||||
wil::com_ptr<ID3D11Device> our_dev;
|
||||
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_context.query_to(c->comp_context.put());
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
42
tests/aux_d3d_dxgi_formats.hpp
Normal file
42
tests/aux_d3d_dxgi_formats.hpp
Normal 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;
|
||||
}
|
|
@ -5,12 +5,14 @@
|
|||
* @brief Direct3D 11 tests.
|
||||
* @author Ryan Pavlik <ryan.pavlik@collabora.com>
|
||||
*/
|
||||
#include "aux_d3d_dxgi_formats.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#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 <util/u_win32_com_guard.hpp>
|
||||
|
||||
|
@ -49,43 +51,17 @@ TEST_CASE("d3d11_device", "[.][needgpu]")
|
|||
CHECK(adapter);
|
||||
wil::com_ptr<ID3D11Device> device;
|
||||
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(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]")
|
||||
{
|
||||
ComGuard comGuard;
|
||||
wil::com_ptr<ID3D11Device> device;
|
||||
wil::com_ptr<ID3D11DeviceContext> context;
|
||||
std::tie(device, context) = createD3D11Device();
|
||||
std::tie(device, context) = createDevice();
|
||||
auto device5 = device.query<ID3D11Device5>();
|
||||
std::vector<wil::com_ptr<ID3D11Texture2D1>> images;
|
||||
std::vector<wil::unique_handle> handles;
|
|
@ -13,7 +13,8 @@
|
|||
#include "catch/catch.hpp"
|
||||
#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 <util/u_win32_com_guard.hpp>
|
||||
|
||||
|
@ -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<ID3D11Device> device;
|
||||
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 *xc = &xcd3d->base;
|
||||
|
||||
|
|
Loading…
Reference in a new issue