diff --git a/neo/libs/optick/optick.h b/neo/libs/optick/optick.h index 989a1bd3..f90257c5 100644 --- a/neo/libs/optick/optick.h +++ b/neo/libs/optick/optick.h @@ -779,7 +779,7 @@ struct OPTICK_API GPUContext //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// OPTICK_API void InitGpuD3D12(ID3D12Device* device, ID3D12CommandQueue** cmdQueues, uint32_t numQueues); OPTICK_API void InitGpuVulkan(VkDevice* vkDevices, VkPhysicalDevice* vkPhysicalDevices, VkQueue* vkQueues, uint32_t* cmdQueuesFamily, uint32_t numQueues, const VulkanFunctions* functions); -OPTICK_API void GpuFlip(void* swapChain); +OPTICK_API void GpuFlip(void* swapChain, uint32_t frameID = 0); OPTICK_API GPUContext SetGpuContext(GPUContext context); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// struct OPTICK_API GPUContextScope @@ -1063,7 +1063,7 @@ struct OptickApp if (OPTICK_CONCAT(gpu_autogen_description_, __LINE__) == nullptr) OPTICK_CONCAT(gpu_autogen_description_, __LINE__) = ::Optick::EventDescription::Create( NAME, __FILE__, __LINE__ ); \ ::Optick::GPUEvent OPTICK_CONCAT(gpu_autogen_event_, __LINE__)( *(OPTICK_CONCAT(gpu_autogen_description_, __LINE__)) ); \ -#define OPTICK_GPU_FLIP(SWAP_CHAIN) ::Optick::GpuFlip(SWAP_CHAIN); +#define OPTICK_GPU_FLIP(...) ::Optick::GpuFlip(__VA_ARGS__); ///////////////////////////////////////////////////////////////////////////////// // [Automation][Startup] @@ -1124,7 +1124,7 @@ struct OptickApp #define OPTICK_GPU_INIT_VULKAN(DEVICES, PHYSICAL_DEVICES, CMD_QUEUES, CMD_QUEUES_FAMILY, NUM_CMD_QUEUS, FUNCTIONS) #define OPTICK_GPU_CONTEXT(...) #define OPTICK_GPU_EVENT(NAME) -#define OPTICK_GPU_FLIP(SWAP_CHAIN) +#define OPTICK_GPU_FLIP(...) #define OPTICK_UPDATE() #define OPTICK_FRAME_FLIP(...) #define OPTICK_FRAME_EVENT(FRAME_TYPE, ...) diff --git a/neo/libs/optick/optick_core.cpp b/neo/libs/optick/optick_core.cpp index 352ee7af..76484b90 100644 --- a/neo/libs/optick/optick_core.cpp +++ b/neo/libs/optick/optick_core.cpp @@ -1801,10 +1801,10 @@ OPTICK_API EventStorage* RegisterStorage(const char* name, uint64_t threadID, Th return entry ? &entry->storage : nullptr; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -OPTICK_API void GpuFlip(void* swapChain) +OPTICK_API void GpuFlip(void* swapChain, uint32_t frameID) { if (GPUProfiler* gpuProfiler = Core::Get().gpuProfiler) - gpuProfiler->Flip(swapChain); + gpuProfiler->Flip(swapChain, frameID); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// OPTICK_API GPUContext SetGpuContext(GPUContext context) diff --git a/neo/libs/optick/optick_gpu.d3d12.cpp b/neo/libs/optick/optick_gpu.d3d12.cpp index e81e22e3..7bc32e42 100644 --- a/neo/libs/optick/optick_gpu.d3d12.cpp +++ b/neo/libs/optick/optick_gpu.d3d12.cpp @@ -73,9 +73,6 @@ namespace Optick ID3D12Fence* syncFence; array frames; - std::queue presentIDs; - std::queue frameIDs; - NodePayload() : commandQueue(nullptr), queryHeap(nullptr), syncFence(nullptr) {} ~NodePayload(); }; @@ -84,9 +81,10 @@ namespace Optick ID3D12Resource* queryBuffer; ID3D12Device* device; - // VSync Stats + // VSync / Present Stats DXGI_FRAME_STATISTICS prevFrameStatistics; - UINT swapChainLatency; + std::queue presentIdQueue; + std::queue frameIdQueue; //void UpdateRange(uint32_t start, uint32_t finish) void InitNodeInternal(const char* nodeName, uint32_t nodeIndex, ID3D12CommandQueue* pCmdQueue); @@ -99,7 +97,7 @@ namespace Optick void QueryTimestamp(ID3D12GraphicsCommandList* context, int64_t* outCpuTimestamp); - void Flip(IDXGISwapChain* swapChain); + void Flip(IDXGISwapChain* swapChain, uint32_t frameID); // Interface implementation @@ -114,9 +112,9 @@ namespace Optick void WaitForFrame(uint32_t nodeIndex, uint64_t frameNumber) override; - void Flip(void* swapChain) override + void Flip(void* swapChain, uint32_t frameID) override { - Flip(static_cast(swapChain)); + Flip(static_cast(swapChain), frameID); } }; @@ -275,7 +273,7 @@ namespace Optick } } - void GPUProfilerD3D12::Flip(IDXGISwapChain* swapChain) + void GPUProfilerD3D12::Flip(IDXGISwapChain* swapChain, uint32_t frameID) { OPTICK_CATEGORY("GPUProfilerD3D12::Flip", Category::Debug); @@ -286,9 +284,6 @@ namespace Optick if (currentState == STATE_RUNNING) { - UINT currentPresentID; - swapChain->GetLastPresentCount(¤tPresentID); - Node& node = *nodes[currentNode]; NodePayload& payload = *nodePayloads[currentNode]; @@ -338,25 +333,15 @@ namespace Optick } else { - DXGI_SWAP_CHAIN_DESC swapChainDesc; - swapChain->GetDesc(&swapChainDesc); - - IDXGISwapChain2* swapChain2; - swapChain->QueryInterface(IID_PPV_ARGS(&swapChain2)); - HRESULT result = swapChain2->GetMaximumFrameLatency(&swapChainLatency); - if (result == S_OK) - swapChainLatency = std::min(swapChainLatency, swapChainDesc.BufferCount + 1); - else - swapChainLatency = swapChainDesc.BufferCount + 1; - - while (!payload.presentIDs.empty()) - { - payload.presentIDs.pop(); - payload.frameIDs.pop(); - } - + // Initialize present / frame statistics prevFrameStatistics = { 0 }; swapChain->GetFrameStatistics(&prevFrameStatistics); + + while (!presentIdQueue.empty()) + { + presentIdQueue.pop(); + frameIdQueue.pop(); + } } commandList->Close(); @@ -364,32 +349,38 @@ namespace Optick payload.commandQueue->ExecuteCommandLists(1, (ID3D12CommandList*const*)&commandList); payload.commandQueue->Signal(payload.syncFence, frameNumber); - payload.presentIDs.push(currentPresentID + 1 + swapChainLatency); - payload.frameIDs.push(Core::Get().GetCurrentFrame(FrameType::CPU)); + // Save presentID to frameID correlation for the next present's vsync tag + if (frameID > 0) + { + UINT prevPresentID = 0; + HRESULT result = swapChain->GetLastPresentCount(&prevPresentID); + if (result == S_OK) + { + presentIdQueue.push(prevPresentID + 1); + frameIdQueue.push(frameID); + } + } - // Process VSync + // Process VSync / Presentation timing DXGI_FRAME_STATISTICS currentFrameStatistics = { 0 }; HRESULT result = swapChain->GetFrameStatistics(¤tFrameStatistics); - if ((result == S_OK) && (prevFrameStatistics.PresentCount < currentFrameStatistics.PresentCount)) + if ((result == S_OK) && (currentFrameStatistics.SyncQPCTime.QuadPart > prevFrameStatistics.SyncQPCTime.QuadPart)) { EventData& data = AddVSyncEvent("Present"); data.start = prevFrameStatistics.SyncQPCTime.QuadPart; data.finish = currentFrameStatistics.SyncQPCTime.QuadPart; - uint32_t droppedFrames = 0; - while (!payload.presentIDs.empty() && payload.presentIDs.front() <= prevFrameStatistics.PresentCount) + while (!presentIdQueue.empty() && presentIdQueue.front() <= prevFrameStatistics.PresentCount) { - if (payload.presentIDs.front() == prevFrameStatistics.PresentCount) + if (presentIdQueue.front() == prevFrameStatistics.PresentCount) { TagData& tag = AddVSyncTag(); tag.timestamp = prevFrameStatistics.SyncQPCTime.QuadPart; - tag.data = payload.frameIDs.front() + currentPresentID - currentFrameStatistics.PresentCount + droppedFrames; + tag.data = frameIdQueue.front(); } - else - droppedFrames++; - payload.presentIDs.pop(); - payload.frameIDs.pop(); + presentIdQueue.pop(); + frameIdQueue.pop(); } prevFrameStatistics = currentFrameStatistics; diff --git a/neo/libs/optick/optick_gpu.h b/neo/libs/optick/optick_gpu.h index 8134ca6d..f0693bc5 100644 --- a/neo/libs/optick/optick_gpu.h +++ b/neo/libs/optick/optick_gpu.h @@ -145,7 +145,7 @@ namespace Optick virtual void QueryTimestamp(void* context, int64_t* cpuTimestampOut) = 0; virtual void ResolveTimestamps(uint32_t nodeIndex, uint32_t startIndex, uint32_t count) = 0; virtual void WaitForFrame(uint32_t nodeIndex, uint64_t frameNumber) = 0; - virtual void Flip(void* swapChain) = 0; + virtual void Flip(void* swapChain, uint32_t frameID) = 0; virtual ~GPUProfiler(); }; diff --git a/neo/libs/optick/optick_gpu.vulkan.cpp b/neo/libs/optick/optick_gpu.vulkan.cpp index d9ce25b7..5c824e08 100644 --- a/neo/libs/optick/optick_gpu.vulkan.cpp +++ b/neo/libs/optick/optick_gpu.vulkan.cpp @@ -58,20 +58,22 @@ namespace Optick array frames; - uint64_t presentTime; - uint32_t presentID; - NodePayload() : vulkanFunctions(), device(VK_NULL_HANDLE), physicalDevice(VK_NULL_HANDLE), queue(VK_NULL_HANDLE), queryPool(VK_NULL_HANDLE), commandPool(VK_NULL_HANDLE), event(VK_NULL_HANDLE) {} ~NodePayload(); }; vector nodePayloads; + // VSync / Present Stats + uint64_t prevPresentTime; + uint32_t prevPresentID; + public: GPUProfilerVulkan(); ~GPUProfilerVulkan(); void InitDevice(VkDevice* devices, VkPhysicalDevice* physicalDevices, VkQueue* cmdQueues, uint32_t* cmdQueuesFamily, uint32_t nodeCount, const VulkanFunctions* functions); void QueryTimestamp(VkCommandBuffer commandBuffer, int64_t* outCpuTimestamp); + void Flip(VkSwapchainKHR swapChain); // Interface implementation @@ -86,7 +88,10 @@ namespace Optick void WaitForFrame(uint32_t nodeIndex, uint64_t frameNumber) override; - void Flip(void* swapChain) override; + void Flip(void* swapChain, uint32_t frameID) override + { + Flip(static_cast(swapChain)); + } }; void InitGpuVulkan(VkDevice* vkDevices, VkPhysicalDevice* vkPhysicalDevices, VkQueue* vkQueues, uint32_t* cmdQueuesFamily, uint32_t numQueues, const VulkanFunctions* functions) @@ -98,6 +103,8 @@ namespace Optick GPUProfilerVulkan::GPUProfilerVulkan() { + prevPresentTime = 0; + prevPresentID = 0; } void GPUProfilerVulkan::InitDevice(VkDevice* devices, VkPhysicalDevice* physicalDevices, VkQueue* cmdQueues, uint32_t* cmdQueuesFamily, uint32_t nodeCount, const VulkanFunctions* functions) @@ -251,7 +258,7 @@ namespace Optick NodePayload* payload = nodePayloads[nodeIndex]; - OPTICK_VK_CHECK((VkResult)(*vulkanFunctions.vkGetQueryPoolResults)(payload->device, payload->queryPool, startIndex, count, 8 * count, &nodes[nodeIndex]->queryGpuTimestamps[startIndex], 8, VK_QUERY_RESULT_64_BIT)); + OPTICK_VK_CHECK((VkResult)(*vulkanFunctions.vkGetQueryPoolResults)(payload->device, payload->queryPool, startIndex, count, 8 * (size_t)count, &nodes[nodeIndex]->queryGpuTimestamps[startIndex], 8, VK_QUERY_RESULT_64_BIT)); (*vulkanFunctions.vkResetQueryPool)(payload->device, payload->queryPool, startIndex, count); // Convert GPU timestamps => CPU Timestamps @@ -272,7 +279,7 @@ namespace Optick } while (r != VK_SUCCESS); } - void GPUProfilerVulkan::Flip(void* swapChain) + void GPUProfilerVulkan::Flip(VkSwapchainKHR swapChain) { OPTICK_CATEGORY("GPUProfilerVulkan::Flip", Category::Debug); @@ -340,8 +347,8 @@ namespace Optick { currentFrame.queryIndexStart = 0; currentFrame.queryIndexCount = queryEnd; - payload.presentTime = 0; - payload.presentID = 0; + prevPresentTime = 0; + prevPresentID = 0; } // Preparing Next Frame @@ -376,18 +383,18 @@ namespace Optick { // Process Presentation Timing / VSync if swap image was actually presented (i.e. not dropped) VkPastPresentationTimingGOOGLE presentTiming = queryPresentTimings[presentIndex]; - if (presentTiming.actualPresentTime > payload.presentTime) + if (presentTiming.actualPresentTime > prevPresentTime) { EventData& data = AddVSyncEvent("Present"); - data.start = payload.presentTime; + data.start = prevPresentTime; data.finish = presentTiming.actualPresentTime; TagData& tag = AddVSyncTag(); - tag.timestamp = payload.presentTime; - tag.data = payload.presentID; + tag.timestamp = prevPresentTime; + tag.data = prevPresentID; - payload.presentTime = presentTiming.actualPresentTime; - payload.presentID = presentTiming.presentID; + prevPresentTime = presentTiming.actualPresentTime; + prevPresentID = presentTiming.presentID; } } }