Răsfoiți Sursa

Added Timer queries

Marko Pintera 12 ani în urmă
părinte
comite
7214304ace

+ 11 - 0
CamelotCore/Include/CmEventQuery.h

@@ -16,6 +16,8 @@ namespace CamelotFramework
 	class CM_EXPORT EventQuery
 	{
 	public:
+		EventQuery()
+			:mActive(false) {}
 		virtual ~EventQuery() {}
 
 		/**
@@ -34,5 +36,14 @@ namespace CamelotFramework
 		boost::signal<void()> onTriggered;
 
 		static EventQueryPtr create();
+
+	protected:
+		friend class QueryManager;
+
+		bool isActive() const { return mActive; }
+		void setActive(bool active) { mActive = active; }
+
+	protected:
+		bool mActive;
 	};
 }

+ 2 - 3
CamelotCore/Include/CmQueryManager.h

@@ -25,9 +25,8 @@ namespace CamelotFramework
 		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;
+		mutable Vector<EventQuery*>::type mEventQueries;
+		mutable Vector<TimerQuery*>::type mTimerQueries;
 
 	protected:
 		friend class EventQuery;

+ 13 - 2
CamelotCore/Include/CmTimerQuery.h

@@ -39,10 +39,21 @@ namespace CamelotFramework
 		 * 			
 		 * @note	Only valid after "isReady" returns true.
 		 */
-		virtual UINT64 getTimeMs() const = 0;
+		virtual float getTimeMs() = 0;
 
-		boost::signal<void(UINT64)> onTriggered;
+		boost::signal<void(float)> onTriggered;
 
 		static TimerQueryPtr create();
+
+	protected:
+		friend class QueryManager;
+
+		virtual void finalize() = 0;
+
+		bool isActive() const { return mActive; }
+		void setActive(bool active) { mActive = active; }
+
+	protected:
+		bool mActive;
 	};
 }

+ 16 - 26
CamelotCore/Source/CmQueryManager.cpp

@@ -5,57 +5,47 @@
 namespace CamelotFramework
 {
 	QueryManager::QueryManager()
-		:mBufferIdx(0)
 	{
 
 	}
 
 	void QueryManager::update()
 	{
-		UINT32 otherBufferIdx = (mBufferIdx + 1) % 2;
-		
-		for(auto& query : mEventQueries[mBufferIdx])
+		for(auto& query : mEventQueries)
 		{
-			if(query->isReady())
+			if(query->isActive() && query->isReady())
+			{
 				query->onTriggered();
-			else
-				mEventQueries[otherBufferIdx].push_back(query);
+				query->setActive(false);
+			}
 		}
 
-		for(auto& query : mTimerQueries[mBufferIdx])
+		for(auto& query : mTimerQueries)
 		{
-			if(query->isReady())
+			if(query->isActive() && query->isReady())
+			{
 				query->onTriggered(query->getTimeMs());
-			else
-				mTimerQueries[otherBufferIdx].push_back(query);
+				query->setActive(false);
+			}
 		}
-
-		mEventQueries[mBufferIdx].clear();
-		mTimerQueries[mBufferIdx].clear();
-
-		mBufferIdx = otherBufferIdx;
 	}
 
 	void QueryManager::deleteEventQuery(EventQuery* query)
 	{
-		UINT32 bufferIdx = instance().mBufferIdx;
+		auto iterFind = std::find(instance().mEventQueries.begin(), instance().mEventQueries.end(), query);
 
-		auto iterFind = std::find(instance().mEventQueries[bufferIdx].begin(), instance().mEventQueries[bufferIdx].end(), query);
-
-		if(iterFind != instance().mEventQueries[bufferIdx].end())
-			instance().mEventQueries[bufferIdx].erase(iterFind);
+		if(iterFind != instance().mEventQueries.end())
+			instance().mEventQueries.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);
+		auto iterFind = std::find(instance().mTimerQueries.begin(), instance().mTimerQueries.end(), query);
 
-		if(iterFind != instance().mTimerQueries[bufferIdx].end())
-			instance().mTimerQueries[bufferIdx].erase(iterFind);
+		if(iterFind != instance().mTimerQueries.end())
+			instance().mTimerQueries.erase(iterFind);
 
 		cm_delete(query);
 	}

+ 0 - 1
CamelotD3D11RenderSystem/Include/CmD3D11EventQuery.h

@@ -27,6 +27,5 @@ namespace CamelotFramework
 	private:
 		ID3D11Query* mQuery;
 		ID3D11DeviceContext* mContext;
-		bool mInitialized;
 	};
 }

+ 10 - 2
CamelotD3D11RenderSystem/Include/CmD3D11TimerQuery.h

@@ -32,9 +32,17 @@ namespace CamelotFramework
 		/**
 		 * @copydoc TimerQuery::getTimeMs
 		 */
-		virtual UINT64 getTimeMs() const;
+		virtual float getTimeMs();
 
 	private:
-		bool mInitialized;
+		bool mFinalized;
+		float mTimeDelta;
+
+		ID3D11Query* mBeginQuery;
+		ID3D11Query* mEndQuery;
+		ID3D11Query* mDisjointQuery;
+		ID3D11DeviceContext* mContext;
+
+		virtual void finalize();
 	};
 }

+ 15 - 16
CamelotD3D11RenderSystem/Source/CmD3D11EventQuery.cpp

@@ -6,26 +6,14 @@
 namespace CamelotFramework
 {
 	D3D11EventQuery::D3D11EventQuery()
-		:mQuery(nullptr), mInitialized(false)
-	{
-
-	}
-
-	D3D11EventQuery::~D3D11EventQuery()
-	{
-		if(mInitialized)
-		{
-			mQuery->Release();
-		}
-	}
-
-	void D3D11EventQuery::begin()
+		:mQuery(nullptr)
 	{
 		D3D11RenderSystem* rs = static_cast<D3D11RenderSystem*>(RenderSystem::instancePtr());
 		D3D11Device& device = rs->getPrimaryDevice();
 
 		D3D11_QUERY_DESC queryDesc;
 		queryDesc.Query = D3D11_QUERY_EVENT;
+		queryDesc.MiscFlags = 0;
 
 		HRESULT hr = device.getD3D11Device()->CreateQuery(&queryDesc, &mQuery);
 		if(hr != S_OK)
@@ -34,9 +22,20 @@ namespace CamelotFramework
 		}
 
 		mContext = device.getImmediateContext();
-		mContext->End(mQuery);
+	}
+
+	D3D11EventQuery::~D3D11EventQuery()
+	{
+		if(mQuery != nullptr)
+		{
+			mQuery->Release();
+		}
+	}
 
-		mInitialized = true;
+	void D3D11EventQuery::begin()
+	{
+		mContext->End(mQuery);
+		setActive(true);
 	}
 
 	bool D3D11EventQuery::isReady() const

+ 2 - 2
CamelotD3D11RenderSystem/Source/CmD3D11QueryManager.cpp

@@ -7,7 +7,7 @@ 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());
+		mEventQueries.push_back(query.get());
 
 		return query;
 	}
@@ -15,7 +15,7 @@ namespace CamelotFramework
 	TimerQueryPtr D3D11QueryManager::createTimerQuery() const
 	{
 		TimerQueryPtr query = std::shared_ptr<D3D11TimerQuery>(cm_new<D3D11TimerQuery>(), &QueryManager::deleteTimerQuery, StdAlloc<GenAlloc>());  
-		mTimerQueries[mBufferIdx].push_back(query.get());
+		mTimerQueries.push_back(query.get());
 
 		return query;
 	}

+ 4 - 0
CamelotD3D11RenderSystem/Source/CmD3D11RenderSystem.cpp

@@ -23,6 +23,7 @@
 #include "CmD3D11RenderUtility.h"
 #include "CmBindableGpuParams.h"
 #include "CmCoreThread.h"
+#include "CmD3D11QueryManager.h"
 #include "CmDebug.h"
 #include "CmException.h"
 
@@ -132,6 +133,8 @@ namespace CamelotFramework
 
 		D3D11RenderUtility::startUp(cm_new<D3D11RenderUtility>(mDevice));
 
+		QueryManager::startUp(cm_new<D3D11QueryManager>());
+
 		RenderSystem::initialize_internal(asyncOp);
 
 		asyncOp.completeOperation(primaryWindow);
@@ -141,6 +144,7 @@ namespace CamelotFramework
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
+		QueryManager::shutDown();
 		D3D11RenderUtility::shutDown();
 
 		if(mIAManager != nullptr)

+ 78 - 13
CamelotD3D11RenderSystem/Source/CmD3D11TimerQuery.cpp

@@ -1,42 +1,107 @@
 #include "CmD3D11TimerQuery.h"
+#include "CmD3D11RenderSystem.h"
+#include "CmD3D11Device.h"
+#include "CmDebug.h"
 
 namespace CamelotFramework
 {
 	D3D11TimerQuery::D3D11TimerQuery()
-		:mInitialized(false)
+		:mFinalized(false), mContext(nullptr), mBeginQuery(nullptr), 
+		mEndQuery(nullptr), mDisjointQuery(nullptr), mTimeDelta(0.0f)
 	{
+		D3D11RenderSystem* rs = static_cast<D3D11RenderSystem*>(RenderSystem::instancePtr());
+		D3D11Device& device = rs->getPrimaryDevice();
 
+		D3D11_QUERY_DESC queryDesc;
+		queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
+		queryDesc.MiscFlags = 0;
+
+		HRESULT hr = device.getD3D11Device()->CreateQuery(&queryDesc, &mDisjointQuery);
+		if(hr != S_OK)
+		{
+			CM_EXCEPT(RenderingAPIException, "Failed to create a timer query.");
+		}
+
+		queryDesc.Query = D3D11_QUERY_TIMESTAMP;
+
+		hr = device.getD3D11Device()->CreateQuery(&queryDesc, &mBeginQuery);
+		if(hr != S_OK)
+		{
+			CM_EXCEPT(RenderingAPIException, "Failed to create a timer query.");
+		}
+
+		hr = device.getD3D11Device()->CreateQuery(&queryDesc, &mEndQuery);
+		if(hr != S_OK)
+		{
+			CM_EXCEPT(RenderingAPIException, "Failed to create a timer query.");
+		}
+
+		mContext = device.getImmediateContext();
 	}
 
 	D3D11TimerQuery::~D3D11TimerQuery()
 	{
-		if(mInitialized)
-		{
-			// TODO
-		}
+		if(mBeginQuery != nullptr)
+			mBeginQuery->Release();
+
+		if(mEndQuery != nullptr)
+			mEndQuery->Release();
+
+		if(mDisjointQuery != nullptr)
+			mDisjointQuery->Release();
 	}
 
 	void D3D11TimerQuery::begin()
 	{
-		// TODO
+		mContext->Begin(mDisjointQuery);
+		mContext->End(mBeginQuery);
 
-		mInitialized = true;
+		setActive(true);
 	}
 
 	void D3D11TimerQuery::end()
 	{
-		// TODO
+		mContext->End(mEndQuery);
+		mContext->End(mDisjointQuery);
 	}
 
 	bool D3D11TimerQuery::isReady() const
 	{
-		// TODO
-		return false;
+		D3D11_QUERY_DATA_TIMESTAMP_DISJOINT disjointData;
+		return mContext->GetData(mDisjointQuery, &disjointData, sizeof(disjointData), 0) == S_OK;
+	}
+
+	float D3D11TimerQuery::getTimeMs()
+	{
+		if(!mFinalized && isReady())
+		{
+			finalize();
+		}
+
+		return mTimeDelta;
 	}
 
-	UINT64 D3D11TimerQuery::getTimeMs() const
+	void D3D11TimerQuery::finalize()
 	{
-		// TODO
-		return 0;
+		UINT64 timeStart, timeEnd;
+
+		mContext->GetData(mBeginQuery, &timeStart, sizeof(timeStart), 0);
+		mContext->GetData(mEndQuery, &timeEnd, sizeof(timeEnd), 0);
+
+		D3D11_QUERY_DATA_TIMESTAMP_DISJOINT disjointData;
+		mContext->GetData(mDisjointQuery, &disjointData, sizeof(disjointData), 0);
+
+		float time = 0.0f;
+		if(disjointData.Disjoint == FALSE)
+		{
+			float frequency = static_cast<float>(disjointData.Frequency);
+
+			UINT64 delta = timeEnd - timeStart;
+			mTimeDelta = (delta / (float)frequency) * 1000.0f;
+		}       
+		else
+		{
+			LOGWRN("Unrealiable GPU timer query detected.");
+		}
 	}
 }

+ 0 - 1
CamelotD3D9Renderer/Include/CmD3D9EventQuery.h

@@ -25,7 +25,6 @@ namespace CamelotFramework
 		virtual bool isReady() const;
 
 	private:
-		bool mInitialized;
 		IDirect3DQuery9* mQuery;
 	};
 }

+ 10 - 2
CamelotD3D9Renderer/Include/CmD3D9TimerQuery.h

@@ -32,9 +32,17 @@ namespace CamelotFramework
 		/**
 		 * @copydoc TimerQuery::getTimeMs
 		 */
-		virtual UINT64 getTimeMs() const;
+		virtual float getTimeMs();
 
 	private:
-		bool mInitialized;
+		bool mFinalized;
+		float mTimeDelta;
+
+		IDirect3DQuery9* mBeginQuery;
+		IDirect3DQuery9* mEndQuery;
+		IDirect3DQuery9* mDisjointQuery;
+		IDirect3DQuery9* mFreqQuery;
+
+		virtual void finalize();
 	};
 }

+ 9 - 12
CamelotD3D9Renderer/Source/CmD3D9EventQuery.cpp

@@ -6,14 +6,20 @@
 namespace CamelotFramework
 {
 	D3D9EventQuery::D3D9EventQuery()
-		:mQuery(nullptr), mInitialized(false)
+		:mQuery(nullptr)
 	{
+		IDirect3DDevice9* device = D3D9RenderSystem::getActiveD3D9Device();
+		HRESULT hr = device->CreateQuery(D3DQUERYTYPE_EVENT, &mQuery);
 
+		if(hr != S_OK)
+		{
+			CM_EXCEPT(RenderingAPIException, "Failed to create an Event query.");
+		}
 	}
 
 	D3D9EventQuery::~D3D9EventQuery()
 	{
-		if(mInitialized)
+		if(mQuery != nullptr)
 		{
 			mQuery->Release();
 		}
@@ -21,17 +27,8 @@ namespace CamelotFramework
 
 	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;
+		setActive(true);
 	}
 
 	bool D3D9EventQuery::isReady() const

+ 2 - 2
CamelotD3D9Renderer/Source/CmD3D9QueryManager.cpp

@@ -7,7 +7,7 @@ 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());
+		mEventQueries.push_back(query.get());
 
 		return query;
 	}
@@ -15,7 +15,7 @@ namespace CamelotFramework
 	TimerQueryPtr D3D9QueryManager::createTimerQuery() const
 	{
 		TimerQueryPtr query = std::shared_ptr<D3D9TimerQuery>(cm_new<D3D9TimerQuery>(), &QueryManager::deleteTimerQuery, StdAlloc<GenAlloc>());  
-		mTimerQueries[mBufferIdx].push_back(query.get());
+		mTimerQueries.push_back(query.get());
 
 		return query;
 	}

+ 4 - 0
CamelotD3D9Renderer/Source/CmD3D9RenderSystem.cpp

@@ -56,6 +56,7 @@ THE SOFTWARE.
 #include "CmGpuParamDesc.h"
 #include "CmGpuParamBlockBuffer.h"
 #include "CmCoreThread.h"
+#include "CmD3D9QueryManager.h"
 #include "CmDebug.h"
 
 #define FLOAT2DWORD(f) *((DWORD*)&f)
@@ -181,6 +182,8 @@ namespace CamelotFramework
 		// Create the texture manager for use by others		
 		TextureManager::startUp(cm_new<D3D9TextureManager>());
 
+		QueryManager::startUp(cm_new<D3D9QueryManager>());
+
 		// call superclass method
 		RenderSystem::initialize_internal(asyncOp);
 
@@ -210,6 +213,7 @@ namespace CamelotFramework
 		}
 		mActiveD3DDriver = NULL;	
 
+		QueryManager::shutDown();
 		TextureManager::shutDown();
 		HardwareBufferManager::shutDown();
 		GpuProgramManager::shutDown();	

+ 77 - 14
CamelotD3D9Renderer/Source/CmD3D9TimerQuery.cpp

@@ -1,42 +1,105 @@
 #include "CmD3D9TimerQuery.h"
+#include "CmD3D9RenderSystem.h"
+#include "CmDebug.h"
 
 namespace CamelotFramework
 {
 	D3D9TimerQuery::D3D9TimerQuery()
-		:mInitialized(false)
+		:mFinalized(false), mBeginQuery(nullptr), mFreqQuery(nullptr),
+		mEndQuery(nullptr), mDisjointQuery(nullptr), mTimeDelta(0.0f)
 	{
+		IDirect3DDevice9* device = D3D9RenderSystem::getActiveD3D9Device();
 
+		HRESULT hr = device->CreateQuery(D3DQUERYTYPE_TIMESTAMPDISJOINT, &mDisjointQuery);
+		if(hr != S_OK)
+		{
+			CM_EXCEPT(RenderingAPIException, "Failed to create a timer query.");
+		}
+
+		hr = device->CreateQuery(D3DQUERYTYPE_TIMESTAMPFREQ, &mFreqQuery);
+		if(hr != S_OK)
+		{
+			CM_EXCEPT(RenderingAPIException, "Failed to create a timer query.");
+		}
+
+		hr = device->CreateQuery(D3DQUERYTYPE_TIMESTAMP, &mBeginQuery);
+		if(hr != S_OK)
+		{
+			CM_EXCEPT(RenderingAPIException, "Failed to create a timer query.");
+		}
+
+		hr = device->CreateQuery(D3DQUERYTYPE_TIMESTAMP, &mEndQuery);
+		if(hr != S_OK)
+		{
+			CM_EXCEPT(RenderingAPIException, "Failed to create a timer query.");
+		}
 	}
 
 	D3D9TimerQuery::~D3D9TimerQuery()
 	{
-		if(mInitialized)
-		{
-			// TODO
-		}
+		if(mBeginQuery != nullptr)
+			mBeginQuery->Release();
+
+		if(mEndQuery != nullptr)
+			mEndQuery->Release();
+
+		if(mDisjointQuery != nullptr)
+			mDisjointQuery->Release();
+
+		if(mFreqQuery != nullptr)
+			mFreqQuery->Release();
 	}
 
 	void D3D9TimerQuery::begin()
 	{
-		// TODO
-
-		mInitialized = true;
+		mDisjointQuery->Issue(D3DISSUE_BEGIN);
+		mFreqQuery->Issue(D3DISSUE_END);
+		mBeginQuery->Issue(D3DISSUE_END);
+		setActive(true);
 	}
 
 	void D3D9TimerQuery::end()
 	{
-		// TODO
+		mEndQuery->Issue(D3DISSUE_END);
+		mDisjointQuery->Issue(D3DISSUE_END);
 	}
 
 	bool D3D9TimerQuery::isReady() const
 	{
-		// TODO
-		return false;
+		BOOL queryData;
+		return mDisjointQuery->GetData(&queryData, sizeof(BOOL), 0) == S_OK;
+	}
+
+	float D3D9TimerQuery::getTimeMs()
+	{
+		if(!mFinalized && isReady())
+		{
+			finalize();
+		}
+
+		return mTimeDelta;
 	}
 
-	UINT64 D3D9TimerQuery::getTimeMs() const
+	void D3D9TimerQuery::finalize()
 	{
-		// TODO
-		return 0;
+		BOOL disjoint;
+		mDisjointQuery->GetData(&disjoint, sizeof(BOOL), 0);
+
+		if(!disjoint)
+		{
+			UINT64 frequency;
+			mFreqQuery->GetData(&frequency, sizeof(UINT64), 0);
+
+			UINT64 timeStart, timeEnd;
+			mBeginQuery->GetData(&timeStart, sizeof(UINT64), 0);
+			mEndQuery->GetData(&timeEnd, sizeof(UINT64), 0);
+
+			UINT64 delta = timeEnd - timeStart;
+			mTimeDelta = (delta/(float)frequency) * 1000.0f;
+		}
+		else
+		{
+			LOGWRN("Unrealiable GPU timer query detected.");
+		}
 	}
 }

+ 0 - 1
CamelotGLRenderer/Include/CmGLEventQuery.h

@@ -26,6 +26,5 @@ namespace CamelotFramework
 
 	private:
 		GLuint mQueryObj;
-		bool mInitialized;
 	};
 }

+ 10 - 3
CamelotGLRenderer/Include/CmGLTimerQuery.h

@@ -32,10 +32,17 @@ namespace CamelotFramework
 		/**
 		 * @copydoc TimerQuery::getTimeMs
 		 */
-		virtual UINT64 getTimeMs() const;
+		virtual float getTimeMs();
 
 	private:
-		GLuint mQueryObj;
-		bool mInitialized;
+		friend class QueryManager;
+
+		GLuint mQueryStartObj;
+		GLuint mQueryEndObj;
+		bool mFinalized;
+
+		float mTimeDelta;
+
+		virtual void finalize();
 	};
 }

+ 8 - 13
CamelotGLRenderer/Source/CmGLEventQuery.cpp

@@ -3,31 +3,26 @@
 namespace CamelotFramework
 {
 	GLEventQuery::GLEventQuery()
-		:mQueryObj(0), mInitialized(false)
+		:mQueryObj(0)
 	{
+		GLuint queries[1];
+		queries[0] = mQueryObj;
 
+		glGenQueries(1, queries);
 	}
 
 	GLEventQuery::~GLEventQuery()
 	{
-		if(mInitialized)
-		{
-			GLuint queries[1];
-			queries[0] = mQueryObj;
+		GLuint queries[1];
+		queries[0] = mQueryObj;
 
-			glDeleteQueries(1, queries);
-		}
+		glDeleteQueries(1, queries);
 	}
 
 	void GLEventQuery::begin()
 	{
-		GLuint queries[1];
-		queries[0] = mQueryObj;
-
-		glGenQueries(1, queries);
 		glQueryCounter(mQueryObj, GL_TIMESTAMP);
-
-		mInitialized = true;
+		setActive(true);
 	}
 
 	bool GLEventQuery::isReady() const

+ 2 - 2
CamelotGLRenderer/Source/CmGLQueryManager.cpp

@@ -7,7 +7,7 @@ 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());
+		mEventQueries.push_back(query.get());
 
 		return query;
 	}
@@ -15,7 +15,7 @@ namespace CamelotFramework
 	TimerQueryPtr GLQueryManager::createTimerQuery() const
 	{
 		TimerQueryPtr query = std::shared_ptr<GLTimerQuery>(cm_new<GLTimerQuery>(), &QueryManager::deleteTimerQuery, StdAlloc<GenAlloc>());  
-		mTimerQueries[mBufferIdx].push_back(query.get());
+		mTimerQueries.push_back(query.get());
 
 		return query;
 	}

+ 4 - 0
CamelotGLRenderer/Source/CmGLRenderSystem.cpp

@@ -52,6 +52,7 @@ THE SOFTWARE.s
 #include "CmGpuParams.h"
 #include "CmGLGpuParamBlockBuffer.h"
 #include "CmCoreThread.h"
+#include "CmGLQueryManager.h"
 #include "CmDebug.h"
 
 // Convenience macro from ARB_vertex_buffer_object spec
@@ -141,6 +142,8 @@ namespace CamelotFramework
 
 		RenderStateManager::startUp(cm_new<RenderStateManager>());
 
+		QueryManager::startUp(cm_new<GLQueryManager>());
+
 		// Initialize a window so we have something to create a GL context with
 		RenderWindowPtr primaryWindow = RenderWindow::create(mPrimaryWindowDesc);
 		             
@@ -221,6 +224,7 @@ namespace CamelotFramework
 		mGLSupport->stop();
 
 		TextureManager::shutDown();
+		QueryManager::shutDown();
 		RenderWindowManager::shutDown();
 		RenderStateManager::shutDown();
 

+ 39 - 13
CamelotGLRenderer/Source/CmGLTimerQuery.cpp

@@ -1,42 +1,68 @@
 #include "CmGLTimerQuery.h"
+#include "CmMath.h"
 
 namespace CamelotFramework
 {
 	GLTimerQuery::GLTimerQuery()
-		:mQueryObj(0), mInitialized(false)
+		:mQueryStartObj(0), mQueryEndObj(0), 
+		mTimeDelta(0.0f), mFinalized(false)
 	{
+		GLuint queries[2];
+		queries[0] = mQueryStartObj;
+		queries[1] = mQueryEndObj;
 
+		glGenQueries(2, queries);
 	}
 
 	GLTimerQuery::~GLTimerQuery()
 	{
-		if(mInitialized)
-		{
-			// TODO
-		}
+		GLuint queries[2];
+		queries[0] = mQueryStartObj;
+		queries[1] = mQueryEndObj;
+
+		glDeleteQueries(2, queries);
 	}
 
 	void GLTimerQuery::begin()
 	{
-		// TODO
+		glQueryCounter(mQueryStartObj, GL_TIMESTAMP);
 
-		mInitialized = true;
+		setActive(true);
 	}
 
 	void GLTimerQuery::end()
 	{
-		// TODO
+		glQueryCounter(mQueryEndObj, GL_TIMESTAMP);
 	}
 
 	bool GLTimerQuery::isReady() const
 	{
-		// TODO
-		return false;
+		GLint done = 0;
+		glGetQueryObjectiv(mQueryEndObj, GL_QUERY_RESULT_AVAILABLE, &done);
+
+		return done == GL_TRUE;
 	}
 
-	UINT64 GLTimerQuery::getTimeMs() const
+	float GLTimerQuery::getTimeMs() 
 	{
-		// TODO
-		return 0;
+		if(!mFinalized && isReady())
+		{
+			finalize();
+		}
+
+		return mTimeDelta;
+	}
+
+	void GLTimerQuery::finalize()
+	{
+		mFinalized = true;
+
+		GLuint64 timeStart;
+		GLuint64 timeEnd;
+
+		glGetQueryObjectui64v(mQueryStartObj, GL_QUERY_RESULT, &timeStart);
+		glGetQueryObjectui64v(mQueryEndObj, GL_QUERY_RESULT, &timeEnd);
+
+		mTimeDelta = (timeEnd - timeStart) / 1000000.0f;
 	}
 }

+ 0 - 3
Opts.txt

@@ -28,9 +28,6 @@ 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