mirror of
https://github.com/saymrwulf/onnxruntime.git
synced 2026-05-14 20:48:00 +00:00
149 lines
5.8 KiB
C++
149 lines
5.8 KiB
C++
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
|
|
#include "lib/Api.Image/pch.h"
|
|
#include "inc/ImageConverter.h"
|
|
#include "inc/ImageConversionHelpers.h"
|
|
#include "inc/D3DDeviceCache.h"
|
|
|
|
using namespace Microsoft::WRL;
|
|
|
|
using namespace _winml;
|
|
|
|
void ImageConverter::SyncD3D11ToD3D12(_In_ D3DDeviceCache& device_cache, _In_ ID3D11Texture2D* pD3D11Texture) {
|
|
assert(pD3D11Texture != nullptr);
|
|
|
|
ComPtr<ID3D11Device> spTextureDevice;
|
|
pD3D11Texture->GetDevice(&spTextureDevice);
|
|
|
|
if (spTextureDevice.Get() == device_cache.GetD3D11Device()) {
|
|
// If the texture is on D3DDeviceCache's device, we sync using D3DDeviceCache's fences
|
|
device_cache.GPUSyncD3D11ToD3D12();
|
|
} else {
|
|
// Otherwise, sync using our own cached fences
|
|
ComPtr<ID3D11Fence> spD3D11DeviceFence = FetchOrCreateFenceOnDevice(device_cache, spTextureDevice.Get());
|
|
device_cache.SyncD3D11DeviceToConverter(spD3D11DeviceFence.Get());
|
|
}
|
|
}
|
|
|
|
void ImageConverter::SyncD3D12ToD3D11(_In_ D3DDeviceCache& device_cache, _In_ ID3D11Texture2D* spTexture) {
|
|
assert(spTexture != nullptr);
|
|
|
|
ComPtr<ID3D11Device> spTextureDevice;
|
|
spTexture->GetDevice(&spTextureDevice);
|
|
|
|
if (spTextureDevice.Get() == device_cache.GetD3D11Device()) {
|
|
// If the texture is on D3DDeviceCache's device, we sync using D3DDeviceCache's fences
|
|
device_cache.GPUSyncD3D12ToD3D11();
|
|
} else {
|
|
// Otherwise, sync using our own cached fences
|
|
ComPtr<ID3D11Fence> spD3D11DeviceFence = FetchOrCreateFenceOnDevice(device_cache, spTextureDevice.Get());
|
|
device_cache.SyncConverterToD3D11Device(spD3D11DeviceFence.Get());
|
|
}
|
|
}
|
|
|
|
ComPtr<ID3D11Fence> ImageConverter::FetchOrCreateFenceOnDevice(
|
|
_In_ D3DDeviceCache& device_cache, _In_ ID3D11Device* pD3D11Device
|
|
) {
|
|
assert(pD3D11Device != nullptr);
|
|
|
|
ComPtr<ID3D11Fence> fence;
|
|
UINT comPtrSize = static_cast<UINT>(sizeof(fence.GetAddressOf()));
|
|
|
|
if (FAILED(pD3D11Device->GetPrivateData(device_cache.GetFenceGuid(), &comPtrSize, fence.GetAddressOf())) ||
|
|
fence.Get() == nullptr) {
|
|
// There's no fence on the device, so create a new one
|
|
ComPtr<ID3D11Device5> spD3D11Device5;
|
|
WINML_THROW_IF_FAILED(pD3D11Device->QueryInterface(IID_PPV_ARGS(&spD3D11Device5)));
|
|
WINML_THROW_IF_FAILED(spD3D11Device5->OpenSharedFence(device_cache.GetConverterFenceHandle(), IID_PPV_ARGS(&fence))
|
|
);
|
|
|
|
// Store the fence on the device
|
|
WINML_THROW_IF_FAILED(spD3D11Device5->SetPrivateDataInterface(device_cache.GetFenceGuid(), fence.Get()));
|
|
}
|
|
|
|
return fence;
|
|
}
|
|
|
|
void ImageConverter::ResetCommandList(_In_ D3DDeviceCache& device_cache) {
|
|
if (!command_list_) {
|
|
assert(command_allocator_ == nullptr);
|
|
|
|
WINML_THROW_IF_FAILED(device_cache.GetD3D12Device()->CreateCommandAllocator(
|
|
device_cache.GetCommandQueue()->GetDesc().Type, IID_PPV_ARGS(command_allocator_.ReleaseAndGetAddressOf())
|
|
));
|
|
|
|
WINML_THROW_IF_FAILED(device_cache.GetD3D12Device()->CreateCommandList(
|
|
0,
|
|
device_cache.GetCommandQueue()->GetDesc().Type,
|
|
command_allocator_.Get(),
|
|
pipeline_state_.Get(),
|
|
IID_PPV_ARGS(command_list_.ReleaseAndGetAddressOf())
|
|
));
|
|
} else {
|
|
command_list_->Reset(command_allocator_.Get(), pipeline_state_.Get());
|
|
}
|
|
}
|
|
|
|
void ImageConverter::ResetAllocator() {
|
|
WINML_THROW_IF_FAILED(command_allocator_->Reset());
|
|
}
|
|
|
|
ComPtr<ID3D11Texture2D> ImageConverter::CreateTextureFromUnsupportedColorFormat(
|
|
const wm::IVideoFrame& videoFrame,
|
|
const wgi::BitmapBounds& inputBounds,
|
|
const wgi::BitmapBounds& outputBounds,
|
|
wgdx::DirectXPixelFormat newFormat
|
|
) {
|
|
assert(videoFrame != nullptr);
|
|
|
|
// Make sure we create the new video frame on the same device. We don't want the VideoFrame pipeline to implicitly share the texture between
|
|
// 2 devices since we will need to do it ourselves anyway.
|
|
auto device = _winmli::GetDeviceFromDirect3DSurface(videoFrame.Direct3DSurface());
|
|
|
|
auto spNewVideoFrame =
|
|
wm::VideoFrame::CreateAsDirect3D11SurfaceBacked(newFormat, outputBounds.Width, outputBounds.Height, device);
|
|
videoFrame.as<wm::IVideoFrame2>().CopyToAsync(spNewVideoFrame, inputBounds, outputBounds).get();
|
|
|
|
using namespace Windows::Graphics::DirectX::Direct3D11;
|
|
|
|
auto spDxgiInterfaceAccess = spNewVideoFrame.Direct3DSurface().as<IDirect3DDxgiInterfaceAccess>();
|
|
ComPtr<ID3D11Texture2D> d3d11Texture;
|
|
WINML_THROW_IF_FAILED(spDxgiInterfaceAccess->GetInterface(IID_PPV_ARGS(&d3d11Texture)));
|
|
|
|
return d3d11Texture;
|
|
}
|
|
|
|
void ImageConverter::CopyTextureIntoTexture(
|
|
_In_ ID3D11Texture2D* pTextureFrom, _In_ const wgi::BitmapBounds& inputBounds, _Inout_ ID3D11Texture2D* pTextureTo
|
|
) {
|
|
assert(pTextureFrom != nullptr);
|
|
assert(pTextureTo != nullptr);
|
|
|
|
D3D11_TEXTURE2D_DESC textureFromDesc, textureToDesc;
|
|
pTextureFrom->GetDesc(&textureFromDesc);
|
|
pTextureTo->GetDesc(&textureToDesc);
|
|
|
|
assert(inputBounds.Width <= textureFromDesc.Width && inputBounds.Width <= textureToDesc.Width);
|
|
assert(inputBounds.Height <= textureFromDesc.Height && inputBounds.Height <= textureToDesc.Height);
|
|
|
|
ComPtr<ID3D11Device> spDeviceFrom, spDeviceTo;
|
|
pTextureFrom->GetDevice(&spDeviceFrom);
|
|
pTextureTo->GetDevice(&spDeviceTo);
|
|
|
|
assert(spDeviceFrom.Get() == spDeviceTo.Get());
|
|
|
|
ComPtr<ID3D11DeviceContext> spDeviceContext;
|
|
spDeviceFrom->GetImmediateContext(&spDeviceContext);
|
|
|
|
if (textureFromDesc.Width != textureToDesc.Width || textureFromDesc.Height != textureToDesc.Height) {
|
|
// We can't copy the whole resource, so we have to use the slower CopySubresource() function
|
|
D3D11_BOX cropBox = CD3D11_BOX(
|
|
inputBounds.X, inputBounds.Y, 0, inputBounds.X + inputBounds.Width, inputBounds.Y + inputBounds.Height, 1
|
|
);
|
|
spDeviceContext->CopySubresourceRegion(pTextureTo, 0, 0, 0, 0, pTextureFrom, 0, &cropBox);
|
|
} else {
|
|
// Use the faster CopyResource() function since both textures have the same dimensions
|
|
spDeviceContext->CopyResource(pTextureTo, pTextureFrom);
|
|
}
|
|
}
|