Files
XCEngine/new_editor/app/Rendering/D3D12/D3D12WindowInteropDevice.cpp

139 lines
4.5 KiB
C++
Raw Normal View History

#include "D3D12WindowInteropInternal.h"
#include <array>
namespace XCEngine::UI::Editor::Host {
using namespace D3D12WindowInteropInternal;
bool D3D12WindowInteropContext::EnsureInterop() {
if (m_windowRenderer == nullptr) {
m_lastError = "EnsureInterop requires an attached D3D12 window renderer.";
return false;
}
if (m_d2dFactory == nullptr) {
m_lastError = "EnsureInterop requires an initialized D2D factory.";
return false;
}
if (m_d3d11On12Device != nullptr &&
m_d2dDeviceContext != nullptr &&
m_interopBrush != nullptr) {
return true;
}
ReleaseInteropState();
ID3D12Device* d3d12Device = m_windowRenderer->GetDevice();
ID3D12CommandQueue* d3d12CommandQueue = m_windowRenderer->GetCommandQueue();
if (d3d12Device == nullptr || d3d12CommandQueue == nullptr) {
m_lastError = "The attached D3D12 window renderer does not expose a native device/queue.";
return false;
}
const std::array<D3D_FEATURE_LEVEL, 4> featureLevels = {
D3D_FEATURE_LEVEL_12_1,
D3D_FEATURE_LEVEL_12_0,
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0
};
const std::array<IUnknown*, 1> commandQueues = {
reinterpret_cast<IUnknown*>(d3d12CommandQueue)
};
UINT createFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
#ifdef _DEBUG
createFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
D3D_FEATURE_LEVEL actualFeatureLevel = D3D_FEATURE_LEVEL_11_0;
HRESULT hr = D3D11On12CreateDevice(
d3d12Device,
createFlags,
featureLevels.data(),
static_cast<UINT>(featureLevels.size()),
commandQueues.data(),
static_cast<UINT>(commandQueues.size()),
0u,
m_d3d11Device.ReleaseAndGetAddressOf(),
m_d3d11DeviceContext.ReleaseAndGetAddressOf(),
&actualFeatureLevel);
#ifdef _DEBUG
if (FAILED(hr)) {
createFlags &= ~D3D11_CREATE_DEVICE_DEBUG;
hr = D3D11On12CreateDevice(
d3d12Device,
createFlags,
featureLevels.data(),
static_cast<UINT>(featureLevels.size()),
commandQueues.data(),
static_cast<UINT>(commandQueues.size()),
0u,
m_d3d11Device.ReleaseAndGetAddressOf(),
m_d3d11DeviceContext.ReleaseAndGetAddressOf(),
&actualFeatureLevel);
}
#endif
if (FAILED(hr) || m_d3d11Device == nullptr || m_d3d11DeviceContext == nullptr) {
m_lastError = HrToInteropString("D3D11On12CreateDevice", hr);
ReleaseInteropState();
return false;
}
hr = m_d3d11Device.As(&m_d3d11On12Device);
if (FAILED(hr) || m_d3d11On12Device == nullptr) {
m_lastError = HrToInteropString("ID3D11Device::QueryInterface(ID3D11On12Device)", hr);
ReleaseInteropState();
return false;
}
Microsoft::WRL::ComPtr<IDXGIDevice> dxgiDevice = {};
hr = m_d3d11Device.As(&dxgiDevice);
if (FAILED(hr) || dxgiDevice == nullptr) {
m_lastError = HrToInteropString("ID3D11Device::QueryInterface(IDXGIDevice)", hr);
ReleaseInteropState();
return false;
}
hr = m_d2dFactory->CreateDevice(dxgiDevice.Get(), m_d2dDevice.ReleaseAndGetAddressOf());
if (FAILED(hr) || m_d2dDevice == nullptr) {
m_lastError = HrToInteropString("ID2D1Factory1::CreateDevice", hr);
ReleaseInteropState();
return false;
}
hr = m_d2dDevice->CreateDeviceContext(
D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
m_d2dDeviceContext.ReleaseAndGetAddressOf());
if (FAILED(hr) || m_d2dDeviceContext == nullptr) {
m_lastError = HrToInteropString("ID2D1Device::CreateDeviceContext", hr);
ReleaseInteropState();
return false;
}
hr = m_d2dDeviceContext->CreateSolidColorBrush(
D2D1::ColorF(1.0f, 1.0f, 1.0f, 1.0f),
m_interopBrush.ReleaseAndGetAddressOf());
if (FAILED(hr) || m_interopBrush == nullptr) {
m_lastError = HrToInteropString("ID2D1DeviceContext::CreateSolidColorBrush", hr);
ReleaseInteropState();
return false;
}
m_d2dDeviceContext->SetDpi(96.0f, 96.0f);
m_d2dDeviceContext->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
m_lastError.clear();
return true;
}
void D3D12WindowInteropContext::ReleaseInteropState() {
ReleaseBackBufferTargets();
m_interopBrush.Reset();
m_d2dDeviceContext.Reset();
m_d2dDevice.Reset();
m_d3d11On12Device.Reset();
m_d3d11DeviceContext.Reset();
m_d3d11Device.Reset();
}
} // namespace XCEngine::UI::Editor::Host