The open source OpenXR runtime
at prediction-2 172 lines 6.4 kB view raw
1// Copyright 2022, Collabora, Ltd. 2// SPDX-License-Identifier: BSL-1.0 3/*! 4 * @file 5 * @brief Misc D3D12 helper routines. 6 * @author Rylie Pavlik <rylie.pavlik@collabora.com> 7 * @ingroup aux_d3d 8 */ 9 10#include "d3d_d3d12_helpers.hpp" 11#include "d3d_d3d12_bits.h" 12 13#include "util/u_logging.h" 14 15#include <d3d12.h> 16#include <wil/com.h> 17#include <wil/result.h> 18 19#include <vector> 20#include <stdexcept> 21 22namespace xrt::auxiliary::d3d::d3d12 { 23 24wil::com_ptr<ID3D12Device> 25createDevice(const wil::com_ptr<IDXGIAdapter> &adapter, u_logging_level log_level) 26{ 27 if (adapter) { 28 U_LOG_IFL_D(log_level, "Adapter provided."); 29 } 30 31 wil::com_ptr<ID3D12Device> device; 32 THROW_IF_FAILED( 33 D3D12CreateDevice(wil::com_raw_ptr(adapter), D3D_FEATURE_LEVEL_11_1, IID_PPV_ARGS(device.put()))); 34 35 return device; 36} 37 38 39HRESULT 40createCommandLists(ID3D12Device &device, 41 ID3D12CommandAllocator &command_allocator, 42 ID3D12Resource &resource, 43 enum xrt_swapchain_usage_bits bits, 44 wil::com_ptr<ID3D12CommandList> out_acquire_command_list, 45 wil::com_ptr<ID3D12CommandList> out_release_command_list) 46{ 47 48 //! @todo do we need to set queue access somehow? 49 wil::com_ptr<ID3D12GraphicsCommandList> acquireCommandList; 50 RETURN_IF_FAILED(device.CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, &command_allocator, nullptr, 51 IID_PPV_ARGS(acquireCommandList.put()))); 52 53 D3D12_RESOURCE_STATES appResourceState = d3d_convert_usage_bits_to_d3d12_app_resource_state(bits); 54 55 /// @todo No idea if this is right, might depend on whether it's the compute or graphics compositor! 56 D3D12_RESOURCE_STATES compositorResourceState = D3D12_RESOURCE_STATE_GENERIC_READ; 57 58 D3D12_RESOURCE_BARRIER barrier{}; 59 barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; 60 barrier.Transition.pResource = &resource; 61 barrier.Transition.StateBefore = compositorResourceState; 62 barrier.Transition.StateAfter = appResourceState; 63 barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; 64 65 acquireCommandList->ResourceBarrier(1, &barrier); 66 RETURN_IF_FAILED(acquireCommandList->Close()); 67 68 wil::com_ptr<ID3D12GraphicsCommandList> releaseCommandList; 69 RETURN_IF_FAILED(device.CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, &command_allocator, nullptr, 70 IID_PPV_ARGS(releaseCommandList.put()))); 71 barrier.Transition.StateBefore = appResourceState; 72 barrier.Transition.StateAfter = compositorResourceState; 73 74 releaseCommandList->ResourceBarrier(1, &barrier); 75 RETURN_IF_FAILED(releaseCommandList->Close()); 76 77 out_acquire_command_list = std::move(acquireCommandList); 78 out_release_command_list = std::move(releaseCommandList); 79 return S_OK; 80} 81 82HRESULT 83createCommandListImageCopy(ID3D12Device &device, 84 ID3D12CommandAllocator &command_allocator, 85 ID3D12Resource &resource_src, 86 ID3D12Resource &resource_dst, 87 D3D12_RESOURCE_STATES src_resource_state, 88 D3D12_RESOURCE_STATES dst_resource_state, 89 wil::com_ptr<ID3D12CommandList> &out_copy_command_list) 90{ 91 wil::com_ptr<ID3D12GraphicsCommandList> copyCommandList; 92 RETURN_IF_FAILED(device.CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, &command_allocator, nullptr, 93 IID_PPV_ARGS(copyCommandList.put()))); 94 95 // Transition images into copy state 96 D3D12_RESOURCE_BARRIER preCopyBarriers[2]{}; 97 preCopyBarriers[0].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; 98 preCopyBarriers[0].Transition.pResource = &resource_src; 99 preCopyBarriers[0].Transition.StateBefore = src_resource_state; 100 preCopyBarriers[0].Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE; 101 preCopyBarriers[0].Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; 102 103 preCopyBarriers[1].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; 104 preCopyBarriers[1].Transition.pResource = &resource_dst; 105 preCopyBarriers[1].Transition.StateBefore = dst_resource_state; 106 preCopyBarriers[1].Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST; 107 preCopyBarriers[1].Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; 108 109 copyCommandList->ResourceBarrier(2, preCopyBarriers); 110 111 // Insert texture copy command 112 D3D12_TEXTURE_COPY_LOCATION srcCopyLocation; 113 srcCopyLocation.pResource = &resource_src; 114 srcCopyLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; 115 srcCopyLocation.SubresourceIndex = 0; 116 117 D3D12_TEXTURE_COPY_LOCATION dstCopyLocation; 118 dstCopyLocation.pResource = &resource_dst; 119 dstCopyLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; 120 dstCopyLocation.SubresourceIndex = 0; 121 122 copyCommandList->CopyTextureRegion(&dstCopyLocation, 0, 0, 0, &srcCopyLocation, nullptr); 123 124 // Transition images back from copy state 125 D3D12_RESOURCE_BARRIER postCopyBarriers[2]{}; 126 postCopyBarriers[0].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; 127 postCopyBarriers[0].Transition.pResource = &resource_src; 128 postCopyBarriers[0].Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_SOURCE; 129 postCopyBarriers[0].Transition.StateAfter = src_resource_state; 130 postCopyBarriers[0].Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; 131 132 postCopyBarriers[1].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; 133 postCopyBarriers[1].Transition.pResource = &resource_dst; 134 postCopyBarriers[1].Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST; 135 postCopyBarriers[1].Transition.StateAfter = dst_resource_state; 136 postCopyBarriers[1].Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; 137 138 copyCommandList->ResourceBarrier(2, postCopyBarriers); 139 140 RETURN_IF_FAILED(copyCommandList->Close()); 141 142 out_copy_command_list = std::move(copyCommandList); 143 return S_OK; 144} 145 146 147wil::com_ptr<ID3D12Resource> 148importImage(ID3D12Device &device, HANDLE h) 149{ 150 wil::com_ptr<ID3D12Resource> tex; 151 152 if (h == nullptr) { 153 throw std::logic_error("Cannot import empty handle"); 154 } 155 THROW_IF_FAILED(device.OpenSharedHandle(h, IID_PPV_ARGS(tex.put()))); 156 return tex; 157} 158 159 160wil::com_ptr<ID3D12Fence1> 161importFence(ID3D12Device &device, HANDLE h) 162{ 163 wil::com_ptr<ID3D12Fence1> fence; 164 165 if (h == nullptr) { 166 throw std::logic_error("Cannot import empty handle"); 167 } 168 THROW_IF_FAILED(device.OpenSharedHandle(h, IID_PPV_ARGS(fence.put()))); 169 return fence; 170} 171 172} // namespace xrt::auxiliary::d3d::d3d12