114 lines
3.3 KiB
C++
114 lines
3.3 KiB
C++
|
|
#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
|