浏览代码

Added a renderer extension interface - Allows a significantly easier way to write code that extends or interacts with renderer's output

BearishSun 9 年之前
父节点
当前提交
34bdebe1e4

+ 2 - 0
Source/BansheeCore/CMakeSources.cmake

@@ -90,6 +90,7 @@ set(BS_BANSHEECORE_INC_RENDERER
 	"Include/BsParamBlocks.h"
 	"Include/BsParamBlocks.h"
 	"Include/BsCamera.h"
 	"Include/BsCamera.h"
 	"Include/BsPostProcessSettings.h"
 	"Include/BsPostProcessSettings.h"
+	"Include/BsRendererExtension.h"
 )
 )
 
 
 set(BS_BANSHEECORE_SRC_LOCALIZATION
 set(BS_BANSHEECORE_SRC_LOCALIZATION
@@ -344,6 +345,7 @@ set(BS_BANSHEECORE_SRC_RENDERER
 	"Source/BsParamBlocks.cpp"
 	"Source/BsParamBlocks.cpp"
 	"Source/BsCamera.cpp"
 	"Source/BsCamera.cpp"
 	"Source/BsPostProcessSettings.cpp"
 	"Source/BsPostProcessSettings.cpp"
+	"Source/BsRendererExtension.cpp"
 )
 )
 
 
 set(BS_BANSHEECORE_SRC_RESOURCES
 set(BS_BANSHEECORE_SRC_RESOURCES

+ 16 - 17
Source/BansheeCore/Include/BsCoreRenderer.h

@@ -8,6 +8,7 @@
 
 
 namespace bs
 namespace bs
 {
 {
+	class RendererExtension;
 	struct PostProcessSettings;
 	struct PostProcessSettings;
 
 
 	/** @addtogroup Renderer-Internal
 	/** @addtogroup Renderer-Internal
@@ -117,25 +118,20 @@ namespace bs
 		 */
 		 */
 		virtual SPtr<RendererMeshData> _createMeshData(const SPtr<MeshData>& meshData);
 		virtual SPtr<RendererMeshData> _createMeshData(const SPtr<MeshData>& meshData);
 
 
-		/**
-		 * Registers a new callback that will be executed when the the specify camera is being rendered.
-		 *
-		 * @param[in]	camera		Camera for which to trigger the callback.
-		 * @param[in]	index		Index that determines the order of rendering when there are multiple registered 
-		 *							callbacks. This must be unique. Lower indices get rendered sooner. Indices below 0 get 
-		 *							rendered before the main viewport elements, while indices equal or greater to zero after. 
-		 * @param[in]	callback	Callback to trigger when the specified camera is being rendered.
-		 * @param[in]	isOverlay	If true the render callback guarantees that it will only render overlay data. Overlay 
-		 *							data doesn't require a depth buffer, a multisampled render target and is usually cheaper
-		 *							to render (although this depends on the exact renderer). 
-		 *							Overlay callbacks are always rendered after all other callbacks, even if their index is negative.
-		 *
+		/** 
+		 * Registers an extension object that will be called every frame by the renderer. Allows external code to perform
+		 * custom rendering interleaved with the renderer's output.
+		 * 
 		 * @note	Core thread.
 		 * @note	Core thread.
 		 */
 		 */
-		void registerRenderCallback(const CameraCore* camera, INT32 index, const std::function<void()>& callback, bool isOverlay = false);
+		void addPlugin(RendererExtension* plugin) { mCallbacks.insert(plugin); }
 
 
-		/** Removes a previously registered callback registered with _registerRenderCallback(). */
-		void unregisterRenderCallback(const CameraCore* camera, INT32 index);
+		/** 
+		 * Unregisters an extension registered with addPlugin(). 
+		 * 
+		 * @note	Core thread.
+		 */
+		void removePlugin(RendererExtension* plugin) { mCallbacks.erase(plugin); }
 
 
 		/**	Sets options used for controlling the rendering. */
 		/**	Sets options used for controlling the rendering. */
 		virtual void setOptions(const SPtr<CoreRendererOptions>& options) { }
 		virtual void setOptions(const SPtr<CoreRendererOptions>& options) { }
@@ -154,7 +150,10 @@ namespace bs
 			std::function<void()> callback;
 			std::function<void()> callback;
 		};
 		};
 
 
-		UnorderedMap<const CameraCore*, Map<INT32, RenderCallbackData>> mRenderCallbacks;
+		/** Callback to trigger when comparing the order in which renderer extensions are called. */
+		static bool compareCallback(const RendererExtension* a, const RendererExtension* b);
+
+		Set<RendererExtension*, std::function<bool(const RendererExtension*, const RendererExtension*)>> mCallbacks;
 	};
 	};
 
 
 	/** @} */
 	/** @} */

+ 115 - 0
Source/BansheeCore/Include/BsRendererExtension.h

@@ -0,0 +1,115 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsCorePrerequisites.h"
+
+namespace bs
+{
+	/** @addtogroup Renderer-Internal
+	 *  @{
+	 */
+
+	/** A set of available locations at which the renderer can call RendererExtension's render() method. */
+	enum class RenderLocation
+	{
+		/** 
+		 * Rendering happens before any scene objects are rendered. The renderer guarantees the render targets used for 
+		 * rendering scene objects will be bound (e.g. GBuffer).
+		 */
+		PreBasePass,
+
+		/** 
+		 * Rendering happens after all scene objects are rendered. The renderer guarantees the render targets used for 
+		 * rendering scene objects will be bound (e.g. GBuffer). 
+		 */
+		PostBasePass,
+
+		/**
+		 * Rendering happens after all scene objects have been rendered and their final information has been written to
+		 * the final scene color buffer, without any post-processing. The renderer guarantees the final scene color render
+		 * target will be bound.
+		 */
+		PostLightPass,
+
+		/**
+		 * Rendering happens after all scene objects have been rendered and their final information has been written to
+		 * the final scene color buffer, with post-processing. The renderer guarantees the final scene color render target 
+		 * will be bound.
+		 */
+		Overlay
+	};
+
+	/** 
+	 * Interface that can be implemented in order to provide custom rendering code to the renderer. 
+	 * See CoreRenderer::addPlugin().
+	 * 
+	 * @note	Core thread.
+	 */
+	class BS_CORE_EXPORT RendererExtension
+	{
+	public:
+		/** 
+		 * Creates a brand new instance of a specific implementation of a renderer extension. Queues initialization of the
+		 * object on the core thread and registers it with the renderer. Destruction will be queued on the core thread when
+		 * the object goes out of scope.
+		 * 
+		 * @note	Sim thread.
+		 */
+		template<class T>
+		static SPtr<T> create(const Any& data)
+		{
+			T* ext = new (bs_alloc<T>()) T();
+			_initializer(ext, data);
+
+			return SPtr<T>(ext, &RendererExtension::_deleter);
+		}
+
+		/** Called when the renderer extension is first initialized. */
+		virtual void initialize(const Any& data) {}
+
+		/** Called just before the renderer extension is destroyed. */
+		virtual void destroy() {}
+
+		/** Returns true if the render() method should be called for the provided camera. */
+		virtual bool check(const CameraCore& camera) = 0;
+
+		/** 
+		 * Called at the point at which rendering should be performed for the provided camera. Relevant render targets
+		 * are guaranteed to be already bound to the render API, depending on the RenderLocation. Note that actual structure
+		 * of the render targets depends on the active renderer.
+		 */
+		virtual void render(const CameraCore& camera) = 0;
+
+		/** 
+		 * Determines when will the render() method execute, compared to other plugins using the same RenderLocation. 
+		 * Higher number means the extension will execute before extensions with lower numbers. Priorities only matter for 
+		 * extensions that share the same RenderLocation.
+		 */
+		UINT32 getPriority() const { return mPriority; }
+
+		/** 
+		 * Returns a location that determines at which point in rendering should the system call the render() method. See
+		 * RenderLocation.
+		 */
+		RenderLocation getLocation() const { return mLocation; }
+
+	protected:
+		RendererExtension(RenderLocation location, UINT32 priority)
+			:mLocation(location), mPriority(priority)
+		{ }
+
+		virtual ~RendererExtension() {}
+	private:
+		/** Initializer that triggers when a renderer extension is first constructed. */
+		static void _initializer(RendererExtension* obj, const Any& data);
+
+		/** Deleter that triggers when a renderer extension object goes out of scope. */
+		static void _deleter(RendererExtension* obj);
+
+		RenderLocation mLocation;
+		UINT32 mPriority;
+	};
+
+	/** @} */
+}

+ 12 - 19
Source/BansheeCore/Source/BsCoreRenderer.cpp

@@ -5,15 +5,12 @@
 #include "BsRenderAPI.h"
 #include "BsRenderAPI.h"
 #include "BsMesh.h"
 #include "BsMesh.h"
 #include "BsMaterial.h"
 #include "BsMaterial.h"
-#include "BsPass.h"
-#include "BsBlendState.h"
-#include "BsDepthStencilState.h"
-#include "BsRasterizerState.h"
-#include "BsGpuParams.h"
+#include "BsRendererExtension.h"
 
 
 namespace bs
 namespace bs
 {
 {
 	CoreRenderer::CoreRenderer()
 	CoreRenderer::CoreRenderer()
+		:mCallbacks(&compareCallback)
 	{ }
 	{ }
 
 
 	SPtr<RendererMeshData> CoreRenderer::_createMeshData(UINT32 numVertices, UINT32 numIndices, VertexLayout layout, IndexType indexType)
 	SPtr<RendererMeshData> CoreRenderer::_createMeshData(UINT32 numVertices, UINT32 numIndices, VertexLayout layout, IndexType indexType)
@@ -28,21 +25,17 @@ namespace bs
 			RendererMeshData(meshData));
 			RendererMeshData(meshData));
 	}
 	}
 
 
-	void CoreRenderer::registerRenderCallback(const CameraCore* camera, INT32 index, 
-		const std::function<void()>& callback, bool isOverlay)
+	bool CoreRenderer::compareCallback(const RendererExtension* a, const RendererExtension* b)
 	{
 	{
-		mRenderCallbacks[camera][index] = { isOverlay, callback };
-	}
-
-	void CoreRenderer::unregisterRenderCallback(const CameraCore* camera, INT32 index)
-	{
-		auto iterFind = mRenderCallbacks.find(camera);
-		if (iterFind != mRenderCallbacks.end())
+		// Sort by alpha setting first, then by cull mode, then by index
+		if (a->getLocation() == b->getLocation())
 		{
 		{
-			iterFind->second.erase(index);
-
-			if (iterFind->second.empty())
-				mRenderCallbacks.erase(iterFind);
+			if (a->getPriority() == b->getPriority())
+				return a > b; // Use address, at this point it doesn't matter, but std::set requires us to differentiate
+			else
+				return a->getPriority() > b->getPriority();
 		}
 		}
-	}
+		else
+			return (UINT32)a->getLocation() < (UINT32)b->getLocation();
+	};
 }
 }

+ 36 - 0
Source/BansheeCore/Source/BsRendererExtension.cpp

@@ -0,0 +1,36 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsRendererExtension.h"
+#include "BsCoreThread.h"
+#include "BsRendererManager.h"
+#include "BsCoreRenderer.h"
+
+namespace bs
+{
+	void RendererExtension::_initializer(RendererExtension* obj, const Any& data)
+	{
+		auto coreInitializer = [=]()
+		{
+			RendererManager::instance().getActive()->addPlugin(obj);
+			obj->initialize(data);
+		};
+
+		gCoreThread().queueCommand(coreInitializer);
+	}
+
+	void RendererExtension::_deleter(RendererExtension* obj)
+	{
+		auto deleteObj = [=]()
+		{
+			RendererManager::instance().getActive()->removePlugin(obj);
+
+			obj->destroy();
+			obj->~RendererExtension();
+
+			bs_free(obj);
+		};
+
+		// Queue deletion on the core thread
+		gCoreThread().queueCommand(deleteObj);
+	}
+}

+ 12 - 23
Source/BansheeEditor/Include/BsDockManager.h

@@ -3,6 +3,7 @@
 #pragma once
 #pragma once
 
 
 #include "BsEditorPrerequisites.h"
 #include "BsEditorPrerequisites.h"
+#include "BsRendererExtension.h"
 #include "BsGUIElementContainer.h"
 #include "BsGUIElementContainer.h"
 #include "BsRect2I.h"
 #include "BsRect2I.h"
 
 
@@ -221,12 +222,6 @@ namespace bs
 		 */
 		 */
 		bool insidePolygon(Vector2* polyPoints, UINT32 numPoints, Vector2 point) const;
 		bool insidePolygon(Vector2* polyPoints, UINT32 numPoints, Vector2 point) const;
 
 
-		/**	Initializes the renderer used for displaying the dock overlay. */
-		void initializeOverlayRenderer(const SPtr<MaterialCore>& initData);
-
-		/**	Destroys the dock overlay renderer. */
-		void destroyOverlayRenderer(DockOverlayRenderer* core);
-
 		/** @copydoc GUIElementBase::updateClippedBounds */
 		/** @copydoc GUIElementBase::updateClippedBounds */
 		void updateClippedBounds() override;
 		void updateClippedBounds() override;
 
 
@@ -239,7 +234,7 @@ namespace bs
 		/** @copydoc GUIElementBase::_mouseEvent */
 		/** @copydoc GUIElementBase::_mouseEvent */
 		bool _mouseEvent(const GUIMouseEvent& event) override;
 		bool _mouseEvent(const GUIMouseEvent& event) override;
 
 
-		std::atomic<DockOverlayRenderer*> mCore;
+		SPtr<DockOverlayRenderer> mRenderer;
 
 
 		EditorWindowBase* mParentWindow;
 		EditorWindowBase* mParentWindow;
 		DockContainer mRootContainer;
 		DockContainer mRootContainer;
@@ -261,26 +256,23 @@ namespace bs
 		Vector2* mRightDropPolygon;
 		Vector2* mRightDropPolygon;
 	};
 	};
 
 
-	/**
-	 * Handles rendering of the dock overlay, on the core thread.
-	 * 			
-	 * @note	Core thread only.
-	 */
-	class DockOverlayRenderer
+	/** Handles rendering of the dock overlay on the core thread. */
+	class DockOverlayRenderer : public RendererExtension
 	{
 	{
 	public:
 	public:
 		DockOverlayRenderer();
 		DockOverlayRenderer();
-		~DockOverlayRenderer();
 
 
 	private:
 	private:
 		friend class DockManager;
 		friend class DockManager;
 
 
-		/**
-		 * Initializes the object. Must be called right after construction and before any use.
-		 *
-		 * @param[in]	material	Material used for drawing the dock overlay.
-		 */
-		void initialize(const SPtr<MaterialCore>& material);
+		/**	@copydoc RendererExtension::initialize */
+		void initialize(const Any& data) override;
+
+		/**	@copydoc RendererExtension::check */
+		bool check(const CameraCore& camera) override;
+
+		/**	@copydoc RendererExtension::render */
+		void render(const CameraCore& camera) override;
 
 
 		/**
 		/**
 		 * Updates the grid mesh to render.
 		 * Updates the grid mesh to render.
@@ -293,9 +285,6 @@ namespace bs
 		void updateData(const SPtr<CameraCore>& camera, const SPtr<MeshCore>& mesh, bool active,
 		void updateData(const SPtr<CameraCore>& camera, const SPtr<MeshCore>& mesh, bool active,
 			DockManager::DockLocation location);
 			DockManager::DockLocation location);
 
 
-		/**	Callback triggered by the renderer, actually draws the dock overlay. */
-		void render();
-		
 		SPtr<CameraCore> mCamera;
 		SPtr<CameraCore> mCamera;
 		SPtr<MaterialCore> mMaterial;
 		SPtr<MaterialCore> mMaterial;
 		SPtr<GpuParamsSetCore> mParams;
 		SPtr<GpuParamsSetCore> mParams;

+ 14 - 32
Source/BansheeEditor/Include/BsGizmoManager.h

@@ -10,6 +10,7 @@
 #include "BsGpuParam.h"
 #include "BsGpuParam.h"
 #include "BsDrawHelper.h"
 #include "BsDrawHelper.h"
 #include "BsParamBlocks.h"
 #include "BsParamBlocks.h"
+#include "BsRendererExtension.h"
 
 
 namespace bs
 namespace bs
 {
 {
@@ -17,7 +18,7 @@ namespace bs
 	 *  @{
 	 *  @{
 	 */
 	 */
 
 
-	class GizmoManagerCore;
+	class GizmoRenderer;
 
 
 	/** Type of mesh that can be drawn by the gizmo renderer. */
 	/** Type of mesh that can be drawn by the gizmo renderer. */
 	enum class GizmoMeshType
 	enum class GizmoMeshType
@@ -255,7 +256,7 @@ namespace bs
 		/** @} */
 		/** @} */
 
 
 	private:
 	private:
-		friend class GizmoManagerCore;
+		friend class GizmoRenderer;
 
 
 		/**	Supported types of gizmo materials (shaders) */
 		/**	Supported types of gizmo materials (shaders) */
 		enum class GizmoMaterial
 		enum class GizmoMaterial
@@ -433,12 +434,6 @@ namespace bs
 		void calculateIconColors(const Color& tint, const SPtr<Camera>& camera, UINT32 iconHeight, bool fixedScale,
 		void calculateIconColors(const Color& tint, const SPtr<Camera>& camera, UINT32 iconHeight, bool fixedScale,
 			Color& normalColor, Color& fadedColor);
 			Color& normalColor, Color& fadedColor);
 
 
-		/**	Initializes the core thread version of the gizmo manager. */
-		void initializeCore(const CoreInitData& initData);
-
-		/**	Destroys the core thread version of the gizmo manager. */
-		void destroyCore(GizmoManagerCore* core);
-
 		static const UINT32 VERTEX_BUFFER_GROWTH;
 		static const UINT32 VERTEX_BUFFER_GROWTH;
 		static const UINT32 INDEX_BUFFER_GROWTH;
 		static const UINT32 INDEX_BUFFER_GROWTH;
 		static const UINT32 SPHERE_QUALITY;
 		static const UINT32 SPHERE_QUALITY;
@@ -481,7 +476,7 @@ namespace bs
 		SPtr<MeshHeap> mIconMeshHeap;
 		SPtr<MeshHeap> mIconMeshHeap;
 		SPtr<TransientMesh> mIconMesh;
 		SPtr<TransientMesh> mIconMesh;
 
 
-		std::atomic<GizmoManagerCore*> mCore;
+		SPtr<GizmoRenderer> mGizmoRenderer;
 
 
 		// Immutable
 		// Immutable
 		SPtr<VertexDataDesc> mIconVertexDesc;
 		SPtr<VertexDataDesc> mIconVertexDesc;
@@ -516,25 +511,23 @@ namespace bs
 
 
 	extern GizmoPickingParamBlockDef gGizmoPickingParamBlockDef;
 	extern GizmoPickingParamBlockDef gGizmoPickingParamBlockDef;
 
 
-	/**
-	 * Core thread version of the gizmo manager that handles most of the rendering of meshes provided by the gizmo manager.
-	 */
-	class GizmoManagerCore
+	/** Performs rendering of gizmos on the core thread, as managed by the GizmoManager. */
+	class GizmoRenderer : public RendererExtension
 	{
 	{
 		friend class GizmoManager;
 		friend class GizmoManager;
 
 
-		struct PrivatelyConstuct { };
-
 	public:
 	public:
-		GizmoManagerCore(const PrivatelyConstuct& dummy);
-		~GizmoManagerCore();
+		GizmoRenderer();
 
 
 	private:
 	private:
-		/**	Initializes the core gizmo manager. Must be called right after creation. */
-		void initialize(const GizmoManager::CoreInitData& initData);
+		/**	@copydoc RendererExtension::initialize */
+		void initialize(const Any& data) override;
 
 
-		/**	Renders all gizmos in the parent camera. */
-		void render();
+		/**	@copydoc RendererExtension::check */
+		bool check(const CameraCore& camera) override;
+
+		/**	@copydoc RendererExtension::render */
+		void render(const CameraCore& camera) override;
 
 
 		/**	
 		/**	
 		 * Renders all provided meshes using the provided camera. 
 		 * Renders all provided meshes using the provided camera. 
@@ -550,17 +543,6 @@ namespace bs
 			const SPtr<MeshCoreBase>& iconMesh, const GizmoManager::IconRenderDataVecPtr& iconRenderData, 
 			const SPtr<MeshCoreBase>& iconMesh, const GizmoManager::IconRenderDataVecPtr& iconRenderData, 
 			bool usePickingMaterial);
 			bool usePickingMaterial);
 
 
-		/**
-		 * Renders a non-icon gizmo mesh using the provided material. Relevant material parameters are expected to be
-		 * assigned before this is called.
-		 *
-		 * @param[in]	mesh		Mesh to render. This is normally the solid or wireframe gizmo mesh.
-		 * @param[in]	texture		Texture to apply to the material, if the material supports a texture.
-		 * @param[in]	material	Material to use for rendering. This is normally the solid, wireframe or picking material.
-		 */
-		void renderGizmoMesh(const SPtr<MeshCoreBase>& mesh, const SPtr<TextureCore>& texture, 
-			GizmoManager::GizmoMaterial material);
-
 		/**
 		/**
 		 * Renders the icon gizmo mesh using the provided parameters.
 		 * Renders the icon gizmo mesh using the provided parameters.
 		 *
 		 *

+ 26 - 35
Source/BansheeEditor/Include/BsHandleDrawManager.h

@@ -3,6 +3,7 @@
 #pragma once
 #pragma once
 
 
 #include "BsEditorPrerequisites.h"
 #include "BsEditorPrerequisites.h"
+#include "BsRendererExtension.h"
 #include "BsGpuParams.h"
 #include "BsGpuParams.h"
 #include "BsDrawHelper.h"
 #include "BsDrawHelper.h"
 #include "BsParamBlocks.h"
 #include "BsParamBlocks.h"
@@ -13,7 +14,7 @@ namespace bs
 	 *  @{
 	 *  @{
 	 */
 	 */
 
 
-	class HandleDrawManagerCore;
+	class HandleRenderer;
 
 
 	/**
 	/**
 	 * Allows you to easily draw various kinds of simple shapes, primarily used for drawing handles in the scene view.
 	 * Allows you to easily draw various kinds of simple shapes, primarily used for drawing handles in the scene view.
@@ -164,21 +165,7 @@ namespace bs
 		void clear();
 		void clear();
 
 
 	private:
 	private:
-		friend class HandleDrawManagerCore;
-
-		/**
-		 * Initializes the core thread portion of the draw manager.
-		 *
-		 * @param[in]	lineMat		Material used for drawing the line objects.
-		 * @param[in]	solidMat	Material used for drawing the solid objects.
-		 * @param[in]	textMat		Material used for drawing the text.
-		 * @param[in]	clearMat	Material used for clearing the alpha channel in the empty areas.
-		 */
-		void initializeCore(const SPtr<MaterialCore>& lineMat, const SPtr<MaterialCore>& solidMat,
-			const SPtr<MaterialCore>& textMat, const SPtr<MaterialCore>& clearMat);
-
-		/** Destroys the core thread portion of the draw manager. */
-		void destroyCore(HandleDrawManagerCore* core);
+		friend class HandleRenderer;
 
 
 		/** Destroys all meshes allocated since the last call to this method. */
 		/** Destroys all meshes allocated since the last call to this method. */
 		void clearMeshes();
 		void clearMeshes();
@@ -191,7 +178,7 @@ namespace bs
 		UINT64 mLastFrameIdx;
 		UINT64 mLastFrameIdx;
 
 
 		Matrix4 mTransform;
 		Matrix4 mTransform;
-		std::atomic<HandleDrawManagerCore*> mCore;
+		SPtr<HandleRenderer> mRenderer;
 		DrawHelper* mDrawHelper;
 		DrawHelper* mDrawHelper;
 	};
 	};
 
 
@@ -207,8 +194,8 @@ namespace bs
 
 
 	extern HandleParamBlockDef gHandleParamBlockDef;
 	extern HandleParamBlockDef gHandleParamBlockDef;
 
 
-	/** Core thread specific portion of the HandleDrawManager that handles actual rendering. */
-	class BS_ED_EXPORT HandleDrawManagerCore
+	/** Performs rendering of handles on the core thread, managed by the parent HandleDrawManager. */
+	class BS_ED_EXPORT HandleRenderer : public RendererExtension
 	{
 	{
 		/** Type of mesh that can be drawn. */
 		/** Type of mesh that can be drawn. */
 		enum class MeshType
 		enum class MeshType
@@ -236,25 +223,32 @@ namespace bs
 			Vector<MeshData> meshes;
 			Vector<MeshData> meshes;
 		};
 		};
 
 
-		struct PrivatelyConstruct { };
+		/** Data used for initializing the renderer. */
+		struct InitData
+		{
+			SPtr<MaterialCore> lineMat;
+			SPtr<MaterialCore> solidMat;
+			SPtr<MaterialCore> textMat;
+			SPtr<MaterialCore> clearMat;
+		};
 
 
 	public:
 	public:
-		HandleDrawManagerCore(const PrivatelyConstruct& dummy);
-		~HandleDrawManagerCore();
+		HandleRenderer();
 
 
 	private:
 	private:
 		friend class HandleDrawManager;
 		friend class HandleDrawManager;
 
 
-		/**
-		 * Initializes the object. Must be called right after construction.
-		 *
-		 * @param[in]	lineMat		Material used for drawing the line objects.
-		 * @param[in]	solidMat	Material used for drawing the solid objects.
-		 * @param[in]	textMat		Material used for drawing the text.
-		 * @param[in]	clearMat	Material used for clearing the alpha channel in the empty areas.
-		 */
-		void initialize(const SPtr<MaterialCore>& lineMat, const SPtr<MaterialCore>& solidMat, 
-			const SPtr<MaterialCore>& textMat, const SPtr<MaterialCore>& clearMat);
+		/** @copydoc RendererExtension::initialize */
+		void initialize(const Any& data) override;
+
+		/** @copydoc RendererExtension::destroy */
+		void destroy() override;
+
+		/** @copydoc RendererExtension::check */
+		bool check(const CameraCore& camera) override;
+
+		/** @copydoc RendererExtension::render */
+		void render(const CameraCore& camera) override;
 
 
 		/**
 		/**
 		 * Queues new data for rendering.
 		 * Queues new data for rendering.
@@ -267,9 +261,6 @@ namespace bs
 		/** Deletes any meshes queued for rendering. */
 		/** Deletes any meshes queued for rendering. */
 		void clearQueued();
 		void clearQueued();
 
 
-		/** Callback triggered by the renderer. Draws all queued meshes. */
-		void render(UINT32 queuedDataIdx);
-
 		Vector<QueuedData> mQueuedData;
 		Vector<QueuedData> mQueuedData;
 
 
 		SPtr<GpuParamBlockBufferCore> mParamBuffer;
 		SPtr<GpuParamBlockBufferCore> mParamBuffer;

+ 20 - 26
Source/BansheeEditor/Include/BsSceneGrid.h

@@ -3,6 +3,7 @@
 #pragma once
 #pragma once
 
 
 #include "BsEditorPrerequisites.h"
 #include "BsEditorPrerequisites.h"
+#include "BsRendererExtension.h"
 #include "BsVector2I.h"
 #include "BsVector2I.h"
 #include "BsColor.h"
 #include "BsColor.h"
 #include "BsMaterial.h"
 #include "BsMaterial.h"
@@ -13,7 +14,7 @@ namespace bs
 	 *  @{
 	 *  @{
 	 */
 	 */
 
 
-	class SceneGridCore;
+	class SceneGridRenderer;
 
 
 	/** Determines how is the scene grid drawn. */
 	/** Determines how is the scene grid drawn. */
 	enum class GridMode
 	enum class GridMode
@@ -55,17 +56,6 @@ namespace bs
 		/**	Rebuilds the scene grid mesh. Call this whenever grid parameters change. */
 		/**	Rebuilds the scene grid mesh. Call this whenever grid parameters change. */
 		void updateGridMesh();
 		void updateGridMesh();
 
 
-		/**
-		 * Initializes the core thread portion of the scene grid renderer.
-		 *
-		 * @param[in]	material	Material used for drawing the grid.
-		 * @param[in]	camera		Camera to render the scene grid to.
-		 */
-		void initializeCore(const SPtr<CameraCore>& camera, const SPtr<MaterialCore>& material);
-
-		/** Destroys the core thread portion of the draw manager. */
-		void destroyCore(SceneGridCore* core);
-
 		float mSpacing = 1.0f;
 		float mSpacing = 1.0f;
 		UINT32 mSize = 256;
 		UINT32 mSize = 256;
 		GridMode mMode = GridMode::Perspective;
 		GridMode mMode = GridMode::Perspective;
@@ -76,26 +66,33 @@ namespace bs
 
 
 		HMesh mGridMesh;
 		HMesh mGridMesh;
 		SPtr<VertexDataDesc> mVertexDesc;
 		SPtr<VertexDataDesc> mVertexDesc;
-		std::atomic<SceneGridCore*> mCore;
+		SPtr<SceneGridRenderer> mRenderer;
 	};
 	};
 
 
 	/** Handles scene grid rendering on the core thread. */
 	/** Handles scene grid rendering on the core thread. */
-	class SceneGridCore
+	class SceneGridRenderer : public RendererExtension
 	{
 	{
 	public:
 	public:
-		SceneGridCore() { }
-		~SceneGridCore();
+		/** Structure used for initializing the renderer. */
+		struct InitData
+		{
+			SPtr<CameraCore> camera;
+			SPtr<MaterialCore> material;
+		};
+
+		SceneGridRenderer();
 
 
 	private:
 	private:
 		friend class SceneGrid;
 		friend class SceneGrid;
 
 
-		/**
-		 * Initializes the object. Must be called right after construction and before any use.
-		 *
-		 * @param[in]	material	Material used for drawing the grid.
-		 * @param[in]	camera		Camera to render the scene grid to.
-		 */
-		void initialize(const SPtr<CameraCore>& camera, const SPtr<MaterialCore>& material);
+		/**	@copydoc RendererExtension::initialize */
+		void initialize(const Any& data) override;
+
+		/**	@copydoc RendererExtension::check */
+		bool check(const CameraCore& camera) override;
+
+		/**	@copydoc RendererExtension::render */
+		void render(const CameraCore& camera) override;
 
 
 		/**
 		/**
 		 * Updates the grid mesh to render.
 		 * Updates the grid mesh to render.
@@ -108,9 +105,6 @@ namespace bs
 		 */
 		 */
 		void updateData(const SPtr<MeshCore>& mesh, float spacing, bool fadeGrid, const Vector3& gridPlaneNormal);
 		void updateData(const SPtr<MeshCore>& mesh, float spacing, bool fadeGrid, const Vector3& gridPlaneNormal);
 
 
-		/**	Callback triggered by the renderer, actually draws the grid mesh. */
-		void render();
-
 		SPtr<CameraCore> mCamera;
 		SPtr<CameraCore> mCamera;
 		SPtr<MeshCore> mGridMesh;
 		SPtr<MeshCore> mGridMesh;
 		SPtr<MaterialCore> mGridMaterial;
 		SPtr<MaterialCore> mGridMaterial;

+ 11 - 28
Source/BansheeEditor/Include/BsSelectionRenderer.h

@@ -3,6 +3,7 @@
 #pragma once
 #pragma once
 
 
 #include "BsEditorPrerequisites.h"
 #include "BsEditorPrerequisites.h"
+#include "BsRendererExtension.h"
 #include "BsColor.h"
 #include "BsColor.h"
 #include "BsMatrix4.h"
 #include "BsMatrix4.h"
 #include "BsGpuParam.h"
 #include "BsGpuParam.h"
@@ -28,44 +29,26 @@ namespace bs
 	private:
 	private:
 		friend class SelectionRendererCore;
 		friend class SelectionRendererCore;
 
 
-		/**
-		 * Initializes the core thread counterpart of the selection renderer.
-		 *
-		 * @param[in]	mat		Material used for selection rendering.
-		 */
-		void initializeCore(const SPtr<MaterialCore>& mat);
-
-		/**
-		 * Destroys the core thread counterpart of the selection renderer.
-		 *
-		 * @param[in]	core	Previously constructed core thread selection renderer instance.
-		 */
-		void destroyCore(SelectionRendererCore* core);
-
-		std::atomic<SelectionRendererCore*> mCore;
+		SPtr<SelectionRendererCore> mRenderer;
 	};
 	};
 
 
 	/** Core thread version of the selection renderer, that handles actual rendering. */
 	/** Core thread version of the selection renderer, that handles actual rendering. */
-	class SelectionRendererCore
+	class SelectionRendererCore : public RendererExtension
 	{
 	{
 		friend class SelectionRenderer;
 		friend class SelectionRenderer;
-		
-		struct PrivatelyConstuct { };
 
 
 	public:
 	public:
-		SelectionRendererCore(const PrivatelyConstuct& dummy);
-		~SelectionRendererCore();
+		SelectionRendererCore();
 
 
 	private:
 	private:
-		/**
-		 * Initializes the selection renderer. Should be called right after construction.
-		 *
-		 * @param[in]	mat	Material used for selection rendering.
-		 */
-		void initialize(const SPtr<MaterialCore>& mat);
+		/** @copydoc RendererExtension::initialize */
+		void initialize(const Any& data) override;
+
+		/** @copydoc RendererExtension::check */
+		bool check(const CameraCore& camera) override;
 
 
-		/** Triggered by the Renderer when the overlay should be rendered. */
-		void render();
+		/** @copydoc RendererExtension::render */
+		void render(const CameraCore& camera) override;
 
 
 		/**
 		/**
 		 * Updates the internal data that determines what will be rendered on the next render() call.
 		 * Updates the internal data that determines what will be rendered on the next render() call.

+ 14 - 42
Source/BansheeEditor/Source/BsDockManager.cpp

@@ -464,9 +464,7 @@ namespace bs
 
 
 		HMaterial dropOverlayMat = BuiltinEditorResources::instance().createDockDropOverlayMaterial();
 		HMaterial dropOverlayMat = BuiltinEditorResources::instance().createDockDropOverlayMaterial();
 
 
-		mCore.store(bs_new<DockOverlayRenderer>(), std::memory_order_release);
-		gCoreThread().queueCommand(std::bind(&DockManager::initializeOverlayRenderer, 
-			this, dropOverlayMat->getCore()));
+		mRenderer = RendererExtension::create<DockOverlayRenderer>(dropOverlayMat->getCore());
 	}
 	}
 
 
 	DockManager::~DockManager()
 	DockManager::~DockManager()
@@ -475,19 +473,6 @@ namespace bs
 		bs_deleteN(mBotDropPolygon, 4);
 		bs_deleteN(mBotDropPolygon, 4);
 		bs_deleteN(mLeftDropPolygon, 4);
 		bs_deleteN(mLeftDropPolygon, 4);
 		bs_deleteN(mRightDropPolygon, 4);
 		bs_deleteN(mRightDropPolygon, 4);
-
-		gCoreThread().queueCommand(std::bind(&DockManager::destroyOverlayRenderer,
-			this, mCore.load(std::memory_order_relaxed)));
-	}
-
-	void DockManager::initializeOverlayRenderer(const SPtr<MaterialCore>& initData)
-	{
-		mCore.load(std::memory_order_acquire)->initialize(initData);
-	}
-
-	void DockManager::destroyOverlayRenderer(DockOverlayRenderer* core)
-	{
-		bs_delete(core);
 	}
 	}
 
 
 	DockManager* DockManager::create(EditorWindowBase* parentWindow)
 	DockManager* DockManager::create(EditorWindowBase* parentWindow)
@@ -507,8 +492,8 @@ namespace bs
 
 
 		HCamera camera = mParentWindow->getGUICamera();
 		HCamera camera = mParentWindow->getGUICamera();
 
 
-		DockOverlayRenderer* core = mCore.load(std::memory_order_relaxed);
-		gCoreThread().queueCommand(std::bind(&DockOverlayRenderer::updateData, core, camera->_getCamera()->getCore(),
+		DockOverlayRenderer* renderer = mRenderer.get();
+		gCoreThread().queueCommand(std::bind(&DockOverlayRenderer::updateData, renderer, camera->_getCamera()->getCore(),
 			mDropOverlayMesh->getCore(), mShowOverlay, mHighlightedDropLoc));
 			mDropOverlayMesh->getCore(), mShowOverlay, mHighlightedDropLoc));
 	}
 	}
 
 
@@ -1131,46 +1116,33 @@ namespace bs
 	const Color DockOverlayRenderer::HIGHLIGHT_COLOR = Color(0.44f, 0.44f, 0.44f, 0.42f);
 	const Color DockOverlayRenderer::HIGHLIGHT_COLOR = Color(0.44f, 0.44f, 0.44f, 0.42f);
 
 
 	DockOverlayRenderer::DockOverlayRenderer()
 	DockOverlayRenderer::DockOverlayRenderer()
-		:mHighlightedDropLoc(DockManager::DockLocation::None), mShowOverlay(false)
+		: RendererExtension(RenderLocation::Overlay, 0), mHighlightedDropLoc(DockManager::DockLocation::None)
+		, mShowOverlay(false)
 	{
 	{
 		
 		
 	}
 	}
 
 
-	DockOverlayRenderer::~DockOverlayRenderer()
-	{
-		if (mCamera != nullptr)
-		{
-			SPtr<CoreRenderer> activeRenderer = RendererManager::instance().getActive();
-			activeRenderer->unregisterRenderCallback(mCamera.get(), 40);
-		}
-	}
-
-	void DockOverlayRenderer::initialize(const SPtr<MaterialCore>& material)
+	void DockOverlayRenderer::initialize(const Any& data)
 	{
 	{
-		mMaterial = material;
-		mParams = material->createParamsSet();
+		mMaterial = any_cast<SPtr<MaterialCore>>(data);
+		mParams = mMaterial->createParamsSet();
 	}
 	}
 
 
 	void DockOverlayRenderer::updateData(const SPtr<CameraCore>& camera, const SPtr<MeshCore>& mesh, bool active, 
 	void DockOverlayRenderer::updateData(const SPtr<CameraCore>& camera, const SPtr<MeshCore>& mesh, bool active, 
 		DockManager::DockLocation location)
 		DockManager::DockLocation location)
 	{
 	{
-		if (mCamera != camera)
-		{
-			SPtr<CoreRenderer> activeRenderer = RendererManager::instance().getActive();
-			if (mCamera != nullptr)
-				activeRenderer->unregisterRenderCallback(mCamera.get(), 40);
-
-			if (camera != nullptr)
-				activeRenderer->registerRenderCallback(camera.get(), 40, std::bind(&DockOverlayRenderer::render, this), true);
-		}
-
 		mCamera = camera;
 		mCamera = camera;
 		mMesh = mesh;
 		mMesh = mesh;
 		mShowOverlay = active;
 		mShowOverlay = active;
 		mHighlightedDropLoc = location;
 		mHighlightedDropLoc = location;
 	}
 	}
 
 
-	void DockOverlayRenderer::render()
+	bool DockOverlayRenderer::check(const CameraCore& camera)
+	{
+		return mCamera.get() == &camera;
+	}
+
+	void DockOverlayRenderer::render(const CameraCore& camera)
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;
 
 

+ 23 - 46
Source/BansheeEditor/Source/BsGizmoManager.cpp

@@ -35,7 +35,7 @@ namespace bs
 
 
 	GizmoManager::GizmoManager()
 	GizmoManager::GizmoManager()
 		: mPickable(false), mCurrentIdx(0), mTransformDirty(false), mColorDirty(false), mDrawHelper(nullptr)
 		: mPickable(false), mCurrentIdx(0), mTransformDirty(false), mColorDirty(false), mDrawHelper(nullptr)
-		, mPickingDrawHelper(nullptr), mCore(nullptr)
+		, mPickingDrawHelper(nullptr)
 		
 		
 	{
 	{
 		mTransform = Matrix4::IDENTITY;
 		mTransform = Matrix4::IDENTITY;
@@ -68,9 +68,7 @@ namespace bs
 		initData.pickingMat = pickingMaterial->getCore();
 		initData.pickingMat = pickingMaterial->getCore();
 		initData.alphaPickingMat = alphaPickingMaterial->getCore();
 		initData.alphaPickingMat = alphaPickingMaterial->getCore();
 
 
-		mCore.store(bs_new<GizmoManagerCore>(GizmoManagerCore::PrivatelyConstuct()), std::memory_order_release);
-
-		gCoreThread().queueCommand(std::bind(&GizmoManager::initializeCore, this, initData));
+		mGizmoRenderer = RendererExtension::create<GizmoRenderer>(initData);
 	}
 	}
 
 
 	GizmoManager::~GizmoManager()
 	GizmoManager::~GizmoManager()
@@ -83,18 +81,6 @@ namespace bs
 
 
 		bs_delete(mDrawHelper);
 		bs_delete(mDrawHelper);
 		bs_delete(mPickingDrawHelper);
 		bs_delete(mPickingDrawHelper);
-
-		gCoreThread().queueCommand(std::bind(&GizmoManager::destroyCore, this, mCore.load(std::memory_order_relaxed)));
-	}
-
-	void GizmoManager::initializeCore(const CoreInitData& initData)
-	{
-		mCore.load(std::memory_order_acquire)->initialize(initData);
-	}
-
-	void GizmoManager::destroyCore(GizmoManagerCore* core)
-	{
-		bs_delete(core);
 	}
 	}
 
 
 	void GizmoManager::startGizmo(const HSceneObject& gizmoParent)
 	void GizmoManager::startGizmo(const HSceneObject& gizmoParent)
@@ -464,9 +450,9 @@ namespace bs
 		mIconMesh = buildIconMesh(camera, mIconData, false, iconRenderData);
 		mIconMesh = buildIconMesh(camera, mIconData, false, iconRenderData);
 		SPtr<MeshCoreBase> iconMesh = mIconMesh->getCore();
 		SPtr<MeshCoreBase> iconMesh = mIconMesh->getCore();
 
 
-		GizmoManagerCore* core = mCore.load(std::memory_order_relaxed);
+		GizmoRenderer* renderer = mGizmoRenderer.get();
 
 
-		gCoreThread().queueCommand(std::bind(&GizmoManagerCore::updateData, core, camera->getCore(),
+		gCoreThread().queueCommand(std::bind(&GizmoRenderer::updateData, renderer, camera->getCore(),
 			proxyData, iconMesh, iconRenderData));
 			proxyData, iconMesh, iconRenderData));
 	}
 	}
 
 
@@ -640,10 +626,10 @@ namespace bs
 		SPtr<TransientMesh> iconMesh = buildIconMesh(camera, iconData, true, iconRenderData);
 		SPtr<TransientMesh> iconMesh = buildIconMesh(camera, iconData, true, iconRenderData);
 
 
 		// Note: This must be rendered while Scene view is being rendered
 		// Note: This must be rendered while Scene view is being rendered
-		GizmoManagerCore* core = mCore.load(std::memory_order_relaxed);
+		GizmoRenderer* renderer = mGizmoRenderer.get();
 
 
 		Vector<MeshRenderData> proxyData = createMeshProxyData(meshes);
 		Vector<MeshRenderData> proxyData = createMeshProxyData(meshes);
-		gCoreThread().queueCommand(std::bind(&GizmoManagerCore::renderData, core, camera->getCore(),
+		gCoreThread().queueCommand(std::bind(&GizmoRenderer::renderData, renderer, camera->getCore(),
 											 proxyData, iconMesh->getCore(), iconRenderData, true));
 											 proxyData, iconMesh->getCore(), iconRenderData, true));
 
 
 		mPickingDrawHelper->clearMeshes(meshes);
 		mPickingDrawHelper->clearMeshes(meshes);
@@ -683,10 +669,10 @@ namespace bs
 
 
 		mIconMesh = nullptr;
 		mIconMesh = nullptr;
 
 
-		GizmoManagerCore* core = mCore.load(std::memory_order_relaxed);
+		GizmoRenderer* renderer = mGizmoRenderer.get();
 		IconRenderDataVecPtr iconRenderData = bs_shared_ptr_new<IconRenderDataVec>();
 		IconRenderDataVecPtr iconRenderData = bs_shared_ptr_new<IconRenderDataVec>();
 		
 		
-		gCoreThread().queueCommand(std::bind(&GizmoManagerCore::updateData, core,
+		gCoreThread().queueCommand(std::bind(&GizmoRenderer::updateData, renderer,
 			nullptr, Vector<MeshRenderData>(), nullptr, iconRenderData));
 			nullptr, Vector<MeshRenderData>(), nullptr, iconRenderData));
 	}
 	}
 
 
@@ -910,23 +896,19 @@ namespace bs
 	GizmoParamBlockDef gHandleParamBlockDef;
 	GizmoParamBlockDef gHandleParamBlockDef;
 	GizmoPickingParamBlockDef gGizmoPickingParamBlockDef;
 	GizmoPickingParamBlockDef gGizmoPickingParamBlockDef;
 
 
-	const float GizmoManagerCore::PICKING_ALPHA_CUTOFF = 0.5f;
+	const float GizmoRenderer::PICKING_ALPHA_CUTOFF = 0.5f;
 
 
-	GizmoManagerCore::GizmoManagerCore(const PrivatelyConstuct& dummy)
+	GizmoRenderer::GizmoRenderer()
+		:RendererExtension(RenderLocation::PostLightPass, 0)
 	{
 	{
 	}
 	}
 
 
-	GizmoManagerCore::~GizmoManagerCore()
-	{
-		SPtr<CoreRenderer> activeRenderer = RendererManager::instance().getActive();
-		if (mCamera != nullptr)
-			activeRenderer->unregisterRenderCallback(mCamera.get(), 20);
-	}
-
-	void GizmoManagerCore::initialize(const GizmoManager::CoreInitData& initData)
+	void GizmoRenderer::initialize(const Any& data)
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;
 
 
+		const GizmoManager::CoreInitData& initData = any_cast_ref<GizmoManager::CoreInitData>(data);
+
 		mMeshMaterials[(UINT32)GizmoMeshType::Solid] = initData.solidMat;
 		mMeshMaterials[(UINT32)GizmoMeshType::Solid] = initData.solidMat;
 		mMeshMaterials[(UINT32)GizmoMeshType::Wire] = initData.wireMat;
 		mMeshMaterials[(UINT32)GizmoMeshType::Wire] = initData.wireMat;
 		mMeshMaterials[(UINT32)GizmoMeshType::Line] = initData.lineMat;
 		mMeshMaterials[(UINT32)GizmoMeshType::Line] = initData.lineMat;
@@ -941,19 +923,9 @@ namespace bs
 		mIconPickingParamBuffer = gGizmoPickingParamBlockDef.createBuffer();
 		mIconPickingParamBuffer = gGizmoPickingParamBlockDef.createBuffer();
 	}
 	}
 
 
-	void GizmoManagerCore::updateData(const SPtr<CameraCore>& camera, const Vector<GizmoManager::MeshRenderData>& meshes,
+	void GizmoRenderer::updateData(const SPtr<CameraCore>& camera, const Vector<GizmoManager::MeshRenderData>& meshes,
 		const SPtr<MeshCoreBase>& iconMesh, const GizmoManager::IconRenderDataVecPtr& iconRenderData)
 		const SPtr<MeshCoreBase>& iconMesh, const GizmoManager::IconRenderDataVecPtr& iconRenderData)
 	{
 	{
-		if (mCamera != camera)
-		{
-			SPtr<CoreRenderer> activeRenderer = RendererManager::instance().getActive();
-			if (mCamera != nullptr)
-				activeRenderer->unregisterRenderCallback(mCamera.get(), 0);
-
-			if (camera != nullptr)
-				activeRenderer->registerRenderCallback(camera.get(), 0, std::bind(&GizmoManagerCore::render, this));
-		}
-
 		mCamera = camera;
 		mCamera = camera;
 		mMeshes = meshes;
 		mMeshes = meshes;
 		mIconMesh = iconMesh;
 		mIconMesh = iconMesh;
@@ -1013,12 +985,17 @@ namespace bs
 		}
 		}
 	}
 	}
 
 
-	void GizmoManagerCore::render()
+	bool GizmoRenderer::check(const CameraCore& camera)
+	{
+		return &camera == mCamera.get();
+	}
+
+	void GizmoRenderer::render(const CameraCore& camera)
 	{
 	{
 		renderData(mCamera, mMeshes, mIconMesh, mIconRenderData, false);
 		renderData(mCamera, mMeshes, mIconMesh, mIconRenderData, false);
 	}
 	}
 
 
-	void GizmoManagerCore::renderData(const SPtr<CameraCore>& camera, Vector<GizmoManager::MeshRenderData>& meshes,
+	void GizmoRenderer::renderData(const SPtr<CameraCore>& camera, Vector<GizmoManager::MeshRenderData>& meshes,
 		const SPtr<MeshCoreBase>& iconMesh, const GizmoManager::IconRenderDataVecPtr& iconRenderData, bool usePickingMaterial)
 		const SPtr<MeshCoreBase>& iconMesh, const GizmoManager::IconRenderDataVecPtr& iconRenderData, bool usePickingMaterial)
 	{
 	{
 		if (camera == nullptr)
 		if (camera == nullptr)
@@ -1106,7 +1083,7 @@ namespace bs
 			renderIconGizmos(screenArea, iconMesh, iconRenderData, usePickingMaterial);
 			renderIconGizmos(screenArea, iconMesh, iconRenderData, usePickingMaterial);
 	}
 	}
 
 
-	void GizmoManagerCore::renderIconGizmos(Rect2I screenArea, SPtr<MeshCoreBase> mesh, 
+	void GizmoRenderer::renderIconGizmos(Rect2I screenArea, SPtr<MeshCoreBase> mesh, 
 		GizmoManager::IconRenderDataVecPtr renderData, bool usePickingMaterial)
 		GizmoManager::IconRenderDataVecPtr renderData, bool usePickingMaterial)
 	{
 	{
 		RenderAPICore& rapi = RenderAPICore::instance();
 		RenderAPICore& rapi = RenderAPICore::instance();

+ 77 - 86
Source/BansheeEditor/Source/BsHandleDrawManager.cpp

@@ -24,7 +24,7 @@ namespace bs
 	const UINT32 HandleDrawManager::ARC_QUALITY = 10;
 	const UINT32 HandleDrawManager::ARC_QUALITY = 10;
 
 
 	HandleDrawManager::HandleDrawManager()
 	HandleDrawManager::HandleDrawManager()
-		:mLastFrameIdx((UINT64)-1), mCore(nullptr)
+		:mLastFrameIdx((UINT64)-1)
 	{
 	{
 		mTransform = Matrix4::IDENTITY;
 		mTransform = Matrix4::IDENTITY;
 		mDrawHelper = bs_new<DrawHelper>();
 		mDrawHelper = bs_new<DrawHelper>();
@@ -34,38 +34,19 @@ namespace bs
 		HMaterial textMaterial = BuiltinEditorResources::instance().createTextGizmoMat();
 		HMaterial textMaterial = BuiltinEditorResources::instance().createTextGizmoMat();
 		HMaterial clearMaterial = BuiltinEditorResources::instance().createHandleClearAlphaMat();
 		HMaterial clearMaterial = BuiltinEditorResources::instance().createHandleClearAlphaMat();
 
 
-		SPtr<MaterialCore> solidMaterialProxy = solidMaterial->getCore();
-		SPtr<MaterialCore> lineMaterialProxy = lineMaterial->getCore();
-		SPtr<MaterialCore> textMaterialProxy = textMaterial->getCore();
-		SPtr<MaterialCore> clearMaterialProxy = clearMaterial->getCore();
+		HandleRenderer::InitData rendererInitData;
+		rendererInitData.solidMat = solidMaterial->getCore();
+		rendererInitData.lineMat = lineMaterial->getCore();
+		rendererInitData.textMat = textMaterial->getCore();
+		rendererInitData.clearMat = clearMaterial->getCore();
 
 
-		mCore.store(bs_new<HandleDrawManagerCore>(HandleDrawManagerCore::PrivatelyConstruct()), std::memory_order_release);
-
-		gCoreThread().queueCommand(std::bind(&HandleDrawManager::initializeCore, this,
-			lineMaterialProxy, solidMaterialProxy, textMaterialProxy, clearMaterialProxy));
+		mRenderer = RendererExtension::create<HandleRenderer>(rendererInitData);
 	}
 	}
 
 
 	HandleDrawManager::~HandleDrawManager()
 	HandleDrawManager::~HandleDrawManager()
 	{
 	{
 		clearMeshes();
 		clearMeshes();
 		bs_delete(mDrawHelper);
 		bs_delete(mDrawHelper);
-
-		gCoreThread().queueCommand(std::bind(&HandleDrawManager::destroyCore, this, mCore.load(std::memory_order_relaxed)));
-	}
-
-	void HandleDrawManager::initializeCore(const SPtr<MaterialCore>& lineMat, const SPtr<MaterialCore>& solidMat, 
-		const SPtr<MaterialCore>& textMat, const SPtr<MaterialCore>& clearMat)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		mCore.load(std::memory_order_acquire)->initialize(lineMat, solidMat, textMat, clearMat);
-	}
-
-	void HandleDrawManager::destroyCore(HandleDrawManagerCore* core)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		bs_delete(core);
 	}
 	}
 
 
 	void HandleDrawManager::setColor(const Color& color)
 	void HandleDrawManager::setColor(const Color& color)
@@ -185,13 +166,13 @@ namespace bs
 
 
 	void HandleDrawManager::draw(const SPtr<Camera>& camera)
 	void HandleDrawManager::draw(const SPtr<Camera>& camera)
 	{
 	{
-		HandleDrawManagerCore* core = mCore.load(std::memory_order_relaxed);
+		HandleRenderer* renderer = mRenderer.get();
 
 
 		// Clear meshes from previous frame
 		// Clear meshes from previous frame
 		UINT64 frameIdx = gTime().getFrameIdx();
 		UINT64 frameIdx = gTime().getFrameIdx();
 		if(frameIdx != mLastFrameIdx)
 		if(frameIdx != mLastFrameIdx)
 		{
 		{
-			gCoreThread().queueCommand(std::bind(&HandleDrawManagerCore::clearQueued, core));
+			gCoreThread().queueCommand(std::bind(&HandleRenderer::clearQueued, renderer));
 
 
 			clearMeshes();
 			clearMeshes();
 			mLastFrameIdx = frameIdx;
 			mLastFrameIdx = frameIdx;
@@ -202,7 +183,7 @@ namespace bs
 		const Vector<DrawHelper::ShapeMeshData>& meshes = mDrawHelper->getMeshes();
 		const Vector<DrawHelper::ShapeMeshData>& meshes = mDrawHelper->getMeshes();
 		mActiveMeshes.push_back(meshes);
 		mActiveMeshes.push_back(meshes);
 
 
-		Vector<HandleDrawManagerCore::MeshData> proxyData;
+		Vector<HandleRenderer::MeshData> proxyData;
 		for (auto& meshData : meshes)
 		for (auto& meshData : meshes)
 		{
 		{
 			SPtr<TextureCore> tex;
 			SPtr<TextureCore> tex;
@@ -211,22 +192,22 @@ namespace bs
 
 
 			if (meshData.type == DrawHelper::MeshType::Solid)
 			if (meshData.type == DrawHelper::MeshType::Solid)
 			{
 			{
-				proxyData.push_back(HandleDrawManagerCore::MeshData(
-					meshData.mesh->getCore(), tex, HandleDrawManagerCore::MeshType::Solid));
+				proxyData.push_back(HandleRenderer::MeshData(
+					meshData.mesh->getCore(), tex, HandleRenderer::MeshType::Solid));
 			}
 			}
 			else if (meshData.type == DrawHelper::MeshType::Line)
 			else if (meshData.type == DrawHelper::MeshType::Line)
 			{
 			{
-				proxyData.push_back(HandleDrawManagerCore::MeshData(
-					meshData.mesh->getCore(), tex, HandleDrawManagerCore::MeshType::Line));
+				proxyData.push_back(HandleRenderer::MeshData(
+					meshData.mesh->getCore(), tex, HandleRenderer::MeshType::Line));
 			}
 			}
 			else // Text
 			else // Text
 			{
 			{
-				proxyData.push_back(HandleDrawManagerCore::MeshData(
-					meshData.mesh->getCore(), tex, HandleDrawManagerCore::MeshType::Text));
+				proxyData.push_back(HandleRenderer::MeshData(
+					meshData.mesh->getCore(), tex, HandleRenderer::MeshType::Text));
 			}
 			}
 		}
 		}
 
 
-		gCoreThread().queueCommand(std::bind(&HandleDrawManagerCore::queueForDraw, core, camera->getCore(), proxyData));
+		gCoreThread().queueCommand(std::bind(&HandleRenderer::queueForDraw, renderer, camera->getCore(), proxyData));
 	}
 	}
 
 
 	void HandleDrawManager::clear()
 	void HandleDrawManager::clear()
@@ -244,35 +225,33 @@ namespace bs
 
 
 	HandleParamBlockDef gHandleParamBlockDef;
 	HandleParamBlockDef gHandleParamBlockDef;
 
 
-	HandleDrawManagerCore::HandleDrawManagerCore(const PrivatelyConstruct& dummy)
-		:mTypeCounters()
+	HandleRenderer::HandleRenderer()
+		:RendererExtension(RenderLocation::PostLightPass, -20), mTypeCounters()
 	{ }
 	{ }
 
 
-	HandleDrawManagerCore::~HandleDrawManagerCore()
+	void HandleRenderer::initialize(const Any& data)
 	{
 	{
-		clearQueued();
-	}
+		const InitData& initData = any_cast_ref<InitData>(data);
 
 
-	void HandleDrawManagerCore::initialize(const SPtr<MaterialCore>& lineMat, const SPtr<MaterialCore>& solidMat, 
-		const SPtr<MaterialCore>& textMat, const SPtr<MaterialCore>& clearMat)
-	{
-		mMaterials[(UINT32)MeshType::Line] = lineMat;
-		mMaterials[(UINT32)MeshType::Solid] = solidMat;
-		mMaterials[(UINT32)MeshType::Text] = textMat;
+		mMaterials[(UINT32)MeshType::Line] = initData.lineMat;
+		mMaterials[(UINT32)MeshType::Solid] = initData.solidMat;
+		mMaterials[(UINT32)MeshType::Text] = initData.textMat;
 
 
-		mClearMaterial = clearMat;
+		mClearMaterial = initData.clearMat;
 
 
 		mParamBuffer = gHandleParamBlockDef.createBuffer();
 		mParamBuffer = gHandleParamBlockDef.createBuffer();
 	}
 	}
 
 
-	void HandleDrawManagerCore::queueForDraw(const SPtr<CameraCore>& camera, Vector<MeshData>& meshes)
+	void HandleRenderer::destroy()
+	{
+		clearQueued();
+	}
+
+	void HandleRenderer::queueForDraw(const SPtr<CameraCore>& camera, Vector<MeshData>& meshes)
 	{
 	{
 		SPtr<CoreRenderer> activeRenderer = RendererManager::instance().getActive();
 		SPtr<CoreRenderer> activeRenderer = RendererManager::instance().getActive();
 		if (camera != nullptr)
 		if (camera != nullptr)
 		{
 		{
-			UINT32 idx = (UINT32)mQueuedData.size();
-			activeRenderer->registerRenderCallback(camera.get(), 20, std::bind(&HandleDrawManagerCore::render, this, idx));
-
 			for(auto& entry : meshes)
 			for(auto& entry : meshes)
 			{
 			{
 				UINT32 typeIdx = (UINT32)entry.type;
 				UINT32 typeIdx = (UINT32)entry.type;
@@ -306,57 +285,69 @@ namespace bs
 		}
 		}
 	}
 	}
 
 
-	void HandleDrawManagerCore::clearQueued()
+	void HandleRenderer::clearQueued()
 	{
 	{
-		SPtr<CoreRenderer> activeRenderer = RendererManager::instance().getActive();
-		for (auto& entry : mQueuedData)
-			activeRenderer->unregisterRenderCallback(entry.camera.get(), 20);
-
 		mQueuedData.clear();
 		mQueuedData.clear();
 	}
 	}
 
 
-	void HandleDrawManagerCore::render(UINT32 queuedDataIdx)
+	bool HandleRenderer::check(const CameraCore& camera)
+	{
+		for(auto& entry : mQueuedData)
+		{
+			if (entry.camera.get() == &camera)
+				return true;
+		}
+
+		return false;
+	}
+
+	void HandleRenderer::render(const CameraCore& camera)
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;
 
 
-		const QueuedData& queueData = mQueuedData[queuedDataIdx];
-		SPtr<CameraCore> camera = queueData.camera;
-		const Vector<MeshData>& meshes = queueData.meshes;
+		for (auto& entry : mQueuedData)
+		{
+			if (entry.camera.get() != &camera)
+				continue;
 
 
-		SPtr<RenderTargetCore> renderTarget = camera->getViewport()->getTarget();
+			const QueuedData& queueData = entry;
+			const Vector<MeshData>& meshes = queueData.meshes;
 
 
-		float width = (float)renderTarget->getProperties().getWidth();
-		float height = (float)renderTarget->getProperties().getHeight();
+			SPtr<RenderTargetCore> renderTarget = camera.getViewport()->getTarget();
 
 
-		Rect2 normArea = camera->getViewport()->getNormArea();
+			float width = (float)renderTarget->getProperties().getWidth();
+			float height = (float)renderTarget->getProperties().getHeight();
 
 
-		Rect2I screenArea;
-		screenArea.x = (int)(normArea.x * width);
-		screenArea.y = (int)(normArea.y * height);
-		screenArea.width = (int)(normArea.width * width);
-		screenArea.height = (int)(normArea.height * height);
+			Rect2 normArea = camera.getViewport()->getNormArea();
 
 
-		Matrix4 viewProjMat = camera->getProjectionMatrixRS() * camera->getViewMatrix();
+			Rect2I screenArea;
+			screenArea.x = (int)(normArea.x * width);
+			screenArea.y = (int)(normArea.y * height);
+			screenArea.width = (int)(normArea.width * width);
+			screenArea.height = (int)(normArea.height * height);
 
 
-		gHandleParamBlockDef.gMatViewProj.set(mParamBuffer, viewProjMat);
-		gHandleParamBlockDef.gViewDir.set(mParamBuffer, (Vector4)camera->getForward());
+			Matrix4 viewProjMat = camera.getProjectionMatrixRS() * camera.getViewMatrix();
 
 
-		UINT32 currentType = -1;
-		for (auto& meshData : meshes)
-		{
-			UINT32 typeIdx = (UINT32)meshData.type;
-			if (currentType != typeIdx)
+			gHandleParamBlockDef.gMatViewProj.set(mParamBuffer, viewProjMat);
+			gHandleParamBlockDef.gViewDir.set(mParamBuffer, (Vector4)camera.getForward());
+
+			UINT32 currentType = -1;
+			for (auto& meshData : meshes)
 			{
 			{
-				gRendererUtility().setPass(mMaterials[typeIdx]);
-				currentType = typeIdx;
+				UINT32 typeIdx = (UINT32)meshData.type;
+				if (currentType != typeIdx)
+				{
+					gRendererUtility().setPass(mMaterials[typeIdx]);
+					currentType = typeIdx;
+				}
+
+				gRendererUtility().setPassParams(mParamSets[typeIdx][meshData.paramIdx]);
+				gRendererUtility().draw(meshData.mesh, meshData.mesh->getProperties().getSubMesh(0));
 			}
 			}
 
 
-			gRendererUtility().setPassParams(mParamSets[typeIdx][meshData.paramIdx]);
-			gRendererUtility().draw(meshData.mesh, meshData.mesh->getProperties().getSubMesh(0));
+			// Set alpha of everything that was drawn to 1 so we can overlay this texture onto GUI using transparency
+			gRendererUtility().setPass(mClearMaterial, 0);
+			gRendererUtility().drawScreenQuad();
 		}
 		}
-
-		// Set alpha of everything that was drawn to 1 so we can overlay this texture onto GUI using transparency
-		gRendererUtility().setPass(mClearMaterial, 0);
-		gRendererUtility().drawScreenQuad();
 	}
 	}
 }
 }

+ 31 - 44
Source/BansheeEditor/Source/BsSceneGrid.cpp

@@ -17,46 +17,31 @@
 
 
 namespace bs
 namespace bs
 {
 {
-	const Color SceneGridCore::GRID_LINE_COLOR = Color(0.5f, 0.5f, 0.5f);
-	const float SceneGridCore::LINE_WIDTH = 0.025f;
-	const float SceneGridCore::LINE_BORDER_WIDTH = 0.00075f;
-	const float SceneGridCore::FADE_OUT_START = 5.0f;
-	const float SceneGridCore::FADE_OUT_END = 40.0f;
+	const Color SceneGridRenderer::GRID_LINE_COLOR = Color(0.5f, 0.5f, 0.5f);
+	const float SceneGridRenderer::LINE_WIDTH = 0.025f;
+	const float SceneGridRenderer::LINE_BORDER_WIDTH = 0.00075f;
+	const float SceneGridRenderer::FADE_OUT_START = 5.0f;
+	const float SceneGridRenderer::FADE_OUT_END = 40.0f;
 
 
 	SceneGrid::SceneGrid(const SPtr<Camera>& camera)
 	SceneGrid::SceneGrid(const SPtr<Camera>& camera)
-		:mCoreDirty(true), mCore(nullptr)
+		:mCoreDirty(true)
 	{
 	{
 		mVertexDesc = bs_shared_ptr_new<VertexDataDesc>();
 		mVertexDesc = bs_shared_ptr_new<VertexDataDesc>();
 		mVertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
 		mVertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
 		mVertexDesc->addVertElem(VET_FLOAT3, VES_NORMAL);
 		mVertexDesc->addVertElem(VET_FLOAT3, VES_NORMAL);
 
 
-		mCore.store(bs_new<SceneGridCore>(), std::memory_order_release);
-
 		HMaterial gridMaterial = BuiltinEditorResources::instance().createSceneGridMaterial();
 		HMaterial gridMaterial = BuiltinEditorResources::instance().createSceneGridMaterial();
-		SPtr<MaterialCore> materialCore = gridMaterial->getCore();
-		gCoreThread().queueCommand(std::bind(&SceneGrid::initializeCore, this, camera->getCore(), materialCore));
 
 
+		SceneGridRenderer::InitData initData;
+		initData.material = gridMaterial->getCore();
+		initData.camera = camera->getCore();
+
+		mRenderer = RendererExtension::create<SceneGridRenderer>(initData);
 		updateGridMesh();
 		updateGridMesh();
 	}
 	}
 
 
 	SceneGrid::~SceneGrid()
 	SceneGrid::~SceneGrid()
-	{
-		gCoreThread().queueCommand(std::bind(&SceneGrid::destroyCore, this, mCore.load(std::memory_order_relaxed)));
-	}
-
-	void SceneGrid::initializeCore(const SPtr<CameraCore>& camera, const SPtr<MaterialCore>& material)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		mCore.load()->initialize(camera, material);
-	}
-
-	void SceneGrid::destroyCore(SceneGridCore* core)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		bs_delete(core);
-	}
+	{ }
 
 
 	void SceneGrid::setSize(UINT32 size)
 	void SceneGrid::setSize(UINT32 size)
 	{
 	{
@@ -114,9 +99,9 @@ namespace bs
 				break;
 				break;
 			}
 			}
 
 
-			SceneGridCore* core = mCore.load(std::memory_order_relaxed);
+			SceneGridRenderer* renderer = mRenderer.get();
 			gCoreThread().queueCommand(
 			gCoreThread().queueCommand(
-				std::bind(&SceneGridCore::updateData, core, mGridMesh->getCore(), mSpacing, 
+				std::bind(&SceneGridRenderer::updateData, renderer, mGridMesh->getCore(), mSpacing, 
 				mMode == GridMode::Perspective, gridPlaneNormal));
 				mMode == GridMode::Perspective, gridPlaneNormal));
 
 
 			mCoreDirty = false;
 			mCoreDirty = false;
@@ -187,17 +172,17 @@ namespace bs
 		mCoreDirty = true;
 		mCoreDirty = true;
 	}
 	}
 
 
-	SceneGridCore::~SceneGridCore()
-	{
-		SPtr<CoreRenderer> activeRenderer = RendererManager::instance().getActive();
-		activeRenderer->unregisterRenderCallback(mCamera.get(), 5);
-	}
+	SceneGridRenderer::SceneGridRenderer()
+		:RendererExtension(RenderLocation::PostLightPass, -5)
+	{ }
 
 
-	void SceneGridCore::initialize(const SPtr<CameraCore>& camera, const SPtr<MaterialCore>& material)
+	void SceneGridRenderer::initialize(const Any& data)
 	{
 	{
-		mCamera = camera;
-		mGridMaterial = material;
-		mMaterialParams = material->createParamsSet();
+		const InitData& initData = any_cast_ref<InitData>(data);
+
+		mCamera = initData.camera;
+		mGridMaterial = initData.material;
+		mMaterialParams = initData.material->createParamsSet();
 
 
 		mViewProjParam = mGridMaterial->getParamMat4("matViewProj");
 		mViewProjParam = mGridMaterial->getParamMat4("matViewProj");
 		mWorldCameraPosParam = mGridMaterial->getParamVec4("worldCameraPos");
 		mWorldCameraPosParam = mGridMaterial->getParamVec4("worldCameraPos");
@@ -206,13 +191,10 @@ namespace bs
 		mGridBorderWidthParam = mGridMaterial->getParamFloat("gridBorderWidth");
 		mGridBorderWidthParam = mGridMaterial->getParamFloat("gridBorderWidth");
 		mGridFadeOutStartParam = mGridMaterial->getParamFloat("gridFadeOutStart");
 		mGridFadeOutStartParam = mGridMaterial->getParamFloat("gridFadeOutStart");
 		mGridFadeOutEndParam = mGridMaterial->getParamFloat("gridFadeOutEnd");
 		mGridFadeOutEndParam = mGridMaterial->getParamFloat("gridFadeOutEnd");
-		mGridMaterial->getParam("gridPlaneNormal", mGridPlaneNormalParam);
-
-		SPtr<CoreRenderer> activeRenderer = RendererManager::instance().getActive();
-		activeRenderer->registerRenderCallback(camera.get(), 5, std::bind(&SceneGridCore::render, this));			
+		mGridMaterial->getParam("gridPlaneNormal", mGridPlaneNormalParam);		
 	}
 	}
 
 
-	void SceneGridCore::updateData(const SPtr<MeshCore>& mesh, float spacing, bool fadeGrid, const Vector3& gridPlaneNormal)
+	void SceneGridRenderer::updateData(const SPtr<MeshCore>& mesh, float spacing, bool fadeGrid, const Vector3& gridPlaneNormal)
 	{
 	{
 		mGridMesh = mesh;
 		mGridMesh = mesh;
 		mSpacing = spacing;
 		mSpacing = spacing;
@@ -220,7 +202,12 @@ namespace bs
 		mGridPlaneNormal = gridPlaneNormal;
 		mGridPlaneNormal = gridPlaneNormal;
 	}
 	}
 
 
-	void SceneGridCore::render()
+	bool SceneGridRenderer::check(const CameraCore& camera)
+	{
+		return mCamera.get() == &camera;
+	}
+
+	void SceneGridRenderer::render(const CameraCore& camera)
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;
 
 

+ 14 - 42
Source/BansheeEditor/Source/BsSelectionRenderer.cpp

@@ -29,29 +29,14 @@ using namespace std::placeholders;
 namespace bs
 namespace bs
 {
 {
 	SelectionRenderer::SelectionRenderer()
 	SelectionRenderer::SelectionRenderer()
-		:mCore(nullptr)
 	{
 	{
 		HMaterial selectionMat = BuiltinEditorResources::instance().createSelectionMat();
 		HMaterial selectionMat = BuiltinEditorResources::instance().createSelectionMat();
 			
 			
-		mCore.store(bs_new<SelectionRendererCore>(SelectionRendererCore::PrivatelyConstuct()), std::memory_order_release);
-
-		gCoreThread().queueCommand(std::bind(&SelectionRenderer::initializeCore, this, selectionMat->getCore()));
+		mRenderer = RendererExtension::create<SelectionRendererCore>(selectionMat->getCore());
 	}
 	}
 
 
 	SelectionRenderer::~SelectionRenderer()
 	SelectionRenderer::~SelectionRenderer()
-	{
-		gCoreThread().queueCommand(std::bind(&SelectionRenderer::destroyCore, this, mCore.load(std::memory_order_relaxed)));
-	}
-
-	void SelectionRenderer::initializeCore(const SPtr<MaterialCore>& initData)
-	{
-		mCore.load(std::memory_order_acquire)->initialize(initData);
-	}
-
-	void SelectionRenderer::destroyCore(SelectionRendererCore* core)
-	{
-		bs_delete(core);
-	}
+	{ }
 
 
 	void SelectionRenderer::update(const SPtr<Camera>& camera)
 	void SelectionRenderer::update(const SPtr<Camera>& camera)
 	{
 	{
@@ -75,30 +60,25 @@ namespace bs
 			}
 			}
 		}
 		}
 
 
-		SelectionRendererCore* core = mCore.load(std::memory_order_relaxed);
-		gCoreThread().queueCommand(std::bind(&SelectionRendererCore::updateData, core, camera->getCore(), objects));
+		SelectionRendererCore* renderer = mRenderer.get();
+		gCoreThread().queueCommand(std::bind(&SelectionRendererCore::updateData, renderer, camera->getCore(), objects));
 	}
 	}
 
 
 	const Color SelectionRendererCore::SELECTION_COLOR = Color(1.0f, 1.0f, 1.0f, 0.3f);
 	const Color SelectionRendererCore::SELECTION_COLOR = Color(1.0f, 1.0f, 1.0f, 0.3f);
 
 
-	SelectionRendererCore::SelectionRendererCore(const PrivatelyConstuct& dummy)
-	{
-	}
-
-	SelectionRendererCore::~SelectionRendererCore()
+	SelectionRendererCore::SelectionRendererCore()
+		:RendererExtension(RenderLocation::PostLightPass, -10)
 	{
 	{
-		SPtr<CoreRenderer> activeRenderer = RendererManager::instance().getActive();
-		if (mCamera != nullptr)
-			activeRenderer->unregisterRenderCallback(mCamera.get(), 10);
 	}
 	}
 
 
-	void SelectionRendererCore::initialize(const SPtr<MaterialCore>& mat)
+	void SelectionRendererCore::initialize(const Any& data)
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;
 		
 		
 		constexpr int numTechniques = sizeof(mTechniqueIndices) / sizeof(mTechniqueIndices[0]);
 		constexpr int numTechniques = sizeof(mTechniqueIndices) / sizeof(mTechniqueIndices[0]);
 		static_assert(numTechniques == (int)RenderableAnimType::Count, "Number of techniques doesn't match the number of possible animation types.");
 		static_assert(numTechniques == (int)RenderableAnimType::Count, "Number of techniques doesn't match the number of possible animation types.");
 
 
+		SPtr<MaterialCore> mat = any_cast<SPtr<MaterialCore>>(data);
 		for(UINT32 i = 0; i < numTechniques; i++)
 		for(UINT32 i = 0; i < numTechniques; i++)
 		{
 		{
 			RenderableAnimType animType = (RenderableAnimType)i;
 			RenderableAnimType animType = (RenderableAnimType)i;
@@ -138,26 +118,18 @@ namespace bs
 
 
 	void SelectionRendererCore::updateData(const SPtr<CameraCore>& camera, const Vector<SPtr<RenderableCore>>& objects)
 	void SelectionRendererCore::updateData(const SPtr<CameraCore>& camera, const Vector<SPtr<RenderableCore>>& objects)
 	{
 	{
-		if (mCamera != camera)
-		{
-			SPtr<CoreRenderer> activeRenderer = RendererManager::instance().getActive();
-			if (mCamera != nullptr)
-				activeRenderer->unregisterRenderCallback(mCamera.get(), 10);
-
-			if (camera != nullptr)
-				activeRenderer->registerRenderCallback(camera.get(), 10, std::bind(&SelectionRendererCore::render, this));
-		}
-
 		mCamera = camera;
 		mCamera = camera;
 		mObjects = objects;
 		mObjects = objects;
 	}
 	}
 
 
-	void SelectionRendererCore::render()
+	bool SelectionRendererCore::check(const CameraCore& camera)
 	{
 	{
-		THROW_IF_NOT_CORE_THREAD;
+		return mCamera.get() == &camera;
+	}
 
 
-		if (mCamera == nullptr)
-			return;
+	void SelectionRendererCore::render(const CameraCore& camera)
+	{
+		THROW_IF_NOT_CORE_THREAD;
 
 
 		const RendererAnimationData& animData = AnimationManager::instance().getRendererData();
 		const RendererAnimationData& animData = AnimationManager::instance().getRendererData();
 		Matrix4 viewProjMat = mCamera->getProjectionMatrixRS() * mCamera->getViewMatrix();
 		Matrix4 viewProjMat = mCamera->getProjectionMatrixRS() * mCamera->getViewMatrix();

+ 17 - 15
Source/BansheeEngine/Include/BsGUIManager.h

@@ -3,6 +3,7 @@
 #pragma once
 #pragma once
 
 
 #include "BsPrerequisites.h"
 #include "BsPrerequisites.h"
+#include "BsRendererExtension.h"
 #include "BsGUIMouseEvent.h"
 #include "BsGUIMouseEvent.h"
 #include "BsGUITextInputEvent.h"
 #include "BsGUITextInputEvent.h"
 #include "BsGUICommandEvent.h"
 #include "BsGUICommandEvent.h"
@@ -21,7 +22,7 @@ namespace bs
 	 *  @{
 	 *  @{
 	 */
 	 */
 
 
-	class GUIManagerCore;
+	class GUIRenderer;
 
 
 	/**
 	/**
 	 * Manages the rendering and input of all GUI widgets in the scene. 
 	 * Manages the rendering and input of all GUI widgets in the scene. 
@@ -220,11 +221,8 @@ namespace bs
 		 */
 		 */
 		SPtr<RenderWindow> getBridgeWindow(const SPtr<RenderTexture>& target) const;
 		SPtr<RenderWindow> getBridgeWindow(const SPtr<RenderTexture>& target) const;
 
 
-		/** Gets the core thread portion of the GUI manager, responsible for rendering of GUI elements. */
-		GUIManagerCore* getCore() const { return mCore.load(std::memory_order_relaxed); }
-
 	private:
 	private:
-		friend class GUIManagerCore;
+		friend class GUIRenderer;
 
 
 		/**	Recreates all dirty GUI meshes and makes them ready for rendering. */
 		/**	Recreates all dirty GUI meshes and makes them ready for rendering. */
 		void updateMeshes();
 		void updateMeshes();
@@ -240,7 +238,7 @@ namespace bs
 		 *
 		 *
 		 * @param[in]	core	Previously constructed core thread GUI manager instance.
 		 * @param[in]	core	Previously constructed core thread GUI manager instance.
 		 */
 		 */
-		void destroyCore(GUIManagerCore* core);
+		void destroyCore(GUIRenderer* core);
 
 
 		/**
 		/**
 		 * Destroys any elements or widgets queued for destruction.
 		 * Destroys any elements or widgets queued for destruction.
@@ -351,7 +349,7 @@ namespace bs
 		SPtr<MeshHeap> mTriangleMeshHeap;
 		SPtr<MeshHeap> mTriangleMeshHeap;
 		SPtr<MeshHeap> mLineMeshHeap;
 		SPtr<MeshHeap> mLineMeshHeap;
 
 
-		std::atomic<GUIManagerCore*> mCore;
+		SPtr<GUIRenderer> mRenderer;
 		bool mCoreDirty;
 		bool mCoreDirty;
 
 
 		SPtr<VertexDataDesc> mTriangleVertexDesc;
 		SPtr<VertexDataDesc> mTriangleVertexDesc;
@@ -431,15 +429,21 @@ namespace bs
 	extern GUISpriteParamBlockDef gGUISpriteParamBlockDef;
 	extern GUISpriteParamBlockDef gGUISpriteParamBlockDef;
 
 
 	/**	Handles GUI rendering on the core thread. */
 	/**	Handles GUI rendering on the core thread. */
-	class BS_EXPORT GUIManagerCore
+	class BS_EXPORT GUIRenderer : public RendererExtension
 	{
 	{
 		friend class GUIManager;
 		friend class GUIManager;
 
 
 	public:
 	public:
-		~GUIManagerCore();
+		GUIRenderer();
+
+		/**	@copydoc RendererExtension::initialize */
+		void initialize(const Any& data) override;
 
 
-		/** Initializes the object. Must be called right after construction. */
-		void initialize();
+		/**	@copydoc RendererExtension::check */
+		bool check(const CameraCore& camera) override;
+
+		/**	@copydoc RendererExtension::render */
+		void render(const CameraCore& camera) override;
 
 
 	private:
 	private:
 		/**
 		/**
@@ -449,10 +453,8 @@ namespace bs
 		 */
 		 */
 		void updateData(const UnorderedMap<SPtr<CameraCore>, Vector<GUIManager::GUICoreRenderData>>& perCameraData);
 		void updateData(const UnorderedMap<SPtr<CameraCore>, Vector<GUIManager::GUICoreRenderData>>& perCameraData);
 
 
-		/**	Triggered by the Renderer when the GUI should be rendered. */
-		void render(const SPtr<CameraCore>& camera);
-
-		UnorderedMap<SPtr<CameraCore>, Vector<GUIManager::GUICoreRenderData>> mPerCameraData;
+		UnorderedMap<const CameraCore*, Vector<GUIManager::GUICoreRenderData>> mPerCameraData;
+		Set<SPtr<CameraCore>> mReferencedCameras;
 		Vector<SPtr<GpuParamBlockBufferCore>> mParamBlocks;
 		Vector<SPtr<GpuParamBlockBufferCore>> mParamBlocks;
 		SPtr<SamplerStateCore> mSamplerState;
 		SPtr<SamplerStateCore> mSamplerState;
 	};
 	};

+ 43 - 83
Source/BansheeEngine/Source/BsGUIManager.cpp

@@ -118,10 +118,7 @@ namespace bs
 		deferredCall(std::bind(&GUIManager::updateCaretTexture, this));
 		deferredCall(std::bind(&GUIManager::updateCaretTexture, this));
 		deferredCall(std::bind(&GUIManager::updateTextSelectionTexture, this));
 		deferredCall(std::bind(&GUIManager::updateTextSelectionTexture, this));
 
 
-		GUIManagerCore* core = bs_new<GUIManagerCore>();
-		mCore.store(core, std::memory_order_release);
-
-		gCoreThread().queueCommand(std::bind(&GUIManagerCore::initialize, core));
+		mRenderer = RendererExtension::create<GUIRenderer>(nullptr);
 	}
 	}
 
 
 	GUIManager::~GUIManager()
 	GUIManager::~GUIManager()
@@ -158,12 +155,10 @@ namespace bs
 		bs_delete(mInputCaret);
 		bs_delete(mInputCaret);
 		bs_delete(mInputSelection);
 		bs_delete(mInputSelection);
 
 
-		gCoreThread().queueCommand(std::bind(&GUIManager::destroyCore, this, mCore.load(std::memory_order_relaxed)));
-
 		assert(mCachedGUIData.size() == 0);
 		assert(mCachedGUIData.size() == 0);
 	}
 	}
 
 
-	void GUIManager::destroyCore(GUIManagerCore* core)
+	void GUIManager::destroyCore(GUIRenderer* core)
 	{
 	{
 		bs_delete(core);
 		bs_delete(core);
 	}
 	}
@@ -422,8 +417,7 @@ namespace bs
 				}
 				}
 			}
 			}
 
 
-			GUIManagerCore* core = mCore.load(std::memory_order_relaxed);
-			gCoreThread().queueCommand(std::bind(&GUIManagerCore::updateData, core, corePerCameraData));
+			gCoreThread().queueCommand(std::bind(&GUIRenderer::updateData, mRenderer.get(), corePerCameraData));
 
 
 			mCoreDirty = false;
 			mCoreDirty = false;
 		}
 		}
@@ -1740,14 +1734,11 @@ namespace bs
 
 
 	GUISpriteParamBlockDef gGUISpriteParamBlockDef;
 	GUISpriteParamBlockDef gGUISpriteParamBlockDef;
 
 
-	GUIManagerCore::~GUIManagerCore()
-	{
-		SPtr<CoreRenderer> activeRenderer = RendererManager::instance().getActive();
-		for (auto& cameraData : mPerCameraData)
-			activeRenderer->unregisterRenderCallback(cameraData.first.get(), 30);
-	}
+	GUIRenderer::GUIRenderer()
+		:RendererExtension(RenderLocation::Overlay, 10)
+	{ }
 
 
-	void GUIManagerCore::initialize()
+	void GUIRenderer::initialize(const Any& data)
 	{
 	{
 		SAMPLER_STATE_DESC ssDesc;
 		SAMPLER_STATE_DESC ssDesc;
 		ssDesc.magFilter = FO_POINT;
 		ssDesc.magFilter = FO_POINT;
@@ -1757,57 +1748,54 @@ namespace bs
 		mSamplerState = RenderStateCoreManager::instance().createSamplerState(ssDesc);
 		mSamplerState = RenderStateCoreManager::instance().createSamplerState(ssDesc);
 	}
 	}
 
 
-	void GUIManagerCore::updateData(const UnorderedMap<SPtr<CameraCore>, Vector<GUIManager::GUICoreRenderData>>& newPerCameraData)
+	bool GUIRenderer::check(const CameraCore& camera)
 	{
 	{
-		bs_frame_mark();
+		auto iterFind = mPerCameraData.find(&camera);
+		return iterFind != mPerCameraData.end();
+	}
+
+	void GUIRenderer::render(const CameraCore& camera)
+	{
+		Vector<GUIManager::GUICoreRenderData>& renderData = mPerCameraData[&camera];
+
+		float invViewportWidth = 1.0f / (camera.getViewport()->getWidth() * 0.5f);
+		float invViewportHeight = 1.0f / (camera.getViewport()->getHeight() * 0.5f);
 
 
+		for (auto& entry : renderData)
 		{
 		{
-			// Assign new per camera data, and find if any cameras were added or removed
-			FrameSet<SPtr<CameraCore>> validCameras;
+			SPtr<GpuParamBlockBufferCore> buffer = mParamBlocks[entry.bufferIdx];
 
 
-			SPtr<CoreRenderer> activeRenderer = RendererManager::instance().getActive();
-			for (auto& newCameraData : newPerCameraData)
-			{
-				UINT32 idx = 0;
-				Vector<GUIManager::GUICoreRenderData>* renderData = nullptr;
-				for (auto& oldCameraData : mPerCameraData)
-				{
-					if (newCameraData.first == oldCameraData.first)
-					{
-						renderData = &oldCameraData.second;
-						validCameras.insert(oldCameraData.first);
-						break;
-					}
+			gGUISpriteParamBlockDef.gInvViewportWidth.set(buffer, invViewportWidth);
+			gGUISpriteParamBlockDef.gInvViewportHeight.set(buffer, invViewportHeight);
 
 
-					idx++;
-				}
+			buffer->flushToGPU();
+		}
 
 
-				if (renderData == nullptr)
-				{
-					SPtr<CameraCore> camera = newCameraData.first;
+		for (auto& entry : renderData)
+		{
+			// TODO - I shouldn't be re-applying the entire material for each entry, instead just check which programs
+			// changed, and apply only those + the modified constant buffers and/or texture.
 
 
-					auto insertedData = mPerCameraData.insert(std::make_pair(newCameraData.first, Vector<GUIManager::GUICoreRenderData>()));
-					renderData = &insertedData.first->second;
+			SPtr<GpuParamBlockBufferCore> buffer = mParamBlocks[entry.bufferIdx];
 
 
-					activeRenderer->registerRenderCallback(camera.get(), 30, std::bind(&GUIManagerCore::render, this, camera), true);
-					validCameras.insert(camera);
-				}
+			entry.material->render(entry.mesh, entry.texture, mSamplerState, buffer, entry.additionalData);
+		}
+	}
 
 
-				*renderData = newCameraData.second;
-			}
+	void GUIRenderer::updateData(const UnorderedMap<SPtr<CameraCore>, Vector<GUIManager::GUICoreRenderData>>& newPerCameraData)
+	{
+		bs_frame_mark();
 
 
-			FrameVector<SPtr<CameraCore>> cameraToRemove;
-			for (auto& cameraData : mPerCameraData)
-			{
-				auto iterFind = validCameras.find(cameraData.first);
-				if (iterFind == validCameras.end())
-					cameraToRemove.push_back(cameraData.first);
-			}
+		{
+			mPerCameraData.clear();
+			mReferencedCameras.clear();
 
 
-			for (auto& camera : cameraToRemove)
+			for (auto& newCameraData : newPerCameraData)
 			{
 			{
-				activeRenderer->unregisterRenderCallback(camera.get(), 30);
-				mPerCameraData.erase(camera);
+				SPtr<CameraCore> camera = newCameraData.first;
+
+				mPerCameraData.insert(std::make_pair(camera.get(), newCameraData.second));
+				mReferencedCameras.insert(camera);
 			}
 			}
 
 
 			// Allocate GPU buffers containing the material parameters
 			// Allocate GPU buffers containing the material parameters
@@ -1842,32 +1830,4 @@ namespace bs
 
 
 		bs_frame_clear();
 		bs_frame_clear();
 	}
 	}
-
-	void GUIManagerCore::render(const SPtr<CameraCore>& camera)
-	{
-		Vector<GUIManager::GUICoreRenderData>& renderData = mPerCameraData[camera];
-
-		float invViewportWidth = 1.0f / (camera->getViewport()->getWidth() * 0.5f);
-		float invViewportHeight = 1.0f / (camera->getViewport()->getHeight() * 0.5f);
-
-		for (auto& entry : renderData)
-		{
-			SPtr<GpuParamBlockBufferCore> buffer = mParamBlocks[entry.bufferIdx];
-
-			gGUISpriteParamBlockDef.gInvViewportWidth.set(buffer, invViewportWidth);
-			gGUISpriteParamBlockDef.gInvViewportHeight.set(buffer, invViewportHeight);
-
-			buffer->flushToGPU();
-		}
-
-		for (auto& entry : renderData)
-		{
-			// TODO - I shouldn't be re-applying the entire material for each entry, instead just check which programs
-			// changed, and apply only those + the modified constant buffers and/or texture.
-
-			SPtr<GpuParamBlockBufferCore> buffer = mParamBlocks[entry.bufferIdx];
-
-			entry.material->render(entry.mesh, entry.texture, mSamplerState, buffer, entry.additionalData);
-		}
-	}
 }
 }

+ 51 - 41
Source/RenderBeast/Source/BsRenderBeast.cpp

@@ -30,6 +30,7 @@
 #include "BsSkeleton.h"
 #include "BsSkeleton.h"
 #include "BsGpuBuffer.h"
 #include "BsGpuBuffer.h"
 #include "BsGpuParamsSet.h"
 #include "BsGpuParamsSet.h"
+#include "BsRendererExtension.h"
 #include "BsMeshData.h"
 #include "BsMeshData.h"
 
 
 using namespace std::placeholders;
 using namespace std::placeholders;
@@ -665,22 +666,18 @@ namespace bs
 		SPtr<RenderTargets> renderTargets = rendererCam->getRenderTargets();
 		SPtr<RenderTargets> renderTargets = rendererCam->getRenderTargets();
 		renderTargets->bindGBuffer();
 		renderTargets->bindGBuffer();
 
 
-		//// Trigger pre-scene callbacks
-		auto iterCameraCallbacks = mRenderCallbacks.find(camera);
-		if (iterCameraCallbacks != mRenderCallbacks.end())
+		//// Trigger pre-base-pass callbacks
+		auto iterRenderCallback = mCallbacks.begin();
+		while(iterRenderCallback != mCallbacks.end())
 		{
 		{
-			for (auto& callbackPair : iterCameraCallbacks->second)
-			{
-				const RenderCallbackData& callbackData = callbackPair.second;
-
-				if (callbackData.overlay)
-					continue;
-
-				if (callbackPair.first >= 0)
-					break;
+			RendererExtension* extension = *iterRenderCallback;
+			if (extension->getLocation() != RenderLocation::PreBasePass)
+				break;
+			
+			if (extension->check(*camera))
+				extension->render(*camera);
 
 
-				callbackData.callback();
-			}
+			++iterRenderCallback;
 		}
 		}
 
 
 		//// Render base pass
 		//// Render base pass
@@ -691,6 +688,19 @@ namespace bs
 			renderElement(*renderElem, iter->passIdx, iter->applyPass, frameInfo, viewProj);
 			renderElement(*renderElem, iter->passIdx, iter->applyPass, frameInfo, viewProj);
 		}
 		}
 
 
+		//// Trigger post-base-pass callbacks
+		while (iterRenderCallback != mCallbacks.end())
+		{
+			RendererExtension* extension = *iterRenderCallback;
+			if (extension->getLocation() != RenderLocation::PostBasePass)
+				break;
+
+			if (extension->check(*camera))
+				extension->render(*camera);
+
+			++iterRenderCallback;
+		}
+
 		renderTargets->bindSceneColor(true);
 		renderTargets->bindSceneColor(true);
 
 
 		//// Render light pass
 		//// Render light pass
@@ -760,36 +770,34 @@ namespace bs
 			renderElement(*renderElem, iter->passIdx, iter->applyPass, frameInfo, viewProj);
 			renderElement(*renderElem, iter->passIdx, iter->applyPass, frameInfo, viewProj);
 		}
 		}
 
 
-		// Render non-overlay post-scene callbacks
-		if (iterCameraCallbacks != mRenderCallbacks.end())
+		//// Trigger post-light-pass callbacks
+		while (iterRenderCallback != mCallbacks.end())
 		{
 		{
-			for (auto& callbackPair : iterCameraCallbacks->second)
-			{
-				const RenderCallbackData& callbackData = callbackPair.second;
+			RendererExtension* extension = *iterRenderCallback;
+			if (extension->getLocation() != RenderLocation::PostLightPass)
+				break;
 
 
-				if (callbackData.overlay || callbackPair.first < 0)
-					continue;
+			if (extension->check(*camera))
+				extension->render(*camera);
 
 
-				callbackData.callback();
-			}
+			++iterRenderCallback;
 		}
 		}
 
 
 		// TODO - If GBuffer has multiple samples, I should resolve them before post-processing
 		// TODO - If GBuffer has multiple samples, I should resolve them before post-processing
 		PostProcessing::instance().postProcess(renderTargets->getSceneColorRT(),
 		PostProcessing::instance().postProcess(renderTargets->getSceneColorRT(),
 			camera, rendererCam->getPPInfo(), frameInfo.delta);
 			camera, rendererCam->getPPInfo(), frameInfo.delta);
 
 
-		// Render overlay post-scene callbacks
-		if (iterCameraCallbacks != mRenderCallbacks.end())
+		//// Trigger overlay callbacks
+		while (iterRenderCallback != mCallbacks.end())
 		{
 		{
-			for (auto& callbackPair : iterCameraCallbacks->second)
-			{
-				const RenderCallbackData& callbackData = callbackPair.second;
+			RendererExtension* extension = *iterRenderCallback;
+			if (extension->getLocation() != RenderLocation::Overlay)
+				break;
 
 
-				if (!callbackData.overlay)
-					continue;
+			if (extension->check(*camera))
+				extension->render(*camera);
 
 
-				callbackData.callback();
-			}
+			++iterRenderCallback;
 		}
 		}
 
 
 		rendererCam->endRendering();
 		rendererCam->endRendering();
@@ -835,19 +843,21 @@ namespace bs
 			}
 			}
 		}
 		}
 
 
-		// Render overlay post-scene callbacks
-		auto iterCameraCallbacks = mRenderCallbacks.find(camera);
-		if (iterCameraCallbacks != mRenderCallbacks.end())
+		// Trigger overlay callbacks
+		auto iterRenderCallback = mCallbacks.begin();
+		while (iterRenderCallback != mCallbacks.end())
 		{
 		{
-			for (auto& callbackPair : iterCameraCallbacks->second)
+			RendererExtension* extension = *iterRenderCallback;
+			if (extension->getLocation() != RenderLocation::Overlay)
 			{
 			{
-				const RenderCallbackData& callbackData = callbackPair.second;
+				++iterRenderCallback;
+				continue;
+			}
 
 
-				if (!callbackData.overlay)
-					continue;
+			if (extension->check(*camera))
+				extension->render(*camera);
 
 
-				callbackData.callback();
-			}
+			++iterRenderCallback;
 		}
 		}
 
 
 		rendererCam->endRendering();
 		rendererCam->endRendering();