// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. #pragma once #if GRAPHICS_API_VULKAN #include "Engine/Graphics/GPUTimerQuery.h" #include "GPUDeviceVulkan.h" /// /// GPU timer query object for Vulkan backend. /// class GPUTimerQueryVulkan : public GPUResourceVulkan { private: struct Query { BufferedQueryPoolVulkan* Pool; uint32 Index; uint64 Result; }; struct QueryPair { Query Begin; Query End; }; bool _hasResult = false; bool _endCalled = false; bool _interrupted = false; float _timeDelta = 0.0f; int32 _queryIndex; Array> _queries; public: /// /// Initializes a new instance of the class. /// /// The graphics device. GPUTimerQueryVulkan(GPUDeviceVulkan* device); public: /// /// Interrupts an in-progress query, allowing the command buffer to submitted. Interrupted queries must be resumed using Resume(). /// /// The GPU commands buffer. void Interrupt(CmdBufferVulkan* cmdBuffer); /// /// Resumes an interrupted query, restoring it back to its original in-progress state. /// /// The GPU commands buffer. void Resume(CmdBufferVulkan* cmdBuffer); private: bool GetResult(Query& query); void WriteTimestamp(CmdBufferVulkan* cmdBuffer, Query& query) const; bool TryGetResult(); bool UseQueries(); public: // [GPUTimerQuery] void Begin() override; void End() override; bool HasResult() override { if (!_endCalled) return false; if (_hasResult) return true; return TryGetResult(); } float GetResult() override { if (_hasResult) { return _timeDelta; } TryGetResult(); return _timeDelta; } protected: // [GPUResourceVulkan] void OnReleaseGPU() override; }; #endif