Selaa lähdekoodia

More work on preparing documentation for Doxygen generation

BearishSun 10 vuotta sitten
vanhempi
sitoutus
eb7c562d03

+ 251 - 274
BansheeCore/Include/BsBlendState.h

@@ -1,274 +1,251 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsResource.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Structure that describes blend states for a single render
-	 * 			target. Used internally by BLEND_STATE_DESC for initializing a BlendState.
-	 * 			
-	 * @see		BLEND_STATE_DESC
-	 * @see		BlendState
-	 */
-	struct BS_CORE_EXPORT RENDER_TARGET_BLEND_STATE_DESC
-	{
-		RENDER_TARGET_BLEND_STATE_DESC()
-			: blendEnable(false)
-			, srcBlend(BF_ONE)
-			, dstBlend(BF_ZERO)
-			, blendOp(BO_ADD)
-			, srcBlendAlpha(BF_ONE)
-			, dstBlendAlpha(BF_ZERO)
-			, blendOpAlpha(BO_ADD)
-			, renderTargetWriteMask(0xFF)
-		{ }
-
-		bool operator==(const RENDER_TARGET_BLEND_STATE_DESC& rhs) const;
-
-		bool blendEnable;
-		BlendFactor srcBlend;
-		BlendFactor dstBlend;
-		BlendOperation blendOp;
-		BlendFactor srcBlendAlpha;
-		BlendFactor dstBlendAlpha;
-		BlendOperation blendOpAlpha;
-		// Enable write to RGBA channels separately by setting first four bits (0 - R, 1 - G, 2 - B, 3 - A)
-		UINT8 renderTargetWriteMask;
-	};
-
-	/**
-	 * @brief	Structure that describes render pipeline blend states. Used for initializing
-	 * 			BlendState.
-	 * 			
-	 * @see		BlendState.
-	 */
-	struct BS_CORE_EXPORT BLEND_STATE_DESC
-	{
-		BLEND_STATE_DESC()
-			: alphaToCoverageEnable(false)
-			, independantBlendEnable(false)
-		{ }
-
-		bool operator==(const BLEND_STATE_DESC& rhs) const;
-
-		bool alphaToCoverageEnable;
-		bool independantBlendEnable;
-		RENDER_TARGET_BLEND_STATE_DESC renderTargetDesc[BS_MAX_MULTIPLE_RENDER_TARGETS];
-	};
-
-	/**
-	 * @brief	Information about a blend state.
-	 */
-	class BS_CORE_EXPORT BlendProperties
-	{
-	public:
-		BlendProperties(const BLEND_STATE_DESC& desc);
-
-		/**
-		 * @brief	Alpha to coverage allows you to perform blending without needing to worry about order of
-		 * 			rendering like regular blending does. It requires multi-sampling to be active in order to
-		 * 			work, and you need to supply an alpha texture that determines object transparency.
-		 *
-		 *			Blending is then performed by only using sub-samples covered by the alpha texture for the current
-		 *			pixel and combining them with sub-samples previously stored. 
-		 *			
-		 *			Be aware this is a limited technique only useful for certain situations. Unless you are having performance
-		 *			problems use regular blending.
-		 */
-		bool getAlphaToCoverageEnabled() const { return mData.alphaToCoverageEnable; }
-
-		/**
-		 * @brief	When not set, only the first render target blend descriptor will be used for all
-		 * 			render targets. If set each render target will use its own blend descriptor.
-		 */
-		bool getIndependantBlendEnable() const { return mData.independantBlendEnable; }
-
-		/**
-		 * @brief	Queries is blending enabled for the specified render target. Blending
-		 * 			allows you to combine the color from current and previous pixel based on
-		 * 			some value.
-		 */
-		bool getBlendEnabled(UINT32 renderTargetIdx) const;
-
-		/**
-		 * @brief	Determines what should the source blend factor be. This value determines
-		 * 			what will the color being generated currently be multiplied by.
-		 */
-		BlendFactor getSrcBlend(UINT32 renderTargetIdx) const;
-
-		/**
-		 * @brief	Determines what should the destination blend factor be. This value determines
-		 * 			what will the color already in render target be multiplied by.
-		 */
-		BlendFactor getDstBlend(UINT32 renderTargetIdx) const;
-
-		/**
-		 * @brief	Determines how are source and destination colors combined (after they are multiplied
-		 * 			by their respective blend factors).
-		 */
-		BlendOperation getBlendOperation(UINT32 renderTargetIdx) const;
-
-		/**
-		 * @brief	Determines what should the alpha source blend factor be. This value determines
-		 * 			what will the alpha value being generated currently be multiplied by.
-		 */
-		BlendFactor getAlphaSrcBlend(UINT32 renderTargetIdx) const;
-
-		/**
-		 * @brief	Determines what should the alpha destination blend factor be. This value determines
-		 * 			what will the alpha value already in render target be multiplied by.
-		 */
-		BlendFactor getAlphaDstBlend(UINT32 renderTargetIdx) const;
-
-		/**
-		 * @brief	Determines how are source and destination alpha values combined (after they are multiplied
-		 * 			by their respective blend factors).
-		 */
-		BlendOperation getAlphaBlendOperation(UINT32 renderTargetIdx) const;
-
-		/**
-		 * @brief	Render target write mask allows to choose which pixel components should the pixel shader
-		 * 			output.
-		 * 			
-		 *			Only the first four bits are used. First bit representing red, second green, third blue and
-		 *			fourth alpha value. Set bits means pixel shader will output those channels.
-		 */
-		UINT8 getRenderTargetWriteMask(UINT32 renderTargetIdx) const;
-
-		/**
-		 * @brief	Returns the hash value generated from the blend state properties.
-		 */
-		UINT64 getHash() const { return mHash; }
-
-	protected:
-		friend class BlendState;
-		friend class BlendStateCore;
-		friend class BlendStateRTTI;
-
-		BLEND_STATE_DESC mData;
-		UINT64 mHash;
-	};
-
-/**
-	 * @brief	Core thread version of a blend state.
-	 *
-	 * @see		BlendState
-	 *
-	 * @note	Core thread.
-	 */
-	class BS_CORE_EXPORT BlendStateCore : public CoreObjectCore
-	{
-	public:
-		virtual ~BlendStateCore();
-
-		/**
-		 * @brief	Returns information about the blend state.
-		 */
-		const BlendProperties& getProperties() const;
-
-		/**
-		 * @brief	Returns a unique state ID. Only the lowest 10 bits are used.
-		 */
-		UINT32 getId() const { return mId; }
-
-		/**
-		 * @brief	Returns the default blend state that you may use
-		 * 			when no other is available.
-		 */
-		static const SPtr<BlendStateCore>& getDefault();
-
-	protected:
-		friend class RenderStateCoreManager;
-
-		BlendStateCore(const BLEND_STATE_DESC& desc, UINT32 id);
-
-		/**
-		 * @copydoc	CoreObjectCore::initialize
-		 */
-		void initialize() override;
-
-		/**
-		 * @brief	Creates any API-specific state objects.
-		 */
-		virtual void createInternal() { }
-
-		BlendProperties mProperties;
-		UINT32 mId;
-	};
-
-	/**
-	 * @brief	Render system pipeline state that allows you to modify how an object is rendered. 
-	 * 			More exactly this state allows to you to control how is a rendered
-	 * 			object blended with any previously renderer objects.
-	 * 			
-	 * @note	Blend states are immutable. Sim thread only.
-	 */
-	class BS_CORE_EXPORT BlendState : public IReflectable, public CoreObject
-	{
-	public:
-		virtual ~BlendState();
-
-		/**
-		 * @brief	Returns information about a blend state.
-		 */
-		const BlendProperties& getProperties() const;
-
-		/**
-		 * @brief	Retrieves a core implementation of the sampler state usable only from the
-		 *			core thread.
-		 */
-		SPtr<BlendStateCore> getCore() const;
-
-		/**
-		 * @brief	Creates a new blend state using the specified blend state description structure.
-		 */
-		static BlendStatePtr create(const BLEND_STATE_DESC& desc);
-
-		/**
-		 * @brief	Returns the default blend state that you may use
-		 * 			when no other is available.
-		 */
-		static const BlendStatePtr& getDefault();
-
-		/**
-		 * @brief	Generates a hash value from a blend state descriptor.
-		 */
-		static UINT64 generateHash(const BLEND_STATE_DESC& desc);
-
-	protected:
-		friend class RenderStateManager;
-
-		BlendState(const BLEND_STATE_DESC& desc);
-
-		/**
-		 * @copydoc	CoreObjectCore::createCore
-		 */
-		SPtr<CoreObjectCore> createCore() const override;
-
-		BlendProperties mProperties;
-		mutable UINT32 mId;
-
-		/************************************************************************/
-		/* 								RTTI		                     		*/
-		/************************************************************************/
-
-	public:
-		friend class BlendStateRTTI;
-		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;	
-	};
-}
-
-/**
- * @brief	Hash value generator for BLEND_STATE_DESC.
- */
-template<>
-struct std::hash<BansheeEngine::BLEND_STATE_DESC>
-{
-	size_t operator()(const BansheeEngine::BLEND_STATE_DESC& value) const
-	{
-		return (size_t)BansheeEngine::BlendState::generateHash(value);
-	}
-};
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsResource.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup RenderAPI
+	 *  @{
+	 */
+
+	/**
+	 * Structure that describes blend states for a single render target. Used internally by BLEND_STATE_DESC for 
+	 * initializing a BlendState.
+	 * 			
+	 * @see		BLEND_STATE_DESC
+	 * @see		BlendState
+	 */
+	struct BS_CORE_EXPORT RENDER_TARGET_BLEND_STATE_DESC
+	{
+		RENDER_TARGET_BLEND_STATE_DESC()
+			: blendEnable(false)
+			, srcBlend(BF_ONE)
+			, dstBlend(BF_ZERO)
+			, blendOp(BO_ADD)
+			, srcBlendAlpha(BF_ONE)
+			, dstBlendAlpha(BF_ZERO)
+			, blendOpAlpha(BO_ADD)
+			, renderTargetWriteMask(0xFF)
+		{ }
+
+		bool operator==(const RENDER_TARGET_BLEND_STATE_DESC& rhs) const;
+
+		bool blendEnable;
+		BlendFactor srcBlend;
+		BlendFactor dstBlend;
+		BlendOperation blendOp;
+		BlendFactor srcBlendAlpha;
+		BlendFactor dstBlendAlpha;
+		BlendOperation blendOpAlpha;
+		// Enable write to RGBA channels separately by setting first four bits (0 - R, 1 - G, 2 - B, 3 - A)
+		UINT8 renderTargetWriteMask;
+	};
+
+	/** Structure that describes render pipeline blend states. Used for initializing BlendState. */
+	struct BS_CORE_EXPORT BLEND_STATE_DESC
+	{
+		BLEND_STATE_DESC()
+			: alphaToCoverageEnable(false)
+			, independantBlendEnable(false)
+		{ }
+
+		bool operator==(const BLEND_STATE_DESC& rhs) const;
+
+		bool alphaToCoverageEnable;
+		bool independantBlendEnable;
+		RENDER_TARGET_BLEND_STATE_DESC renderTargetDesc[BS_MAX_MULTIPLE_RENDER_TARGETS];
+	};
+
+	/** Properties of a BlendState. Shared between sim and core thread versions of BlendState. */
+	class BS_CORE_EXPORT BlendProperties
+	{
+	public:
+		BlendProperties(const BLEND_STATE_DESC& desc);
+
+		/**
+		 * Alpha to coverage allows you to perform blending without needing to worry about order of rendering like regular 
+		 * blending does. It requires multi-sampling to be active in order to work, and you need to supply an alpha texture
+		 * that determines object transparency.
+		 *
+		 * Blending is then performed by only using sub-samples covered by the alpha texture for the current pixel and 
+		 * combining them with sub-samples previously stored. 
+		 *			
+		 * Be aware this is a limited technique only useful for certain situations. Unless you are having performance 
+		 * problems use regular blending.
+		 */
+		bool getAlphaToCoverageEnabled() const { return mData.alphaToCoverageEnable; }
+
+		/**
+		 * When not set, only the first render target blend descriptor will be used for all render targets. If set each 
+		 * render target will use its own blend descriptor.
+		 */
+		bool getIndependantBlendEnable() const { return mData.independantBlendEnable; }
+
+		/**
+		 * Queries is blending enabled for the specified render target. Blending allows you to combine the color from 
+		 * current and previous pixel based on some value.
+		 */
+		bool getBlendEnabled(UINT32 renderTargetIdx) const;
+
+		/**
+		 * Determines what should the source blend factor be. This value determines what will the color being generated 
+		 * currently be multiplied by.
+		 */
+		BlendFactor getSrcBlend(UINT32 renderTargetIdx) const;
+
+		/**
+		 * Determines what should the destination blend factor be. This value determines what will the color already in 
+		 * render target be multiplied by.
+		 */
+		BlendFactor getDstBlend(UINT32 renderTargetIdx) const;
+
+		/**
+		 * Determines how are source and destination colors combined (after they are multiplied by their respective blend 
+		 * factors).
+		 */
+		BlendOperation getBlendOperation(UINT32 renderTargetIdx) const;
+
+		/**
+		 * Determines what should the alpha source blend factor be. This value determines what will the alpha value being 
+		 * generated currently be multiplied by.
+		 */
+		BlendFactor getAlphaSrcBlend(UINT32 renderTargetIdx) const;
+
+		/**
+		 * Determines what should the alpha destination blend factor be. This value determines what will the alpha value 
+		 * already in render target be multiplied by.
+		 */
+		BlendFactor getAlphaDstBlend(UINT32 renderTargetIdx) const;
+
+		/**
+		 * Determines how are source and destination alpha values combined (after they are multiplied by their respective
+		 * blend factors).
+		 */
+		BlendOperation getAlphaBlendOperation(UINT32 renderTargetIdx) const;
+
+		/**
+		 * Render target write mask allows to choose which pixel components should the pixel shader output.
+		 * 			
+		 * Only the first four bits are used. First bit representing red, second green, third blue and fourth alpha value. 
+		 * Set bits means pixel shader will output those channels.
+		 */
+		UINT8 getRenderTargetWriteMask(UINT32 renderTargetIdx) const;
+
+		/** Returns the hash value generated from the blend state properties. */
+		UINT64 getHash() const { return mHash; }
+
+	protected:
+		friend class BlendState;
+		friend class BlendStateCore;
+		friend class BlendStateRTTI;
+
+		BLEND_STATE_DESC mData;
+		UINT64 mHash;
+	};
+
+	/** @cond INTERNAL */
+
+	/**
+	 * Core thread version of BlendState.
+	 *
+	 * @note	Core thread.
+	 */
+	class BS_CORE_EXPORT BlendStateCore : public CoreObjectCore
+	{
+	public:
+		virtual ~BlendStateCore();
+
+		/** Returns information about the blend state. */
+		const BlendProperties& getProperties() const;
+
+		/** Returns a unique state ID. Only the lowest 10 bits are used. */
+		UINT32 getId() const { return mId; }
+
+		/**	Returns the default blend state that you may use when no other is available. */
+		static const SPtr<BlendStateCore>& getDefault();
+
+	protected:
+		friend class RenderStateCoreManager;
+
+		BlendStateCore(const BLEND_STATE_DESC& desc, UINT32 id);
+
+		/** @copydoc CoreObjectCore::initialize */
+		void initialize() override;
+
+		/**	Creates any API-specific state objects. */
+		virtual void createInternal() { }
+
+		BlendProperties mProperties;
+		UINT32 mId;
+	};
+
+	/** @endcond */
+
+	/**
+	 * Render system pipeline state that allows you to modify how an object is rendered. More exactly this state allows to 
+	 * you to control how is a rendered object blended with any previously renderer objects.
+	 * 			
+	 * @note	Blend states are immutable. Sim thread only.
+	 */
+	class BS_CORE_EXPORT BlendState : public IReflectable, public CoreObject
+	{
+	public:
+		virtual ~BlendState();
+
+		/**	Returns information about a blend state. */
+		const BlendProperties& getProperties() const;
+
+		/** Retrieves a core implementation of the sampler state usable only from the core thread. */
+		SPtr<BlendStateCore> getCore() const;
+
+		/**	Creates a new blend state using the specified blend state description structure. */
+		static BlendStatePtr create(const BLEND_STATE_DESC& desc);
+
+		/**	Returns the default blend state that you may use when no other is available. */
+		static const BlendStatePtr& getDefault();
+
+		/**	Generates a hash value from a blend state descriptor. */
+		static UINT64 generateHash(const BLEND_STATE_DESC& desc);
+
+	protected:
+		friend class RenderStateManager;
+
+		BlendState(const BLEND_STATE_DESC& desc);
+
+		/** @copydoc CoreObjectCore::createCore */
+		SPtr<CoreObjectCore> createCore() const override;
+
+		BlendProperties mProperties;
+		mutable UINT32 mId;
+
+		/************************************************************************/
+		/* 								RTTI		                     		*/
+		/************************************************************************/
+
+	public:
+		friend class BlendStateRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		virtual RTTITypeBase* getRTTI() const override;	
+	};
+
+	/** @} */
+}
+
+/** @cond STDLIB */
+/** @addtogroup RenderAPI
+ *  @{
+ */
+
+/**	Hash value generator for BLEND_STATE_DESC. */
+template<>
+struct std::hash<BansheeEngine::BLEND_STATE_DESC>
+{
+	size_t operator()(const BansheeEngine::BLEND_STATE_DESC& value) const
+	{
+		return (size_t)BansheeEngine::BlendState::generateHash(value);
+	}
+};
+
+/** @} */
+/** @endcond */

+ 12 - 0
BansheeCore/Include/BsCorePrerequisites.h

@@ -28,6 +28,18 @@
  *	Functionality for dealing with materials, shaders, and in general how objects are rendered.
  */
 
+/** @defgroup Platform Platform
+ *	Functionality specific for some platform (e.g. Windows, Mac).
+ */
+
+ /** @defgroup Profiling Profiling
+  *	Functionality for measuring CPU and GPU execution times and memory usage.
+  */
+
+/** @defgroup RenderAPI RenderAPI
+  *	Functionality for interacting with underlying render API (e.g. DirectX, OpenGL).
+  */
+
 /** @} */
 
 #define BS_MAX_MULTIPLE_RENDER_TARGETS 8

+ 242 - 277
BansheeCore/Include/BsDepthStencilState.h

@@ -1,277 +1,242 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsIReflectable.h"
-#include "BsCoreObject.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Descriptor structured used for initializing DepthStencilState.
-	 *
-	 * @see		DepthStencilState
-	 */
-	struct BS_CORE_EXPORT DEPTH_STENCIL_STATE_DESC
-	{
-		DEPTH_STENCIL_STATE_DESC()
-			: depthReadEnable(true)
-			, depthWriteEnable(true)
-			, depthComparisonFunc(CMPF_LESS)
-			, stencilEnable(false)
-			, stencilReadMask(0xFF)
-			, stencilWriteMask(0xFF)
-			, frontStencilFailOp(SOP_KEEP)
-			, frontStencilZFailOp(SOP_KEEP)
-			, frontStencilPassOp(SOP_KEEP)
-			, frontStencilComparisonFunc(CMPF_ALWAYS_PASS)
-			, backStencilFailOp(SOP_KEEP)
-			, backStencilZFailOp(SOP_KEEP)
-			, backStencilPassOp(SOP_KEEP)
-			, backStencilComparisonFunc(CMPF_ALWAYS_PASS)
-		{ }
-
-		bool operator==(const DEPTH_STENCIL_STATE_DESC& rhs) const;
-
-		bool depthReadEnable;
-		bool depthWriteEnable;
-		CompareFunction depthComparisonFunc;
-
-		bool stencilEnable;
-		UINT8 stencilReadMask;
-		UINT8 stencilWriteMask;
-
-		StencilOperation frontStencilFailOp;
-		StencilOperation frontStencilZFailOp;
-		StencilOperation frontStencilPassOp;
-		CompareFunction frontStencilComparisonFunc;
-
-		StencilOperation backStencilFailOp;
-		StencilOperation backStencilZFailOp;
-		StencilOperation backStencilPassOp;
-		CompareFunction backStencilComparisonFunc;
-	};
-
-	BS_ALLOW_MEMCPY_SERIALIZATION(DEPTH_STENCIL_STATE_DESC);
-
-	/**
-	 * @brief	Information about a depth stencil state.
-	 */
-	class BS_CORE_EXPORT DepthStencilProperties
-	{
-	public:
-		DepthStencilProperties(const DEPTH_STENCIL_STATE_DESC& desc);
-
-		/**
-		 * @brief	If enabled, any pixel about to be written will be tested against the depth value
-		 *			currently in the buffer. If the depth test passes (depending on the set value
-		 *			and chosen depth comparison function), that pixel is written and depth is
-		 *			updated (if depth write is enabled).
-		 */
-		bool getDepthReadEnable() const { return mData.depthReadEnable; }
-
-		/**
-		 * @brief	If enabled rendering pixels will update the depth buffer value. 
-		 */
-		bool getDepthWriteEnable() const { return mData.depthWriteEnable; }
-
-		/**
-		 * @brief	Determines what operation should the renderer use when comparing previous and 
-		 *			current depth value. If the operation passes, pixel with the current depth
-		 *			value will be considered visible.
-		 */
-		CompareFunction getDepthComparisonFunc() const { return mData.depthComparisonFunc; }
-
-		/**
-		 * @brief	If true then stencil buffer will also be updated when a pixel is written, and
-		 *			pixels will be tested against the stencil buffer before rendering.
-		 */
-		bool getStencilEnable() const { return mData.stencilEnable; }
-
-		/**
-		 * @brief	Mask to apply to any value read from the stencil buffer, before applying the
-		 *			stencil comparison function.
-		 */
-		UINT8 getStencilReadMask() const { return mData.stencilReadMask; }
-
-		/**
-		 * @brief	Mask to apply to any value about to be written in the stencil buffer.
-		 */
-		UINT8 getStencilWriteMask() const { return mData.stencilWriteMask; }
-
-		/**
-		 * @brief	Operation that happens when stencil comparison function fails on a front facing polygon.
-		 */
-		StencilOperation getStencilFrontFailOp() const { return mData.frontStencilFailOp; }
-
-		/**
-		* @brief	Operation that happens when stencil comparison function passes but depth test fails
-		*			on a front facing polygon.
-		*/
-		StencilOperation getStencilFrontZFailOp() const { return mData.frontStencilZFailOp; }
-
-		/**
-		* @brief	Operation that happens when stencil comparison function passes on a front facing polygon.
-		*/
-		StencilOperation getStencilFrontPassOp() const { return mData.frontStencilPassOp; }
-
-		/**
-		 * @brief	Stencil comparison function used for front facing polygons. Stencil buffer will be modified according
-		 *			to previously set stencil operations depending whether this comparison passes or fails.
-		 */
-		CompareFunction getStencilFrontCompFunc() const { return mData.frontStencilComparisonFunc; }
-
-		/**
-		* @brief	Operation that happens when stencil comparison function fails on a back facing polygon.
-		*/
-		StencilOperation getStencilBackFailOp() const { return mData.backStencilFailOp; }
-
-		/**
-		* @brief	Operation that happens when stencil comparison function passes but depth test fails
-		*			on a back facing polygon.
-		*/
-		StencilOperation getStencilBackZFailOp() const { return mData.backStencilZFailOp; }
-
-		/**
-		* @brief	Operation that happens when stencil comparison function passes on a back facing polygon.
-		*/
-		StencilOperation getStencilBackPassOp() const { return mData.backStencilPassOp; }
-
-		/**
-		* @brief	Stencil comparison function used for back facing polygons. Stencil buffer will be modified according
-		*			to previously set stencil operations depending whether this comparison passes or fails.
-		*/
-		CompareFunction getStencilBackCompFunc() const { return mData.backStencilComparisonFunc; }
-
-		/**
-		 * @brief	Returns the hash value generated from the depth-stencil state properties.
-		 */
-		UINT64 getHash() const { return mHash; }
-
-	protected:
-		friend class DepthStencilState;
-		friend class DepthStencilStateCore;
-		friend class DepthStencilStateRTTI;
-
-		DEPTH_STENCIL_STATE_DESC mData;
-		UINT64 mHash;
-	};
-
-	/**
-	 * @brief	Core thread version of the depth stencil state.
-	 *
-	 * @see		DepthStencilState
-	 *
-	 * @note	Core thread.
-	 */
-	class BS_CORE_EXPORT DepthStencilStateCore : public CoreObjectCore
-	{
-	public:
-		virtual ~DepthStencilStateCore();
-
-		/**
-		 * @brief	Returns information about the depth stencil state.
-		 */
-		const DepthStencilProperties& getProperties() const;
-
-		/**
-		 * @brief	Returns a unique state ID. Only the lowest 10 bits are used.
-		 */
-		UINT32 getId() const { return mId; }
-
-		/**
-		 * @brief	Returns the default depth stencil state that you may use when no other is available.
-		 */
-		static const SPtr<DepthStencilStateCore>& getDefault();
-
-	protected:
-		friend class RenderStateCoreManager;
-
-		DepthStencilStateCore(const DEPTH_STENCIL_STATE_DESC& desc, UINT32 id);
-
-		/**
-		 * @copydoc	CoreObjectCore::initialize
-		 */
-		void initialize() override;
-
-		/**
-		 * @brief	Creates any API-specific state objects.
-		 */
-		virtual void createInternal() { }
-
-		DepthStencilProperties mProperties;
-		UINT32 mId;
-	};
-
-	/**
-	 * @brief	Render system pipeline state that allows you to modify how an object is rendered.
-	 * 			More exactly this state allows to you to control how are depth and stencil buffers
-	 *			modified upon rendering.
-	 *
-	 * @note	Depth stencil states are immutable. Sim thread only.
-	 */
-	class BS_CORE_EXPORT DepthStencilState : public IReflectable, public CoreObject
-	{
-	public:
-		virtual ~DepthStencilState();
-
-		/**
-		 * @brief	Returns information about the depth stencil state.
-		 */
-		const DepthStencilProperties& getProperties() const;
-
-		/**
-		 * @brief	Retrieves a core implementation of a sampler state usable only from the
-		 *			core thread.
-		 */
-		SPtr<DepthStencilStateCore> getCore() const;
-
-		/**
-		 * @brief	Creates a new depth stencil state using the specified depth stencil state description structure.
-		 */
-		static DepthStencilStatePtr create(const DEPTH_STENCIL_STATE_DESC& desc);
-
-		/**
-		 * @brief	Returns the default depth stencil state that you may use when no other is available.
-		 */
-		static const DepthStencilStatePtr& getDefault();
-
-		/**
-		 * @brief	Generates a hash value from a depth-stencil state descriptor.
-		 */
-		static UINT64 generateHash(const DEPTH_STENCIL_STATE_DESC& desc);
-
-	protected:
-		friend class RenderStateManager;
-
-		DepthStencilState(const DEPTH_STENCIL_STATE_DESC& desc);
-
-		/**
-		 * @copydoc	CoreObjectCore::createCore
-		 */
-		SPtr<CoreObjectCore> createCore() const override;
-
-		DepthStencilProperties mProperties;
-		mutable UINT32 mId;
-
-		/************************************************************************/
-		/* 								RTTI		                     		*/
-		/************************************************************************/
-
-	public:
-		friend class DepthStencilStateRTTI;
-		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;	
-	};
-}
-
-/**
- * @brief	Hash value generator for DEPTH_STENCIL_STATE_DESC.
- */
-template<>
-struct std::hash<BansheeEngine::DEPTH_STENCIL_STATE_DESC>
-{
-	size_t operator()(const BansheeEngine::DEPTH_STENCIL_STATE_DESC& value) const
-	{
-		return (size_t)BansheeEngine::DepthStencilState::generateHash(value);
-	}
-};
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsIReflectable.h"
+#include "BsCoreObject.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup RenderAPI
+	 *  @{
+	 */
+
+	/**
+	 * Descriptor structured used for initializing DepthStencilState.
+	 *
+	 * @see		DepthStencilState
+	 */
+	struct BS_CORE_EXPORT DEPTH_STENCIL_STATE_DESC
+	{
+		DEPTH_STENCIL_STATE_DESC()
+			: depthReadEnable(true)
+			, depthWriteEnable(true)
+			, depthComparisonFunc(CMPF_LESS)
+			, stencilEnable(false)
+			, stencilReadMask(0xFF)
+			, stencilWriteMask(0xFF)
+			, frontStencilFailOp(SOP_KEEP)
+			, frontStencilZFailOp(SOP_KEEP)
+			, frontStencilPassOp(SOP_KEEP)
+			, frontStencilComparisonFunc(CMPF_ALWAYS_PASS)
+			, backStencilFailOp(SOP_KEEP)
+			, backStencilZFailOp(SOP_KEEP)
+			, backStencilPassOp(SOP_KEEP)
+			, backStencilComparisonFunc(CMPF_ALWAYS_PASS)
+		{ }
+
+		bool operator==(const DEPTH_STENCIL_STATE_DESC& rhs) const;
+
+		bool depthReadEnable;
+		bool depthWriteEnable;
+		CompareFunction depthComparisonFunc;
+
+		bool stencilEnable;
+		UINT8 stencilReadMask;
+		UINT8 stencilWriteMask;
+
+		StencilOperation frontStencilFailOp;
+		StencilOperation frontStencilZFailOp;
+		StencilOperation frontStencilPassOp;
+		CompareFunction frontStencilComparisonFunc;
+
+		StencilOperation backStencilFailOp;
+		StencilOperation backStencilZFailOp;
+		StencilOperation backStencilPassOp;
+		CompareFunction backStencilComparisonFunc;
+	};
+
+	/** @cond SPECIALIZATIONS */
+	BS_ALLOW_MEMCPY_SERIALIZATION(DEPTH_STENCIL_STATE_DESC);
+	/** @endcond */
+
+	/** Properties of DepthStencilState. Shared between sim and core thread versions of DepthStencilState. */
+	class BS_CORE_EXPORT DepthStencilProperties
+	{
+	public:
+		DepthStencilProperties(const DEPTH_STENCIL_STATE_DESC& desc);
+
+		/**
+		 * If enabled, any pixel about to be written will be tested against the depth value currently in the buffer. If the 
+		 * depth test passes (depending on the set valueand chosen depth comparison function), that pixel is written and 
+		 * depth is updated (if depth write is enabled).
+		 */
+		bool getDepthReadEnable() const { return mData.depthReadEnable; }
+
+		/** If enabled rendering pixels will update the depth buffer value. */
+		bool getDepthWriteEnable() const { return mData.depthWriteEnable; }
+
+		/**
+		 * Determines what operation should the renderer use when comparing previous and current depth value. If the 
+		 * operation passes, pixel with the current depth value will be considered visible.
+		 */
+		CompareFunction getDepthComparisonFunc() const { return mData.depthComparisonFunc; }
+
+		/**
+		 * If true then stencil buffer will also be updated when a pixel is written, and pixels will be tested against 
+		 * the stencil buffer before rendering.
+		 */
+		bool getStencilEnable() const { return mData.stencilEnable; }
+
+		/** Mask to apply to any value read from the stencil buffer, before applying the stencil comparison function. */
+		UINT8 getStencilReadMask() const { return mData.stencilReadMask; }
+
+		/**	Mask to apply to any value about to be written in the stencil buffer. */
+		UINT8 getStencilWriteMask() const { return mData.stencilWriteMask; }
+
+		/**	Operation that happens when stencil comparison function fails on a front facing polygon. */
+		StencilOperation getStencilFrontFailOp() const { return mData.frontStencilFailOp; }
+
+		/** Operation that happens when stencil comparison function passes but depth test fails on a front facing polygon. */
+		StencilOperation getStencilFrontZFailOp() const { return mData.frontStencilZFailOp; }
+
+		/**	Operation that happens when stencil comparison function passes on a front facing polygon. */
+		StencilOperation getStencilFrontPassOp() const { return mData.frontStencilPassOp; }
+
+		/**
+		 * Stencil comparison function used for front facing polygons. Stencil buffer will be modified according to 
+		 * previously set stencil operations depending whether this comparison passes or fails.
+		 */
+		CompareFunction getStencilFrontCompFunc() const { return mData.frontStencilComparisonFunc; }
+
+		/** Operation that happens when stencil comparison function fails on a back facing polygon. */
+		StencilOperation getStencilBackFailOp() const { return mData.backStencilFailOp; }
+
+		/** Operation that happens when stencil comparison function passes but depth test fails on a back facing polygon. */
+		StencilOperation getStencilBackZFailOp() const { return mData.backStencilZFailOp; }
+
+		/**	Operation that happens when stencil comparison function passes on a back facing polygon. */
+		StencilOperation getStencilBackPassOp() const { return mData.backStencilPassOp; }
+
+		/**
+		 * Stencil comparison function used for back facing polygons. Stencil buffer will be modified according	to 
+		 * previously set stencil operations depending whether this comparison passes or fails.
+		 */
+		CompareFunction getStencilBackCompFunc() const { return mData.backStencilComparisonFunc; }
+
+		/** Returns the hash value generated from the depth-stencil state properties. */
+		UINT64 getHash() const { return mHash; }
+
+	protected:
+		friend class DepthStencilState;
+		friend class DepthStencilStateCore;
+		friend class DepthStencilStateRTTI;
+
+		DEPTH_STENCIL_STATE_DESC mData;
+		UINT64 mHash;
+	};
+
+	/** @cond INTERNAL */
+
+	/**
+	 * Core thread version of DepthStencilState.
+	 *
+	 * @note	Core thread.
+	 */
+	class BS_CORE_EXPORT DepthStencilStateCore : public CoreObjectCore
+	{
+	public:
+		virtual ~DepthStencilStateCore();
+
+		/**	Returns information about the depth stencil state. */
+		const DepthStencilProperties& getProperties() const;
+
+		/**	Returns a unique state ID. Only the lowest 10 bits are used. */
+		UINT32 getId() const { return mId; }
+
+		/**	Returns the default depth stencil state that you may use when no other is available. */
+		static const SPtr<DepthStencilStateCore>& getDefault();
+
+	protected:
+		friend class RenderStateCoreManager;
+
+		DepthStencilStateCore(const DEPTH_STENCIL_STATE_DESC& desc, UINT32 id);
+
+		/** @copydoc CoreObjectCore::initialize */
+		void initialize() override;
+
+		/**	Creates any API-specific state objects. */
+		virtual void createInternal() { }
+
+		DepthStencilProperties mProperties;
+		UINT32 mId;
+	};
+
+	/** @endcond */
+
+	/**
+	 * Render system pipeline state that allows you to modify how an object is rendered. More exactly this state allows to 
+	 * you to control how are depth and stencil buffers modified upon rendering.
+	 *
+	 * @note	Depth stencil states are immutable. Sim thread only.
+	 */
+	class BS_CORE_EXPORT DepthStencilState : public IReflectable, public CoreObject
+	{
+	public:
+		virtual ~DepthStencilState();
+
+		/**	Returns information about the depth stencil state. */
+		const DepthStencilProperties& getProperties() const;
+
+		/**	Retrieves a core implementation of a sampler state usable only from the core thread. */
+		SPtr<DepthStencilStateCore> getCore() const;
+
+		/**	Creates a new depth stencil state using the specified depth stencil state description structure. */
+		static DepthStencilStatePtr create(const DEPTH_STENCIL_STATE_DESC& desc);
+
+		/**	Returns the default depth stencil state that you may use when no other is available. */
+		static const DepthStencilStatePtr& getDefault();
+
+		/**	Generates a hash value from a depth-stencil state descriptor. */
+		static UINT64 generateHash(const DEPTH_STENCIL_STATE_DESC& desc);
+
+	protected:
+		friend class RenderStateManager;
+
+		DepthStencilState(const DEPTH_STENCIL_STATE_DESC& desc);
+
+		/** @copydoc CoreObjectCore::createCore */
+		SPtr<CoreObjectCore> createCore() const override;
+
+		DepthStencilProperties mProperties;
+		mutable UINT32 mId;
+
+		/************************************************************************/
+		/* 								RTTI		                     		*/
+		/************************************************************************/
+
+	public:
+		friend class DepthStencilStateRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		virtual RTTITypeBase* getRTTI() const override;	
+	};
+
+	/** @} */
+}
+
+/** @cond STDLIB */
+/** @addtogroup RenderAPI
+ *  @{
+ */
+
+/**	Hash value generator for DEPTH_STENCIL_STATE_DESC. */
+template<>
+struct std::hash<BansheeEngine::DEPTH_STENCIL_STATE_DESC>
+{
+	size_t operator()(const BansheeEngine::DEPTH_STENCIL_STATE_DESC& value) const
+	{
+		return (size_t)BansheeEngine::DepthStencilState::generateHash(value);
+	}
+};
+
+/** @} */
+/** @endcond */

+ 25 - 25
BansheeCore/Include/BsDrawOps.h

@@ -1,26 +1,26 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Describes operation that will be used for rendering a certain
-	 *			set of vertices.
-	 */
-	enum DrawOperationType 
-	{
-		DOT_POINT_LIST = 1,
-		DOT_LINE_LIST = 2,
-		DOT_LINE_STRIP = 3,
-		DOT_TRIANGLE_LIST = 4,
-		DOT_TRIANGLE_STRIP = 5,
-		DOT_TRIANGLE_FAN = 6
-	};
-
-	/**
-	* @brief	Converts the number of vertices to number of primitives
-	* 			based on the specified draw operation.
-	*/
-	UINT32 BS_CORE_EXPORT vertexCountToPrimCount(DrawOperationType type, UINT32 elementCount);
+#pragma once
+
+#include "BsCorePrerequisites.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup RenderAPI
+	 *  @{
+	 */
+
+	/** Describes operation that will be used for rendering a certain set of vertices. */
+	enum DrawOperationType 
+	{
+		DOT_POINT_LIST = 1,
+		DOT_LINE_LIST = 2,
+		DOT_LINE_STRIP = 3,
+		DOT_TRIANGLE_LIST = 4,
+		DOT_TRIANGLE_STRIP = 5,
+		DOT_TRIANGLE_FAN = 6
+	};
+
+	/** Converts the number of vertices to number of primitives based on the specified draw operation. */
+	UINT32 BS_CORE_EXPORT vertexCountToPrimCount(DrawOperationType type, UINT32 elementCount);
+
+	/** @} */
 }

+ 424 - 466
BansheeCore/Include/BsPlatform.h

@@ -1,467 +1,425 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsInputFwd.h"
-#include "BsVector2I.h"
-#include "BsRect2I.h"
-#include "BsEvent.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Contains values representing default
-	 *			mouse cursor types.
-	 */
-	enum class PlatformCursorType
-	{
-		Arrow,
-		Wait,
-		IBeam,
-		Help,
-		Hand,
-		SizeAll,
-		SizeNESW,
-		SizeNS,
-		SizeNWSE,
-		SizeWE
-	};
-
-	/**
-	 * @brief	Contains values reprenting window non client areas.
-	 *
-	 * @note	These are used for things like resize/move and tell the OS
-	 *			where each of those areas are on our window.
-	 */
-	enum class NonClientAreaBorderType
-	{
-		TopLeft,
-		Top,
-		TopRight,
-		Left,
-		Right,
-		BottomLeft,
-		Bottom,
-		BottomRight
-	};
-
-	/**
-	 * @brief	Types of mouse buttons provided by the OS.
-	 */
-	enum class OSMouseButton
-	{
-		Left, Middle, Right, Count
-	};
-
-	/**
-	 * @brief	Describes pointer (mouse, touch) states as reported
-	 *			by the OS.
-	 */
-	struct BS_CORE_EXPORT OSPointerButtonStates
-	{
-		OSPointerButtonStates()
-		{
-			mouseButtons[0] = false;
-			mouseButtons[1] = false;
-			mouseButtons[2] = false;
-
-			shift = false;
-			ctrl = false;
-		}
-
-		bool mouseButtons[OSMouseButton::Count];
-		bool shift, ctrl;
-	};
-
-	/**
-	 * @brief	Type of drop event type. This is used
-	 *			when dragging items over drop targets.
-	 */
-	enum class OSDropType
-	{
-		FileList,
-		None
-	};
-
-	/**
-	 * @brief	Drop targets allow you to register a certain portion of a window as a drop target that
-	 *			accepts certain drop types from the OS (platform) specific drag and drop system. Accepted 
-	 *			drop types are provided by the OS and include things like file and item dragging.
-	 *
-	 *			You will receive events with the specified drop area as long as it is active.
-	 */
-	class BS_CORE_EXPORT OSDropTarget
-	{
-	public:
-		/**
-		 * @brief	Triggered when a pointer is being dragged over the drop area.
-		 *			Provides window coordinates of the pointer position.
-		 */
-		Event<void(INT32 x, INT32 y)> onDragOver;
-
-		/**
-		 * @brief	Triggered when the user completes a drop while pointer is over
-		 *			the drop area.
-		 *			Provides window coordinates of the pointer position.
-		 */
-		Event<void(INT32 x, INT32 y)> onDrop;
-
-		/**
-		 * @brief	Triggered when a pointer enters the drop area.
-		 *			Provides window coordinates of the pointer position.
-		 */
-		Event<void(INT32 x, INT32 y)> onEnter;
-
-		/**
-		 * @brief	Triggered when a pointer leaves the drop area.
-		 */
-		Event<void()> onLeave;
-
-		/**
-		 * @brief	Sets the drop target area, in local window coordinates.
-		 */
-		void setArea(INT32 x, INT32 y, UINT32 width, UINT32 height);
-
-		/**
-		 * @brief	Gets the type of drop that this drop target is looking for. Only
-		 *			valid after a drop has been triggered.
-		 */
-		OSDropType getDropType() const { return mDropType; }
-
-		/**
-		 * @brief	Returns a list of files received by the drop target. Only valid
-		 *			after a drop of FileList type has been triggered.
-		 */
-		const Vector<WString>& getFileList() const { return *mFileList; }
-
-		/**
-		 * @brief	Internal method. Clears all internal values.
-		 */
-		void _clear();
-
-		/**
-		 * @brief	Internal method. Sets the file list and marks the drop event as FileList.
-		 */
-		void _setFileList(const Vector<WString>& fileList);
-
-		/**
-		 * @brief	Marks the drop area as inactive or active.
-		 */
-		void _setActive(bool active) { mActive = active; }
-
-		/**
-		 * @brief	Checks is the specified position within the current drop area.
-		 *			Position should be in window local coordinates.
-		 */
-		bool _isInside(const Vector2I& pos) const;
-
-		/**
-		 * @brief	Returns true if the drop target is active.
-		 */
-		bool _isActive() const { return mActive; }
-	private:
-		friend class Platform;
-
-		OSDropTarget(const RenderWindow* ownerWindow, INT32 x, INT32 y, UINT32 width, UINT32 height);
-		~OSDropTarget();
-
-		/**
-		 * @brief	Returns a render window this drop target is attached to.
-		 */
-		const RenderWindow* getOwnerWindow() const { return mOwnerWindow; }
-	private:
-		INT32 mX, mY;
-		UINT32 mWidth, mHeight;
-		bool mActive;
-		const RenderWindow* mOwnerWindow;
-
-		OSDropType mDropType;
-
-		union
-		{
-			Vector<WString>* mFileList;
-		};
-	};
-
-	/**
-	 * @brief	Represents a specific non client area used for window resizing.
-	 */
-	struct BS_CORE_EXPORT NonClientResizeArea
-	{
-		NonClientAreaBorderType type;
-		Rect2I area;
-	};
-
-	/**
-	 * @brief	Contains a list of window move and resize non client areas.
-	 */
-	struct BS_CORE_EXPORT WindowNonClientAreaData
-	{
-		Vector<NonClientResizeArea> resizeAreas;
-		Vector<Rect2I> moveAreas;
-	};
-
-	/**
-	 * @brief	Provides access to various operating system functions, including
-	 * 			the main message pump.
-	 */
-	class BS_CORE_EXPORT Platform
-	{
-	public:
-		struct Pimpl;
-
-		Platform() { }
-		virtual ~Platform();
-
-		/**
-		 * @brief	Retrieves the cursor position in screen coordinates.
-		 *
-		 * @note	Thread safe.
-		 */
-		static Vector2I getCursorPosition();
-
-		/**
-		 * @brief	Moves the cursor to the specified screen position.
-		 *
-		 * @note	Thread safe.
-		 */
-		static void setCursorPosition(const Vector2I& screenPos);
-
-		/**
-		 * @brief	Capture mouse to this window so that we get mouse input even if the mouse leaves the window area.
-		 *
-		 * @note	Thread safe.
-		 */
-		static void captureMouse(const RenderWindow& window);
-
-		/**
-		 * @brief	Releases the mouse capture set by "captureMouse"
-		 *
-		 * @note	Thread safe.
-		 */
-		static void releaseMouseCapture();
-
-		/**
-		 * @brief	Checks if provided over screen position is over the specified window.
-		 */
-		static bool isPointOverWindow(const RenderWindow& window, const Vector2I& screenPos);
-
-		/**
-		 * @brief	Limit cursor movement to the specified window.
-		 *
-		 * @note	Thread safe.
-		 */
-		static void clipCursorToWindow(const RenderWindow& window);
-
-		/**
-		 * @brief	Clip cursor to specific area on the screen.
-		 *
-		 * @note	Thread safe.
-		 */
-
-		static void clipCursorToRect(const Rect2I& screenRect);
-
-		/**
-		 * @brief	Disables cursor clipping.
-		 *
-		 * @note	Thread safe.
-		 */
-		static void clipCursorDisable();
-
-		/**
-		 * @brief	Hides the cursor.
-		 *
-		 * @note	Thread safe.
-		 */
-		static void hideCursor();
-
-		/**
-		 * @brief	Shows the cursor.
-		 *
-		 * @note	Thread safe.
-		 */
-		static void showCursor();
-
-		/**
-		 * @brief	Query if the cursor is hidden.
-		 *
-		 * @note	Thread safe.
-		 */
-		static bool isCursorHidden();
-
-		/**
-		 * @brief	Sets a cursor using a custom image.
-		 *
-		 * @param 	pixelData	Cursor image data.
-		 * @param	hotSpot		Offset on the cursor image to where the actual input happens (e.g. tip of the Arrow cursor).
-		 *
-		 * @note	Thread safe.
-		 */
-		static void setCursor(PixelData& pixelData, const Vector2I& hotSpot);
-
-		/**
-		 * @brief	Sets an icon for the main application window.
-		 *
-		 * @param 	pixelData	Icon image data. This will be resized to the required icon size, depending on platform
-		 * 						implementation.
-		 *
-		 * @note	Thread safe.
-		 */
-		static void setIcon(const PixelData& pixelData);
-
-		/**
-		 * @brief	Sets custom caption non client areas for the specified window. Using custom client
-		 * 			areas will override window move/drag operation and trigger when user interacts
-		 * 			with the custom area.
-		 *
-		 * @note	Thread safe.
-		 * 			All provided areas are relative to the specified window.
-		 * 			Mostly useful for frameless windows that don't have typical caption bar.
-		 */
-		static void setCaptionNonClientAreas(const RenderWindowCore& window, const Vector<Rect2I>& nonClientAreas);
-
-		/**
-		 * @brief	Sets custom non client areas for the specified window. Using custom client
-		 * 			areas will override window resize operation and trigger when user interacts
-		 * 			with the custom area.
-		 *
-		 * @note	Thread safe.
-		 * 			All provided areas are relative to the specified window.
-		 * 			Mostly useful for frameless windows that don't have typical border.
-		 */
-		static void setResizeNonClientAreas(const RenderWindowCore& window, const Vector<NonClientResizeArea>& nonClientAreas);
-
-		/**
-		 * @brief	Resets the non client areas for the specified windows and allows
-		 * 			the platform to use the default values.
-		 *
-		 * @note	Thread safe.
-		 */
-		static void resetNonClientAreas(const RenderWindowCore& window);
-
-		/**
-		 * @brief	Creates a drop target that you can use for tracking OS drag and drop operations performed over
-		 * 			a certain area on the specified window.
-		 *
-		 * @param	window	The window on which to track drop operations.
-		 * @param	x	  	The x coordinate of the area to track, relative to window.
-		 * @param	y	  	The y coordinate of the area to track, relative to window.
-		 * @param	width 	The width of the area to track.
-		 * @param	height	The height of the area to track.
-		 *
-		 * @return	OSDropTarget that you will use to receive all drop data. When no longer needed make sure to destroy it with
-		 * 			destroyDropTarget().
-		 */
-		static OSDropTarget& createDropTarget(const RenderWindow* window, int x, int y, unsigned int width, unsigned int height);
-
-		/**
-		 * @brief	Destroys a drop target previously created with createDropTarget.
-		 */
-		static void destroyDropTarget(OSDropTarget& target);
-
-		/**
-		 * @brief	Message pump. Processes OS messages and returns when it's free.
-		 *
-		 * @note	Internal method.
-		 * 			Core thread only.
-		 */
-		static void _messagePump();
-
-		/**
-		 * @brief	Called during application start up from the sim thread.
-		 * 			Must be called before any other operations are done.
-		 *
-		 * @note	Internal method.
-		 */
-		static void _startUp();
-
-		/**
-		 * @brief	Called once per frame from the sim thread.
-		 *
-		 * @note	Internal method.
-		 * 			Sim thread only.
-		 */
-		static void _update();
-
-		/**
-		 * @brief	Called once per frame from the core thread.
-		 *
-		 * @note	Internal method.
-		 * 			Core thread only.
-		 */
-		static void _coreUpdate();
-
-		/**
-		 * @brief	Called during application shut down from the sim thread.
-		 *
-		 * @note	Internal method.
-		 * 			Sim thread only.
-		 */
-		static void _shutDown();
-
-		/**
-		 * @brief	Triggered when a pointer leaves the provided window.
-		 *
-		 * @note	Sim thread only.
-		 */
-		static Event<void(RenderWindowCore*)> onMouseLeftWindow;
-
-		/**
-		 * @brief	Triggered whenever the pointer moves.
-		 *
-		 * @note	Core thread only.
-		 */
-		static Event<void(const Vector2I&, OSPointerButtonStates)> onCursorMoved;
-
-		/**
-		 * @brief	Triggered whenever a pointer button is pressed.
-		 *
-		 * @note	Core thread only.
-		 */
-		static Event<void(const Vector2I&, OSMouseButton button, OSPointerButtonStates)> onCursorButtonPressed;
-
-		/**
-		 * @brief	Triggered whenever pointer button is released.
-		 *
-		 * @note	Core thread only.
-		 */
-		static Event<void(const Vector2I&, OSMouseButton button, OSPointerButtonStates)> onCursorButtonReleased;
-
-		/**
-		 * @brief	Triggered whenever a pointer button is double clicked.
-		 *
-		 * @note	Core thread only.
-		 */
-		static Event<void(const Vector2I&, OSPointerButtonStates)> onCursorDoubleClick;
-
-		/**
-		 * @brief	Triggered whenever an input command is entered.
-		 *
-		 * @note	Core thread only.
-		 */
-		static Event<void(InputCommandType)> onInputCommand;
-
-		/**
-		 * @brief	Triggered whenever the mouse wheel is scolled.
-		 *
-		 * @note	Core thread only.
-		 */
-		static Event<void(float)> onMouseWheelScrolled;
-
-		/**
-		 * @brief	Triggered whenever a character is entered.
-		 *
-		 * @note	Core thread only.
-		 */
-		static Event<void(UINT32)> onCharInput;
-
-		/**
-		 * @brief	Triggered whenever mouse capture state for the window is changed
-		 * 			(it receives or loses it).
-		 *
-		 * @note	Core thread only.
-		 */
-		static Event<void()> onMouseCaptureChanged;
-	protected:
-		static Pimpl* mData;
-	};
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsInputFwd.h"
+#include "BsVector2I.h"
+#include "BsRect2I.h"
+#include "BsEvent.h"
+
+namespace BansheeEngine
+{
+	/** @cond INTERNAL */
+	/** @addtogroup Platform
+	 *  @{
+	 */
+
+	/** Contains values representing default mouse cursor types. */
+	enum class PlatformCursorType
+	{
+		Arrow,
+		Wait,
+		IBeam,
+		Help,
+		Hand,
+		SizeAll,
+		SizeNESW,
+		SizeNS,
+		SizeNWSE,
+		SizeWE
+	};
+
+	/**
+	 * Contains values reprenting window non client areas.
+	 *
+	 * @note	These are used for things like resize/move and tell the OS where each of those areas are on our window.
+	 */
+	enum class NonClientAreaBorderType
+	{
+		TopLeft,
+		Top,
+		TopRight,
+		Left,
+		Right,
+		BottomLeft,
+		Bottom,
+		BottomRight
+	};
+
+	/** Types of mouse buttons provided by the OS. */
+	enum class OSMouseButton
+	{
+		Left, Middle, Right, Count
+	};
+
+	/** Describes pointer (mouse, touch) states as reported by the OS. */
+	struct BS_CORE_EXPORT OSPointerButtonStates
+	{
+		OSPointerButtonStates()
+		{
+			mouseButtons[0] = false;
+			mouseButtons[1] = false;
+			mouseButtons[2] = false;
+
+			shift = false;
+			ctrl = false;
+		}
+
+		bool mouseButtons[OSMouseButton::Count];
+		bool shift, ctrl;
+	};
+
+	/** Type of drop event type. This is used when dragging items over drop targets. */
+	enum class OSDropType
+	{
+		FileList,
+		None
+	};
+
+	/**
+	 * Drop targets allow you to register a certain portion of a window as a drop target that accepts certain drop types 
+	 * from the OS (platform) specific drag and drop system. Accepted drop types are provided by the OS and include things
+	 * like file and item dragging.
+	 *
+	 * You will receive events with the specified drop area as long as it is active.
+	 */
+	class BS_CORE_EXPORT OSDropTarget
+	{
+	public:
+		/**
+		 * Triggered when a pointer is being dragged over the drop area. Provides window coordinates of the pointer position.
+		 */
+		Event<void(INT32 x, INT32 y)> onDragOver;
+
+		/**
+		 * Triggered when the user completes a drop while pointer is over the drop area. Provides window coordinates of the 
+		 * pointer position.
+		 */
+		Event<void(INT32 x, INT32 y)> onDrop;
+
+		/**
+		 * Triggered when a pointer enters the drop area. Provides window coordinates of the pointer position.
+		 */
+		Event<void(INT32 x, INT32 y)> onEnter;
+
+		/** Triggered when a pointer leaves the drop area. */
+		Event<void()> onLeave;
+
+		/**	Sets the drop target area, in local window coordinates. */
+		void setArea(INT32 x, INT32 y, UINT32 width, UINT32 height);
+
+		/**	Gets the type of drop that this drop target is looking for. Only valid after a drop has been triggered. */
+		OSDropType getDropType() const { return mDropType; }
+
+		/**	
+		 * Returns a list of files received by the drop target. Only valid after a drop of FileList type has been triggered.
+		 */
+		const Vector<WString>& getFileList() const { return *mFileList; }
+
+		/** Clears all internal values. */
+		void _clear();
+
+		/** Sets the file list and marks the drop event as FileList. */
+		void _setFileList(const Vector<WString>& fileList);
+
+		/** Marks the drop area as inactive or active. */
+		void _setActive(bool active) { mActive = active; }
+
+		/**	Checks is the specified position within the current drop area. Position should be in window local coordinates. */
+		bool _isInside(const Vector2I& pos) const;
+
+		/** Returns true if the drop target is active. */
+		bool _isActive() const { return mActive; }
+	private:
+		friend class Platform;
+
+		OSDropTarget(const RenderWindow* ownerWindow, INT32 x, INT32 y, UINT32 width, UINT32 height);
+		~OSDropTarget();
+
+		/**	Returns a render window this drop target is attached to. */
+		const RenderWindow* getOwnerWindow() const { return mOwnerWindow; }
+	private:
+		INT32 mX, mY;
+		UINT32 mWidth, mHeight;
+		bool mActive;
+		const RenderWindow* mOwnerWindow;
+
+		OSDropType mDropType;
+
+		union
+		{
+			Vector<WString>* mFileList;
+		};
+	};
+
+	/**	Represents a specific non client area used for window resizing. */
+	struct BS_CORE_EXPORT NonClientResizeArea
+	{
+		NonClientAreaBorderType type;
+		Rect2I area;
+	};
+
+	/** Contains a list of window move and resize non client areas. */
+	struct BS_CORE_EXPORT WindowNonClientAreaData
+	{
+		Vector<NonClientResizeArea> resizeAreas;
+		Vector<Rect2I> moveAreas;
+	};
+
+	/**	Provides access to various operating system functions, including the main message pump. */
+	class BS_CORE_EXPORT Platform
+	{
+	public:
+		struct Pimpl;
+
+		Platform() { }
+		virtual ~Platform();
+
+		/**
+		 * Retrieves the cursor position in screen coordinates.
+		 *
+		 * @note	Thread safe.
+		 */
+		static Vector2I getCursorPosition();
+
+		/**
+		 * Moves the cursor to the specified screen position.
+		 *
+		 * @note	Thread safe.
+		 */
+		static void setCursorPosition(const Vector2I& screenPos);
+
+		/**
+		 * Capture mouse to this window so that we get mouse input even if the mouse leaves the window area.
+		 *
+		 * @note	Thread safe.
+		 */
+		static void captureMouse(const RenderWindow& window);
+
+		/**
+		 * Releases the mouse capture set by captureMouse().
+		 *
+		 * @note	Thread safe.
+		 */
+		static void releaseMouseCapture();
+
+		/**
+		 * Checks if provided over screen position is over the specified window.
+		 */
+		static bool isPointOverWindow(const RenderWindow& window, const Vector2I& screenPos);
+
+		/**
+		 * Limit cursor movement to the specified window.
+		 *
+		 * @note	Thread safe.
+		 */
+		static void clipCursorToWindow(const RenderWindow& window);
+
+		/**
+		 * Clip cursor to specific area on the screen.
+		 *
+		 * @note	Thread safe.
+		 */
+
+		static void clipCursorToRect(const Rect2I& screenRect);
+
+		/**
+		 * Disables cursor clipping.
+		 *
+		 * @note	Thread safe.
+		 */
+		static void clipCursorDisable();
+
+		/**
+		 * Hides the cursor.
+		 *
+		 * @note	Thread safe.
+		 */
+		static void hideCursor();
+
+		/**
+		 * Shows the cursor.
+		 *
+		 * @note	Thread safe.
+		 */
+		static void showCursor();
+
+		/**
+		 * Query if the cursor is hidden.
+		 *
+		 * @note	Thread safe.
+		 */
+		static bool isCursorHidden();
+
+		/**
+		 * Sets a cursor using a custom image.
+		 *
+		 * @param[in] 	pixelData	Cursor image data.
+		 * @param[in]	hotSpot		Offset on the cursor image to where the actual input happens (e.g. tip of the Arrow 
+		 *							cursor).
+		 *
+		 * @note	Thread safe.
+		 */
+		static void setCursor(PixelData& pixelData, const Vector2I& hotSpot);
+
+		/**
+		 * Sets an icon for the main application window.
+		 *
+		 * @param[in] 	pixelData	Icon image data. This will be resized to the required icon size, depending on platform
+		 * 							implementation.
+		 *
+		 * @note	Thread safe.
+		 */
+		static void setIcon(const PixelData& pixelData);
+
+		/**
+		 * Sets custom caption non client areas for the specified window. Using custom client areas will override window 
+		 * move/drag operation and trigger when user interacts with the custom area.
+		 *
+		 * @note	
+		 * Thread safe.
+		 * @note
+		 * All provided areas are relative to the specified window. Mostly useful for frameless windows that don't have 
+		 * typical caption bar.
+		 */
+		static void setCaptionNonClientAreas(const RenderWindowCore& window, const Vector<Rect2I>& nonClientAreas);
+
+		/**
+		 * Sets custom non client areas for the specified window. Using custom client areas will override window resize 
+		 * operation and trigger when user interacts with the custom area.
+		 *
+		 * @note	
+		 * Thread safe.
+		 * @note
+		 * All provided areas are relative to the specified window. Mostly useful for frameless windows that don't have 
+		 * typical border.
+		 */
+		static void setResizeNonClientAreas(const RenderWindowCore& window, const Vector<NonClientResizeArea>& nonClientAreas);
+
+		/**
+		 * Resets the non client areas for the specified windows and allows the platform to use the default values.
+		 *
+		 * @note	Thread safe.
+		 */
+		static void resetNonClientAreas(const RenderWindowCore& window);
+
+		/**
+		 * Creates a drop target that you can use for tracking OS drag and drop operations performed over a certain area 
+		 * on the specified window.
+		 *
+		 * @param[in]	window	The window on which to track drop operations.
+		 * @param[in]	x	  	The x coordinate of the area to track, relative to window.
+		 * @param[in]	y	  	The y coordinate of the area to track, relative to window.
+		 * @param[in]	width 	The width of the area to track.
+		 * @param[in]	height	The height of the area to track.
+		 * @return				OSDropTarget that you will use to receive all drop data. When no longer needed make sure 
+		 *						to destroy it with destroyDropTarget().
+		 */
+		static OSDropTarget& createDropTarget(const RenderWindow* window, int x, int y, unsigned int width, unsigned int height);
+
+		/** Destroys a drop target previously created with createDropTarget. */
+		static void destroyDropTarget(OSDropTarget& target);
+
+		/**
+		 * Message pump. Processes OS messages and returns when it's free.
+		 *
+		 * @note	Core thread only.
+		 */
+		static void _messagePump();
+
+		/**
+		 * Called during application start up from the sim thread. Must be called before any other operations are done.
+		 *
+		 * @note	Internal method.
+		 */
+		static void _startUp();
+
+		/**
+		 * Called once per frame from the sim thread.
+		 *
+		 * @note	Sim thread only.
+		 */
+		static void _update();
+
+		/**
+		 * Called once per frame from the core thread.
+		 *
+		 * @note	Core thread only.
+		 */
+		static void _coreUpdate();
+
+		/**
+		 * Called during application shut down from the sim thread.
+		 *
+		 * @note	Sim thread only.
+		 */
+		static void _shutDown();
+
+		/**
+		 * Triggered when a pointer leaves the provided window.
+		 *
+		 * @note	Sim thread only.
+		 */
+		static Event<void(RenderWindowCore*)> onMouseLeftWindow;
+
+		/**
+		 * Triggered whenever the pointer moves.
+		 *
+		 * @note	Core thread only.
+		 */
+		static Event<void(const Vector2I&, OSPointerButtonStates)> onCursorMoved;
+
+		/**
+		 * Triggered whenever a pointer button is pressed.
+		 *
+		 * @note	Core thread only.
+		 */
+		static Event<void(const Vector2I&, OSMouseButton button, OSPointerButtonStates)> onCursorButtonPressed;
+
+		/**
+		 * Triggered whenever pointer button is released.
+		 *
+		 * @note	Core thread only.
+		 */
+		static Event<void(const Vector2I&, OSMouseButton button, OSPointerButtonStates)> onCursorButtonReleased;
+
+		/**
+		 * Triggered whenever a pointer button is double clicked.
+		 *
+		 * @note	Core thread only.
+		 */
+		static Event<void(const Vector2I&, OSPointerButtonStates)> onCursorDoubleClick;
+
+		/**
+		 * Triggered whenever an input command is entered.
+		 *
+		 * @note	Core thread only.
+		 */
+		static Event<void(InputCommandType)> onInputCommand;
+
+		/**
+		 * Triggered whenever the mouse wheel is scolled.
+		 *
+		 * @note	Core thread only.
+		 */
+		static Event<void(float)> onMouseWheelScrolled;
+
+		/**
+		 * Triggered whenever a character is entered.
+		 *
+		 * @note	Core thread only.
+		 */
+		static Event<void(UINT32)> onCharInput;
+
+		/**
+		 * Triggered whenever mouse capture state for the window is changed (it receives or loses it).
+		 *
+		 * @note	Core thread only.
+		 */
+		static Event<void()> onMouseCaptureChanged;
+	protected:
+		static Pimpl* mData;
+	};
+
+	/** @} */
+	/** @endcond */
 }

+ 420 - 472
BansheeCore/Include/BsProfilerCPU.h

@@ -1,473 +1,421 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsModule.h"
-#include "BsFrameAlloc.h"
-
-namespace BansheeEngine
-{
-	class CPUProfilerReport;
-
-	/**
-	 * @brief	Provides various performance measuring methods.
-	 * 			
-	 * @note	Thread safe. Matching begin*\end* calls
-	 * 			must belong to the same thread though.
-	 */
-	class BS_CORE_EXPORT ProfilerCPU : public Module<ProfilerCPU>
-	{
-		/**
-		 * @brief	Timer class responsible for tracking elapsed time.
-		 */
-		class Timer
-		{
-		public:
-			Timer();
-
-			/**
-			 * @brief	Sets the start time for the timer.
-			 */
-			void start();
-
-			/**
-			 * @brief	Stops the timer and calculates the elapsed time
-			 *			from start time to now.
-			 */
-			void stop();
-
-			/**
-			 * @brief	Resets the elapsed time to zero.
-			 */
-			void reset();
-
-			double time;
-		private:
-			double startTime;
-
-			/**
-			 * @brief	Returns time elapsed since CPU was started in millseconds.
-			 */
-			static inline double getCurrentTime();
-		};
-
-		/**
-		 * @brief	Timer class responsible for tracking number of elapsed CPU cycles.
-		 */
-		class TimerPrecise
-		{
-		public:
-			TimerPrecise();
-
-			/**
-			 * @brief	Starts the counter marking the current number of executed
-			 *			CPU cycles since CPU was started.
-			 */
-			void start();
-
-			/**
-			 * @brief	Ends the counter and calculates the number of CPU cycles between
-			 *			now and the start time.
-			 */
-			void stop();
-
-			/**
-			 * @brief	Resets the cycle count to zero.
-			 */
-			void reset();
-
-			UINT64 cycles;
-		private:
-			UINT64 startCycles;
-
-			/**
-			 * @brief	Queries the CPU for the current number of CPU cycles executed since the
-			 *			program was started.
-			 */
-			static inline UINT64 getNumCycles();
-		};
-
-		/**
-		 * @brief	Contains data about a single profiler sample (counting time in milliseconds).
-		 *	
-		 * @note	A sample is created whenever a named profile block is entered. e.g. if you have a function
-		 *			you are profiling, and it gets called 10 times, there will be 10 samples.
-		 */
-		struct ProfileSample
-		{
-			ProfileSample(double _time, UINT64 _numAllocs, UINT64 _numFrees)
-				:time(_time), numAllocs(_numAllocs), numFrees(_numFrees)
-			{ }
-
-			double time;
-			UINT64 numAllocs;
-			UINT64 numFrees;
-		};
-
-		/**
-		 * @brief	Contains data about a single precise profiler sample (counting CPU cycles).
-		 *
-		 * @note	A sample is created whenever a named profile block is entered. e.g. if you have a function
-		 *			you are profiling, and it gets called 10 times, there will be 10 samples.
-		 */
-		struct PreciseProfileSample
-		{
-			PreciseProfileSample(UINT64 _cycles, UINT64 _numAllocs, UINT64 _numFrees)
-				:cycles(_cycles), numAllocs(_numAllocs), numFrees(_numFrees)
-			{ }
-
-			UINT64 cycles;
-			UINT64 numAllocs;
-			UINT64 numFrees;
-		};
-
-		/**
-		 * @brief	Contains basic (time based) profiling data contained in a profiling block.
-		 */
-		struct ProfileData
-		{
-			ProfileData(FrameAlloc* alloc);
-
-			/**
-			 * @brief	Begins a new sample and records current sample state. Previous sample must
-			 *			not be active.
-			 */
-			void beginSample();
-
-			/**
-			 * @brief	Records current sample state and creates a new sample based on start and end state.
-			 *			Adds the sample to the sample list.
-			 */
-			void endSample();
-
-			/**
-			 * @brief	Removes the last added sample from the sample list and makes it active again. You must
-			 *			call endSample when done as if you called beginSample.
-			 */
-			void resumeLastSample();
-
-			Vector<ProfileSample, StdFrameAlloc<ProfileSample>> samples;
-			Timer timer;
-
-			UINT64 memAllocs;
-			UINT64 memFrees;
-		};
-
-		/**
-		 * @brief	Contains precise (CPU cycle based) profiling data contained in a profiling block.
-		 */
-		struct PreciseProfileData
-		{
-			PreciseProfileData(FrameAlloc* alloc);
-
-			/**
-			 * @brief	Begins a new sample and records current sample state. Previous sample must
-			 *			not be active.
-			 */
-			void beginSample();
-
-			/**
-			 * @brief	Records current sample state and creates a new sample based on start and end state.
-			 *			Adds the sample to the sample list.
-			 */
-			void endSample();
-
-			/**
-			 * @brief	Removes the last added sample from the sample list and makes it active again. You must
-			 *			call endSample when done as if you called beginSample.
-			 */
-			void resumeLastSample();
-
-			Vector<PreciseProfileSample, StdFrameAlloc<ProfileSample>> samples;
-			TimerPrecise timer;
-
-			UINT64 memAllocs;
-			UINT64 memFrees;
-		};
-
-		/**
-		 * @brief	Contains all sampling information about a single named profiling block.
-		 *			Each block has its own sampling information and optionally child blocks.
-		 */
-		struct ProfiledBlock
-		{
-			ProfiledBlock(FrameAlloc* alloc);
-			~ProfiledBlock();
-
-			/**
-			 * @brief	Attempts to find a child block with the specified name. Returns
-			 *			null if not found.
-			 */
-			ProfiledBlock* findChild(const char* name) const;
-
-			char* name;
-			
-			ProfileData basic;
-			PreciseProfileData precise;
-
-			Vector<ProfiledBlock*, StdFrameAlloc<ProfiledBlock*>> children;
-		};
-
-		/**
-		 * @brief	CPU sampling type.
-		 */
-		enum class ActiveSamplingType
-		{
-			Basic, /**< Sample using milliseconds. */
-			Precise /**< Sample using CPU cycles. */
-		};
-
-		/**
-		 * @brief	Contains data about the currently active profiling block.
-		 */
-		struct ActiveBlock
-		{
-			ActiveBlock()
-				:type(ActiveSamplingType::Basic), block(nullptr)
-			{ }
-
-			ActiveBlock(ActiveSamplingType _type, ProfiledBlock* _block)
-				:type(_type), block(_block)
-			{ }
-
-			ActiveSamplingType type;
-			ProfiledBlock* block;
-		};
-
-		/**
-		 * @brief	Contains data about an active profiling thread.
-		 */
-		struct ThreadInfo
-		{
-			ThreadInfo();
-
-			/**
-			 * @brief	Starts profiling on the thread. New primary profiling block
-			 *			is created with the given name.
-			 */
-			void begin(const char* _name);
-
-			/**
-			 * @brief	Ends profiling on the thread. You should end all samples before calling this,
-			 *			but if you don't they will be terminated automatically.
-			 */
-			void end();
-
-			/**
-			 * @brief	Deletes all internal profiling data and makes the object ready for another
-			 *			iteration. Should be called after end in order to delete any existing data.
-			 */
-			void reset();
-
-			/**
-			 * @brief	Gets the primary profiling block used by the thread.
-			 */
-			ProfiledBlock* getBlock(const char* name);
-			
-			/**
-			 * @brief	Deletes the provided block.
-			 */
-			void releaseBlock(ProfiledBlock* block);
-
-			static BS_THREADLOCAL ThreadInfo* activeThread;
-			bool isActive;
-
-			ProfiledBlock* rootBlock;
-
-			FrameAlloc frameAlloc;
-			ActiveBlock activeBlock;
-			Stack<ActiveBlock, StdFrameAlloc<ActiveBlock>>* activeBlocks;
-		};
-
-	public:
-		ProfilerCPU();
-		~ProfilerCPU();
-
-		/**
-		 * @brief	Registers a new thread we will be doing sampling in. This needs to be called before any beginSample*\endSample* calls
-		 * 			are made in that thread.
-		 *
-		 * @param	name	Name that will allow you to more easily identify the thread.
-		 */
-		void beginThread(const char* name);
-
-		/**
-		 * @brief	Ends sampling for the current thread. No beginSample*\endSample* calls after this point.
-		 */
-		void endThread();
-
-		/**
-		 * @brief	Begins sample measurement. Must be followed by endSample. 
-		 *
-		 * @param	name	Unique name for the sample you can later use to find the sampling data.
-		 */
-		void beginSample(const char* name);
-
-		/**
-		 * @brief	Ends sample measurement.
-		 *
-		 * @param	name	Unique name for the sample. 
-		 * 					
-		 * @note	Unique name is primarily needed to more easily identify mismatched
-		 * 			begin/end sample pairs. Otherwise the name in beginSample would be enough.
-		 */
-		void endSample(const char* name);
-
-		/**
-		 * @brief	Begins sample measurement. Must be followed by endSample. 
-		 *
-		 * @param	name	Unique name for the sample you can later use to find the sampling data.
-		 * 					
-		 * @note	This method uses very precise CPU counters to determine variety of data not
-		 * 			provided by standard beginSample. However due to the way these counters work you should
-		 * 			not use this method for larger parts of code. It does not consider context switches so if the OS
-		 * 			decides to switch context between measurements you will get invalid data.
-		 */
-		void beginSamplePrecise(const char* name);
-
-		/**
-		 * @brief	Ends precise sample measurement.
-		 *
-		 * @param	name	Unique name for the sample. 
-		 * 					
-		 * @note	Unique name is primarily needed to more easily identify mismatched
-		 * 			begin/end sample pairs. Otherwise the name in beginSamplePrecise would be enough.
-		 */
-		void endSamplePrecise(const char* name);
-
-		/**
-		 * @brief	Clears all sampling data, and ends any unfinished sampling blocks.
-		 */
-		void reset();
-
-		/**
-		 * @brief	Generates a report from all previously sampled data.
-		 * 			
-		 * @note	Generating a report will stop all in-progress sampling. You should make sure
-		 * 			you call endSample* manually beforehand so this doesn't have to happen.
-		 */
-		CPUProfilerReport generateReport();
-
-	private:
-		/**
-		 * @brief	Calculates overhead that the timing and sampling methods themselves introduce
-		 *			so we might get more accurate measurements when creating reports.
-		 */
-		void estimateTimerOverhead();
-
-	private:
-		double mBasicTimerOverhead;
-		UINT64 mPreciseTimerOverhead;
-
-		double mBasicSamplingOverheadMs;
-		double mPreciseSamplingOverheadMs;
-		UINT64 mBasicSamplingOverheadCycles;
-		UINT64 mPreciseSamplingOverheadCycles;
-
-		ProfilerVector<ThreadInfo*> mActiveThreads;
-		BS_MUTEX(mThreadSync);
-	};
-
-	/**
-	 * @brief	Profiling entry containing information about a single CPU profiling block
-	 *			containing timing information.
-	 */
-	struct BS_CORE_EXPORT CPUProfilerBasicSamplingEntry
-	{
-		struct BS_CORE_EXPORT Data
-		{
-			Data();
-
-			String name; /**< Name of the profiling block. */
-			UINT32 numCalls; /**< Number of times the block was entered. */
-
-			UINT64 memAllocs; /**< Number of memory allocations that happened within the block. */
-			UINT64 memFrees; /**< Number of memory deallocations that happened within the block. */
-
-			double avgTimeMs; /**< Average time it took to execute the block, per call. In milliseconds. */
-			double maxTimeMs; /**< Maximum time of a single call in the block. In milliseconds. */
-			double totalTimeMs; /**< Total time the block took, across all calls. In milliseconds. */
-
-			double avgSelfTimeMs; /**< Average time it took to execute the block, per call. Ignores time used by child blocks. In milliseconds. */
-			double totalSelfTimeMs; /**< Total time the block took, across all calls. Ignores time used by child blocks. In milliseconds. */
-
-			double estimatedSelfOverheadMs; /**< Estimated overhead of profiling methods, only for this exact block. In milliseconds. */
-			double estimatedOverheadMs; /**< Estimated overhead of profiling methods for this block and all children. In milliseconds. */
-
-			float pctOfParent; /**< Percent of parent block time this block took to execute. Ranging [0.0, 1.0]. */
-		} data;
-
-		ProfilerVector<CPUProfilerBasicSamplingEntry> childEntries;
-	};
-
-	/**
-	* @brief	Profiling entry containing information about a single CPU profiling block
-	*			containing CPU cycle count based information.
-	*/
-	struct BS_CORE_EXPORT CPUProfilerPreciseSamplingEntry
-	{
-		struct BS_CORE_EXPORT Data
-		{
-			Data();
-
-			String name; /**< Name of the profiling block. */
-			UINT32 numCalls; /**< Number of times the block was entered. */
-
-			UINT64 memAllocs; /**< Number of memory allocations that happened within the block. */
-			UINT64 memFrees; /**< Number of memory deallocations that happened within the block. */
-
-			UINT64 avgCycles; /**< Average number of cycles it took to execute the block, per call. */
-			UINT64 maxCycles; /**< Maximum number of cycles of a single call in the block. */
-			UINT64 totalCycles; /**< Total number of cycles across all calls in the block. */
-
-			UINT64 avgSelfCycles; /**< Average number of cycles it took to execute the block, per call. Ignores cycles used by child blocks. */
-			UINT64 totalSelfCycles; /**< Total number of cycles across all calls in the block. Ignores time used by child blocks. */
-
-			UINT64 estimatedSelfOverhead; /**< Estimated overhead of profiling methods, only for this exact block. In cycles. */
-			UINT64 estimatedOverhead; /**< Estimated overhead of profiling methods for this block and all children. In cycles. */
-
-			float pctOfParent; /**< Percent of parent block cycles used by this block. Ranging [0.0, 1.0]. */
-		} data;
-
-		ProfilerVector<CPUProfilerPreciseSamplingEntry> childEntries;
-	};
-
-	/**
-	 * @brief	CPU profiling report containing all profiling information for a single profiling session.
-	 */
-	class BS_CORE_EXPORT CPUProfilerReport
-	{
-	public:
-		CPUProfilerReport();
-
-		/**
-		 * @brief	Returns root entry for the basic (time based) sampling data. Root entry always contains the
-		 *			profiling block associated with the entire thread.
-		 */
-		const CPUProfilerBasicSamplingEntry& getBasicSamplingData() const { return mBasicSamplingRootEntry; }
-
-		/**
-		 * @brief	Returns root entry for the precise (CPU cycle based) sampling data. Root entry always contains the
-		 *			profiling block associated with the entire thread.
-		 */
-		const CPUProfilerPreciseSamplingEntry& getPreciseSamplingData() const { return mPreciseSamplingRootEntry; }
-
-	private:
-		friend class ProfilerCPU;
-
-		CPUProfilerBasicSamplingEntry mBasicSamplingRootEntry;
-		CPUProfilerPreciseSamplingEntry mPreciseSamplingRootEntry;
-	};
-
-	/**
-	* @brief	Quick way to access the CPU profiler.
-	*/
-	BS_CORE_EXPORT ProfilerCPU& gProfilerCPU();
-
-	/**
-	* @brief	Shortcut for profiling a single function call.
-	*/
-#define PROFILE_CALL(call, name)							\
-	BansheeEngine::gProfilerCPU().beginSample(##name##);	\
-	call;													\
-	BansheeEngine::gProfilerCPU().endSample(##name##);
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsModule.h"
+#include "BsFrameAlloc.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Profiling
+	 *  @{
+	 */
+
+	class CPUProfilerReport;
+
+	/**
+	 * Provides various performance measuring methods.
+	 * 			
+	 * @note	Thread safe. Matching begin*\end* calls must belong to the same thread though.
+	 */
+	class BS_CORE_EXPORT ProfilerCPU : public Module<ProfilerCPU>
+	{
+		/**	Timer class responsible for tracking elapsed time. */
+		class Timer
+		{
+		public:
+			Timer();
+
+			/** Sets the start time for the timer. */
+			void start();
+
+			/** Stops the timer and calculates the elapsed time from start time to now. */
+			void stop();
+
+			/**	Resets the elapsed time to zero. */
+			void reset();
+
+			double time;
+		private:
+			double startTime;
+
+			/**	Returns time elapsed since CPU was started in millseconds. */
+			static inline double getCurrentTime();
+		};
+
+		/**	Timer class responsible for tracking number of elapsed CPU cycles. */
+		class TimerPrecise
+		{
+		public:
+			TimerPrecise();
+
+			/** Starts the counter marking the current number of executed CPU cycles since CPU was started. */
+			void start();
+
+			/** Ends the counter and calculates the number of CPU cycles between now and the start time. */
+			void stop();
+
+			/**	Resets the cycle count to zero. */
+			void reset();
+
+			UINT64 cycles;
+		private:
+			UINT64 startCycles;
+
+			/** Queries the CPU for the current number of CPU cycles executed since the program was started. */
+			static inline UINT64 getNumCycles();
+		};
+
+		/**
+		 * Contains data about a single profiler sample (counting time in milliseconds).
+		 *	
+		 * @note	
+		 * A sample is created whenever a named profile block is entered. e.g. if you have a function you are profiling, 
+		 * and it gets called 10 times, there will be 10 samples.
+		 */
+		struct ProfileSample
+		{
+			ProfileSample(double _time, UINT64 _numAllocs, UINT64 _numFrees)
+				:time(_time), numAllocs(_numAllocs), numFrees(_numFrees)
+			{ }
+
+			double time;
+			UINT64 numAllocs;
+			UINT64 numFrees;
+		};
+
+		/**
+		 * Contains data about a single precise profiler sample (counting CPU cycles).
+		 *
+		 * @note	
+		 * A sample is created whenever a named profile block is entered. e.g. if you have a function you are profiling, 
+		 * and it gets called 10 times, there will be 10 samples.
+		 */
+		struct PreciseProfileSample
+		{
+			PreciseProfileSample(UINT64 _cycles, UINT64 _numAllocs, UINT64 _numFrees)
+				:cycles(_cycles), numAllocs(_numAllocs), numFrees(_numFrees)
+			{ }
+
+			UINT64 cycles;
+			UINT64 numAllocs;
+			UINT64 numFrees;
+		};
+
+		/**	Contains basic (time based) profiling data contained in a profiling block. */
+		struct ProfileData
+		{
+			ProfileData(FrameAlloc* alloc);
+
+			/** Begins a new sample and records current sample state. Previous sample must not be active. */
+			void beginSample();
+
+			/**
+			 * Records current sample state and creates a new sample based on start and end state. Adds the sample to the 
+			 * sample list.
+			 */
+			void endSample();
+
+			/**
+			 * Removes the last added sample from the sample list and makes it active again. You must call endSample() 
+			 * when done as if you called beginSample().
+			 */
+			void resumeLastSample();
+
+			Vector<ProfileSample, StdFrameAlloc<ProfileSample>> samples;
+			Timer timer;
+
+			UINT64 memAllocs;
+			UINT64 memFrees;
+		};
+
+		/**	Contains precise (CPU cycle based) profiling data contained in a profiling block. */
+		struct PreciseProfileData
+		{
+			PreciseProfileData(FrameAlloc* alloc);
+
+			/** Begins a new sample and records current sample state. Previous sample must not be active. */
+			void beginSample();
+
+			/**
+			 * Records current sample state and creates a new sample based on start and end state. Adds the sample to the 
+			 * sample list.
+			 */
+			void endSample();
+
+			/**
+			 * Removes the last added sample from the sample list and makes it active again. You must call endSample() 
+			 * when done as if you called beginSample.
+			 */
+			void resumeLastSample();
+
+			Vector<PreciseProfileSample, StdFrameAlloc<ProfileSample>> samples;
+			TimerPrecise timer;
+
+			UINT64 memAllocs;
+			UINT64 memFrees;
+		};
+
+		/**
+		 * Contains all sampling information about a single named profiling block. Each block has its own sampling 
+		 * information and optionally child blocks.
+		 */
+		struct ProfiledBlock
+		{
+			ProfiledBlock(FrameAlloc* alloc);
+			~ProfiledBlock();
+
+			/**	Attempts to find a child block with the specified name. Returns null if not found. */
+			ProfiledBlock* findChild(const char* name) const;
+
+			char* name;
+			
+			ProfileData basic;
+			PreciseProfileData precise;
+
+			Vector<ProfiledBlock*, StdFrameAlloc<ProfiledBlock*>> children;
+		};
+
+		/**	CPU sampling type. */
+		enum class ActiveSamplingType
+		{
+			Basic, /**< Sample using milliseconds. */
+			Precise /**< Sample using CPU cycles. */
+		};
+
+		/**	Contains data about the currently active profiling block. */
+		struct ActiveBlock
+		{
+			ActiveBlock()
+				:type(ActiveSamplingType::Basic), block(nullptr)
+			{ }
+
+			ActiveBlock(ActiveSamplingType _type, ProfiledBlock* _block)
+				:type(_type), block(_block)
+			{ }
+
+			ActiveSamplingType type;
+			ProfiledBlock* block;
+		};
+
+		/** Contains data about an active profiling thread. */
+		struct ThreadInfo
+		{
+			ThreadInfo();
+
+			/**
+			 * Starts profiling on the thread. New primary profiling block is created with the given name.
+			 */
+			void begin(const char* _name);
+
+			/**
+			 * Ends profiling on the thread. You should end all samples before calling this, but if you don't they will be 
+			 * terminated automatically.
+			 */
+			void end();
+
+			/**
+			 * 	Deletes all internal profiling data and makes the object ready for another iteration. Should be called 
+			 * after end in order to delete any existing data.
+			 */
+			void reset();
+
+			/**	Gets the primary profiling block used by the thread. */
+			ProfiledBlock* getBlock(const char* name);
+			
+			/** Deletes the provided block. */
+			void releaseBlock(ProfiledBlock* block);
+
+			static BS_THREADLOCAL ThreadInfo* activeThread;
+			bool isActive;
+
+			ProfiledBlock* rootBlock;
+
+			FrameAlloc frameAlloc;
+			ActiveBlock activeBlock;
+			Stack<ActiveBlock, StdFrameAlloc<ActiveBlock>>* activeBlocks;
+		};
+
+	public:
+		ProfilerCPU();
+		~ProfilerCPU();
+
+		/**
+		 * Registers a new thread we will be doing sampling in. This needs to be called before any beginSample*\endSample* 
+		 * calls are made in that thread.
+		 *
+		 * @param[in]	name	Name that will allow you to more easily identify the thread.
+		 */
+		void beginThread(const char* name);
+
+		/**	Ends sampling for the current thread. No beginSample*\endSample* calls after this point. */
+		void endThread();
+
+		/**
+		 * Begins sample measurement. Must be followed by endSample(). 
+		 *
+		 * @param[in]	name	Unique name for the sample you can later use to find the sampling data.
+		 */
+		void beginSample(const char* name);
+
+		/**
+		 * Ends sample measurement.
+		 *
+		 * @param[in]	name	Unique name for the sample. 
+		 * 					
+		 * @note	
+		 * Unique name is primarily needed to more easily identify mismatched begin/end sample pairs. Otherwise the name in 
+		 * beginSample() would be enough.
+		 */
+		void endSample(const char* name);
+
+		/**
+		 * Begins precise sample measurement. Must be followed by endSamplePrecise(). 
+		 *
+		 * @param[in]	name	Unique name for the sample you can later use to find the sampling data.
+		 * 					
+		 * @note	
+		 * This method uses very precise CPU counters to determine variety of data not provided by standard beginSample(). 
+		 * However due to the way these counters work you should not use this method for larger parts of code. It does not 
+		 * consider context switches so if the OS decides to switch context between measurements you will get invalid data.
+		 */
+		void beginSamplePrecise(const char* name);
+
+		/**
+		 * Ends precise sample measurement.
+		 *
+		 * @param[in]	name	Unique name for the sample. 
+		 * 					
+		 * @note	
+		 * Unique name is primarily needed to more easily identify mismatched begin/end sample pairs. Otherwise the name 
+		 * in beginSamplePrecise() would be enough.
+		 */
+		void endSamplePrecise(const char* name);
+
+		/** Clears all sampling data, and ends any unfinished sampling blocks. */
+		void reset();
+
+		/**
+		 * Generates a report from all previously sampled data.
+		 * 			
+		 * @note	Generating a report will stop all in-progress sampling. You should make sure
+		 * 			you call endSample* manually beforehand so this doesn't have to happen.
+		 */
+		CPUProfilerReport generateReport();
+
+	private:
+		/**
+		 * Calculates overhead that the timing and sampling methods themselves introduce so we might get more accurate 
+		 * measurements when creating reports.
+		 */
+		void estimateTimerOverhead();
+
+	private:
+		double mBasicTimerOverhead;
+		UINT64 mPreciseTimerOverhead;
+
+		double mBasicSamplingOverheadMs;
+		double mPreciseSamplingOverheadMs;
+		UINT64 mBasicSamplingOverheadCycles;
+		UINT64 mPreciseSamplingOverheadCycles;
+
+		ProfilerVector<ThreadInfo*> mActiveThreads;
+		BS_MUTEX(mThreadSync);
+	};
+
+	/** Profiling entry containing information about a single CPU profiling block containing timing information. */
+	struct BS_CORE_EXPORT CPUProfilerBasicSamplingEntry
+	{
+		struct BS_CORE_EXPORT Data
+		{
+			Data();
+
+			String name; /**< Name of the profiling block. */
+			UINT32 numCalls; /**< Number of times the block was entered. */
+
+			UINT64 memAllocs; /**< Number of memory allocations that happened within the block. */
+			UINT64 memFrees; /**< Number of memory deallocations that happened within the block. */
+
+			double avgTimeMs; /**< Average time it took to execute the block, per call. In milliseconds. */
+			double maxTimeMs; /**< Maximum time of a single call in the block. In milliseconds. */
+			double totalTimeMs; /**< Total time the block took, across all calls. In milliseconds. */
+
+			double avgSelfTimeMs; /**< Average time it took to execute the block, per call. Ignores time used by child blocks. In milliseconds. */
+			double totalSelfTimeMs; /**< Total time the block took, across all calls. Ignores time used by child blocks. In milliseconds. */
+
+			double estimatedSelfOverheadMs; /**< Estimated overhead of profiling methods, only for this exact block. In milliseconds. */
+			double estimatedOverheadMs; /**< Estimated overhead of profiling methods for this block and all children. In milliseconds. */
+
+			float pctOfParent; /**< Percent of parent block time this block took to execute. Ranging [0.0, 1.0]. */
+		} data;
+
+		ProfilerVector<CPUProfilerBasicSamplingEntry> childEntries;
+	};
+
+	/**
+	 * Profiling entry containing information about a single CPU profiling block containing CPU cycle count based 
+	 * information.
+	 */
+	struct BS_CORE_EXPORT CPUProfilerPreciseSamplingEntry
+	{
+		struct BS_CORE_EXPORT Data
+		{
+			Data();
+
+			String name; /**< Name of the profiling block. */
+			UINT32 numCalls; /**< Number of times the block was entered. */
+
+			UINT64 memAllocs; /**< Number of memory allocations that happened within the block. */
+			UINT64 memFrees; /**< Number of memory deallocations that happened within the block. */
+
+			UINT64 avgCycles; /**< Average number of cycles it took to execute the block, per call. */
+			UINT64 maxCycles; /**< Maximum number of cycles of a single call in the block. */
+			UINT64 totalCycles; /**< Total number of cycles across all calls in the block. */
+
+			UINT64 avgSelfCycles; /**< Average number of cycles it took to execute the block, per call. Ignores cycles used by child blocks. */
+			UINT64 totalSelfCycles; /**< Total number of cycles across all calls in the block. Ignores time used by child blocks. */
+
+			UINT64 estimatedSelfOverhead; /**< Estimated overhead of profiling methods, only for this exact block. In cycles. */
+			UINT64 estimatedOverhead; /**< Estimated overhead of profiling methods for this block and all children. In cycles. */
+
+			float pctOfParent; /**< Percent of parent block cycles used by this block. Ranging [0.0, 1.0]. */
+		} data;
+
+		ProfilerVector<CPUProfilerPreciseSamplingEntry> childEntries;
+	};
+
+	/** CPU profiling report containing all profiling information for a single profiling session. */
+	class BS_CORE_EXPORT CPUProfilerReport
+	{
+	public:
+		CPUProfilerReport();
+
+		/**
+		 * Returns root entry for the basic (time based) sampling data. Root entry always contains the profiling block 
+		 * associated with the entire thread.
+		 */
+		const CPUProfilerBasicSamplingEntry& getBasicSamplingData() const { return mBasicSamplingRootEntry; }
+
+		/**
+		 * Returns root entry for the precise (CPU cycle based) sampling data. Root entry always contains the profiling 
+		 * block associated with the entire thread.
+		 */
+		const CPUProfilerPreciseSamplingEntry& getPreciseSamplingData() const { return mPreciseSamplingRootEntry; }
+
+	private:
+		friend class ProfilerCPU;
+
+		CPUProfilerBasicSamplingEntry mBasicSamplingRootEntry;
+		CPUProfilerPreciseSamplingEntry mPreciseSamplingRootEntry;
+	};
+
+	/** Easier way to access ProfilerCPU. */
+	BS_CORE_EXPORT ProfilerCPU& gProfilerCPU();
+
+	/** Shortcut for profiling a single function call. */
+#define PROFILE_CALL(call, name)							\
+	BansheeEngine::gProfilerCPU().beginSample(##name##);	\
+	call;													\
+	BansheeEngine::gProfilerCPU().endSample(##name##);
+
+	/** @} */
 }

+ 176 - 184
BansheeCore/Include/BsProfilerGPU.h

@@ -1,185 +1,177 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsModule.h"
-#include "BsRenderStats.h"
-
-namespace BansheeEngine
-{
-	/**
-	* @brief	Contains various profiler statistics about a single GPU profiling sample
-	*/
-	struct GPUProfileSample
-	{
-		String name; /**< Name of the sample for easier identification. */
-		float timeMs; /**< Time in milliseconds it took to execute the sampled block. */
-
-		UINT32 numDrawCalls; /**< Number of draw calls that happened. */
-		UINT32 numRenderTargetChanges; /**< How many times was render target changed. */
-		UINT32 numPresents; /**< How many times did a buffer swap happen on a double buffered render target. */
-		UINT32 numClears; /**< How many times was render target cleared. */
-
-		UINT32 numVertices; /**< Total number of vertices sent to the GPU. */
-		UINT32 numPrimitives; /**< Total number of primitives sent to the GPU. */
-		UINT32 numDrawnSamples; /**< Number of samples drawn by the GPU. */
-
-		UINT32 numBlendStateChanges; /**< How many times did the blend state change. */
-		UINT32 numRasterizerStateChanges; /**< How many times did the rasterizer state change. */
-		UINT32 numDepthStencilStateChanges; /**< How many times did the depth stencil state change. */
-
-		UINT32 numTextureBinds; /**< How many times was a texture bound. */
-		UINT32 numSamplerBinds; /**< How many times was a sampler bound. */
-		UINT32 numVertexBufferBinds; /**< How many times was a vertex buffer bound. */
-		UINT32 numIndexBufferBinds; /**< How many times was an index buffer bound. */
-		UINT32 numGpuParamBufferBinds; /**< How many times was an GPU parameter buffer bound. */
-		UINT32 numGpuProgramBinds; /**< How many times was a GPU program bound. */
-
-		UINT32 numResourceWrites; /**< How many times were GPU resources written to. */
-		UINT32 numResourceReads; /**< How many times were GPU resources read from. */
-
-		UINT32 numObjectsCreated; /**< How many GPU objects were created. */
-		UINT32 numObjectsDestroyed; /**< How many GPU objects were destroyed. */
-	};
-
-	/**
-	 * @brief	Profiler report containing information about GPU sampling data 
-	 *			from a single frame.
-	 */
-	struct GPUProfilerReport
-	{
-		GPUProfileSample frameSample; /**< Sample containing data for entire frame. */
-		Vector<GPUProfileSample> samples;
-	};
-
-	/**
-	 * @brief	Profiler that measures time and amount of various GPU operations.
-	 *
-	 * @note	Core thread only except where noted otherwise.
-	 */
-	class BS_CORE_EXPORT ProfilerGPU : public Module<ProfilerGPU>
-	{
-	private:
-		struct ActiveSample
-		{
-			ProfilerString sampleName;
-			RenderStatsData startStats;
-			RenderStatsData endStats;
-			TimerQueryPtr activeTimeQuery;
-			OcclusionQueryPtr activeOcclusionQuery;
-		};
-
-		struct ActiveFrame
-		{
-			ActiveSample frameSample;
-			Vector<ActiveSample> samples;
-		};
-
-	public:
-		ProfilerGPU();
-
-		/**
-		 * @brief	Signals a start of a new frame. Every frame will generate a separate profiling report.
-		 *			This call must be followed by "endFrame", and any sampling operations must happen between
-		 *			beginFrame and endFrame.
-		 */
-		void beginFrame();
-
-		/**
-		 * @brief	Signals an end of the currently sampled frame. Results of the sampling will be available
-		 *			once getNumAvailableReports increments. This may take a while as the sampling is scheduled on
-		 *			the core thread and on the GPU.
-		 */
-		void endFrame();
-
-		/**
-		 * @brief	Begins sample measurement. Must be followed by endSample.
-		 *
-		 * @param	name	Unique name for the sample you can later use to find the sampling data.
-		 *
-		 * @note	Must be called between beginFrame/endFrame calls.
-		 */
-		void beginSample(const ProfilerString& name);
-
-		/**
-		 * @brief	Ends sample measurement.
-		 *
-		 * @param	name	Unique name for the sample.
-		 *
-		 * @note	Unique name is primarily needed to more easily identify mismatched
-		 * 			begin/end sample pairs. Otherwise the name in beginSample would be enough.
-		 *			Must be called between beginFrame/endFrame calls.
-		 */
-		void endSample(const ProfilerString& name);
-
-		/**
-		 * @brief	Returns number of profiling reports that are ready but haven't been
-		 *			retrieved yet. 
-		 *
-		 * @note	There is an internal limit of maximum number of available reports, where oldest ones will
-		 *			get deleted so make sure to call this often if you don't want to miss some.
-		 *
-		 *			Thread safe.
-		 */
-		UINT32 getNumAvailableReports();
-
-		/**
-		 * @brief	Gets the oldest report available and removes it from the internal list.
-		 *			Throws an exception if no reports are available.
-		 *
-		 * @note	Thread safe.
-		 */
-		GPUProfilerReport getNextReport();
-
-		/**
-		 * @brief	To be called once per frame from the Core thread.
-		 *
-		 * @note	Internal method.
-		 */
-		void _update();
-
-	private:
-		/**
-		 * @brief	Assigns start values for the provided sample.
-		 */
-		void beginSampleInternal(ActiveSample& sample);
-
-		/**
-		 * @brief	Assigns end values for the provided sample.
-		 */
-		void endSampleInternal(ActiveSample& sample);
-
-		/**
-		 * @brief	Creates a new timer query or returns an existing free query.
-		 */
-		TimerQueryPtr getTimerQuery() const;
-
-		/**
-		 * @brief	Creates a new occlusion query or returns an existing free query.
-		 */
-		OcclusionQueryPtr getOcclusionQuery() const;
-
-		/**
-		 * @brief	Interprets the active frame results and generates a profiler report for
-		 *			the frame. Provided frame queries must have finished before calling this.
-		 */
-		GPUProfilerReport resolveFrame(ActiveFrame& frame);
-
-		/**
-		 * @brief	Resolves an active sample and converts it to report sample.
-		 */
-		void resolveSample(const ActiveSample& sample, GPUProfileSample& reportSample);
-
-	private:
-		ActiveFrame mActiveFrame;
-		bool mIsFrameActive;
-		Stack<UINT32> mActiveSampleIndexes;
-
-		Queue<ActiveFrame> mUnresolvedFrames;
-		Queue<GPUProfilerReport> mReadyReports;
-
-		mutable Stack<TimerQueryPtr> mFreeTimerQueries;
-		mutable Stack<OcclusionQueryPtr> mFreeOcclusionQueries;
-
-		BS_MUTEX(mMutex);
-	};
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsModule.h"
+#include "BsRenderStats.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Profiling
+	 *  @{
+	 */
+
+	/** Contains various profiler statistics about a single GPU profiling sample. */
+	struct GPUProfileSample
+	{
+		String name; /**< Name of the sample for easier identification. */
+		float timeMs; /**< Time in milliseconds it took to execute the sampled block. */
+
+		UINT32 numDrawCalls; /**< Number of draw calls that happened. */
+		UINT32 numRenderTargetChanges; /**< How many times was render target changed. */
+		UINT32 numPresents; /**< How many times did a buffer swap happen on a double buffered render target. */
+		UINT32 numClears; /**< How many times was render target cleared. */
+
+		UINT32 numVertices; /**< Total number of vertices sent to the GPU. */
+		UINT32 numPrimitives; /**< Total number of primitives sent to the GPU. */
+		UINT32 numDrawnSamples; /**< Number of samples drawn by the GPU. */
+
+		UINT32 numBlendStateChanges; /**< How many times did the blend state change. */
+		UINT32 numRasterizerStateChanges; /**< How many times did the rasterizer state change. */
+		UINT32 numDepthStencilStateChanges; /**< How many times did the depth stencil state change. */
+
+		UINT32 numTextureBinds; /**< How many times was a texture bound. */
+		UINT32 numSamplerBinds; /**< How many times was a sampler bound. */
+		UINT32 numVertexBufferBinds; /**< How many times was a vertex buffer bound. */
+		UINT32 numIndexBufferBinds; /**< How many times was an index buffer bound. */
+		UINT32 numGpuParamBufferBinds; /**< How many times was an GPU parameter buffer bound. */
+		UINT32 numGpuProgramBinds; /**< How many times was a GPU program bound. */
+
+		UINT32 numResourceWrites; /**< How many times were GPU resources written to. */
+		UINT32 numResourceReads; /**< How many times were GPU resources read from. */
+
+		UINT32 numObjectsCreated; /**< How many GPU objects were created. */
+		UINT32 numObjectsDestroyed; /**< How many GPU objects were destroyed. */
+	};
+
+	/** Profiler report containing information about GPU sampling data from a single frame. */
+	struct GPUProfilerReport
+	{
+		GPUProfileSample frameSample; /**< Sample containing data for entire frame. */
+		Vector<GPUProfileSample> samples;
+	};
+
+	/**
+	 * Profiler that measures time and amount of various GPU operations.
+	 *
+	 * @note	Core thread only except where noted otherwise.
+	 */
+	class BS_CORE_EXPORT ProfilerGPU : public Module<ProfilerGPU>
+	{
+	private:
+		struct ActiveSample
+		{
+			ProfilerString sampleName;
+			RenderStatsData startStats;
+			RenderStatsData endStats;
+			TimerQueryPtr activeTimeQuery;
+			OcclusionQueryPtr activeOcclusionQuery;
+		};
+
+		struct ActiveFrame
+		{
+			ActiveSample frameSample;
+			Vector<ActiveSample> samples;
+		};
+
+	public:
+		ProfilerGPU();
+
+		/**
+		 * Signals a start of a new frame. Every frame will generate a separate profiling report. This call must be followed
+		 * by endFrame(), and any sampling operations must happen between beginFrame() and endFrame().
+		 */
+		void beginFrame();
+
+		/**
+		 * Signals an end of the currently sampled frame. Results of the sampling will be available once 
+		 * getNumAvailableReports increments. This may take a while as the sampling is scheduled on the core thread and 
+		 * on the GPU.
+		 */
+		void endFrame();
+
+		/**
+		 * Begins sample measurement. Must be followed by endSample().
+		 *
+		 * @param[in]	name	Unique name for the sample you can later use to find the sampling data.
+		 *
+		 * @note	Must be called between beginFrame()/endFrame() calls.
+		 */
+		void beginSample(const ProfilerString& name);
+
+		/**
+		 * Ends sample measurement.
+		 *
+		 * @param[in]	name	Unique name for the sample.
+		 *
+		 * @note	
+		 * Unique name is primarily needed to more easily identify mismatched begin/end sample pairs. Otherwise the name in 
+		 * beginSample() would be enough. Must be called between beginFrame()/endFrame() calls.
+		 */
+		void endSample(const ProfilerString& name);
+
+		/**
+		 * Returns number of profiling reports that are ready but haven't been retrieved yet. 
+		 *
+		 * @note	
+		 * There is an internal limit of maximum number of available reports, where oldest ones will get deleted so make 
+		 * sure to call this often if you don't want to miss some.
+		 * @note
+		 * Thread safe.
+		 */
+		UINT32 getNumAvailableReports();
+
+		/**
+		 * Gets the oldest report available and removes it from the internal list. Throws an exception if no reports are 
+		 * available.
+		 *
+		 * @note	Thread safe.
+		 */
+		GPUProfilerReport getNextReport();
+
+		/** @cond INTERNAL */
+
+		/**
+		 * To be called once per frame from the Core thread.
+		 */
+		void _update();
+
+		/** @endcond */
+
+	private:
+		/** Assigns start values for the provided sample. */
+		void beginSampleInternal(ActiveSample& sample);
+
+		/**	Assigns end values for the provided sample. */
+		void endSampleInternal(ActiveSample& sample);
+
+		/**	Creates a new timer query or returns an existing free query. */
+		TimerQueryPtr getTimerQuery() const;
+
+		/**	Creates a new occlusion query or returns an existing free query. */
+		OcclusionQueryPtr getOcclusionQuery() const;
+
+		/**
+		 * Interprets the active frame results and generates a profiler report for the frame. Provided frame queries must 
+		 * have finished before calling this.
+		 */
+		GPUProfilerReport resolveFrame(ActiveFrame& frame);
+
+		/** Resolves an active sample and converts it to report sample. */
+		void resolveSample(const ActiveSample& sample, GPUProfileSample& reportSample);
+
+	private:
+		ActiveFrame mActiveFrame;
+		bool mIsFrameActive;
+		Stack<UINT32> mActiveSampleIndexes;
+
+		Queue<ActiveFrame> mUnresolvedFrames;
+		Queue<GPUProfilerReport> mReadyReports;
+
+		mutable Stack<TimerQueryPtr> mFreeTimerQueries;
+		mutable Stack<OcclusionQueryPtr> mFreeOcclusionQueries;
+
+		BS_MUTEX(mMutex);
+	};
+
+	/** @} */
 }

+ 75 - 77
BansheeCore/Include/BsProfilingManager.h

@@ -1,78 +1,76 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsModule.h"
-#include "BsProfilerCPU.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Contains data about a profiling session.
-	 */
-	struct ProfilerReport
-	{
-		CPUProfilerReport cpuReport;
-	};
-
-	/**
-	 * @brief	Type of thread used by the profiler.
-	 */
-	enum class ProfiledThread
-	{
-		Sim,
-		Core
-	};
-
-	/**
-	 * @brief	Tracks CPU profiling information with each frame for sim and core threads.
-	 *
-	 * @note	Sim thread only unless specified otherwise.
-	 */
-	class BS_CORE_EXPORT ProfilingManager : public Module<ProfilingManager>
-	{
-	public:
-		ProfilingManager();
-		~ProfilingManager();
-
-		/**
-		 * @brief	Called every frame.
-		 *
-		 * @note	Internal method.
-		 */
-		void _update();
-
-		/**
-		 * @brief	Called every frame from the core thread.
-		 * 			
-		 * @note	Internal method. Core thread only.
-		 */
-		void _updateCore();
-
-		/**
-		 * @brief	Returns a profiler report for the specified frame, for the specified thread.
-		 *
-		 * @param	Profiler report index, ranging [0, NUM_SAVED_FRAMES]. 0 always returns the latest
-		 * 					 report. Increasing indexes return reports for older and older frames. Out of range
-		 * 					 indexes will be clamped.
-		 *
-		 * @note	Profiler reports get updated every frame. Oldest reports that no longer fit in the saved reports buffer
-		 * 			are discarded.
-		 */
-		const ProfilerReport& getReport(ProfiledThread thread, UINT32 idx = 0) const;
-
-	private:
-		static const UINT32 NUM_SAVED_FRAMES;
-		ProfilerReport* mSavedSimReports;
-		UINT32 mNextSimReportIdx;
-
-		ProfilerReport* mSavedCoreReports;
-		UINT32 mNextCoreReportIdx;
-
-		BS_MUTEX(mSync);
-	};
-
-	/**
-	 * @brief	Quick way to access the profiler.
-	 */
-	BS_CORE_EXPORT ProfilingManager& gProfiler();
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsModule.h"
+#include "BsProfilerCPU.h"
+
+namespace BansheeEngine
+{
+	/** @cond INTERNAL */
+	/** @addtogroup Profiling
+	 *  @{
+	 */
+
+	/**	Contains data about a profiling session. */
+	struct ProfilerReport
+	{
+		CPUProfilerReport cpuReport;
+	};
+
+	/**	Type of thread used by the profiler. */
+	enum class ProfiledThread
+	{
+		Sim,
+		Core
+	};
+
+	/**
+	 * Tracks CPU profiling information with each frame for sim and core threads.
+	 *
+	 * @note	Sim thread only unless specified otherwise.
+	 */
+	class BS_CORE_EXPORT ProfilingManager : public Module<ProfilingManager>
+	{
+	public:
+		ProfilingManager();
+		~ProfilingManager();
+
+		/** Called every frame. */
+		void _update();
+
+		/**
+		 * Called every frame from the core thread.
+		 * 			
+		 * @note	Core thread only.
+		 */
+		void _updateCore();
+
+		/**
+		 * Returns a profiler report for the specified frame, for the specified thread.
+		 *
+		 * @param[in]	Profiler report index, ranging [0, NUM_SAVED_FRAMES]. 0 always returns the latest  report. 
+		 *				Increasing indexes return reports for older and older frames. Out of range  indexes will be clamped.
+		 *
+		 * @note	
+		 * Profiler reports get updated every frame. Oldest reports that no longer fit in the saved reports buffer are 
+		 * discarded.
+		 */
+		const ProfilerReport& getReport(ProfiledThread thread, UINT32 idx = 0) const;
+
+	private:
+		static const UINT32 NUM_SAVED_FRAMES;
+		ProfilerReport* mSavedSimReports;
+		UINT32 mNextSimReportIdx;
+
+		ProfilerReport* mSavedCoreReports;
+		UINT32 mNextCoreReportIdx;
+
+		BS_MUTEX(mSync);
+	};
+
+	/** Easy way to access ProfilingManager. */
+	BS_CORE_EXPORT ProfilingManager& gProfiler();
+
+	/** @} */
+	/** @endcond */
 }

+ 248 - 250
BansheeCore/Include/BsRasterizerState.h

@@ -1,251 +1,249 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsIReflectable.h"
-#include "BsCoreObject.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Structure that describes pipeline rasterizer state. Used for initializing
-	 *			a RasterizerState.
-	 *
-	 * @see		RasterizerState
-	 */
-	struct BS_CORE_EXPORT RASTERIZER_STATE_DESC
-	{
-		RASTERIZER_STATE_DESC()
-			: polygonMode(PM_SOLID)
-			, cullMode(CULL_COUNTERCLOCKWISE)
-			, depthBias(0)
-			, depthBiasClamp(0.0f)
-			, slopeScaledDepthBias(0.0f)
-			, depthClipEnable(true)
-			, scissorEnable(false)
-			, multisampleEnable(true)
-			, antialiasedLineEnable(false)
-		{ }
-
-		bool operator==(const RASTERIZER_STATE_DESC& rhs) const;
-
-		PolygonMode polygonMode;
-		CullingMode cullMode;
-
-		float depthBias;
-		float depthBiasClamp;
-		float slopeScaledDepthBias;
-
-		bool depthClipEnable;
-		bool scissorEnable;
-		bool multisampleEnable;
-		bool antialiasedLineEnable;
-	};
-
-	/**
-	 * @brief	Information about a rasterizer state.
-	 */
-	class BS_CORE_EXPORT RasterizerProperties
-	{
-	public:
-		RasterizerProperties(const RASTERIZER_STATE_DESC& desc);
-
-		/**
-		 * @brief	Polygon mode allows you to draw polygons as solid objects or as wireframe by
-		 *			just drawing their edges.
-		 */
-		PolygonMode getPolygonMode() const { return mData.polygonMode; }
-
-		/**
-		 * @brief	Sets vertex winding order. Faces that contain vertices with this order will 
-		 *			be culled and not rasterized. Used primarily for saving cycles by not rendering
-		 *			backfacing faces.
-		 */
-		CullingMode getCullMode() const { return mData.cullMode; }
-
-		/**
-		* @brief	Represents a constant depth bias that will offset the depth values of new pixels 
-		*			by the specified amount.
-		*
-		* @note		This is useful if you want to avoid z fighting for objects at the same or similar depth.
-		*/
-		float getDepthBias() const { return mData.depthBias; }
-
-		/**
-		 * @brief	Maximum depth bias value.
-		 */
-		float getDepthBiasClamp() const { return mData.depthBiasClamp; }
-
-		/**
-		 * @brief	Represents a dynamic depth bias that increases as the slope of the rendered polygons 
-		 *			surface increases. Resulting value offsets depth values of new pixels. This offset will 
-		 *			be added on top of the constant depth bias.
-		 *
-		 * @note	This is useful if you want to avoid z fighting for objects at the same or similar depth.
-		 */
-		float getSlopeScaledDepthBias() const { return mData.slopeScaledDepthBias; }
-
-		/**
-		 * @brief	If true, clipping of polygons past the far Z plane is enabled. This ensures proper
-		 *			Z ordering for polygons outside of valid depth range (otherwise they all have the same
-		 *			depth). It can be useful to disable if you are performing stencil operations that count on
-		 *			objects having a front and a back (like stencil shadow) and don't want to clip the back.
-		 */
-		bool getDepthClipEnable() const { return mData.depthClipEnable; }
-
-		/**
-		 * @brief	Scissor rectangle allows you to cull all pixels outside of the scissor rectangle.
-		 *			
-		 * @see		RenderAPICore::setScissorRect
-		 */
-		bool getScissorEnable() const { return mData.scissorEnable; }
-
-		/**
-		 * @brief	Determines how are samples in multi-sample render targets handled.
-		 *			If disabled all samples in the render target will be written the same value, 
-		 *			and if enabled each sample will be generated separately.
-		 *			
-		 * @note	In order to get an antialiased image you need to both enable this option and use
-		 *			a MSAA render target.
-		 */
-		bool getMultisampleEnable() const { return mData.multisampleEnable; }
-
-		/**
-		 * @brief	Determines should the lines be antialiased. This is separate from multi-sample
-		 *			antialiasing setting as lines can be antialiased without multi-sampling.
-		 *
-		 * @note	This setting is usually ignored if MSAA is used, as that provides sufficient antialiasing.
-		 */
-		bool getAntialiasedLineEnable() const { return mData.antialiasedLineEnable; }
-
-		/**
-		 * @brief	Returns the hash value generated from the rasterizer state properties.
-		 */
-		UINT64 getHash() const { return mHash; }
-
-	protected:
-		friend class RasterizerState;
-		friend class RasterizerStateCore;
-		friend class RasterizerStateRTTI;
-
-		RASTERIZER_STATE_DESC mData;
-		UINT64 mHash;
-	};
-
-	/**
-	 * @brief	Core thread version of a rasterizer state.
-	 *
-	 * @see		RasterizerState
-	 *
-	 * @note	Core thread.
-	 */
-	class BS_CORE_EXPORT RasterizerStateCore : public CoreObjectCore
-	{
-	public:
-		virtual ~RasterizerStateCore();
-
-		/**
-		 * @brief	Returns information about the rasterizer state.
-		 */
-		const RasterizerProperties& getProperties() const;
-
-		/**
-		 * @brief	Returns a unique state ID. Only the lowest 10 bits are used.
-		 */
-		UINT32 getId() const { return mId; }
-
-		/**
-		 * @brief	Returns the default rasterizer state.
-		 */
-		static const SPtr<RasterizerStateCore>& getDefault();
-
-	protected:
-		friend class RenderStateCoreManager;
-
-		RasterizerStateCore(const RASTERIZER_STATE_DESC& desc, UINT32 id);
-
-		/**
-		 * @copydoc	CoreObjectCore::initialize
-		 */
-		void initialize() override;
-
-		/**
-		 * @brief	Creates any API-specific state objects.
-		 */
-		virtual void createInternal() { }
-
-		RasterizerProperties mProperties;
-		UINT32 mId;
-	};
-
-	/**
-	 * @brief	Render system pipeline state that allows you to modify how an object is rasterized.
-	 *			i.e. how are polygons converted to pixels.
-	 *
-	 * @note	Rasterizer states are immutable. Sim thread only.
-	 */
-	class BS_CORE_EXPORT RasterizerState : public IReflectable, public CoreObject
-	{
-	public:
-		virtual ~RasterizerState();
-
-		/**
-		 * @brief	Returns information about the rasterizer state.
-		 */
-		const RasterizerProperties& getProperties() const;
-
-		/**
-		 * @brief	Retrieves a core implementation of the rasterizer state usable only from the
-		 *			core thread.
-		 */
-		SPtr<RasterizerStateCore> getCore() const;
-
-		/**
-		 * @brief	Creates a new rasterizer state using the specified rasterizer state descriptor structure.
-		 */
-		static RasterizerStatePtr create(const RASTERIZER_STATE_DESC& desc);
-
-		/**
-		 * @brief	Returns the default rasterizer state.
-		 */
-		static const RasterizerStatePtr& getDefault();
-
-		/**
-		 * @brief	Generates a hash value from a rasterizer state descriptor.
-		 */
-		static UINT64 generateHash(const RASTERIZER_STATE_DESC& desc);
-
-	protected:
-		friend class RenderStateManager;
-
-		RasterizerState(const RASTERIZER_STATE_DESC& desc);
-		
-		/**
-		 * @copydoc	CoreObjectCore::createCore
-		 */
-		SPtr<CoreObjectCore> createCore() const override;
-
-		RasterizerProperties mProperties;
-		mutable UINT32 mId;
-
-		/************************************************************************/
-		/* 								RTTI		                     		*/
-		/************************************************************************/
-
-	public:
-		friend class RasterizerStateRTTI;
-		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;	
-	};
-}
-
-/**
- * @brief	Hash value generator for RASTERIZER_STATE_DESC.
- */
-template<>
-struct std::hash<BansheeEngine::RASTERIZER_STATE_DESC>
-{
-	size_t operator()(const BansheeEngine::RASTERIZER_STATE_DESC& value) const
-	{
-		return (size_t)BansheeEngine::RasterizerState::generateHash(value);
-	}
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsIReflectable.h"
+#include "BsCoreObject.h"
+
+namespace BansheeEngine
+{
+	/**
+	 * @brief	Structure that describes pipeline rasterizer state. Used for initializing
+	 *			a RasterizerState.
+	 *
+	 * @see		RasterizerState
+	 */
+	struct BS_CORE_EXPORT RASTERIZER_STATE_DESC
+	{
+		RASTERIZER_STATE_DESC()
+			: polygonMode(PM_SOLID)
+			, cullMode(CULL_COUNTERCLOCKWISE)
+			, depthBias(0)
+			, depthBiasClamp(0.0f)
+			, slopeScaledDepthBias(0.0f)
+			, depthClipEnable(true)
+			, scissorEnable(false)
+			, multisampleEnable(true)
+			, antialiasedLineEnable(false)
+		{ }
+
+		bool operator==(const RASTERIZER_STATE_DESC& rhs) const;
+
+		PolygonMode polygonMode;
+		CullingMode cullMode;
+
+		float depthBias;
+		float depthBiasClamp;
+		float slopeScaledDepthBias;
+
+		bool depthClipEnable;
+		bool scissorEnable;
+		bool multisampleEnable;
+		bool antialiasedLineEnable;
+	};
+
+	/**
+	 * @brief	Properties of RasterizerState. Shared between sim and core thread versions of RasterizerState.
+	 */
+	class BS_CORE_EXPORT RasterizerProperties
+	{
+	public:
+		RasterizerProperties(const RASTERIZER_STATE_DESC& desc);
+
+		/**
+		 * @brief	Polygon mode allows you to draw polygons as solid objects or as wireframe by
+		 *			just drawing their edges.
+		 */
+		PolygonMode getPolygonMode() const { return mData.polygonMode; }
+
+		/**
+		 * @brief	Sets vertex winding order. Faces that contain vertices with this order will 
+		 *			be culled and not rasterized. Used primarily for saving cycles by not rendering
+		 *			backfacing faces.
+		 */
+		CullingMode getCullMode() const { return mData.cullMode; }
+
+		/**
+		* @brief	Represents a constant depth bias that will offset the depth values of new pixels 
+		*			by the specified amount.
+		*
+		* @note		This is useful if you want to avoid z fighting for objects at the same or similar depth.
+		*/
+		float getDepthBias() const { return mData.depthBias; }
+
+		/**
+		 * @brief	Maximum depth bias value.
+		 */
+		float getDepthBiasClamp() const { return mData.depthBiasClamp; }
+
+		/**
+		 * @brief	Represents a dynamic depth bias that increases as the slope of the rendered polygons 
+		 *			surface increases. Resulting value offsets depth values of new pixels. This offset will 
+		 *			be added on top of the constant depth bias.
+		 *
+		 * @note	This is useful if you want to avoid z fighting for objects at the same or similar depth.
+		 */
+		float getSlopeScaledDepthBias() const { return mData.slopeScaledDepthBias; }
+
+		/**
+		 * @brief	If true, clipping of polygons past the far Z plane is enabled. This ensures proper
+		 *			Z ordering for polygons outside of valid depth range (otherwise they all have the same
+		 *			depth). It can be useful to disable if you are performing stencil operations that count on
+		 *			objects having a front and a back (like stencil shadow) and don't want to clip the back.
+		 */
+		bool getDepthClipEnable() const { return mData.depthClipEnable; }
+
+		/**
+		 * @brief	Scissor rectangle allows you to cull all pixels outside of the scissor rectangle.
+		 *			
+		 * @see		RenderAPICore::setScissorRect
+		 */
+		bool getScissorEnable() const { return mData.scissorEnable; }
+
+		/**
+		 * @brief	Determines how are samples in multi-sample render targets handled.
+		 *			If disabled all samples in the render target will be written the same value, 
+		 *			and if enabled each sample will be generated separately.
+		 *			
+		 * @note	In order to get an antialiased image you need to both enable this option and use
+		 *			a MSAA render target.
+		 */
+		bool getMultisampleEnable() const { return mData.multisampleEnable; }
+
+		/**
+		 * @brief	Determines should the lines be antialiased. This is separate from multi-sample
+		 *			antialiasing setting as lines can be antialiased without multi-sampling.
+		 *
+		 * @note	This setting is usually ignored if MSAA is used, as that provides sufficient antialiasing.
+		 */
+		bool getAntialiasedLineEnable() const { return mData.antialiasedLineEnable; }
+
+		/**
+		 * @brief	Returns the hash value generated from the rasterizer state properties.
+		 */
+		UINT64 getHash() const { return mHash; }
+
+	protected:
+		friend class RasterizerState;
+		friend class RasterizerStateCore;
+		friend class RasterizerStateRTTI;
+
+		RASTERIZER_STATE_DESC mData;
+		UINT64 mHash;
+	};
+
+	/**
+	 * @brief	Core thread version of RasterizerState.
+	 *
+	 * @note	Core thread.
+	 */
+	class BS_CORE_EXPORT RasterizerStateCore : public CoreObjectCore
+	{
+	public:
+		virtual ~RasterizerStateCore();
+
+		/**
+		 * @brief	Returns information about the rasterizer state.
+		 */
+		const RasterizerProperties& getProperties() const;
+
+		/**
+		 * @brief	Returns a unique state ID. Only the lowest 10 bits are used.
+		 */
+		UINT32 getId() const { return mId; }
+
+		/**
+		 * @brief	Returns the default rasterizer state.
+		 */
+		static const SPtr<RasterizerStateCore>& getDefault();
+
+	protected:
+		friend class RenderStateCoreManager;
+
+		RasterizerStateCore(const RASTERIZER_STATE_DESC& desc, UINT32 id);
+
+		/**
+		 * @copydoc	CoreObjectCore::initialize
+		 */
+		void initialize() override;
+
+		/**
+		 * @brief	Creates any API-specific state objects.
+		 */
+		virtual void createInternal() { }
+
+		RasterizerProperties mProperties;
+		UINT32 mId;
+	};
+
+	/**
+	 * @brief	Render system pipeline state that allows you to modify how an object is rasterized.
+	 *			i.e. how are polygons converted to pixels.
+	 *
+	 * @note	Rasterizer states are immutable. Sim thread only.
+	 */
+	class BS_CORE_EXPORT RasterizerState : public IReflectable, public CoreObject
+	{
+	public:
+		virtual ~RasterizerState();
+
+		/**
+		 * @brief	Returns information about the rasterizer state.
+		 */
+		const RasterizerProperties& getProperties() const;
+
+		/**
+		 * @brief	Retrieves a core implementation of the rasterizer state usable only from the
+		 *			core thread.
+		 */
+		SPtr<RasterizerStateCore> getCore() const;
+
+		/**
+		 * @brief	Creates a new rasterizer state using the specified rasterizer state descriptor structure.
+		 */
+		static RasterizerStatePtr create(const RASTERIZER_STATE_DESC& desc);
+
+		/**
+		 * @brief	Returns the default rasterizer state.
+		 */
+		static const RasterizerStatePtr& getDefault();
+
+		/**
+		 * @brief	Generates a hash value from a rasterizer state descriptor.
+		 */
+		static UINT64 generateHash(const RASTERIZER_STATE_DESC& desc);
+
+	protected:
+		friend class RenderStateManager;
+
+		RasterizerState(const RASTERIZER_STATE_DESC& desc);
+		
+		/**
+		 * @copydoc	CoreObjectCore::createCore
+		 */
+		SPtr<CoreObjectCore> createCore() const override;
+
+		RasterizerProperties mProperties;
+		mutable UINT32 mId;
+
+		/************************************************************************/
+		/* 								RTTI		                     		*/
+		/************************************************************************/
+
+	public:
+		friend class RasterizerStateRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		virtual RTTITypeBase* getRTTI() const override;	
+	};
+}
+
+/**
+ * @brief	Hash value generator for RASTERIZER_STATE_DESC.
+ */
+template<>
+struct std::hash<BansheeEngine::RASTERIZER_STATE_DESC>
+{
+	size_t operator()(const BansheeEngine::RASTERIZER_STATE_DESC& value) const
+	{
+		return (size_t)BansheeEngine::RasterizerState::generateHash(value);
+	}
 };

+ 188 - 187
BansheeCore/Include/BsRenderStats.h

@@ -1,188 +1,189 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsModule.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Common types to track resource statistics for.
-	 */
-	enum RenderStatResourceType
-	{
-		RenderStatObject_IndexBuffer,
-		RenderStatObject_VertexBuffer,
-		RenderStatObject_GpuBuffer,
-		RenderStatObject_GpuParamBuffer,
-		RenderStatObject_Texture,
-		RenderStatObject_GpuProgram,
-		RenderStatObject_Query
-	};
-
-	/**
-	 * @brief	Object that stores various render statistics.
-	 */
-	struct BS_CORE_EXPORT RenderStatsData
-	{
-		RenderStatsData()
-		: numDrawCalls(0), numRenderTargetChanges(0), numPresents(0), numClears(0),
-		  numVertices(0), numPrimitives(0), numBlendStateChanges(0), numRasterizerStateChanges(0), 
-		  numDepthStencilStateChanges(0), numTextureBinds(0), numSamplerBinds(0), numVertexBufferBinds(0), 
-		  numIndexBufferBinds(0), numGpuParamBufferBinds(0), numGpuProgramBinds(0)
-		{ }
-
-		UINT64 numDrawCalls;
-		UINT64 numRenderTargetChanges;
-		UINT64 numPresents;
-		UINT64 numClears;
-
-		UINT64 numVertices;
-		UINT64 numPrimitives;
-
-		UINT64 numBlendStateChanges; 
-		UINT64 numRasterizerStateChanges; 
-		UINT64 numDepthStencilStateChanges;
-
-		UINT64 numTextureBinds; 
-		UINT64 numSamplerBinds; 
-		UINT64 numVertexBufferBinds; 
-		UINT64 numIndexBufferBinds;
-		UINT64 numGpuParamBufferBinds;
-		UINT64 numGpuProgramBinds; 
-
-		UINT64 numResourceWrites;
-		UINT64 numResourceReads;
-
-		UINT64 numObjectsCreated; 
-		UINT64 numObjectsDestroyed;
-	};
-
-	/**
-	 * @brief	Tracks various render system statistics.
-	 *
-	 * @note	Core thread only.
-	 */
-	class BS_CORE_EXPORT RenderStats : public Module<RenderStats>
-	{
-	public:
-		/** Increments draw call counter indicating how many times were
-		 *  render system API Draw methods called. */
-		void incNumDrawCalls() { mData.numDrawCalls++; }
-
-		/** Increments render target change counter indicating how many
-		 *  times did the active render target change. */
-		void incNumRenderTargetChanges() { mData.numRenderTargetChanges++; }
-
-		/** Increments render target present counter indicating how many
-		 *  times did the buffer swap happen. */
-		void incNumPresents() { mData.numPresents++; }
-
-		/** Increments render target clear counter indicating how many
-		 *  times did the target the cleared, entirely or partially. */
-		void incNumClears() { mData.numClears++; }
-
-		/** Increments vertex draw counter indicating how many
-		 *  vertices were sent to the pipeline. */
-		void addNumVertices(UINT32 count) { mData.numVertices += count; }
-
-		/** Increments primitive draw counter indicating how many
-		 *  primitives were sent to the pipeline. */
-		void addNumPrimitives(UINT32 count) { mData.numPrimitives += count; }
-
-		/** Increments blend state change counter indicating how many
-		 *  times was a blend state bound to the pipeline. */
-		void incNumBlendStateChanges() { mData.numBlendStateChanges++; }
-
-		/** Increments rasterizer state change counter indicating how many
-		 *  times was a rasterizer state bound to the pipeline. */
-		void incNumRasterizerStateChanges() { mData.numRasterizerStateChanges++; }
-
-		/** Increments depth/stencil state change counter indicating how many
-		 *  times was a depth/stencil state bound to the pipeline. */
-		void incNumDepthStencilStateChanges() { mData.numDepthStencilStateChanges++; }
-
-		/** Increments texture change counter indicating how many
-		 *  times was a texture bound to the pipeline. */
-		void incNumTextureBinds() { mData.numTextureBinds++; }
-
-		/** Increments sampler state change counter indicating how many
-		 *  times was a sampler state bound to the pipeline. */
-		void incNumSamplerBinds() { mData.numSamplerBinds++; }
-
-		/** Increments vertex buffer change counter indicating how many
-		 *  times was a vertex buffer bound to the pipeline. */
-		void incNumVertexBufferBinds() { mData.numVertexBufferBinds++; }
-
-		/** Increments index buffer change counter indicating how many
-		 *  times was a index buffer bound to the pipeline. */
-		void incNumIndexBufferBinds() { mData.numIndexBufferBinds++; }
-
-		/** Increments GPU parameter buffer change counter indicating how many
-		 *  times was a GPU parameter buffer bound to the pipeline. */
-		void incNumGpuParamBufferBinds() { mData.numGpuParamBufferBinds++; }
-
-		/** Increments GPU program change counter indicating how many
-		 *  times was a GPU program bound to the pipeline. */
-		void incNumGpuProgramBinds() { mData.numGpuProgramBinds++; }
-
-		/**
-		 * Increments created GPU resource counter. 
-		 *
-		 * @param	category	Category of the resource.
-		 */
-		void incResCreated(UINT32 category) 
-		{
-			// TODO - I'm ignoring resourceType for now. Later I will want to
-			// count object creation/destruction/read/write per type. I will
-			// also want to allow the caller to assign names to specific "resourceType" id.
-			// (Since many types will be RenderAPI specific).
-
-			// TODO - I should also track number of active GPU objects using this method, instead
-			// of just keeping track of how many were created and destroyed during the frame.
-
-			mData.numObjectsCreated++;
-		}
-
-		/**
-		 * Increments destroyed GPU resource counter. 
-		 *
-		 * @param	category	Category of the resource.
-		 */
-		void incResDestroyed(UINT32 category) { mData.numObjectsDestroyed++; }
-
-		/**
-		 * Increments GPU resource read counter. 
-		 *
-		 * @param	category	Category of the resource.
-		 */
-		void incResRead(UINT32 category) { mData.numResourceReads++; }
-
-		/**
-		 * Increments GPU resource write counter. 
-		 *
-		 * @param	category	Category of the resource.
-		 */
-		void incResWrite(UINT32 category) { mData.numResourceWrites++; }
-
-		/**
-		 * Returns an object containing various rendering statistics.
-		 *			
-		 * @note	Do not modify the returned state unless you know what you are doing, it will
-		 *			change the actual internal object.
-		 */
-		RenderStatsData& getData() { return mData; }
-
-	private:
-		RenderStatsData mData;
-	};
-
-#if BS_PROFILING_ENABLED
-	#define BS_INC_RENDER_STAT_CAT(Stat, Category) RenderStats::instance().inc##Stat##((UINT32)##Category##)
-	#define BS_INC_RENDER_STAT(Stat) RenderStats::instance().inc##Stat##()
-	#define BS_ADD_RENDER_STAT(Stat, Count) RenderStats::instance().add##Stat##(##Count##)
-#else
-	#define BS_INC_RENDER_STAT_CAT(Stat, Category)
-	#define BS_INC_RENDER_STAT(Stat)
-	#define BS_ADD_RENDER_STAT(Stat, Count)
-#endif
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsModule.h"
+
+namespace BansheeEngine
+{
+	/** @cond INTERNAL */
+	/** @addtogroup Profiling
+	 *  @{
+	 */
+
+	/**	Common object types to track resource statistics for. */
+	enum RenderStatResourceType
+	{
+		RenderStatObject_IndexBuffer,
+		RenderStatObject_VertexBuffer,
+		RenderStatObject_GpuBuffer,
+		RenderStatObject_GpuParamBuffer,
+		RenderStatObject_Texture,
+		RenderStatObject_GpuProgram,
+		RenderStatObject_Query
+	};
+
+	/** Object that stores various render statistics. */
+	struct BS_CORE_EXPORT RenderStatsData
+	{
+		RenderStatsData()
+		: numDrawCalls(0), numRenderTargetChanges(0), numPresents(0), numClears(0),
+		  numVertices(0), numPrimitives(0), numBlendStateChanges(0), numRasterizerStateChanges(0), 
+		  numDepthStencilStateChanges(0), numTextureBinds(0), numSamplerBinds(0), numVertexBufferBinds(0), 
+		  numIndexBufferBinds(0), numGpuParamBufferBinds(0), numGpuProgramBinds(0)
+		{ }
+
+		UINT64 numDrawCalls;
+		UINT64 numRenderTargetChanges;
+		UINT64 numPresents;
+		UINT64 numClears;
+
+		UINT64 numVertices;
+		UINT64 numPrimitives;
+
+		UINT64 numBlendStateChanges; 
+		UINT64 numRasterizerStateChanges; 
+		UINT64 numDepthStencilStateChanges;
+
+		UINT64 numTextureBinds; 
+		UINT64 numSamplerBinds; 
+		UINT64 numVertexBufferBinds; 
+		UINT64 numIndexBufferBinds;
+		UINT64 numGpuParamBufferBinds;
+		UINT64 numGpuProgramBinds; 
+
+		UINT64 numResourceWrites;
+		UINT64 numResourceReads;
+
+		UINT64 numObjectsCreated; 
+		UINT64 numObjectsDestroyed;
+	};
+
+	/**
+	 * Tracks various render system statistics.
+	 *
+	 * @note	Core thread only.
+	 */
+	class BS_CORE_EXPORT RenderStats : public Module<RenderStats>
+	{
+	public:
+		/** Increments draw call counter indicating how many times were render system API Draw methods called. */
+		void incNumDrawCalls() { mData.numDrawCalls++; }
+
+		/** Increments render target change counter indicating how many times did the active render target change. */
+		void incNumRenderTargetChanges() { mData.numRenderTargetChanges++; }
+
+		/** Increments render target present counter indicating how many times did the buffer swap happen. */
+		void incNumPresents() { mData.numPresents++; }
+
+		/** 
+		 * Increments render target clear counter indicating how many times did the target the cleared, entirely or 
+		 * partially. 
+		 */
+		void incNumClears() { mData.numClears++; }
+
+		/** Increments vertex draw counter indicating how many vertices were sent to the pipeline. */
+		void addNumVertices(UINT32 count) { mData.numVertices += count; }
+
+		/** Increments primitive draw counter indicating how many primitives were sent to the pipeline. */
+		void addNumPrimitives(UINT32 count) { mData.numPrimitives += count; }
+
+		/** Increments blend state change counter indicating how many times was a blend state bound to the pipeline. */
+		void incNumBlendStateChanges() { mData.numBlendStateChanges++; }
+
+		/** 
+		 * Increments rasterizer state change counter indicating how many times was a rasterizer state bound to the 
+		 * pipeline.
+		 */
+		void incNumRasterizerStateChanges() { mData.numRasterizerStateChanges++; }
+
+		/** 
+		 * Increments depth/stencil state change counter indicating how many times was a depth/stencil state bound to the 
+		 * pipeline. 
+		 */
+		void incNumDepthStencilStateChanges() { mData.numDepthStencilStateChanges++; }
+
+		/** Increments texture change counter indicating how many times was a texture bound to the pipeline. */
+		void incNumTextureBinds() { mData.numTextureBinds++; }
+
+		/** Increments sampler state change counter indicating how many times was a sampler state bound to the pipeline. */
+		void incNumSamplerBinds() { mData.numSamplerBinds++; }
+
+		/** Increments vertex buffer change counter indicating how many times was a vertex buffer bound to the pipeline. */
+		void incNumVertexBufferBinds() { mData.numVertexBufferBinds++; }
+
+		/** Increments index buffer change counter indicating how many times was a index buffer bound to the pipeline. */
+		void incNumIndexBufferBinds() { mData.numIndexBufferBinds++; }
+
+		/** 
+		 * Increments GPU parameter buffer change counter indicating how many times was a GPU parameter buffer bound to the 
+		 * pipeline.
+		 */
+		void incNumGpuParamBufferBinds() { mData.numGpuParamBufferBinds++; }
+
+		/** Increments GPU program change counter indicating how many times was a GPU program bound to the pipeline. */
+		void incNumGpuProgramBinds() { mData.numGpuProgramBinds++; }
+
+		/**
+		 * Increments created GPU resource counter. 
+		 *
+		 * @param[in]	category	Category of the resource.
+		 */
+		void incResCreated(UINT32 category) 
+		{
+			// TODO - I'm ignoring resourceType for now. Later I will want to
+			// count object creation/destruction/read/write per type. I will
+			// also want to allow the caller to assign names to specific "resourceType" id.
+			// (Since many types will be RenderAPI specific).
+
+			// TODO - I should also track number of active GPU objects using this method, instead
+			// of just keeping track of how many were created and destroyed during the frame.
+
+			mData.numObjectsCreated++;
+		}
+
+		/**
+		 * Increments destroyed GPU resource counter. 
+		 *
+		 * @param[in]	category	Category of the resource.
+		 */
+		void incResDestroyed(UINT32 category) { mData.numObjectsDestroyed++; }
+
+		/**
+		 * Increments GPU resource read counter. 
+		 *
+		 * @param[in]	category	Category of the resource.
+		 */
+		void incResRead(UINT32 category) { mData.numResourceReads++; }
+
+		/**
+		 * Increments GPU resource write counter. 
+		 *
+		 * @param[in]	category	Category of the resource.
+		 */
+		void incResWrite(UINT32 category) { mData.numResourceWrites++; }
+
+		/**
+		 * Returns an object containing various rendering statistics.
+		 *			
+		 * @note	
+		 * Do not modify the returned state unless you know what you are doing, it will change the actual internal object.
+		 */
+		RenderStatsData& getData() { return mData; }
+
+	private:
+		RenderStatsData mData;
+	};
+
+#if BS_PROFILING_ENABLED
+	#define BS_INC_RENDER_STAT_CAT(Stat, Category) RenderStats::instance().inc##Stat##((UINT32)##Category##)
+	#define BS_INC_RENDER_STAT(Stat) RenderStats::instance().inc##Stat##()
+	#define BS_ADD_RENDER_STAT(Stat, Count) RenderStats::instance().add##Stat##(##Count##)
+#else
+	#define BS_INC_RENDER_STAT_CAT(Stat, Category)
+	#define BS_INC_RENDER_STAT(Stat)
+	#define BS_ADD_RENDER_STAT(Stat, Count)
+#endif
+
+	/** @} */
+	/** @endcond */
 }

+ 221 - 223
BansheeCore/Include/BsSamplerState.h

@@ -1,224 +1,222 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsMatrix4.h"
-#include "BsPixelUtil.h"
-#include "BsTexture.h"
-#include "BsColor.h"
-#include "BsIReflectable.h"
-#include "BsCoreObject.h"
-
-namespace BansheeEngine 
-{
-	/**
-	 * @brief	Structure used for initializing a SamplerState.
-	 *
-	 * @see		SamplerState
-	 */
-	struct BS_CORE_EXPORT SAMPLER_STATE_DESC
-	{
-		SAMPLER_STATE_DESC()
-			: minFilter(FO_LINEAR), magFilter(FO_LINEAR), mipFilter(FO_POINT), 
-			maxAniso(0), mipmapBias(0), comparisonFunc(CMPF_ALWAYS_FAIL), mipMin(-FLT_MAX), 
-			mipMax(FLT_MAX), borderColor(Color::White)
-		{ }
-
-		bool operator==(const SAMPLER_STATE_DESC& rhs) const;
-
-		UVWAddressingMode addressMode;
-		FilterOptions minFilter;
-		FilterOptions magFilter;
-		FilterOptions mipFilter;
-		UINT32 maxAniso;
-		float mipmapBias;
-		float mipMin;
-		float mipMax;
-		Color borderColor;
-		CompareFunction comparisonFunc;
-	};
-
-	/**
-	 * @brief	Information about a sampler state.
-	 */
-	class BS_CORE_EXPORT SamplerProperties
-	{
-	public:
-		SamplerProperties(const SAMPLER_STATE_DESC& desc);
-
-		/**
-		 * @brief	Returns texture addressing mode for each possible texture coordinate. Addressing
-		 *			modes determine how are texture coordinates outside of [0, 1] range handled.
-		 */
-		const UVWAddressingMode& getTextureAddressingMode() const { return mData.addressMode; }
-
-		/**
-		 * @brief	Gets the filtering used when sampling from a texture.
-		 */
-        FilterOptions getTextureFiltering(FilterType ftpye) const;
-
-		/**
-		 * @brief	Gets the anisotropy level. Higher anisotropy means better filtering
-		 *			for textures displayed on an angled slope relative to the viewer.
-		 */
-		unsigned int getTextureAnisotropy() const { return mData.maxAniso; }
-
-		/**
-		 * @brief	Gets a function that compares sampled data with existing sampled data.
-		 */
-		CompareFunction getComparisonFunction() const { return mData.comparisonFunc; }
-
-		/**
-		* @brief	Mipmap bias allows you to adjust the mipmap selection calculation. Negative values 
-		*			force a larger mipmap to be used, and positive values smaller. Units are in values
-		*			of mip levels, so -1 means use a mipmap one level higher than default.
-		*/
-		float getTextureMipmapBias() const { return mData.mipmapBias; }
-
-		/**
-		 * @brief	Returns the minimum mip map level.
-		 */
-		float getMinimumMip() const { return mData.mipMin; }
-
-		/**
-		 * @brief	Returns the maximum mip map level.
-		 */
-		float getMaximumMip() const { return mData.mipMax; }
-
-		/**
-		 * @brief	Gets the border color that will be used when border texture addressing is used
-		 *			and texture address is outside of the valid range.
-		 */
-		const Color& getBorderColor() const;
-
-		/**
-		 * @brief	Returns the hash value generated from the sampler state properties.
-		 */
-		UINT64 getHash() const { return mHash; }
-
-		/**
-		 * @brief	Returns the descriptor originally used for creating the sampler state.
-		 */
-		SAMPLER_STATE_DESC getDesc() const { return mData; }
-
-	protected:
-		friend class SamplerState;
-		friend class SamplerStateCore;
-		friend class SamplerStateRTTI;
-
-		SAMPLER_STATE_DESC mData;
-		UINT64 mHash;
-	};
-
-	/**
-	 * @brief	Core thread version of a sampler state.
-	 *
-	 * @see		SamplerState
-	 *
-	 * @note	Core thread.
-	 */
-	class BS_CORE_EXPORT SamplerStateCore : public CoreObjectCore
-	{
-	public:
-		virtual ~SamplerStateCore();
-
-		/**
-		 * @brief	Returns information about the sampler state.
-		 */
-		const SamplerProperties& getProperties() const;
-
-		/**
-		 * @brief	Returns the default sampler state.
-		 */
-		static const SPtr<SamplerStateCore>& getDefault();
-
-	protected:
-		friend class RenderStateCoreManager;
-
-		SamplerStateCore(const SAMPLER_STATE_DESC& desc);
-
-		/**
-		 * @copydoc	CoreObjectCore::initialize
-		 */
-		void initialize() override;
-
-		/**
-		 * @brief	Creates any API-specific state objects.
-		 */
-		virtual void createInternal() { }
-
-		SamplerProperties mProperties;
-	};
-
-	/**
-	 * @brief	Class representing the state of a texture sampler.
-	 *	
-	 * @note	Sampler units are used for retrieving and filtering data from
-	 *			textures set in a GPU program. Sampler states are immutable.
-	 *
-	 *			Sim thread.
-	 */
-	class BS_CORE_EXPORT SamplerState : public IReflectable, public CoreObject
-    {
-    public:
-		virtual ~SamplerState();
-
-		/**
-		 * @brief	Returns information about the sampler state.
-		 */
-		const SamplerProperties& getProperties() const;
-
-		/**
-		 * @brief	Retrieves a core implementation of the sampler state usable only from the
-		 *			core thread.
-		 */
-		SPtr<SamplerStateCore> getCore() const;
-
-		/**
-		 * @brief	Creates a new sampler state using the provided descriptor structure.
-		 */
-		static SamplerStatePtr create(const SAMPLER_STATE_DESC& desc);
-
-		/**
-		 * @brief	Returns the default sampler state.
-		 */
-		static const SamplerStatePtr& getDefault();
-
-		/**
-		 * @brief	Generates a hash value from a sampler state descriptor.
-		 */
-		static UINT64 generateHash(const SAMPLER_STATE_DESC& desc);
-
-	protected:
-		SamplerState(const SAMPLER_STATE_DESC& desc);
-
-		/**
-		 * @copydoc	CoreObjectCore::createCore
-		 */
-		SPtr<CoreObjectCore> createCore() const override;
-
-		SamplerProperties mProperties;
-
-		friend class RenderStateManager;
-
-		/************************************************************************/
-		/* 								RTTI		                     		*/
-		/************************************************************************/
-
-	public:
-		friend class SamplerStateRTTI;
-		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;
-    };
-}
-
-/**
- * @brief	Hash value generator for SAMPLER_STATE_DESC.
- */
-template<>
-struct std::hash<BansheeEngine::SAMPLER_STATE_DESC>
-{
-	size_t operator()(const BansheeEngine::SAMPLER_STATE_DESC& value) const
-	{
-		return (size_t)BansheeEngine::SamplerState::generateHash(value);
-	}
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsMatrix4.h"
+#include "BsPixelUtil.h"
+#include "BsTexture.h"
+#include "BsColor.h"
+#include "BsIReflectable.h"
+#include "BsCoreObject.h"
+
+namespace BansheeEngine 
+{
+	/**
+	 * @brief	Structure used for initializing a SamplerState.
+	 *
+	 * @see		SamplerState
+	 */
+	struct BS_CORE_EXPORT SAMPLER_STATE_DESC
+	{
+		SAMPLER_STATE_DESC()
+			: minFilter(FO_LINEAR), magFilter(FO_LINEAR), mipFilter(FO_POINT), 
+			maxAniso(0), mipmapBias(0), comparisonFunc(CMPF_ALWAYS_FAIL), mipMin(-FLT_MAX), 
+			mipMax(FLT_MAX), borderColor(Color::White)
+		{ }
+
+		bool operator==(const SAMPLER_STATE_DESC& rhs) const;
+
+		UVWAddressingMode addressMode;
+		FilterOptions minFilter;
+		FilterOptions magFilter;
+		FilterOptions mipFilter;
+		UINT32 maxAniso;
+		float mipmapBias;
+		float mipMin;
+		float mipMax;
+		Color borderColor;
+		CompareFunction comparisonFunc;
+	};
+
+	/**
+	 * @brief	Properties of SamplerState. Shared between sim and core thread versions of SamplerState.
+	 */
+	class BS_CORE_EXPORT SamplerProperties
+	{
+	public:
+		SamplerProperties(const SAMPLER_STATE_DESC& desc);
+
+		/**
+		 * @brief	Returns texture addressing mode for each possible texture coordinate. Addressing
+		 *			modes determine how are texture coordinates outside of [0, 1] range handled.
+		 */
+		const UVWAddressingMode& getTextureAddressingMode() const { return mData.addressMode; }
+
+		/**
+		 * @brief	Gets the filtering used when sampling from a texture.
+		 */
+        FilterOptions getTextureFiltering(FilterType ftpye) const;
+
+		/**
+		 * @brief	Gets the anisotropy level. Higher anisotropy means better filtering
+		 *			for textures displayed on an angled slope relative to the viewer.
+		 */
+		unsigned int getTextureAnisotropy() const { return mData.maxAniso; }
+
+		/**
+		 * @brief	Gets a function that compares sampled data with existing sampled data.
+		 */
+		CompareFunction getComparisonFunction() const { return mData.comparisonFunc; }
+
+		/**
+		* @brief	Mipmap bias allows you to adjust the mipmap selection calculation. Negative values 
+		*			force a larger mipmap to be used, and positive values smaller. Units are in values
+		*			of mip levels, so -1 means use a mipmap one level higher than default.
+		*/
+		float getTextureMipmapBias() const { return mData.mipmapBias; }
+
+		/**
+		 * @brief	Returns the minimum mip map level.
+		 */
+		float getMinimumMip() const { return mData.mipMin; }
+
+		/**
+		 * @brief	Returns the maximum mip map level.
+		 */
+		float getMaximumMip() const { return mData.mipMax; }
+
+		/**
+		 * @brief	Gets the border color that will be used when border texture addressing is used
+		 *			and texture address is outside of the valid range.
+		 */
+		const Color& getBorderColor() const;
+
+		/**
+		 * @brief	Returns the hash value generated from the sampler state properties.
+		 */
+		UINT64 getHash() const { return mHash; }
+
+		/**
+		 * @brief	Returns the descriptor originally used for creating the sampler state.
+		 */
+		SAMPLER_STATE_DESC getDesc() const { return mData; }
+
+	protected:
+		friend class SamplerState;
+		friend class SamplerStateCore;
+		friend class SamplerStateRTTI;
+
+		SAMPLER_STATE_DESC mData;
+		UINT64 mHash;
+	};
+
+	/**
+	 * @brief	Core thread version of SamplerState.
+	 *
+	 * @note	Core thread.
+	 */
+	class BS_CORE_EXPORT SamplerStateCore : public CoreObjectCore
+	{
+	public:
+		virtual ~SamplerStateCore();
+
+		/**
+		 * @brief	Returns information about the sampler state.
+		 */
+		const SamplerProperties& getProperties() const;
+
+		/**
+		 * @brief	Returns the default sampler state.
+		 */
+		static const SPtr<SamplerStateCore>& getDefault();
+
+	protected:
+		friend class RenderStateCoreManager;
+
+		SamplerStateCore(const SAMPLER_STATE_DESC& desc);
+
+		/**
+		 * @copydoc	CoreObjectCore::initialize
+		 */
+		void initialize() override;
+
+		/**
+		 * @brief	Creates any API-specific state objects.
+		 */
+		virtual void createInternal() { }
+
+		SamplerProperties mProperties;
+	};
+
+	/**
+	 * @brief	Class representing the state of a texture sampler.
+	 *	
+	 * @note	Sampler units are used for retrieving and filtering data from
+	 *			textures set in a GPU program. Sampler states are immutable.
+	 *
+	 *			Sim thread.
+	 */
+	class BS_CORE_EXPORT SamplerState : public IReflectable, public CoreObject
+    {
+    public:
+		virtual ~SamplerState();
+
+		/**
+		 * @brief	Returns information about the sampler state.
+		 */
+		const SamplerProperties& getProperties() const;
+
+		/**
+		 * @brief	Retrieves a core implementation of the sampler state usable only from the
+		 *			core thread.
+		 */
+		SPtr<SamplerStateCore> getCore() const;
+
+		/**
+		 * @brief	Creates a new sampler state using the provided descriptor structure.
+		 */
+		static SamplerStatePtr create(const SAMPLER_STATE_DESC& desc);
+
+		/**
+		 * @brief	Returns the default sampler state.
+		 */
+		static const SamplerStatePtr& getDefault();
+
+		/**
+		 * @brief	Generates a hash value from a sampler state descriptor.
+		 */
+		static UINT64 generateHash(const SAMPLER_STATE_DESC& desc);
+
+	protected:
+		SamplerState(const SAMPLER_STATE_DESC& desc);
+
+		/**
+		 * @copydoc	CoreObjectCore::createCore
+		 */
+		SPtr<CoreObjectCore> createCore() const override;
+
+		SamplerProperties mProperties;
+
+		friend class RenderStateManager;
+
+		/************************************************************************/
+		/* 								RTTI		                     		*/
+		/************************************************************************/
+
+	public:
+		friend class SamplerStateRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		virtual RTTITypeBase* getRTTI() const override;
+    };
+}
+
+/**
+ * @brief	Hash value generator for SAMPLER_STATE_DESC.
+ */
+template<>
+struct std::hash<BansheeEngine::SAMPLER_STATE_DESC>
+{
+	size_t operator()(const BansheeEngine::SAMPLER_STATE_DESC& value) const
+	{
+		return (size_t)BansheeEngine::SamplerState::generateHash(value);
+	}
 };

+ 45 - 41
BansheeCore/Include/Win32/BSWin32PlatformData.h

@@ -1,42 +1,46 @@
-#include "BsPlatform.h"
-#include "Win32/BsWin32Defs.h"
-#include "Win32/BsWin32DropTarget.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Encapsulate native cursor data so we can avoid including windows.h as it pollutes the global namespace
-	 */
-	struct BS_CORE_EXPORT NativeCursorData
-	{
-		HCURSOR cursor;
-	};
-
-	/**
-	 * @brief	Encapsulate drop target data so we can avoid including windows.h as it pollutes the global namespace
-	 */
-	struct BS_CORE_EXPORT NativeDropTargetData
-	{
-		Map<const RenderWindow*, Win32DropTarget*> dropTargetsPerWindow;
-		Vector<Win32DropTarget*> dropTargetsToInitialize;
-		Vector<Win32DropTarget*> dropTargetsToDestroy;
-	};
-
-	struct Platform::Pimpl
-	{
-		bool mIsCursorHidden = false;
-		NativeCursorData mCursor;
-		bool mUsingCustomCursor = false;
-		Map<const RenderWindowCore*, WindowNonClientAreaData> mNonClientAreas;
-
-		bool mIsTrackingMouse = false;
-		Vector<RenderWindowCore*> mModalWindowStack;
-
-		NativeDropTargetData mDropTargets;
-
-		bool mRequiresStartUp = false;
-		bool mRequiresShutDown = false;
-
-		BS_MUTEX(mSync);
-	};
+#include "BsPlatform.h"
+#include "Win32/BsWin32Defs.h"
+#include "Win32/BsWin32DropTarget.h"
+
+namespace BansheeEngine
+{
+	/** @cond INTERNAL */
+	/** @addtogroup Platform
+	 *  @{
+	 */
+
+	/** Encapsulate native cursor data so we can avoid including windows.h as it pollutes the global namespace. */
+	struct BS_CORE_EXPORT NativeCursorData
+	{
+		HCURSOR cursor;
+	};
+
+	/**	Encapsulate drop target data so we can avoid including windows.h as it pollutes the global namespace. */
+	struct BS_CORE_EXPORT NativeDropTargetData
+	{
+		Map<const RenderWindow*, Win32DropTarget*> dropTargetsPerWindow;
+		Vector<Win32DropTarget*> dropTargetsToInitialize;
+		Vector<Win32DropTarget*> dropTargetsToDestroy;
+	};
+
+	struct Platform::Pimpl
+	{
+		bool mIsCursorHidden = false;
+		NativeCursorData mCursor;
+		bool mUsingCustomCursor = false;
+		Map<const RenderWindowCore*, WindowNonClientAreaData> mNonClientAreas;
+
+		bool mIsTrackingMouse = false;
+		Vector<RenderWindowCore*> mModalWindowStack;
+
+		NativeDropTargetData mDropTargets;
+
+		bool mRequiresStartUp = false;
+		bool mRequiresShutDown = false;
+
+		BS_MUTEX(mSync);
+	};
+
+	/** @} */
+	/** @endcond */
 }

+ 384 - 407
BansheeCore/Include/Win32/BsWin32DropTarget.h

@@ -1,408 +1,385 @@
-#pragma once
-
-#include "Shellapi.h"
-
-// This is just a helper include for BsPlatformImpl.cpp, it's not meant to be used on its own
-
-namespace BansheeEngine
-{
-	/**
-	* @brief	Called by the OS when various drag and drop actions are performed over a
-	* 			window this control is registered for.
-	* 			
-	* @note		This class queues all messages receives by the OS (from the core thread), and then executes
-	* 			the queue on sim thread. You should be wary of which methods are allowed to be called from which
-	* 			thread.
-	*/
-	class Win32DropTarget : public IDropTarget
-	{
-		/**
-		 * @brief	Type of drag and drop event.
-		 */
-		enum class DropOpType
-		{
-			DragOver,
-			Drop,
-			Leave
-		};
-
-		/**
-		 * @brief	Type of data that a drag and drop operation contains.
-		 */
-		enum class DropOpDataType
-		{
-			FileList,
-			None
-		};
-
-		/**
-		 * @brief	Structure describing a drag and drop operation.
-		 */
-		struct DropTargetOp
-		{
-			DropTargetOp(DropOpType _type, const Vector2I& _pos)
-				:type(_type), position(_pos), dataType(DropOpDataType::None)
-			{ }
-
-			DropOpType type;
-			Vector2I position;
-
-			DropOpDataType dataType;
-			union 
-			{
-				Vector<WString>* mFileList;
-			};
-		};
-
-	public:
-		Win32DropTarget(HWND hWnd)
-			:mHWnd(hWnd), mRefCount(1), mAcceptDrag(false)
-		{ }
-
-		~Win32DropTarget()
-		{
-			BS_LOCK_MUTEX(mSync);
-
-			for(auto& fileList : mFileLists)
-			{
-				bs_delete(fileList);
-			}
-
-			mFileLists.clear();
-			mQueuedDropOps.clear();
-		}
-
-		/**
-		 * @brief	Registers the drop target with the operating system. Monitoring
-		 * 			for drag and drop operations starts.
-		 */
-		void registerWithOS()
-		{
-			CoLockObjectExternal(this, TRUE, FALSE);
-			HRESULT hr = RegisterDragDrop(mHWnd, this);
-		}
-
-		/**
-		 * @brief	Unregisters the drop target with the operating system. Monitoring
-		 * 			for drag and drop operations stops.
-		 */
-		void unregisterWithOS()
-		{
-			RevokeDragDrop(mHWnd);
-			CoLockObjectExternal(this, FALSE, FALSE);
-		}
-
-		/**
-		 * @brief	COM requirement. Returns instance of an interface of
-		 * 			provided type.
-		 */
-		HRESULT __stdcall QueryInterface(REFIID iid, void** ppvObject) override
-		{
-			if(iid == IID_IDropTarget || iid == IID_IUnknown)
-			{
-				AddRef();
-				*ppvObject = this;
-				return S_OK;
-			}
-			else
-			{
-				*ppvObject = nullptr;
-				return E_NOINTERFACE;
-			}
-		}
-
-		/**
-		 * @brief	COM requirement. Increments objects
-		 * 			reference count.
-		 */
-		ULONG __stdcall AddRef() override
-		{
-			return InterlockedIncrement(&mRefCount);
-		} 
-
-		/**
-		 * @brief	COM requirement. Decreases the objects 
-		 * 			reference count and deletes the object
-		 * 			if its zero.
-		 */
-		ULONG __stdcall Release() override
-		{
-			LONG count = InterlockedDecrement(&mRefCount);
-
-			if(count == 0)
-			{
-				bs_delete(this);
-				return 0;
-			}
-			else
-			{
-				return count;
-			}
-		} 
-
-		/**
-		 * @brief	Called by the OS when user enters the drop target area while dragging an object.
-		 * 			
-		 * @note	Called on core thread.
-		 */
-		HRESULT __stdcall DragEnter(IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) override
-		{
-			*pdwEffect = DROPEFFECT_LINK;
-
-			mAcceptDrag = isDataValid(pDataObj);
-			if(!mAcceptDrag)
-				return S_OK;
-
-			{
-				BS_LOCK_MUTEX(mSync);
-
-				mFileLists.push_back(getFileListFromData(pDataObj));
-
-				ScreenToClient(mHWnd, (POINT *)&pt);
-				mQueuedDropOps.push_back(DropTargetOp(DropOpType::DragOver, Vector2I((int)pt.x, (int)pt.y)));
-
-				DropTargetOp& op = mQueuedDropOps.back();
-				op.dataType = DropOpDataType::FileList;
-				op.mFileList = mFileLists.back();
-			}
-			
-			return S_OK;
-		}
-
-		/**
-		 * @brief	Called by the OS while user continues to drag an object over the drop target.
-		 * 			
-		 * @note	Called on core thread.
-		 */
-		HRESULT __stdcall DragOver(DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) override
-		{
-			*pdwEffect = DROPEFFECT_LINK;
-
-			if(!mAcceptDrag)
-				return S_OK;
-
-			{
-				BS_LOCK_MUTEX(mSync);
-
-				ScreenToClient(mHWnd, (POINT *)&pt);
-				mQueuedDropOps.push_back(DropTargetOp(DropOpType::DragOver, Vector2I((int)pt.x, (int)pt.y)));
-
-				DropTargetOp& op = mQueuedDropOps.back();
-				op.dataType = DropOpDataType::FileList;
-				op.mFileList = mFileLists.back();
-			}
-			
-			return S_OK;
-		} 
-
-		/**
-		 * @brief	Called by the OS when user leaves the drop target.
-		 * 			
-		 * @note	Called on core thread.
-		 */
-		HRESULT __stdcall DragLeave() override
-		{
-			{
-				BS_LOCK_MUTEX(mSync);
-
-				mQueuedDropOps.push_back(DropTargetOp(DropOpType::Leave, Vector2I()));
-
-				DropTargetOp& op = mQueuedDropOps.back();
-				op.dataType = DropOpDataType::FileList;
-				op.mFileList = mFileLists.back();
-			}
-
-			return S_OK;
-		}
-
-		/**
-		 * @brief	Called by the OS when the user ends the drag operation while
-		 * 			over the drop target.
-		 * 			
-		 * @note	Called on core thread.
-		 */
-		HRESULT __stdcall Drop(IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) override
-		{
-			*pdwEffect = DROPEFFECT_LINK;
-			mAcceptDrag = false;
-
-			if(!isDataValid(pDataObj))
-				return S_OK;
-
-			{
-				BS_LOCK_MUTEX(mSync);
-
-				mFileLists.push_back(getFileListFromData(pDataObj));
-
-				ScreenToClient(mHWnd, (POINT *)&pt);
-				mQueuedDropOps.push_back(DropTargetOp(DropOpType::Drop, Vector2I((int)pt.x, (int)pt.y)));
-
-				DropTargetOp& op = mQueuedDropOps.back();
-				op.dataType = DropOpDataType::FileList;
-				op.mFileList = mFileLists.back();
-			}
-
-			return S_OK;
-		}
-
-		/**
-		 * @brief	Registers a new drop target to monitor.
-		 *
-		 * @note	Sim thread only.
-		 */
-		void registerDropTarget(OSDropTarget* dropTarget)
-		{
-			mDropTargets.push_back(dropTarget);
-		}
-
-		/**
-		 * @brief	Unregisters an existing drop target and stops monitoring it.
-		 *
-		 * @note	Sim thread only.
-		 */
-		void unregisterDropTarget(OSDropTarget* dropTarget)
-		{
-			auto findIter = std::find(begin(mDropTargets), end(mDropTargets), dropTarget);
-			if(findIter != mDropTargets.end())
-				mDropTargets.erase(findIter);
-		}
-
-		/**
-		 * @brief	Gets the total number of monitored drop targets.
-		 * 			
-		 * @note	Sim thread only.
-		 */
-		unsigned int getNumDropTargets() const 
-		{ 
-			return (unsigned int)mDropTargets.size(); 
-		}
-
-		/**
-		 * @brief	Called every frame by the sim thread. Internal method.
-		 */
-		void update()
-		{
-			BS_LOCK_MUTEX(mSync);
-
-			for(auto& op: mQueuedDropOps)
-			{
-				for(auto& target : mDropTargets)
-				{
-					if(op.type != DropOpType::Leave)
-					{
-						if(target->_isInside(op.position))
-						{
-							if(!target->_isActive())
-							{
-								target->_setFileList(*op.mFileList);
-								target->onEnter(op.position.x, op.position.y);
-							}
-
-							if(op.type == DropOpType::DragOver)
-								target->onDragOver(op.position.x, op.position.y);
-							else if(op.type == DropOpType::Drop)
-							{
-								target->_setFileList(*op.mFileList);
-								target->onDrop(op.position.x, op.position.y);
-							}
-						}
-						else
-						{
-							if(target->_isActive())
-							{
-								target->onLeave();
-								target->_clear();
-								target->_setActive(false);
-							}
-						}
-					}
-					else
-					{
-						if(target->_isActive())
-						{
-							target->onLeave();
-							target->_clear();
-							target->_setActive(false);
-						}
-					}
-				}
-
-				if(op.type == DropOpType::Leave || op.type == DropOpType::Drop)
-				{
-					while (!mFileLists.empty())
-					{
-						bool done = mFileLists[0] == op.mFileList;
-
-						bs_delete(mFileLists[0]);
-						mFileLists.erase(mFileLists.begin());
-
-						if (done)
-							break;
-					}
-				}
-			}
-
-			mQueuedDropOps.clear();
-		}
-	private:
-		/**
-		 * @brief	Check if we support the data in the provided drag and drop data object.
-		 */
-		bool isDataValid(IDataObject* data)
-		{
-			// TODO - Currently only supports file drag and drop, so only CF_HDROP is used
-			FORMATETC fmtetc = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
-
-			return data->QueryGetData(&fmtetc) == S_OK ? true : false;
-		}
-
-		/**
-		 * @brief	Gets a file list from data. Caller must ensure that the data actually
-		 * 			contains a file list.
-		 */
-		Vector<WString>* getFileListFromData(IDataObject* data)
-		{
-			FORMATETC fmtetc = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
-			STGMEDIUM stgmed;
-
-			Vector<WString>* files = bs_new<Vector<WString>>();
-			if(data->GetData(&fmtetc, &stgmed) == S_OK)
-			{
-				PVOID data = GlobalLock(stgmed.hGlobal);
-
-				HDROP hDrop = (HDROP)data;
-				UINT numFiles = DragQueryFileW(hDrop, 0xFFFFFFFF, nullptr, 0);
-
-				files->resize(numFiles);
-				for(UINT i = 0; i < numFiles; i++)
-				{
-					UINT numChars = DragQueryFileW(hDrop, i, nullptr, 0) + 1;
-					wchar_t* buffer = (wchar_t*)bs_alloc((UINT32)numChars * sizeof(wchar_t));
-
-					DragQueryFileW(hDrop, i, buffer, numChars);
-
-					(*files)[i] = WString(buffer);
-
-					bs_free(buffer);
-				}
-
-				GlobalUnlock(stgmed.hGlobal);
-				ReleaseStgMedium(&stgmed);
-			}
-
-			return files;
-		}
-
-	private:
-		Vector<OSDropTarget*> mDropTargets;
-
-		LONG mRefCount;
-		HWND mHWnd;
-		bool mAcceptDrag;
-
-		Vector<DropTargetOp> mQueuedDropOps;
-		Vector<Vector<WString>*> mFileLists; 
-
-		BS_MUTEX(mSync);
-	};
+#pragma once
+
+#include "Shellapi.h"
+
+// This is just a helper include for BsPlatformImpl.cpp, it's not meant to be used on its own
+
+namespace BansheeEngine
+{
+	/** @cond INTERNAL */
+	/** @addtogroup Platform
+	 *  @{
+	 */
+
+	/**
+	* Called by the OS when various drag and drop actions are performed over a window this control is registered for.
+	* 			
+	* @note		
+	* This class queues all messages receives by the OS (from the core thread), and then executes the queue on sim thread.
+	* You should be wary of which methods are allowed to be called from which thread.
+	*/
+	class Win32DropTarget : public IDropTarget
+	{
+		/** Type of drag and drop event. */
+		enum class DropOpType
+		{
+			DragOver,
+			Drop,
+			Leave
+		};
+
+		/** Type of data that a drag and drop operation contains. */
+		enum class DropOpDataType
+		{
+			FileList,
+			None
+		};
+
+		/**	Structure describing a drag and drop operation. */
+		struct DropTargetOp
+		{
+			DropTargetOp(DropOpType _type, const Vector2I& _pos)
+				:type(_type), position(_pos), dataType(DropOpDataType::None)
+			{ }
+
+			DropOpType type;
+			Vector2I position;
+
+			DropOpDataType dataType;
+			union 
+			{
+				Vector<WString>* mFileList;
+			};
+		};
+
+	public:
+		Win32DropTarget(HWND hWnd)
+			:mHWnd(hWnd), mRefCount(1), mAcceptDrag(false)
+		{ }
+
+		~Win32DropTarget()
+		{
+			BS_LOCK_MUTEX(mSync);
+
+			for(auto& fileList : mFileLists)
+			{
+				bs_delete(fileList);
+			}
+
+			mFileLists.clear();
+			mQueuedDropOps.clear();
+		}
+
+		/** Registers the drop target with the operating system. Monitoring for drag and drop operations starts. */
+		void registerWithOS()
+		{
+			CoLockObjectExternal(this, TRUE, FALSE);
+			HRESULT hr = RegisterDragDrop(mHWnd, this);
+		}
+
+		/** Unregisters the drop target with the operating system. Monitoring for drag and drop operations stops. */
+		void unregisterWithOS()
+		{
+			RevokeDragDrop(mHWnd);
+			CoLockObjectExternal(this, FALSE, FALSE);
+		}
+
+		/** COM requirement. Returns instance of an interface of the provided type. */
+		HRESULT __stdcall QueryInterface(REFIID iid, void** ppvObject) override
+		{
+			if(iid == IID_IDropTarget || iid == IID_IUnknown)
+			{
+				AddRef();
+				*ppvObject = this;
+				return S_OK;
+			}
+			else
+			{
+				*ppvObject = nullptr;
+				return E_NOINTERFACE;
+			}
+		}
+
+		/**	COM requirement. Increments objects reference count. */
+		ULONG __stdcall AddRef() override
+		{
+			return InterlockedIncrement(&mRefCount);
+		} 
+
+		/** COM requirement. Decreases the objects reference count and deletes the object if its zero. */
+		ULONG __stdcall Release() override
+		{
+			LONG count = InterlockedDecrement(&mRefCount);
+
+			if(count == 0)
+			{
+				bs_delete(this);
+				return 0;
+			}
+			else
+			{
+				return count;
+			}
+		} 
+
+		/**
+		 * Called by the OS when user enters the drop target area while dragging an object.
+		 * 			
+		 * @note	Called on core thread.
+		 */
+		HRESULT __stdcall DragEnter(IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) override
+		{
+			*pdwEffect = DROPEFFECT_LINK;
+
+			mAcceptDrag = isDataValid(pDataObj);
+			if(!mAcceptDrag)
+				return S_OK;
+
+			{
+				BS_LOCK_MUTEX(mSync);
+
+				mFileLists.push_back(getFileListFromData(pDataObj));
+
+				ScreenToClient(mHWnd, (POINT *)&pt);
+				mQueuedDropOps.push_back(DropTargetOp(DropOpType::DragOver, Vector2I((int)pt.x, (int)pt.y)));
+
+				DropTargetOp& op = mQueuedDropOps.back();
+				op.dataType = DropOpDataType::FileList;
+				op.mFileList = mFileLists.back();
+			}
+			
+			return S_OK;
+		}
+
+		/**
+		 * Called by the OS while user continues to drag an object over the drop target.
+		 * 			
+		 * @note	Called on core thread.
+		 */
+		HRESULT __stdcall DragOver(DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) override
+		{
+			*pdwEffect = DROPEFFECT_LINK;
+
+			if(!mAcceptDrag)
+				return S_OK;
+
+			{
+				BS_LOCK_MUTEX(mSync);
+
+				ScreenToClient(mHWnd, (POINT *)&pt);
+				mQueuedDropOps.push_back(DropTargetOp(DropOpType::DragOver, Vector2I((int)pt.x, (int)pt.y)));
+
+				DropTargetOp& op = mQueuedDropOps.back();
+				op.dataType = DropOpDataType::FileList;
+				op.mFileList = mFileLists.back();
+			}
+			
+			return S_OK;
+		} 
+
+		/**
+		 * Called by the OS when user leaves the drop target.
+		 * 			
+		 * @note	Called on core thread.
+		 */
+		HRESULT __stdcall DragLeave() override
+		{
+			{
+				BS_LOCK_MUTEX(mSync);
+
+				mQueuedDropOps.push_back(DropTargetOp(DropOpType::Leave, Vector2I()));
+
+				DropTargetOp& op = mQueuedDropOps.back();
+				op.dataType = DropOpDataType::FileList;
+				op.mFileList = mFileLists.back();
+			}
+
+			return S_OK;
+		}
+
+		/**
+		 * Called by the OS when the user ends the drag operation while over the drop target.
+		 * 			
+		 * @note	Called on core thread.
+		 */
+		HRESULT __stdcall Drop(IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) override
+		{
+			*pdwEffect = DROPEFFECT_LINK;
+			mAcceptDrag = false;
+
+			if(!isDataValid(pDataObj))
+				return S_OK;
+
+			{
+				BS_LOCK_MUTEX(mSync);
+
+				mFileLists.push_back(getFileListFromData(pDataObj));
+
+				ScreenToClient(mHWnd, (POINT *)&pt);
+				mQueuedDropOps.push_back(DropTargetOp(DropOpType::Drop, Vector2I((int)pt.x, (int)pt.y)));
+
+				DropTargetOp& op = mQueuedDropOps.back();
+				op.dataType = DropOpDataType::FileList;
+				op.mFileList = mFileLists.back();
+			}
+
+			return S_OK;
+		}
+
+		/**
+		 * Registers a new drop target to monitor.
+		 *
+		 * @note	Sim thread only.
+		 */
+		void registerDropTarget(OSDropTarget* dropTarget)
+		{
+			mDropTargets.push_back(dropTarget);
+		}
+
+		/**
+		 * Unregisters an existing drop target and stops monitoring it.
+		 *
+		 * @note	Sim thread only.
+		 */
+		void unregisterDropTarget(OSDropTarget* dropTarget)
+		{
+			auto findIter = std::find(begin(mDropTargets), end(mDropTargets), dropTarget);
+			if(findIter != mDropTargets.end())
+				mDropTargets.erase(findIter);
+		}
+
+		/**
+		 * Gets the total number of monitored drop targets.
+		 * 			
+		 * @note	Sim thread only.
+		 */
+		unsigned int getNumDropTargets() const 
+		{ 
+			return (unsigned int)mDropTargets.size(); 
+		}
+
+		/** Called every frame by the sim thread. Internal method. */
+		void update()
+		{
+			BS_LOCK_MUTEX(mSync);
+
+			for(auto& op: mQueuedDropOps)
+			{
+				for(auto& target : mDropTargets)
+				{
+					if(op.type != DropOpType::Leave)
+					{
+						if(target->_isInside(op.position))
+						{
+							if(!target->_isActive())
+							{
+								target->_setFileList(*op.mFileList);
+								target->onEnter(op.position.x, op.position.y);
+							}
+
+							if(op.type == DropOpType::DragOver)
+								target->onDragOver(op.position.x, op.position.y);
+							else if(op.type == DropOpType::Drop)
+							{
+								target->_setFileList(*op.mFileList);
+								target->onDrop(op.position.x, op.position.y);
+							}
+						}
+						else
+						{
+							if(target->_isActive())
+							{
+								target->onLeave();
+								target->_clear();
+								target->_setActive(false);
+							}
+						}
+					}
+					else
+					{
+						if(target->_isActive())
+						{
+							target->onLeave();
+							target->_clear();
+							target->_setActive(false);
+						}
+					}
+				}
+
+				if(op.type == DropOpType::Leave || op.type == DropOpType::Drop)
+				{
+					while (!mFileLists.empty())
+					{
+						bool done = mFileLists[0] == op.mFileList;
+
+						bs_delete(mFileLists[0]);
+						mFileLists.erase(mFileLists.begin());
+
+						if (done)
+							break;
+					}
+				}
+			}
+
+			mQueuedDropOps.clear();
+		}
+	private:
+		/**	Check if we support the data in the provided drag and drop data object. */
+		bool isDataValid(IDataObject* data)
+		{
+			// TODO - Currently only supports file drag and drop, so only CF_HDROP is used
+			FORMATETC fmtetc = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+
+			return data->QueryGetData(&fmtetc) == S_OK ? true : false;
+		}
+
+		/**	Gets a file list from data. Caller must ensure that the data actually contains a file list. */
+		Vector<WString>* getFileListFromData(IDataObject* data)
+		{
+			FORMATETC fmtetc = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+			STGMEDIUM stgmed;
+
+			Vector<WString>* files = bs_new<Vector<WString>>();
+			if(data->GetData(&fmtetc, &stgmed) == S_OK)
+			{
+				PVOID data = GlobalLock(stgmed.hGlobal);
+
+				HDROP hDrop = (HDROP)data;
+				UINT numFiles = DragQueryFileW(hDrop, 0xFFFFFFFF, nullptr, 0);
+
+				files->resize(numFiles);
+				for(UINT i = 0; i < numFiles; i++)
+				{
+					UINT numChars = DragQueryFileW(hDrop, i, nullptr, 0) + 1;
+					wchar_t* buffer = (wchar_t*)bs_alloc((UINT32)numChars * sizeof(wchar_t));
+
+					DragQueryFileW(hDrop, i, buffer, numChars);
+
+					(*files)[i] = WString(buffer);
+
+					bs_free(buffer);
+				}
+
+				GlobalUnlock(stgmed.hGlobal);
+				ReleaseStgMedium(&stgmed);
+			}
+
+			return files;
+		}
+
+	private:
+		Vector<OSDropTarget*> mDropTargets;
+
+		LONG mRefCount;
+		HWND mHWnd;
+		bool mAcceptDrag;
+
+		Vector<DropTargetOp> mQueuedDropOps;
+		Vector<Vector<WString>*> mFileLists; 
+
+		BS_MUTEX(mSync);
+	};
+
+	/** @} */
+	/** @endcond */
 }

+ 85 - 99
BansheeCore/Include/Win32/BsWin32FolderMonitor.h

@@ -1,100 +1,86 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	These values types of notifications we would like to receive
-	 *			when we start a FolderMonitor on a certain folder.
-	 */
-	enum class FolderChange
-	{
-		FileName = 0x0001, /**< Called when filename changes. */
-		DirName = 0x0002, /**< Called when directory name changes. */
-		Attributes = 0x0004, /**< Called when attributes changes. */
-		Size = 0x0008, /**< Called when file size changes. */
-		LastWrite = 0x0010, /**< Called when file is written to. */
-		LastAccess = 0x0020, /**< Called when file is accessed. */
-		Creation = 0x0040, /**< Called when file is created. */
-		Security = 0x0080 /**< Called when file security descriptor changes. */
-	};
-
-	/**
-	 * @brief	Allows monitoring a file system folder for changes. Depending on the flags
-	 *			set this monitor can notify you when file is changed/moved/renamed and similar.
-	 */
-	class BS_CORE_EXPORT FolderMonitor
-	{
-		struct Pimpl;
-		class FileNotifyInfo;
-		struct FolderWatchInfo;
-	public:
-		FolderMonitor();
-		~FolderMonitor();
-
-		/**
-		 * @brief	Starts monitoring a folder at the specified path.
-		 *
-		 * @param	folderPath		Absolute path to the folder you want to monitor.
-		 * @param	subdirectories	If true, provided folder and all of its subdirectories will be monitored
-		 *							for changes. Otherwise only the provided folder will be monitored.
-		 * @param	changeFilter	A set of flags you may OR together. Different notification events will
-		 *							trigger depending on which flags you set.
-		 */
-		void startMonitor(const Path& folderPath, bool subdirectories, FolderChange changeFilter);
-
-		/**
-		 * @brief	Stops monitoring the folder at the specified path.
-		 */
-		void stopMonitor(const Path& folderPath);
-
-		/**
-		 * @brief	Stops monitoring all folders that are currently being monitored.
-		 */
-		void stopMonitorAll();
-
-		/**
-		 * @brief	Callbacks will only get fired after update is called().
-		 * 			
-		 * @note	Internal method.
-		 */
-		void _update();
-
-		/**
-		 * @brief	Triggers when a file in the monitored folder is modified. Provides absolute path to the file.
-		 */
-		Event<void(const Path&)> onModified;
-
-		/**
-		 * @brief	Triggers when a file/folder is added in the monitored folder. Provides
-		 *			absolute path to the file/folder.
-		 */
-		Event<void(const Path&)> onAdded;
-
-		/**
-		 * @brief	Triggers when a file/folder is removed from the monitored folder. Provides
-		 *			absolute path to the file/folder.
-		 */
-		Event<void(const Path&)> onRemoved;
-
-		/**
-		 * @brief	Triggers when a file/folder is renamed in the monitored folder. 
-		 *			Provides absolute path with old and new names.
-		 */
-		Event<void(const Path&, const Path&)> onRenamed;
-
-	private:
-		Pimpl* mPimpl;
-
-		/**
-		 * @brief	Worker method that monitors the IO ports for any modification notifications.
-		 */
-		void workerThreadMain();
-
-		/**
-		 * @brief	Called by the worker thread whenever a modification notification is received.
-		 */
-		void handleNotifications(FileNotifyInfo& notifyInfo, FolderWatchInfo& watchInfo);
-	};
+#pragma once
+
+#include "BsCorePrerequisites.h"
+
+namespace BansheeEngine
+{
+	/** @cond INTERNAL */
+	/** @addtogroup Platform
+	 *  @{
+	 */
+
+	/** Types of notifications we would like to receive when we start a FolderMonitor on a certain folder. */
+	enum class FolderChange
+	{
+		FileName = 0x0001, /**< Called when filename changes. */
+		DirName = 0x0002, /**< Called when directory name changes. */
+		Attributes = 0x0004, /**< Called when attributes changes. */
+		Size = 0x0008, /**< Called when file size changes. */
+		LastWrite = 0x0010, /**< Called when file is written to. */
+		LastAccess = 0x0020, /**< Called when file is accessed. */
+		Creation = 0x0040, /**< Called when file is created. */
+		Security = 0x0080 /**< Called when file security descriptor changes. */
+	};
+
+	/**
+	 * Allows monitoring a file system folder for changes. Depending on the flags set this monitor can notify you when file
+	 * is changed/moved/renamed and similar.
+	 */
+	class BS_CORE_EXPORT FolderMonitor
+	{
+		struct Pimpl;
+		class FileNotifyInfo;
+		struct FolderWatchInfo;
+	public:
+		FolderMonitor();
+		~FolderMonitor();
+
+		/**
+		 * Starts monitoring a folder at the specified path.
+		 *
+		 * @param[in]	folderPath		Absolute path to the folder you want to monitor.
+		 * @param[in]	subdirectories	If true, provided folder and all of its subdirectories will be monitored for 
+		 *								changes. Otherwise only the provided folder will be monitored.
+		 * @param[in]	changeFilter	A set of flags you may OR together. Different notification events will trigger 
+		 *								depending on which flags you set.
+		 */
+		void startMonitor(const Path& folderPath, bool subdirectories, FolderChange changeFilter);
+
+		/** Stops monitoring the folder at the specified path. */
+		void stopMonitor(const Path& folderPath);
+
+		/**	Stops monitoring all folders that are currently being monitored. */
+		void stopMonitorAll();
+
+		/**
+		 * Callbacks will only get fired after update is called().
+		 * 			
+		 * @note	Internal method.
+		 */
+		void _update();
+
+		/** Triggers when a file in the monitored folder is modified. Provides absolute path to the file. */
+		Event<void(const Path&)> onModified;
+
+		/**	Triggers when a file/folder is added in the monitored folder. Provides absolute path to the file/folder. */
+		Event<void(const Path&)> onAdded;
+
+		/**	Triggers when a file/folder is removed from the monitored folder. Provides absolute path to the file/folder. */
+		Event<void(const Path&)> onRemoved;
+
+		/**	Triggers when a file/folder is renamed in the monitored folder. Provides absolute path with old and new names. */
+		Event<void(const Path&, const Path&)> onRenamed;
+
+	private:
+		/**	Worker method that monitors the IO ports for any modification notifications. */
+		void workerThreadMain();
+
+		/**	Called by the worker thread whenever a modification notification is received. */
+		void handleNotifications(FileNotifyInfo& notifyInfo, FolderWatchInfo& watchInfo);
+
+		Pimpl* mPimpl;
+	};
+
+	/** @} */
+	/** @endcond */
 }

+ 34 - 27
BansheeCore/Include/Win32/BsWin32Platform.h

@@ -1,28 +1,35 @@
-#pragma once
-
-#include "BsPlatform.h"
-#include "BsWin32Defs.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Contains the main message loop
-	 *
-	 * @note	This is separated from the main Platform because we don't want to include various Windows
-	 * 			defines in a lot of our code that includes "Platform.h".
-	 */
-	class BS_CORE_EXPORT Win32Platform : public Platform
-	{
-	public:
-		/**
-		 * @brief	Creates a new bitmap usable by various Win32 methods from the provided pixel data.
-		 *			Caller must ensure to call ::DeleteObject on the bitmap handle when finished.
-		 */
-		static HBITMAP createBitmap(const PixelData& pixelData, bool premultiplyAlpha);
-
-		/**
-		 * @brief	Main message loop callback that processes messages received from windows.
-		 */
-		static LRESULT CALLBACK _win32WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
-	};
+#pragma once
+
+#include "BsPlatform.h"
+#include "BsWin32Defs.h"
+
+namespace BansheeEngine
+{
+	/** @cond INTERNAL */
+	/** @addtogroup Platform
+	 *  @{
+	 */
+
+	/**
+	 * Contains the main message loop.
+	 *
+	 * @note	
+	 * This is separated from the main Platform because we don't want to include various Windows defines in a lot of our 
+	 * code that includes "Platform.h".
+	 */
+	class BS_CORE_EXPORT Win32Platform : public Platform
+	{
+	public:
+		/**
+		 * Creates a new bitmap usable by various Win32 methods from the provided pixel data. Caller must ensure to call 
+		 * DeleteObject() on the bitmap handle when finished.
+		 */
+		static HBITMAP createBitmap(const PixelData& pixelData, bool premultiplyAlpha);
+
+		/** Main message loop callback that processes messages received from windows. */
+		static LRESULT CALLBACK _win32WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+	};
+
+	/** @} */
+	/** @endcond */
 }