171 lines
4.7 KiB
C++
171 lines
4.7 KiB
C++
#include "Rendering/D3D12/D3D12WindowSwapChainPresenter.h"
|
|
|
|
namespace XCEngine::UI::Editor::Host {
|
|
|
|
using ::XCEngine::RHI::D3D12SwapChain;
|
|
using ::XCEngine::RHI::D3D12Texture;
|
|
using ::XCEngine::RHI::RHISwapChain;
|
|
using ::XCEngine::RHI::SwapChainDesc;
|
|
|
|
bool D3D12WindowSwapChainPresenter::Initialize(
|
|
D3D12HostDevice& hostDevice,
|
|
HWND hwnd,
|
|
int width,
|
|
int height) {
|
|
Shutdown();
|
|
|
|
if (hwnd == nullptr || width <= 0 || height <= 0) {
|
|
m_lastError = "Initialize rejected an invalid hwnd or size.";
|
|
return false;
|
|
}
|
|
|
|
if (hostDevice.GetRHIDevice() == nullptr || hostDevice.GetRHICommandQueue() == nullptr) {
|
|
m_lastError = "Initialize requires an initialized host D3D12 device.";
|
|
return false;
|
|
}
|
|
|
|
m_hwnd = hwnd;
|
|
m_width = width;
|
|
m_height = height;
|
|
m_hostDevice = &hostDevice;
|
|
|
|
if (!CreateSwapChain(width, height)) {
|
|
Shutdown();
|
|
return false;
|
|
}
|
|
|
|
m_lastError.clear();
|
|
return true;
|
|
}
|
|
|
|
bool D3D12WindowSwapChainPresenter::CreateSwapChain(int width, int height) {
|
|
if (m_hostDevice == nullptr ||
|
|
m_hostDevice->GetRHIDevice() == nullptr ||
|
|
m_hostDevice->GetRHICommandQueue() == nullptr) {
|
|
m_lastError = "CreateSwapChain requires an initialized host D3D12 device.";
|
|
return false;
|
|
}
|
|
|
|
SwapChainDesc swapChainDesc = {};
|
|
swapChainDesc.windowHandle = m_hwnd;
|
|
swapChainDesc.width = static_cast<std::uint32_t>(width);
|
|
swapChainDesc.height = static_cast<std::uint32_t>(height);
|
|
swapChainDesc.bufferCount = kSwapChainBufferCount;
|
|
m_swapChain = m_hostDevice->GetRHIDevice()->CreateSwapChain(
|
|
swapChainDesc,
|
|
m_hostDevice->GetRHICommandQueue());
|
|
if (m_swapChain == nullptr || GetD3D12SwapChain() == nullptr) {
|
|
m_lastError = "Failed to create the D3D12 swap chain.";
|
|
return false;
|
|
}
|
|
|
|
ConfigureFrameLatency();
|
|
|
|
if (!RecreateBackBufferViews()) {
|
|
m_lastError = "Failed to create swap chain back buffer views.";
|
|
return false;
|
|
}
|
|
|
|
m_width = width;
|
|
m_height = height;
|
|
return true;
|
|
}
|
|
|
|
void D3D12WindowSwapChainPresenter::ConfigureFrameLatency() {
|
|
D3D12SwapChain* d3d12SwapChain = GetD3D12SwapChain();
|
|
if (d3d12SwapChain == nullptr) {
|
|
return;
|
|
}
|
|
|
|
auto* nativeSwapChain =
|
|
static_cast<IDXGISwapChain3*>(d3d12SwapChain->GetNativeHandle());
|
|
if (nativeSwapChain == nullptr) {
|
|
return;
|
|
}
|
|
|
|
nativeSwapChain->SetMaximumFrameLatency(1u);
|
|
}
|
|
|
|
void D3D12WindowSwapChainPresenter::DestroySwapChain() {
|
|
ReleaseBackBufferViews();
|
|
|
|
if (m_swapChain != nullptr) {
|
|
m_swapChain->Shutdown();
|
|
delete m_swapChain;
|
|
m_swapChain = nullptr;
|
|
}
|
|
}
|
|
|
|
bool D3D12WindowSwapChainPresenter::RecreateSwapChain(int width, int height) {
|
|
DestroySwapChain();
|
|
m_hostDevice->ResetFrameTracking();
|
|
return CreateSwapChain(width, height);
|
|
}
|
|
|
|
void D3D12WindowSwapChainPresenter::Shutdown() {
|
|
if (m_hostDevice != nullptr) {
|
|
m_hostDevice->WaitForGpuIdle();
|
|
}
|
|
|
|
DestroySwapChain();
|
|
|
|
m_hwnd = nullptr;
|
|
m_width = 0;
|
|
m_height = 0;
|
|
m_hostDevice = nullptr;
|
|
m_lastError.clear();
|
|
}
|
|
|
|
const std::string& D3D12WindowSwapChainPresenter::GetLastError() const {
|
|
return m_lastError;
|
|
}
|
|
|
|
RHISwapChain* D3D12WindowSwapChainPresenter::GetSwapChain() const {
|
|
return m_swapChain;
|
|
}
|
|
|
|
const ::XCEngine::Rendering::RenderSurface*
|
|
D3D12WindowSwapChainPresenter::GetCurrentRenderSurface() const {
|
|
if (m_swapChain == nullptr) {
|
|
return nullptr;
|
|
}
|
|
|
|
const std::uint32_t backBufferIndex = m_swapChain->GetCurrentBackBufferIndex();
|
|
if (backBufferIndex >= m_backBufferSurfaces.size()) {
|
|
return nullptr;
|
|
}
|
|
|
|
return &m_backBufferSurfaces[backBufferIndex];
|
|
}
|
|
|
|
const D3D12Texture* D3D12WindowSwapChainPresenter::GetCurrentBackBufferTexture() const {
|
|
if (m_swapChain == nullptr) {
|
|
return nullptr;
|
|
}
|
|
|
|
return GetBackBufferTexture(m_swapChain->GetCurrentBackBufferIndex());
|
|
}
|
|
|
|
const D3D12Texture* D3D12WindowSwapChainPresenter::GetBackBufferTexture(std::uint32_t index) const {
|
|
const D3D12SwapChain* d3d12SwapChain = GetD3D12SwapChain();
|
|
if (d3d12SwapChain == nullptr) {
|
|
return nullptr;
|
|
}
|
|
|
|
return d3d12SwapChain->TryGetBackBuffer(index);
|
|
}
|
|
|
|
std::uint32_t D3D12WindowSwapChainPresenter::GetBackBufferCount() const {
|
|
return kSwapChainBufferCount;
|
|
}
|
|
|
|
std::uint32_t D3D12WindowSwapChainPresenter::GetCurrentBackBufferIndex() const {
|
|
return m_swapChain != nullptr ? m_swapChain->GetCurrentBackBufferIndex() : 0u;
|
|
}
|
|
|
|
D3D12SwapChain* D3D12WindowSwapChainPresenter::GetD3D12SwapChain() const {
|
|
return m_swapChain != nullptr ? static_cast<D3D12SwapChain*>(m_swapChain) : nullptr;
|
|
}
|
|
|
|
} // namespace XCEngine::UI::Editor::Host
|