// 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