I'm working on a graphics application where I use a command queue to render scenes. However, I'm facing some uncertainty about when to call Present for my swapchain to ensure that I'm not presenting an incomplete frame.
It's important to note that I do not wait for the GPU to finish its work before starting to render the next frame.
Here's a simplified version of my code:
void CommandQueue::BeginFrame(ID3D12PipelineState* pPSO)
{
CHECK_FAILURE(m_commandAllocators[m_frameIndex]->Reset());
CHECK_FAILURE(m_commandList->Reset(m_commandAllocators[m_frameIndex].Get(), pPSO));
}
void CommandQueue::EndFrame()
{
CHECK_FAILURE(m_commandList->Close());
const uint64 currentFenceValue = m_fenceValues[m_frameIndex];
CHECK_FAILURE(m_commandQueue->Signal(m_fence.Get(), currentFenceValue));
// Update the frame index.
m_frameIndex = m_frameIndex + 1 % QUEUE_FRAMES_COUNT;
// If the next frame is not ready to be rendered yet, wait until it is ready.
if (m_fence->GetCompletedValue() < m_fenceValues[m_frameIndex])
{
CHECK_FAILURE(m_fence->SetEventOnCompletion(m_fenceValues[m_frameIndex], m_fenceEvent));
WaitForSingleObjectEx(m_fenceEvent, INFINITE, FALSE);
}
// Set the fence value for the next frame.
m_fenceValues[m_frameIndex] = currentFenceValue + 1;
}
Could someone please provide guidance on when and where I should call Present to ensure that I present a fully rendered frame without potential issues, given that I don't wait for the GPU to complete its work before initiating the next frame's rendering? Any code examples or best practices would be greatly appreciated.