Diligent Engine  v.2.4.g
QueryBase.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2019-2021 Diligent Graphics LLC
3  * Copyright 2015-2019 Egor Yusov
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * In no event and under no legal theory, whether in tort (including negligence),
18  * contract, or otherwise, unless required by applicable law (such as deliberate
19  * and grossly negligent acts) or agreed to in writing, shall any Contributor be
20  * liable for any damages, including any direct, indirect, special, incidental,
21  * or consequential damages of any character arising as a result of this License or
22  * out of the use or inability to use the software (including but not limited to damages
23  * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
24  * all other commercial damages or losses), even if such Contributor has been advised
25  * of the possibility of such damages.
26  */
27 
28 #pragma once
29 
32 
33 #include "Query.h"
34 #include "DeviceObjectBase.hpp"
35 #include "GraphicsTypes.h"
36 #include "RefCntAutoPtr.hpp"
37 
38 namespace Diligent
39 {
40 
42 
44 template <typename EngineImplTraits>
45 class QueryBase : public DeviceObjectBase<typename EngineImplTraits::QueryInterface, typename EngineImplTraits::RenderDeviceImplType, QueryDesc>
46 {
47 public:
48  // Base interface this class inherits (IQueryD3D12, IQueryVk, etc.)
49  using BaseInterface = typename EngineImplTraits::QueryInterface;
50 
51  // Render device implementation type (RenderDeviceD3D12Impl, RenderDeviceVkImpl, etc.).
52  using RenderDeviceImplType = typename EngineImplTraits::RenderDeviceImplType;
53 
54  enum class QueryState
55  {
56  Inactive,
57  Querying,
58  Ended
59  };
60 
62 
69  RenderDeviceImplType* pDevice,
70  const QueryDesc& Desc,
71  bool bIsDeviceInternal = false) :
72  TDeviceObjectBase{pRefCounters, pDevice, Desc, bIsDeviceInternal}
73  {
74  const auto& deviceFeatures = pDevice->GetDeviceCaps().Features;
75  static_assert(QUERY_TYPE_NUM_TYPES == 6, "Not all QUERY_TYPE enum values are handled below");
76  switch (Desc.Type)
77  {
79  if (!deviceFeatures.OcclusionQueries)
80  LOG_ERROR_AND_THROW("Occlusion queries are not supported by this device");
81  break;
82 
84  if (!deviceFeatures.BinaryOcclusionQueries)
85  LOG_ERROR_AND_THROW("Binary occlusion queries are not supported by this device");
86  break;
87 
89  if (!deviceFeatures.TimestampQueries)
90  LOG_ERROR_AND_THROW("Timestamp queries are not supported by this device");
91  break;
92 
94  if (!deviceFeatures.PipelineStatisticsQueries)
95  LOG_ERROR_AND_THROW("Pipeline statistics queries are not supported by this device");
96  break;
97 
99  if (!deviceFeatures.DurationQueries)
100  LOG_ERROR_AND_THROW("Duration queries are not supported by this device");
101  break;
102 
103  default:
104  UNEXPECTED("Unexpected device type");
105  }
106  }
107 
109  {
111  {
112  LOG_ERROR_MESSAGE("Destroying query '", this->m_Desc.Name,
113  "' that is in querying state. End the query before releasing it.");
114  }
115  }
116 
118 
119  virtual void DILIGENT_CALL_TYPE Invalidate() override
120  {
122  }
123 
124  void OnBeginQuery(struct IDeviceContext* pContext)
125  {
127  "BeginQuery cannot be called on timestamp query '", this->m_Desc.Name,
128  "'. Call EndQuery to set the timestamp.");
129 
131  "Attempting to begin query '", this->m_Desc.Name,
132  "' twice. A query must be ended before it can be begun again.");
133 
134  m_pContext = pContext;
136  }
137 
138  void OnEndQuery(IDeviceContext* pContext)
139  {
140  if (this->m_Desc.Type != QUERY_TYPE_TIMESTAMP)
141  {
143  "Attempting to end query '", this->m_Desc.Name, "' that has not been begun.");
144  }
145 
146  if (m_pContext == nullptr)
147  {
149  "Ending query '", this->m_Desc.Name, "' that has not been begun.");
150  m_pContext = pContext;
151  }
152  else
153  {
154  DEV_CHECK_ERR(m_pContext == pContext, "Query '", this->m_Desc.Name, "' has been begun by another context.");
155  }
156 
158  }
159 
161  {
162  return m_State;
163  }
164 
165  void CheckQueryDataPtr(void* pData, Uint32 DataSize)
166  {
168  "Attempting to get data of query '", this->m_Desc.Name, "' that has not been ended.");
169 
170  if (pData != nullptr)
171  {
172  DEV_CHECK_ERR(*reinterpret_cast<QUERY_TYPE*>(pData) == this->m_Desc.Type, "Incorrect query data structure type.");
173 
174  static_assert(QUERY_TYPE_NUM_TYPES == 6, "Not all QUERY_TYPE enum values are handled below.");
175  switch (this->m_Desc.Type)
176  {
178  UNEXPECTED("Undefined query type is unexpected.");
179  break;
180 
182  DEV_CHECK_ERR(DataSize == sizeof(QueryDataOcclusion),
183  "The size of query data (", DataSize, ") is incorrect: ", sizeof(QueryDataOcclusion), " (aka sizeof(QueryDataOcclusion)) is expected.");
184  break;
185 
187  DEV_CHECK_ERR(DataSize == sizeof(QueryDataBinaryOcclusion),
188  "The size of query data (", DataSize, ") is incorrect: ", sizeof(QueryDataBinaryOcclusion), " (aka sizeof(QueryDataBinaryOcclusion)) is expected.");
189  break;
190 
192  DEV_CHECK_ERR(DataSize == sizeof(QueryDataTimestamp),
193  "The size of query data (", DataSize, ") is incorrect: ", sizeof(QueryDataTimestamp), " (aka sizeof(QueryDataTimestamp)) is expected.");
194  break;
195 
197  DEV_CHECK_ERR(DataSize == sizeof(QueryDataPipelineStatistics),
198  "The size of query data (", DataSize, ") is incorrect: ", sizeof(QueryDataPipelineStatistics), " (aka sizeof(QueryDataPipelineStatistics)) is expected.");
199  break;
200 
201  case QUERY_TYPE_DURATION:
202  DEV_CHECK_ERR(DataSize == sizeof(QueryDataDuration),
203  "The size of query data (", DataSize, ") is incorrect: ", sizeof(QueryDataDuration), " (aka sizeof(QueryDataDuration)) is expected.");
204  break;
205 
206  default:
207  UNEXPECTED("Unexpected query type.");
208  }
209  }
210  }
211 
212 protected:
214 
216 };
217 
218 } // namespace Diligent
Diligent::QueryBase::QueryState::Ended
@ Ended
Diligent::IReferenceCounters
Base interface for a reference counter object that stores the number of strong and weak references an...
Definition: ReferenceCounters.h:44
LOG_ERROR_MESSAGE
#define LOG_ERROR_MESSAGE(...)
Definition: Errors.hpp:122
Diligent::QueryDataBinaryOcclusion
Binary occlusion query data. This structure is filled by IQuery::GetData() for Diligent::QUERY_TYPE_B...
Definition: Query.h:57
LOG_ERROR_AND_THROW
#define LOG_ERROR_AND_THROW(...)
Definition: Errors.hpp:101
DeviceObjectBase.hpp
Diligent::QueryDesc
Query description.
Definition: Query.h:150
Diligent::QueryDataTimestamp
Timestamp query data. This structure is filled by IQuery::GetData() for Diligent::QUERY_TYPE_TIMESTAM...
Definition: Query.h:70
Diligent::QueryBase::QueryState::Inactive
@ Inactive
UNEXPECTED
#define UNEXPECTED(...)
Definition: DebugUtilities.hpp:77
Diligent::QueryBase::OnBeginQuery
void OnBeginQuery(struct IDeviceContext *pContext)
Definition: QueryBase.hpp:124
Diligent::DeviceObjectBase< EngineImplTraits::QueryInterface, EngineImplTraits::RenderDeviceImplType, QueryDesc >::m_Desc
QueryDesc m_Desc
Object description.
Definition: DeviceObjectBase.hpp:182
Diligent::QueryBase< EngineGLImplTraits >::QueryState
QueryState
Definition: QueryBase.hpp:54
Diligent::QueryBase::GetState
QueryState GetState() const
Definition: QueryBase.hpp:160
Diligent::QueryBase< EngineGLImplTraits >::RenderDeviceImplType
typename EngineGLImplTraits ::RenderDeviceImplType RenderDeviceImplType
Definition: QueryBase.hpp:52
DEV_CHECK_ERR
#define DEV_CHECK_ERR(...)
Definition: DebugUtilities.hpp:90
Query.h
Diligent::QueryDataOcclusion
Occlusion query data. This structure is filled by IQuery::GetData() for Diligent::QUERY_TYPE_OCCLUSIO...
Definition: Query.h:44
Diligent::QUERY_TYPE_BINARY_OCCLUSION
@ QUERY_TYPE_BINARY_OCCLUSION
Acts like QUERY_TYPE_OCCLUSION except that it returns simply a binary true/false result: false indica...
Definition: GraphicsTypes.h:1458
Diligent::QueryBase::~QueryBase
~QueryBase()
Definition: QueryBase.hpp:108
Diligent::QueryDesc::Type
enum QUERY_TYPE Type
Query type, see Diligent::QUERY_TYPE.
Definition: Query.h:153
IMPLEMENT_QUERY_INTERFACE_IN_PLACE
#define IMPLEMENT_QUERY_INTERFACE_IN_PLACE(InterfaceID, ParentClassName)
Definition: ObjectBase.hpp:59
Diligent::RefCntAutoPtr
Template class that implements reference counting.
Definition: RefCntAutoPtr.hpp:73
DILIGENT_CALL_TYPE
#define DILIGENT_CALL_TYPE
Definition: CommonDefinitions.h:45
Diligent::QueryBase::QueryBase
QueryBase(IReferenceCounters *pRefCounters, RenderDeviceImplType *pDevice, const QueryDesc &Desc, bool bIsDeviceInternal=false)
Definition: QueryBase.hpp:68
Diligent::Uint32
uint32_t Uint32
32-bit unsigned integer
Definition: BasicTypes.h:51
Diligent::QUERY_TYPE_DURATION
@ QUERY_TYPE_DURATION
Gets the number of high-frequency counter ticks between IDeviceContext::BeginQuery and IDeviceContext...
Definition: GraphicsTypes.h:1470
Diligent::QueryBase::m_State
QueryState m_State
Definition: QueryBase.hpp:215
Diligent::QueryDataDuration
Duration query data. This structure is filled by IQuery::GetData() for Diligent::QUERY_TYPE_DURATION ...
Definition: Query.h:132
Diligent::QUERY_TYPE_UNDEFINED
@ QUERY_TYPE_UNDEFINED
Query type is undefined.
Definition: GraphicsTypes.h:1449
Diligent::QUERY_TYPE_NUM_TYPES
@ QUERY_TYPE_NUM_TYPES
The number of query types in the enum.
Definition: GraphicsTypes.h:1473
Diligent::QUERY_TYPE_OCCLUSION
@ QUERY_TYPE_OCCLUSION
Gets the number of samples that passed the depth and stencil tests in between IDeviceContext::BeginQu...
Definition: GraphicsTypes.h:1453
Diligent::QueryDataPipelineStatistics
Pipeline statistics query data. This structure is filled by IQuery::GetData() for Diligent::QUERY_TYP...
Definition: Query.h:88
Diligent::QueryBase::CheckQueryDataPtr
void CheckQueryDataPtr(void *pData, Uint32 DataSize)
Definition: QueryBase.hpp:165
Diligent::QueryBase::QueryState::Querying
@ Querying
Diligent::IDeviceContext
Device context interface.
Definition: DeviceContext.h:1460
Diligent::QueryBase< EngineGLImplTraits >::BaseInterface
typename EngineGLImplTraits ::QueryInterface BaseInterface
Definition: QueryBase.hpp:49
Diligent::QUERY_TYPE
QUERY_TYPE
Query type.
Definition: GraphicsTypes.h:1446
Diligent::QueryBase::Invalidate
virtual void Invalidate() override
Definition: QueryBase.hpp:119
RefCntAutoPtr.hpp
GraphicsTypes.h
Diligent::QUERY_TYPE_TIMESTAMP
@ QUERY_TYPE_TIMESTAMP
Gets the GPU timestamp corresponding to IDeviceContext::EndQuery call. Fot this query type IDeviceCon...
Definition: GraphicsTypes.h:1462
Diligent::QueryBase::m_pContext
RefCntAutoPtr< IDeviceContext > m_pContext
Definition: QueryBase.hpp:213
Diligent::QUERY_TYPE_PIPELINE_STATISTICS
@ QUERY_TYPE_PIPELINE_STATISTICS
Gets pipeline statistics, such as the number of pixel shader invocations in between IDeviceContext::B...
Definition: GraphicsTypes.h:1466
Diligent::DeviceObjectAttribs::Name
const Char * Name
Object name.
Definition: GraphicsTypes.h:1199
Diligent::DeviceObjectBase
Template class implementing base functionality of the device object.
Definition: DeviceObjectBase.hpp:45
Diligent::QueryBase::OnEndQuery
void OnEndQuery(IDeviceContext *pContext)
Definition: QueryBase.hpp:138
Diligent
The library uses Direct3D-style math:
Definition: AdvancedMath.hpp:37
Diligent::QueryBase::TDeviceObjectBase
DeviceObjectBase< BaseInterface, RenderDeviceImplType, QueryDesc > TDeviceObjectBase
Definition: QueryBase.hpp:61
Diligent::QueryBase
Template class implementing base functionality of the query object.
Definition: QueryBase.hpp:45