refactor(new_editor/app): reorganize host structure and add smoke test
This commit is contained in:
138
new_editor/app/Rendering/D3D12/D3D12WindowInteropDevice.cpp
Normal file
138
new_editor/app/Rendering/D3D12/D3D12WindowInteropDevice.cpp
Normal file
@@ -0,0 +1,138 @@
|
||||
#include "D3D12WindowInteropSupport.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace XCEngine::UI::Editor::Host {
|
||||
|
||||
using namespace InteropSupport;
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user