// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. #pragma once #if GRAPHICS_API_DIRECTX12 class TimerQueryDX12; class GPUDeviceDX12; class GPUContextDX12; class GPUBuffer; #include "CommandQueueDX12.h" /// /// GPU queries heap for DirectX 12 backend. /// class QueryHeapDX12 { public: /// /// The query element handle. /// typedef int32 ElementHandle; private: struct QueryBatch { /// /// The synchronization point when query has been submitted to be executed. /// SyncPointDX12 Sync; /// /// The first element in the batch (inclusive). /// int32 Start = 0; /// /// The amount of elements added to this batch. /// int32 Count = 0; /// /// Is the batch still open for more begin/end queries. /// bool Open = false; /// /// Clears this batch. /// inline void Clear() { Sync = SyncPointDX12(); Start = 0; Count = 0; Open = false; } /// /// Checks if this query batch contains a given element contains the element. /// /// The index of the element. /// True if element is in this query, otherwise false. bool ContainsElement(int32 elementIndex) const { return elementIndex >= Start && elementIndex < Start + Count; } }; private: GPUDeviceDX12* _device; ID3D12QueryHeap* _queryHeap; ID3D12Resource* _resultBuffer; D3D12_QUERY_TYPE _queryType; D3D12_QUERY_HEAP_TYPE _queryHeapType; int32 _currentIndex; int32 _resultSize; int32 _queryHeapCount; QueryBatch _currentBatch; Array _batches; Array _resultData; public: /// /// Initializes a new instance of the class. /// /// The device. /// Type of the query heap. /// The query heap count. QueryHeapDX12(GPUDeviceDX12* device, const D3D12_QUERY_HEAP_TYPE& queryHeapType, int32 queryHeapCount); public: /// /// Initializes this instance. /// /// True if failed, otherwise false. bool Init(); /// /// Destroys this instance. /// void Destroy(); public: /// /// Gets the query heap capacity. /// /// The queries count. FORCE_INLINE int32 GetQueryHeapCount() const { return _queryHeapCount; } /// /// Gets the size of the result value (in bytes). /// /// The size of the query result value (in bytes). FORCE_INLINE int32 GetResultSize() const { return _resultSize; } /// /// Gets the result buffer (CPU readable via Map/Unmap). /// /// The query results buffer. FORCE_INLINE ID3D12Resource* GetResultBuffer() const { return _resultBuffer; } public: /// /// Stops tracking the current batch of begin/end query calls that will be resolved together. This implicitly starts a new batch. /// /// The context. void EndQueryBatchAndResolveQueryData(GPUContextDX12* context); /// /// Allocates the query heap element. /// /// The context. /// The result handle. void AllocQuery(GPUContextDX12* context, ElementHandle& handle); /// /// Calls BeginQuery on command list for the given query heap slot. /// /// The context. /// The query handle. void BeginQuery(GPUContextDX12* context, ElementHandle& handle); /// /// Calls EndQuery on command list for the given query heap slot. /// /// The context. /// The query handle. void EndQuery(GPUContextDX12* context, ElementHandle& handle); /// /// Determines whether the specified query handle is ready to read data (command list has been executed by the GPU). /// /// The handle. /// true if the specified query handle is ready; otherwise, false. bool IsReady(ElementHandle& handle); /// /// Resolves the query (or skips if already resolved). /// /// The result handle. /// The pointer to the resolved query data. void* ResolveQuery(ElementHandle& handle); private: /// /// Starts tracking a new batch of begin/end query calls that will be resolved together /// void StartQueryBatch(); }; #endif