Kaynağa Gözat

Queries WIP

Marko Pintera 12 yıl önce
ebeveyn
işleme
04132bc6d9
34 değiştirilmiş dosya ile 888 ekleme ve 3 silme
  1. 6 0
      CamelotCore/CamelotCore.vcxproj
  2. 18 0
      CamelotCore/CamelotCore.vcxproj.filters
  3. 38 0
      CamelotCore/Include/CmEventQuery.h
  4. 4 0
      CamelotCore/Include/CmPrerequisites.h
  5. 39 0
      CamelotCore/Include/CmQueryManager.h
  6. 48 0
      CamelotCore/Include/CmTimerQuery.h
  7. 10 0
      CamelotCore/Source/CmEventQuery.cpp
  8. 62 0
      CamelotCore/Source/CmQueryManager.cpp
  9. 10 0
      CamelotCore/Source/CmTimerQuery.cpp
  10. 6 0
      CamelotD3D11RenderSystem/CamelotD3D11RenderSystem.vcxproj
  11. 18 0
      CamelotD3D11RenderSystem/CamelotD3D11RenderSystem.vcxproj.filters
  12. 32 0
      CamelotD3D11RenderSystem/Include/CmD3D11EventQuery.h
  13. 14 0
      CamelotD3D11RenderSystem/Include/CmD3D11QueryManager.h
  14. 40 0
      CamelotD3D11RenderSystem/Include/CmD3D11TimerQuery.h
  15. 47 0
      CamelotD3D11RenderSystem/Source/CmD3D11EventQuery.cpp
  16. 22 0
      CamelotD3D11RenderSystem/Source/CmD3D11QueryManager.cpp
  17. 42 0
      CamelotD3D11RenderSystem/Source/CmD3D11TimerQuery.cpp
  18. 6 0
      CamelotD3D9Renderer/CamelotD3D9Renderer.vcxproj
  19. 18 0
      CamelotD3D9Renderer/CamelotD3D9Renderer.vcxproj.filters
  20. 31 0
      CamelotD3D9Renderer/Include/CmD3D9EventQuery.h
  21. 14 0
      CamelotD3D9Renderer/Include/CmD3D9QueryManager.h
  22. 40 0
      CamelotD3D9Renderer/Include/CmD3D9TimerQuery.h
  23. 42 0
      CamelotD3D9Renderer/Source/CmD3D9EventQuery.cpp
  24. 22 0
      CamelotD3D9Renderer/Source/CmD3D9QueryManager.cpp
  25. 42 0
      CamelotD3D9Renderer/Source/CmD3D9TimerQuery.cpp
  26. 6 0
      CamelotGLRenderer/CamelotGLRenderer.vcxproj
  27. 18 0
      CamelotGLRenderer/CamelotGLRenderer.vcxproj.filters
  28. 31 0
      CamelotGLRenderer/Include/CmGLEventQuery.h
  29. 14 0
      CamelotGLRenderer/Include/CmGLQueryManager.h
  30. 41 0
      CamelotGLRenderer/Include/CmGLTimerQuery.h
  31. 40 0
      CamelotGLRenderer/Source/CmGLEventQuery.cpp
  32. 22 0
      CamelotGLRenderer/Source/CmGLQueryManager.cpp
  33. 42 0
      CamelotGLRenderer/Source/CmGLTimerQuery.cpp
  34. 3 3
      Opts.txt

+ 6 - 0
CamelotCore/CamelotCore.vcxproj

@@ -279,6 +279,7 @@
     <ClInclude Include="Include\CmDefaultRenderQueue.h" />
     <ClInclude Include="Include\CmDeferredCallManager.h" />
     <ClInclude Include="Include\CmDrawOps.h" />
+    <ClInclude Include="Include\CmEventQuery.h" />
     <ClInclude Include="Include\CmGameObjectHandle.h" />
     <ClInclude Include="Include\CmGameObject.h" />
     <ClInclude Include="Include\CmGameObjectRTTI.h" />
@@ -295,6 +296,7 @@
     <ClInclude Include="Include\CmPixelUtil.h" />
     <ClInclude Include="Include\CmPlatformWndProc.h" />
     <ClInclude Include="Include\CmProfiler.h" />
+    <ClInclude Include="Include\CmQueryManager.h" />
     <ClInclude Include="Include\CmRenderOperation.h" />
     <ClInclude Include="Include\CmRenderQueue.h" />
     <ClInclude Include="Include\CmSceneObjectRTTI.h" />
@@ -344,6 +346,7 @@
     <ClInclude Include="Include\CmSubMesh.h" />
     <ClInclude Include="Include\CmTextureView.h" />
     <ClInclude Include="Include\CmTextData.h" />
+    <ClInclude Include="Include\CmTimerQuery.h" />
     <ClInclude Include="Include\CmVertexBuffer.h" />
     <ClInclude Include="Include\CmHighLevelGpuProgram.h" />
     <ClInclude Include="Include\CmHighLevelGpuProgramManager.h" />
@@ -416,6 +419,7 @@
     <ClCompile Include="Source\CmCPUProfiler.cpp" />
     <ClCompile Include="Source\CmDefaultRenderQueue.cpp" />
     <ClCompile Include="Source\CmDeferredCallManager.cpp" />
+    <ClCompile Include="Source\CmEventQuery.cpp" />
     <ClCompile Include="Source\CmGameObjectHandle.cpp" />
     <ClCompile Include="Source\CmGameObject.cpp" />
     <ClCompile Include="Source\CmApplication.cpp" />
@@ -458,10 +462,12 @@
     <ClCompile Include="Source\CmPlatform.cpp" />
     <ClCompile Include="Source\CmPlatformWndProc.cpp" />
     <ClCompile Include="Source\CmProfiler.cpp" />
+    <ClCompile Include="Source\CmQueryManager.cpp" />
     <ClCompile Include="Source\CmRenderer.cpp" />
     <ClCompile Include="Source\CmRenderQueue.cpp" />
     <ClCompile Include="Source\CmTextureView.cpp" />
     <ClCompile Include="Source\CmTextData.cpp" />
+    <ClCompile Include="Source\CmTimerQuery.cpp" />
     <ClCompile Include="Source\CmVertexBuffer.cpp" />
     <ClCompile Include="Source\CmHighLevelGpuProgram.cpp" />
     <ClCompile Include="Source\CmHighLevelGpuProgramManager.cpp" />

+ 18 - 0
CamelotCore/CamelotCore.vcxproj.filters

@@ -501,6 +501,15 @@
     <ClInclude Include="Include\CmSubMesh.h">
       <Filter>Header Files\RenderSystem</Filter>
     </ClInclude>
+    <ClInclude Include="Include\CmEventQuery.h">
+      <Filter>Header Files\RenderSystem</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\CmQueryManager.h">
+      <Filter>Header Files\RenderSystem</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\CmTimerQuery.h">
+      <Filter>Source Files\RenderSystem</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\CmApplication.cpp">
@@ -779,5 +788,14 @@
     <ClCompile Include="Source\CmVertexDataDesc.cpp">
       <Filter>Source Files\Resources</Filter>
     </ClCompile>
+    <ClCompile Include="Source\CmQueryManager.cpp">
+      <Filter>Source Files\RenderSystem</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\CmEventQuery.cpp">
+      <Filter>Source Files\RenderSystem</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\CmTimerQuery.cpp">
+      <Filter>Source Files\RenderSystem</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 38 - 0
CamelotCore/Include/CmEventQuery.h

@@ -0,0 +1,38 @@
+#pragma once
+
+#include "CmPrerequisites.h"
+
+namespace CamelotFramework
+{
+	/**
+	 * @brief	Represents a GPU query that gets triggered when GPU starts processing the query.
+	 * 			
+	 * @note	Normally GPU will have many commands in its command buffer. When EventQuery::begin is called it is placed
+	 * 			in that command buffer. Once the buffer empties and GPU reaches the EventQuery command, the query
+	 * 			callback is triggered.
+	 * 			
+	 *			Core thread only.
+	 */
+	class CM_EXPORT EventQuery
+	{
+	public:
+		virtual ~EventQuery() {}
+
+		/**
+		 * @brief	Starts the query. 
+		 * 			
+		 * @note	Once the query is started you may poll "isReady" method to check when query has finished,
+		 * 			or you may hook up an "onTriggered" callback and be notified that way.
+		 */
+		virtual void begin() = 0;
+
+		/**
+		 * @brief	Check if GPU has processed the query.
+		 */
+		virtual bool isReady() const = 0;
+
+		boost::signal<void()> onTriggered;
+
+		static EventQueryPtr create();
+	};
+}

+ 4 - 0
CamelotCore/Include/CmPrerequisites.h

@@ -129,6 +129,8 @@ namespace CamelotFramework
 	class RenderQueue;
 	struct ProfilerReport;
 	class VertexDataDesc;
+	class EventQuery;
+	class TimerQuery;
 	// Asset import
 	class SpecificImporter;
 	class Importer;
@@ -210,6 +212,8 @@ namespace CamelotFramework
 	typedef CoreThreadAccessor<CommandQueueSync> SyncedCoreAccessor;
 	typedef std::shared_ptr<CoreThreadAccessor<CommandQueueNoSync>> CoreAccessorPtr;
 	typedef std::shared_ptr<CoreThreadAccessor<CommandQueueSync>> SyncedCoreAccessorPtr;
+	typedef std::shared_ptr<EventQuery> EventQueryPtr;
+	typedef std::shared_ptr<TimerQuery> TimerQueryPtr;
 }
 
 /************************************************************************/

+ 39 - 0
CamelotCore/Include/CmQueryManager.h

@@ -0,0 +1,39 @@
+#pragma once
+
+#include "CmPrerequisites.h"
+#include "CmEventQuery.h"
+#include "CmModule.h"
+
+namespace CamelotFramework
+{
+	/**
+	 * @brief	Handles creation and destruction of GPU queries.
+	 * 			
+	 * @note	Core thread only.
+	 */
+	class CM_EXPORT QueryManager : public Module<QueryManager>
+	{
+	public:
+		QueryManager();
+
+		virtual EventQueryPtr createEventQuery() const = 0;
+		virtual TimerQueryPtr createTimerQuery() const = 0;
+
+		/**
+		 * @note	Internal method, called every frame.
+		 */
+		void update();
+
+	protected:
+		mutable Vector<EventQuery*>::type mEventQueries[2]; // Two buffers so we can ping-pong between them
+		mutable Vector<TimerQuery*>::type mTimerQueries[2];
+		UINT32 mBufferIdx;
+
+	protected:
+		friend class EventQuery;
+		friend class TimerQuery;
+
+		static void deleteEventQuery(EventQuery* query);
+		static void deleteTimerQuery(TimerQuery* query);
+	};
+}

+ 48 - 0
CamelotCore/Include/CmTimerQuery.h

@@ -0,0 +1,48 @@
+#pragma once
+
+#include "CmPrerequisites.h"
+
+namespace CamelotFramework
+{
+	/**
+	 * @brief	Represents a GPU query that measures execution time of GPU operations. The query will measure
+	 * 			any GPU operations that take place between its "begin" and "end" calls.
+	 * 			
+	 * @note	Core thread only.
+	 */
+	class CM_EXPORT TimerQuery
+	{
+	public:
+		virtual ~TimerQuery() {}
+
+		/**
+		 * @brief	Starts the counter. 
+		 * 			
+		 * @note	Place any commands you want to measure after this call. Call "end" when done.
+		 */
+		virtual void begin() = 0;
+
+		/**
+		 * @brief	Stops the counter.
+		 */
+		virtual void end() = 0;
+
+		/**
+		 * @brief	Check if GPU has processed the query.
+		 */
+		virtual bool isReady() const = 0;
+
+		/**
+		 * @brief	Returns the time it took for the query to execute.
+		 *
+		 * @return	The time milliseconds.
+		 * 			
+		 * @note	Only valid after "isReady" returns true.
+		 */
+		virtual UINT64 getTimeMs() const = 0;
+
+		boost::signal<void(UINT64)> onTriggered;
+
+		static TimerQueryPtr create();
+	};
+}

+ 10 - 0
CamelotCore/Source/CmEventQuery.cpp

@@ -0,0 +1,10 @@
+#include "CmEventQuery.h"
+#include "CmQueryManager.h"
+
+namespace CamelotFramework
+{
+	EventQueryPtr EventQuery::create()
+	{
+		return QueryManager::instance().createEventQuery();
+	}
+}

+ 62 - 0
CamelotCore/Source/CmQueryManager.cpp

@@ -0,0 +1,62 @@
+#include "CmQueryManager.h"
+#include "CmEventQuery.h"
+#include "CmTimerQuery.h"
+
+namespace CamelotFramework
+{
+	QueryManager::QueryManager()
+		:mBufferIdx(0)
+	{
+
+	}
+
+	void QueryManager::update()
+	{
+		UINT32 otherBufferIdx = (mBufferIdx + 1) % 2;
+		
+		for(auto& query : mEventQueries[mBufferIdx])
+		{
+			if(query->isReady())
+				query->onTriggered();
+			else
+				mEventQueries[otherBufferIdx].push_back(query);
+		}
+
+		for(auto& query : mTimerQueries[mBufferIdx])
+		{
+			if(query->isReady())
+				query->onTriggered(query->getTimeMs());
+			else
+				mTimerQueries[otherBufferIdx].push_back(query);
+		}
+
+		mEventQueries[mBufferIdx].clear();
+		mTimerQueries[mBufferIdx].clear();
+
+		mBufferIdx = otherBufferIdx;
+	}
+
+	void QueryManager::deleteEventQuery(EventQuery* query)
+	{
+		UINT32 bufferIdx = instance().mBufferIdx;
+
+		auto iterFind = std::find(instance().mEventQueries[bufferIdx].begin(), instance().mEventQueries[bufferIdx].end(), query);
+
+		if(iterFind != instance().mEventQueries[bufferIdx].end())
+			instance().mEventQueries[bufferIdx].erase(iterFind);
+
+		cm_delete(query);
+	}
+
+	void QueryManager::deleteTimerQuery(TimerQuery* query)
+	{
+		UINT32 bufferIdx = instance().mBufferIdx;
+
+		auto iterFind = std::find(instance().mTimerQueries[bufferIdx].begin(), instance().mTimerQueries[bufferIdx].end(), query);
+
+		if(iterFind != instance().mTimerQueries[bufferIdx].end())
+			instance().mTimerQueries[bufferIdx].erase(iterFind);
+
+		cm_delete(query);
+	}
+}

+ 10 - 0
CamelotCore/Source/CmTimerQuery.cpp

@@ -0,0 +1,10 @@
+#include "CmTimerQuery.h"
+#include "CmQueryManager.h"
+
+namespace CamelotFramework
+{
+	TimerQueryPtr TimerQuery::create()
+	{
+		return QueryManager::instance().createTimerQuery();
+	}
+}

+ 6 - 0
CamelotD3D11RenderSystem/CamelotD3D11RenderSystem.vcxproj

@@ -234,6 +234,7 @@
   <ItemGroup>
     <ClInclude Include="Include\CmD3D11BlendState.h" />
     <ClInclude Include="Include\CmD3D11DepthStencilState.h" />
+    <ClInclude Include="Include\CmD3D11EventQuery.h" />
     <ClInclude Include="Include\CmD3D11GpuBuffer.h" />
     <ClInclude Include="Include\CmD3D11GpuBufferView.h" />
     <ClInclude Include="Include\CmD3D11HardwareBufferManager.h" />
@@ -252,8 +253,10 @@
     <ClInclude Include="Include\CmD3D11MultiRenderTexture.h" />
     <ClInclude Include="Include\CmD3D11GpuParamBlockBuffer.h" />
     <ClInclude Include="Include\CmD3D11Prerequisites.h" />
+    <ClInclude Include="Include\CmD3D11QueryManager.h" />
     <ClInclude Include="Include\CmD3D11RenderUtility.h" />
     <ClInclude Include="Include\CmD3D11TextureView.h" />
+    <ClInclude Include="Include\CmD3D11TimerQuery.h" />
     <ClInclude Include="Include\CmD3D11VertexBuffer.h" />
     <ClInclude Include="Include\CmD3D11RasterizerState.h" />
     <ClInclude Include="Include\CmD3D11RenderStateManager.h" />
@@ -275,6 +278,7 @@
     <ClCompile Include="Source\CmD3D11Device.cpp" />
     <ClCompile Include="Source\CmD3D11Driver.cpp" />
     <ClCompile Include="Source\CmD3D11DriverList.cpp" />
+    <ClCompile Include="Source\CmD3D11EventQuery.cpp" />
     <ClCompile Include="Source\CmD3D11GpuBuffer.cpp" />
     <ClCompile Include="Source\CmD3D11GpuBufferView.cpp" />
     <ClCompile Include="Source\CmD3D11GpuParamBlockBuffer.cpp" />
@@ -289,8 +293,10 @@
     <ClCompile Include="Source\CmD3D11InputLayoutManager.cpp" />
     <ClCompile Include="Source\CmD3D11Mappings.cpp" />
     <ClCompile Include="Source\CmD3D11Plugin.cpp" />
+    <ClCompile Include="Source\CmD3D11QueryManager.cpp" />
     <ClCompile Include="Source\CmD3D11RenderUtility.cpp" />
     <ClCompile Include="Source\CmD3D11TextureView.cpp" />
+    <ClCompile Include="Source\CmD3D11TimerQuery.cpp" />
     <ClCompile Include="Source\CmD3D11VertexBuffer.cpp" />
     <ClCompile Include="Source\CmD3D11MultiRenderTexture.cpp" />
     <ClCompile Include="Source\CmD3D11RasterizerState.cpp" />

+ 18 - 0
CamelotD3D11RenderSystem/CamelotD3D11RenderSystem.vcxproj.filters

@@ -126,6 +126,15 @@
     <ClInclude Include="Include\CmD3D11RenderUtility.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Include\CmD3D11EventQuery.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\CmD3D11QueryManager.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\CmD3D11TimerQuery.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\CmD3D11GpuProgram.cpp">
@@ -233,5 +242,14 @@
     <ClCompile Include="Source\CmD3D11RenderUtility.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\CmD3D11EventQuery.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\CmD3D11QueryManager.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\CmD3D11TimerQuery.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 32 - 0
CamelotD3D11RenderSystem/Include/CmD3D11EventQuery.h

@@ -0,0 +1,32 @@
+#pragma once
+
+#include "CmD3D11Prerequisites.h"
+#include "CmEventQuery.h"
+
+namespace CamelotFramework
+{
+	/**
+	 * @copydoc EventQuery
+	 */
+	class CM_D3D11_EXPORT D3D11EventQuery : public EventQuery
+	{
+	public:
+		D3D11EventQuery();
+		~D3D11EventQuery();
+
+		/**
+		 * @copydoc EventQuery::begin
+		 */
+		virtual void begin();
+
+		/**
+		 * @copydoc EventQuery::isReady
+		 */
+		virtual bool isReady() const;
+
+	private:
+		ID3D11Query* mQuery;
+		ID3D11DeviceContext* mContext;
+		bool mInitialized;
+	};
+}

+ 14 - 0
CamelotD3D11RenderSystem/Include/CmD3D11QueryManager.h

@@ -0,0 +1,14 @@
+#pragma once
+
+#include "CmD3D11Prerequisites.h"
+#include "CmQueryManager.h"
+
+namespace CamelotFramework
+{
+	class CM_D3D11_EXPORT D3D11QueryManager : public QueryManager
+	{
+	public:
+		EventQueryPtr createEventQuery() const;
+		TimerQueryPtr createTimerQuery() const;
+	};
+}

+ 40 - 0
CamelotD3D11RenderSystem/Include/CmD3D11TimerQuery.h

@@ -0,0 +1,40 @@
+#pragma once
+
+#include "CmD3D11Prerequisites.h"
+#include "CmTimerQuery.h"
+
+namespace CamelotFramework
+{
+	/**
+	 * @copydoc TimerQuery
+	 */
+	class CM_D3D11_EXPORT D3D11TimerQuery : public TimerQuery
+	{
+	public:
+		D3D11TimerQuery();
+		~D3D11TimerQuery();
+
+		/**
+		 * @copydoc TimerQuery::begin
+		 */
+		virtual void begin();
+
+		/**
+		 * @copydoc TimerQuery::end
+		 */
+		virtual void end();
+
+		/**
+		 * @copydoc TimerQuery::isReady
+		 */
+		virtual bool isReady() const;
+
+		/**
+		 * @copydoc TimerQuery::getTimeMs
+		 */
+		virtual UINT64 getTimeMs() const;
+
+	private:
+		bool mInitialized;
+	};
+}

+ 47 - 0
CamelotD3D11RenderSystem/Source/CmD3D11EventQuery.cpp

@@ -0,0 +1,47 @@
+#include "CmD3D11EventQuery.h"
+#include "CmD3D11RenderSystem.h"
+#include "CmD3D11Device.h"
+#include "CmException.h"
+
+namespace CamelotFramework
+{
+	D3D11EventQuery::D3D11EventQuery()
+		:mQuery(nullptr), mInitialized(false)
+	{
+
+	}
+
+	D3D11EventQuery::~D3D11EventQuery()
+	{
+		if(mInitialized)
+		{
+			mQuery->Release();
+		}
+	}
+
+	void D3D11EventQuery::begin()
+	{
+		D3D11RenderSystem* rs = static_cast<D3D11RenderSystem*>(RenderSystem::instancePtr());
+		D3D11Device& device = rs->getPrimaryDevice();
+
+		D3D11_QUERY_DESC queryDesc;
+		queryDesc.Query = D3D11_QUERY_EVENT;
+
+		HRESULT hr = device.getD3D11Device()->CreateQuery(&queryDesc, &mQuery);
+		if(hr != S_OK)
+		{
+			CM_EXCEPT(RenderingAPIException, "Failed to create an Event query.");
+		}
+
+		mContext = device.getImmediateContext();
+		mContext->End(mQuery);
+
+		mInitialized = true;
+	}
+
+	bool D3D11EventQuery::isReady() const
+	{
+		BOOL queryData;
+		return mContext->GetData(mQuery, &queryData, sizeof(BOOL), 0) == S_OK;
+	}
+}

+ 22 - 0
CamelotD3D11RenderSystem/Source/CmD3D11QueryManager.cpp

@@ -0,0 +1,22 @@
+#include "CmD3D11QueryManager.h"
+#include "CmD3D11EventQuery.h"
+#include "CmD3D11TimerQuery.h"
+
+namespace CamelotFramework
+{
+	EventQueryPtr D3D11QueryManager::createEventQuery() const
+	{
+		EventQueryPtr query = std::shared_ptr<D3D11EventQuery>(cm_new<D3D11EventQuery>(), &QueryManager::deleteEventQuery, StdAlloc<GenAlloc>());  
+		mEventQueries[mBufferIdx].push_back(query.get());
+
+		return query;
+	}
+
+	TimerQueryPtr D3D11QueryManager::createTimerQuery() const
+	{
+		TimerQueryPtr query = std::shared_ptr<D3D11TimerQuery>(cm_new<D3D11TimerQuery>(), &QueryManager::deleteTimerQuery, StdAlloc<GenAlloc>());  
+		mTimerQueries[mBufferIdx].push_back(query.get());
+
+		return query;
+	}
+}

+ 42 - 0
CamelotD3D11RenderSystem/Source/CmD3D11TimerQuery.cpp

@@ -0,0 +1,42 @@
+#include "CmD3D11TimerQuery.h"
+
+namespace CamelotFramework
+{
+	D3D11TimerQuery::D3D11TimerQuery()
+		:mInitialized(false)
+	{
+
+	}
+
+	D3D11TimerQuery::~D3D11TimerQuery()
+	{
+		if(mInitialized)
+		{
+			// TODO
+		}
+	}
+
+	void D3D11TimerQuery::begin()
+	{
+		// TODO
+
+		mInitialized = true;
+	}
+
+	void D3D11TimerQuery::end()
+	{
+		// TODO
+	}
+
+	bool D3D11TimerQuery::isReady() const
+	{
+		// TODO
+		return false;
+	}
+
+	UINT64 D3D11TimerQuery::getTimeMs() const
+	{
+		// TODO
+		return 0;
+	}
+}

+ 6 - 0
CamelotD3D9Renderer/CamelotD3D9Renderer.vcxproj

@@ -237,6 +237,7 @@
     <ClInclude Include="Include\CmD3D9DeviceManager.h" />
     <ClInclude Include="Include\CmD3D9Driver.h" />
     <ClInclude Include="Include\CmD3D9DriverList.h" />
+    <ClInclude Include="Include\CmD3D9EventQuery.h" />
     <ClInclude Include="Include\CmD3D9GpuBuffer.h" />
     <ClInclude Include="Include\CmD3D9GpuProgram.h" />
     <ClInclude Include="Include\CmD3D9GpuProgramManager.h" />
@@ -245,6 +246,8 @@
     <ClInclude Include="Include\CmD3D9IndexBuffer.h" />
     <ClInclude Include="Include\CmD3D9OcclusionQuery.h" />
     <ClInclude Include="Include\CmD3D9PixelBuffer.h" />
+    <ClInclude Include="Include\CmD3D9QueryManager.h" />
+    <ClInclude Include="Include\CmD3D9TimerQuery.h" />
     <ClInclude Include="Include\CmD3D9VertexBuffer.h" />
     <ClInclude Include="Include\CmD3D9HLSLProgram.h" />
     <ClInclude Include="Include\CmD3D9HLSLProgramFactory.h" />
@@ -271,6 +274,7 @@
     <ClCompile Include="Source\CmD3D9DeviceManager.cpp" />
     <ClCompile Include="Source\CmD3D9Driver.cpp" />
     <ClCompile Include="Source\CmD3D9DriverList.cpp" />
+    <ClCompile Include="Source\CmD3D9EventQuery.cpp" />
     <ClCompile Include="Source\CmD3D9GpuBuffer.cpp" />
     <ClCompile Include="Source\CmD3D9GpuProgram.cpp" />
     <ClCompile Include="Source\CmD3D9GpuProgramManager.cpp" />
@@ -278,6 +282,8 @@
     <ClCompile Include="Source\CmD3D9IndexBuffer.cpp" />
     <ClCompile Include="Source\CmD3D9OcclusionQuery.cpp" />
     <ClCompile Include="Source\CmD3D9PixelBuffer.cpp" />
+    <ClCompile Include="Source\CmD3D9QueryManager.cpp" />
+    <ClCompile Include="Source\CmD3D9TimerQuery.cpp" />
     <ClCompile Include="Source\CmD3D9VertexBuffer.cpp" />
     <ClCompile Include="Source\CmD3D9HLSLProgram.cpp" />
     <ClCompile Include="Source\CmD3D9HLSLProgramFactory.cpp" />

+ 18 - 0
CamelotD3D9Renderer/CamelotD3D9Renderer.vcxproj.filters

@@ -111,6 +111,15 @@
     <ClInclude Include="Include\CmD3D9HLSLParamParser.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Include\CmD3D9EventQuery.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\CmD3D9QueryManager.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\CmD3D9TimerQuery.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\CmD3D9Device.cpp">
@@ -200,5 +209,14 @@
     <ClCompile Include="Source\CmD3D9GpuBuffer.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\CmD3D9EventQuery.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\CmD3D9QueryManager.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\CmD3D9TimerQuery.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 31 - 0
CamelotD3D9Renderer/Include/CmD3D9EventQuery.h

@@ -0,0 +1,31 @@
+#pragma once
+
+#include "CmD3D9Prerequisites.h"
+#include "CmEventQuery.h"
+
+namespace CamelotFramework
+{
+	/**
+	 * @copydoc EventQuery
+	 */
+	class CM_D3D9_EXPORT D3D9EventQuery : public EventQuery
+	{
+	public:
+		D3D9EventQuery();
+		~D3D9EventQuery();
+
+		/**
+		 * @copydoc EventQuery::begin
+		 */
+		virtual void begin();
+
+		/**
+		 * @copydoc EventQuery::isReady
+		 */
+		virtual bool isReady() const;
+
+	private:
+		bool mInitialized;
+		IDirect3DQuery9* mQuery;
+	};
+}

+ 14 - 0
CamelotD3D9Renderer/Include/CmD3D9QueryManager.h

@@ -0,0 +1,14 @@
+#pragma once
+
+#include "CmD3D9Prerequisites.h"
+#include "CmQueryManager.h"
+
+namespace CamelotFramework
+{
+	class CM_D3D9_EXPORT D3D9QueryManager : public QueryManager
+	{
+	public:
+		EventQueryPtr createEventQuery() const;
+		TimerQueryPtr createTimerQuery() const;
+	};
+}

+ 40 - 0
CamelotD3D9Renderer/Include/CmD3D9TimerQuery.h

@@ -0,0 +1,40 @@
+#pragma once
+
+#include "CmD3D9Prerequisites.h"
+#include "CmTimerQuery.h"
+
+namespace CamelotFramework
+{
+	/**
+	 * @copydoc TimerQuery
+	 */
+	class CM_D3D9_EXPORT D3D9TimerQuery : public TimerQuery
+	{
+	public:
+		D3D9TimerQuery();
+		~D3D9TimerQuery();
+
+		/**
+		 * @copydoc TimerQuery::begin
+		 */
+		virtual void begin();
+
+		/**
+		 * @copydoc TimerQuery::end
+		 */
+		virtual void end();
+
+		/**
+		 * @copydoc TimerQuery::isReady
+		 */
+		virtual bool isReady() const;
+
+		/**
+		 * @copydoc TimerQuery::getTimeMs
+		 */
+		virtual UINT64 getTimeMs() const;
+
+	private:
+		bool mInitialized;
+	};
+}

+ 42 - 0
CamelotD3D9Renderer/Source/CmD3D9EventQuery.cpp

@@ -0,0 +1,42 @@
+#include "CmD3D9EventQuery.h"
+#include "CmD3D9RenderSystem.h"
+#include "CmD3D9Device.h"
+#include "CmException.h"
+
+namespace CamelotFramework
+{
+	D3D9EventQuery::D3D9EventQuery()
+		:mQuery(nullptr), mInitialized(false)
+	{
+
+	}
+
+	D3D9EventQuery::~D3D9EventQuery()
+	{
+		if(mInitialized)
+		{
+			mQuery->Release();
+		}
+	}
+
+	void D3D9EventQuery::begin()
+	{
+		IDirect3DDevice9* device = D3D9RenderSystem::getActiveD3D9Device();
+		HRESULT hr = device->CreateQuery(D3DQUERYTYPE_EVENT, &mQuery);
+
+		if(hr != S_OK)
+		{
+			CM_EXCEPT(RenderingAPIException, "Failed to create an Event query.");
+		}
+
+		mQuery->Issue(D3DISSUE_END);
+
+		mInitialized = true;
+	}
+
+	bool D3D9EventQuery::isReady() const
+	{
+		BOOL queryData;
+		return mQuery->GetData(&queryData, sizeof(BOOL), 0) == S_OK;
+	}
+}

+ 22 - 0
CamelotD3D9Renderer/Source/CmD3D9QueryManager.cpp

@@ -0,0 +1,22 @@
+#include "CmD3D9QueryManager.h"
+#include "CmD3D9EventQuery.h"
+#include "CmD3D9TimerQuery.h"
+
+namespace CamelotFramework
+{
+	EventQueryPtr D3D9QueryManager::createEventQuery() const
+	{
+		EventQueryPtr query = std::shared_ptr<D3D9EventQuery>(cm_new<D3D9EventQuery>(), &QueryManager::deleteEventQuery, StdAlloc<GenAlloc>());  
+		mEventQueries[mBufferIdx].push_back(query.get());
+
+		return query;
+	}
+
+	TimerQueryPtr D3D9QueryManager::createTimerQuery() const
+	{
+		TimerQueryPtr query = std::shared_ptr<D3D9TimerQuery>(cm_new<D3D9TimerQuery>(), &QueryManager::deleteTimerQuery, StdAlloc<GenAlloc>());  
+		mTimerQueries[mBufferIdx].push_back(query.get());
+
+		return query;
+	}
+}

+ 42 - 0
CamelotD3D9Renderer/Source/CmD3D9TimerQuery.cpp

@@ -0,0 +1,42 @@
+#include "CmD3D9TimerQuery.h"
+
+namespace CamelotFramework
+{
+	D3D9TimerQuery::D3D9TimerQuery()
+		:mInitialized(false)
+	{
+
+	}
+
+	D3D9TimerQuery::~D3D9TimerQuery()
+	{
+		if(mInitialized)
+		{
+			// TODO
+		}
+	}
+
+	void D3D9TimerQuery::begin()
+	{
+		// TODO
+
+		mInitialized = true;
+	}
+
+	void D3D9TimerQuery::end()
+	{
+		// TODO
+	}
+
+	bool D3D9TimerQuery::isReady() const
+	{
+		// TODO
+		return false;
+	}
+
+	UINT64 D3D9TimerQuery::getTimeMs() const
+	{
+		// TODO
+		return 0;
+	}
+}

+ 6 - 0
CamelotGLRenderer/CamelotGLRenderer.vcxproj

@@ -234,6 +234,7 @@
   </ItemDefinitionGroup>
   <ItemGroup>
     <ClInclude Include="Include\CmGLContext.h" />
+    <ClInclude Include="Include\CmGLEventQuery.h" />
     <ClInclude Include="Include\CmGLFrameBufferObject.h" />
     <ClInclude Include="Include\CmGLGpuBuffer.h" />
     <ClInclude Include="Include\CmGLGpuParamBlockBuffer.h" />
@@ -242,6 +243,8 @@
     <ClInclude Include="Include\CmGLIndexBuffer.h" />
     <ClInclude Include="Include\CmGLOcclusionQuery.h" />
     <ClInclude Include="Include\CmGLPixelBuffer.h" />
+    <ClInclude Include="Include\CmGLQueryManager.h" />
+    <ClInclude Include="Include\CmGLTimerQuery.h" />
     <ClInclude Include="Include\CmGLVertexBuffer.h" />
     <ClInclude Include="Include\CmGLMultiRenderTexture.h" />
     <ClInclude Include="Include\CmGLPixelFormat.h" />
@@ -270,6 +273,7 @@
   <ItemGroup>
     <ClCompile Include="CmGLPlugin.cpp" />
     <ClCompile Include="Source\CmGLContext.cpp" />
+    <ClCompile Include="Source\CmGLEventQuery.cpp" />
     <ClCompile Include="Source\CmGLFrameBufferObject.cpp" />
     <ClCompile Include="Source\CmGLGpuBuffer.cpp" />
     <ClCompile Include="Source\CmGLGpuParamBlockBuffer.cpp" />
@@ -278,6 +282,8 @@
     <ClCompile Include="Source\CmGLIndexBuffer.cpp" />
     <ClCompile Include="Source\CmGLOcclusionQuery.cpp" />
     <ClCompile Include="Source\CmGLPixelBuffer.cpp" />
+    <ClCompile Include="Source\CmGLQueryManager.cpp" />
+    <ClCompile Include="Source\CmGLTimerQuery.cpp" />
     <ClCompile Include="Source\CmGLVertexBuffer.cpp" />
     <ClCompile Include="Source\CmGLMultiRenderTexture.cpp" />
     <ClCompile Include="Source\CmGLPixelFormat.cpp" />

+ 18 - 0
CamelotGLRenderer/CamelotGLRenderer.vcxproj.filters

@@ -123,6 +123,15 @@
     <ClInclude Include="Include\CmGLGpuParamBlockBuffer.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Include\CmGLEventQuery.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\CmGLQueryManager.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\CmGLTimerQuery.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\GLSL\src\CmGLSLExtSupport.cpp">
@@ -215,5 +224,14 @@
     <ClCompile Include="Source\CmGLGpuParamBlockBuffer.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\CmGLEventQuery.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\CmGLQueryManager.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\CmGLTimerQuery.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 31 - 0
CamelotGLRenderer/Include/CmGLEventQuery.h

@@ -0,0 +1,31 @@
+#pragma once
+
+#include "CmGLPrerequisites.h"
+#include "CmEventQuery.h"
+
+namespace CamelotFramework
+{
+	/**
+	 * @copydoc EventQuery
+	 */
+	class CM_RSGL_EXPORT GLEventQuery : public EventQuery
+	{
+	public:
+		GLEventQuery();
+		~GLEventQuery();
+
+		/**
+		 * @copydoc EventQuery::begin
+		 */
+		virtual void begin();
+
+		/**
+		 * @copydoc EventQuery::isReady
+		 */
+		virtual bool isReady() const;
+
+	private:
+		GLuint mQueryObj;
+		bool mInitialized;
+	};
+}

+ 14 - 0
CamelotGLRenderer/Include/CmGLQueryManager.h

@@ -0,0 +1,14 @@
+#pragma once
+
+#include "CmGLPrerequisites.h"
+#include "CmQueryManager.h"
+
+namespace CamelotFramework
+{
+	class CM_RSGL_EXPORT GLQueryManager : public QueryManager
+	{
+	public:
+		EventQueryPtr createEventQuery() const;
+		TimerQueryPtr createTimerQuery() const;
+	};
+}

+ 41 - 0
CamelotGLRenderer/Include/CmGLTimerQuery.h

@@ -0,0 +1,41 @@
+#pragma once
+
+#include "CmGLPrerequisites.h"
+#include "CmTimerQuery.h"
+
+namespace CamelotFramework
+{
+	/**
+	 * @copydoc TimerQuery
+	 */
+	class CM_RSGL_EXPORT GLTimerQuery : public TimerQuery
+	{
+	public:
+		GLTimerQuery();
+		~GLTimerQuery();
+
+		/**
+		 * @copydoc TimerQuery::begin
+		 */
+		virtual void begin();
+
+		/**
+		 * @copydoc TimerQuery::end
+		 */
+		virtual void end();
+
+		/**
+		 * @copydoc TimerQuery::isReady
+		 */
+		virtual bool isReady() const;
+
+		/**
+		 * @copydoc TimerQuery::getTimeMs
+		 */
+		virtual UINT64 getTimeMs() const;
+
+	private:
+		GLuint mQueryObj;
+		bool mInitialized;
+	};
+}

+ 40 - 0
CamelotGLRenderer/Source/CmGLEventQuery.cpp

@@ -0,0 +1,40 @@
+#include "CmGLEventQuery.h"
+
+namespace CamelotFramework
+{
+	GLEventQuery::GLEventQuery()
+		:mQueryObj(0), mInitialized(false)
+	{
+
+	}
+
+	GLEventQuery::~GLEventQuery()
+	{
+		if(mInitialized)
+		{
+			GLuint queries[1];
+			queries[0] = mQueryObj;
+
+			glDeleteQueries(1, queries);
+		}
+	}
+
+	void GLEventQuery::begin()
+	{
+		GLuint queries[1];
+		queries[0] = mQueryObj;
+
+		glGenQueries(1, queries);
+		glQueryCounter(mQueryObj, GL_TIMESTAMP);
+
+		mInitialized = true;
+	}
+
+	bool GLEventQuery::isReady() const
+	{
+		GLint done = 0;
+		glGetQueryObjectiv(mQueryObj, GL_QUERY_RESULT_AVAILABLE, &done);
+
+		return done == GL_TRUE;
+	}
+}

+ 22 - 0
CamelotGLRenderer/Source/CmGLQueryManager.cpp

@@ -0,0 +1,22 @@
+#include "CmGLQueryManager.h"
+#include "CmGLEventQuery.h"
+#include "CmGLTimerQuery.h"
+
+namespace CamelotFramework
+{
+	EventQueryPtr GLQueryManager::createEventQuery() const
+	{
+		EventQueryPtr query = std::shared_ptr<GLEventQuery>(cm_new<GLEventQuery>(), &QueryManager::deleteEventQuery, StdAlloc<GenAlloc>());  
+		mEventQueries[mBufferIdx].push_back(query.get());
+
+		return query;
+	}
+
+	TimerQueryPtr GLQueryManager::createTimerQuery() const
+	{
+		TimerQueryPtr query = std::shared_ptr<GLTimerQuery>(cm_new<GLTimerQuery>(), &QueryManager::deleteTimerQuery, StdAlloc<GenAlloc>());  
+		mTimerQueries[mBufferIdx].push_back(query.get());
+
+		return query;
+	}
+}

+ 42 - 0
CamelotGLRenderer/Source/CmGLTimerQuery.cpp

@@ -0,0 +1,42 @@
+#include "CmGLTimerQuery.h"
+
+namespace CamelotFramework
+{
+	GLTimerQuery::GLTimerQuery()
+		:mQueryObj(0), mInitialized(false)
+	{
+
+	}
+
+	GLTimerQuery::~GLTimerQuery()
+	{
+		if(mInitialized)
+		{
+			// TODO
+		}
+	}
+
+	void GLTimerQuery::begin()
+	{
+		// TODO
+
+		mInitialized = true;
+	}
+
+	void GLTimerQuery::end()
+	{
+		// TODO
+	}
+
+	bool GLTimerQuery::isReady() const
+	{
+		// TODO
+		return false;
+	}
+
+	UINT64 GLTimerQuery::getTimeMs() const
+	{
+		// TODO
+		return 0;
+	}
+}

+ 3 - 3
Opts.txt

@@ -1,8 +1,5 @@
 Make sure to also update TextSprite and ImageSprite and anything else in UpdateMesh, then don't forget to find the issue that causes elements to get marked as dirty every single frame
 
-GpuParamBlock should be tied directly with GpuParamBlockBuffer
-  - Modify material so it always sets just the first GpuParams with a specific name. This will avoid updating same buffer multiple times.
-
 FrameAlloc
    Keeps two internal stacks
      - One core, one sim
@@ -31,6 +28,9 @@ TransientMesh
    - Need to implement a proper GPU query interface
  - Keeps track of fragmentation and has an option to defragment, manually or auto after certain %
 
+Queries:
+ - Startup QueryManager, Implement Timer queries, Test all queries
+
 ----------
 
 BIG TODO FINALLY: Reorganize GUI so it all uses one big vertex buffer (probably in the form of a TransientMesh). This means I need better support for drawing individual objects