Explorar o código

Various fixes to get shutdown work properly
Potential fixes for mouse input problems

Marko Pintera %!s(int64=11) %!d(string=hai) anos
pai
achega
a9bf1fec5f

+ 1 - 0
BansheeCore/Include/BsCoreApplication.h

@@ -98,6 +98,7 @@ namespace BansheeEngine
 		RenderWindowPtr mPrimaryWindow;
 
 		DynLib* mSceneManagerPlugin;
+		DynLib* mRendererPlugin;
 
 		bool mIsFrameRenderingFinished;
 		BS_MUTEX(mFrameRenderingFinishedMutex);

+ 2 - 0
BansheeCore/Include/BsRendererManager.h

@@ -15,6 +15,8 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT RendererManager : public Module<RendererManager>
 	{
 	public:
+		~RendererManager();
+
 		/**
 		 * @brief	Attempts to find a renderer with the specified name and makes it active.
 		 * 			Exception is thrown if renderer with the specified name doesn't exist.

+ 2 - 0
BansheeCore/Include/BsResourceHandle.h

@@ -27,6 +27,8 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT ResourceHandleBase : public IReflectable
 	{
 	public:
+		virtual ~ResourceHandleBase();
+
 		/**
 		 * @brief	Checks if the resource is loaded. Until resource is loaded this handle
 		 *			is invalid and you may not get the internal resource from it.

+ 12 - 3
BansheeCore/Source/BsCoreApplication.cpp

@@ -49,7 +49,8 @@
 namespace BansheeEngine
 {
 	CoreApplication::CoreApplication(START_UP_DESC& desc)
-		:mPrimaryWindow(nullptr), mIsFrameRenderingFinished(true), mRunMainLoop(false), mSceneManagerPlugin(nullptr)
+		:mPrimaryWindow(nullptr), mIsFrameRenderingFinished(true), mRunMainLoop(false), 
+		mSceneManagerPlugin(nullptr), mRendererPlugin(nullptr)
 	{
 		UINT32 numWorkerThreads = BS_THREAD_HARDWARE_CONCURRENCY - 1; // Number of cores while excluding current thread.
 
@@ -79,7 +80,7 @@ namespace BansheeEngine
 		Input::startUp();
 		RendererManager::startUp();
 
-		loadPlugin(desc.renderer);
+		loadPlugin(desc.renderer, &mRendererPlugin);
 		loadPlugin(desc.sceneManager, &mSceneManagerPlugin);
 
 		RendererManager::instance().setActive(desc.renderer);
@@ -109,14 +110,22 @@ namespace BansheeEngine
 		ProfilerGPU::shutDown();
 
 		unloadPlugin(mSceneManagerPlugin);
-
+		
 		RendererManager::shutDown();
 		RenderSystemManager::shutDown();
+		unloadPlugin(mRendererPlugin);
+
 		Input::shutDown();
 
 		GpuProgramManager::shutDown();
 		Resources::shutDown();
 		GameObjectManager::shutDown();
+
+		// All CoreObject related modules should be shut down now. They have likely queued CoreObjects for destruction, so
+		// we need to wait for those objects to get destroyed before continuing.
+		gCoreThread().update();
+		gCoreThread().submitAccessors(true);
+
 		CoreObjectManager::shutDown(); // Must shut down before DynLibManager to ensure all objects are destroyed before unloading their libraries
 		DynLibManager::shutDown();
 		Time::shutDown();

+ 1 - 1
BansheeCore/Source/BsCoreObjectManager.cpp

@@ -8,7 +8,7 @@ namespace BansheeEngine
 		:mNextAvailableID(1)
 	{
 
-	}
+	} 
 
 	CoreObjectManager::~CoreObjectManager()
 	{

+ 1 - 1
BansheeCore/Source/BsMaterial.cpp

@@ -23,7 +23,7 @@ namespace BansheeEngine
 
 	Material::~Material()
 	{
-		
+
 	}
 
 	void Material::setShader(ShaderPtr shader)

+ 2 - 0
BansheeCore/Source/BsMeshHeap.cpp

@@ -47,6 +47,8 @@ namespace BansheeEngine
 
 		growVertexBuffer(mNumVertices);
 		growIndexBuffer(mNumIndices);
+
+		CoreObject::initialize_internal();
 	}
 
 	void MeshHeap::destroy_internal()

+ 2 - 2
BansheeCore/Source/BsPass.cpp

@@ -20,7 +20,7 @@ namespace BansheeEngine
 
     Pass::~Pass()
     {
-	
+
     }
 
     Pass& Pass::operator=(const Pass& oth)
@@ -41,7 +41,7 @@ namespace BansheeEngine
 		return *this;
     }
 
-    bool Pass::isTransparent(void) const
+    bool Pass::isTransparent() const
     {
 		bool transparent = false;
 

+ 6 - 0
BansheeCore/Source/BsRendererManager.cpp

@@ -4,6 +4,12 @@
 
 namespace BansheeEngine
 {
+	RendererManager::~RendererManager()
+	{
+		if (mActiveRenderer != nullptr)
+			mActiveRenderer->_onDeactivated();
+	}
+
 	void RendererManager::setActive(const String& name)
 	{
 		for(auto iter = mAvailableFactories.begin(); iter != mAvailableFactories.end(); ++iter)

+ 5 - 0
BansheeCore/Source/BsResourceHandle.cpp

@@ -14,6 +14,11 @@ namespace BansheeEngine
 		mData = nullptr;
 	}
 
+	ResourceHandleBase::~ResourceHandleBase() 
+	{ 
+
+	}
+
 	bool ResourceHandleBase::isLoaded() const 
 	{ 
 		return (mData != nullptr && mData->mIsCreated && mData->mPtr != nullptr); 

+ 1 - 1
BansheeD3D11RenderSystem/Source/BsD3D11DepthStencilState.cpp

@@ -12,7 +12,7 @@ namespace BansheeEngine
 
 	D3D11DepthStencilState::~D3D11DepthStencilState()
 	{
-		
+
 	}
 
 	void D3D11DepthStencilState::initialize_internal()

+ 2 - 0
BansheeEngine/Include/BsRenderableHandler.h

@@ -19,6 +19,8 @@ namespace BansheeEngine
 	class BS_EXPORT RenderableHandler
 	{
 	public:
+		virtual ~RenderableHandler() {}
+
 		/**
 		 * @brief	Initializes the specified renderable element, making it ready
 		 *			to be used. Caller must ensure the renderable element actually

+ 7 - 0
BansheeOISInput/Include/BsInputHandlerOIS.h

@@ -144,6 +144,12 @@ namespace BansheeEngine
 		 */
 		static const float MOUSE_MAX;
 
+		/**
+		 * @brief	Number of seconds the mouse needs to reach the MOUSE_MAX value in, in order to
+		 *			max out the axis.
+		 */
+		static const float MOUSE_MAX_TIME;
+
 		OIS::InputManager* mInputManager;
 		OIS::Mouse*	mMouse;
 		OIS::Keyboard* mKeyboard;
@@ -155,6 +161,7 @@ namespace BansheeEngine
 		INT32 mMouseSampleAccumulator[2];
 		float mMouseSmoothedAxis[2];
 		UINT32 mLastMouseUpdateFrame;
+		bool mMouseSamplesObsolete;
 
 		UINT64 mTimestampClockOffset;
 	};

+ 18 - 9
BansheeOISInput/Source/BsInputHandlerOIS.cpp

@@ -10,6 +10,7 @@ namespace BansheeEngine
 {
 	const UINT32 InputHandlerOIS::MOUSE_DPI = 800;
 	const float InputHandlerOIS::MOUSE_MAX = 0.05f;
+	const float InputHandlerOIS::MOUSE_MAX_TIME = 0.020f; // 20 ms
 
 	GamepadEventListener::GamepadEventListener(InputHandlerOIS* parentHandler, UINT32 joystickIdx)
 		:mParentHandler(parentHandler), mGamepadIdx(joystickIdx)
@@ -47,14 +48,12 @@ namespace BansheeEngine
 
 		mParentHandler->onAxisMoved(mGamepadIdx, axisState, (UINT32)axis);
 
-		LOGWRN(toString(axis) + " - " + toString(axisState.abs));
-
 		return true;
 	}
 
 	InputHandlerOIS::InputHandlerOIS(unsigned int hWnd)
 		:mInputManager(nullptr), mKeyboard(nullptr), mMouse(nullptr), mTimestampClockOffset(0),
-		mLastMouseUpdateFrame(0)
+		mLastMouseUpdateFrame(0), mMouseSamplesObsolete(true)
 	{
 		mMouseSampleAccumulator[0] = 0;
 		mMouseSampleAccumulator[1] = 0;
@@ -209,20 +208,22 @@ namespace BansheeEngine
 			rawYValue = (float)mMouseSampleAccumulator[1];
 		}
 
-		mMouseSampleAccumulator[0] = 0;
-		mMouseSampleAccumulator[1] = 0;
+		mMouseSamplesObsolete = true;
+
+		// Scale by time so that we are framerate independant: rawXValue = rawXValue * (MOUSE_MAX_TIME / gTime().getFrameDelta());
+		// Scale to valid [-1.0, 1.0] range: rawXValue / (MOUSE_DPI * MOUSE_MAX)
+		// This is just the combination of the two:
 
-		// Move the axis values in [-1.0, 1.0] range.
-		float maxAxis = MOUSE_DPI * MOUSE_MAX;
+		float axisScale = ((MOUSE_DPI * MOUSE_MAX) / MOUSE_MAX_TIME) * gTime().getFrameDelta();
 
 		RawAxisState xState;
-		xState.rel = -Math::clamp(rawXValue / maxAxis, -1.0f, 1.0f);
+		xState.rel = -Math::clamp(rawXValue / axisScale, -1.0f, 1.0f);
 		xState.abs = xState.rel; // Abs value irrelevant for mouse
 
 		onAxisMoved(0, xState, (UINT32)InputAxis::MouseX);
 
 		RawAxisState yState;
-		yState.rel = -Math::clamp(rawYValue / maxAxis, -1.0f, 1.0f);
+		yState.rel = -Math::clamp(rawYValue / axisScale, -1.0f, 1.0f);
 		yState.abs = yState.rel; // Abs value irrelevant for mouse
 		
 		onAxisMoved(0, yState, (UINT32)InputAxis::MouseY);
@@ -252,6 +253,14 @@ namespace BansheeEngine
 
 	bool InputHandlerOIS::mouseMoved(const OIS::MouseEvent& arg)
 	{
+		if (mMouseSamplesObsolete)
+		{
+			mMouseSampleAccumulator[0] = 0;
+			mMouseSampleAccumulator[1] = 0;
+
+			mMouseSamplesObsolete = false;
+		}
+
 		mMouseSampleAccumulator[0] += arg.state.X.rel;
 		mMouseSampleAccumulator[1] += arg.state.Y.rel;
 

+ 26 - 1
ExampleProject/Main/Main.cpp

@@ -29,6 +29,7 @@
 #include "BsCoreThread.h"
 #include "BsProfilerOverlay.h"
 #include "BsRenderer.h"
+#include "BsResources.h"
 
 #include "CameraFlyer.h"
 
@@ -42,6 +43,11 @@ namespace BansheeEngine
 	 */
 	void setUpExample();
 
+	/**
+	 * Releases all resources and prepares the example fur shutdown.
+	 */
+	void shutDownExample();
+
 	/**
 	 * Toggles the primary window between full-screen and windowed mode.
 	 */
@@ -78,13 +84,15 @@ int CALLBACK WinMain(
 	Application::startUp(renderWindowDesc, RenderSystemPlugin::DX11);
 
 	// Imports all of ours assets and prepares GameObject that handle the example logic.
-	setUpExample();
+	//setUpExample();
 	
 	// Runs the main loop that does most of the work. This method will exit when user closes the main
 	// window or exits in some other way.
 	Application::instance().runMainLoop();
 
 	// Perform cleanup
+	//shutDownExample();
+
 	Application::shutDown();
 
 	return 0;
@@ -389,6 +397,23 @@ namespace BansheeEngine
 		profilerOverlay = guiSO->addComponent<ProfilerOverlay>(guiCamera->getViewport());
 	}
 
+	void shutDownExample()
+	{
+		// We require all handles to be released before shutdown.
+		gResources().unload(exampleModel);
+		gResources().unload(exampleTexture);
+		gResources().unload(exampleFragmentGPUProg);
+		gResources().unload(exampleVertexGPUProg);
+
+		exampleModel = nullptr;
+		exampleTexture = nullptr;
+		exampleFragmentGPUProg = nullptr;
+		exampleVertexGPUProg = nullptr;
+
+		sceneCamera = nullptr;
+		profilerOverlay = nullptr;
+	}
+
 	void toggleFullscreen()
 	{
 		RenderWindowPtr window = gApplication().getPrimaryWindow();

+ 4 - 2
Polish.txt

@@ -1,7 +1,6 @@
 Polish TODO:
  - Finalize example with resolution settings and proper GUI
   - Ensure that going fullscreen and windowed works fine
- - Mouse movement is release build is too slow
  - Add an example model
  - Test if example shuts down fine
 
@@ -19,7 +18,10 @@ Polish TODO:
  - Test checking out source and extracting dependencies and see if it compiles
  - Test compiling on another PC
 
-Transient meshes never get released. I'm assuming its circular reference MeshBase and MeshProxy have to each-other. Figure out a way to resolve it properly.
+Input issues:
+ - I cannot have input of 1 one frame and input of 0 another. This happens when frames are too short. I might need to add very short smoothing times?
+ - I cannot have input set to 1 during the entire frame if the frame is very long and user just moved the mouse a bit.
+   - This might be even more of an issue with joystick axes as I currently have no mechanism of knowing what % of the frame are they being moved.
 
 -----------------