#include "D3D12HostDevice.h" namespace XCEngine::UI::Editor::Host { using ::XCEngine::RHI::D3D12CommandList; using ::XCEngine::RHI::RHICommandList; bool D3D12HostDevice::BeginFrame(std::uint32_t frameIndex) { WaitForFrame(frameIndex); RHICommandList* commandList = GetCommandList(frameIndex); D3D12CommandList* d3d12CommandList = GetD3D12CommandList(frameIndex); if (commandList == nullptr || d3d12CommandList == nullptr) { m_lastError = "BeginFrame could not resolve the active command list."; return false; } commandList->Reset(); m_lastError.clear(); return true; } bool D3D12HostDevice::SubmitFrame(std::uint32_t frameIndex) { RHICommandList* commandList = GetCommandList(frameIndex); if (commandList == nullptr || m_commandQueue == nullptr) { m_lastError = "SubmitFrame requires an initialized command list and queue."; return false; } commandList->Close(); void* commandLists[] = { commandList }; m_commandQueue->ExecuteCommandLists(1, commandLists); m_lastError.clear(); return true; } bool D3D12HostDevice::SignalFrameCompletion(std::uint32_t frameIndex) { ID3D12CommandQueue* commandQueue = GetCommandQueue(); if (commandQueue == nullptr || m_frameCompletionFence == nullptr || frameIndex >= m_frameFenceValues.size()) { return false; } ++m_lastSubmittedFrameValue; const HRESULT hr = commandQueue->Signal( m_frameCompletionFence.Get(), m_lastSubmittedFrameValue); if (SUCCEEDED(hr)) { m_frameFenceValues[frameIndex] = m_lastSubmittedFrameValue; m_lastError.clear(); } return SUCCEEDED(hr); } void D3D12HostDevice::WaitForFrame(std::uint32_t frameIndex) { if (m_frameCompletionFence == nullptr || m_frameCompletionEvent == nullptr || frameIndex >= m_frameFenceValues.size()) { return; } const std::uint64_t fenceValue = m_frameFenceValues[frameIndex]; if (fenceValue == 0u || m_frameCompletionFence->GetCompletedValue() >= fenceValue) { return; } const HRESULT hr = m_frameCompletionFence->SetEventOnCompletion( fenceValue, m_frameCompletionEvent); if (SUCCEEDED(hr)) { WaitForSingleObject(m_frameCompletionEvent, INFINITE); } } void D3D12HostDevice::WaitForGpuIdle() { ID3D12CommandQueue* commandQueue = GetCommandQueue(); if (commandQueue == nullptr || m_frameCompletionFence == nullptr || m_frameCompletionEvent == nullptr) { if (m_commandQueue != nullptr) { m_commandQueue->WaitForIdle(); } return; } ++m_lastSubmittedFrameValue; const std::uint64_t fenceValue = m_lastSubmittedFrameValue; const HRESULT signalHr = commandQueue->Signal( m_frameCompletionFence.Get(), fenceValue); if (FAILED(signalHr)) { return; } if (m_frameCompletionFence->GetCompletedValue() >= fenceValue) { return; } const HRESULT waitHr = m_frameCompletionFence->SetEventOnCompletion( fenceValue, m_frameCompletionEvent); if (SUCCEEDED(waitHr)) { WaitForSingleObject(m_frameCompletionEvent, INFINITE); } } void D3D12HostDevice::ResetFrameTracking() { m_frameFenceValues.fill(0u); } } // namespace XCEngine::UI::Editor::Host