Marko Pintera 11 лет назад
Родитель
Сommit
87c63a50e6
29 измененных файлов с 520 добавлено и 767 удалено
  1. 0 1
      BansheeEngine.sln
  2. 1 1
      CamelotCore/Include/CmEventQuery.h
  3. 71 127
      CamelotCore/Include/CmOcclusionQuery.h
  4. 2 0
      CamelotCore/Include/CmPrerequisites.h
  5. 38 5
      CamelotCore/Include/CmQueryManager.h
  6. 10 2
      CamelotCore/Include/CmTimerQuery.h
  7. 1 1
      CamelotCore/Source/CmApplication.cpp
  8. 13 43
      CamelotCore/Source/CmOcclusionQuery.cpp
  9. 21 1
      CamelotCore/Source/CmQueryManager.cpp
  10. 2 0
      CamelotD3D11RenderSystem/CamelotD3D11RenderSystem.vcxproj
  11. 6 0
      CamelotD3D11RenderSystem/CamelotD3D11RenderSystem.vcxproj.filters
  12. 48 0
      CamelotD3D11RenderSystem/Include/CmD3D11OcclusionQuery.h
  13. 12 0
      CamelotD3D11RenderSystem/Include/CmD3D11QueryManager.h
  14. 1 1
      CamelotD3D11RenderSystem/Include/CmD3D11TimerQuery.h
  15. 87 0
      CamelotD3D11RenderSystem/Source/CmD3D11OcclusionQuery.cpp
  16. 9 0
      CamelotD3D11RenderSystem/Source/CmD3D11QueryManager.cpp
  17. 26 94
      CamelotD3D9Renderer/Include/CmD3D9OcclusionQuery.h
  18. 12 0
      CamelotD3D9Renderer/Include/CmD3D9QueryManager.h
  19. 1 1
      CamelotD3D9Renderer/Include/CmD3D9TimerQuery.h
  20. 35 225
      CamelotD3D9Renderer/Source/CmD3D9OcclusionQuery.cpp
  21. 9 0
      CamelotD3D9Renderer/Source/CmD3D9QueryManager.cpp
  22. 41 102
      CamelotGLRenderer/Include/CmGLOcclusionQuery.h
  23. 12 0
      CamelotGLRenderer/Include/CmGLQueryManager.h
  24. 1 1
      CamelotGLRenderer/Include/CmGLTimerQuery.h
  25. 48 126
      CamelotGLRenderer/Source/CmGLOcclusionQuery.cpp
  26. 9 0
      CamelotGLRenderer/Source/CmGLQueryManager.cpp
  27. 1 1
      Notes.txt
  28. 3 0
      TODO.txt
  29. 0 35
      TaskScheduler.txt

+ 0 - 1
BansheeEngine.sln

@@ -37,7 +37,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
 		RenderOperation.txt = RenderOperation.txt
 		RenderOperation.txt = RenderOperation.txt
 		ResourceBundles.txt = ResourceBundles.txt
 		ResourceBundles.txt = ResourceBundles.txt
 		SpriteTexture.txt = SpriteTexture.txt
 		SpriteTexture.txt = SpriteTexture.txt
-		TaskScheduler.txt = TaskScheduler.txt
 		TODO.txt = TODO.txt
 		TODO.txt = TODO.txt
 		TODODoc.txt = TODODoc.txt
 		TODODoc.txt = TODODoc.txt
 		TransformUpdatesAndRenderer.txt = TransformUpdatesAndRenderer.txt
 		TransformUpdatesAndRenderer.txt = TransformUpdatesAndRenderer.txt

+ 1 - 1
CamelotCore/Include/CmEventQuery.h

@@ -47,7 +47,7 @@ namespace BansheeEngine
 		friend class QueryManager;
 		friend class QueryManager;
 
 
 		/**
 		/**
-		 * @brief	Returns true if the query is still waiting for its "ready" callback to be triggered.
+		 * @brief	Returns true if the has still not been completed by the GPU.
 		 */
 		 */
 		bool isActive() const { return mActive; }
 		bool isActive() const { return mActive; }
 		void setActive(bool active) { mActive = active; }
 		void setActive(bool active) { mActive = active; }

+ 71 - 127
CamelotCore/Include/CmOcclusionQuery.h

@@ -1,132 +1,76 @@
-/*
------------------------------------------------------------------------------
-This source file is part of OGRE
-    (Object-oriented Graphics Rendering Engine)
-For the latest info, see http://www.ogre3d.org
+#pragma once
 
 
-Copyright (c) 2000-2011 Torus Knot Software Ltd
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
------------------------------------------------------------------------------
-*/
-#ifndef _HardwareOcclusionQuery__
-#define _HardwareOcclusionQuery__
-
-// Precompiler options
 #include "CmPrerequisites.h"
 #include "CmPrerequisites.h"
 
 
-namespace BansheeEngine {
-
-
-
-	/** \addtogroup Core
-	*  @{
-	*/
-	/** \addtogroup RenderSystem
-	*  @{
-	*/
-/**
-  * This is a abstract class that that provides the interface for the query class for 
-  * hardware occlusion.
-  *
-  * @author Lee Sandberg
-  * Updated on 13/8/2005 by Tuan Kuranes email: [email protected]
-  */
-	class CM_EXPORT OcclusionQuery
+namespace BansheeEngine
 {
 {
-//----------------------------------------------------------------------
-// Public methods
-//--
-public:
-	/**
-	  * Object public member functions
-	  */
-
-	/**
-	  * Default object constructor
-	  * 
-	  */
-	OcclusionQuery();
-
-	/**
-	  * Object destructor
-	  */
-	virtual ~OcclusionQuery();
-
-	/**
-	  * Starts the hardware occlusion query
-	  * @Remarks	Simple usage: Create one or more OcclusionQuery object one per outstanding query or one per tested object 
-	  *				OcclusionQuery* m_pOcclusionQuery;
-	  *				createOcclusionQuery( &m_pOcclusionQuery );
-	  *				In the rendering loop:
-	  *				Draw all occluders
-	  *				m_pOcclusionQuery->startOcclusionQuery();
-	  *				Draw the polygons to be tested
-	  *				m_pOcclusionQuery->endOcclusionQuery();
-	  *
-	  *				Results must be pulled using:
-	  *				UINT	m_uintNumberOfPixelsVisable;
-	  *				pullOcclusionQuery( &m_dwNumberOfPixelsVisable );
-	  *			
-	  */
-	virtual void beginOcclusionQuery() = 0;
-
-	/**
-	  * Ends the hardware occlusion test
-	  */
-	virtual void endOcclusionQuery() = 0;
-
-	/**
-      * Pulls the hardware occlusion query.
-	  * @note Waits until the query result is available; use isStillOutstanding
-	  *		if just want to test if the result is available.
-      * @retval NumOfFragments will get the resulting number of fragments.
-      * @return True if success or false if not.
-      */
-	virtual bool pullOcclusionQuery(unsigned int* NumOfFragments) = 0;
-
 	/**
 	/**
-	  * Let's you get the last pixel count with out doing the hardware occlusion test
-	  * @return The last fragment count from the last test.
-	  * Remarks This function won't give you new values, just the old value.
-	  */
-	unsigned int getLastQuerysPixelcount() const { return mPixelCount; }
-
-	/**
-	  * Lets you know when query is done, or still be processed by the Hardware
-	  * @return true if query isn't finished.
-	  */
-	 virtual bool isStillOutstanding(void) = 0; 
-
-
-    //----------------------------------------------------------------------
-    // protected members
-    //--
-    protected :
-        // numbers of visible pixels determined by last query
-        unsigned int mPixelCount;
-        // is query hasn't yet returned a result.
-		bool		 mIsQueryResultStillOutstanding;
-};
-
-	/** @} */
-	/** @} */
-}
-#endif
-
+	* @brief	Represents a query that counts number of fragments rendered by the GPU
+	*			while the query is active.
+	*
+	* @note		Core thread only.
+	*/
+	class CM_EXPORT OcclusionQuery
+	{
+	public:
+		OcclusionQuery(bool binary);
+		virtual ~OcclusionQuery() {}
+
+		/**
+		* @brief	Starts the query. Any draw calls after this call will have any rendered fragments
+		*			counted in the query.
+		*
+		* @note		Place any commands you want to measure after this call. Call "end" when done.
+		*/
+		virtual void begin() = 0;
+
+		/**
+		* @brief	Stops the query. 
+		*
+		* @note		Be aware that queries are executed on the GPU and the results will not be immediately available.
+		*/
+		virtual void end() = 0;
+
+		/**
+		* @brief	Check if GPU has processed the query.
+		*/
+		virtual bool isReady() const = 0;
+
+		/**
+		 * @brief	Returns the number of fragments that passed the depth and stencil test between
+		 *			query start and end.
+		 *
+		 * @note	If the query is binary, this will return 0 or 1. 1 meaning one or more samples were rendered,
+		 *			but will not give you the exact count.
+		 */
+		virtual UINT32 getNumFragments() = 0;
+
+		/**
+		 * @brief	Triggered when the query has completed. Argument provided
+		 *			is the number of fragments counted by the query.
+		 */
+		Event<void(UINT32)> onComplete;
+
+		/**
+		 * @brief	Creates a new occlusion query. 
+		 *
+		 * @param binary	If query is binary it will not give you an exact count of fragments rendered, but will instead
+		 *					just return 0 (no fragments were rendered) or 1 (one or more fragments were rendered). Binary
+		 *					queries can return sooner as they potentially do not need to wait until all of the geometry is rendered.
+		 */
+		static OcclusionQueryPtr create(bool binary);
+
+	protected:
+		friend class QueryManager;
+
+		/**
+		* @brief	Returns true if the has still not been completed by the GPU.
+		*/
+		bool isActive() const { return mActive; }
+		void setActive(bool active) { mActive = active; }
+
+	protected:
+		bool mActive;
+		bool mBinary;
+	};
+}

+ 2 - 0
CamelotCore/Include/CmPrerequisites.h

@@ -130,6 +130,7 @@ namespace BansheeEngine
 	class VertexDataDesc;
 	class VertexDataDesc;
 	class EventQuery;
 	class EventQuery;
 	class TimerQuery;
 	class TimerQuery;
+	class OcclusionQuery;
 	class FrameAlloc;
 	class FrameAlloc;
 	class FolderMonitor;
 	class FolderMonitor;
 	// Asset import
 	// Asset import
@@ -220,6 +221,7 @@ namespace BansheeEngine
 	typedef std::shared_ptr<CoreThreadAccessor<CommandQueueSync>> SyncedCoreAccessorPtr;
 	typedef std::shared_ptr<CoreThreadAccessor<CommandQueueSync>> SyncedCoreAccessorPtr;
 	typedef std::shared_ptr<EventQuery> EventQueryPtr;
 	typedef std::shared_ptr<EventQuery> EventQueryPtr;
 	typedef std::shared_ptr<TimerQuery> TimerQueryPtr;
 	typedef std::shared_ptr<TimerQuery> TimerQueryPtr;
+	typedef std::shared_ptr<OcclusionQuery> OcclusionQueryPtr;
 	typedef std::shared_ptr<ResourceManifest> ResourceManifestPtr;
 	typedef std::shared_ptr<ResourceManifest> ResourceManifestPtr;
 }
 }
 
 

+ 38 - 5
CamelotCore/Include/CmQueryManager.h

@@ -16,23 +16,56 @@ namespace BansheeEngine
 	public:
 	public:
 		QueryManager();
 		QueryManager();
 
 
+		/**
+		 * @brief	Creates a new event query that allows you to get notified
+		 *			when GPU starts executing the query.
+		 */
 		virtual EventQueryPtr createEventQuery() const = 0;
 		virtual EventQueryPtr createEventQuery() const = 0;
+
+		/**
+		* @brief	Creates a new timer query that allows you to get notified
+		*			of how much time has passed between query start and end.
+		*/
 		virtual TimerQueryPtr createTimerQuery() const = 0;
 		virtual TimerQueryPtr createTimerQuery() const = 0;
 
 
+		/**
+		* @brief	Creates a new occlusion query that allows you to know
+		*			how many fragments were rendered between query start and end.
+		*
+		* @param binary	If query is binary it will not give you an exact count of fragments rendered, but will instead
+		*				just return 0 (no fragments were rendered) or 1 (one or more fragments were rendered). Binary
+		*				queries can return sooner as they potentially do not need to wait until all of the geometry is rendered.
+		*/
+		virtual OcclusionQueryPtr createOcclusionQuery(bool binary) const = 0;
+
 		/**
 		/**
 		 * @note	Internal method, called every frame.
 		 * @note	Internal method, called every frame.
 		 */
 		 */
-		void update();
-
-	protected:
-		mutable Vector<EventQuery*> mEventQueries;
-		mutable Vector<TimerQuery*> mTimerQueries;
+		void _update();
 
 
 	protected:
 	protected:
 		friend class EventQuery;
 		friend class EventQuery;
 		friend class TimerQuery;
 		friend class TimerQuery;
+		friend class OcclusionQuery;
 
 
+		/**
+		 * @brief	Deletes an Event query. Always use this method and don't delete them manually.
+		 */
 		static void deleteEventQuery(EventQuery* query);
 		static void deleteEventQuery(EventQuery* query);
+
+		/**
+		* @brief	Deletes a Timer query. Always use this method and don't delete them manually.
+		*/
 		static void deleteTimerQuery(TimerQuery* query);
 		static void deleteTimerQuery(TimerQuery* query);
+
+		/**
+		* @brief	Deletes an Occlusion query. Always use this method and don't delete them manually.
+		*/
+		static void deleteOcclusionQuery(OcclusionQuery* query);
+
+	protected:
+		mutable Vector<EventQuery*> mEventQueries;
+		mutable Vector<TimerQuery*> mTimerQueries;
+		mutable Vector<OcclusionQuery*> mOcclusionQueries;
 	};
 	};
 }
 }

+ 10 - 2
CamelotCore/Include/CmTimerQuery.h

@@ -41,15 +41,23 @@ namespace BansheeEngine
 		 */
 		 */
 		virtual float getTimeMs() = 0;
 		virtual float getTimeMs() = 0;
 
 
+		/**
+		* @brief	Triggered when GPU processes the query. As a parameter
+		*			it provides query duration in milliseconds.
+		*/
 		Event<void(float)> onTriggered;
 		Event<void(float)> onTriggered;
 
 
+		/**
+		 * @brief	Creates a new query, but does not schedule it on GPU.
+		 */
 		static TimerQueryPtr create();
 		static TimerQueryPtr create();
 
 
 	protected:
 	protected:
 		friend class QueryManager;
 		friend class QueryManager;
 
 
-		virtual void finalize() = 0;
-
+		/**
+		* @brief	Returns true if the has still not been completed by the GPU.
+		*/
 		bool isActive() const { return mActive; }
 		bool isActive() const { return mActive; }
 		void setActive(bool active) { mActive = active; }
 		void setActive(bool active) { mActive = active; }
 
 

+ 1 - 1
CamelotCore/Source/CmApplication.cpp

@@ -114,7 +114,7 @@ namespace BansheeEngine
 			PROFILE_CALL(gSceneManager().update(), "SceneManager");
 			PROFILE_CALL(gSceneManager().update(), "SceneManager");
 
 
 			gCoreThread().queueCommand(std::bind(&Application::beginCoreProfiling, this));
 			gCoreThread().queueCommand(std::bind(&Application::beginCoreProfiling, this));
-			gCoreThread().queueCommand(std::bind(&QueryManager::update, QueryManager::instancePtr()));
+			gCoreThread().queueCommand(std::bind(&QueryManager::_update, QueryManager::instancePtr()));
 
 
 			if(!mainLoopCallback.empty())
 			if(!mainLoopCallback.empty())
 				mainLoopCallback();
 				mainLoopCallback();

+ 13 - 43
CamelotCore/Source/CmOcclusionQuery.cpp

@@ -1,44 +1,14 @@
-/*
------------------------------------------------------------------------------
-This source file is part of OGRE
-    (Object-oriented Graphics Rendering Engine)
-For the latest info, see http://www.ogre3d.org
-
-Copyright (c) 2000-2011 Torus Knot Software Ltd
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
------------------------------------------------------------------------------
-*/
-
 #include "CmOcclusionQuery.h"
 #include "CmOcclusionQuery.h"
-
-namespace BansheeEngine {
-
-
-    OcclusionQuery::OcclusionQuery() : 
-        mPixelCount(0),
-        mIsQueryResultStillOutstanding(false)
-    {
-    }
-    OcclusionQuery::~OcclusionQuery()
-    {
-    }
-
-}
-
+#include "CmQueryManager.h"
+
+namespace BansheeEngine
+{
+	OcclusionQuery::OcclusionQuery(bool binary)
+		:mActive(false), mBinary(binary)
+	{ }
+
+	OcclusionQueryPtr OcclusionQuery::create(bool binary)
+	{
+		return QueryManager::instance().createOcclusionQuery(binary);
+	}
+}

+ 21 - 1
CamelotCore/Source/CmQueryManager.cpp

@@ -1,6 +1,7 @@
 #include "CmQueryManager.h"
 #include "CmQueryManager.h"
 #include "CmEventQuery.h"
 #include "CmEventQuery.h"
 #include "CmTimerQuery.h"
 #include "CmTimerQuery.h"
+#include "CmOcclusionQuery.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -9,7 +10,7 @@ namespace BansheeEngine
 
 
 	}
 	}
 
 
-	void QueryManager::update()
+	void QueryManager::_update()
 	{
 	{
 		for(auto& query : mEventQueries)
 		for(auto& query : mEventQueries)
 		{
 		{
@@ -28,6 +29,15 @@ namespace BansheeEngine
 				query->setActive(false);
 				query->setActive(false);
 			}
 			}
 		}
 		}
+
+		for (auto& query : mOcclusionQueries)
+		{
+			if (query->isActive() && query->isReady())
+			{
+				query->onComplete(query->getNumFragments());
+				query->setActive(false);
+			}
+		}
 	}
 	}
 
 
 	void QueryManager::deleteEventQuery(EventQuery* query)
 	void QueryManager::deleteEventQuery(EventQuery* query)
@@ -49,4 +59,14 @@ namespace BansheeEngine
 
 
 		cm_delete(query);
 		cm_delete(query);
 	}
 	}
+
+	void QueryManager::deleteOcclusionQuery(OcclusionQuery* query)
+	{
+		auto iterFind = std::find(instance().mOcclusionQueries.begin(), instance().mOcclusionQueries.end(), query);
+
+		if (iterFind != instance().mOcclusionQueries.end())
+			instance().mOcclusionQueries.erase(iterFind);
+
+		cm_delete(query);
+	}
 }
 }

+ 2 - 0
CamelotD3D11RenderSystem/CamelotD3D11RenderSystem.vcxproj

@@ -250,6 +250,7 @@
     <ClInclude Include="Include\CmD3D11Mappings.h" />
     <ClInclude Include="Include\CmD3D11Mappings.h" />
     <ClInclude Include="Include\CmD3D11MultiRenderTexture.h" />
     <ClInclude Include="Include\CmD3D11MultiRenderTexture.h" />
     <ClInclude Include="Include\CmD3D11GpuParamBlockBuffer.h" />
     <ClInclude Include="Include\CmD3D11GpuParamBlockBuffer.h" />
+    <ClInclude Include="Include\CmD3D11OcclusionQuery.h" />
     <ClInclude Include="Include\CmD3D11Prerequisites.h" />
     <ClInclude Include="Include\CmD3D11Prerequisites.h" />
     <ClInclude Include="Include\CmD3D11QueryManager.h" />
     <ClInclude Include="Include\CmD3D11QueryManager.h" />
     <ClInclude Include="Include\CmD3D11RenderUtility.h" />
     <ClInclude Include="Include\CmD3D11RenderUtility.h" />
@@ -288,6 +289,7 @@
     <ClCompile Include="Source\CmD3D11HLSLProgramFactory.cpp" />
     <ClCompile Include="Source\CmD3D11HLSLProgramFactory.cpp" />
     <ClCompile Include="Source\CmD3D11InputLayoutManager.cpp" />
     <ClCompile Include="Source\CmD3D11InputLayoutManager.cpp" />
     <ClCompile Include="Source\CmD3D11Mappings.cpp" />
     <ClCompile Include="Source\CmD3D11Mappings.cpp" />
+    <ClCompile Include="Source\CmD3D11OcclusionQuery.cpp" />
     <ClCompile Include="Source\CmD3D11Plugin.cpp" />
     <ClCompile Include="Source\CmD3D11Plugin.cpp" />
     <ClCompile Include="Source\CmD3D11QueryManager.cpp" />
     <ClCompile Include="Source\CmD3D11QueryManager.cpp" />
     <ClCompile Include="Source\CmD3D11RenderUtility.cpp" />
     <ClCompile Include="Source\CmD3D11RenderUtility.cpp" />

+ 6 - 0
CamelotD3D11RenderSystem/CamelotD3D11RenderSystem.vcxproj.filters

@@ -129,6 +129,9 @@
     <ClInclude Include="Include\CmD3D11GpuProgramRTTI.h">
     <ClInclude Include="Include\CmD3D11GpuProgramRTTI.h">
       <Filter>Header Files\RTTI</Filter>
       <Filter>Header Files\RTTI</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="Include\CmD3D11OcclusionQuery.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\CmD3D11GpuProgram.cpp">
     <ClCompile Include="Source\CmD3D11GpuProgram.cpp">
@@ -239,5 +242,8 @@
     <ClCompile Include="Source\CmD3D11TimerQuery.cpp">
     <ClCompile Include="Source\CmD3D11TimerQuery.cpp">
       <Filter>Source Files</Filter>
       <Filter>Source Files</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="Source\CmD3D11OcclusionQuery.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
 </Project>
 </Project>

+ 48 - 0
CamelotD3D11RenderSystem/Include/CmD3D11OcclusionQuery.h

@@ -0,0 +1,48 @@
+#pragma once
+
+#include "CmD3D11Prerequisites.h"
+#include "CmOcclusionQuery.h"
+
+namespace BansheeEngine
+{
+	/**
+	* @copydoc OcclusionQuery
+	*/
+	class CM_D3D11_EXPORT D3D11OcclusionQuery : public OcclusionQuery
+	{
+	public:
+		D3D11OcclusionQuery(bool binary);
+		~D3D11OcclusionQuery();
+
+		/**
+		* @copydoc OcclusionQuery::begin
+		*/
+		virtual void begin();
+
+		/**
+		* @copydoc OcclusionQuery::end
+		*/
+		virtual void end();
+
+		/**
+		* @copydoc OcclusionQuery::isReady
+		*/
+		virtual bool isReady() const;
+
+		/**
+		* @copydoc OcclusionQuery::getNumFragments
+		*/
+		virtual UINT32 getNumFragments();
+
+	private:
+		friend class QueryManager;
+
+		ID3D11Query* mQuery;
+		ID3D11DeviceContext* mContext;
+		bool mFinalized;
+
+		UINT32 mNumFragments;
+
+		void finalize();
+	};
+}

+ 12 - 0
CamelotD3D11RenderSystem/Include/CmD3D11QueryManager.h

@@ -8,7 +8,19 @@ namespace BansheeEngine
 	class CM_D3D11_EXPORT D3D11QueryManager : public QueryManager
 	class CM_D3D11_EXPORT D3D11QueryManager : public QueryManager
 	{
 	{
 	public:
 	public:
+		/**
+		 * @copydoc		QueryManager::createEventQuery
+		 */
 		EventQueryPtr createEventQuery() const;
 		EventQueryPtr createEventQuery() const;
+
+		/**
+		 * @copydoc		QueryManager::createTimerQuery
+		 */
 		TimerQueryPtr createTimerQuery() const;
 		TimerQueryPtr createTimerQuery() const;
+
+		/**
+		 * @copydoc		QueryManager::createOcclusionQuery
+		 */
+		OcclusionQueryPtr createOcclusionQuery(bool binary) const;
 	};
 	};
 }
 }

+ 1 - 1
CamelotD3D11RenderSystem/Include/CmD3D11TimerQuery.h

@@ -43,6 +43,6 @@ namespace BansheeEngine
 		ID3D11Query* mDisjointQuery;
 		ID3D11Query* mDisjointQuery;
 		ID3D11DeviceContext* mContext;
 		ID3D11DeviceContext* mContext;
 
 
-		virtual void finalize();
+		void finalize();
 	};
 	};
 }
 }

+ 87 - 0
CamelotD3D11RenderSystem/Source/CmD3D11OcclusionQuery.cpp

@@ -0,0 +1,87 @@
+#include "CmD3D11OcclusionQuery.h"
+#include "CmD3D11RenderSystem.h"
+#include "CmD3D11Device.h"
+#include "CmMath.h"
+
+namespace BansheeEngine
+{
+	D3D11OcclusionQuery::D3D11OcclusionQuery(bool binary)
+		:OcclusionQuery(binary), mContext(nullptr), mQuery(nullptr), mNumFragments(0), mFinalized(false)
+	{
+		D3D11RenderSystem* rs = static_cast<D3D11RenderSystem*>(RenderSystem::instancePtr());
+		D3D11Device& device = rs->getPrimaryDevice();
+
+		D3D11_QUERY_DESC queryDesc;
+		queryDesc.Query = mBinary ? D3D11_QUERY_OCCLUSION_PREDICATE : D3D11_QUERY_OCCLUSION;
+		queryDesc.MiscFlags = 0;
+
+		HRESULT hr = device.getD3D11Device()->CreateQuery(&queryDesc, &mQuery);
+		if (hr != S_OK)
+			CM_EXCEPT(RenderingAPIException, "Failed to create an occlusion query.");
+
+		mContext = device.getImmediateContext();
+	}
+
+	D3D11OcclusionQuery::~D3D11OcclusionQuery()
+	{
+		if (mQuery != nullptr)
+			mQuery->Release();
+	}
+
+	void D3D11OcclusionQuery::begin()
+	{
+		mContext->Begin(mQuery);
+
+		mNumFragments = 0;
+		setActive(true);
+	}
+
+	void D3D11OcclusionQuery::end()
+	{
+		mContext->End(mQuery);
+	}
+
+	bool D3D11OcclusionQuery::isReady() const
+	{
+		if (mBinary)
+		{
+			BOOL anyFragments = FALSE;
+			return mContext->GetData(mQuery, &anyFragments, sizeof(anyFragments), 0) == S_OK;
+		}
+		else
+		{
+			UINT64 numFragments = 0;
+			return mContext->GetData(mQuery, &numFragments, sizeof(numFragments), 0) == S_OK;
+		}
+	}
+
+	UINT32 D3D11OcclusionQuery::getNumFragments()
+	{
+		if (!mFinalized && isReady())
+		{
+			finalize();
+		}
+
+		return mNumFragments;
+	}
+
+	void D3D11OcclusionQuery::finalize()
+	{
+		mFinalized = true;
+
+		if (mBinary)
+		{
+			BOOL anyFragments = FALSE;
+			mContext->GetData(mQuery, &anyFragments, sizeof(anyFragments), 0);
+
+			mNumFragments = anyFragments == TRUE ? 1 : 0;
+		}
+		else
+		{
+			UINT64 numFragments = 0;
+			mContext->GetData(mQuery, &numFragments, sizeof(numFragments), 0);
+
+			mNumFragments = (UINT32)numFragments;
+		}
+	}
+}

+ 9 - 0
CamelotD3D11RenderSystem/Source/CmD3D11QueryManager.cpp

@@ -1,6 +1,7 @@
 #include "CmD3D11QueryManager.h"
 #include "CmD3D11QueryManager.h"
 #include "CmD3D11EventQuery.h"
 #include "CmD3D11EventQuery.h"
 #include "CmD3D11TimerQuery.h"
 #include "CmD3D11TimerQuery.h"
+#include "CmD3D11OcclusionQuery.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -19,4 +20,12 @@ namespace BansheeEngine
 
 
 		return query;
 		return query;
 	}
 	}
+
+	OcclusionQueryPtr D3D11QueryManager::createOcclusionQuery(bool binary) const
+	{
+		OcclusionQueryPtr query = std::shared_ptr<D3D11OcclusionQuery>(cm_new<D3D11OcclusionQuery>(binary), &QueryManager::deleteOcclusionQuery, StdAlloc<GenAlloc>());
+		mOcclusionQueries.push_back(query.get());
+
+		return query;
+	}
 }
 }

+ 26 - 94
CamelotD3D9Renderer/Include/CmD3D9OcclusionQuery.h

@@ -1,115 +1,47 @@
-/*
------------------------------------------------------------------------------
-This source file is part of OGRE
-(Object-oriented Graphics Rendering Engine)
-For the latest info, see http://www.ogre3d.org
-
-Copyright (c) 2000-2011 Torus Knot Software Ltd
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
------------------------------------------------------------------------------
-*/
-
-#ifndef _D3D9HARWAREOCCLUSIONQUERY_H__
-#define _D3D9HARWAREOCCLUSIONQUERY_H__
+#pragma once
 
 
 #include "CmD3D9Prerequisites.h"
 #include "CmD3D9Prerequisites.h"
 #include "CmOcclusionQuery.h"
 #include "CmOcclusionQuery.h"
-#include "CmD3D9Resource.h"
-
-
-namespace BansheeEngine {
-
-	// If you use multiple rendering passes you can test only the first pass and all other passes don't have to be rendered 
-	// if the first pass results has too few pixels visible.
-
-	// Be sure to render all occluder first and whats out so the RenderQue don't switch places on 
-	// the occluding objects and the tested objects because it thinks it's more effective..
 
 
+namespace BansheeEngine
+{
 	/**
 	/**
-	* This is a class that is the DirectX9 implementation of 
-	* hardware occlusion testing.
-	*
-	* @author Lee Sandberg, email [email protected]
-	*
-	* Updated on 12/7/2004 by Chris McGuirk
-	* Updated on 4/8/2005 by Tuan Kuranes email: [email protected]
+	* @copydoc OcclusionQuery
 	*/
 	*/
-	class CM_D3D9_EXPORT D3D9OcclusionQuery : public OcclusionQuery, public D3D9Resource
+	class CM_D3D9_EXPORT D3D9OcclusionQuery : public OcclusionQuery
 	{
 	{
-		//----------------------------------------------------------------------
-		// Public methods
-		//--
 	public:
 	public:
+		D3D9OcclusionQuery(bool binary);
+		~D3D9OcclusionQuery();
 
 
 		/**
 		/**
-		* Default object constructor
-		* 
+		* @copydoc OcclusionQuery::begin
 		*/
 		*/
-		D3D9OcclusionQuery();
+		virtual void begin();
 
 
 		/**
 		/**
-		* Object destructor
+		* @copydoc OcclusionQuery::end
 		*/
 		*/
-		~D3D9OcclusionQuery();
+		virtual void end();
 
 
-		//------------------------------------------------------------------
-		// Occlusion query functions (see base class documentation for this)
-		//--
-
-		void beginOcclusionQuery();	
-		void endOcclusionQuery();
-		bool pullOcclusionQuery( unsigned int* NumOfFragments);
-		unsigned int getLastQuerysPixelcount();
-        bool isStillOutstanding(void);
-	
-		// Called immediately after the Direct3D device has been created.
-		virtual void notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device);
-
-		// Called before the Direct3D device is going to be destroyed.
-		virtual void notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device);
-		
-		// Called immediately after the Direct3D device has entered a lost state.
-		// This is the place to release non-managed resources.
-		virtual void notifyOnDeviceLost(IDirect3DDevice9* d3d9Device);
+		/**
+		* @copydoc OcclusionQuery::isReady
+		*/
+		virtual bool isReady() const;
 
 
-		// Called immediately after the Direct3D device has been reset.
-		// This is the place to create non-managed resources.
-		virtual void notifyOnDeviceReset(IDirect3DDevice9* d3d9Device);
-	
+		/**
+		* @copydoc OcclusionQuery::getNumFragments
+		*/
+		virtual UINT32 getNumFragments();
 
 
 	private:
 	private:
-		void createQuery(IDirect3DDevice9* d3d9Device);
-		void releaseQuery(IDirect3DDevice9* d3d9Device);
+		friend class QueryManager;
 
 
-		//----------------------------------------------------------------------
-		// private members
-		//--
-	private:					
-		typedef Map<IDirect3DDevice9*, IDirect3DQuery9*> DeviceToQueryMap;
-		typedef DeviceToQueryMap::iterator					   DeviceToQueryIterator;
+		IDirect3DQuery9* mQuery;
+		bool mFinalized;
 
 
-		DeviceToQueryMap				mMapDeviceToQuery;		
-	};
-
-
-}
+		UINT32 mNumFragments;
 
 
-
-#endif
+		void finalize();
+	};
+}

+ 12 - 0
CamelotD3D9Renderer/Include/CmD3D9QueryManager.h

@@ -8,7 +8,19 @@ namespace BansheeEngine
 	class CM_D3D9_EXPORT D3D9QueryManager : public QueryManager
 	class CM_D3D9_EXPORT D3D9QueryManager : public QueryManager
 	{
 	{
 	public:
 	public:
+		/**
+		 * @copydoc		QueryManager::createEventQuery
+		 */
 		EventQueryPtr createEventQuery() const;
 		EventQueryPtr createEventQuery() const;
+
+		/**
+		 * @copydoc		QueryManager::createTimerQuery
+		 */
 		TimerQueryPtr createTimerQuery() const;
 		TimerQueryPtr createTimerQuery() const;
+
+		/**
+		 * @copydoc		QueryManager::createOcclusionQuery
+		 */
+		OcclusionQueryPtr createOcclusionQuery(bool binary) const;
 	};
 	};
 }
 }

+ 1 - 1
CamelotD3D9Renderer/Include/CmD3D9TimerQuery.h

@@ -43,6 +43,6 @@ namespace BansheeEngine
 		IDirect3DQuery9* mDisjointQuery;
 		IDirect3DQuery9* mDisjointQuery;
 		IDirect3DQuery9* mFreqQuery;
 		IDirect3DQuery9* mFreqQuery;
 
 
-		virtual void finalize();
+		void finalize();
 	};
 	};
 }
 }

+ 35 - 225
CamelotD3D9Renderer/Source/CmD3D9OcclusionQuery.cpp

@@ -1,253 +1,63 @@
-/*
------------------------------------------------------------------------------
-This source file is part of OGRE
-(Object-oriented Graphics Rendering Engine)
-For the latest info, see http://www.ogre3d.org
-
-Copyright (c) 2000-2011 Torus Knot Software Ltd
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
------------------------------------------------------------------------------
-*/
 #include "CmD3D9OcclusionQuery.h"
 #include "CmD3D9OcclusionQuery.h"
-#include "CmRenderSystemCapabilities.h"
-#include "CmException.h"
 #include "CmD3D9RenderSystem.h"
 #include "CmD3D9RenderSystem.h"
+#include "CmMath.h"
 
 
-namespace BansheeEngine {
-
-	/**
-	* This is a class that is the DirectX9 implementation of 
-	* hardware occlusion testing.
-	*
-	* @author Lee Sandberg
-	*
-	* Updated on 12/7/2004 by Chris McGuirk
-	* Updated on 4/8/2005 by Tuan Kuranes email: [email protected]
-	*/
-
-	/**
-	* Default object constructor
-	*/
-    D3D9OcclusionQuery::D3D9OcclusionQuery()
-	{ 
-		
-	}
-
-	/**
-	* Object destructor
-	*/
-	D3D9OcclusionQuery::~D3D9OcclusionQuery() 
-	{ 
-		DeviceToQueryIterator it = mMapDeviceToQuery.begin();
-
-		while (it != mMapDeviceToQuery.end())
-		{
-			SAFE_RELEASE(it->second);
-			++it;
-		}	
-		mMapDeviceToQuery.clear();
-	}
-
-	//------------------------------------------------------------------
-	// Occlusion query functions (see base class documentation for this)
-	//--
-	void D3D9OcclusionQuery::beginOcclusionQuery() 
-	{	
-		IDirect3DDevice9* pCurDevice  = D3D9RenderSystem::getActiveD3D9Device();				
-		DeviceToQueryIterator it      = mMapDeviceToQuery.find(pCurDevice);
-
-		// No resource exits for current device -> create it.
-		if (it == mMapDeviceToQuery.end() || it->second == NULL)		
-			createQuery(pCurDevice);			
-		
-
-		// Grab the query of the current device.
-		IDirect3DQuery9* pOccQuery = mMapDeviceToQuery[pCurDevice];
-
-		
-		if (pOccQuery != NULL)
-		{
-			pOccQuery->Issue(D3DISSUE_BEGIN); 
-			mIsQueryResultStillOutstanding = true;
-			mPixelCount = 0;
-		}		
-	}
+namespace BansheeEngine
+{
+	D3D9OcclusionQuery::D3D9OcclusionQuery(bool binary)
+		:OcclusionQuery(binary), mQuery(nullptr), mNumFragments(0), mFinalized(false)
+	{
+		IDirect3DDevice9* device = D3D9RenderSystem::getActiveD3D9Device();
 
 
-	void D3D9OcclusionQuery::endOcclusionQuery() 
-	{ 
-		IDirect3DDevice9* pCurDevice  = D3D9RenderSystem::getActiveD3D9Device();				
-		DeviceToQueryIterator it      = mMapDeviceToQuery.find(pCurDevice);
-		
-		if (it == mMapDeviceToQuery.end())
+		HRESULT hr = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &mQuery);
+		if (hr != S_OK)
 		{
 		{
-			CM_EXCEPT(RenderingAPIException, "End occlusion called without matching begin call !!" );
+			CM_EXCEPT(RenderingAPIException, "Failed to create an occlusion query.");
 		}
 		}
-
-		IDirect3DQuery9* pOccQuery = mMapDeviceToQuery[pCurDevice];
-
-		if (pOccQuery != NULL)
-			pOccQuery->Issue(D3DISSUE_END); 
-	}	
-
-	//------------------------------------------------------------------
-	bool D3D9OcclusionQuery::pullOcclusionQuery( unsigned int* NumOfFragments ) 
-	{
-		IDirect3DDevice9* pCurDevice = D3D9RenderSystem::getActiveD3D9Device();
-		DeviceToQueryIterator it     = mMapDeviceToQuery.find(pCurDevice);
-
-		if (it == mMapDeviceToQuery.end())		
-			return false;
-
-		if (it->second == NULL)
-			return false;
-
-        // in case you didn't check if query arrived and want the result now.
-        if (mIsQueryResultStillOutstanding)
-        {
-            // Loop until the data becomes available
-            DWORD pixels;
-            const size_t dataSize = sizeof( DWORD );
-			while (1)
-            {
-                const HRESULT hr = it->second->GetData((void *)&pixels, dataSize, D3DGETDATA_FLUSH);
-
-                if  (hr == S_FALSE)
-                    continue;
-                if  (hr == S_OK)
-                {
-                    mPixelCount = pixels;
-                    *NumOfFragments = pixels;
-                    break;
-                }
-                if (hr == D3DERR_DEVICELOST)
-                {
-                    *NumOfFragments = 0;
-                    mPixelCount = 0;
-                    SAFE_RELEASE(it->second);
-                    break;
-                }
-            } 
-            mIsQueryResultStillOutstanding = false;
-        }
-        else
-        {
-            // we already stored result from last frames.
-            *NumOfFragments = mPixelCount;
-        }		
-		return true;
 	}
 	}
 
 
-	//------------------------------------------------------------------
-	unsigned int D3D9OcclusionQuery::getLastQuerysPixelcount()
+	D3D9OcclusionQuery::~D3D9OcclusionQuery()
 	{
 	{
-		return mPixelCount;
+		if (mQuery != nullptr)
+			mQuery->Release();
 	}
 	}
 
 
-    //------------------------------------------------------------------
-    bool D3D9OcclusionQuery::isStillOutstanding(void)
-    {       
-        // in case you already asked for this query
-        if (!mIsQueryResultStillOutstanding)
-            return false;
-
-		IDirect3DDevice9* pCurDevice = D3D9RenderSystem::getActiveD3D9Device();
-		DeviceToQueryIterator it     = mMapDeviceToQuery.find(pCurDevice);
-
-		if (it == mMapDeviceToQuery.end())		
-			return false;
-
-		if (it->second == NULL)
-			return false;
-
-
-        DWORD pixels;
-        const HRESULT hr = it->second->GetData( (void *) &pixels, sizeof( DWORD ), 0);
-
-        if (hr  == S_FALSE)
-            return true;
-
-        if (hr == D3DERR_DEVICELOST)
-        {
-            mPixelCount = 100000;  
-			SAFE_RELEASE(it->second);
-        }
-
-        mPixelCount = pixels;
-        mIsQueryResultStillOutstanding = false;
-        return false;
-	}
-
-	//------------------------------------------------------------------
-	void D3D9OcclusionQuery::notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device)
+	void D3D9OcclusionQuery::begin()
 	{
 	{
-		
-	}
+		mQuery->Issue(D3DISSUE_BEGIN);
 
 
-	//------------------------------------------------------------------
-	void D3D9OcclusionQuery::notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device)
-	{		
-		releaseQuery(d3d9Device);
+		mNumFragments = 0;
+		setActive(true);
 	}
 	}
 
 
-	//------------------------------------------------------------------
-	void D3D9OcclusionQuery::notifyOnDeviceLost(IDirect3DDevice9* d3d9Device)
-	{		
-		releaseQuery(d3d9Device);		
+	void D3D9OcclusionQuery::end()
+	{
+		mQuery->Issue(D3DISSUE_END);
 	}
 	}
 
 
-	//------------------------------------------------------------------
-	void D3D9OcclusionQuery::notifyOnDeviceReset(IDirect3DDevice9* d3d9Device)
-	{		
-		
+	bool D3D9OcclusionQuery::isReady() const
+	{
+		BOOL queryData;
+		return mQuery->GetData(&queryData, sizeof(BOOL), 0) == S_OK;
 	}
 	}
 
 
-	//------------------------------------------------------------------
-	void D3D9OcclusionQuery::createQuery(IDirect3DDevice9* d3d9Device)
+	UINT32 D3D9OcclusionQuery::getNumFragments()
 	{
 	{
-		HRESULT hr;
-
-		// Check if query supported.
-		hr = d3d9Device->CreateQuery(D3DQUERYTYPE_OCCLUSION, NULL);
-		if (FAILED(hr))
+		if (!mFinalized && isReady())
 		{
 		{
-			mMapDeviceToQuery[d3d9Device] = NULL;
-			return;
+			finalize();
 		}
 		}
 
 
-		// create the occlusion query.
-		IDirect3DQuery9*  pCurQuery;
-		hr = d3d9Device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &pCurQuery);
-				
-		mMapDeviceToQuery[d3d9Device] = pCurQuery;	
+		return mNumFragments;
 	}
 	}
 
 
-	//------------------------------------------------------------------
-	void D3D9OcclusionQuery::releaseQuery(IDirect3DDevice9* d3d9Device)
+	void D3D9OcclusionQuery::finalize()
 	{
 	{
-		DeviceToQueryIterator it     = mMapDeviceToQuery.find(d3d9Device);
+		mFinalized = true;
 
 
-		// Remove from query resource map.
-		if (it != mMapDeviceToQuery.end())		
-		{
-			SAFE_RELEASE(it->second);
-			mMapDeviceToQuery.erase(it);
-		}
+		DWORD numFragments;
+		mQuery->GetData(&numFragments, sizeof(DWORD), 0);
+
+		mNumFragments = (UINT32)numFragments;
 	}
 	}
-}
+}

+ 9 - 0
CamelotD3D9Renderer/Source/CmD3D9QueryManager.cpp

@@ -1,6 +1,7 @@
 #include "CmD3D9QueryManager.h"
 #include "CmD3D9QueryManager.h"
 #include "CmD3D9EventQuery.h"
 #include "CmD3D9EventQuery.h"
 #include "CmD3D9TimerQuery.h"
 #include "CmD3D9TimerQuery.h"
+#include "CmD3D9OcclusionQuery.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -19,4 +20,12 @@ namespace BansheeEngine
 
 
 		return query;
 		return query;
 	}
 	}
+
+	OcclusionQueryPtr D3D9QueryManager::createOcclusionQuery(bool binary) const
+	{
+		OcclusionQueryPtr query = std::shared_ptr<D3D9OcclusionQuery>(cm_new<D3D9OcclusionQuery>(binary), &QueryManager::deleteOcclusionQuery, StdAlloc<GenAlloc>());
+		mOcclusionQueries.push_back(query.get());
+
+		return query;
+	}
 }
 }

+ 41 - 102
CamelotGLRenderer/Include/CmGLOcclusionQuery.h

@@ -1,108 +1,47 @@
-/*
------------------------------------------------------------------------------
-This source file is part of OGRE
-    (Object-oriented Graphics Rendering Engine)
-For the latest info, see http://www.ogre3d.org
-
-Copyright (c) 2000-2011 Torus Knot Software Ltd
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
------------------------------------------------------------------------------
-*/
-
-/*
-The nVidia occlusion query extension is defined in glext.h so you don't 
-need anything else. You do need to look up the function, we provide a 
-GLSupport class to do this, which has platform implementations for 
-getProcAddress. Check the way that extensions like glActiveTextureARB are 
-initialised and used in glRenderSystem and copy what is done there.
-
-
-
-  To do: fix so dx7 and DX9 checks and flags if HW Occlusion is supported
-  See the openGl dito for ideas what to do.
-
-*/
-
-
-
-//GL_ActiveTextureARB_Func* glActiveTextureARB_ptr = (GL_ActiveTextureARB_Func)mGLSupport->getProcAddress("glActiveTextureARB");
-
-#ifndef __GLHARDWAREOCCLUSIONQUERY_H__
-#define __GLHARDWAREOCCLUSIONQUERY_H__
+#pragma once
 
 
 #include "CmGLPrerequisites.h"
 #include "CmGLPrerequisites.h"
 #include "CmOcclusionQuery.h"
 #include "CmOcclusionQuery.h"
 
 
-
-namespace BansheeEngine { 
-
-
-// If you use multiple rendering passes you can test only the first pass and all other passes don't have to be rendered 
-// if the first pass result has too few pixels visible.
-
-// Be sure to render all occluder first and whats out so the RenderQue don't switch places on 
-// the occluding objects and the tested objects because it thinks it's more effective..
-
-
-/**
-  * This is a class that is the base class of the query class for 
-  * hardware occlusion.
-  *
-  * @author Lee Sandberg email: [email protected]
-  * Updated on 13/9/2005 by Tuan Kuranes email: [email protected]
-  */
-
-class CM_RSGL_EXPORT GLOcclusionQuery : public OcclusionQuery
+namespace BansheeEngine
 {
 {
-//----------------------------------------------------------------------
-// Public methods
-//--
-public:
-	/**
-	  * Default object constructor
-	  * 
-	  */
-	GLOcclusionQuery();
 	/**
 	/**
-	  * Object destructor
-	  */
-	~GLOcclusionQuery();
-
-	//------------------------------------------------------------------
-	// Occlusion query functions (see base class documentation for this)
-	//--
-	void beginOcclusionQuery();
-	void endOcclusionQuery();
-	bool pullOcclusionQuery( unsigned int* NumOfFragments); 
-	bool isStillOutstanding(void);
-
-
-    //----------------------------------------------------------------------
-    // private members
-    //--
-    private:
-
-	    GLuint			mQueryID;
-};
-
-}
-
-#endif 
-
+	 * @copydoc OcclusionQuery
+	 */
+	class CM_RSGL_EXPORT GLOcclusionQuery : public OcclusionQuery
+	{
+	public:
+		GLOcclusionQuery(bool binary);
+		~GLOcclusionQuery();
+
+		/**
+		 * @copydoc OcclusionQuery::begin
+		 */
+		virtual void begin();
+
+		/**
+		 * @copydoc OcclusionQuery::end
+		 */
+		virtual void end();
+
+		/**
+		 * @copydoc OcclusionQuery::isReady
+		 */
+		virtual bool isReady() const;
+
+		/**
+		 * @copydoc OcclusionQuery::getNumFragments
+		 */
+		virtual UINT32 getNumFragments();
+
+	private:
+		friend class QueryManager;
+
+		GLuint mQueryObj;
+		bool mFinalized;
+
+		UINT32 mNumFragments;
+
+		void finalize();
+	};
+}

+ 12 - 0
CamelotGLRenderer/Include/CmGLQueryManager.h

@@ -8,7 +8,19 @@ namespace BansheeEngine
 	class CM_RSGL_EXPORT GLQueryManager : public QueryManager
 	class CM_RSGL_EXPORT GLQueryManager : public QueryManager
 	{
 	{
 	public:
 	public:
+		/**
+		 * @copydoc		QueryManager::createEventQuery
+		 */
 		EventQueryPtr createEventQuery() const;
 		EventQueryPtr createEventQuery() const;
+
+		/**
+		 * @copydoc		QueryManager::createTimerQuery
+		 */
 		TimerQueryPtr createTimerQuery() const;
 		TimerQueryPtr createTimerQuery() const;
+
+		/**
+		 * @copydoc		QueryManager::createOcclusionQuery
+		 */
+		OcclusionQueryPtr createOcclusionQuery(bool binary) const;
 	};
 	};
 }
 }

+ 1 - 1
CamelotGLRenderer/Include/CmGLTimerQuery.h

@@ -43,6 +43,6 @@ namespace BansheeEngine
 
 
 		float mTimeDelta;
 		float mTimeDelta;
 
 
-		virtual void finalize();
+		void finalize();
 	};
 	};
 }
 }

+ 48 - 126
CamelotGLRenderer/Source/CmGLOcclusionQuery.cpp

@@ -1,145 +1,67 @@
-/*
------------------------------------------------------------------------------
-This source file is part of OGRE
-    (Object-oriented Graphics Rendering Engine)
-For the latest info, see http://www.ogre3d.org
-
-Copyright (c) 2000-2011 Torus Knot Software Ltd
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
------------------------------------------------------------------------------
-*/
-
 #include "CmGLOcclusionQuery.h"
 #include "CmGLOcclusionQuery.h"
-#include "CmException.h"
+#include "CmMath.h"
 
 
-namespace BansheeEngine {
-
-/**
-  * This is a class that is the base class of the query class for 
-  * hardware occlusion testing.
-  *
-  * @author Lee Sandberg email: [email protected]
-  *
-  * Updated on 12/7/2004 by Chris McGuirk
-  * - Implemented ARB_occlusion_query
-  * Updated on 13/9/2005 by Tuan Kuranes email: [email protected]
-  */
-//------------------------------------------------------------------
-/**
-  * Default object constructor
-  * 
-  */
-GLOcclusionQuery::GLOcclusionQuery() 
-{ 
-	// Check for hardware occlusion support
-    if(GLEW_VERSION_1_5 || GLEW_ARB_occlusion_query)
-	{
-	    glGenQueriesARB(1, &mQueryID );	
-	}
-	else if (GLEW_NV_occlusion_query)
-	{
-		glGenOcclusionQueriesNV(1, &mQueryID);
-	}
-	else
-    {
-		CM_EXCEPT(InternalErrorException, 
-                    "Cannot allocate a Hardware query. This video card doesn't supports it, sorry.");
-    }
-	
-}
-//------------------------------------------------------------------
-/**
-  * Object destructor
-  */
-GLOcclusionQuery::~GLOcclusionQuery() 
-{ 
-    if(GLEW_VERSION_1_5 || GLEW_ARB_occlusion_query)
-	{
-		glDeleteQueriesARB(1, &mQueryID);  
-	}
-	else if (GLEW_NV_occlusion_query)
-	{
-		glDeleteOcclusionQueriesNV(1, &mQueryID);  
-	}
-}
-//------------------------------------------------------------------
-void GLOcclusionQuery::beginOcclusionQuery() 
-{ 
-    if(GLEW_VERSION_1_5 || GLEW_ARB_occlusion_query)
-	{
-		glBeginQueryARB(GL_SAMPLES_PASSED_ARB, mQueryID);
-	}
-	else if (GLEW_NV_occlusion_query)
-	{
-		glBeginOcclusionQueryNV(mQueryID);
-	}
-}
-//------------------------------------------------------------------
-void GLOcclusionQuery::endOcclusionQuery() 
-{ 
-    if(GLEW_VERSION_1_5 || GLEW_ARB_occlusion_query)
+namespace BansheeEngine
+{
+	GLOcclusionQuery::GLOcclusionQuery(bool binary)
+		:OcclusionQuery(binary), mQueryObj(0), mNumFragments(0), mFinalized(false)
 	{
 	{
-	    glEndQueryARB(GL_SAMPLES_PASSED_ARB);
+		glGenQueries(1, &mQueryObj);
 	}
 	}
-	else if (GLEW_NV_occlusion_query)
+
+	GLOcclusionQuery::~GLOcclusionQuery()
 	{
 	{
-		glEndOcclusionQueryNV();
+		glDeleteQueries(1, &mQueryObj);
 	}
 	}
-	
-}
-//------------------------------------------------------------------
-bool GLOcclusionQuery::pullOcclusionQuery( unsigned int* NumOfFragments ) 
-{
-    if(GLEW_VERSION_1_5 || GLEW_ARB_occlusion_query)
+
+	void GLOcclusionQuery::begin()
 	{
 	{
-		glGetQueryObjectuivARB(mQueryID, GL_QUERY_RESULT_ARB, (GLuint*)NumOfFragments);
-		mPixelCount = *NumOfFragments;
-		return true;
+		glBeginQuery(mBinary ? GL_ANY_SAMPLES_PASSED : GL_SAMPLES_PASSED, mQueryObj);
+
+		mNumFragments = 0;
+		setActive(true);
 	}
 	}
-	else if (GLEW_NV_occlusion_query)
+
+	void GLOcclusionQuery::end()
 	{
 	{
-		glGetOcclusionQueryuivNV(mQueryID, GL_PIXEL_COUNT_NV, (GLuint*)NumOfFragments);
-		mPixelCount = *NumOfFragments;
-		return true;
+		glEndQuery(mBinary ? GL_ANY_SAMPLES_PASSED : GL_SAMPLES_PASSED);
 	}
 	}
 
 
-	return false;
-}
-//------------------------------------------------------------------
-bool GLOcclusionQuery::isStillOutstanding(void)
-{    
-      GLuint available;
-
-    if(GLEW_VERSION_1_5 || GLEW_ARB_occlusion_query)
+	bool GLOcclusionQuery::isReady() const
 	{
 	{
-	    glGetQueryObjectuivARB(mQueryID, GL_QUERY_RESULT_AVAILABLE_ARB, &available);
+		GLint done = 0;
+		glGetQueryObjectiv(mQueryObj, GL_QUERY_RESULT_AVAILABLE, &done);
+
+		return done == GL_TRUE;
 	}
 	}
-	else if (GLEW_NV_occlusion_query)
+
+	UINT32 GLOcclusionQuery::getNumFragments()
 	{
 	{
-	    glGetOcclusionQueryuivNV(mQueryID, GL_PIXEL_COUNT_AVAILABLE_NV, &available);
+		if (!mFinalized && isReady())
+		{
+			finalize();
+		}
+
+		return mNumFragments;
 	}
 	}
 
 
-	// GL_TRUE means a wait would occur
-    return !(available == GL_TRUE);  
-} 
+	void GLOcclusionQuery::finalize()
+	{
+		mFinalized = true;
 
 
-}
+		if (mBinary)
+		{
+			GLboolean anyPassed = GL_FALSE;
+			glGetQueryObjectuiv(mQueryObj, GL_QUERY_RESULT_ARB, (GLuint*)&anyPassed);
 
 
+			mNumFragments = anyPassed == GL_TRUE ? 1 : 0;
+		}
+		else
+		{
+			GLuint numFragments = 0;
+			glGetQueryObjectuiv(mQueryObj, GL_QUERY_RESULT_ARB, (GLuint*)&numFragments);
 
 
+			mNumFragments = (UINT32)numFragments;
+		}
+	}
+}

+ 9 - 0
CamelotGLRenderer/Source/CmGLQueryManager.cpp

@@ -1,6 +1,7 @@
 #include "CmGLQueryManager.h"
 #include "CmGLQueryManager.h"
 #include "CmGLEventQuery.h"
 #include "CmGLEventQuery.h"
 #include "CmGLTimerQuery.h"
 #include "CmGLTimerQuery.h"
+#include "CmGLOcclusionQuery.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -19,4 +20,12 @@ namespace BansheeEngine
 
 
 		return query;
 		return query;
 	}
 	}
+
+	OcclusionQueryPtr GLQueryManager::createOcclusionQuery(bool binary) const
+	{
+		OcclusionQueryPtr query = std::shared_ptr<GLOcclusionQuery>(cm_new<GLOcclusionQuery>(binary), &QueryManager::deleteOcclusionQuery, StdAlloc<GenAlloc>());
+		mOcclusionQueries.push_back(query.get());
+
+		return query;
+	}
 }
 }

+ 1 - 1
Notes.txt

@@ -25,7 +25,6 @@ Reminders:
   - Add Unified shader so I can easily switch between HLSL and GLSL shaders (they need same parameters usually, just different code)
   - Add Unified shader so I can easily switch between HLSL and GLSL shaders (they need same parameters usually, just different code)
     - Maybe just add support for Cg and force everyone to use that? - I'd like to be able to just switch out renderer in a single location and that everything keeps on working without 
     - Maybe just add support for Cg and force everyone to use that? - I'd like to be able to just switch out renderer in a single location and that everything keeps on working without 
 	  further modifications.
 	  further modifications.
-  - Port boost threads to std threads (CmThreadDefines.h)
   - Remove HardwarePixelBuffer (DX11 doesn't use it, and DX9 and OpenGL textures can be rewritten so they have its methods internally)
   - Remove HardwarePixelBuffer (DX11 doesn't use it, and DX9 and OpenGL textures can be rewritten so they have its methods internally)
   - Multihead device
   - Multihead device
   - Don't forget to check out Unity DX11 documentation on how to implement DX11 features (http://docs.unity3d.com/Documentation/Manual/DirectX11.html)
   - Don't forget to check out Unity DX11 documentation on how to implement DX11 features (http://docs.unity3d.com/Documentation/Manual/DirectX11.html)
@@ -61,6 +60,7 @@ Reminders:
 	  - It really helps when you get an error on a Component that hundreds of SceneObjects use
 	  - It really helps when you get an error on a Component that hundreds of SceneObjects use
 	- When displaying an error with a callstack, make each line of the callstack clickable where it opens the external editor
 	- When displaying an error with a callstack, make each line of the callstack clickable where it opens the external editor
   - std::function allocates memory but I have no got way of using custom allocators as I'd have to wrap std::bind and that seems non-trivial
   - std::function allocates memory but I have no got way of using custom allocators as I'd have to wrap std::bind and that seems non-trivial
+  - Add a TaskScheduler profiler that neatly shows time slices of each task and on which thread they are run on
 
 
 Potential optimizations:
 Potential optimizations:
  - bulkPixelConversion is EXTREMELY poorly unoptimized. Each pixel it calls a separate method that does redudant operations every pixel.
  - bulkPixelConversion is EXTREMELY poorly unoptimized. Each pixel it calls a separate method that does redudant operations every pixel.

+ 3 - 0
TODO.txt

@@ -119,6 +119,9 @@ Low priority TODO
     entire buffer. It would be better to handle this differently. Same thing happens in MeshHeap
     entire buffer. It would be better to handle this differently. Same thing happens in MeshHeap
  - OpenGL also supports texture views using glTextureView but so far I only use them in DX11
  - OpenGL also supports texture views using glTextureView but so far I only use them in DX11
  - I don't have a way to set Texture filtering or wrap modes, default ones are always set on initialization
  - I don't have a way to set Texture filtering or wrap modes, default ones are always set on initialization
+ - Module does need to be fixed for multi-threading. If it is created on one thread and used on another, a race condition could occurr. But do I use modules on two different threads?
+   - I will with Debug, and probably others
+   - Making the shutdown/destroy variables atomic should be enough
 ----------------------------------------------------------------------------------------------
 ----------------------------------------------------------------------------------------------
 Optional:
 Optional:
  - Need better handling for shader techniques. Some Materials are able to run on all renderers yet I can only specify one. This is problematic
  - Need better handling for shader techniques. Some Materials are able to run on all renderers yet I can only specify one. This is problematic

+ 0 - 35
TaskScheduler.txt

@@ -1,35 +0,0 @@
-TaskManager (or JobScheduler)
- - Ensure it only uses 6 threads. Two should be reserved for sim and core thread.
-    - Potentially a separate ThreadPool class?
- - Support for task dependencies
- - Support for task priorities
- - Callable from multiple threads
- - When task is queued a Task object is returned (can be copied)
-   - You may use that for chaining dependencies
-   - For waiting on a task
- - HOW DO I CHECK WHEN TASKS ARE COMPLETE?
-   - Check AsyncOp and use that same approach. In fact maybe use AsyncOp itself within the Task
-
- - Ability for threads to wait() until task is complete. And while waiting to complete tasks themselves.
-  - Only main threads can wait (core and sim threads)
-  - When they wait they will actually stop, and the task scheduler will start a new thread to run tasks in their place
-    - Once the task they are waiting for is done, the new thread is returned to thread pool
-  - When calling wait() and starting a new thread, first check if any active thread is being shut-down and if so, cancel the shutdown instead of creating a new thread
-
- - Tasks should have names (later for visualization and profiling purposes)
-
-
-ThreadPool
- - NEVER start threads manually. Only use ThreadPool.
- - This way I can initialize stack allocators and profiler threads just one for the started threads and don't have to worry about user forgetting how to do that.
-
-
-LATER - Profiler should be able to visualize tasks
-
-------------------
-
-Non-task-scheduler:
-
-Module does need to be fixed for multi-threading. If it is created on one thread and used on another, a race condition could occurr. But do I use modules on two different threads?
- - I will with Debug, and probably others
- - Making the shutdown/destroy variables atomic should be enough