| 194 | } |
| 195 | |
| 196 | void EndFrame(IDXGISwapChain3* swapChain, uint32 syncIntervals) |
| 197 | { |
| 198 | Assert_(Device); |
| 199 | |
| 200 | DXCall(CmdList->Close()); |
| 201 | |
| 202 | EndFrame_Upload(); |
| 203 | |
| 204 | ID3D12CommandList* commandLists[] = { CmdList }; |
| 205 | GfxQueue->ExecuteCommandLists(ArraySize_(commandLists), commandLists); |
| 206 | |
| 207 | // Present the frame. |
| 208 | if(swapChain) |
| 209 | DXCall(swapChain->Present(syncIntervals, 0)); |
| 210 | |
| 211 | ++CurrentCPUFrame; |
| 212 | |
| 213 | // Signal the fence with the current frame number, so that we can check back on it |
| 214 | FrameFence.Signal(GfxQueue, CurrentCPUFrame); |
| 215 | |
| 216 | // Wait for the GPU to catch up before we stomp an executing command buffer |
| 217 | const uint64 gpuLag = DX12::CurrentCPUFrame - DX12::CurrentGPUFrame; |
| 218 | Assert_(gpuLag <= DX12::RenderLatency); |
| 219 | if(gpuLag >= DX12::RenderLatency) |
| 220 | { |
| 221 | // Make sure that the previous frame is finished |
| 222 | FrameFence.Wait(DX12::CurrentGPUFrame + 1); |
| 223 | ++DX12::CurrentGPUFrame; |
| 224 | } |
| 225 | |
| 226 | CurrFrameIdx = DX12::CurrentCPUFrame % NumCmdAllocators; |
| 227 | |
| 228 | // Prepare the command buffers to be used for the next frame |
| 229 | DXCall(CmdAllocators[CurrFrameIdx]->Reset()); |
| 230 | DXCall(CmdList->Reset(CmdAllocators[CurrFrameIdx], nullptr)); |
| 231 | |
| 232 | EndFrame_Helpers(); |
| 233 | |
| 234 | // See if we have any deferred releases to process |
| 235 | ProcessDeferredReleases(CurrFrameIdx); |
| 236 | } |
| 237 | |
| 238 | void FlushGPU() |
| 239 | { |
nothing calls this directly
no test coverage detected