Browse Source

DirectX 9 device reset works properly

Marko Pintera 11 years ago
parent
commit
e22d917c50

+ 1 - 1
BansheeEditor/Source/DbgEditorWidget2.cpp

@@ -36,7 +36,7 @@ namespace BansheeEngine
 		else
 		{
 			//gCoreAccessor().setFullscreen(window, *videoMode);
-			gCoreAccessor().setFullscreen(gApplication().getPrimaryWindow(), 1680, 1050, 60, 0);
+			gCoreAccessor().setFullscreen(gApplication().getPrimaryWindow(), 1920, 1200, 60, 0);
 		}
 
 		cm_dbg_fullscreen = !cm_dbg_fullscreen;

+ 1 - 1
BansheeEditorExec/BsEditorExec.cpp

@@ -11,7 +11,7 @@ int CALLBACK WinMain(
 	_In_  int nCmdShow
 	)
 {
-	EditorApplication::startUp(RenderSystemPlugin::OpenGL);
+	EditorApplication::startUp(RenderSystemPlugin::DX9);
 	EditorApplication::instance().runMainLoop();
 	EditorApplication::shutDown();
 

+ 35 - 1
CamelotD3D9Renderer/Include/CmD3D9EventQuery.h

@@ -1,6 +1,7 @@
 #pragma once
 
 #include "CmD3D9Prerequisites.h"
+#include "CmD3D9Resource.h"
 #include "CmEventQuery.h"
 
 namespace BansheeEngine
@@ -8,7 +9,7 @@ namespace BansheeEngine
 	/**
 	 * @copydoc EventQuery
 	 */
-	class CM_D3D9_EXPORT D3D9EventQuery : public EventQuery
+	class CM_D3D9_EXPORT D3D9EventQuery : public EventQuery, public D3D9Resource
 	{
 	public:
 		D3D9EventQuery();
@@ -24,7 +25,40 @@ namespace BansheeEngine
 		 */
 		virtual bool isReady() const;
 
+		/**
+		 * @copydoc	D3D9Resource::notifyOnDeviceCreate
+		 */
+		virtual void notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device);
+
+		/**
+		 * @copydoc	D3D9Resource::notifyOnDeviceDestroy
+		 */
+		virtual void notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device);
+
+		/**
+		 * @copydoc	D3D9Resource::notifyOnDeviceLost
+		 */
+		virtual void notifyOnDeviceLost(IDirect3DDevice9* d3d9Device);
+
+		/**
+		 * @copydoc	D3D9Resource::notifyOnDeviceReset
+		 */
+		virtual void notifyOnDeviceReset(IDirect3DDevice9* d3d9Device);
+
+	private:
+		/**
+		 * @brief	Creates the internal DX9 query.
+		 */
+		void createQuery();
+
+		/**
+		 * @brief	Releases the internal DX9 query.
+		 */
+		void releaseQuery();
+
 	private:
+		bool mQueryIssued;
 		IDirect3DQuery9* mQuery;
+		IDirect3DDevice9* mDevice;
 	};
 }

+ 12 - 4
CamelotD3D9Renderer/Include/CmD3D9IndexBuffer.h

@@ -26,16 +26,24 @@ namespace BansheeEngine
         /** See HardwareBuffer. */
 		void writeData(UINT32 offset, UINT32 length, const void* source, BufferWriteType writeFlags = BufferWriteType::Normal);
 
-		// Called immediately after the Direct3D device has been created.
+		/**
+		 * @copydoc	D3D9Resource::notifyOnDeviceCreate
+		 */
 		virtual void notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device);
 
-		// Called before the Direct3D device is going to be destroyed.
+		/**
+		 * @copydoc	D3D9Resource::notifyOnDeviceDestroy
+		 */
 		virtual void notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device);
 
-		// Called immediately after the Direct3D device has entered a lost state.
+		/**
+		 * @copydoc	D3D9Resource::notifyOnDeviceLost
+		 */
 		virtual void notifyOnDeviceLost(IDirect3DDevice9* d3d9Device);
 
-		// Called immediately after the Direct3D device has been reset
+		/**
+		 * @copydoc	D3D9Resource::notifyOnDeviceReset
+		 */
 		virtual void notifyOnDeviceReset(IDirect3DDevice9* d3d9Device);
 
 		// Create the actual index buffer.

+ 39 - 3
CamelotD3D9Renderer/Include/CmD3D9OcclusionQuery.h

@@ -1,6 +1,7 @@
 #pragma once
 
 #include "CmD3D9Prerequisites.h"
+#include "CmD3D9Resource.h"
 #include "CmOcclusionQuery.h"
 
 namespace BansheeEngine
@@ -8,7 +9,7 @@ namespace BansheeEngine
 	/**
 	* @copydoc OcclusionQuery
 	*/
-	class CM_D3D9_EXPORT D3D9OcclusionQuery : public OcclusionQuery
+	class CM_D3D9_EXPORT D3D9OcclusionQuery : public OcclusionQuery, public D3D9Resource
 	{
 	public:
 		D3D9OcclusionQuery(bool binary);
@@ -34,14 +35,49 @@ namespace BansheeEngine
 		*/
 		virtual UINT32 getNumFragments();
 
+		/**
+		* @copydoc	D3D9Resource::notifyOnDeviceCreate
+		*/
+		virtual void notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device);
+
+		/**
+		 * @copydoc	D3D9Resource::notifyOnDeviceDestroy
+		 */
+		virtual void notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device);
+
+		/**
+		 * @copydoc	D3D9Resource::notifyOnDeviceLost
+		 */
+		virtual void notifyOnDeviceLost(IDirect3DDevice9* d3d9Device);
+
+		/**
+		 * @copydoc	D3D9Resource::notifyOnDeviceReset
+		 */
+		virtual void notifyOnDeviceReset(IDirect3DDevice9* d3d9Device);
+
 	private:
 		friend class QueryManager;
 
+		/**
+		 * @brief	Creates the internal DX9 query.
+		 */
+		void createQuery();
+
+		/**
+		 * @brief	Releases the internal DX9 query.
+		 */
+		void releaseQuery();
+
+		/**
+		 * @brief	Resolves query results after it is ready.
+		 */
+		void finalize();
+	private:
+		IDirect3DDevice9* mDevice;
 		IDirect3DQuery9* mQuery;
+		bool mQueryIssued;
 		bool mFinalized;
 
 		UINT32 mNumFragments;
-
-		void finalize();
 	};
 }

+ 33 - 1
CamelotD3D9Renderer/Include/CmD3D9RenderTexture.h

@@ -1,12 +1,13 @@
 #pragma once
 
 #include "CmD3D9Prerequisites.h"
+#include "CmD3D9Resource.h"
 #include "CmRenderTexture.h"
 
 namespace BansheeEngine
 {
 	/// RenderTexture implementation for D3D9
-	class CM_D3D9_EXPORT D3D9RenderTexture : public RenderTexture
+	class CM_D3D9_EXPORT D3D9RenderTexture : public RenderTexture, public D3D9Resource
 	{
 	public:
 		virtual ~D3D9RenderTexture();
@@ -14,6 +15,26 @@ namespace BansheeEngine
 		bool requiresTextureFlipping() const { return false; }
 		virtual void getCustomAttribute(const String& name, void* pData) const;
 
+		/**
+		 * @copydoc	D3D9Resource::notifyOnDeviceCreate
+		 */
+		virtual void notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device);
+
+		/**
+		 * @copydoc	D3D9Resource::notifyOnDeviceDestroy
+		 */
+		virtual void notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device);
+
+		/**
+		 * @copydoc	D3D9Resource::notifyOnDeviceLost
+		 */
+		virtual void notifyOnDeviceLost(IDirect3DDevice9* d3d9Device);
+
+		/**
+		 * @copydoc	D3D9Resource::notifyOnDeviceReset
+		 */
+		virtual void notifyOnDeviceReset(IDirect3DDevice9* d3d9Device);
+
 	protected:
 		friend class D3D9TextureManager;
 
@@ -24,6 +45,17 @@ namespace BansheeEngine
 		 */
 		void initialize_internal();
 
+		/**
+		 * @brief	Initializes the internal color and depth surfaces.
+		 */
+		void initializeSurfaces();
+
+		/**
+		 * @brief	Releases the internal color and depth surfaces.
+		 */
+		void releaseSurfaces();
+
+	protected:
 		IDirect3DSurface9* mDX9ColorSurface;
 		IDirect3DSurface9* mDX9DepthStencilSurface;
 		bool mIsBindableToShader;

+ 1 - 7
CamelotD3D9Renderer/Include/CmD3D9RenderWindow.h

@@ -110,11 +110,6 @@ namespace BansheeEngine
 		 * @brief	Accessor for render surface.
 		 */
 		IDirect3DSurface9* _getRenderSurface() const;
-
-		/**
-		 * @brief	Indicate that fullscreen / windowed switching has finished.
-		 */
-		void _finishSwitchingFullscreen();
 	
 		/**
 		 * @brief	Returns true if this window use depth buffer.
@@ -152,8 +147,7 @@ namespace BansheeEngine
 		bool						mDeviceValid;			// Device was validation succeeded.
 		HWND						mHWnd;					// Win32 Window handle		
 		bool						mIsExternal;			// window not created by Ogre
-		bool						mClosed;				// Is this window destroyed.		
-		bool						mSwitchingFullscreen;	// Are we switching from fullscreen to windowed or vice versa		
+		bool						mClosed;				// Is this window destroyed.			
 		D3DMULTISAMPLE_TYPE			mFSAAType;				// AA type.
 		DWORD						mFSAAQuality;			// AA quality.
 		UINT						mDisplayFrequency;		// Display frequency.

+ 26 - 17
CamelotD3D9Renderer/Include/CmD3D9Resource.h

@@ -2,39 +2,48 @@
 
 #include "CmD3D9Prerequisites.h"
 
-namespace BansheeEngine {
-
-	/** Represents a Direct3D rendering resource.
-	Provide unified interface to
-	handle various device states.
-	*/
+namespace BansheeEngine 
+{
+	/**
+	 * @brief	Provides an interface for dealing with DX9 resources. Primarily
+	 *			notifying the resources of any changed states.
+	 */
 	class CM_D3D9_EXPORT D3D9Resource
 	{
-	// Interface.
 	public:
 		D3D9Resource();
 		virtual ~D3D9Resource();
 
-		// Called immediately after the Direct3D device has been created.
+		/**
+		 * @brief	Called immediately after the Direct3D device has been created.
+		 */
 		virtual void notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device) {}
 
-		// Called before the Direct3D device is going to be destroyed.
+		/**
+		 * @brief	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.
+		/**
+		 * @brief	Called immediately after the Direct3D device has entered a lost state.
+		 */
 		virtual void notifyOnDeviceLost(IDirect3DDevice9* d3d9Device) {}
 
-		// Called immediately after the Direct3D device has been reset.
-		// This is the place to create non-managed resources.
+		/**
+		 * @brief	Called immediately after the Direct3D device has been reset.
+		 */
 		virtual void notifyOnDeviceReset(IDirect3DDevice9* d3d9Device) {}
 
-		// Called when device state is changing. Access to any device should be locked.
-		// Relevant for multi thread application.
+		/**
+		 * @brief	Called when device state is changing. Access to any device should be locked.
+		 *			Relevant for multi thread application.
+		 */
 		static void lockDeviceAccess();
 
-		// Called when device state change completed. Access to any device is allowed.
-		// Relevant for multi thread application.
+		/**
+		 * @brief	Called when device state change completed. Access to any device is allowed.
+		 *			Relevant for multi thread application.
+		 */
 		static void unlockDeviceAccess();
 
 	protected:

+ 13 - 5
CamelotD3D9Renderer/Include/CmD3D9Texture.h

@@ -69,17 +69,25 @@ namespace BansheeEngine
 		*/
 		PixelBufferPtr getBuffer(UINT32 face, UINT32 mipmap);
 
-		// Called immediately after the Direct3D device has been created.
+		/**
+		 * @copydoc	D3D9Resource::notifyOnDeviceCreate
+		 */
 		virtual void notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device);
 
-		// Called before the Direct3D device is going to be destroyed.
+		/**
+		 * @copydoc	D3D9Resource::notifyOnDeviceDestroy
+		 */
 		virtual void notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device);
 
-		// Called immediately after the Direct3D device has entered a lost state.
+		/**
+		 * @copydoc	D3D9Resource::notifyOnDeviceLost
+		 */
 		virtual void notifyOnDeviceLost(IDirect3DDevice9* d3d9Device);
 
-		// Called immediately after the Direct3D device has been reset
-		virtual void notifyOnDeviceReset(IDirect3DDevice9* d3d9Device);	
+		/**
+		 * @copydoc	D3D9Resource::notifyOnDeviceReset
+		 */
+		virtual void notifyOnDeviceReset(IDirect3DDevice9* d3d9Device);
 
 	protected:	
 		friend class D3D9TextureManager;

+ 45 - 3
CamelotD3D9Renderer/Include/CmD3D9TimerQuery.h

@@ -1,6 +1,7 @@
 #pragma once
 
 #include "CmD3D9Prerequisites.h"
+#include "CmD3D9Resource.h"
 #include "CmTimerQuery.h"
 
 namespace BansheeEngine
@@ -8,7 +9,7 @@ namespace BansheeEngine
 	/**
 	 * @copydoc TimerQuery
 	 */
-	class CM_D3D9_EXPORT D3D9TimerQuery : public TimerQuery
+	class CM_D3D9_EXPORT D3D9TimerQuery : public TimerQuery, public D3D9Resource
 	{
 	public:
 		D3D9TimerQuery();
@@ -34,15 +35,56 @@ namespace BansheeEngine
 		 */
 		virtual float getTimeMs();
 
+		/**
+		 * @copydoc	D3D9Resource::notifyOnDeviceCreate
+		 */
+		virtual void notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device);
+
+		/**
+		 * @copydoc	D3D9Resource::notifyOnDeviceDestroy
+		 */
+		virtual void notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device);
+
+		/**
+		 * @copydoc	D3D9Resource::notifyOnDeviceLost
+		 */
+		virtual void notifyOnDeviceLost(IDirect3DDevice9* d3d9Device);
+
+		/**
+		 * @copydoc	D3D9Resource::notifyOnDeviceReset
+		 */
+		virtual void notifyOnDeviceReset(IDirect3DDevice9* d3d9Device);
+
+	private:
+		/**
+		 * @brief	Resolve timing information after the query has finished.
+		 */
+		void finalize();
+
+		/**
+		 * @brief	Creates the internal DX9 query.
+		 */
+		void createQuery();
+
+		/**
+		 * @brief	Releases the internal DX9 query.
+		 */
+		void releaseQuery();
+
+		/**
+		 * @brief	Checks if the internal query object is valid.
+		 */
+		bool isQueryValid() const;
+
 	private:
 		bool mFinalized;
+		bool mQueryIssued;
 		float mTimeDelta;
 
+		IDirect3DDevice9* mDevice;
 		IDirect3DQuery9* mBeginQuery;
 		IDirect3DQuery9* mEndQuery;
 		IDirect3DQuery9* mDisjointQuery;
 		IDirect3DQuery9* mFreqQuery;
-
-		void finalize();
 	};
 }

+ 12 - 4
CamelotD3D9Renderer/Include/CmD3D9VertexBuffer.h

@@ -26,16 +26,24 @@ namespace BansheeEngine
         /** See HardwareBuffer. */
         void writeData(UINT32 offset, UINT32 length, const void* source, BufferWriteType writeFlags = BufferWriteType::Normal);
 	
-		// Called immediately after the Direct3D device has been created.
+		/**
+		 * @copydoc	D3D9Resource::notifyOnDeviceCreate
+		 */
 		virtual void notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device);
 
-		// Called before the Direct3D device is going to be destroyed.
+		/**
+		 * @copydoc	D3D9Resource::notifyOnDeviceDestroy
+		 */
 		virtual void notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device);
 
-		// Called immediately after the Direct3D device has entered a lost state.
+		/**
+		 * @copydoc	D3D9Resource::notifyOnDeviceLost
+		 */
 		virtual void notifyOnDeviceLost(IDirect3DDevice9* d3d9Device);
 
-		// Called immediately after the Direct3D device has been reset
+		/**
+		 * @copydoc	D3D9Resource::notifyOnDeviceReset
+		 */
 		virtual void notifyOnDeviceReset(IDirect3DDevice9* d3d9Device);
 
 		// Create the actual vertex buffer.

+ 48 - 10
CamelotD3D9Renderer/Source/CmD3D9EventQuery.cpp

@@ -1,39 +1,77 @@
 #include "CmD3D9EventQuery.h"
 #include "CmD3D9RenderSystem.h"
+#include "CmD3D9ResourceManager.h"
 #include "CmD3D9Device.h"
 #include "CmException.h"
 
 namespace BansheeEngine
 {
 	D3D9EventQuery::D3D9EventQuery()
-		:mQuery(nullptr)
+		:mQuery(nullptr), mDevice(nullptr), mQueryIssued(false)
 	{
-		IDirect3DDevice9* device = D3D9RenderSystem::getActiveD3D9Device();
-		HRESULT hr = device->CreateQuery(D3DQUERYTYPE_EVENT, &mQuery);
+		createQuery();
+	}
+
+	D3D9EventQuery::~D3D9EventQuery()
+	{
+		releaseQuery();
+	}
+
+	void D3D9EventQuery::createQuery()
+	{
+		mDevice = D3D9RenderSystem::getActiveD3D9Device();
 
-		if(hr != S_OK)
+		HRESULT hr = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &mQuery);
+		if (hr != S_OK)
 		{
 			CM_EXCEPT(RenderingAPIException, "Failed to create an Event query.");
 		}
 	}
 
-	D3D9EventQuery::~D3D9EventQuery()
+	void D3D9EventQuery::releaseQuery()
 	{
-		if(mQuery != nullptr)
-		{
-			mQuery->Release();
-		}
+		SAFE_RELEASE(mQuery);
 	}
 
 	void D3D9EventQuery::begin()
 	{
-		mQuery->Issue(D3DISSUE_END);
+		if (mQuery != nullptr)
+			mQuery->Issue(D3DISSUE_END);
+
 		setActive(true);
+		mQueryIssued = true;
 	}
 
 	bool D3D9EventQuery::isReady() const
 	{
+		if (mQuery == nullptr) // Possibly device reset, in which case query is done
+			return mQueryIssued;
+
 		BOOL queryData;
 		return mQuery->GetData(&queryData, sizeof(BOOL), 0) == S_OK;
 	}
+
+	void D3D9EventQuery::notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device)
+	{
+		if (d3d9Device == mDevice)
+			createQuery();
+	}
+
+	void D3D9EventQuery::notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device)
+	{
+		if (d3d9Device == mDevice)
+			releaseQuery();
+	}
+
+	void D3D9EventQuery::notifyOnDeviceLost(IDirect3DDevice9* d3d9Device)
+	{
+		if (d3d9Device == mDevice)
+			releaseQuery();
+	}
+
+	void D3D9EventQuery::notifyOnDeviceReset(IDirect3DDevice9* d3d9Device)
+	{
+		if (d3d9Device == mDevice)
+			createQuery();
+	}
 }

+ 57 - 8
CamelotD3D9Renderer/Source/CmD3D9OcclusionQuery.cpp

@@ -5,38 +5,57 @@
 namespace BansheeEngine
 {
 	D3D9OcclusionQuery::D3D9OcclusionQuery(bool binary)
-		:OcclusionQuery(binary), mQuery(nullptr), mNumFragments(0), mFinalized(false)
+		:OcclusionQuery(binary), mQuery(nullptr), mNumFragments(0), 
+		mFinalized(false), mDevice(nullptr), mQueryIssued(false)
 	{
-		IDirect3DDevice9* device = D3D9RenderSystem::getActiveD3D9Device();
+		createQuery();
+	}
+
+	D3D9OcclusionQuery::~D3D9OcclusionQuery()
+	{
+		releaseQuery();
+	}
+
+	void D3D9OcclusionQuery::createQuery()
+	{
+		mDevice = D3D9RenderSystem::getActiveD3D9Device();
 
-		HRESULT hr = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &mQuery);
+		HRESULT hr = mDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &mQuery);
 		if (hr != S_OK)
 		{
 			CM_EXCEPT(RenderingAPIException, "Failed to create an occlusion query.");
 		}
 	}
 
-	D3D9OcclusionQuery::~D3D9OcclusionQuery()
+	void D3D9OcclusionQuery::releaseQuery()
 	{
-		if (mQuery != nullptr)
-			mQuery->Release();
+		SAFE_RELEASE(mQuery);
 	}
 
 	void D3D9OcclusionQuery::begin()
 	{
-		mQuery->Issue(D3DISSUE_BEGIN);
+		if (mQuery != nullptr)
+			mQuery->Issue(D3DISSUE_BEGIN);
 
 		mNumFragments = 0;
+		mQueryIssued = false;
 		setActive(true);
 	}
 
 	void D3D9OcclusionQuery::end()
 	{
-		mQuery->Issue(D3DISSUE_END);
+		if (mQuery != nullptr)
+			mQuery->Issue(D3DISSUE_END);
+
+		mQueryIssued = true;
+		mFinalized = false;
 	}
 
 	bool D3D9OcclusionQuery::isReady() const
 	{
+		if (mQuery == nullptr)
+			return mQueryIssued; // If we lost the query, return as ready if it was ever issued
+
 		BOOL queryData;
 		return mQuery->GetData(&queryData, sizeof(BOOL), 0) == S_OK;
 	}
@@ -55,9 +74,39 @@ namespace BansheeEngine
 	{
 		mFinalized = true;
 
+		if (mQuery == nullptr)
+		{
+			mNumFragments = 0;
+			return;
+		}
+
 		DWORD numFragments;
 		mQuery->GetData(&numFragments, sizeof(DWORD), 0);
 
 		mNumFragments = (UINT32)numFragments;
 	}
+
+	void D3D9OcclusionQuery::notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device)
+	{
+		if (d3d9Device == mDevice)
+			createQuery();
+	}
+
+	void D3D9OcclusionQuery::notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device)
+	{
+		if (d3d9Device == mDevice)
+			releaseQuery();
+	}
+
+	void D3D9OcclusionQuery::notifyOnDeviceLost(IDirect3DDevice9* d3d9Device)
+	{
+		if (d3d9Device == mDevice)
+			releaseQuery();
+	}
+
+	void D3D9OcclusionQuery::notifyOnDeviceReset(IDirect3DDevice9* d3d9Device)
+	{
+		if (d3d9Device == mDevice)
+			createQuery();
+	}
 }

+ 8 - 7
CamelotD3D9Renderer/Source/CmD3D9RenderSystem.cpp

@@ -555,7 +555,8 @@ namespace BansheeEngine
 		setTextureFiltering(unit, FT_MIP, state->getTextureFiltering(FT_MIP));
 
 		// Set texture layer filtering
-		setTextureAnisotropy(unit, state->getTextureAnisotropy());
+		if (state->getTextureAnisotropy() > 0)
+			setTextureAnisotropy(unit, state->getTextureAnisotropy());
 
 		// Set mipmap biasing
 		setTextureMipmapBias(unit, state->getTextureMipmapBias());
@@ -1401,14 +1402,14 @@ namespace BansheeEngine
 		if(!clearEntireTarget)
 		{
 			D3DRECT clearD3DRect;
-			clearD3DRect.x1 = clearRect.x;
-			clearD3DRect.x2 = clearD3DRect.x1 + clearRect.width;
+			clearD3DRect.x1 = (LONG)Math::clamp(clearRect.x, 0, (INT32)mActiveRenderTarget->getWidth() - 1);
+			clearD3DRect.x2 = (LONG)Math::clamp((INT32)clearD3DRect.x1 + clearRect.width, 0, (INT32)mActiveRenderTarget->getWidth() - 1);
 
-			clearD3DRect.y1 = clearRect.y;
-			clearD3DRect.y2 = clearD3DRect.y1 + clearRect.height;
+			clearD3DRect.y1 = (LONG)Math::clamp(clearRect.y, 0, (INT32)mActiveRenderTarget->getHeight() - 1);
+			clearD3DRect.y2 = (LONG)Math::clamp((INT32)clearD3DRect.y1 + clearRect.height, 0, (INT32)mActiveRenderTarget->getHeight() - 1);
 
 			HRESULT hr;
-			if(FAILED( hr = getActiveD3D9Device()->Clear(1, &clearD3DRect, flags, color.getAsBGRA(), depth, stencil)))
+			if(FAILED(hr = getActiveD3D9Device()->Clear(1, &clearD3DRect, flags, color.getAsBGRA(), depth, stencil)))
 			{
 				String msg = DXGetErrorDescription(hr);
 				CM_EXCEPT(RenderingAPIException, "Error clearing frame buffer : " + msg);
@@ -1417,7 +1418,7 @@ namespace BansheeEngine
 		else
 		{
 			HRESULT hr;
-			if(FAILED( hr = getActiveD3D9Device()->Clear(0, nullptr, flags, color.getAsBGRA(), depth, stencil)))
+			if(FAILED(hr = getActiveD3D9Device()->Clear(0, nullptr, flags, color.getAsBGRA(), depth, stencil)))
 			{
 				String msg = DXGetErrorDescription(hr);
 				CM_EXCEPT(RenderingAPIException, "Error clearing frame buffer : " + msg);

+ 42 - 10
CamelotD3D9Renderer/Source/CmD3D9RenderTexture.cpp

@@ -17,6 +17,33 @@ namespace BansheeEngine
 
 	}
 
+	void D3D9RenderTexture::initialize_internal()
+	{
+		initializeSurfaces();
+
+		RenderTexture::initialize_internal();
+	}
+
+	void D3D9RenderTexture::initializeSurfaces()
+	{
+		D3D9Texture* d3d9texture = static_cast<D3D9Texture*>(mColorSurface->getTexture().get());
+		D3D9PixelBuffer* pixelBuffer = static_cast<D3D9PixelBuffer*>(
+			d3d9texture->getBuffer(mColorSurface->getFirstArraySlice(), mColorSurface->getMostDetailedMip()).get());
+		mDX9ColorSurface = pixelBuffer->getSurface(D3D9RenderSystem::getActiveD3D9Device());
+
+		D3D9Texture* d3d9DepthStencil = static_cast<D3D9Texture*>(mDepthStencilSurface->getTexture().get());
+		D3D9PixelBuffer* depthStencilBuffer = static_cast<D3D9PixelBuffer*>(
+			d3d9DepthStencil->getBuffer(mDepthStencilSurface->getFirstArraySlice(), mDepthStencilSurface->getMostDetailedMip()).get());
+		mDX9DepthStencilSurface = depthStencilBuffer->getSurface(D3D9RenderSystem::getActiveD3D9Device());
+	}
+
+	void D3D9RenderTexture::releaseSurfaces()
+	{
+		// All actual releasing happens in the color and depth textures.
+		mDX9ColorSurface = nullptr;
+		mDX9DepthStencilSurface = nullptr;
+	}
+
 	void D3D9RenderTexture::getCustomAttribute(const String& name, void* pData) const
 	{
 		if(name == "DDBACKBUFFER")
@@ -39,18 +66,23 @@ namespace BansheeEngine
 		}
 	}
 
-	void D3D9RenderTexture::initialize_internal()
+	void D3D9RenderTexture::notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device)
 	{
-		D3D9Texture* d3d9texture = static_cast<D3D9Texture*>(mColorSurface->getTexture().get());
-		D3D9PixelBuffer* pixelBuffer = static_cast<D3D9PixelBuffer*>(
-			d3d9texture->getBuffer(mColorSurface->getFirstArraySlice(), mColorSurface->getMostDetailedMip()).get());
-		mDX9ColorSurface = pixelBuffer->getSurface(D3D9RenderSystem::getActiveD3D9Device());
+		initializeSurfaces();
+	}
 
-		D3D9Texture* d3d9DepthStencil = static_cast<D3D9Texture*>(mDepthStencilSurface->getTexture().get());
-		D3D9PixelBuffer* depthStencilBuffer = static_cast<D3D9PixelBuffer*>(
-			d3d9DepthStencil->getBuffer(mDepthStencilSurface->getFirstArraySlice(), mDepthStencilSurface->getMostDetailedMip()).get());
-		mDX9DepthStencilSurface = depthStencilBuffer->getSurface(D3D9RenderSystem::getActiveD3D9Device());
+	void D3D9RenderTexture::notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device)
+	{
+		releaseSurfaces();
+	}
 
-		RenderTexture::initialize_internal();
+	void D3D9RenderTexture::notifyOnDeviceLost(IDirect3DDevice9* d3d9Device)
+	{
+		releaseSurfaces();
+	}
+
+	void D3D9RenderTexture::notifyOnDeviceReset(IDirect3DDevice9* d3d9Device)
+	{
+		initializeSurfaces();
 	}
 }

+ 4 - 51
CamelotD3D9Renderer/Source/CmD3D9RenderWindow.cpp

@@ -21,7 +21,6 @@ namespace BansheeEngine
 		mHWnd = 0;
 		mActive = false;		
 		mClosed = false;
-		mSwitchingFullscreen = false;
 		mDisplayFrequency = 0;
 		mDeviceValid = false;
 	}
@@ -276,7 +275,6 @@ namespace BansheeEngine
 		mDisplayFrequency = Math::roundToInt(refreshRate);
 
 		mIsFullScreen = true;
-		mSwitchingFullscreen = true;
 
 		HMONITOR hMonitor = outputInfo.getMonitorHandle();
 		MONITORINFO monitorInfo;
@@ -290,17 +288,18 @@ namespace BansheeEngine
 
 		if (oldFullscreen) // Was previously fullscreen, just changing the resolution
 		{
-			SetWindowPos(mHWnd, HWND_TOPMOST, mLeft, mTop, mWidth, mHeight, SWP_NOACTIVATE);
+			//SetWindowPos(mHWnd, HWND_TOPMOST, mLeft, mTop, mWidth, mHeight, SWP_NOACTIVATE);
 		}
 		else
 		{
-			SetWindowPos(mHWnd, HWND_TOPMOST, mLeft, mTop, mWidth, mHeight, SWP_NOACTIVATE);
+			//SetWindowPos(mHWnd, HWND_TOPMOST, mLeft, mTop, mWidth, mHeight, SWP_NOACTIVATE);
 			SetWindowLong(mHWnd, GWL_STYLE, mStyle);
 			SetWindowPos(mHWnd, 0, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
 		}
 
 		// Invalidate device, which resets it
 		mDevice->invalidate(this);
+		mDevice->acquire();
 	}
 
 	void D3D9RenderWindow::setFullscreen(const VideoMode& mode, UINT32 refreshRateIdx)
@@ -329,7 +328,6 @@ namespace BansheeEngine
 			return;
 
 		mIsFullScreen = false;
-		mSwitchingFullscreen = true;
 
 		mStyle = WS_VISIBLE | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW;
 
@@ -341,6 +339,7 @@ namespace BansheeEngine
 			SWP_DRAWFRAME | SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOACTIVATE);
 
 		mDevice->invalidate(this);
+		mDevice->acquire();
 	}
 
 	void D3D9RenderWindow::setHidden(bool hidden)
@@ -526,52 +525,6 @@ namespace BansheeEngine
 			*winHeight = maxH;
 
 	}
-
-	void D3D9RenderWindow::_finishSwitchingFullscreen()
-	{		
-		if(mIsFullScreen)
-		{
-			// Need to reset the region on the window sometimes, when the 
-			// windowed mode was constrained by desktop 
-			HRGN hRgn = CreateRectRgn(0,0,mWidth, mHeight);
-			SetWindowRgn(mHWnd, hRgn, FALSE);
-		}
-		else
-		{
-			// When switching back to windowed mode, need to reset window size 
-			// after device has been restored
-			// We may have had a resize event which polluted our desired sizes
-			unsigned int winWidth, winHeight;
-			_adjustWindow(mDesiredWidth, mDesiredHeight, mStyle, &winWidth, &winHeight);
-
-			// deal with centreing when switching down to smaller resolution
-
-			HMONITOR hMonitor = MonitorFromWindow(mHWnd, MONITOR_DEFAULTTONEAREST);
-			MONITORINFO monitorInfo;
-			memset(&monitorInfo, 0, sizeof(MONITORINFO));
-			monitorInfo.cbSize = sizeof(MONITORINFO);
-			GetMonitorInfo(hMonitor, &monitorInfo);
-
-			LONG screenw = monitorInfo.rcWork.right  - monitorInfo.rcWork.left;
-			LONG screenh = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;
-
-
-			int left = screenw > int(winWidth) ? ((screenw - int(winWidth)) / 2) : 0;
-			int top = screenh > int(winHeight) ? ((screenh - int(winHeight)) / 2) : 0;
-			SetWindowPos(mHWnd, HWND_NOTOPMOST, left, top, winWidth, winHeight,
-				SWP_DRAWFRAME | SWP_FRAMECHANGED | SWP_NOACTIVATE);
-
-			if (mWidth != mDesiredWidth ||
-				mHeight != mDesiredHeight)
-			{
-				mWidth = mDesiredWidth;
-				mHeight = mDesiredHeight;
-
-				// TODO - Notify viewports of resize		
-			}
-		}
-		mSwitchingFullscreen = false;
-	}
 	
 	void D3D9RenderWindow::_buildPresentParameters(D3DPRESENT_PARAMETERS* presentParams) const
 	{		

+ 83 - 27
CamelotD3D9Renderer/Source/CmD3D9TimerQuery.cpp

@@ -5,67 +5,91 @@
 namespace BansheeEngine
 {
 	D3D9TimerQuery::D3D9TimerQuery()
-		:mFinalized(false), mBeginQuery(nullptr), mFreqQuery(nullptr),
-		mEndQuery(nullptr), mDisjointQuery(nullptr), mTimeDelta(0.0f)
+		:mFinalized(false), mBeginQuery(nullptr), mFreqQuery(nullptr), mQueryIssued(false),
+		mEndQuery(nullptr), mDisjointQuery(nullptr), mTimeDelta(0.0f), mDevice(nullptr)
 	{
-		IDirect3DDevice9* device = D3D9RenderSystem::getActiveD3D9Device();
+		createQuery();
+	}
+
+	D3D9TimerQuery::~D3D9TimerQuery()
+	{
+		releaseQuery();
+	}
 
-		HRESULT hr = device->CreateQuery(D3DQUERYTYPE_TIMESTAMPDISJOINT, &mDisjointQuery);
-		if(hr != S_OK)
+	void D3D9TimerQuery::createQuery()
+	{
+		mDevice = D3D9RenderSystem::getActiveD3D9Device();
+
+		HRESULT hr = mDevice->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)
+		hr = mDevice->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)
+		hr = mDevice->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)
+		hr = mDevice->CreateQuery(D3DQUERYTYPE_TIMESTAMP, &mEndQuery);
+		if (hr != S_OK)
 		{
 			CM_EXCEPT(RenderingAPIException, "Failed to create a timer query.");
 		}
 	}
 
-	D3D9TimerQuery::~D3D9TimerQuery()
+	void D3D9TimerQuery::releaseQuery()
 	{
-		if(mBeginQuery != nullptr)
-			mBeginQuery->Release();
-
-		if(mEndQuery != nullptr)
-			mEndQuery->Release();
-
-		if(mDisjointQuery != nullptr)
-			mDisjointQuery->Release();
+		SAFE_RELEASE(mBeginQuery);
+		SAFE_RELEASE(mEndQuery);
+		SAFE_RELEASE(mDisjointQuery);
+		SAFE_RELEASE(mFreqQuery);
+	}
 
-		if(mFreqQuery != nullptr)
-			mFreqQuery->Release();
+	bool D3D9TimerQuery::isQueryValid() const
+	{
+		return mDisjointQuery != nullptr && mBeginQuery != nullptr && 
+			mEndQuery != nullptr && mFreqQuery != nullptr;
 	}
 
 	void D3D9TimerQuery::begin()
 	{
-		mDisjointQuery->Issue(D3DISSUE_BEGIN);
-		mFreqQuery->Issue(D3DISSUE_END);
-		mBeginQuery->Issue(D3DISSUE_END);
+		mQueryIssued = false;
+
+		if (isQueryValid())
+		{
+			mDisjointQuery->Issue(D3DISSUE_BEGIN);
+			mFreqQuery->Issue(D3DISSUE_END);
+			mBeginQuery->Issue(D3DISSUE_END);
+		}
+
 		setActive(true);
 	}
 
 	void D3D9TimerQuery::end()
 	{
-		mEndQuery->Issue(D3DISSUE_END);
-		mDisjointQuery->Issue(D3DISSUE_END);
+		if (isQueryValid())
+		{
+			mEndQuery->Issue(D3DISSUE_END);
+			mDisjointQuery->Issue(D3DISSUE_END);
+		}
+
+		mQueryIssued = true;
+		mFinalized = false;
 	}
 
 	bool D3D9TimerQuery::isReady() const
 	{
+		if (!isQueryValid()) // Possibly device reset, in which case query is considered done if issued
+			return mQueryIssued;
+
 		BOOL queryData;
 		return mDisjointQuery->GetData(&queryData, sizeof(BOOL), 0) == S_OK;
 	}
@@ -82,6 +106,14 @@ namespace BansheeEngine
 
 	void D3D9TimerQuery::finalize()
 	{
+		mFinalized = true;
+
+		if (!isQueryValid())
+		{
+			mTimeDelta = 0.0f;
+			return;
+		}
+
 		BOOL disjoint;
 		mDisjointQuery->GetData(&disjoint, sizeof(BOOL), 0);
 
@@ -102,4 +134,28 @@ namespace BansheeEngine
 			LOGWRN("Unrealiable GPU timer query detected.");
 		}
 	}
+
+	void D3D9TimerQuery::notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device)
+	{
+		if (d3d9Device == mDevice)
+			createQuery();
+	}
+
+	void D3D9TimerQuery::notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device)
+	{
+		if (d3d9Device == mDevice)
+			releaseQuery();
+	}
+
+	void D3D9TimerQuery::notifyOnDeviceLost(IDirect3DDevice9* d3d9Device)
+	{
+		if (d3d9Device == mDevice)
+			releaseQuery();
+	}
+
+	void D3D9TimerQuery::notifyOnDeviceReset(IDirect3DDevice9* d3d9Device)
+	{
+		if (d3d9Device == mDevice)
+			createQuery();
+	}
 }

+ 11 - 10
Polish.txt

@@ -15,18 +15,8 @@ Finish GPUProfiler:
 
  Fullscreen stuff:
 
- In DX9 RenderWindow delete _finishSwitchingFullscreen method if possible after I test fullscreen switching
- Update OpenGL render window set fullscreen methods.
-
-Test if it all works. Especially going fullscreen on another monitor.
 When initializing a render window I don't have an option to use exact refresh rate (i.e. in RENDER_WINDOW_DESC)
 
-ChangeDisplaySettingEx - For actually changing resolution and refresh rate
- - http://msdn.microsoft.com/en-us/library/windows/desktop/dd183413(v=vs.85).aspx
-
- Add ability to change FSAA on RenderWindow.
-  - Maybe later. OpenGL requires window to be re-created for it to change I think. As SetPixelFormat is allowed to be called just once per window
-
 Add a better way of specifying FSAA (and don't call it FSAA because it's multisampling)
  - fsaaHint is useless in most cases. Add an Enum instead.
 
@@ -34,6 +24,17 @@ I should be able to specify resolution when going to windowed mode
  - Maybe just store the windowed and fullscreen resolutions separately and restore automatically?
 
 OpenGL going back from windowed mode doesn't restore window style properly.
+OpenGL doesn't list windows in the same order as DirectX
+
+DirectX 9 still crashes when going to fullscreen (presumably only when using retail DX9 runtime)
+Switching from higher to lower resoltuion in DX9 causes an issue where viewport is larger than the render target. 
+Test DirectX 9 full-screen on another monitor
+In DX9 render window I have disabled top most style.
+  - If needed re-enable it, if not remove it from OpenGL as well as I think it disables alt+tab
+
+LATER:
+ Add ability to change FSAA on RenderWindow.
+  - Maybe later. OpenGL requires window to be re-created for it to change I think. As SetPixelFormat is allowed to be called just once per window
 
  -----------------------------