Browse Source

Added the ability to bind a depth texture both for testing and reading from shader
Fixing point light rendering

BearishSun 10 years ago
parent
commit
7d7abe6999
27 changed files with 7788 additions and 7635 deletions
  1. 526 521
      BansheeCore/Include/BsRenderAPI.h
  2. 183 183
      BansheeCore/Include/BsRenderTexture.h
  3. 0 10
      BansheeCore/Source/BsMaterialParams.cpp
  4. 3 2
      BansheeCore/Source/BsRenderAPI.cpp
  5. 172 163
      BansheeD3D11RenderAPI/Include/BsD3D11Mappings.h
  6. 274 274
      BansheeD3D11RenderAPI/Include/BsD3D11RenderAPI.h
  7. 170 168
      BansheeD3D11RenderAPI/Include/BsD3D11Texture.h
  8. 120 114
      BansheeD3D11RenderAPI/Include/BsD3D11TextureView.h
  9. 859 825
      BansheeD3D11RenderAPI/Source/BsD3D11Mappings.cpp
  10. 51 44
      BansheeD3D11RenderAPI/Source/BsD3D11MultiRenderTexture.cpp
  11. 6 2
      BansheeD3D11RenderAPI/Source/BsD3D11RenderAPI.cpp
  12. 42 41
      BansheeD3D11RenderAPI/Source/BsD3D11RenderTexture.cpp
  13. 15 4
      BansheeD3D11RenderAPI/Source/BsD3D11RenderWindow.cpp
  14. 793 749
      BansheeD3D11RenderAPI/Source/BsD3D11Texture.cpp
  15. 250 242
      BansheeD3D11RenderAPI/Source/BsD3D11TextureView.cpp
  16. 596 596
      BansheeD3D9RenderAPI/Include/BsD3D9RenderAPI.h
  17. 2316 2316
      BansheeD3D9RenderAPI/Source/BsD3D9RenderAPI.cpp
  18. 1 1
      BansheeEngine/Source/BsLight.cpp
  19. 605 605
      BansheeGLRenderAPI/Include/BsGLRenderAPI.h
  20. 1 1
      BansheeGLRenderAPI/Source/BsGLRenderAPI.cpp
  21. 11 29
      RenderBeast/Include/BsLightRendering.h
  22. 314 306
      RenderBeast/Include/BsRenderBeast.h
  23. 77 86
      RenderBeast/Include/BsStaticRenderableHandler.h
  24. 6 2
      RenderBeast/Source/BsLightRendering.cpp
  25. 65 20
      RenderBeast/Source/BsRenderBeast.cpp
  26. 198 198
      RenderBeast/Source/BsRenderTargets.cpp
  27. 134 133
      RenderBeast/Source/BsStaticRenderableHandler.cpp

+ 526 - 521
BansheeCore/Include/BsRenderAPI.h

@@ -1,522 +1,527 @@
-#pragma once
-#include "BsCorePrerequisites.h"
-
-#include <memory>
-
-#include "BsSamplerState.h"
-#include "BsCommandQueue.h"
-#include "BsDrawOps.h"
-#include "BsRenderAPICapabilities.h"
-#include "BsRenderTarget.h"
-#include "BsRenderTexture.h"
-#include "BsRenderWindow.h"
-#include "BsGpuProgram.h"
-#include "BsVertexDeclaration.h"
-#include "BsPlane.h"
-#include "BsModule.h"
-#include "BsEvent.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Version of the render API interface usable from the sim thread. All the commands
-	 *			get queued on the accessor provided to each method and will be executed on
-	 *			the core thread later.
-	 *
-	 * @see		RenderAPICore
-	 *
-	 * @note	Sim thread only.
-	 */
-	class BS_CORE_EXPORT RenderAPI
-	{
-	public:
-		/** @copydoc RenderAPICore::disableTextureUnit() */
-		static void disableTextureUnit(CoreAccessor& accessor, GpuProgramType gptype, UINT16 texUnit);
-
-		/** @copydoc RenderAPICore::setTexture() */
-		static void setTexture(CoreAccessor& accessor, GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr &texPtr);
-
-		/** @copydoc RenderAPICore::setLoadStoreTexture() */
-		static void setLoadStoreTexture(CoreAccessor& accessor, GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr& texPtr,
-			const TextureSurface& surface);
-
-		/** @copydoc RenderAPICore::setSamplerState() */
-		static void setSamplerState(CoreAccessor& accessor, GpuProgramType gptype, UINT16 texUnit, const SamplerStatePtr& samplerState);
-
-		/** @copydoc RenderAPICore::setBlendState() */
-		static void setBlendState(CoreAccessor& accessor, const BlendStatePtr& blendState);
-
-		/** @copydoc RenderAPICore::setRasterizerState() */
-		static void setRasterizerState(CoreAccessor& accessor, const RasterizerStatePtr& rasterizerState);
-
-		/** @copydoc RenderAPICore::setRasterizerState() */
-		static void setDepthStencilState(CoreAccessor& accessor, const DepthStencilStatePtr& depthStencilState, UINT32 stencilRefValue);
-
-		/** @copydoc RenderAPICore::setVertexBuffers() */
-		static void setVertexBuffers(CoreAccessor& accessor, UINT32 index, const Vector<VertexBufferPtr>& buffers);
-
-		/** @copydoc RenderAPICore::setIndexBuffer() */
-		static void setIndexBuffer(CoreAccessor& accessor, const IndexBufferPtr& buffer);
-
-		/** @copydoc RenderAPICore::setVertexDeclaration() */
-		static void setVertexDeclaration(CoreAccessor& accessor, const VertexDeclarationPtr& vertexDeclaration);
-
-		/** @copydoc RenderAPICore::setViewport() */
-		static void setViewport(CoreAccessor& accessor, const Rect2& vp);
-
-		/** @copydoc RenderAPICore::setDrawOperation() */
-		static void setDrawOperation(CoreAccessor& accessor, DrawOperationType op);
-
-		/** @copydoc RenderAPICore::setClipPlanes() */
-		static void setClipPlanes(CoreAccessor& accessor, const PlaneList& clipPlanes);
-
-		/** @copydoc RenderAPICore::addClipPlane(const Plane&) */
-		static void addClipPlane(CoreAccessor& accessor, const Plane& p);
-
-		/** @copydoc RenderAPICore::resetClipPlanes() */
-		static void resetClipPlanes(CoreAccessor& accessor);
-
-		/** @copydoc RenderAPICore::setScissorTest() */
-		static void setScissorTest(CoreAccessor& accessor, UINT32 left = 0, UINT32 top = 0, UINT32 right = 800, UINT32 bottom = 600);
-
-		/** @copydoc RenderAPICore::setRenderTarget() */
-		static void setRenderTarget(CoreAccessor& accessor, const RenderTargetPtr& target);
-
-		/** @copydoc RenderAPICore::bindGpuProgram() */
-		static void bindGpuProgram(CoreAccessor& accessor, const GpuProgramPtr& prg);
-
-		/** @copydoc RenderAPICore::unbindGpuProgram() */
-		static void unbindGpuProgram(CoreAccessor& accessor, GpuProgramType gptype);
-
-		/** @copydoc RenderAPICore::setConstantBuffers() */
-		static void setConstantBuffers(CoreAccessor& accessor, GpuProgramType gptype, const GpuParamsPtr& params);
-
-		/** @copydoc RenderAPICore::setGpuParams() */
-		static void setGpuParams(CoreAccessor& accessor, GpuProgramType gptype, const GpuParamsPtr& params);
-
-		/** @copydoc RenderAPICore::beginFrame() */
-		static void beginRender(CoreAccessor& accessor);
-
-		/** @copydoc RenderAPICore::endFrame() */
-		static void endRender(CoreAccessor& accessor);
-
-		/** @copydoc RenderAPICore::clearRenderTarget() */
-		static void clearRenderTarget(CoreAccessor& accessor, UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0);
-
-		/** @copydoc RenderAPICore::clearViewport() */
-		static void clearViewport(CoreAccessor& accessor, UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0);
-
-		/** @copydoc RenderAPICore::swapBuffers() */
-		static void swapBuffers(CoreAccessor& accessor, const RenderTargetPtr& target);
-
-		/** @copydoc RenderAPICore::draw() */
-		static void draw(CoreAccessor& accessor, UINT32 vertexOffset, UINT32 vertexCount);
-
-		/** @copydoc RenderAPICore::drawIndexed() */
-		static void drawIndexed(CoreAccessor& accessor, UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount);
-
-		/** @copydoc RenderAPICore::getVideoModeInfo */
-		static const VideoModeInfo& getVideoModeInfo();
-
-		/** @copydoc RenderAPICore::getColorVertexElementType */
-		static VertexElementType getColorVertexElementType();
-
-		/** @copydoc RenderAPICore::convertProjectionMatrix */
-		static void convertProjectionMatrix(const Matrix4& matrix, Matrix4& dest);
-
-		/** @copydoc RenderAPICore::getHorizontalTexelOffset */
-		static float getHorizontalTexelOffset();
-
-		/** @copydoc RenderAPICore::getVerticalTexelOffset */
-		static float getVerticalTexelOffset();
-
-		/** @copydoc RenderAPICore::getMinimumDepthInputValue */
-		static float getMinimumDepthInputValue();
-
-		/** @copydoc RenderAPICore::getMaximumDepthInputValue */
-		static float getMaximumDepthInputValue();
-
-		/** @copydoc RenderAPICore::getVertexColorFlipRequired */
-		static bool getVertexColorFlipRequired();
-	};
-
-	/**
-	 * @brief	Render system provides base functionality for a rendering API like
-	 *			DirectX or OpenGL. Most of the class is abstract and specific
-	 *			subclass for each rendering API needs to be implemented.
-	 *
-	 * @note	Core thread only unless specifically noted otherwise on per-method basis.
-	 */
-	class BS_CORE_EXPORT RenderAPICore : public Module<RenderAPICore>
-	{
-	public:
-		RenderAPICore();
-		virtual ~RenderAPICore();
-
-		/**
-		 * @brief	Returns the name of the rendering system. 
-		 *
-		 * @note	Thread safe.
-		 */
-		virtual const StringID& getName() const = 0;
-
-		/**
-		 * @brief	Gets the name of the primary shading language
-		 *			used by the rendering system.
-		 *
-		 * @note	Thread safe.
-		 */
-		virtual const String& getShadingLanguageName() const = 0;
-
-		/**
-		 * @brief	Sets a sampler state for the specified texture unit.
-		 *
-		 * @see		SamplerState
-		 */
-		virtual void setSamplerState(GpuProgramType gptype, UINT16 texUnit, const SPtr<SamplerStateCore>& samplerState) = 0;
-
-		/**
-		 * @brief	Sets a blend state used for all active render targets.
-		 *
-		 * @see		BlendState
-		 */
-		virtual void setBlendState(const SPtr<BlendStateCore>& blendState) = 0;
-
-		/**
-		 * @brief	Sets a state that controls various rasterizer options. 
-		 *
-		 * @see		RasterizerState
-		 */
-		virtual void setRasterizerState(const SPtr<RasterizerStateCore>& rasterizerState) = 0;
-
-		/**
-		 * @brief	Sets a state that controls depth & stencil buffer options.
-		 *
-		 * @see		DepthStencilState
-		 */
-		virtual void setDepthStencilState(const SPtr<DepthStencilStateCore>& depthStencilState, UINT32 stencilRefValue) = 0;
-
-		/**
-		 * @brief	Binds a texture to the pipeline for the specified GPU program type at the specified slot.
-		 *			If the slot matches the one configured in the GPU program the program will be able to access
-		 *			this texture on the GPU.
-		 */
-		virtual void setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr) = 0;
-
-		/**
-		* @brief	Turns off a texture unit.
-		*/
-		virtual void disableTextureUnit(GpuProgramType gptype, UINT16 texUnit);
-
-		/**
-		 * @brief	Binds a texture that can be used for random load/store operations from a GPU program.
-		 */
-		virtual void setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, 
-			const SPtr<TextureCore>& texPtr, const TextureSurface& surface) = 0;
-
-		/**
-		 * @brief	Signals that rendering for a specific viewport has started. Any draw calls
-		 *			need to be called between beginFrame and endFrame. You may not switch render targets
-		 *			until you call endFrame.
-		 */
-		virtual void beginFrame() = 0;
-		
-		/**
-		 * @brief	Ends that rendering to a specific viewport has ended.
-		 */
-		virtual void endFrame() = 0;
-
-		/**
-		 * @brief	Sets the active viewport that will be used for all render operations.
-		 *
-		 * @param	area	Area of the viewport, in normalized ([0,1] range) coordinates.
-		 */
-		virtual void setViewport(const Rect2& area) = 0;
-
-		/**
-		 * @brief	Sets the provided vertex buffers starting at the specified source index.
-		 *			Set buffer to nullptr to clear the buffer at the specified index.
-		 */
-		virtual void setVertexBuffers(UINT32 index, SPtr<VertexBufferCore>* buffers, UINT32 numBuffers) = 0;
-
-		/**
-		 * @brief	Sets an index buffer to use when drawing. Indices in an index buffer
-		 * 			reference vertices in the vertex buffer, which increases cache coherency
-		 * 			and reduces the size of vertex buffers by eliminating duplicate data.
-		 */
-		virtual void setIndexBuffer(const SPtr<IndexBufferCore>& buffer) = 0;
-
-		/**
-		 * @brief	Sets the vertex declaration to use when drawing. Vertex declaration
-		 * 			is used to decode contents of a single vertex in a vertex buffer.
-		 */
-		virtual void setVertexDeclaration(const SPtr<VertexDeclarationCore>& vertexDeclaration) = 0;
-
-		/**
-		 * @brief	Sets the draw operation that determines how to interpret the elements
-		 * 			of the index or vertex buffers.
-		 */
-		virtual void setDrawOperation(DrawOperationType op) = 0;
-
-		/**
-		 * @brief	Draw an object based on currently bound GPU programs, vertex declaration and vertex buffers.
-		 * 			
-		 *			Draws directly from the vertex buffer without using indices.
-		 */
-		virtual void draw(UINT32 vertexOffset, UINT32 vertexCount) = 0;
-
-		/**
-		 * @brief	Draw an object based on currently bound GPU programs, vertex declaration, vertex 
-		 * 			and index buffers.
-		 */
-		virtual void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount) = 0;
-
-		/**
-		 * @brief	Swap the front and back buffer of the specified render target.
-		 */
-		virtual void swapBuffers(const SPtr<RenderTargetCore>& target);
-
-		/**
-		 * @brief	Gets the capabilities of the render system.
-		 *
-		 * @note	Thread safe.
-		 */
-		const RenderAPICapabilities* getCapabilities() const;
-
-		/**
-		 * @brief	Returns information about the driver version.
-		 */
-		virtual const DriverVersion& getDriverVersion() const;
-
-		/**
-		 * @brief	Binds the provided GPU program to the pipeline. Any following
-		 *			draw operations will use this program. 
-		 *
-		 * @note	You need to bind at least a vertex and a fragment program in order to draw something.
-		 */
-		virtual void bindGpuProgram(const SPtr<GpuProgramCore>& prg);
-
-		/**
-		 * @brief	Binds constant(uniform) GPU program parameters. Caller must ensure these match the previously
-		 *			bound GPU program.
-		 */
-		virtual void setConstantBuffers(GpuProgramType gptype, const SPtr<GpuParamsCore>& params) = 0;
-
-		/**
-		 * @brief	Binds all specified GPU program parameters. Caller must ensure these match the previously
-		 *			bound GPU program.
-		 */
-		virtual void setGpuParams(GpuProgramType gptype, const SPtr<GpuParamsCore>& params);
-
-		/**
-		 * @brief	Unbinds a program of a given type. 
-		 */
-		virtual void unbindGpuProgram(GpuProgramType gptype);
-
-		/**
-		 * @brief	Query if a GPU program of a given type is currently bound.
-		 */
-		virtual bool isGpuProgramBound(GpuProgramType gptype);
-
-		/**
-		 * @brief	Sets up clip planes that will clip drawn geometry on the negative side of the planes.
-		 */
-		virtual void setClipPlanes(const PlaneList& clipPlanes);
-
-		/**
-		 * @brief	Adds a new clip plane. All drawn geometry will be clipped to this plane.
-		 */
-		virtual void addClipPlane(const Plane& p);
-
-		/**
-		 * @brief	Clears all clip planes.
-		 */
-		virtual void resetClipPlanes();
-
-		/**
-		 * @brief	Allows you to set up a region in which rendering can take place. Coordinates are in pixels.
-		 *			No rendering will be done to render target pixels outside of the provided region.
-		 */
-		virtual void setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom) = 0;
-
-		/**
-		 * @brief	Clears the currently active render target.
-		 *
-		 * @param	buffers			Combination of one or more elements of FrameBufferType
-		 *							denoting which buffers are to be cleared.
-		 * @param	color			(optional) The color to clear the color buffer with, if enabled.
-		 * @param	depth			(optional) The value to initialize the depth buffer with, if enabled.
-		 * @param	stencil			(optional) The value to initialize the stencil buffer with, if enabled.
-		 */
-		virtual void clearRenderTarget(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0) = 0;
-
-		/**
-		 * @brief	Clears the currently active viewport (i.e. it clears just a sub-area of a render-target that is covered by the viewport,
-		 * 			as opposed to clearRenderTarget which always clears the entire render target).
-		 *
-		 * @param	buffers			Combination of one or more elements of FrameBufferType
-		 *							denoting which buffers are to be cleared.
-		 * @param	color			(optional) The color to clear the color buffer with, if enabled.
-		 * @param	depth			(optional) The value to initialize the depth buffer with, if enabled.
-		 * @param	stencil			(optional) The value to initialize the stencil buffer with, if enabled.
-		 */
-		virtual void clearViewport(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0) = 0;
-
-		/**
-		 * @brief	Change the render target into which we want to draw.
-		 */
-        virtual void setRenderTarget(const SPtr<RenderTargetCore>& target) = 0;
-
-		/**
-		 * @brief	Returns information about available output devices and their video modes.
-		 *
-		 * @note	Thread safe.
-		 */
-		const VideoModeInfo& getVideoModeInfo() const { return *mVideoModeInfo; }
-
-		/************************************************************************/
-		/* 								UTILITY METHODS                    		*/
-		/************************************************************************/
-
-		/**
-		 * @brief	Gets the native type used for vertex colors.
-		 *
-		 * @note	Thread safe.
-		 */
-		virtual VertexElementType getColorVertexElementType() const = 0;
-
-		/**
-		 * @brief	Contains a default matrix into a matrix suitable for use
-		 *			by this specific render system.
-		 *
-		 * @note	Thread safe.
-		 */
-		virtual void convertProjectionMatrix(const Matrix4& matrix, Matrix4& dest) = 0;
-
-		/**
-		 * @brief	Gets horizontal texel offset used for mapping texels to pixels
-		 *			in this render system.
-		 *
-		 * @note	Thread safe.
-		 */
-		virtual float getHorizontalTexelOffset() = 0;
-
-		/**
-		 * @brief	Gets vertical texel offset used for mapping texels to pixels
-		 *			in this render system.
-		 *
-		 * @note		Thread safe.
-		 */
-		virtual float getVerticalTexelOffset() = 0;
-
-		/**
-		 * @brief	Gets the minimum (closest) depth value used by this
-		 *			render system.
-		 *
-		 * @note	Thread safe.
-		 */
-		virtual float getMinimumDepthInputValue() = 0;
-
-		/**
-		 * @brief	Gets the maximum (farthest) depth value used by this
-		 *			render system.
-		 *
-		 * @note	Thread safe.
-		 */
-		virtual float getMaximumDepthInputValue() = 0;
-
-		/**
-		 * @brief	Checks if vertex color needs to be flipped before sent to the shader.
-		 *
-		 * @note	Thread safe.
-		 */
-		virtual bool getVertexColorFlipRequired() const { return false; }
-
-		/**
-		 * @brief	Checks whether GPU programs expect matrices in column major format.
-		 */
-		virtual bool getGpuProgramHasColumnMajorMatrices() const { return false; }
-
-		/**
-		 * @brief	Generates a parameter block description and calculates per-parameter offsets for the provided gpu
-		 * 			data parameters. The offsets are render API specific and correspond to std140 layout for OpenGL, and
-		 * 			the default layout in DirectX.
-		 * 			
-		 * @param	name	Name to assign the parameter block.
-		 * @param	params	List of parameters in the parameter block. Only name, type and array size fields need to be
-		 * 					populated, the rest will be populated when the method returns.
-		 * 					
-		 * @returns	Descriptor for the parameter block holding the provided parameters as laid out by the default render
-		 * 			API layout.
-		 */
-		virtual GpuParamBlockDesc generateParamBlockDesc(const String& name, Vector<GpuParamDataDesc>& params) = 0;
-
-		/************************************************************************/
-		/* 							INTERNAL METHODS				        	*/
-		/************************************************************************/
-	protected:
-		/**
-		 * @brief	Initializes the render API system and creates a primary render window.
-		 *
-		 * @note	Although I'd like otherwise, due to the nature of some render API implementations,
-		 * 			you cannot initialize the render system without a window.
-		 *
-		 *			Sim thread.
-		 */
-		RenderWindowPtr initialize(const RENDER_WINDOW_DESC& primaryWindowDesc);
-
-		/**
-		 * @brief	Prepares the initialization of the render API system on the core thread. After
-		 *			the system is prepared a render window can be created and initialization finalized.
-		 */
-		virtual void initializePrepare();
-
-		/**
-		 * @brief	Finalizes the initialization of the render API system on the core thread. 
-		 *			Should be called after the primary render window is created.
-		 */
-		virtual void initializeFinalize(const SPtr<RenderWindowCore>& primaryWindow);
-
-		/**
-		 * @brief	Shuts down the render API system and cleans up all resources.
-		 *
-		 * @note	Sim thread.
-		 */
-		void destroy();
-
-		/**
-		 * @brief	Performs render API system shutdown on the core thread.
-		 */
-		virtual void destroyCore();
-
-		/**
-		 * @copydoc	setClipPlanes.
-		 */
-		virtual void setClipPlanesImpl(const PlaneList& clipPlanes) = 0;
-
-		/************************************************************************/
-		/* 								INTERNAL DATA					       	*/
-		/************************************************************************/
-	protected:
-		friend class RenderAPIManager;
-
-		SPtr<RenderTargetCore> mActiveRenderTarget;
-
-		DriverVersion mDriverVersion;
-		CullingMode mCullingMode;
-		UINT16 mDisabledTexUnitsFrom;
-
-		bool mVertexProgramBound;
-		bool mGeometryProgramBound;
-		bool mFragmentProgramBound;
-		bool mDomainProgramBound;
-		bool mHullProgramBound;
-		bool mComputeProgramBound;
-
-		PlaneList mClipPlanes;
-		bool mClipPlanesDirty;
-
-		RenderAPICapabilities* mCurrentCapabilities;
-		VideoModeInfoPtr mVideoModeInfo;
-	};
+#pragma once
+#include "BsCorePrerequisites.h"
+
+#include <memory>
+
+#include "BsSamplerState.h"
+#include "BsCommandQueue.h"
+#include "BsDrawOps.h"
+#include "BsRenderAPICapabilities.h"
+#include "BsRenderTarget.h"
+#include "BsRenderTexture.h"
+#include "BsRenderWindow.h"
+#include "BsGpuProgram.h"
+#include "BsVertexDeclaration.h"
+#include "BsPlane.h"
+#include "BsModule.h"
+#include "BsEvent.h"
+
+namespace BansheeEngine
+{
+	/**
+	 * @brief	Version of the render API interface usable from the sim thread. All the commands
+	 *			get queued on the accessor provided to each method and will be executed on
+	 *			the core thread later.
+	 *
+	 * @see		RenderAPICore
+	 *
+	 * @note	Sim thread only.
+	 */
+	class BS_CORE_EXPORT RenderAPI
+	{
+	public:
+		/** @copydoc RenderAPICore::disableTextureUnit() */
+		static void disableTextureUnit(CoreAccessor& accessor, GpuProgramType gptype, UINT16 texUnit);
+
+		/** @copydoc RenderAPICore::setTexture() */
+		static void setTexture(CoreAccessor& accessor, GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr &texPtr);
+
+		/** @copydoc RenderAPICore::setLoadStoreTexture() */
+		static void setLoadStoreTexture(CoreAccessor& accessor, GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr& texPtr,
+			const TextureSurface& surface);
+
+		/** @copydoc RenderAPICore::setSamplerState() */
+		static void setSamplerState(CoreAccessor& accessor, GpuProgramType gptype, UINT16 texUnit, const SamplerStatePtr& samplerState);
+
+		/** @copydoc RenderAPICore::setBlendState() */
+		static void setBlendState(CoreAccessor& accessor, const BlendStatePtr& blendState);
+
+		/** @copydoc RenderAPICore::setRasterizerState() */
+		static void setRasterizerState(CoreAccessor& accessor, const RasterizerStatePtr& rasterizerState);
+
+		/** @copydoc RenderAPICore::setRasterizerState() */
+		static void setDepthStencilState(CoreAccessor& accessor, const DepthStencilStatePtr& depthStencilState, UINT32 stencilRefValue);
+
+		/** @copydoc RenderAPICore::setVertexBuffers() */
+		static void setVertexBuffers(CoreAccessor& accessor, UINT32 index, const Vector<VertexBufferPtr>& buffers);
+
+		/** @copydoc RenderAPICore::setIndexBuffer() */
+		static void setIndexBuffer(CoreAccessor& accessor, const IndexBufferPtr& buffer);
+
+		/** @copydoc RenderAPICore::setVertexDeclaration() */
+		static void setVertexDeclaration(CoreAccessor& accessor, const VertexDeclarationPtr& vertexDeclaration);
+
+		/** @copydoc RenderAPICore::setViewport() */
+		static void setViewport(CoreAccessor& accessor, const Rect2& vp);
+
+		/** @copydoc RenderAPICore::setDrawOperation() */
+		static void setDrawOperation(CoreAccessor& accessor, DrawOperationType op);
+
+		/** @copydoc RenderAPICore::setClipPlanes() */
+		static void setClipPlanes(CoreAccessor& accessor, const PlaneList& clipPlanes);
+
+		/** @copydoc RenderAPICore::addClipPlane(const Plane&) */
+		static void addClipPlane(CoreAccessor& accessor, const Plane& p);
+
+		/** @copydoc RenderAPICore::resetClipPlanes() */
+		static void resetClipPlanes(CoreAccessor& accessor);
+
+		/** @copydoc RenderAPICore::setScissorTest() */
+		static void setScissorTest(CoreAccessor& accessor, UINT32 left = 0, UINT32 top = 0, UINT32 right = 800, UINT32 bottom = 600);
+
+		/** @copydoc RenderAPICore::setRenderTarget() */
+		static void setRenderTarget(CoreAccessor& accessor, const RenderTargetPtr& target, bool readOnlyDepthStencil = false);
+
+		/** @copydoc RenderAPICore::bindGpuProgram() */
+		static void bindGpuProgram(CoreAccessor& accessor, const GpuProgramPtr& prg);
+
+		/** @copydoc RenderAPICore::unbindGpuProgram() */
+		static void unbindGpuProgram(CoreAccessor& accessor, GpuProgramType gptype);
+
+		/** @copydoc RenderAPICore::setConstantBuffers() */
+		static void setConstantBuffers(CoreAccessor& accessor, GpuProgramType gptype, const GpuParamsPtr& params);
+
+		/** @copydoc RenderAPICore::setGpuParams() */
+		static void setGpuParams(CoreAccessor& accessor, GpuProgramType gptype, const GpuParamsPtr& params);
+
+		/** @copydoc RenderAPICore::beginFrame() */
+		static void beginRender(CoreAccessor& accessor);
+
+		/** @copydoc RenderAPICore::endFrame() */
+		static void endRender(CoreAccessor& accessor);
+
+		/** @copydoc RenderAPICore::clearRenderTarget() */
+		static void clearRenderTarget(CoreAccessor& accessor, UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0);
+
+		/** @copydoc RenderAPICore::clearViewport() */
+		static void clearViewport(CoreAccessor& accessor, UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0);
+
+		/** @copydoc RenderAPICore::swapBuffers() */
+		static void swapBuffers(CoreAccessor& accessor, const RenderTargetPtr& target);
+
+		/** @copydoc RenderAPICore::draw() */
+		static void draw(CoreAccessor& accessor, UINT32 vertexOffset, UINT32 vertexCount);
+
+		/** @copydoc RenderAPICore::drawIndexed() */
+		static void drawIndexed(CoreAccessor& accessor, UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount);
+
+		/** @copydoc RenderAPICore::getVideoModeInfo */
+		static const VideoModeInfo& getVideoModeInfo();
+
+		/** @copydoc RenderAPICore::getColorVertexElementType */
+		static VertexElementType getColorVertexElementType();
+
+		/** @copydoc RenderAPICore::convertProjectionMatrix */
+		static void convertProjectionMatrix(const Matrix4& matrix, Matrix4& dest);
+
+		/** @copydoc RenderAPICore::getHorizontalTexelOffset */
+		static float getHorizontalTexelOffset();
+
+		/** @copydoc RenderAPICore::getVerticalTexelOffset */
+		static float getVerticalTexelOffset();
+
+		/** @copydoc RenderAPICore::getMinimumDepthInputValue */
+		static float getMinimumDepthInputValue();
+
+		/** @copydoc RenderAPICore::getMaximumDepthInputValue */
+		static float getMaximumDepthInputValue();
+
+		/** @copydoc RenderAPICore::getVertexColorFlipRequired */
+		static bool getVertexColorFlipRequired();
+	};
+
+	/**
+	 * @brief	Render system provides base functionality for a rendering API like
+	 *			DirectX or OpenGL. Most of the class is abstract and specific
+	 *			subclass for each rendering API needs to be implemented.
+	 *
+	 * @note	Core thread only unless specifically noted otherwise on per-method basis.
+	 */
+	class BS_CORE_EXPORT RenderAPICore : public Module<RenderAPICore>
+	{
+	public:
+		RenderAPICore();
+		virtual ~RenderAPICore();
+
+		/**
+		 * @brief	Returns the name of the rendering system. 
+		 *
+		 * @note	Thread safe.
+		 */
+		virtual const StringID& getName() const = 0;
+
+		/**
+		 * @brief	Gets the name of the primary shading language
+		 *			used by the rendering system.
+		 *
+		 * @note	Thread safe.
+		 */
+		virtual const String& getShadingLanguageName() const = 0;
+
+		/**
+		 * @brief	Sets a sampler state for the specified texture unit.
+		 *
+		 * @see		SamplerState
+		 */
+		virtual void setSamplerState(GpuProgramType gptype, UINT16 texUnit, const SPtr<SamplerStateCore>& samplerState) = 0;
+
+		/**
+		 * @brief	Sets a blend state used for all active render targets.
+		 *
+		 * @see		BlendState
+		 */
+		virtual void setBlendState(const SPtr<BlendStateCore>& blendState) = 0;
+
+		/**
+		 * @brief	Sets a state that controls various rasterizer options. 
+		 *
+		 * @see		RasterizerState
+		 */
+		virtual void setRasterizerState(const SPtr<RasterizerStateCore>& rasterizerState) = 0;
+
+		/**
+		 * @brief	Sets a state that controls depth & stencil buffer options.
+		 *
+		 * @see		DepthStencilState
+		 */
+		virtual void setDepthStencilState(const SPtr<DepthStencilStateCore>& depthStencilState, UINT32 stencilRefValue) = 0;
+
+		/**
+		 * @brief	Binds a texture to the pipeline for the specified GPU program type at the specified slot.
+		 *			If the slot matches the one configured in the GPU program the program will be able to access
+		 *			this texture on the GPU.
+		 */
+		virtual void setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr) = 0;
+
+		/**
+		* @brief	Turns off a texture unit.
+		*/
+		virtual void disableTextureUnit(GpuProgramType gptype, UINT16 texUnit);
+
+		/**
+		 * @brief	Binds a texture that can be used for random load/store operations from a GPU program.
+		 */
+		virtual void setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, 
+			const SPtr<TextureCore>& texPtr, const TextureSurface& surface) = 0;
+
+		/**
+		 * @brief	Signals that rendering for a specific viewport has started. Any draw calls
+		 *			need to be called between beginFrame and endFrame. You may not switch render targets
+		 *			until you call endFrame.
+		 */
+		virtual void beginFrame() = 0;
+		
+		/**
+		 * @brief	Ends that rendering to a specific viewport has ended.
+		 */
+		virtual void endFrame() = 0;
+
+		/**
+		 * @brief	Sets the active viewport that will be used for all render operations.
+		 *
+		 * @param	area	Area of the viewport, in normalized ([0,1] range) coordinates.
+		 */
+		virtual void setViewport(const Rect2& area) = 0;
+
+		/**
+		 * @brief	Sets the provided vertex buffers starting at the specified source index.
+		 *			Set buffer to nullptr to clear the buffer at the specified index.
+		 */
+		virtual void setVertexBuffers(UINT32 index, SPtr<VertexBufferCore>* buffers, UINT32 numBuffers) = 0;
+
+		/**
+		 * @brief	Sets an index buffer to use when drawing. Indices in an index buffer
+		 * 			reference vertices in the vertex buffer, which increases cache coherency
+		 * 			and reduces the size of vertex buffers by eliminating duplicate data.
+		 */
+		virtual void setIndexBuffer(const SPtr<IndexBufferCore>& buffer) = 0;
+
+		/**
+		 * @brief	Sets the vertex declaration to use when drawing. Vertex declaration
+		 * 			is used to decode contents of a single vertex in a vertex buffer.
+		 */
+		virtual void setVertexDeclaration(const SPtr<VertexDeclarationCore>& vertexDeclaration) = 0;
+
+		/**
+		 * @brief	Sets the draw operation that determines how to interpret the elements
+		 * 			of the index or vertex buffers.
+		 */
+		virtual void setDrawOperation(DrawOperationType op) = 0;
+
+		/**
+		 * @brief	Draw an object based on currently bound GPU programs, vertex declaration and vertex buffers.
+		 * 			
+		 *			Draws directly from the vertex buffer without using indices.
+		 */
+		virtual void draw(UINT32 vertexOffset, UINT32 vertexCount) = 0;
+
+		/**
+		 * @brief	Draw an object based on currently bound GPU programs, vertex declaration, vertex 
+		 * 			and index buffers.
+		 */
+		virtual void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount) = 0;
+
+		/**
+		 * @brief	Swap the front and back buffer of the specified render target.
+		 */
+		virtual void swapBuffers(const SPtr<RenderTargetCore>& target);
+
+		/**
+		 * @brief	Gets the capabilities of the render system.
+		 *
+		 * @note	Thread safe.
+		 */
+		const RenderAPICapabilities* getCapabilities() const;
+
+		/**
+		 * @brief	Returns information about the driver version.
+		 */
+		virtual const DriverVersion& getDriverVersion() const;
+
+		/**
+		 * @brief	Binds the provided GPU program to the pipeline. Any following
+		 *			draw operations will use this program. 
+		 *
+		 * @note	You need to bind at least a vertex and a fragment program in order to draw something.
+		 */
+		virtual void bindGpuProgram(const SPtr<GpuProgramCore>& prg);
+
+		/**
+		 * @brief	Binds constant(uniform) GPU program parameters. Caller must ensure these match the previously
+		 *			bound GPU program.
+		 */
+		virtual void setConstantBuffers(GpuProgramType gptype, const SPtr<GpuParamsCore>& params) = 0;
+
+		/**
+		 * @brief	Binds all specified GPU program parameters. Caller must ensure these match the previously
+		 *			bound GPU program.
+		 */
+		virtual void setGpuParams(GpuProgramType gptype, const SPtr<GpuParamsCore>& params);
+
+		/**
+		 * @brief	Unbinds a program of a given type. 
+		 */
+		virtual void unbindGpuProgram(GpuProgramType gptype);
+
+		/**
+		 * @brief	Query if a GPU program of a given type is currently bound.
+		 */
+		virtual bool isGpuProgramBound(GpuProgramType gptype);
+
+		/**
+		 * @brief	Sets up clip planes that will clip drawn geometry on the negative side of the planes.
+		 */
+		virtual void setClipPlanes(const PlaneList& clipPlanes);
+
+		/**
+		 * @brief	Adds a new clip plane. All drawn geometry will be clipped to this plane.
+		 */
+		virtual void addClipPlane(const Plane& p);
+
+		/**
+		 * @brief	Clears all clip planes.
+		 */
+		virtual void resetClipPlanes();
+
+		/**
+		 * @brief	Allows you to set up a region in which rendering can take place. Coordinates are in pixels.
+		 *			No rendering will be done to render target pixels outside of the provided region.
+		 */
+		virtual void setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom) = 0;
+
+		/**
+		 * @brief	Clears the currently active render target.
+		 *
+		 * @param	buffers			Combination of one or more elements of FrameBufferType
+		 *							denoting which buffers are to be cleared.
+		 * @param	color			(optional) The color to clear the color buffer with, if enabled.
+		 * @param	depth			(optional) The value to initialize the depth buffer with, if enabled.
+		 * @param	stencil			(optional) The value to initialize the stencil buffer with, if enabled.
+		 */
+		virtual void clearRenderTarget(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0) = 0;
+
+		/**
+		 * @brief	Clears the currently active viewport (i.e. it clears just a sub-area of a render-target that is covered by the viewport,
+		 * 			as opposed to clearRenderTarget which always clears the entire render target).
+		 *
+		 * @param	buffers			Combination of one or more elements of FrameBufferType
+		 *							denoting which buffers are to be cleared.
+		 * @param	color			(optional) The color to clear the color buffer with, if enabled.
+		 * @param	depth			(optional) The value to initialize the depth buffer with, if enabled.
+		 * @param	stencil			(optional) The value to initialize the stencil buffer with, if enabled.
+		 */
+		virtual void clearViewport(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0) = 0;
+
+		/**
+		 * @brief	Change the render target into which we want to draw.
+		 *
+		 * @param	target					Render target to draw to.
+		 * @param	readOnlyDepthStencil	If true the caller guarantees he won't write to the depth/stencil buffer (if 
+		 *									any was provided). This allows the depth buffer to be bound for depth testing, 
+		 *									as well as reading in a shader, at the same time.
+		 */
+        virtual void setRenderTarget(const SPtr<RenderTargetCore>& target, bool readOnlyDepthStencil = false) = 0;
+
+		/**
+		 * @brief	Returns information about available output devices and their video modes.
+		 *
+		 * @note	Thread safe.
+		 */
+		const VideoModeInfo& getVideoModeInfo() const { return *mVideoModeInfo; }
+
+		/************************************************************************/
+		/* 								UTILITY METHODS                    		*/
+		/************************************************************************/
+
+		/**
+		 * @brief	Gets the native type used for vertex colors.
+		 *
+		 * @note	Thread safe.
+		 */
+		virtual VertexElementType getColorVertexElementType() const = 0;
+
+		/**
+		 * @brief	Contains a default matrix into a matrix suitable for use
+		 *			by this specific render system.
+		 *
+		 * @note	Thread safe.
+		 */
+		virtual void convertProjectionMatrix(const Matrix4& matrix, Matrix4& dest) = 0;
+
+		/**
+		 * @brief	Gets horizontal texel offset used for mapping texels to pixels
+		 *			in this render system.
+		 *
+		 * @note	Thread safe.
+		 */
+		virtual float getHorizontalTexelOffset() = 0;
+
+		/**
+		 * @brief	Gets vertical texel offset used for mapping texels to pixels
+		 *			in this render system.
+		 *
+		 * @note		Thread safe.
+		 */
+		virtual float getVerticalTexelOffset() = 0;
+
+		/**
+		 * @brief	Gets the minimum (closest) depth value used by this
+		 *			render system.
+		 *
+		 * @note	Thread safe.
+		 */
+		virtual float getMinimumDepthInputValue() = 0;
+
+		/**
+		 * @brief	Gets the maximum (farthest) depth value used by this
+		 *			render system.
+		 *
+		 * @note	Thread safe.
+		 */
+		virtual float getMaximumDepthInputValue() = 0;
+
+		/**
+		 * @brief	Checks if vertex color needs to be flipped before sent to the shader.
+		 *
+		 * @note	Thread safe.
+		 */
+		virtual bool getVertexColorFlipRequired() const { return false; }
+
+		/**
+		 * @brief	Checks whether GPU programs expect matrices in column major format.
+		 */
+		virtual bool getGpuProgramHasColumnMajorMatrices() const { return false; }
+
+		/**
+		 * @brief	Generates a parameter block description and calculates per-parameter offsets for the provided gpu
+		 * 			data parameters. The offsets are render API specific and correspond to std140 layout for OpenGL, and
+		 * 			the default layout in DirectX.
+		 * 			
+		 * @param	name	Name to assign the parameter block.
+		 * @param	params	List of parameters in the parameter block. Only name, type and array size fields need to be
+		 * 					populated, the rest will be populated when the method returns.
+		 * 					
+		 * @returns	Descriptor for the parameter block holding the provided parameters as laid out by the default render
+		 * 			API layout.
+		 */
+		virtual GpuParamBlockDesc generateParamBlockDesc(const String& name, Vector<GpuParamDataDesc>& params) = 0;
+
+		/************************************************************************/
+		/* 							INTERNAL METHODS				        	*/
+		/************************************************************************/
+	protected:
+		/**
+		 * @brief	Initializes the render API system and creates a primary render window.
+		 *
+		 * @note	Although I'd like otherwise, due to the nature of some render API implementations,
+		 * 			you cannot initialize the render system without a window.
+		 *
+		 *			Sim thread.
+		 */
+		RenderWindowPtr initialize(const RENDER_WINDOW_DESC& primaryWindowDesc);
+
+		/**
+		 * @brief	Prepares the initialization of the render API system on the core thread. After
+		 *			the system is prepared a render window can be created and initialization finalized.
+		 */
+		virtual void initializePrepare();
+
+		/**
+		 * @brief	Finalizes the initialization of the render API system on the core thread. 
+		 *			Should be called after the primary render window is created.
+		 */
+		virtual void initializeFinalize(const SPtr<RenderWindowCore>& primaryWindow);
+
+		/**
+		 * @brief	Shuts down the render API system and cleans up all resources.
+		 *
+		 * @note	Sim thread.
+		 */
+		void destroy();
+
+		/**
+		 * @brief	Performs render API system shutdown on the core thread.
+		 */
+		virtual void destroyCore();
+
+		/**
+		 * @copydoc	setClipPlanes.
+		 */
+		virtual void setClipPlanesImpl(const PlaneList& clipPlanes) = 0;
+
+		/************************************************************************/
+		/* 								INTERNAL DATA					       	*/
+		/************************************************************************/
+	protected:
+		friend class RenderAPIManager;
+
+		SPtr<RenderTargetCore> mActiveRenderTarget;
+
+		DriverVersion mDriverVersion;
+		CullingMode mCullingMode;
+		UINT16 mDisabledTexUnitsFrom;
+
+		bool mVertexProgramBound;
+		bool mGeometryProgramBound;
+		bool mFragmentProgramBound;
+		bool mDomainProgramBound;
+		bool mHullProgramBound;
+		bool mComputeProgramBound;
+
+		PlaneList mClipPlanes;
+		bool mClipPlanesDirty;
+
+		RenderAPICapabilities* mCurrentCapabilities;
+		VideoModeInfoPtr mVideoModeInfo;
+	};
 }

+ 183 - 183
BansheeCore/Include/BsRenderTexture.h

@@ -1,184 +1,184 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsTexture.h"
-#include "BsRenderTarget.h"
-
-namespace BansheeEngine
-{    
-	/**
-	 * @brief	Structure that describes a render texture color and depth/stencil surfaces.
-	 */
-	struct BS_CORE_EXPORT RENDER_TEXTURE_DESC
-	{
-		RENDER_SURFACE_DESC colorSurface;
-		RENDER_SURFACE_DESC depthStencilSurface;
-	};
-
-	/**
-	 * @see		RENDER_TEXTURE_DESC
-	 *
-	 * @note	References core textures instead of texture handles.
-	 */
-	struct BS_CORE_EXPORT RENDER_TEXTURE_CORE_DESC
-	{
-		RENDER_SURFACE_CORE_DESC colorSurface;
-		RENDER_SURFACE_CORE_DESC depthStencilSurface;
-	};
-
-	/**
-	 * @brief	Contains various properties that describe a render texture.
-	 */
-	class BS_CORE_EXPORT RenderTextureProperties : public RenderTargetProperties
-	{
-	public:
-		RenderTextureProperties(const RENDER_TEXTURE_DESC& desc, bool requiresFlipping);
-		RenderTextureProperties(const RENDER_TEXTURE_CORE_DESC& desc, bool requiresFlipping);
-		virtual ~RenderTextureProperties() { }
-
-	private:
-		void construct(const TextureProperties* textureProps, bool requiresFlipping);
-
-		friend class RenderTextureCore;
-		friend class RenderTexture;
-	};
-
-	/**
-	 * @brief	Provides access to internal render texture implementation usable only from the core thread.
-	 *
-	 * @note	Core thread only.
-	 */
-	class BS_CORE_EXPORT RenderTextureCore : public RenderTargetCore
-	{
-	public:
-		RenderTextureCore(const RENDER_TEXTURE_CORE_DESC& desc);
-		virtual ~RenderTextureCore();
-
-		/**
-		 * @copydoc	CoreObjectCore::initialize
-		 */
-		virtual void initialize();
-
-		/**
-		 * @brief	Returns a color surface texture you may bind as an input to an GPU program.
-		 *
-		 * @note	Be aware that you cannot bind a render texture for reading and writing at the same time.
-		 */
-		SPtr<TextureCore> getBindableColorTexture() const { return mDesc.colorSurface.texture; }
-
-		/**
-		 * @brief	Returns a depth/stencil surface texture you may bind as an input to an GPU program.
-		 *
-		 * @note	Be aware that you cannot bind a render texture for reading and writing at the same time.
-		 */
-		SPtr<TextureCore> getBindableDepthStencilTexture() const { return mDesc.depthStencilSurface.texture; }
-
-
-		/**
-		 * @brief	Returns properties that describe the render texture.
-		 */
-		const RenderTextureProperties& getProperties() const;
-
-	protected:
-		/**
-		 * @copydoc	CoreObjectCore::syncToCore
-		 */
-		virtual void syncToCore(const CoreSyncData& data) override;
-
-	private:
-		/**
-		 * @brief	Throws an exception of the color and depth/stencil buffers aren't compatible.
-		 */
-		void throwIfBuffersDontMatch() const;
-
-	protected:
-		friend class RenderTexture;
-
-		TextureViewPtr mColorSurface;
-		TextureViewPtr mDepthStencilSurface;
-
-		RENDER_TEXTURE_CORE_DESC mDesc;
-	};
-
-	/**
-	 * @brief	Render target specialization that allows you to render into a texture you may
-	 *			later bind in further render operations.
-	 *
-	 * @note	Sim thread only. Retrieve core implementation from getCore()
-	 *			for core thread only functionality.
-	 */
-    class BS_CORE_EXPORT RenderTexture : public RenderTarget
-    {
-	public:
-		virtual ~RenderTexture() { }
-
-		/**
-		 * @brief	Creates a new render texture with color and optionally depth/stencil surfaces.
-		 *
-		 * @param	textureType			Type of texture to render to.
-		 * @param	width				Width of the render texture, in pixels.
-		 * @param	height				Height of the render texture, in pixels.
-		 * @param	format				Pixel format used by the texture color surface.
-		 * @param	hwGamma				Should the written pixels be gamma corrected.
-		 * @param	multisampleCount	If higher than 1, texture containing multiple samples per pixel is created.
-		 * @param	createDepth			Should a depth/stencil surface be created along with the color surface.
-		 * @param	depthStencilFormat	Format used by the depth stencil surface, if one is created.
-		 */
-		static RenderTexturePtr create(TextureType textureType, UINT32 width, UINT32 height, 
-			PixelFormat format = PF_R8G8B8A8, bool hwGamma = false, UINT32 multisampleCount = 0, 
-			bool createDepth = true, PixelFormat depthStencilFormat = PF_D24S8);
-
-		/**
-		 * @copydoc	TextureManager::createRenderTexture(const RENDER_TEXTURE_DESC&)
-		 */
-		static RenderTexturePtr create(const RENDER_TEXTURE_DESC& desc);
-
-		/**
-		 * @brief	Returns a color surface texture you may bind as an input to an GPU program.
-		 *
-		 * @note	Be aware that you cannot bind a render texture for reading and writing at the same time.
-		 */
-		const HTexture& getBindableColorTexture() const { return mBindableColorTex; }
-
-		/**
-		 * @brief	Returns a depth/stencil surface texture you may bind as an input to an GPU program.
-		 *
-		 * @note		Be aware that you cannot bind a render texture for reading and writing at the same time.
-		 */
-		const HTexture& getBindableDepthStencilTexture() const { return mBindableDepthStencilTex; }
-
-		/**
-		 * @brief	Retrieves a core implementation of a render texture usable only from the
-		 *			core thread.
-		 *
-		 * @note	Core thread only.
-		 */
-		SPtr<RenderTextureCore> getCore() const;
-
-		/**
-		 * @brief	Returns properties that describe the render texture.
-		 */
-		const RenderTextureProperties& getProperties() const;
-
-	protected:
-		friend class TextureManager;
-
-		RenderTexture(const RENDER_TEXTURE_DESC& desc);
-
-		/**
-		 * @copydoc	RenderTexture::createCore
-		 */
-		virtual SPtr<CoreObjectCore> createCore() const override;
-
-		/**
-		 * @copydoc	CoreObjectCore::syncToCore
-		 */
-		virtual CoreSyncData syncToCore(FrameAlloc* allocator) override;
-
-	protected:
-		HTexture mBindableColorTex;
-		HTexture mBindableDepthStencilTex;
-
-		RENDER_TEXTURE_DESC mDesc;
-	};
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsTexture.h"
+#include "BsRenderTarget.h"
+
+namespace BansheeEngine
+{    
+	/**
+	 * @brief	Structure that describes a render texture color and depth/stencil surfaces.
+	 */
+	struct BS_CORE_EXPORT RENDER_TEXTURE_DESC
+	{
+		RENDER_SURFACE_DESC colorSurface;
+		RENDER_SURFACE_DESC depthStencilSurface;
+	};
+
+	/**
+	 * @see		RENDER_TEXTURE_DESC
+	 *
+	 * @note	References core textures instead of texture handles.
+	 */
+	struct BS_CORE_EXPORT RENDER_TEXTURE_CORE_DESC
+	{
+		RENDER_SURFACE_CORE_DESC colorSurface;
+		RENDER_SURFACE_CORE_DESC depthStencilSurface;
+	};
+
+	/**
+	 * @brief	Contains various properties that describe a render texture.
+	 */
+	class BS_CORE_EXPORT RenderTextureProperties : public RenderTargetProperties
+	{
+	public:
+		RenderTextureProperties(const RENDER_TEXTURE_DESC& desc, bool requiresFlipping);
+		RenderTextureProperties(const RENDER_TEXTURE_CORE_DESC& desc, bool requiresFlipping);
+		virtual ~RenderTextureProperties() { }
+
+	private:
+		void construct(const TextureProperties* textureProps, bool requiresFlipping);
+
+		friend class RenderTextureCore;
+		friend class RenderTexture;
+	};
+
+	/**
+	 * @brief	Provides access to internal render texture implementation usable only from the core thread.
+	 *
+	 * @note	Core thread only.
+	 */
+	class BS_CORE_EXPORT RenderTextureCore : public RenderTargetCore
+	{
+	public:
+		RenderTextureCore(const RENDER_TEXTURE_CORE_DESC& desc);
+		virtual ~RenderTextureCore();
+
+		/**
+		 * @copydoc	CoreObjectCore::initialize
+		 */
+		virtual void initialize();
+
+		/**
+		 * @brief	Returns a color surface texture you may bind as an input to an GPU program.
+		 *
+		 * @note	Be aware that you cannot bind a render texture for reading and writing at the same time.
+		 */
+		SPtr<TextureCore> getBindableColorTexture() const { return mDesc.colorSurface.texture; }
+
+		/**
+		 * @brief	Returns a depth/stencil surface texture you may bind as an input to an GPU program.
+		 *
+		 * @note	Be aware that you cannot bind a render texture for reading and writing at the same time.
+		 */
+		SPtr<TextureCore> getBindableDepthStencilTexture() const { return mDesc.depthStencilSurface.texture; }
+
+
+		/**
+		 * @brief	Returns properties that describe the render texture.
+		 */
+		const RenderTextureProperties& getProperties() const;
+
+	protected:
+		/**
+		 * @copydoc	CoreObjectCore::syncToCore
+		 */
+		virtual void syncToCore(const CoreSyncData& data) override;
+
+	private:
+		/**
+		 * @brief	Throws an exception of the color and depth/stencil buffers aren't compatible.
+		 */
+		void throwIfBuffersDontMatch() const;
+
+	protected:
+		friend class RenderTexture;
+
+		TextureViewPtr mColorSurface;
+		TextureViewPtr mDepthStencilSurface;
+
+		RENDER_TEXTURE_CORE_DESC mDesc;
+	};
+
+	/**
+	 * @brief	Render target specialization that allows you to render into a texture you may
+	 *			later bind in further render operations.
+	 *
+	 * @note	Sim thread only. Retrieve core implementation from getCore()
+	 *			for core thread only functionality.
+	 */
+    class BS_CORE_EXPORT RenderTexture : public RenderTarget
+    {
+	public:
+		virtual ~RenderTexture() { }
+
+		/**
+		 * @brief	Creates a new render texture with color and optionally depth/stencil surfaces.
+		 *
+		 * @param	textureType			Type of texture to render to.
+		 * @param	width				Width of the render texture, in pixels.
+		 * @param	height				Height of the render texture, in pixels.
+		 * @param	format				Pixel format used by the texture color surface.
+		 * @param	hwGamma				Should the written pixels be gamma corrected.
+		 * @param	multisampleCount	If higher than 1, texture containing multiple samples per pixel is created.
+		 * @param	createDepth			Should a depth/stencil surface be created along with the color surface.
+		 * @param	depthStencilFormat	Format used by the depth stencil surface, if one is created.
+		 */
+		static RenderTexturePtr create(TextureType textureType, UINT32 width, UINT32 height, 
+			PixelFormat format = PF_R8G8B8A8, bool hwGamma = false, UINT32 multisampleCount = 0, 
+			bool createDepth = true, PixelFormat depthStencilFormat = PF_D24S8);
+
+		/**
+		 * @copydoc	TextureManager::createRenderTexture(const RENDER_TEXTURE_DESC&)
+		 */
+		static RenderTexturePtr create(const RENDER_TEXTURE_DESC& desc);
+
+		/**
+		 * @brief	Returns a color surface texture you may bind as an input to an GPU program.
+		 *
+		 * @note	Be aware that you cannot bind a render texture for reading and writing at the same time.
+		 */
+		const HTexture& getBindableColorTexture() const { return mBindableColorTex; }
+
+		/**
+		 * @brief	Returns a depth/stencil surface texture you may bind as an input to an GPU program.
+		 *
+		 * @note		Be aware that you cannot bind a render texture for reading and writing at the same time.
+		 */
+		const HTexture& getBindableDepthStencilTexture() const { return mBindableDepthStencilTex; }
+
+		/**
+		 * @brief	Retrieves a core implementation of a render texture usable only from the
+		 *			core thread.
+		 *
+		 * @note	Core thread only.
+		 */
+		SPtr<RenderTextureCore> getCore() const;
+
+		/**
+		 * @brief	Returns properties that describe the render texture.
+		 */
+		const RenderTextureProperties& getProperties() const;
+
+	protected:
+		friend class TextureManager;
+
+		RenderTexture(const RENDER_TEXTURE_DESC& desc);
+
+		/**
+		 * @copydoc	RenderTexture::createCore
+		 */
+		virtual SPtr<CoreObjectCore> createCore() const override;
+
+		/**
+		 * @copydoc	CoreObjectCore::syncToCore
+		 */
+		virtual CoreSyncData syncToCore(FrameAlloc* allocator) override;
+
+	protected:
+		HTexture mBindableColorTex;
+		HTexture mBindableDepthStencilTex;
+
+		RENDER_TEXTURE_DESC mDesc;
+	};
 }

+ 0 - 10
BansheeCore/Source/BsMaterialParams.cpp

@@ -224,26 +224,16 @@ namespace BansheeEngine
 	{
 		auto iterFind = mParams.find(name);
 		if (iterFind == mParams.end())
-		{
-			LOGWRN("Material doesn't have a parameter named " + name + ".");
 			return GetParamResult::NotFound;
-		}
 
 		const ParamData& param = iterFind->second;
 		*output = &param;
 
 		if (param.type != type || (type == ParamType::Data && param.dataType != dataType))
-		{
-			LOGWRN("Parameter \"" + name + "\" is not of the requested type.");
 			return GetParamResult::InvalidType;
-		}
 
 		if (arrayIdx >= param.arraySize)
-		{
-			LOGWRN("Parameter \"" + name + "\" array index " + toString(arrayIdx) + " out of range. Array length is " +
-				toString(param.arraySize) + ".");
 			return GetParamResult::IndexOutOfBounds;
-		}
 
 		return GetParamResult::Success;
 	}

+ 3 - 2
BansheeCore/Source/BsRenderAPI.cpp

@@ -109,9 +109,10 @@ namespace BansheeEngine
 		accessor.queueCommand(std::bind(&RenderAPICore::setScissorRect, RenderAPICore::instancePtr(), left, top, right, bottom));
 	}
 
-	void RenderAPI::setRenderTarget(CoreAccessor& accessor, const RenderTargetPtr& target)
+	void RenderAPI::setRenderTarget(CoreAccessor& accessor, const RenderTargetPtr& target, bool readOnlyDepthStencil)
 	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setRenderTarget, RenderAPICore::instancePtr(), target->getCore()));
+		accessor.queueCommand(std::bind(&RenderAPICore::setRenderTarget, 
+			RenderAPICore::instancePtr(), target->getCore(), readOnlyDepthStencil));
 	}
 
 	void RenderAPI::bindGpuProgram(CoreAccessor& accessor, const GpuProgramPtr& prg)

+ 172 - 163
BansheeD3D11RenderAPI/Include/BsD3D11Mappings.h

@@ -1,164 +1,173 @@
-#pragma once
-
-#include "BsD3D11Prerequisites.h"
-#include "BsTexture.h"
-#include "BsPixelData.h"
-#include "BsIndexBuffer.h"
-#include "BsVertexData.h"
-#include "BsSamplerState.h"
-#include "BsDrawOps.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Helper class that maps engine types to DirectX 1 types
-	 */
-	class BS_D3D11_EXPORT D3D11Mappings
-	{
-	public:
-		/**
-		 * @brief	Converts engine to DX11 specific texture addressing mode.
-		 */
-		static D3D11_TEXTURE_ADDRESS_MODE get(TextureAddressingMode tam);
-
-		/**
-		 * @brief	Converts engine to DX11 specific blend factor.
-		 */
-		static D3D11_BLEND get(BlendFactor bf);
-
-		/**
-		 * @brief	Converts engine to DX11 specific blend operation.
-		 */
-		static D3D11_BLEND_OP get(BlendOperation bo);
-
-		/**
-		 * @brief	Converts engine to DX11 specific comparison function.
-		 */
-		static D3D11_COMPARISON_FUNC get(CompareFunction cf);
-
-		/**
-		 * @brief	Converts engine to DX11 specific culling mode.
-		 */
-		static D3D11_CULL_MODE get(CullingMode cm);
-
-		/**
-		 * @brief	Converts engine to DX11 specific polygon fill mode.
-		 */
-		static D3D11_FILL_MODE get(PolygonMode mode);
-
-		/**
-		 * @brief	Return DirectX 11 stencil operation and optionally 
-		 *			invert it (greater than becomes less than, etc.)
-		 */
-		static D3D11_STENCIL_OP get(StencilOperation op, bool invert = false);
-
-		/**
-		 * @brief	Converts engine texture filter type to DirectX 11 filter
-		 *			shift (used for combining to get actual min/mag/mip filter
-		 *			bit location).
-		 */
-		static DWORD get(FilterType ft);
-
-		/**
-		 * @brief	Returns DirectX 11 texture filter from the provided min, mag
-		 *			and mip filter options, and optionally a filter with comparison support.
-		 */
-		static D3D11_FILTER get(const FilterOptions min, const FilterOptions mag, 
-			const FilterOptions mip, const bool comparison = false);
-
-		/**
-		 * @brief	Converts engine to DX11 buffer usage.
-		 */
-		static DWORD get(GpuBufferUsage usage);
-
-		/**
-		 * @brief	Converts engine to DX11 lock options, while also constraining
-		 *			the options depending on provided usage type.
-		 */
-		static D3D11_MAP get(GpuLockOptions options, GpuBufferUsage usage);
-
-		/**
-		 * @brief	Converts engine to DX11 vertex element type.
-		 */
-		static DXGI_FORMAT get(VertexElementType type);
-
-		/**
-		 * @brief	Returns a string describing the provided vertex element semantic.
-		 */
-		static LPCSTR get(VertexElementSemantic sem);
-
-		/**
-		 * @brief	Returns engine semantic from the provided semantic string. Throws an exception
-		 *			for semantics that do not exist.
-		 */
-		static VertexElementSemantic get(LPCSTR sem);
-
-		/**
-		 * @brief	Converts DirectX 11 GPU parameter component type to engine vertex element type.
-		 */
-		static VertexElementType getInputType(D3D_REGISTER_COMPONENT_TYPE type);
-
-		/**
-		 * @brief	Returns DX11 primitive topology based on the provided draw operation type.
-		 */
-		static D3D11_PRIMITIVE_TOPOLOGY getPrimitiveType(DrawOperationType type);
-
-		/**
-		 * @brief	Converts engine color to DX11 color.
-		 */
-		static void get(const Color& inColor, float* outColor);
-
-		/**
-		 * @brief	Checks does the provided map value include writing.
-		 */
-		static bool isMappingWrite(D3D11_MAP map);
-
-		/**
-		 * @brief	Checks does the provided map value include reading.
-		 */
-		static bool isMappingRead(D3D11_MAP map);
-
-		/**
-		 * @brief	Converts DX11 pixel format to engine pixel format.
-		 */
-		static PixelFormat getPF(DXGI_FORMAT d3dPF);
-
-		/**
-		 * @brief	Converts engine pixel format to DX11 pixel format. Some formats
-		 *			depend on whether hardware gamma is used or not, in which case
-		 *			set the "hwGamma" parameter as needed.
-		 */
-		static DXGI_FORMAT getPF(PixelFormat format, bool hwGamma);
-		
-		/**
-		 * @brief	Converts engine to DX11 buffer usage.
-		 */
-		static D3D11_USAGE getUsage(GpuBufferUsage mUsage);
-
-		/**
-		 * @brief	Converts engine to DX11 buffer access flags.
-		 */
-		static UINT getAccessFlags(GpuBufferUsage mUsage);
-
-		/**
-		 * @brief	Converts engine to DX11 lock options.
-		 */
-		static D3D11_MAP getLockOptions(GpuLockOptions lockOptions);
-
-		/**
-		 * @brief	Checks is the provided buffer usage dynamic.
-		 */
-		static bool isDynamic(GpuBufferUsage mUsage);
-
-		/**
-		 * @brief	Finds the closest pixel format that DX11 supports.
-		 */
-		static PixelFormat getClosestSupportedPF(PixelFormat format, bool hwGamma);
-
-		/**
-		 * @brief	Returns size in bytes of a pixel surface of the specified size and format, while
-		 *			using DX11 allocation rules for padding.
-		 */
-		static UINT32 getSizeInBytes(PixelFormat pf, UINT32 width = 1, UINT32 height = 1);
-	};
+#pragma once
+
+#include "BsD3D11Prerequisites.h"
+#include "BsTexture.h"
+#include "BsPixelData.h"
+#include "BsIndexBuffer.h"
+#include "BsVertexData.h"
+#include "BsSamplerState.h"
+#include "BsDrawOps.h"
+
+namespace BansheeEngine
+{
+	/**
+	 * @brief	Helper class that maps engine types to DirectX 1 types
+	 */
+	class BS_D3D11_EXPORT D3D11Mappings
+	{
+	public:
+		/**
+		 * @brief	Converts engine to DX11 specific texture addressing mode.
+		 */
+		static D3D11_TEXTURE_ADDRESS_MODE get(TextureAddressingMode tam);
+
+		/**
+		 * @brief	Converts engine to DX11 specific blend factor.
+		 */
+		static D3D11_BLEND get(BlendFactor bf);
+
+		/**
+		 * @brief	Converts engine to DX11 specific blend operation.
+		 */
+		static D3D11_BLEND_OP get(BlendOperation bo);
+
+		/**
+		 * @brief	Converts engine to DX11 specific comparison function.
+		 */
+		static D3D11_COMPARISON_FUNC get(CompareFunction cf);
+
+		/**
+		 * @brief	Converts engine to DX11 specific culling mode.
+		 */
+		static D3D11_CULL_MODE get(CullingMode cm);
+
+		/**
+		 * @brief	Converts engine to DX11 specific polygon fill mode.
+		 */
+		static D3D11_FILL_MODE get(PolygonMode mode);
+
+		/**
+		 * @brief	Return DirectX 11 stencil operation and optionally 
+		 *			invert it (greater than becomes less than, etc.)
+		 */
+		static D3D11_STENCIL_OP get(StencilOperation op, bool invert = false);
+
+		/**
+		 * @brief	Converts engine texture filter type to DirectX 11 filter
+		 *			shift (used for combining to get actual min/mag/mip filter
+		 *			bit location).
+		 */
+		static DWORD get(FilterType ft);
+
+		/**
+		 * @brief	Returns DirectX 11 texture filter from the provided min, mag
+		 *			and mip filter options, and optionally a filter with comparison support.
+		 */
+		static D3D11_FILTER get(const FilterOptions min, const FilterOptions mag, 
+			const FilterOptions mip, const bool comparison = false);
+
+		/**
+		 * @brief	Converts engine to DX11 buffer usage.
+		 */
+		static DWORD get(GpuBufferUsage usage);
+
+		/**
+		 * @brief	Converts engine to DX11 lock options, while also constraining
+		 *			the options depending on provided usage type.
+		 */
+		static D3D11_MAP get(GpuLockOptions options, GpuBufferUsage usage);
+
+		/**
+		 * @brief	Converts engine to DX11 vertex element type.
+		 */
+		static DXGI_FORMAT get(VertexElementType type);
+
+		/**
+		 * @brief	Returns a string describing the provided vertex element semantic.
+		 */
+		static LPCSTR get(VertexElementSemantic sem);
+
+		/**
+		 * @brief	Returns engine semantic from the provided semantic string. Throws an exception
+		 *			for semantics that do not exist.
+		 */
+		static VertexElementSemantic get(LPCSTR sem);
+
+		/**
+		 * @brief	Converts DirectX 11 GPU parameter component type to engine vertex element type.
+		 */
+		static VertexElementType getInputType(D3D_REGISTER_COMPONENT_TYPE type);
+
+		/**
+		 * @brief	Returns DX11 primitive topology based on the provided draw operation type.
+		 */
+		static D3D11_PRIMITIVE_TOPOLOGY getPrimitiveType(DrawOperationType type);
+
+		/**
+		 * @brief	Converts engine color to DX11 color.
+		 */
+		static void get(const Color& inColor, float* outColor);
+
+		/**
+		 * @brief	Checks does the provided map value include writing.
+		 */
+		static bool isMappingWrite(D3D11_MAP map);
+
+		/**
+		 * @brief	Checks does the provided map value include reading.
+		 */
+		static bool isMappingRead(D3D11_MAP map);
+
+		/**
+		 * @brief	Converts DX11 pixel format to engine pixel format.
+		 */
+		static PixelFormat getPF(DXGI_FORMAT d3dPF);
+
+		/**
+		 * @brief	Converts engine pixel format to DX11 pixel format. Some formats
+		 *			depend on whether hardware gamma is used or not, in which case
+		 *			set the "hwGamma" parameter as needed.
+		 */
+		static DXGI_FORMAT getPF(PixelFormat format, bool hwGamma);
+		
+		/** 
+		 * Returns a typeless version of a depth stencil format. Required for creating a depth stencil texture it can be
+		 * bound both for shader reading and depth/stencil writing.
+		 */
+		static DXGI_FORMAT getTypelessDepthStencilPF(PixelFormat format);
+
+		/** Returns a format of a depth stencil texture that can be used for reading the texture in the shader. */
+		static DXGI_FORMAT getShaderResourceDepthStencilPF(PixelFormat format);
+
+		/**
+		 * @brief	Converts engine to DX11 buffer usage.
+		 */
+		static D3D11_USAGE getUsage(GpuBufferUsage mUsage);
+
+		/**
+		 * @brief	Converts engine to DX11 buffer access flags.
+		 */
+		static UINT getAccessFlags(GpuBufferUsage mUsage);
+
+		/**
+		 * @brief	Converts engine to DX11 lock options.
+		 */
+		static D3D11_MAP getLockOptions(GpuLockOptions lockOptions);
+
+		/**
+		 * @brief	Checks is the provided buffer usage dynamic.
+		 */
+		static bool isDynamic(GpuBufferUsage mUsage);
+
+		/**
+		 * @brief	Finds the closest pixel format that DX11 supports.
+		 */
+		static PixelFormat getClosestSupportedPF(PixelFormat format, bool hwGamma);
+
+		/**
+		 * @brief	Returns size in bytes of a pixel surface of the specified size and format, while
+		 *			using DX11 allocation rules for padding.
+		 */
+		static UINT32 getSizeInBytes(PixelFormat pf, UINT32 width = 1, UINT32 height = 1);
+	};
 }

+ 274 - 274
BansheeD3D11RenderAPI/Include/BsD3D11RenderAPI.h

@@ -1,275 +1,275 @@
-#pragma once
-
-#include "BsD3D11Prerequisites.h"
-#include "BsRenderAPI.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Implementation of a render system using DirectX 11. Provides abstracted
-	 *			access to various low level DX11 methods.
-	 */
-	class BS_D3D11_EXPORT D3D11RenderAPI : public RenderAPICore
-	{
-	public:
-		D3D11RenderAPI();
-		~D3D11RenderAPI();
-
-		/**
-		 * @copydoc RenderAPICore::getName
-		 */
-		const StringID& getName() const override;
-		
-		/**
-		 * @copydoc RenderAPICore::getShadingLanguageName
-		 */
-		const String& getShadingLanguageName() const override;
-
-		/**
-		 * @copydoc	RenderAPICore::setBlendState
-		 */
-		void setBlendState(const SPtr<BlendStateCore>& blendState) override;
-
-		/**
-		 * @copydoc	RenderAPICore::setRasterizerState
-		 */
-		void setRasterizerState(const SPtr<RasterizerStateCore>& rasterizerState) override;
-
-		/**
-		 * @copydoc	RenderAPICore::setDepthStencilState
-		 */
-		void setDepthStencilState(const SPtr<DepthStencilStateCore>& depthStencilState, UINT32 stencilRefValue) override;
-
-		/**
-		 * @copydoc	RenderAPICore::setSamplerState
-		 */
-		void setSamplerState(GpuProgramType gptype, UINT16 texUnit, const SPtr<SamplerStateCore>& samplerState) override;
-
-		/**
-		 * @copydoc	RenderAPICore::setTexture
-		 */
-		void setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr) override;
-
-		/**
-		 * @copydoc	RenderAPICore::setLoadStoreTexture
-		 */
-		void setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr,
-			const TextureSurface& surface) override;
-
-		/**
-		 * @copydoc	RenderAPICore::disableTextureUnit
-		 */
-		void disableTextureUnit(GpuProgramType gptype, UINT16 texUnit) override;
-
-		/**
-		 * @copydoc	RenderAPICore::beginFrame
-		 */
-		void beginFrame() override;
-
-		/**
-		 * @copydoc	RenderAPICore::endFrame
-		 */
-		void endFrame() override;
-
-		/**
-		 * @copydoc RenderAPICore::clearRenderTarget
-		 */
-		void clearRenderTarget(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0) override;
-
-		/**
-		 * @copydoc RenderAPICore::clearViewport
-		 */
-		void clearViewport(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0) override;
-
-		/**
-		 * @copydoc	RenderAPICore::setRenderTarget
-		 */
-		void setRenderTarget(const SPtr<RenderTargetCore>& target) override;
-
-		/**
-		 * @copydoc	RenderAPICore::setViewport
-		 */
-		void setViewport(const Rect2& vp) override;
-
-		/**
-		 * @copydoc	RenderAPICore::setScissorRect
-		 */
-		void setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom) override;
-
-		/**
-		 * @copydoc	RenderAPICore::setVertexBuffers
-		 */
-		void setVertexBuffers(UINT32 index, SPtr<VertexBufferCore>* buffers, UINT32 numBuffers) override;
-
-		/**
-		 * @copydoc	RenderAPICore::setIndexBuffer
-		 */
-		void setIndexBuffer(const SPtr<IndexBufferCore>& buffer) override;
-
-		/**
-		 * @copydoc	RenderAPICore::setVertexDeclaration
-		 */
-		void setVertexDeclaration(const SPtr<VertexDeclarationCore>& vertexDeclaration) override;
-
-		/**
-		 * @copydoc	RenderAPICore::setDrawOperation
-		 */
-		void setDrawOperation(DrawOperationType op) override;
-
-		/**
-		 * @copydoc	RenderAPICore::draw
-		 */
-		void draw(UINT32 vertexOffset, UINT32 vertexCount) override;
-
-		/**
-		 * @copydoc	RenderAPICore::drawIndexed
-		 */
-		void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount) override;
-
-		/** 
-		 * @copydoc RenderAPICore::bindGpuProgram
-		 */
-		void bindGpuProgram(const SPtr<GpuProgramCore>& prg) override;
-
-		/** 
-		 * @copydoc RenderAPICore::unbindGpuProgram
-		 */
-		void unbindGpuProgram(GpuProgramType gptype) override;
-
-		/** 
-		 * @copydoc RenderAPICore::setConstantBuffers
-		 */
-		void setConstantBuffers(GpuProgramType gptype, const SPtr<GpuParamsCore>& params) override;
-		
-		/**
-		 * @copydoc	RenderAPICore::setClipPlanesImpl
-		 */
-		void setClipPlanesImpl(const PlaneList& clipPlanes) override;
-
-		/**
-		 * @copydoc	RenderAPICore::convertProjectionMatrix
-		 */
-		void convertProjectionMatrix(const Matrix4& matrix, Matrix4& dest) override;
-
-		/**
-		 * @copydoc	RenderAPICore::getColorVertexElementType
-		 */
-		VertexElementType getColorVertexElementType() const override;
-
-		/**
-		 * @copydoc	RenderAPICore::getHorizontalTexelOffset
-		 */
-		float getHorizontalTexelOffset() override;
-
-		/**
-		 * @copydoc	RenderAPICore::getVerticalTexelOffset
-		 */
-		float getVerticalTexelOffset() override;
-
-		/**
-		 * @copydoc	RenderAPICore::getMinimumDepthInputValue
-		 */
-		float getMinimumDepthInputValue() override;
-
-		/**
-		 * @copydoc	RenderAPICore::getMaximumDepthInputValue
-		 */
-		float getMaximumDepthInputValue() override;
-
-		/**
-		 * @copydoc RenderAPICore::generateParamBlockDesc()
-		 */
-		GpuParamBlockDesc generateParamBlockDesc(const String& name, Vector<GpuParamDataDesc>& params) override;
-
-		/************************************************************************/
-		/* 				Internal use by DX11 RenderSystem only                  */
-		/************************************************************************/
-
-		/**
-		 * @brief	Determines DXGI multisample settings from the provided parameters.
-		 *
-		 * @param	multisampleCount	Number of requested samples.
-		 * @param	format				Pixel format used by the render target.
-		 * @param	outputSampleDesc	Output structure that will contain the requested multisample settings.
-		 */
-		void determineMultisampleSettings(UINT32 multisampleCount, DXGI_FORMAT format, DXGI_SAMPLE_DESC* outputSampleDesc);
-
-		/**
-		 * @brief	Returns the main DXGI factory object.
-		 */
-		IDXGIFactory* getDXGIFactory() const { return mDXGIFactory; }
-
-		/**
-		 * @brief	Returns the primary DX11 device object.
-		 */
-		D3D11Device& getPrimaryDevice() const { return *mDevice; }
-		
-		/**
-		 * @brief	Returns information describing all available drivers.
-		 */
-		D3D11DriverList* getDriverList() const { return mDriverList; }
-
-	protected:
-		friend class D3D11RenderAPIFactory;
-
-		/**
-		 * @copydoc	RenderAPICore::initializePrepare
-		 */
-		void initializePrepare() override;
-
-		/**
-		 * @copydoc	RenderAPICore::initializeFinalize
-		 */
-		void initializeFinalize(const SPtr<RenderWindowCore>& primaryWindow) override;
-
-		/**
-		 * @copydoc	RenderAPICore::destroy_internal
-		 */
-		void destroyCore() override;
-
-		/**
-		 * @brief	Creates or retrieves a proper input layout depending on the currently set vertex shader
-		 * 			and vertex buffer.
-		 *
-		 *			Applies the input layout to the pipeline.
-		 */
-		void applyInputLayout();
-
-		/**
-		 * @brief	Recalculates actual viewport dimensions based on currently 
-		 *			set viewport normalized dimensions and render target and applies
-		 *			them for further rendering.
-		 */
-		void applyViewport();
-
-		/**
-		 * @brief	Creates and populates a set of render system capabilities describing which functionality
-		 *			is available.
-		 */
-		RenderAPICapabilities* createRenderSystemCapabilities() const;
-
-	private:
-		IDXGIFactory* mDXGIFactory;
-		D3D11Device* mDevice;
-
-		D3D11DriverList* mDriverList;
-		D3D11Driver* mActiveD3DDriver;
-
-		D3D_FEATURE_LEVEL mFeatureLevel;
-
-		D3D11HLSLProgramFactory* mHLSLFactory;
-		D3D11InputLayoutManager* mIAManager;
-
-		std::pair<SPtr<TextureCore>, TextureViewPtr> mBoundUAVs[D3D11_PS_CS_UAV_REGISTER_COUNT];
-
-		UINT32 mStencilRef;
-		Rect2 mViewportNorm;
-		D3D11_VIEWPORT mViewport;
-		D3D11_RECT mScissorRect;
-
-		SPtr<VertexDeclarationCore> mActiveVertexDeclaration;
-		SPtr<D3D11GpuProgramCore> mActiveVertexShader;
-
-		DrawOperationType mActiveDrawOp;
-	};
+#pragma once
+
+#include "BsD3D11Prerequisites.h"
+#include "BsRenderAPI.h"
+
+namespace BansheeEngine
+{
+	/**
+	 * @brief	Implementation of a render system using DirectX 11. Provides abstracted
+	 *			access to various low level DX11 methods.
+	 */
+	class BS_D3D11_EXPORT D3D11RenderAPI : public RenderAPICore
+	{
+	public:
+		D3D11RenderAPI();
+		~D3D11RenderAPI();
+
+		/**
+		 * @copydoc RenderAPICore::getName
+		 */
+		const StringID& getName() const override;
+		
+		/**
+		 * @copydoc RenderAPICore::getShadingLanguageName
+		 */
+		const String& getShadingLanguageName() const override;
+
+		/**
+		 * @copydoc	RenderAPICore::setBlendState
+		 */
+		void setBlendState(const SPtr<BlendStateCore>& blendState) override;
+
+		/**
+		 * @copydoc	RenderAPICore::setRasterizerState
+		 */
+		void setRasterizerState(const SPtr<RasterizerStateCore>& rasterizerState) override;
+
+		/**
+		 * @copydoc	RenderAPICore::setDepthStencilState
+		 */
+		void setDepthStencilState(const SPtr<DepthStencilStateCore>& depthStencilState, UINT32 stencilRefValue) override;
+
+		/**
+		 * @copydoc	RenderAPICore::setSamplerState
+		 */
+		void setSamplerState(GpuProgramType gptype, UINT16 texUnit, const SPtr<SamplerStateCore>& samplerState) override;
+
+		/**
+		 * @copydoc	RenderAPICore::setTexture
+		 */
+		void setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr) override;
+
+		/**
+		 * @copydoc	RenderAPICore::setLoadStoreTexture
+		 */
+		void setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr,
+			const TextureSurface& surface) override;
+
+		/**
+		 * @copydoc	RenderAPICore::disableTextureUnit
+		 */
+		void disableTextureUnit(GpuProgramType gptype, UINT16 texUnit) override;
+
+		/**
+		 * @copydoc	RenderAPICore::beginFrame
+		 */
+		void beginFrame() override;
+
+		/**
+		 * @copydoc	RenderAPICore::endFrame
+		 */
+		void endFrame() override;
+
+		/**
+		 * @copydoc RenderAPICore::clearRenderTarget
+		 */
+		void clearRenderTarget(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0) override;
+
+		/**
+		 * @copydoc RenderAPICore::clearViewport
+		 */
+		void clearViewport(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0) override;
+
+		/**
+		 * @copydoc	RenderAPICore::setRenderTarget
+		 */
+		void setRenderTarget(const SPtr<RenderTargetCore>& target, bool readOnlyDepthStencil = false) override;
+
+		/**
+		 * @copydoc	RenderAPICore::setViewport
+		 */
+		void setViewport(const Rect2& vp) override;
+
+		/**
+		 * @copydoc	RenderAPICore::setScissorRect
+		 */
+		void setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom) override;
+
+		/**
+		 * @copydoc	RenderAPICore::setVertexBuffers
+		 */
+		void setVertexBuffers(UINT32 index, SPtr<VertexBufferCore>* buffers, UINT32 numBuffers) override;
+
+		/**
+		 * @copydoc	RenderAPICore::setIndexBuffer
+		 */
+		void setIndexBuffer(const SPtr<IndexBufferCore>& buffer) override;
+
+		/**
+		 * @copydoc	RenderAPICore::setVertexDeclaration
+		 */
+		void setVertexDeclaration(const SPtr<VertexDeclarationCore>& vertexDeclaration) override;
+
+		/**
+		 * @copydoc	RenderAPICore::setDrawOperation
+		 */
+		void setDrawOperation(DrawOperationType op) override;
+
+		/**
+		 * @copydoc	RenderAPICore::draw
+		 */
+		void draw(UINT32 vertexOffset, UINT32 vertexCount) override;
+
+		/**
+		 * @copydoc	RenderAPICore::drawIndexed
+		 */
+		void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount) override;
+
+		/** 
+		 * @copydoc RenderAPICore::bindGpuProgram
+		 */
+		void bindGpuProgram(const SPtr<GpuProgramCore>& prg) override;
+
+		/** 
+		 * @copydoc RenderAPICore::unbindGpuProgram
+		 */
+		void unbindGpuProgram(GpuProgramType gptype) override;
+
+		/** 
+		 * @copydoc RenderAPICore::setConstantBuffers
+		 */
+		void setConstantBuffers(GpuProgramType gptype, const SPtr<GpuParamsCore>& params) override;
+		
+		/**
+		 * @copydoc	RenderAPICore::setClipPlanesImpl
+		 */
+		void setClipPlanesImpl(const PlaneList& clipPlanes) override;
+
+		/**
+		 * @copydoc	RenderAPICore::convertProjectionMatrix
+		 */
+		void convertProjectionMatrix(const Matrix4& matrix, Matrix4& dest) override;
+
+		/**
+		 * @copydoc	RenderAPICore::getColorVertexElementType
+		 */
+		VertexElementType getColorVertexElementType() const override;
+
+		/**
+		 * @copydoc	RenderAPICore::getHorizontalTexelOffset
+		 */
+		float getHorizontalTexelOffset() override;
+
+		/**
+		 * @copydoc	RenderAPICore::getVerticalTexelOffset
+		 */
+		float getVerticalTexelOffset() override;
+
+		/**
+		 * @copydoc	RenderAPICore::getMinimumDepthInputValue
+		 */
+		float getMinimumDepthInputValue() override;
+
+		/**
+		 * @copydoc	RenderAPICore::getMaximumDepthInputValue
+		 */
+		float getMaximumDepthInputValue() override;
+
+		/**
+		 * @copydoc RenderAPICore::generateParamBlockDesc()
+		 */
+		GpuParamBlockDesc generateParamBlockDesc(const String& name, Vector<GpuParamDataDesc>& params) override;
+
+		/************************************************************************/
+		/* 				Internal use by DX11 RenderSystem only                  */
+		/************************************************************************/
+
+		/**
+		 * @brief	Determines DXGI multisample settings from the provided parameters.
+		 *
+		 * @param	multisampleCount	Number of requested samples.
+		 * @param	format				Pixel format used by the render target.
+		 * @param	outputSampleDesc	Output structure that will contain the requested multisample settings.
+		 */
+		void determineMultisampleSettings(UINT32 multisampleCount, DXGI_FORMAT format, DXGI_SAMPLE_DESC* outputSampleDesc);
+
+		/**
+		 * @brief	Returns the main DXGI factory object.
+		 */
+		IDXGIFactory* getDXGIFactory() const { return mDXGIFactory; }
+
+		/**
+		 * @brief	Returns the primary DX11 device object.
+		 */
+		D3D11Device& getPrimaryDevice() const { return *mDevice; }
+		
+		/**
+		 * @brief	Returns information describing all available drivers.
+		 */
+		D3D11DriverList* getDriverList() const { return mDriverList; }
+
+	protected:
+		friend class D3D11RenderAPIFactory;
+
+		/**
+		 * @copydoc	RenderAPICore::initializePrepare
+		 */
+		void initializePrepare() override;
+
+		/**
+		 * @copydoc	RenderAPICore::initializeFinalize
+		 */
+		void initializeFinalize(const SPtr<RenderWindowCore>& primaryWindow) override;
+
+		/**
+		 * @copydoc	RenderAPICore::destroy_internal
+		 */
+		void destroyCore() override;
+
+		/**
+		 * @brief	Creates or retrieves a proper input layout depending on the currently set vertex shader
+		 * 			and vertex buffer.
+		 *
+		 *			Applies the input layout to the pipeline.
+		 */
+		void applyInputLayout();
+
+		/**
+		 * @brief	Recalculates actual viewport dimensions based on currently 
+		 *			set viewport normalized dimensions and render target and applies
+		 *			them for further rendering.
+		 */
+		void applyViewport();
+
+		/**
+		 * @brief	Creates and populates a set of render system capabilities describing which functionality
+		 *			is available.
+		 */
+		RenderAPICapabilities* createRenderSystemCapabilities() const;
+
+	private:
+		IDXGIFactory* mDXGIFactory;
+		D3D11Device* mDevice;
+
+		D3D11DriverList* mDriverList;
+		D3D11Driver* mActiveD3DDriver;
+
+		D3D_FEATURE_LEVEL mFeatureLevel;
+
+		D3D11HLSLProgramFactory* mHLSLFactory;
+		D3D11InputLayoutManager* mIAManager;
+
+		std::pair<SPtr<TextureCore>, TextureViewPtr> mBoundUAVs[D3D11_PS_CS_UAV_REGISTER_COUNT];
+
+		UINT32 mStencilRef;
+		Rect2 mViewportNorm;
+		D3D11_VIEWPORT mViewport;
+		D3D11_RECT mScissorRect;
+
+		SPtr<VertexDeclarationCore> mActiveVertexDeclaration;
+		SPtr<D3D11GpuProgramCore> mActiveVertexShader;
+
+		DrawOperationType mActiveDrawOp;
+	};
 }

+ 170 - 168
BansheeD3D11RenderAPI/Include/BsD3D11Texture.h

@@ -1,169 +1,171 @@
-#pragma once
-
-#include "BsD3D11Prerequisites.h"
-#include "BsTexture.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	DirectX 11 implementation of a texture.
-	 */
-	class D3D11TextureCore : public TextureCore
-	{
-	public:
-		~D3D11TextureCore();
-
-		/**
-		 * @brief	Returns internal DX11 texture resource object.
-		 */
-		ID3D11Resource* getDX11Resource() const { return mTex; }
-
-		/**
-		 * @brief	Returns shader resource view associated with the texture.
-		 */
-		ID3D11ShaderResourceView* getSRV() const { return mShaderResourceView; }
-
-		/**
-		 * @brief	Returns DXGI pixel format used by the texture.
-		 */
-		DXGI_FORMAT getDXGIFormat() const { return mDXGIFormat; }
-
-	protected:
-		friend class D3D11TextureCoreManager;
-
-		D3D11TextureCore(TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps,
-			PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount, const PixelDataPtr& initialData);
-
-		/**
-		* @copydoc	CoreObjectCore::initialize()
-		*/
-		void initialize() override;
-
-		/**
-		 * @copydoc Texture::lockImpl
-		 */
-		PixelData lockImpl(GpuLockOptions options, UINT32 mipLevel = 0, UINT32 face = 0) override;
-
-		/**
-		 * @copydoc Texture::unlockImpl
-		 */
-		void unlockImpl() override;
-
-		/**
-		 * @copydoc Texture::copyImpl
-		 */
-		void copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 destFace, UINT32 destMipLevel, const SPtr<TextureCore>& target) override;
-
-		/**
-		 * @copydoc Texture::readData
-		 */
-		void readData(PixelData& dest, UINT32 mipLevel = 0, UINT32 face = 0) override;
-
-		/**
-		 * @copydoc Texture::writeData
-		 */
-		void writeData(const PixelData& src, UINT32 mipLevel = 0, UINT32 face = 0, bool discardWholeBuffer = false) override;
-
-		/**
-		 * @brief	Creates a blank DX11 1D texture object.
-		 */
-		void create1DTex();
-
-		/**
-		 * @brief	Creates a blank DX11 2D texture object.
-		 */
-		void create2DTex();
-
-		/**
-		 * @brief	Creates a blank DX11 3D texture object.
-		 */
-		void create3DTex();
-
-		/**
-		 * @brief	Creates a staging buffer that is used as a temporary buffer for read operations on textures
-		 *			that do not support direct reading.
-		 */
-		void createStagingBuffer();
-
-		/**
-		 * @brief	Maps the specified texture surface for reading/writing. 
-		 *
-		 * @param	res			Texture resource to map.
-		 * @param	flags		Mapping flags that let the API know what are we planning to do with mapped memory.
-		 * @param	mipLevel	Mip level to map (0 being the base level).
-		 * @param	face		Texture face to map, in case texture has more than one.
-		 * @param	rowPitch	Output size of a single row in bytes.
-		 * @param	slicePitch	Output size of a single slice in bytes (relevant only for 3D textures).
-		 *
-		 * @returns	Pointer to the mapped area of memory.
-		 *
-		 * @note	Non-staging textures must be dynamic in order to be mapped directly and only for writing.
-		 *			No restrictions are made on staging textures.
-		 */
-		void* map(ID3D11Resource* res, D3D11_MAP flags, UINT32 mipLevel, UINT32 face, UINT32& rowPitch, UINT32& slicePitch);
-
-		/**
-		 * @brief	Unmaps a previously mapped texture.
-		 */
-		void unmap(ID3D11Resource* res);
-
-		/**
-		 * @brief	Copies texture data into a staging buffer and maps the staging buffer. Will create a staging
-		 *			buffer if one doesn't already exist (potentially wasting a lot of memory).
-		 *
-		 * @param	flags		Mapping flags that let the API know what are we planning to do with mapped memory.
-		 * @param	mipLevel	Mip level to map (0 being the base level).
-		 * @param	face		Texture face to map, in case texture has more than one.
-		 * @param	rowPitch	Output size of a single row in bytes.
-		 * @param	slicePitch	Output size of a single slice in bytes (relevant only for 3D textures).
-		 *
-		 * @returns	Pointer to the mapped area of memory.
-		 */
-		void* mapstagingbuffer(D3D11_MAP flags, UINT32 mipLevel, UINT32 face, UINT32& rowPitch, UINT32& slicePitch);
-
-		/**
-		 * @brief	Unmaps a previously mapped staging buffer.
-		 */
-		void unmapstagingbuffer();
-		
-		/**
-		 * @brief	Maps a static buffer, for writing only. Returned pointer points to temporary CPU memory
-		 *			that will be copied to the mapped resource on "unmap" call.
-		 *
-		 * @param	flags		Mapping flags that let the API know what are we planning to do with mapped memory.
-		 * @param	mipLevel	Mip level to map (0 being the base level).
-		 * @param	face		Texture face to map, in case texture has more than one.
-		 * @param	rowPitch	Output size of a single row in bytes.
-		 * @param	slicePitch	Output size of a single slice in bytes (relevant only for 3D textures).
-		 *
-		 * @returns	Pointer to the mapped area of memory.
-		 */
-		void* mapstaticbuffer(PixelData lock, UINT32 mipLevel, UINT32 slice);
-
-		/**
-		 * @brief	Unmaps a previously mapped static buffer and flushes its data to the actual GPU buffer.
-		 */
-		void unmapstaticbuffer();
-
-		/**
-		 * @brief	Creates an empty and uninitialized texture view object.
-		 */
-		TextureViewPtr createView(const SPtr<TextureCore>& texture, const TEXTURE_VIEW_DESC& desc) override;
-
-	protected:
-		ID3D11Texture1D* m1DTex;
-		ID3D11Texture2D* m2DTex;
-		ID3D11Texture3D* m3DTex;
-		ID3D11Resource* mTex;
-
-		ID3D11ShaderResourceView* mShaderResourceView;
-		D3D11_SHADER_RESOURCE_VIEW_DESC mSRVDesc;
-		D3D11_SRV_DIMENSION mDimension;
-		DXGI_FORMAT mDXGIFormat;
-
-		ID3D11Resource* mStagingBuffer;
-		PixelData* mStaticBuffer;
-		UINT32 mLockedSubresourceIdx;
-		bool mLockedForReading;
-	};
+#pragma once
+
+#include "BsD3D11Prerequisites.h"
+#include "BsTexture.h"
+
+namespace BansheeEngine
+{
+	/**
+	 * @brief	DirectX 11 implementation of a texture.
+	 */
+	class D3D11TextureCore : public TextureCore
+	{
+	public:
+		~D3D11TextureCore();
+
+		/**	Returns internal DX11 texture resource object. */
+		ID3D11Resource* getDX11Resource() const { return mTex; }
+
+		/**	Returns shader resource view associated with the texture. */
+		ID3D11ShaderResourceView* getSRV() const { return mShaderResourceView; }
+
+		/** Returns DXGI pixel format that was used to create the texture. */
+		DXGI_FORMAT getDXGIFormat() const { return mDXGIFormat; }
+
+		/** Returns DXGI pixel used for reading the texture as a shader resource or writing as a render target. */
+		DXGI_FORMAT getColorFormat() const { return mDXGIColorFormat; }
+
+		/** Returns DXGI pixel used for writing to a depth stencil texture. */
+		DXGI_FORMAT getDepthStencilFormat() const { return mDXGIDepthStencilFormat; }
+
+	protected:
+		friend class D3D11TextureCoreManager;
+
+		D3D11TextureCore(TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps,
+			PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount, const PixelDataPtr& initialData);
+
+		/**
+		* @copydoc	CoreObjectCore::initialize()
+		*/
+		void initialize() override;
+
+		/**
+		 * @copydoc Texture::lockImpl
+		 */
+		PixelData lockImpl(GpuLockOptions options, UINT32 mipLevel = 0, UINT32 face = 0) override;
+
+		/**
+		 * @copydoc Texture::unlockImpl
+		 */
+		void unlockImpl() override;
+
+		/**
+		 * @copydoc Texture::copyImpl
+		 */
+		void copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 destFace, UINT32 destMipLevel, const SPtr<TextureCore>& target) override;
+
+		/**
+		 * @copydoc Texture::readData
+		 */
+		void readData(PixelData& dest, UINT32 mipLevel = 0, UINT32 face = 0) override;
+
+		/**
+		 * @copydoc Texture::writeData
+		 */
+		void writeData(const PixelData& src, UINT32 mipLevel = 0, UINT32 face = 0, bool discardWholeBuffer = false) override;
+
+		/**
+		 * @brief	Creates a blank DX11 1D texture object.
+		 */
+		void create1DTex();
+
+		/**
+		 * @brief	Creates a blank DX11 2D texture object.
+		 */
+		void create2DTex();
+
+		/**
+		 * @brief	Creates a blank DX11 3D texture object.
+		 */
+		void create3DTex();
+
+		/**
+		 * @brief	Creates a staging buffer that is used as a temporary buffer for read operations on textures
+		 *			that do not support direct reading.
+		 */
+		void createStagingBuffer();
+
+		/**
+		 * @brief	Maps the specified texture surface for reading/writing. 
+		 *
+		 * @param	res			Texture resource to map.
+		 * @param	flags		Mapping flags that let the API know what are we planning to do with mapped memory.
+		 * @param	mipLevel	Mip level to map (0 being the base level).
+		 * @param	face		Texture face to map, in case texture has more than one.
+		 * @param	rowPitch	Output size of a single row in bytes.
+		 * @param	slicePitch	Output size of a single slice in bytes (relevant only for 3D textures).
+		 *
+		 * @returns	Pointer to the mapped area of memory.
+		 *
+		 * @note	Non-staging textures must be dynamic in order to be mapped directly and only for writing.
+		 *			No restrictions are made on staging textures.
+		 */
+		void* map(ID3D11Resource* res, D3D11_MAP flags, UINT32 mipLevel, UINT32 face, UINT32& rowPitch, UINT32& slicePitch);
+
+		/**
+		 * @brief	Unmaps a previously mapped texture.
+		 */
+		void unmap(ID3D11Resource* res);
+
+		/**
+		 * @brief	Copies texture data into a staging buffer and maps the staging buffer. Will create a staging
+		 *			buffer if one doesn't already exist (potentially wasting a lot of memory).
+		 *
+		 * @param	flags		Mapping flags that let the API know what are we planning to do with mapped memory.
+		 * @param	mipLevel	Mip level to map (0 being the base level).
+		 * @param	face		Texture face to map, in case texture has more than one.
+		 * @param	rowPitch	Output size of a single row in bytes.
+		 * @param	slicePitch	Output size of a single slice in bytes (relevant only for 3D textures).
+		 *
+		 * @returns	Pointer to the mapped area of memory.
+		 */
+		void* mapstagingbuffer(D3D11_MAP flags, UINT32 mipLevel, UINT32 face, UINT32& rowPitch, UINT32& slicePitch);
+
+		/**
+		 * @brief	Unmaps a previously mapped staging buffer.
+		 */
+		void unmapstagingbuffer();
+		
+		/**
+		 * @brief	Maps a static buffer, for writing only. Returned pointer points to temporary CPU memory
+		 *			that will be copied to the mapped resource on "unmap" call.
+		 *
+		 * @param	flags		Mapping flags that let the API know what are we planning to do with mapped memory.
+		 * @param	mipLevel	Mip level to map (0 being the base level).
+		 * @param	face		Texture face to map, in case texture has more than one.
+		 * @param	rowPitch	Output size of a single row in bytes.
+		 * @param	slicePitch	Output size of a single slice in bytes (relevant only for 3D textures).
+		 *
+		 * @returns	Pointer to the mapped area of memory.
+		 */
+		void* mapstaticbuffer(PixelData lock, UINT32 mipLevel, UINT32 slice);
+
+		/**
+		 * @brief	Unmaps a previously mapped static buffer and flushes its data to the actual GPU buffer.
+		 */
+		void unmapstaticbuffer();
+
+		/**
+		 * @brief	Creates an empty and uninitialized texture view object.
+		 */
+		TextureViewPtr createView(const SPtr<TextureCore>& texture, const TEXTURE_VIEW_DESC& desc) override;
+
+	protected:
+		ID3D11Texture1D* m1DTex;
+		ID3D11Texture2D* m2DTex;
+		ID3D11Texture3D* m3DTex;
+		ID3D11Resource* mTex;
+
+		ID3D11ShaderResourceView* mShaderResourceView;
+		D3D11_SHADER_RESOURCE_VIEW_DESC mSRVDesc;
+		D3D11_SRV_DIMENSION mDimension;
+		DXGI_FORMAT mDXGIFormat;
+		DXGI_FORMAT mDXGIColorFormat;
+		DXGI_FORMAT mDXGIDepthStencilFormat;
+
+		ID3D11Resource* mStagingBuffer;
+		PixelData* mStaticBuffer;
+		UINT32 mLockedSubresourceIdx;
+		bool mLockedForReading;
+	};
 }

+ 120 - 114
BansheeD3D11RenderAPI/Include/BsD3D11TextureView.h

@@ -1,115 +1,121 @@
-#pragma once
-
-#include "BsD3D11Prerequisites.h"
-#include "BsTextureView.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	DirectX implementation of a texture resource view.
-	 */
-	class BS_D3D11_EXPORT D3D11TextureView : public TextureView
-	{
-	public:
-		~D3D11TextureView();
-
-		/**
-		 * @brief	Returns a shader resource view. Caller must take care this texture view
-		 *			actually contains a shader resource view, otherwise it returns null.
-		 */
-		ID3D11ShaderResourceView* getSRV() const { return mSRV; }
-
-		/**
-		 * @brief	Returns a render target view. Caller must take care this texture view
-		 *			actually contains a render target view, otherwise it returns null.
-		 */
-		ID3D11RenderTargetView*	getRTV() const { return mRTV; }
-
-		/**
-		 * @brief	Returns a unordered access view. Caller must take care this texture view
-		 *			actually contains a unordered access view, otherwise it returns null.
-		 */
-		ID3D11UnorderedAccessView* getUAV() const { return mUAV; }
-
-		/**
-		 * @brief	Returns a depth stencil view. Caller must take care this texture view
-		 *			actually contains a depth stencil view, otherwise it returns null.
-		 */
-		ID3D11DepthStencilView*	getDSV() const { return mDSV; }
-
-	protected:
-		friend class D3D11TextureCore;
-
-		D3D11TextureView(const SPtr<TextureCore>& texture, const TEXTURE_VIEW_DESC& desc);
-	private:
-		/**
-		 * @brief	Creates a shader resource view that allows the provided surfaces 
-		 *			to be bound as normal shader resources.
-		 *
-		 * @param	texture			Texture to create the resource view for.
-		 * @param	mostDetailMip	First mip level to create the resource view for (0 - base level). 
-		 * @param	numMips			Number of mip levels to create the view for.
-		 * @param	firstArraySlice	First array slice to create the view for. This will be array index 
-		 *							for 1D and 2D array textures, texture slice index for 3D textures, and face
-		 *							index for cube textures (cube index * 6).
-		 * @param	nuMArraySlices	Number of array slices to create the view for. This will be number of
-		 *							array elements for 1D and 2D array textures, number of slices for 3D textures,
-		 *							and number of cubes for cube textures.
-		 */
-		ID3D11ShaderResourceView* createSRV(D3D11TextureCore* texture, 
-			UINT32 mostDetailMip, UINT32 numMips, UINT32 firstArraySlice, UINT32 numArraySlices);
-
-		/**
-		 * @brief	Creates a shader resource view that allows the provided surfaces 
-		 *			to be bound as render targets.
-		 *
-		 * @param	texture			Texture to create the resource view for.
-		 * @param	mipSlice		Mip level to create the resource view for (0 - base level).
-		 * @param	firstArraySlice	First array slice to create the view for. This will be array index 
-		 *							for 1D and 2D array textures, texture slice index for 3D textures, and face
-		 *							index for cube textures (cube index * 6).
-		 * @param	nuMArraySlices	Number of array slices to create the view for. This will be number of
-		 *							array elements for 1D and 2D array textures, number of slices for 3D textures,
-		 *							and number of cubes for cube textures.
-		 */
-		ID3D11RenderTargetView* createRTV(D3D11TextureCore* texture, 
-			UINT32 mipSlice, UINT32 firstArraySlice, UINT32 numArraySlices);
-
-		/**
-		 * @brief	Creates a shader resource view that allows the provided surfaces 
-		 *			to be bound as unordered access buffers.
-		 *
-		 * @param	texture			Texture to create the resource view for.
-		 * @param	mipSlice		Mip level to create the resource view for (0 - base level).
-		 * @param	firstArraySlice	First array slice to create the view for. This will be array index
-		 *							for 1D and 2D array textures, texture slice index for 3D textures, and face
-		 *							index for cube textures (cube index * 6).
-		 * @param	nuMArraySlices	Number of array slices to create the view for. This will be number of
-		 *							array elements for 1D and 2D array textures, number of slices for 3D textures,
-		 *							and number of cubes for cube textures.
-		 */
-		ID3D11UnorderedAccessView* createUAV(D3D11TextureCore* texture, 
-			UINT32 mipSlice, UINT32 firstArraySlice, UINT32 numArraySlices);
-
-		/**
-		 * @brief	Creates a shader resource view that allows the provided surfaces 
-		 *			to be bound as depth stencil buffers.
-		 *
-		 * @param	texture			Texture to create the resource view for.
-		 * @param	mipSlice		Mip level to create the resource view for (0 - base level).
-		 * @param	firstArraySlice	First array slice to create the view for. This will be array index
-		 *							for 1D and 2D array textures, texture slice index for 3D textures, and face
-		 *							index for cube textures (cube index * 6).
-		 * @param	nuMArraySlices	Number of array slices to create the view for. This will be number of
-		 *							array elements for 1D and 2D array textures, number of slices for 3D textures,
-		 *							and number of cubes for cube textures.
-		 */
-		ID3D11DepthStencilView* createDSV(D3D11TextureCore* texture, 
-			UINT32 mipSlice, UINT32 firstArraySlice, UINT32 numArraySlices);
-
-		ID3D11ShaderResourceView* mSRV;
-		ID3D11RenderTargetView* mRTV;
-		ID3D11UnorderedAccessView* mUAV;
-		ID3D11DepthStencilView*	mDSV;
-	};
+#pragma once
+
+#include "BsD3D11Prerequisites.h"
+#include "BsTextureView.h"
+
+namespace BansheeEngine
+{
+	/**
+	 * @brief	DirectX implementation of a texture resource view.
+	 */
+	class BS_D3D11_EXPORT D3D11TextureView : public TextureView
+	{
+	public:
+		~D3D11TextureView();
+
+		/**
+		 * @brief	Returns a shader resource view. Caller must take care this texture view
+		 *			actually contains a shader resource view, otherwise it returns null.
+		 */
+		ID3D11ShaderResourceView* getSRV() const { return mSRV; }
+
+		/**
+		 * @brief	Returns a render target view. Caller must take care this texture view
+		 *			actually contains a render target view, otherwise it returns null.
+		 */
+		ID3D11RenderTargetView*	getRTV() const { return mRTV; }
+
+		/**
+		 * @brief	Returns a unordered access view. Caller must take care this texture view
+		 *			actually contains a unordered access view, otherwise it returns null.
+		 */
+		ID3D11UnorderedAccessView* getUAV() const { return mUAV; }
+
+		/**
+		 * @brief	Returns a depth stencil view. Caller must take care this texture view
+		 *			actually contains a depth stencil view, otherwise it returns null.
+		 *
+		 * @param[in]	readOnly	Should the depth stencil view only support read operations (allows the bound texture to
+		 *							be also used as a shader resource view while bound as a depth stencil target).
+		 */
+		ID3D11DepthStencilView*	getDSV(bool readOnly) const { return readOnly ? mRODSV : mDSV; }
+
+	protected:
+		friend class D3D11TextureCore;
+
+		D3D11TextureView(const SPtr<TextureCore>& texture, const TEXTURE_VIEW_DESC& desc);
+	private:
+		/**
+		 * @brief	Creates a shader resource view that allows the provided surfaces 
+		 *			to be bound as normal shader resources.
+		 *
+		 * @param	texture			Texture to create the resource view for.
+		 * @param	mostDetailMip	First mip level to create the resource view for (0 - base level). 
+		 * @param	numMips			Number of mip levels to create the view for.
+		 * @param	firstArraySlice	First array slice to create the view for. This will be array index 
+		 *							for 1D and 2D array textures, texture slice index for 3D textures, and face
+		 *							index for cube textures (cube index * 6).
+		 * @param	numArraySlices	Number of array slices to create the view for. This will be number of
+		 *							array elements for 1D and 2D array textures, number of slices for 3D textures,
+		 *							and number of cubes for cube textures.
+		 */
+		ID3D11ShaderResourceView* createSRV(D3D11TextureCore* texture, 
+			UINT32 mostDetailMip, UINT32 numMips, UINT32 firstArraySlice, UINT32 numArraySlices);
+
+		/**
+		 * @brief	Creates a shader resource view that allows the provided surfaces 
+		 *			to be bound as render targets.
+		 *
+		 * @param	texture			Texture to create the resource view for.
+		 * @param	mipSlice		Mip level to create the resource view for (0 - base level).
+		 * @param	firstArraySlice	First array slice to create the view for. This will be array index 
+		 *							for 1D and 2D array textures, texture slice index for 3D textures, and face
+		 *							index for cube textures (cube index * 6).
+		 * @param	numArraySlices	Number of array slices to create the view for. This will be number of
+		 *							array elements for 1D and 2D array textures, number of slices for 3D textures,
+		 *							and number of cubes for cube textures.
+		 */
+		ID3D11RenderTargetView* createRTV(D3D11TextureCore* texture, 
+			UINT32 mipSlice, UINT32 firstArraySlice, UINT32 numArraySlices);
+
+		/**
+		 * @brief	Creates a shader resource view that allows the provided surfaces 
+		 *			to be bound as unordered access buffers.
+		 *
+		 * @param	texture			Texture to create the resource view for.
+		 * @param	mipSlice		Mip level to create the resource view for (0 - base level).
+		 * @param	firstArraySlice	First array slice to create the view for. This will be array index
+		 *							for 1D and 2D array textures, texture slice index for 3D textures, and face
+		 *							index for cube textures (cube index * 6).
+		 * @param	numArraySlices	Number of array slices to create the view for. This will be number of
+		 *							array elements for 1D and 2D array textures, number of slices for 3D textures,
+		 *							and number of cubes for cube textures.
+		 */
+		ID3D11UnorderedAccessView* createUAV(D3D11TextureCore* texture, 
+			UINT32 mipSlice, UINT32 firstArraySlice, UINT32 numArraySlices);
+
+		/**
+		 * @brief	Creates a shader resource view that allows the provided surfaces 
+		 *			to be bound as depth stencil buffers.
+		 *
+		 * @param	texture			Texture to create the resource view for.
+		 * @param	mipSlice		Mip level to create the resource view for (0 - base level).
+		 * @param	firstArraySlice	First array slice to create the view for. This will be array index
+		 *							for 1D and 2D array textures, texture slice index for 3D textures, and face
+		 *							index for cube textures (cube index * 6).
+		 * @param	numArraySlices	Number of array slices to create the view for. This will be number of
+		 *							array elements for 1D and 2D array textures, number of slices for 3D textures,
+		 *							and number of cubes for cube textures.
+		 * @param	readOnly		Should the depth stencil view only support read operations (allows the bound texture to
+		 *							be also used as a shader resource view while bound as a depth stencil target).
+		 */
+		ID3D11DepthStencilView* createDSV(D3D11TextureCore* texture, 
+			UINT32 mipSlice, UINT32 firstArraySlice, UINT32 numArraySlices, bool readOnly);
+
+		ID3D11ShaderResourceView* mSRV;
+		ID3D11RenderTargetView* mRTV;
+		ID3D11UnorderedAccessView* mUAV;
+		ID3D11DepthStencilView*	mDSV;
+		ID3D11DepthStencilView*	mRODSV;
+	};
 }

+ 859 - 825
BansheeD3D11RenderAPI/Source/BsD3D11Mappings.cpp

@@ -1,826 +1,860 @@
-#include "BsD3D11Mappings.h"
-#include "BsDebug.h"
-#include "BsException.h"
-
-namespace BansheeEngine
-{
-	D3D11_TEXTURE_ADDRESS_MODE D3D11Mappings::get(TextureAddressingMode tam)
-	{
-		switch(tam)
-		{
-		case TAM_WRAP:
-			return D3D11_TEXTURE_ADDRESS_WRAP;
-		case TAM_MIRROR:
-			return D3D11_TEXTURE_ADDRESS_MIRROR;
-		case TAM_CLAMP:
-			return D3D11_TEXTURE_ADDRESS_CLAMP;
-		case TAM_BORDER:
-			return D3D11_TEXTURE_ADDRESS_BORDER;
-		}
-
-		return D3D11_TEXTURE_ADDRESS_MIRROR_ONCE;
-	}
-
-	D3D11_BLEND D3D11Mappings::get(BlendFactor bf)
-	{
-		switch(bf)
-		{
-		case BF_ONE:
-			return D3D11_BLEND_ONE;
-		case BF_ZERO:
-			return D3D11_BLEND_ZERO;
-		case BF_DEST_COLOR:
-			return D3D11_BLEND_DEST_COLOR;
-		case BF_SOURCE_COLOR:
-			return D3D11_BLEND_SRC_COLOR;
-		case BF_INV_DEST_COLOR:
-			return D3D11_BLEND_INV_DEST_COLOR;
-		case BF_INV_SOURCE_COLOR:
-			return D3D11_BLEND_INV_SRC_COLOR;
-		case BF_DEST_ALPHA:
-			return D3D11_BLEND_DEST_ALPHA;
-		case BF_SOURCE_ALPHA:
-			return D3D11_BLEND_SRC_ALPHA;
-		case BF_INV_DEST_ALPHA:
-			return D3D11_BLEND_INV_DEST_ALPHA;
-		case BF_INV_SOURCE_ALPHA:
-			return D3D11_BLEND_INV_SRC_ALPHA;
-		}
-
-		// Unsupported type
-		return D3D11_BLEND_ZERO;
-	}
-
-	D3D11_BLEND_OP D3D11Mappings::get(BlendOperation bo)
-	{
-		switch(bo)
-		{
-		case BO_ADD:
-			return D3D11_BLEND_OP_ADD;
-		case BO_SUBTRACT:
-			return D3D11_BLEND_OP_SUBTRACT;
-		case BO_REVERSE_SUBTRACT:
-			return D3D11_BLEND_OP_REV_SUBTRACT;
-		case BO_MIN:
-			return D3D11_BLEND_OP_MIN;
-		case BO_MAX:
-			return D3D11_BLEND_OP_MAX;
-		}
-
-		// Unsupported type
-		return D3D11_BLEND_OP_ADD;
-	}
-
-	D3D11_COMPARISON_FUNC D3D11Mappings::get(CompareFunction cf)
-	{
-		switch(cf)
-		{
-		case CMPF_ALWAYS_FAIL:
-			return D3D11_COMPARISON_NEVER;
-		case CMPF_ALWAYS_PASS:
-			return D3D11_COMPARISON_ALWAYS;
-		case CMPF_LESS:
-			return D3D11_COMPARISON_LESS;
-		case CMPF_LESS_EQUAL:
-			return D3D11_COMPARISON_LESS_EQUAL;
-		case CMPF_EQUAL:
-			return D3D11_COMPARISON_EQUAL;
-		case CMPF_NOT_EQUAL:
-			return D3D11_COMPARISON_NOT_EQUAL;
-		case CMPF_GREATER_EQUAL:
-			return D3D11_COMPARISON_GREATER_EQUAL;
-		case CMPF_GREATER:
-			return D3D11_COMPARISON_GREATER;
-		};
-
-		// Unsupported type
-		return D3D11_COMPARISON_ALWAYS;
-	}
-
-	D3D11_CULL_MODE D3D11Mappings::get(CullingMode cm)
-	{
-		switch(cm)
-		{
-		case CULL_NONE:
-			return D3D11_CULL_NONE;
-		case CULL_CLOCKWISE:
-			return D3D11_CULL_FRONT;
-		case CULL_COUNTERCLOCKWISE:
-			return D3D11_CULL_BACK;
-		}
-
-		// Unsupported type
-		return D3D11_CULL_NONE;
-	}
-
-	D3D11_FILL_MODE D3D11Mappings::get(PolygonMode mode)
-	{
-		switch(mode)
-		{
-		case PM_WIREFRAME:
-			return D3D11_FILL_WIREFRAME;
-		case PM_SOLID:
-			return D3D11_FILL_SOLID;
-		}
-
-		return D3D11_FILL_SOLID;
-	}
-
-	D3D11_STENCIL_OP D3D11Mappings::get(StencilOperation op, bool invert)
-	{
-		switch(op)
-		{
-		case SOP_KEEP:
-			return D3D11_STENCIL_OP_KEEP;
-		case SOP_ZERO:
-			return D3D11_STENCIL_OP_ZERO;
-		case SOP_REPLACE:
-			return D3D11_STENCIL_OP_REPLACE;
-		case SOP_INCREMENT:
-			return invert ? D3D11_STENCIL_OP_DECR_SAT : D3D11_STENCIL_OP_INCR_SAT;
-		case SOP_DECREMENT:
-			return invert ? D3D11_STENCIL_OP_INCR_SAT : D3D11_STENCIL_OP_DECR_SAT;
-		case SOP_INCREMENT_WRAP:
-			return invert ? D3D11_STENCIL_OP_DECR : D3D11_STENCIL_OP_INCR;
-		case SOP_DECREMENT_WRAP:
-			return invert ? D3D11_STENCIL_OP_INCR : D3D11_STENCIL_OP_DECR;
-		case SOP_INVERT:
-			return D3D11_STENCIL_OP_INVERT;
-		}
-
-		// Unsupported type
-		return D3D11_STENCIL_OP_KEEP;
-	}
-
-	DWORD D3D11Mappings::get(FilterType ft)
-	{
-		switch (ft)
-		{
-		case FT_MIN:
-			return D3D11_MIN_FILTER_SHIFT;
-			break;
-		case FT_MAG:
-			return D3D11_MAG_FILTER_SHIFT;
-			break;
-		case FT_MIP:
-			return D3D11_MIP_FILTER_SHIFT;
-			break;
-		}
-
-		// Unsupported type
-		return D3D11_MIP_FILTER_SHIFT;
-	}
-
-	D3D11_FILTER D3D11Mappings::get(const FilterOptions min, const FilterOptions mag, const FilterOptions mip, const bool comparison)
-	{
-		D3D11_FILTER res;
-#define MERGE_FOR_SWITCH(_comparison_, _min_ , _mag_, _mip_ ) ((_comparison_ << 16) | (_min_ << 8) | (_mag_ << 4) | (_mip_))
-
-		switch((MERGE_FOR_SWITCH(comparison, min, mag, mip)))
-		{
-		case MERGE_FOR_SWITCH(true, FO_POINT, FO_POINT, FO_POINT):
-			res = D3D11_FILTER_COMPARISON_MIN_MAG_MIP_POINT;
-			break;
-		case MERGE_FOR_SWITCH(true, FO_POINT, FO_POINT, FO_LINEAR):
-			res = D3D11_FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR;
-			break;
-		case MERGE_FOR_SWITCH(true, FO_POINT, FO_LINEAR, FO_POINT):
-			res = D3D11_FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT;
-			break;
-		case MERGE_FOR_SWITCH(true, FO_POINT, FO_LINEAR, FO_LINEAR):
-			res = D3D11_FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR;
-			break;
-		case MERGE_FOR_SWITCH(true, FO_LINEAR, FO_POINT, FO_POINT):
-			res = D3D11_FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT;
-			break;
-		case MERGE_FOR_SWITCH(true, FO_LINEAR, FO_POINT, FO_LINEAR):
-			res = D3D11_FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
-			break;		
-		case MERGE_FOR_SWITCH(true, FO_LINEAR, FO_LINEAR, FO_POINT):
-			res = D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT;
-			break;
-		case MERGE_FOR_SWITCH(true, FO_LINEAR, FO_LINEAR, FO_LINEAR):
-			res = D3D11_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR;
-			break;
-		case MERGE_FOR_SWITCH(true, FO_ANISOTROPIC, FO_ANISOTROPIC, FO_ANISOTROPIC):
-			res = D3D11_FILTER_COMPARISON_ANISOTROPIC;
-			break;
-		case MERGE_FOR_SWITCH(false, FO_POINT, FO_POINT, FO_POINT):
-			res = D3D11_FILTER_MIN_MAG_MIP_POINT;
-			break;
-		case MERGE_FOR_SWITCH(false, FO_POINT, FO_POINT, FO_LINEAR):
-			res = D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
-			break;
-		case MERGE_FOR_SWITCH(false, FO_POINT, FO_LINEAR, FO_POINT):
-			res = D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
-			break;
-		case MERGE_FOR_SWITCH(false, FO_POINT, FO_LINEAR, FO_LINEAR):
-			res = D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR;
-			break;
-		case MERGE_FOR_SWITCH(false, FO_LINEAR, FO_POINT, FO_POINT):
-			res = D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
-			break;
-		case MERGE_FOR_SWITCH(false, FO_LINEAR, FO_POINT, FO_LINEAR):
-			res = D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
-			break;		
-		case MERGE_FOR_SWITCH(false, FO_LINEAR, FO_LINEAR, FO_POINT):
-			res = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
-			break;
-		case MERGE_FOR_SWITCH(false, FO_LINEAR, FO_LINEAR, FO_LINEAR):
-			res = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
-			break;
-		case MERGE_FOR_SWITCH(false, FO_ANISOTROPIC, FO_ANISOTROPIC, FO_ANISOTROPIC):
-			res = D3D11_FILTER_ANISOTROPIC;
-			break;
-		default:
-			res = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
-		}	
-
-		return res;
-	}
-
-	DWORD D3D11Mappings::get(GpuBufferUsage usage)
-	{
-		DWORD ret = D3D11_USAGE_DEFAULT;
-
-		if (usage & GBU_DYNAMIC)
-			ret = D3D11_USAGE_DYNAMIC;
-
-		return ret;
-	}
-
-	D3D11_MAP D3D11Mappings::get(GpuLockOptions options, GpuBufferUsage usage)
-	{
-		D3D11_MAP ret = D3D11_MAP_READ_WRITE;
-		if (options == GBL_WRITE_ONLY_DISCARD)
-		{
-			// D3D doesn't like discard on non-dynamic buffers
-			if (usage & GBU_DYNAMIC)
-				ret = D3D11_MAP_WRITE_DISCARD;
-			else
-				ret = D3D11_MAP_WRITE;
-		}
-		else if (options == GBL_READ_ONLY)
-		{
-			ret = D3D11_MAP_READ;
-		}
-		else if (options == GBL_WRITE_ONLY_NO_OVERWRITE)
-		{
-			ret = D3D11_MAP_WRITE_NO_OVERWRITE; // Only allowed for vertex/index buffers
-		}
-
-		return ret;
-	}
-
-	DXGI_FORMAT D3D11Mappings::get(VertexElementType type)
-	{
-		switch (type)
-		{
-		case VET_COLOR:
-		case VET_COLOR_ABGR:
-		case VET_COLOR_ARGB:
-			return DXGI_FORMAT_R8G8B8A8_UNORM;
-			break;
-		case VET_FLOAT1:
-			return DXGI_FORMAT_R32_FLOAT;
-			break;
-		case VET_FLOAT2:
-			return DXGI_FORMAT_R32G32_FLOAT;
-			break;
-		case VET_FLOAT3:
-			return DXGI_FORMAT_R32G32B32_FLOAT;
-			break;
-		case VET_FLOAT4:
-			return DXGI_FORMAT_R32G32B32A32_FLOAT;
-			break;
-		case VET_SHORT2:
-			return DXGI_FORMAT_R16G16_SINT;
-			break;
-		case VET_SHORT4:
-			return DXGI_FORMAT_R16G16B16A16_SINT;
-			break;
-		case VET_UBYTE4:
-			return DXGI_FORMAT_R8G8B8A8_UINT;
-			break;
-		case VET_UINT4:
-			return DXGI_FORMAT_R32G32B32A32_UINT;
-			break;
-		case VET_SINT4:
-			return DXGI_FORMAT_R32G32B32A32_SINT;
-			break;
-		}
-
-		// Unsupported type
-		return DXGI_FORMAT_R32G32B32A32_FLOAT;
-	}
-
-	VertexElementSemantic D3D11Mappings::get(LPCSTR sem)
-	{
-		if(strcmp(sem, "BLENDINDICES") == 0)
-			return VES_BLEND_INDICES;
-		if(strcmp(sem, "BLENDWEIGHT") == 0)
-			return VES_BLEND_WEIGHTS;
-		if(strcmp(sem, "COLOR") == 0)
-			return VES_COLOR;
-		if(strcmp(sem, "NORMAL") == 0)
-			return VES_NORMAL;
-		if(strcmp(sem, "POSITION") == 0)
-			return VES_POSITION;
-		if(strcmp(sem, "TEXCOORD") == 0)
-			return VES_TEXCOORD;
-		if(strcmp(sem, "BINORMAL") == 0)
-			return VES_BITANGENT;
-		if(strcmp(sem, "TANGENT") == 0)
-			return VES_TANGENT;
-		if(strcmp(sem, "POSITIONT") == 0)
-			return VES_POSITIONT;
-		if(strcmp(sem, "PSIZE") == 0) 
-			return VES_PSIZE;
-
-		// Unsupported type
-		return VES_POSITION;
-	}
-
-	LPCSTR D3D11Mappings::get(VertexElementSemantic sem)
-	{
-		switch (sem)	
-		{
-		case VES_BLEND_INDICES:
-			return "BLENDINDICES";
-			break;
-		case VES_BLEND_WEIGHTS:
-			return "BLENDWEIGHT";
-			break;
-		case VES_COLOR:
-			return "COLOR";
-			break;
-		case VES_NORMAL:
-			return "NORMAL";
-			break;
-		case VES_POSITION:
-			return "POSITION";
-			break;
-		case VES_TEXCOORD:
-			return "TEXCOORD";
-			break;
-		case VES_BITANGENT:
-			return "BINORMAL";
-			break;
-		case VES_TANGENT:
-			return "TANGENT";
-			break;
-		case VES_POSITIONT:
-			return "POSITIONT";
-			break;
-		case VES_PSIZE:
-			return "PSIZE";
-			break;
-		}
-
-		// Unsupported type
-		return "";
-	}
-
-	VertexElementType D3D11Mappings::getInputType(D3D_REGISTER_COMPONENT_TYPE type)
-	{
-		switch(type)
-		{
-		case D3D_REGISTER_COMPONENT_FLOAT32:
-			return VET_FLOAT4;
-		case D3D_REGISTER_COMPONENT_SINT32:
-			return VET_SINT4;
-		case D3D_REGISTER_COMPONENT_UINT32:
-			return VET_UINT4;
-		default:
-			return VET_FLOAT4;
-		}
-	}
-
-	void D3D11Mappings::get(const Color& inColor, float* outColor)
-	{
-		outColor[0] = inColor.r;
-		outColor[1] = inColor.g;
-		outColor[2] = inColor.b;
-		outColor[3] = inColor.a;	
-	}
-
-	PixelFormat D3D11Mappings::getPF(DXGI_FORMAT pf)
-	{
-		switch(pf)
-		{
-		case DXGI_FORMAT_UNKNOWN:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R32G32B32A32_TYPELESS:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R32G32B32A32_FLOAT:
-			return PF_FLOAT32_RGBA;
-		case DXGI_FORMAT_R32G32B32A32_UINT:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R32G32B32A32_SINT:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R32G32B32_TYPELESS:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R32G32B32_FLOAT:
-			return PF_FLOAT32_RGB;
-		case DXGI_FORMAT_R32G32B32_UINT:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R32G32B32_SINT:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R16G16B16A16_TYPELESS:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R16G16B16A16_FLOAT:
-			return PF_FLOAT16_RGBA;
-		case DXGI_FORMAT_R16G16B16A16_UNORM:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R16G16B16A16_UINT:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R16G16B16A16_SNORM:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R16G16B16A16_SINT:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R32G32_TYPELESS:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R32G32_FLOAT:
-			return PF_FLOAT32_RG;
-		case DXGI_FORMAT_R32G32_UINT:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R32G32_SINT:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R32G8X24_TYPELESS:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
-			return PF_D32_S8X24;
-		case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R10G10B10A2_TYPELESS:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R10G10B10A2_UNORM:
-			return PF_UNORM_R10G10B10A2;
-		case DXGI_FORMAT_R10G10B10A2_UINT:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R11G11B10_FLOAT:
-			return PF_FLOAT_R11G11B10;
-		case DXGI_FORMAT_R8G8B8A8_TYPELESS:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R8G8B8A8_UNORM:
-			return PF_R8G8B8A8;
-		case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R8G8B8A8_UINT:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R8G8B8A8_SNORM:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R8G8B8A8_SINT:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R16G16_TYPELESS:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R16G16_FLOAT:
-			return PF_FLOAT16_RG;
-		case DXGI_FORMAT_R16G16_UNORM:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R16G16_UINT:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R16G16_SNORM:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R16G16_SINT:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R32_TYPELESS:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_D32_FLOAT:
-			return PF_D32;
-		case DXGI_FORMAT_R32_FLOAT:
-			return PF_FLOAT32_R;
-		case DXGI_FORMAT_R32_UINT:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R32_SINT:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R24G8_TYPELESS:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_D24_UNORM_S8_UINT:
-			return PF_D24S8;
-		case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R8G8_TYPELESS:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R8G8_UNORM:
-			return PF_R8G8;
-		case DXGI_FORMAT_R8G8_UINT:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R8G8_SNORM:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R8G8_SINT:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R16_TYPELESS:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R16_FLOAT:
-			return PF_FLOAT16_R;
-		case DXGI_FORMAT_D16_UNORM:
-			return PF_D16;
-		case DXGI_FORMAT_R16_UNORM:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R16_UINT:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R16_SNORM:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R16_SINT:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R8_TYPELESS:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R8_UNORM:
-			return PF_R8;
-		case DXGI_FORMAT_R8_UINT:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R8_SNORM:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R8_SINT:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_A8_UNORM:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R1_UNORM:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_R8G8_B8G8_UNORM:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_G8R8_G8B8_UNORM:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_BC1_TYPELESS:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_BC1_UNORM:
-			return PF_BC1;
-		case DXGI_FORMAT_BC1_UNORM_SRGB:
-			return PF_BC1;
-		case DXGI_FORMAT_BC2_TYPELESS:
-			return PF_BC2;
-		case DXGI_FORMAT_BC2_UNORM:
-			return PF_BC2;
-		case DXGI_FORMAT_BC2_UNORM_SRGB:
-			return PF_BC2;
-		case DXGI_FORMAT_BC3_TYPELESS:
-			return PF_BC3;
-		case DXGI_FORMAT_BC3_UNORM:
-			return PF_BC3;
-		case DXGI_FORMAT_BC3_UNORM_SRGB:
-			return PF_BC3;
-		case DXGI_FORMAT_BC4_TYPELESS:
-			return PF_BC4;
-		case DXGI_FORMAT_BC4_UNORM:
-			return PF_BC4;
-		case DXGI_FORMAT_BC4_SNORM:
-			return PF_BC4;
-		case DXGI_FORMAT_BC5_TYPELESS:
-			return PF_BC5;
-		case DXGI_FORMAT_BC5_UNORM:
-			return PF_BC5;
-		case DXGI_FORMAT_BC5_SNORM:
-			return PF_BC5;
-		case DXGI_FORMAT_BC6H_UF16:
-			return PF_BC6H;
-		case DXGI_FORMAT_BC6H_SF16:
-			return PF_BC6H;
-		case DXGI_FORMAT_BC6H_TYPELESS:
-			return PF_BC6H;
-		case DXGI_FORMAT_BC7_UNORM:
-			return PF_BC7;
-		case DXGI_FORMAT_BC7_UNORM_SRGB:
-			return PF_BC7;
-		case DXGI_FORMAT_BC7_TYPELESS:
-			return PF_BC7;
-		case DXGI_FORMAT_B5G6R5_UNORM:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_B5G5R5A1_UNORM:
-			return PF_UNKNOWN;
-		case DXGI_FORMAT_B8G8R8A8_UNORM:
-			return PF_B8G8R8A8;
-		case DXGI_FORMAT_B8G8R8X8_UNORM:
-			return PF_B8G8R8X8;
-		default:
-			return PF_UNKNOWN;
-		}
-	}
-
-	DXGI_FORMAT D3D11Mappings::getPF(PixelFormat pf, bool gamma)
-	{
-		switch(pf)
-		{
-		case PF_R8:
-			return DXGI_FORMAT_R8_UNORM;
-		case PF_R8G8:
-			return DXGI_FORMAT_R8G8_UNORM; 
-		case PF_R8G8B8:
-			return DXGI_FORMAT_UNKNOWN;
-		case PF_A8R8G8B8:
-			return DXGI_FORMAT_UNKNOWN;
-		case PF_A8B8G8R8:
-			return DXGI_FORMAT_UNKNOWN;
-		case PF_X8R8G8B8:
-			return DXGI_FORMAT_UNKNOWN;
-		case PF_X8B8G8R8:
-			return DXGI_FORMAT_UNKNOWN;
-		case PF_R8G8B8A8:
-			return DXGI_FORMAT_R8G8B8A8_UNORM;
-		case PF_B8G8R8A8:
-			return DXGI_FORMAT_B8G8R8A8_UNORM;
-		case PF_B8G8R8X8:
-			return DXGI_FORMAT_B8G8R8X8_UNORM;
-		case PF_FLOAT16_R:
-			return DXGI_FORMAT_R16_FLOAT;
-		case PF_FLOAT16_RG:
-			return DXGI_FORMAT_R16G16_FLOAT;
-		case PF_FLOAT16_RGB:
-			return DXGI_FORMAT_UNKNOWN;
-		case PF_FLOAT16_RGBA:
-			return DXGI_FORMAT_R16G16B16A16_FLOAT;
-		case PF_FLOAT32_R:
-			return DXGI_FORMAT_R32_FLOAT;
-		case PF_FLOAT32_RG:
-			return DXGI_FORMAT_R32G32_FLOAT;
-		case PF_FLOAT32_RGB:
-			return DXGI_FORMAT_R32G32B32_FLOAT;
-		case PF_FLOAT32_RGBA:
-			return DXGI_FORMAT_R32G32B32A32_FLOAT;
-		case PF_BC1:
-		case PF_BC1a:
-			return DXGI_FORMAT_BC1_UNORM;
-		case PF_BC2:
-			return DXGI_FORMAT_BC2_UNORM;
-		case PF_BC3:
-			return DXGI_FORMAT_BC3_UNORM;
-		case PF_BC4:
-			return DXGI_FORMAT_BC4_UNORM;
-		case PF_BC5:
-			return DXGI_FORMAT_BC5_UNORM;
-		case PF_BC6H:
-			return DXGI_FORMAT_BC6H_UF16;
-		case PF_BC7:
-			if (gamma)
-				return DXGI_FORMAT_BC7_UNORM_SRGB;
-			else
-				return DXGI_FORMAT_BC7_UNORM;
-		case PF_D32_S8X24:
-			return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
-		case PF_D24S8:
-			return DXGI_FORMAT_D24_UNORM_S8_UINT;
-		case PF_D32:
-			return DXGI_FORMAT_D32_FLOAT;
-		case PF_D16:
-			return DXGI_FORMAT_D16_UNORM;
-		case PF_FLOAT_R11G11B10:
-			return DXGI_FORMAT_R11G11B10_FLOAT;
-		case PF_UNORM_R10G10B10A2:
-			return DXGI_FORMAT_R10G10B10A2_UNORM;
-		case PF_UNKNOWN:
-		default:
-			return DXGI_FORMAT_UNKNOWN;
-		}
-	}
-
-	PixelFormat D3D11Mappings::getClosestSupportedPF(PixelFormat pf, bool hwGamma)
-	{
-		if (getPF(pf, hwGamma) != DXGI_FORMAT_UNKNOWN)
-		{
-			return pf;
-		}
-		switch(pf)
-		{
-		case PF_FLOAT16_RGB:
-			return PF_FLOAT16_RGBA;
-		case PF_R8G8B8:
-			return PF_R8G8B8A8;
-		case PF_B8G8R8:
-			return PF_R8G8B8A8;
-		case PF_A8R8G8B8:
-			return PF_R8G8B8A8;
-		case PF_A8B8G8R8:
-			return PF_B8G8R8A8;
-		case PF_X8R8G8B8:
-			return PF_R8G8B8A8;
-		case PF_X8B8G8R8:
-			return PF_B8G8R8X8;
-		case PF_R8G8B8X8:
-			return PF_B8G8R8X8;
-		case PF_UNKNOWN:
-		default:
-			return PF_R8G8B8A8;
-		}
-	}
-
-	D3D11_USAGE D3D11Mappings::getUsage(GpuBufferUsage usage)
-	{
-		if (isDynamic(usage))
-			return D3D11_USAGE_DYNAMIC;
-		else
-			return D3D11_USAGE_DEFAULT;
-	}
-
-	bool D3D11Mappings::isDynamic(GpuBufferUsage usage)
-	{
-		switch (usage)
-		{
-		case GBU_DYNAMIC:
-			return true;
-		}
-
-		return false;
-	}
-
-	bool D3D11Mappings::isMappingWrite(D3D11_MAP map)
-	{
-		if(map == D3D11_MAP_READ)
-			return false;
-
-		return true;
-	}
-
-	bool D3D11Mappings::isMappingRead(D3D11_MAP map)
-	{
-		if(map == D3D11_MAP_READ || map == D3D11_MAP_READ_WRITE)
-			return true;
-
-		return false;
-	}
-
-	UINT D3D11Mappings::getAccessFlags(GpuBufferUsage usage)
-	{
-		if(isDynamic(usage))
-			return D3D11_CPU_ACCESS_WRITE;
-		else
-			return 0;
-	}
-
-	D3D11_PRIMITIVE_TOPOLOGY D3D11Mappings::getPrimitiveType(DrawOperationType type)
-	{
-		switch(type)
-		{
-		case DOT_POINT_LIST:
-			return D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
-		case DOT_LINE_LIST:
-			return D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
-		case DOT_LINE_STRIP:
-			return D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP;
-		case DOT_TRIANGLE_LIST:
-			return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
-		case DOT_TRIANGLE_STRIP:
-			return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
-		case DOT_TRIANGLE_FAN:
-			BS_EXCEPT(InvalidParametersException, "D3D11 doesn't support triangle fan primitive type.");
-		}
-
-		return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
-	}
-
-	UINT32 D3D11Mappings::getSizeInBytes(PixelFormat pf, UINT32 width, UINT32 height)
-	{
-		if(width == 0 || height == 0)
-			return 0;
-
-		if(PixelUtil::isCompressed(pf))
-		{
-			// D3D wants the width of one row of cells in bytes
-			if (pf == PF_BC1 || pf == PF_BC4)
-			{
-				// 64 bits (8 bytes) per 4x4 block
-				return std::max<UINT32>(1, width / 4) * std::max<UINT32>(1, height / 4) * 8;
-			}
-			else
-			{
-				// 128 bits (16 bytes) per 4x4 block
-				return std::max<UINT32>(1, width / 4) * std::max<UINT32>(1, height / 4) * 16;
-			}
-		}
-		else
-		{
-			return width * height * PixelUtil::getNumElemBytes(pf);
-		}
-	}
-
-	D3D11_MAP D3D11Mappings::getLockOptions(GpuLockOptions lockOptions)
-	{
-		switch(lockOptions)
-		{
-		case GBL_WRITE_ONLY_NO_OVERWRITE:
-			return D3D11_MAP_WRITE_NO_OVERWRITE;
-			break;
-		case GBL_READ_WRITE:
-			return D3D11_MAP_READ_WRITE;
-			break;
-		case GBL_WRITE_ONLY_DISCARD:
-			return D3D11_MAP_WRITE_DISCARD;
-			break;
-		case GBL_READ_ONLY:
-			return D3D11_MAP_READ;
-			break;
-		case GBL_WRITE_ONLY:
-			return D3D11_MAP_WRITE;
-			break;
-		default: 
-			break;
-		};
-
-		BS_EXCEPT(RenderingAPIException, "Invalid lock option. No DX11 equivalent of: " + toString(lockOptions));
-	}
+#include "BsD3D11Mappings.h"
+#include "BsDebug.h"
+#include "BsException.h"
+
+namespace BansheeEngine
+{
+	D3D11_TEXTURE_ADDRESS_MODE D3D11Mappings::get(TextureAddressingMode tam)
+	{
+		switch(tam)
+		{
+		case TAM_WRAP:
+			return D3D11_TEXTURE_ADDRESS_WRAP;
+		case TAM_MIRROR:
+			return D3D11_TEXTURE_ADDRESS_MIRROR;
+		case TAM_CLAMP:
+			return D3D11_TEXTURE_ADDRESS_CLAMP;
+		case TAM_BORDER:
+			return D3D11_TEXTURE_ADDRESS_BORDER;
+		}
+
+		return D3D11_TEXTURE_ADDRESS_MIRROR_ONCE;
+	}
+
+	D3D11_BLEND D3D11Mappings::get(BlendFactor bf)
+	{
+		switch(bf)
+		{
+		case BF_ONE:
+			return D3D11_BLEND_ONE;
+		case BF_ZERO:
+			return D3D11_BLEND_ZERO;
+		case BF_DEST_COLOR:
+			return D3D11_BLEND_DEST_COLOR;
+		case BF_SOURCE_COLOR:
+			return D3D11_BLEND_SRC_COLOR;
+		case BF_INV_DEST_COLOR:
+			return D3D11_BLEND_INV_DEST_COLOR;
+		case BF_INV_SOURCE_COLOR:
+			return D3D11_BLEND_INV_SRC_COLOR;
+		case BF_DEST_ALPHA:
+			return D3D11_BLEND_DEST_ALPHA;
+		case BF_SOURCE_ALPHA:
+			return D3D11_BLEND_SRC_ALPHA;
+		case BF_INV_DEST_ALPHA:
+			return D3D11_BLEND_INV_DEST_ALPHA;
+		case BF_INV_SOURCE_ALPHA:
+			return D3D11_BLEND_INV_SRC_ALPHA;
+		}
+
+		// Unsupported type
+		return D3D11_BLEND_ZERO;
+	}
+
+	D3D11_BLEND_OP D3D11Mappings::get(BlendOperation bo)
+	{
+		switch(bo)
+		{
+		case BO_ADD:
+			return D3D11_BLEND_OP_ADD;
+		case BO_SUBTRACT:
+			return D3D11_BLEND_OP_SUBTRACT;
+		case BO_REVERSE_SUBTRACT:
+			return D3D11_BLEND_OP_REV_SUBTRACT;
+		case BO_MIN:
+			return D3D11_BLEND_OP_MIN;
+		case BO_MAX:
+			return D3D11_BLEND_OP_MAX;
+		}
+
+		// Unsupported type
+		return D3D11_BLEND_OP_ADD;
+	}
+
+	D3D11_COMPARISON_FUNC D3D11Mappings::get(CompareFunction cf)
+	{
+		switch(cf)
+		{
+		case CMPF_ALWAYS_FAIL:
+			return D3D11_COMPARISON_NEVER;
+		case CMPF_ALWAYS_PASS:
+			return D3D11_COMPARISON_ALWAYS;
+		case CMPF_LESS:
+			return D3D11_COMPARISON_LESS;
+		case CMPF_LESS_EQUAL:
+			return D3D11_COMPARISON_LESS_EQUAL;
+		case CMPF_EQUAL:
+			return D3D11_COMPARISON_EQUAL;
+		case CMPF_NOT_EQUAL:
+			return D3D11_COMPARISON_NOT_EQUAL;
+		case CMPF_GREATER_EQUAL:
+			return D3D11_COMPARISON_GREATER_EQUAL;
+		case CMPF_GREATER:
+			return D3D11_COMPARISON_GREATER;
+		};
+
+		// Unsupported type
+		return D3D11_COMPARISON_ALWAYS;
+	}
+
+	D3D11_CULL_MODE D3D11Mappings::get(CullingMode cm)
+	{
+		switch(cm)
+		{
+		case CULL_NONE:
+			return D3D11_CULL_NONE;
+		case CULL_CLOCKWISE:
+			return D3D11_CULL_FRONT;
+		case CULL_COUNTERCLOCKWISE:
+			return D3D11_CULL_BACK;
+		}
+
+		// Unsupported type
+		return D3D11_CULL_NONE;
+	}
+
+	D3D11_FILL_MODE D3D11Mappings::get(PolygonMode mode)
+	{
+		switch(mode)
+		{
+		case PM_WIREFRAME:
+			return D3D11_FILL_WIREFRAME;
+		case PM_SOLID:
+			return D3D11_FILL_SOLID;
+		}
+
+		return D3D11_FILL_SOLID;
+	}
+
+	D3D11_STENCIL_OP D3D11Mappings::get(StencilOperation op, bool invert)
+	{
+		switch(op)
+		{
+		case SOP_KEEP:
+			return D3D11_STENCIL_OP_KEEP;
+		case SOP_ZERO:
+			return D3D11_STENCIL_OP_ZERO;
+		case SOP_REPLACE:
+			return D3D11_STENCIL_OP_REPLACE;
+		case SOP_INCREMENT:
+			return invert ? D3D11_STENCIL_OP_DECR_SAT : D3D11_STENCIL_OP_INCR_SAT;
+		case SOP_DECREMENT:
+			return invert ? D3D11_STENCIL_OP_INCR_SAT : D3D11_STENCIL_OP_DECR_SAT;
+		case SOP_INCREMENT_WRAP:
+			return invert ? D3D11_STENCIL_OP_DECR : D3D11_STENCIL_OP_INCR;
+		case SOP_DECREMENT_WRAP:
+			return invert ? D3D11_STENCIL_OP_INCR : D3D11_STENCIL_OP_DECR;
+		case SOP_INVERT:
+			return D3D11_STENCIL_OP_INVERT;
+		}
+
+		// Unsupported type
+		return D3D11_STENCIL_OP_KEEP;
+	}
+
+	DWORD D3D11Mappings::get(FilterType ft)
+	{
+		switch (ft)
+		{
+		case FT_MIN:
+			return D3D11_MIN_FILTER_SHIFT;
+			break;
+		case FT_MAG:
+			return D3D11_MAG_FILTER_SHIFT;
+			break;
+		case FT_MIP:
+			return D3D11_MIP_FILTER_SHIFT;
+			break;
+		}
+
+		// Unsupported type
+		return D3D11_MIP_FILTER_SHIFT;
+	}
+
+	D3D11_FILTER D3D11Mappings::get(const FilterOptions min, const FilterOptions mag, const FilterOptions mip, const bool comparison)
+	{
+		D3D11_FILTER res;
+#define MERGE_FOR_SWITCH(_comparison_, _min_ , _mag_, _mip_ ) ((_comparison_ << 16) | (_min_ << 8) | (_mag_ << 4) | (_mip_))
+
+		switch((MERGE_FOR_SWITCH(comparison, min, mag, mip)))
+		{
+		case MERGE_FOR_SWITCH(true, FO_POINT, FO_POINT, FO_POINT):
+			res = D3D11_FILTER_COMPARISON_MIN_MAG_MIP_POINT;
+			break;
+		case MERGE_FOR_SWITCH(true, FO_POINT, FO_POINT, FO_LINEAR):
+			res = D3D11_FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR;
+			break;
+		case MERGE_FOR_SWITCH(true, FO_POINT, FO_LINEAR, FO_POINT):
+			res = D3D11_FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT;
+			break;
+		case MERGE_FOR_SWITCH(true, FO_POINT, FO_LINEAR, FO_LINEAR):
+			res = D3D11_FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR;
+			break;
+		case MERGE_FOR_SWITCH(true, FO_LINEAR, FO_POINT, FO_POINT):
+			res = D3D11_FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT;
+			break;
+		case MERGE_FOR_SWITCH(true, FO_LINEAR, FO_POINT, FO_LINEAR):
+			res = D3D11_FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
+			break;		
+		case MERGE_FOR_SWITCH(true, FO_LINEAR, FO_LINEAR, FO_POINT):
+			res = D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT;
+			break;
+		case MERGE_FOR_SWITCH(true, FO_LINEAR, FO_LINEAR, FO_LINEAR):
+			res = D3D11_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR;
+			break;
+		case MERGE_FOR_SWITCH(true, FO_ANISOTROPIC, FO_ANISOTROPIC, FO_ANISOTROPIC):
+			res = D3D11_FILTER_COMPARISON_ANISOTROPIC;
+			break;
+		case MERGE_FOR_SWITCH(false, FO_POINT, FO_POINT, FO_POINT):
+			res = D3D11_FILTER_MIN_MAG_MIP_POINT;
+			break;
+		case MERGE_FOR_SWITCH(false, FO_POINT, FO_POINT, FO_LINEAR):
+			res = D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
+			break;
+		case MERGE_FOR_SWITCH(false, FO_POINT, FO_LINEAR, FO_POINT):
+			res = D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
+			break;
+		case MERGE_FOR_SWITCH(false, FO_POINT, FO_LINEAR, FO_LINEAR):
+			res = D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR;
+			break;
+		case MERGE_FOR_SWITCH(false, FO_LINEAR, FO_POINT, FO_POINT):
+			res = D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
+			break;
+		case MERGE_FOR_SWITCH(false, FO_LINEAR, FO_POINT, FO_LINEAR):
+			res = D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
+			break;		
+		case MERGE_FOR_SWITCH(false, FO_LINEAR, FO_LINEAR, FO_POINT):
+			res = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
+			break;
+		case MERGE_FOR_SWITCH(false, FO_LINEAR, FO_LINEAR, FO_LINEAR):
+			res = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
+			break;
+		case MERGE_FOR_SWITCH(false, FO_ANISOTROPIC, FO_ANISOTROPIC, FO_ANISOTROPIC):
+			res = D3D11_FILTER_ANISOTROPIC;
+			break;
+		default:
+			res = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
+		}	
+
+		return res;
+	}
+
+	DWORD D3D11Mappings::get(GpuBufferUsage usage)
+	{
+		DWORD ret = D3D11_USAGE_DEFAULT;
+
+		if (usage & GBU_DYNAMIC)
+			ret = D3D11_USAGE_DYNAMIC;
+
+		return ret;
+	}
+
+	D3D11_MAP D3D11Mappings::get(GpuLockOptions options, GpuBufferUsage usage)
+	{
+		D3D11_MAP ret = D3D11_MAP_READ_WRITE;
+		if (options == GBL_WRITE_ONLY_DISCARD)
+		{
+			// D3D doesn't like discard on non-dynamic buffers
+			if (usage & GBU_DYNAMIC)
+				ret = D3D11_MAP_WRITE_DISCARD;
+			else
+				ret = D3D11_MAP_WRITE;
+		}
+		else if (options == GBL_READ_ONLY)
+		{
+			ret = D3D11_MAP_READ;
+		}
+		else if (options == GBL_WRITE_ONLY_NO_OVERWRITE)
+		{
+			ret = D3D11_MAP_WRITE_NO_OVERWRITE; // Only allowed for vertex/index buffers
+		}
+
+		return ret;
+	}
+
+	DXGI_FORMAT D3D11Mappings::get(VertexElementType type)
+	{
+		switch (type)
+		{
+		case VET_COLOR:
+		case VET_COLOR_ABGR:
+		case VET_COLOR_ARGB:
+			return DXGI_FORMAT_R8G8B8A8_UNORM;
+			break;
+		case VET_FLOAT1:
+			return DXGI_FORMAT_R32_FLOAT;
+			break;
+		case VET_FLOAT2:
+			return DXGI_FORMAT_R32G32_FLOAT;
+			break;
+		case VET_FLOAT3:
+			return DXGI_FORMAT_R32G32B32_FLOAT;
+			break;
+		case VET_FLOAT4:
+			return DXGI_FORMAT_R32G32B32A32_FLOAT;
+			break;
+		case VET_SHORT2:
+			return DXGI_FORMAT_R16G16_SINT;
+			break;
+		case VET_SHORT4:
+			return DXGI_FORMAT_R16G16B16A16_SINT;
+			break;
+		case VET_UBYTE4:
+			return DXGI_FORMAT_R8G8B8A8_UINT;
+			break;
+		case VET_UINT4:
+			return DXGI_FORMAT_R32G32B32A32_UINT;
+			break;
+		case VET_SINT4:
+			return DXGI_FORMAT_R32G32B32A32_SINT;
+			break;
+		}
+
+		// Unsupported type
+		return DXGI_FORMAT_R32G32B32A32_FLOAT;
+	}
+
+	VertexElementSemantic D3D11Mappings::get(LPCSTR sem)
+	{
+		if(strcmp(sem, "BLENDINDICES") == 0)
+			return VES_BLEND_INDICES;
+		if(strcmp(sem, "BLENDWEIGHT") == 0)
+			return VES_BLEND_WEIGHTS;
+		if(strcmp(sem, "COLOR") == 0)
+			return VES_COLOR;
+		if(strcmp(sem, "NORMAL") == 0)
+			return VES_NORMAL;
+		if(strcmp(sem, "POSITION") == 0)
+			return VES_POSITION;
+		if(strcmp(sem, "TEXCOORD") == 0)
+			return VES_TEXCOORD;
+		if(strcmp(sem, "BINORMAL") == 0)
+			return VES_BITANGENT;
+		if(strcmp(sem, "TANGENT") == 0)
+			return VES_TANGENT;
+		if(strcmp(sem, "POSITIONT") == 0)
+			return VES_POSITIONT;
+		if(strcmp(sem, "PSIZE") == 0) 
+			return VES_PSIZE;
+
+		// Unsupported type
+		return VES_POSITION;
+	}
+
+	LPCSTR D3D11Mappings::get(VertexElementSemantic sem)
+	{
+		switch (sem)	
+		{
+		case VES_BLEND_INDICES:
+			return "BLENDINDICES";
+			break;
+		case VES_BLEND_WEIGHTS:
+			return "BLENDWEIGHT";
+			break;
+		case VES_COLOR:
+			return "COLOR";
+			break;
+		case VES_NORMAL:
+			return "NORMAL";
+			break;
+		case VES_POSITION:
+			return "POSITION";
+			break;
+		case VES_TEXCOORD:
+			return "TEXCOORD";
+			break;
+		case VES_BITANGENT:
+			return "BINORMAL";
+			break;
+		case VES_TANGENT:
+			return "TANGENT";
+			break;
+		case VES_POSITIONT:
+			return "POSITIONT";
+			break;
+		case VES_PSIZE:
+			return "PSIZE";
+			break;
+		}
+
+		// Unsupported type
+		return "";
+	}
+
+	VertexElementType D3D11Mappings::getInputType(D3D_REGISTER_COMPONENT_TYPE type)
+	{
+		switch(type)
+		{
+		case D3D_REGISTER_COMPONENT_FLOAT32:
+			return VET_FLOAT4;
+		case D3D_REGISTER_COMPONENT_SINT32:
+			return VET_SINT4;
+		case D3D_REGISTER_COMPONENT_UINT32:
+			return VET_UINT4;
+		default:
+			return VET_FLOAT4;
+		}
+	}
+
+	void D3D11Mappings::get(const Color& inColor, float* outColor)
+	{
+		outColor[0] = inColor.r;
+		outColor[1] = inColor.g;
+		outColor[2] = inColor.b;
+		outColor[3] = inColor.a;	
+	}
+
+	PixelFormat D3D11Mappings::getPF(DXGI_FORMAT pf)
+	{
+		switch(pf)
+		{
+		case DXGI_FORMAT_UNKNOWN:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R32G32B32A32_FLOAT:
+			return PF_FLOAT32_RGBA;
+		case DXGI_FORMAT_R32G32B32A32_UINT:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R32G32B32A32_SINT:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R32G32B32_TYPELESS:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R32G32B32_FLOAT:
+			return PF_FLOAT32_RGB;
+		case DXGI_FORMAT_R32G32B32_UINT:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R32G32B32_SINT:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R16G16B16A16_FLOAT:
+			return PF_FLOAT16_RGBA;
+		case DXGI_FORMAT_R16G16B16A16_UNORM:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R16G16B16A16_UINT:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R16G16B16A16_SNORM:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R16G16B16A16_SINT:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R32G32_TYPELESS:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R32G32_FLOAT:
+			return PF_FLOAT32_RG;
+		case DXGI_FORMAT_R32G32_UINT:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R32G32_SINT:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R32G8X24_TYPELESS:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+			return PF_D32_S8X24;
+		case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R10G10B10A2_UNORM:
+			return PF_UNORM_R10G10B10A2;
+		case DXGI_FORMAT_R10G10B10A2_UINT:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R11G11B10_FLOAT:
+			return PF_FLOAT_R11G11B10;
+		case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R8G8B8A8_UNORM:
+			return PF_R8G8B8A8;
+		case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R8G8B8A8_UINT:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R8G8B8A8_SNORM:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R8G8B8A8_SINT:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R16G16_TYPELESS:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R16G16_FLOAT:
+			return PF_FLOAT16_RG;
+		case DXGI_FORMAT_R16G16_UNORM:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R16G16_UINT:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R16G16_SNORM:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R16G16_SINT:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R32_TYPELESS:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_D32_FLOAT:
+			return PF_D32;
+		case DXGI_FORMAT_R32_FLOAT:
+			return PF_FLOAT32_R;
+		case DXGI_FORMAT_R32_UINT:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R32_SINT:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R24G8_TYPELESS:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_D24_UNORM_S8_UINT:
+			return PF_D24S8;
+		case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R8G8_TYPELESS:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R8G8_UNORM:
+			return PF_R8G8;
+		case DXGI_FORMAT_R8G8_UINT:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R8G8_SNORM:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R8G8_SINT:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R16_TYPELESS:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R16_FLOAT:
+			return PF_FLOAT16_R;
+		case DXGI_FORMAT_D16_UNORM:
+			return PF_D16;
+		case DXGI_FORMAT_R16_UNORM:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R16_UINT:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R16_SNORM:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R16_SINT:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R8_TYPELESS:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R8_UNORM:
+			return PF_R8;
+		case DXGI_FORMAT_R8_UINT:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R8_SNORM:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R8_SINT:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_A8_UNORM:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R1_UNORM:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_R8G8_B8G8_UNORM:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_G8R8_G8B8_UNORM:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_BC1_TYPELESS:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_BC1_UNORM:
+			return PF_BC1;
+		case DXGI_FORMAT_BC1_UNORM_SRGB:
+			return PF_BC1;
+		case DXGI_FORMAT_BC2_TYPELESS:
+			return PF_BC2;
+		case DXGI_FORMAT_BC2_UNORM:
+			return PF_BC2;
+		case DXGI_FORMAT_BC2_UNORM_SRGB:
+			return PF_BC2;
+		case DXGI_FORMAT_BC3_TYPELESS:
+			return PF_BC3;
+		case DXGI_FORMAT_BC3_UNORM:
+			return PF_BC3;
+		case DXGI_FORMAT_BC3_UNORM_SRGB:
+			return PF_BC3;
+		case DXGI_FORMAT_BC4_TYPELESS:
+			return PF_BC4;
+		case DXGI_FORMAT_BC4_UNORM:
+			return PF_BC4;
+		case DXGI_FORMAT_BC4_SNORM:
+			return PF_BC4;
+		case DXGI_FORMAT_BC5_TYPELESS:
+			return PF_BC5;
+		case DXGI_FORMAT_BC5_UNORM:
+			return PF_BC5;
+		case DXGI_FORMAT_BC5_SNORM:
+			return PF_BC5;
+		case DXGI_FORMAT_BC6H_UF16:
+			return PF_BC6H;
+		case DXGI_FORMAT_BC6H_SF16:
+			return PF_BC6H;
+		case DXGI_FORMAT_BC6H_TYPELESS:
+			return PF_BC6H;
+		case DXGI_FORMAT_BC7_UNORM:
+			return PF_BC7;
+		case DXGI_FORMAT_BC7_UNORM_SRGB:
+			return PF_BC7;
+		case DXGI_FORMAT_BC7_TYPELESS:
+			return PF_BC7;
+		case DXGI_FORMAT_B5G6R5_UNORM:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_B5G5R5A1_UNORM:
+			return PF_UNKNOWN;
+		case DXGI_FORMAT_B8G8R8A8_UNORM:
+			return PF_B8G8R8A8;
+		case DXGI_FORMAT_B8G8R8X8_UNORM:
+			return PF_B8G8R8X8;
+		default:
+			return PF_UNKNOWN;
+		}
+	}
+
+	DXGI_FORMAT D3D11Mappings::getPF(PixelFormat pf, bool gamma)
+	{
+		switch(pf)
+		{
+		case PF_R8:
+			return DXGI_FORMAT_R8_UNORM;
+		case PF_R8G8:
+			return DXGI_FORMAT_R8G8_UNORM; 
+		case PF_R8G8B8:
+			return DXGI_FORMAT_UNKNOWN;
+		case PF_A8R8G8B8:
+			return DXGI_FORMAT_UNKNOWN;
+		case PF_A8B8G8R8:
+			return DXGI_FORMAT_UNKNOWN;
+		case PF_X8R8G8B8:
+			return DXGI_FORMAT_UNKNOWN;
+		case PF_X8B8G8R8:
+			return DXGI_FORMAT_UNKNOWN;
+		case PF_R8G8B8A8:
+			return DXGI_FORMAT_R8G8B8A8_UNORM;
+		case PF_B8G8R8A8:
+			return DXGI_FORMAT_B8G8R8A8_UNORM;
+		case PF_B8G8R8X8:
+			return DXGI_FORMAT_B8G8R8X8_UNORM;
+		case PF_FLOAT16_R:
+			return DXGI_FORMAT_R16_FLOAT;
+		case PF_FLOAT16_RG:
+			return DXGI_FORMAT_R16G16_FLOAT;
+		case PF_FLOAT16_RGB:
+			return DXGI_FORMAT_UNKNOWN;
+		case PF_FLOAT16_RGBA:
+			return DXGI_FORMAT_R16G16B16A16_FLOAT;
+		case PF_FLOAT32_R:
+			return DXGI_FORMAT_R32_FLOAT;
+		case PF_FLOAT32_RG:
+			return DXGI_FORMAT_R32G32_FLOAT;
+		case PF_FLOAT32_RGB:
+			return DXGI_FORMAT_R32G32B32_FLOAT;
+		case PF_FLOAT32_RGBA:
+			return DXGI_FORMAT_R32G32B32A32_FLOAT;
+		case PF_BC1:
+		case PF_BC1a:
+			return DXGI_FORMAT_BC1_UNORM;
+		case PF_BC2:
+			return DXGI_FORMAT_BC2_UNORM;
+		case PF_BC3:
+			return DXGI_FORMAT_BC3_UNORM;
+		case PF_BC4:
+			return DXGI_FORMAT_BC4_UNORM;
+		case PF_BC5:
+			return DXGI_FORMAT_BC5_UNORM;
+		case PF_BC6H:
+			return DXGI_FORMAT_BC6H_UF16;
+		case PF_BC7:
+			if (gamma)
+				return DXGI_FORMAT_BC7_UNORM_SRGB;
+			else
+				return DXGI_FORMAT_BC7_UNORM;
+		case PF_D32_S8X24:
+			return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
+		case PF_D24S8:
+			return DXGI_FORMAT_D24_UNORM_S8_UINT;
+		case PF_D32:
+			return DXGI_FORMAT_D32_FLOAT;
+		case PF_D16:
+			return DXGI_FORMAT_D16_UNORM;
+		case PF_FLOAT_R11G11B10:
+			return DXGI_FORMAT_R11G11B10_FLOAT;
+		case PF_UNORM_R10G10B10A2:
+			return DXGI_FORMAT_R10G10B10A2_UNORM;
+		case PF_UNKNOWN:
+		default:
+			return DXGI_FORMAT_UNKNOWN;
+		}
+	}
+
+	DXGI_FORMAT D3D11Mappings::getTypelessDepthStencilPF(PixelFormat format)
+	{
+		switch(format)
+		{
+		case PF_D32_S8X24:
+			return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
+		case PF_D24S8:
+			return DXGI_FORMAT_R24G8_TYPELESS;
+		case PF_D32:
+			return DXGI_FORMAT_R32_TYPELESS;
+		case PF_D16:
+			return DXGI_FORMAT_R16_TYPELESS;
+		default:
+			return DXGI_FORMAT_UNKNOWN;
+		}
+	}
+
+	DXGI_FORMAT D3D11Mappings::getShaderResourceDepthStencilPF(PixelFormat format)
+	{
+		switch (format)
+		{
+		case PF_D32_S8X24:
+			return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
+		case PF_D24S8:
+			return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
+		case PF_D32:
+			return DXGI_FORMAT_R32_FLOAT;
+		case PF_D16:
+			return DXGI_FORMAT_R16_UNORM;
+		default:
+			return DXGI_FORMAT_UNKNOWN;
+		}
+	}
+
+	PixelFormat D3D11Mappings::getClosestSupportedPF(PixelFormat pf, bool hwGamma)
+	{
+		if (getPF(pf, hwGamma) != DXGI_FORMAT_UNKNOWN)
+		{
+			return pf;
+		}
+		switch(pf)
+		{
+		case PF_FLOAT16_RGB:
+			return PF_FLOAT16_RGBA;
+		case PF_R8G8B8:
+			return PF_R8G8B8A8;
+		case PF_B8G8R8:
+			return PF_R8G8B8A8;
+		case PF_A8R8G8B8:
+			return PF_R8G8B8A8;
+		case PF_A8B8G8R8:
+			return PF_B8G8R8A8;
+		case PF_X8R8G8B8:
+			return PF_R8G8B8A8;
+		case PF_X8B8G8R8:
+			return PF_B8G8R8X8;
+		case PF_R8G8B8X8:
+			return PF_B8G8R8X8;
+		case PF_UNKNOWN:
+		default:
+			return PF_R8G8B8A8;
+		}
+	}
+
+	D3D11_USAGE D3D11Mappings::getUsage(GpuBufferUsage usage)
+	{
+		if (isDynamic(usage))
+			return D3D11_USAGE_DYNAMIC;
+		else
+			return D3D11_USAGE_DEFAULT;
+	}
+
+	bool D3D11Mappings::isDynamic(GpuBufferUsage usage)
+	{
+		switch (usage)
+		{
+		case GBU_DYNAMIC:
+			return true;
+		}
+
+		return false;
+	}
+
+	bool D3D11Mappings::isMappingWrite(D3D11_MAP map)
+	{
+		if(map == D3D11_MAP_READ)
+			return false;
+
+		return true;
+	}
+
+	bool D3D11Mappings::isMappingRead(D3D11_MAP map)
+	{
+		if(map == D3D11_MAP_READ || map == D3D11_MAP_READ_WRITE)
+			return true;
+
+		return false;
+	}
+
+	UINT D3D11Mappings::getAccessFlags(GpuBufferUsage usage)
+	{
+		if(isDynamic(usage))
+			return D3D11_CPU_ACCESS_WRITE;
+		else
+			return 0;
+	}
+
+	D3D11_PRIMITIVE_TOPOLOGY D3D11Mappings::getPrimitiveType(DrawOperationType type)
+	{
+		switch(type)
+		{
+		case DOT_POINT_LIST:
+			return D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
+		case DOT_LINE_LIST:
+			return D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
+		case DOT_LINE_STRIP:
+			return D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP;
+		case DOT_TRIANGLE_LIST:
+			return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
+		case DOT_TRIANGLE_STRIP:
+			return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
+		case DOT_TRIANGLE_FAN:
+			BS_EXCEPT(InvalidParametersException, "D3D11 doesn't support triangle fan primitive type.");
+		}
+
+		return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
+	}
+
+	UINT32 D3D11Mappings::getSizeInBytes(PixelFormat pf, UINT32 width, UINT32 height)
+	{
+		if(width == 0 || height == 0)
+			return 0;
+
+		if(PixelUtil::isCompressed(pf))
+		{
+			// D3D wants the width of one row of cells in bytes
+			if (pf == PF_BC1 || pf == PF_BC4)
+			{
+				// 64 bits (8 bytes) per 4x4 block
+				return std::max<UINT32>(1, width / 4) * std::max<UINT32>(1, height / 4) * 8;
+			}
+			else
+			{
+				// 128 bits (16 bytes) per 4x4 block
+				return std::max<UINT32>(1, width / 4) * std::max<UINT32>(1, height / 4) * 16;
+			}
+		}
+		else
+		{
+			return width * height * PixelUtil::getNumElemBytes(pf);
+		}
+	}
+
+	D3D11_MAP D3D11Mappings::getLockOptions(GpuLockOptions lockOptions)
+	{
+		switch(lockOptions)
+		{
+		case GBL_WRITE_ONLY_NO_OVERWRITE:
+			return D3D11_MAP_WRITE_NO_OVERWRITE;
+			break;
+		case GBL_READ_WRITE:
+			return D3D11_MAP_READ_WRITE;
+			break;
+		case GBL_WRITE_ONLY_DISCARD:
+			return D3D11_MAP_WRITE_DISCARD;
+			break;
+		case GBL_READ_ONLY:
+			return D3D11_MAP_READ;
+			break;
+		case GBL_WRITE_ONLY:
+			return D3D11_MAP_WRITE;
+			break;
+		default: 
+			break;
+		};
+
+		BS_EXCEPT(RenderingAPIException, "Invalid lock option. No DX11 equivalent of: " + toString(lockOptions));
+	}
 }

+ 51 - 44
BansheeD3D11RenderAPI/Source/BsD3D11MultiRenderTexture.cpp

@@ -1,45 +1,52 @@
-#include "BsD3D11MultiRenderTexture.h"
-#include "BsD3D11Texture.h"
-#include "BsD3D11RenderTexture.h"
-#include "BsD3D11TextureView.h"
-
-namespace BansheeEngine
-{
-	D3D11MultiRenderTextureCore::D3D11MultiRenderTextureCore(const MULTI_RENDER_TEXTURE_CORE_DESC& desc)
-		:MultiRenderTextureCore(desc), mProperties(desc)
-	{
-
-	}
-
-	D3D11MultiRenderTextureCore::~D3D11MultiRenderTextureCore()
-	{
-
-	}
-
-	void D3D11MultiRenderTextureCore::getCustomAttribute(const String& name, void* pData) const
-	{
-		if(name == "RTV")
-		{
-			ID3D11RenderTargetView** rtvs = (ID3D11RenderTargetView **)pData;
-			for(UINT32 i = 0; i < (UINT32)mColorSurfaces.size(); ++i)		
-			{
-				if (mColorSurfaces[i] == nullptr)
-					continue;
-
-				D3D11TextureView* textureView = static_cast<D3D11TextureView*>(mColorSurfaces[i].get());
-				rtvs[i] = textureView->getRTV();	
-			}
-		}
-		else if(name == "DSV")
-		{
-			ID3D11DepthStencilView** dsv = (ID3D11DepthStencilView **)pData;
-
-			D3D11TextureView* depthStencilView = static_cast<D3D11TextureView*>(mDepthStencilSurface.get());
-			*dsv = depthStencilView->getDSV();
-		}
-	}
-
-	D3D11MultiRenderTexture::D3D11MultiRenderTexture(const MULTI_RENDER_TEXTURE_DESC& desc)
-		:MultiRenderTexture(desc), mProperties(desc)
-	{ }
+#include "BsD3D11MultiRenderTexture.h"
+#include "BsD3D11Texture.h"
+#include "BsD3D11RenderTexture.h"
+#include "BsD3D11TextureView.h"
+
+namespace BansheeEngine
+{
+	D3D11MultiRenderTextureCore::D3D11MultiRenderTextureCore(const MULTI_RENDER_TEXTURE_CORE_DESC& desc)
+		:MultiRenderTextureCore(desc), mProperties(desc)
+	{
+
+	}
+
+	D3D11MultiRenderTextureCore::~D3D11MultiRenderTextureCore()
+	{
+
+	}
+
+	void D3D11MultiRenderTextureCore::getCustomAttribute(const String& name, void* pData) const
+	{
+		if(name == "RTV")
+		{
+			ID3D11RenderTargetView** rtvs = (ID3D11RenderTargetView **)pData;
+			for(UINT32 i = 0; i < (UINT32)mColorSurfaces.size(); ++i)		
+			{
+				if (mColorSurfaces[i] == nullptr)
+					continue;
+
+				D3D11TextureView* textureView = static_cast<D3D11TextureView*>(mColorSurfaces[i].get());
+				rtvs[i] = textureView->getRTV();	
+			}
+		}
+		else if(name == "DSV")
+		{
+			ID3D11DepthStencilView** dsv = (ID3D11DepthStencilView **)pData;
+
+			D3D11TextureView* depthStencilView = static_cast<D3D11TextureView*>(mDepthStencilSurface.get());
+			*dsv = depthStencilView->getDSV(false);
+		}
+		else if (name == "RODSV")
+		{
+			ID3D11DepthStencilView** dsv = (ID3D11DepthStencilView **)pData;
+
+			D3D11TextureView* depthStencilView = static_cast<D3D11TextureView*>(mDepthStencilSurface.get());
+			*dsv = depthStencilView->getDSV(true);
+		}
+	}
+
+	D3D11MultiRenderTexture::D3D11MultiRenderTexture(const MULTI_RENDER_TEXTURE_DESC& desc)
+		:MultiRenderTexture(desc), mProperties(desc)
+	{ }
 }

+ 6 - 2
BansheeD3D11RenderAPI/Source/BsD3D11RenderAPI.cpp

@@ -740,7 +740,7 @@ namespace BansheeEngine
 		BS_INC_RENDER_STAT(NumClears);
 	}
 
-	void D3D11RenderAPI::setRenderTarget(const SPtr<RenderTargetCore>& target)
+	void D3D11RenderAPI::setRenderTarget(const SPtr<RenderTargetCore>& target, bool readOnlyDepthStencil)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
@@ -755,7 +755,11 @@ namespace BansheeEngine
 		if (target != nullptr)
 		{
 			target->getCustomAttribute("RTV", views);
-			target->getCustomAttribute("DSV", &depthStencilView);
+
+			if(readOnlyDepthStencil)
+				target->getCustomAttribute("RODSV", &depthStencilView);
+			else
+				target->getCustomAttribute("DSV", &depthStencilView);
 		}
 
 		// Bind render targets

+ 42 - 41
BansheeD3D11RenderAPI/Source/BsD3D11RenderTexture.cpp

@@ -1,42 +1,43 @@
-#include "BsD3D11RenderTexture.h"
-#include "BsD3D11RenderAPI.h"
-#include "BsD3D11Device.h"
-#include "BsD3D11Texture.h"
-#include "BsD3D11Mappings.h"
-#include "BsD3D11TextureView.h"
-#include "BsTextureManager.h"
-#include "BsException.h"
-
-namespace BansheeEngine
-{
-	D3D11RenderTextureCore::D3D11RenderTextureCore(const RENDER_TEXTURE_CORE_DESC& desc)
-		:RenderTextureCore(desc), mProperties(desc, false)
-	{ 
-
-	}
-
-	void D3D11RenderTextureCore::getCustomAttribute(const String& name, void* pData) const
-	{
-		if(name == "RTV")
-		{
-			ID3D11RenderTargetView** pRTVs = (ID3D11RenderTargetView **)pData;			
-			D3D11TextureView* textureView = static_cast<D3D11TextureView*>(mColorSurface.get());
-			*pRTVs = textureView->getRTV();		
-
-			return;
-		}
-		else if(name == "DSV")
-		{
-			ID3D11DepthStencilView** pDSV = (ID3D11DepthStencilView **)pData;
-			D3D11TextureView* depthStencilView = static_cast<D3D11TextureView*>(mDepthStencilSurface.get());
-			*pDSV = depthStencilView->getDSV();
-			return;
-		}
-	}
-
-	D3D11RenderTexture::D3D11RenderTexture(const RENDER_TEXTURE_DESC& desc)
-		:RenderTexture(desc), mProperties(desc, false)
-	{ 
-
-	}
+#include "BsD3D11RenderTexture.h"
+#include "BsD3D11TextureView.h"
+
+namespace BansheeEngine
+{
+	D3D11RenderTextureCore::D3D11RenderTextureCore(const RENDER_TEXTURE_CORE_DESC& desc)
+		:RenderTextureCore(desc), mProperties(desc, false)
+	{ 
+
+	}
+
+	void D3D11RenderTextureCore::getCustomAttribute(const String& name, void* pData) const
+	{
+		if(name == "RTV")
+		{
+			ID3D11RenderTargetView** pRTVs = (ID3D11RenderTargetView **)pData;			
+			D3D11TextureView* textureView = static_cast<D3D11TextureView*>(mColorSurface.get());
+			*pRTVs = textureView->getRTV();		
+
+			return;
+		}
+		else if(name == "DSV")
+		{
+			ID3D11DepthStencilView** pDSV = (ID3D11DepthStencilView **)pData;
+			D3D11TextureView* depthStencilView = static_cast<D3D11TextureView*>(mDepthStencilSurface.get());
+			*pDSV = depthStencilView->getDSV(false);
+			return;
+		}
+		else if (name == "RODSV")
+		{
+			ID3D11DepthStencilView** pDSV = (ID3D11DepthStencilView **)pData;
+			D3D11TextureView* depthStencilView = static_cast<D3D11TextureView*>(mDepthStencilSurface.get());
+			*pDSV = depthStencilView->getDSV(true);
+			return;
+		}
+	}
+
+	D3D11RenderTexture::D3D11RenderTexture(const RENDER_TEXTURE_DESC& desc)
+		:RenderTexture(desc), mProperties(desc, false)
+	{ 
+
+	}
 }

+ 15 - 4
BansheeD3D11RenderAPI/Source/BsD3D11RenderWindow.cpp

@@ -46,10 +46,7 @@ namespace BansheeEngine
 		}
 
 		if (mDepthStencilView != nullptr)
-		{
 			TextureCore::releaseView(mDepthStencilView);
-			mDepthStencilView = nullptr;
-		}
 
 		destroySizeDependedD3DResources();
 	}
@@ -425,7 +422,21 @@ namespace BansheeEngine
 			if (mDepthStencilView != nullptr)
 			{
 				D3D11TextureView* d3d11TextureView = static_cast<D3D11TextureView*>(mDepthStencilView.get());
-				*static_cast<ID3D11DepthStencilView**>(pData) = d3d11TextureView->getDSV();
+				*static_cast<ID3D11DepthStencilView**>(pData) = d3d11TextureView->getDSV(false);
+			}
+			else
+			{
+				*static_cast<ID3D11DepthStencilView**>(pData) = nullptr;
+			}
+
+			return;
+		}
+		else if (name == "RODSV")
+		{
+			if (mDepthStencilView != nullptr)
+			{
+				D3D11TextureView* d3d11TextureView = static_cast<D3D11TextureView*>(mDepthStencilView.get());
+				*static_cast<ID3D11DepthStencilView**>(pData) = d3d11TextureView->getDSV(true);
 			}
 			else
 			{

+ 793 - 749
BansheeD3D11RenderAPI/Source/BsD3D11Texture.cpp

@@ -1,750 +1,794 @@
-#include "BsD3D11Texture.h"
-#include "BsD3D11Mappings.h"
-#include "BsD3D11Device.h"
-#include "BsD3D11RenderAPI.h"
-#include "BsD3D11TextureView.h"
-#include "BsCoreThread.h"
-#include "BsException.h"
-#include "BsAsyncOp.h"
-#include "BsRenderStats.h"
-#include "BsDebug.h"
-
-namespace BansheeEngine
-{
-	D3D11TextureCore::D3D11TextureCore(TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps,
-		PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount, const PixelDataPtr& initialData)
-		: TextureCore(textureType, width, height, depth, numMipmaps, format, usage, hwGamma, multisampleCount, initialData),
-		m1DTex(nullptr), m2DTex(nullptr), m3DTex(nullptr), 
-		mTex(nullptr), mShaderResourceView(nullptr), mStagingBuffer(nullptr), 
-		mLockedSubresourceIdx(-1), mLockedForReading(false), mStaticBuffer(nullptr)
-	{ }
-
-	D3D11TextureCore::~D3D11TextureCore()
-	{ 
-		SAFE_RELEASE(mTex);
-		SAFE_RELEASE(mShaderResourceView);
-		SAFE_RELEASE(m1DTex);
-		SAFE_RELEASE(m2DTex);
-		SAFE_RELEASE(m3DTex);
-		SAFE_RELEASE(mStagingBuffer);
-
-		BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_Texture);
-	}
-
-	void D3D11TextureCore::initialize()
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		switch (mProperties.getTextureType())
-		{
-		case TEX_TYPE_1D:
-			create1DTex();
-			break;
-		case TEX_TYPE_2D:
-		case TEX_TYPE_CUBE_MAP:
-			create2DTex();
-			break;
-		case TEX_TYPE_3D:
-			create3DTex();
-			break;
-		default:
-			BS_EXCEPT(RenderingAPIException, "Unknown texture type");
-		}
-
-		BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_Texture);
-		TextureCore::initialize();
-	}
-
-	void D3D11TextureCore::copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 destFace, UINT32 destMipLevel, const SPtr<TextureCore>& target)
-	{
-		D3D11TextureCore* other = static_cast<D3D11TextureCore*>(target.get());
-
-		UINT32 srcResIdx = D3D11CalcSubresource(srcMipLevel, srcFace, mProperties.getNumMipmaps() + 1);
-		UINT32 destResIdx = D3D11CalcSubresource(destMipLevel, destFace, target->getProperties().getNumMipmaps() + 1);
-
-		D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr());
-		D3D11Device& device = rs->getPrimaryDevice();
-
-		bool srcHasMultisample = mProperties.getMultisampleCount() > 1;
-		bool destHasMultisample = target->getProperties().getMultisampleCount() > 1;
-
-		if (srcHasMultisample && destHasMultisample && mProperties.getMultisampleCount() != target->getProperties().getMultisampleCount()) // Resolving from MS to non-MS texture
-		{
-			device.getImmediateContext()->ResolveSubresource(other->getDX11Resource(), destResIdx, mTex, srcResIdx, mDXGIFormat);
-		}
-		else
-		{
-			device.getImmediateContext()->CopySubresourceRegion(other->getDX11Resource(), destResIdx, 0, 0, 0, mTex, srcResIdx, nullptr);
-
-			if (device.hasError())
-			{
-				String errorDescription = device.getErrorDescription();
-				BS_EXCEPT(RenderingAPIException, "D3D11 device cannot copy subresource\nError Description:" + errorDescription);
-			}
-		}
-	}
-
-	PixelData D3D11TextureCore::lockImpl(GpuLockOptions options, UINT32 mipLevel, UINT32 face)
-	{
-		if (mProperties.getMultisampleCount() > 1)
-			BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
-
-#if BS_PROFILING_ENABLED
-		if (options == GBL_READ_ONLY || options == GBL_READ_WRITE)
-		{
-			BS_INC_RENDER_STAT_CAT(ResRead, RenderStatObject_Texture);
-		}
-
-		if (options == GBL_READ_WRITE || options == GBL_WRITE_ONLY || options == GBL_WRITE_ONLY_DISCARD || options == GBL_WRITE_ONLY_NO_OVERWRITE)
-		{
-			BS_INC_RENDER_STAT_CAT(ResWrite, RenderStatObject_Texture);
-		}
-#endif
-
-		UINT32 mipWidth = mProperties.getWidth() >> mipLevel;
-		UINT32 mipHeight = mProperties.getHeight() >> mipLevel;
-		UINT32 mipDepth = mProperties.getDepth() >> mipLevel;
-
-		PixelData lockedArea(mipWidth, mipHeight, mipDepth, mProperties.getFormat());
-
-		D3D11_MAP flags = D3D11Mappings::getLockOptions(options);
-
-		UINT32 rowPitch, slicePitch;
-
-		if(flags == D3D11_MAP_READ || flags == D3D11_MAP_READ_WRITE)
-		{
-			UINT8* data = (UINT8*)mapstagingbuffer(flags, face, mipLevel, rowPitch, slicePitch);
-			lockedArea.setExternalBuffer(data);
-			lockedArea.setRowPitch(rowPitch);
-			lockedArea.setSlicePitch(slicePitch);
-			mLockedForReading = true;
-		}
-		else
-		{
-			if (mProperties.getUsage() == TU_DYNAMIC)
-			{
-				UINT8* data = (UINT8*)map(mTex, flags, face, mipLevel, rowPitch, slicePitch);
-				lockedArea.setExternalBuffer(data);
-				lockedArea.setRowPitch(rowPitch);
-				lockedArea.setSlicePitch(slicePitch);
-			}
-			else
-				lockedArea.setExternalBuffer((UINT8*)mapstaticbuffer(lockedArea, mipLevel, face));
-
-			mLockedForReading = false;
-		}
-
-		return lockedArea;
-	}
-
-	void D3D11TextureCore::unlockImpl()
-	{
-		if(mLockedForReading)
-			unmapstagingbuffer();
-		else
-		{
-			if (mProperties.getUsage() == TU_DYNAMIC)
-				unmap(mTex);
-			else
-				unmapstaticbuffer();
-		}
-	}
-
-	void D3D11TextureCore::readData(PixelData& dest, UINT32 mipLevel, UINT32 face)
-	{
-		if (mProperties.getMultisampleCount() > 1)
-			BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
-
-		PixelData myData = lock(GBL_READ_ONLY, mipLevel, face);
-
-#if BS_DEBUG_MODE
-		if(dest.getConsecutiveSize() != myData.getConsecutiveSize())
-		{
-			unlock();
-			BS_EXCEPT(InternalErrorException, "Buffer sizes don't match");
-		}
-#endif
-
-		PixelUtil::bulkPixelConversion(myData, dest);
-
-		unlock();
-	}
-
-	void D3D11TextureCore::writeData(const PixelData& src, UINT32 mipLevel, UINT32 face, bool discardWholeBuffer)
-	{
-		PixelFormat format = mProperties.getFormat();
-
-		if (mProperties.getMultisampleCount() > 1)
-			BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
-
-		if ((mProperties.getUsage() & TU_DYNAMIC) != 0)
-		{
-			PixelData myData = lock(discardWholeBuffer ? GBL_WRITE_ONLY_DISCARD : GBL_WRITE_ONLY, mipLevel, face);
-			PixelUtil::bulkPixelConversion(src, myData);
-			unlock();
-		}
-		else if ((mProperties.getUsage() & TU_DEPTHSTENCIL) == 0)
-		{
-			mipLevel = Math::clamp(mipLevel, (UINT32)mipLevel, mProperties.getNumMipmaps());
-			face = Math::clamp(face, (UINT32)0, mProperties.getDepth() - 1);
-
-			if(mProperties.getTextureType() == TEX_TYPE_3D)
-				face = 0;
-
-			D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr());
-			D3D11Device& device = rs->getPrimaryDevice();
-
-			UINT subresourceIdx = D3D11CalcSubresource(mipLevel, face, mProperties.getNumMipmaps() + 1);
-			UINT32 rowWidth = D3D11Mappings::getSizeInBytes(format, src.getWidth());
-			UINT32 sliceWidth = D3D11Mappings::getSizeInBytes(format, src.getWidth(), src.getHeight());
-
-			device.getImmediateContext()->UpdateSubresource(mTex, subresourceIdx, nullptr, src.getData(), rowWidth, sliceWidth);
-
-			if (device.hasError())
-			{
-				String errorDescription = device.getErrorDescription();
-				BS_EXCEPT(RenderingAPIException, "D3D11 device cannot map texture\nError Description:" + errorDescription);
-			}
-
-			BS_INC_RENDER_STAT_CAT(ResWrite, RenderStatObject_Texture);
-		}
-		else
-		{
-			BS_EXCEPT(RenderingAPIException, "Trying to write into a buffer with unsupported usage: " + toString(mProperties.getUsage()));
-		}
-	}
-
-	void D3D11TextureCore::create1DTex()
-	{
-		UINT32 width = mProperties.getWidth();
-		int usage = mProperties.getUsage();
-		UINT32 numMips = mProperties.getNumMipmaps();
-		PixelFormat format = mProperties.getFormat();
-		bool hwGamma = mProperties.isHardwareGammaEnabled();
-		TextureType texType = mProperties.getTextureType();
-
-		// We must have those defined here
-		assert(width > 0);
-
-		// Determine which D3D11 pixel format we'll use
-		HRESULT hr;
-		DXGI_FORMAT d3dPF = D3D11Mappings::getPF(D3D11Mappings::getClosestSupportedPF(format, hwGamma), hwGamma);
-
-		if (format != D3D11Mappings::getPF(d3dPF))
-		{
-			BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(format));
-		}
-
-		D3D11_TEXTURE1D_DESC desc;
-		desc.Width = static_cast<UINT32>(width);
-		desc.ArraySize		= 1;
-		desc.Format			= d3dPF;
-		desc.MiscFlags		= 0;
-
-		if((usage & TU_RENDERTARGET) != 0)
-		{
-			desc.Usage			= D3D11_USAGE_DEFAULT;
-			desc.BindFlags		= D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
-			desc.CPUAccessFlags = 0;
-			desc.MipLevels		= 1;
-		}
-		else if ((usage & TU_DEPTHSTENCIL) != 0)
-		{
-			desc.Usage			= D3D11_USAGE_DEFAULT;
-			desc.BindFlags		= D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
-			desc.CPUAccessFlags = 0;
-			desc.MipLevels		= 1;
-		}
-		else
-		{
-			desc.Usage			= D3D11Mappings::getUsage((GpuBufferUsage)usage);
-			desc.BindFlags		= D3D11_BIND_SHADER_RESOURCE;
-			desc.CPUAccessFlags = D3D11Mappings::getAccessFlags((GpuBufferUsage)usage);
-
-			// Determine total number of mipmaps including main one (d3d11 convention)
-			desc.MipLevels = (numMips == MIP_UNLIMITED || (1U << numMips) > width) ? 0 : numMips + 1;
-		}
-
-		if ((usage & TU_LOADSTORE) != 0)
-			desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
-
-		// Create the texture
-		D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr());
-		D3D11Device& device = rs->getPrimaryDevice();
-		hr = device.getD3D11Device()->CreateTexture1D(&desc, nullptr, &m1DTex);
-
-		// Check result and except if failed
-		if (FAILED(hr) || device.hasError())
-		{
-			String errorDescription = device.getErrorDescription();
-			BS_EXCEPT(RenderingAPIException, "Error creating texture\nError Description:" + errorDescription);
-		}
-
-		hr = m1DTex->QueryInterface(__uuidof(ID3D11Resource), (void **)&mTex);
-
-		if(FAILED(hr) || device.hasError())
-		{
-			String errorDescription = device.getErrorDescription();
-			BS_EXCEPT(RenderingAPIException, "Can't get base texture\nError Description:" + errorDescription);
-		}
-
-		m1DTex->GetDesc(&desc);
-
-		if(numMips != (desc.MipLevels - 1))
-		{
-			BS_EXCEPT(RenderingAPIException, "Driver returned different number of mip maps than requested. " \
-				"Requested: " + toString(numMips) + ". Got: " + toString(desc.MipLevels - 1) + ".");
-		}
-
-		mDXGIFormat = desc.Format;
-		mDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
-
-		// Create texture view
-		if ((usage & TU_DEPTHSTENCIL) == 0)
-		{
-			ZeroMemory(&mSRVDesc, sizeof(mSRVDesc));
-			mSRVDesc.Format = desc.Format;
-			mSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D; 
-			mSRVDesc.Texture1D.MipLevels = desc.MipLevels;
-			hr = device.getD3D11Device()->CreateShaderResourceView(m1DTex, &mSRVDesc, &mShaderResourceView);
-
-			if (FAILED(hr) || device.hasError())
-			{
-				String errorDescription = device.getErrorDescription();
-				BS_EXCEPT(RenderingAPIException, "D3D11 device can't create shader resource view.\nError Description:" + errorDescription);
-			}
-		}
-	}
-
-	void D3D11TextureCore::create2DTex()
-	{
-		UINT32 width = mProperties.getWidth();
-		UINT32 height = mProperties.getHeight();
-		int usage = mProperties.getUsage();
-		UINT32 numMips = mProperties.getNumMipmaps();
-		PixelFormat format = mProperties.getFormat();
-		bool hwGamma = mProperties.isHardwareGammaEnabled();
-		UINT32 sampleCount = mProperties.getMultisampleCount();
-		TextureType texType = mProperties.getTextureType();
-
-		// We must have those defined here
-		assert(width > 0 || height > 0);
-
-		// Determine which D3D11 pixel format we'll use
-		HRESULT hr;
-		DXGI_FORMAT d3dPF = D3D11Mappings::getPF(D3D11Mappings::getClosestSupportedPF(format, hwGamma), hwGamma);
-
-		if (format != D3D11Mappings::getPF(d3dPF))
-		{
-			BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(format));
-		}
-
-		D3D11_TEXTURE2D_DESC desc;
-		desc.Width			= static_cast<UINT32>(width);
-		desc.Height			= static_cast<UINT32>(height);
-		desc.ArraySize		= 1;
-		desc.Format			= d3dPF;
-		desc.MiscFlags		= 0;
-
-		if((usage & TU_RENDERTARGET) != 0)
-		{
-			desc.Usage			= D3D11_USAGE_DEFAULT;
-			desc.BindFlags		= D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
-			desc.CPUAccessFlags = 0;
-			desc.MipLevels		= 1;
-
-			DXGI_SAMPLE_DESC sampleDesc;
-			D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr());
-			rs->determineMultisampleSettings(sampleCount, d3dPF, &sampleDesc);
-			desc.SampleDesc		= sampleDesc;
-
-			if (texType == TEX_TYPE_CUBE_MAP)
-			{
-				BS_EXCEPT(NotImplementedException, "Cube map not yet supported as a render target."); // TODO: Will be once I add proper texture array support
-			}
-		}
-		else if((usage & TU_DEPTHSTENCIL) != 0)
-		{
-			desc.Usage			= D3D11_USAGE_DEFAULT;
-			desc.BindFlags		= D3D11_BIND_DEPTH_STENCIL;
-			desc.CPUAccessFlags = 0;
-			desc.MipLevels		= 1;
-
-			DXGI_SAMPLE_DESC sampleDesc;
-			D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr());
-			rs->determineMultisampleSettings(sampleCount, d3dPF, &sampleDesc);
-			desc.SampleDesc		= sampleDesc;
-
-			if (texType == TEX_TYPE_CUBE_MAP)
-			{
-				BS_EXCEPT(NotImplementedException, "Cube map not yet supported as a depth stencil target."); // TODO: Will be once I add proper texture array support
-			}
-		}
-		else
-		{
-			desc.Usage = D3D11Mappings::getUsage((GpuBufferUsage)usage);
-			desc.BindFlags		= D3D11_BIND_SHADER_RESOURCE;
-			desc.CPUAccessFlags = D3D11Mappings::getAccessFlags((GpuBufferUsage)usage);
-
-			// Determine total number of mipmaps including main one (d3d11 convention)
-			desc.MipLevels		= (numMips == MIP_UNLIMITED || (1U << numMips) > width) ? 0 : numMips + 1;
-
-			DXGI_SAMPLE_DESC sampleDesc;
-			sampleDesc.Count	= 1;
-			sampleDesc.Quality	= 0;
-			desc.SampleDesc		= sampleDesc;
-		}
-
-		if (texType == TEX_TYPE_CUBE_MAP)
-        {
-            desc.MiscFlags      |= D3D11_RESOURCE_MISC_TEXTURECUBE;
-            desc.ArraySize       = 6;
-        }
-
-		if ((usage & TU_LOADSTORE) != 0)
-			desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
-
-		// Create the texture
-		D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr());
-		D3D11Device& device = rs->getPrimaryDevice();
-		hr = device.getD3D11Device()->CreateTexture2D(&desc, nullptr, &m2DTex);
-
-		// Check result and except if failed
-		if (FAILED(hr) || device.hasError())
-		{
-			String errorDescription = device.getErrorDescription();
-			BS_EXCEPT(RenderingAPIException, "Error creating texture\nError Description:" + errorDescription);
-		}
-
-		hr = m2DTex->QueryInterface(__uuidof(ID3D11Resource), (void **)&mTex);
-
-		if(FAILED(hr) || device.hasError())
-		{
-			String errorDescription = device.getErrorDescription();
-			BS_EXCEPT(RenderingAPIException, "Can't get base texture\nError Description:" + errorDescription);
-		}
-
-		m2DTex->GetDesc(&desc);
-
-		if(numMips != (desc.MipLevels - 1))
-		{
-			BS_EXCEPT(RenderingAPIException, "Driver returned different number of mip maps than requested. " \
-				"Requested: " + toString(numMips) + ". Got: " + toString(desc.MipLevels - 1) + ".");
-		}
-
-		mDXGIFormat = desc.Format;
-
-		// Create shader texture view
-		if((usage & TU_DEPTHSTENCIL) == 0)
-		{
-			ZeroMemory(&mSRVDesc, sizeof(mSRVDesc));
-			mSRVDesc.Format = desc.Format;
-
-			if((usage & TU_RENDERTARGET) != 0)
-			{
-				if (sampleCount > 1)
-				{
-					mSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
-					mSRVDesc.Texture2D.MostDetailedMip = 0;
-					mSRVDesc.Texture2D.MipLevels = desc.MipLevels;
-				}
-				else
-				{
-					mSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
-					mSRVDesc.Texture2D.MostDetailedMip = 0;
-					mSRVDesc.Texture2D.MipLevels = desc.MipLevels;
-				}
-			}
-			else
-			{
-				switch (texType)
-				{
-				case TEX_TYPE_CUBE_MAP:
-					mSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
-					mSRVDesc.TextureCube.MipLevels = desc.MipLevels;
-					mSRVDesc.TextureCube.MostDetailedMip = 0;
-					break;
-
-				case TEX_TYPE_2D:
-					mSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
-					mSRVDesc.Texture2D.MostDetailedMip = 0;
-					mSRVDesc.Texture2D.MipLevels = desc.MipLevels;
-					break;
-				}
-			}
-
-			mDimension = mSRVDesc.ViewDimension;
-			hr = device.getD3D11Device()->CreateShaderResourceView(m2DTex, &mSRVDesc, &mShaderResourceView);
-
-			if (FAILED(hr) || device.hasError())
-			{
-				String errorDescription = device.getErrorDescription();
-				BS_EXCEPT(RenderingAPIException, "D3D11 device can't create shader resource view.\nError Description:" + errorDescription);
-			}
-		}
-		else
-		{
-			if (sampleCount > 1)
-				mDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
-			else
-				mDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
-		}
-	}
-
-	void D3D11TextureCore::create3DTex()
-	{
-		UINT32 width = mProperties.getWidth();
-		UINT32 height = mProperties.getHeight();
-		UINT32 depth = mProperties.getDepth();
-		int usage = mProperties.getUsage();
-		UINT32 numMips = mProperties.getNumMipmaps();
-		PixelFormat format = mProperties.getFormat();
-		bool hwGamma = mProperties.isHardwareGammaEnabled();
-
-		// We must have those defined here
-		assert(width > 0 && height > 0 && depth > 0);
-
-		// Determine which D3D11 pixel format we'll use
-		HRESULT hr;
-		DXGI_FORMAT d3dPF = D3D11Mappings::getPF(
-			D3D11Mappings::getClosestSupportedPF(format, hwGamma), hwGamma);
-		
-		if (format != D3D11Mappings::getPF(d3dPF))
-		{
-			BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(format));
-		}
-
-		D3D11_TEXTURE3D_DESC desc;
-		desc.Width = static_cast<UINT32>(width);
-		desc.Height = static_cast<UINT32>(height);
-		desc.Depth = static_cast<UINT32>(depth);
-		desc.Format			= d3dPF;
-		desc.MiscFlags		= 0;
-
-		if ((mProperties.getUsage() & TU_RENDERTARGET) != 0)
-		{
-			desc.Usage			= D3D11_USAGE_DEFAULT;
-			desc.BindFlags		= D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
-			desc.CPUAccessFlags = 0;
-			desc.MipLevels		= 1;
-		}
-		else if ((mProperties.getUsage() & TU_DEPTHSTENCIL) != 0)
-		{
-			desc.Usage			= D3D11_USAGE_DEFAULT;
-			desc.BindFlags		= D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
-			desc.CPUAccessFlags = 0;
-			desc.MipLevels		= 1;
-		}
-		else
-		{
-			desc.Usage			= D3D11Mappings::getUsage((GpuBufferUsage)usage);
-			desc.BindFlags		= D3D11_BIND_SHADER_RESOURCE;
-			desc.CPUAccessFlags = D3D11Mappings::getAccessFlags((GpuBufferUsage)usage);
-
-			// Determine total number of mipmaps including main one (d3d11 convention)
-			desc.MipLevels		= (numMips == MIP_UNLIMITED || (1U << numMips)
-				> std::max(std::max(width, height), depth)) ? 0 : numMips + 1;
-		}
-
-		if ((usage & TU_LOADSTORE) != 0)
-			desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
-
-		// Create the texture
-		D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr());
-		D3D11Device& device = rs->getPrimaryDevice();
-		hr = device.getD3D11Device()->CreateTexture3D(&desc, nullptr, &m3DTex);
-
-		// Check result and except if failed
-		if (FAILED(hr) || device.hasError())
-		{
-			String errorDescription = device.getErrorDescription();
-			BS_EXCEPT(RenderingAPIException, "Error creating texture\nError Description:" + errorDescription);
-		}
-
-		hr = m3DTex->QueryInterface(__uuidof(ID3D11Resource), (void **)&mTex);
-
-		if(FAILED(hr) || device.hasError())
-		{
-			String errorDescription = device.getErrorDescription();
-			BS_EXCEPT(RenderingAPIException, "Can't get base texture\nError Description:" + errorDescription);
-		}
-
-		// Create texture view
-		m3DTex->GetDesc(&desc);
-
-		if (mProperties.getNumMipmaps() != (desc.MipLevels - 1))
-		{
-			BS_EXCEPT(RenderingAPIException, "Driver returned different number of mip maps than requested. " \
-				"Requested: " + toString(mProperties.getNumMipmaps()) + ". Got: " + toString(desc.MipLevels - 1) + ".");
-		}
-
-		mDXGIFormat = desc.Format;
-		mDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
-
-		if ((usage & TU_DEPTHSTENCIL) == 0)
-		{
-			ZeroMemory(&mSRVDesc, sizeof(mSRVDesc));
-			mSRVDesc.Format = desc.Format;
-			mSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
-			mSRVDesc.Texture3D.MostDetailedMip = 0;
-			mSRVDesc.Texture3D.MipLevels = desc.MipLevels;
-
-			hr = device.getD3D11Device()->CreateShaderResourceView(m2DTex, &mSRVDesc, &mShaderResourceView);
-
-			if (FAILED(hr) || device.hasError())
-			{
-				String errorDescription = device.getErrorDescription();
-				BS_EXCEPT(RenderingAPIException, "D3D11 device can't create shader resource view.\nError Description:" + errorDescription);
-			}
-		}
-	}
-
-	void* D3D11TextureCore::map(ID3D11Resource* res, D3D11_MAP flags, UINT32 mipLevel, UINT32 face, UINT32& rowPitch, UINT32& slicePitch)
-	{
-		D3D11_MAPPED_SUBRESOURCE pMappedResource;
-		pMappedResource.pData = nullptr;
-
-		mipLevel = Math::clamp(mipLevel, (UINT32)mipLevel, mProperties.getNumMipmaps());
-		face = Math::clamp(face, (UINT32)0, mProperties.getDepth() - 1);
-
-		if (mProperties.getTextureType() == TEX_TYPE_3D)
-			face = 0;
-
-		D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr());
-		D3D11Device& device = rs->getPrimaryDevice();
-
-		mLockedSubresourceIdx = D3D11CalcSubresource(mipLevel, face, mProperties.getNumMipmaps() + 1);
-		device.getImmediateContext()->Map(res, mLockedSubresourceIdx, flags, 0, &pMappedResource);
-
-		if (device.hasError())
-		{
-			String errorDescription = device.getErrorDescription();
-			BS_EXCEPT(RenderingAPIException, "D3D11 device cannot map texture\nError Description:" + errorDescription);
-		}
-
-		UINT32 bytesPerPixel = PixelUtil::getNumElemBytes(mProperties.getFormat());
-		rowPitch = pMappedResource.RowPitch / bytesPerPixel;
-		slicePitch = pMappedResource.DepthPitch / bytesPerPixel;
-
-		return pMappedResource.pData;
-	}
-
-	void D3D11TextureCore::unmap(ID3D11Resource* res)
-	{
-		D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr());
-		D3D11Device& device = rs->getPrimaryDevice();
-		device.getImmediateContext()->Unmap(res, mLockedSubresourceIdx);
-
-		if (device.hasError())
-		{
-			String errorDescription = device.getErrorDescription();
-			BS_EXCEPT(RenderingAPIException, "D3D11 device unmap resource\nError Description:" + errorDescription);
-		}
-	}
-
-	void* D3D11TextureCore::mapstagingbuffer(D3D11_MAP flags, UINT32 mipLevel, UINT32 face, UINT32& rowPitch, UINT32& slicePitch)
-	{
-		// Note: I am creating and destroying a staging resource every time a texture is read. 
-		// Consider offering a flag on init that will keep this active all the time (at the cost of double memory).
-		// Reading is slow operation anyway so I don't believe doing it as we are now will influence it much.
-
-		if(!mStagingBuffer)
-			createStagingBuffer(); 
-
-		D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr());
-		D3D11Device& device = rs->getPrimaryDevice();
-		device.getImmediateContext()->CopyResource(mStagingBuffer, mTex);
-
-		return map(mStagingBuffer, flags, face, mipLevel, rowPitch, slicePitch);
-	}
-
-	void D3D11TextureCore::unmapstagingbuffer()
-	{
-		unmap(mStagingBuffer);
-		SAFE_RELEASE(mStagingBuffer);
-	}
-
-	void* D3D11TextureCore::mapstaticbuffer(PixelData lock, UINT32 mipLevel, UINT32 face)
-	{
-		UINT32 sizeOfImage = lock.getConsecutiveSize();
-		mLockedSubresourceIdx = D3D11CalcSubresource(mipLevel, face, mProperties.getNumMipmaps()+1);
-
-		mStaticBuffer = bs_new<PixelData>(lock.getWidth(), lock.getHeight(), lock.getDepth(), lock.getFormat());
-		mStaticBuffer->allocateInternalBuffer();
-
-		return mStaticBuffer->getData();
-	}
-
-	void D3D11TextureCore::unmapstaticbuffer()
-	{
-		UINT32 rowWidth = D3D11Mappings::getSizeInBytes(mStaticBuffer->getFormat(), mStaticBuffer->getWidth());
-		UINT32 sliceWidth = D3D11Mappings::getSizeInBytes(mStaticBuffer->getFormat(), mStaticBuffer->getWidth(), mStaticBuffer->getHeight());
-
-		D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr());
-		D3D11Device& device = rs->getPrimaryDevice();
-		device.getImmediateContext()->UpdateSubresource(mTex, mLockedSubresourceIdx, nullptr, mStaticBuffer->getData(), rowWidth, sliceWidth);
-
-		if (device.hasError())
-		{
-			String errorDescription = device.getErrorDescription();
-			BS_EXCEPT(RenderingAPIException, "D3D11 device cannot map texture\nError Description:" + errorDescription);
-		}
-
-		if(mStaticBuffer != nullptr)
-			bs_delete(mStaticBuffer);
-	}
-
-	void D3D11TextureCore::createStagingBuffer()
-	{
-		D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr());
-		D3D11Device& device = rs->getPrimaryDevice();
-		switch (mProperties.getTextureType())
-		{
-		case TEX_TYPE_1D:
-			{
-				D3D11_TEXTURE1D_DESC desc;
-				m1DTex->GetDesc(&desc);
-
-				desc.BindFlags = 0;
-				desc.MiscFlags = 0;
-				desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ;
-				desc.Usage = D3D11_USAGE_STAGING;
-
-				device.getD3D11Device()->CreateTexture1D(&desc, nullptr, (ID3D11Texture1D**)(&mStagingBuffer));
-			} 					
-			break;
-		case TEX_TYPE_2D:
-		case TEX_TYPE_CUBE_MAP:
-			{
-				D3D11_TEXTURE2D_DESC desc;
-				m2DTex->GetDesc(&desc);
-
-				desc.BindFlags = 0;
-				desc.MiscFlags = 0;
-				desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ;
-				desc.Usage = D3D11_USAGE_STAGING;
-
-				device.getD3D11Device()->CreateTexture2D(&desc, nullptr, (ID3D11Texture2D**)(&mStagingBuffer));
-			}
-			break;
-		case TEX_TYPE_3D:
-			{
-				D3D11_TEXTURE3D_DESC desc;
-				m3DTex->GetDesc(&desc);
-
-				desc.BindFlags = 0;
-				desc.MiscFlags = 0;
-				desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ;
-				desc.Usage = D3D11_USAGE_STAGING;
-
-				device.getD3D11Device()->CreateTexture3D(&desc, nullptr, (ID3D11Texture3D**)(&mStagingBuffer));
-			}
-			break;
-		}
-	}
-
-	TextureViewPtr D3D11TextureCore::createView(const SPtr<TextureCore>& texture, const TEXTURE_VIEW_DESC& desc)
-	{
-		return bs_shared_ptr<D3D11TextureView>(new (bs_alloc<D3D11TextureView>()) D3D11TextureView(texture, desc));
-	}
+#include "BsD3D11Texture.h"
+#include "BsD3D11Mappings.h"
+#include "BsD3D11Device.h"
+#include "BsD3D11RenderAPI.h"
+#include "BsD3D11TextureView.h"
+#include "BsCoreThread.h"
+#include "BsException.h"
+#include "BsAsyncOp.h"
+#include "BsRenderStats.h"
+#include "BsDebug.h"
+
+namespace BansheeEngine
+{
+	D3D11TextureCore::D3D11TextureCore(TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps,
+		PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount, const PixelDataPtr& initialData)
+		: TextureCore(textureType, width, height, depth, numMipmaps, format, usage, hwGamma, multisampleCount, initialData),
+		m1DTex(nullptr), m2DTex(nullptr), m3DTex(nullptr), mDXGIFormat(DXGI_FORMAT_UNKNOWN), mDXGIColorFormat(DXGI_FORMAT_UNKNOWN),
+		mTex(nullptr), mShaderResourceView(nullptr), mStagingBuffer(nullptr), mDXGIDepthStencilFormat(DXGI_FORMAT_UNKNOWN),
+		mLockedSubresourceIdx(-1), mLockedForReading(false), mStaticBuffer(nullptr)
+	{ }
+
+	D3D11TextureCore::~D3D11TextureCore()
+	{ 
+		SAFE_RELEASE(mTex);
+		SAFE_RELEASE(mShaderResourceView);
+		SAFE_RELEASE(m1DTex);
+		SAFE_RELEASE(m2DTex);
+		SAFE_RELEASE(m3DTex);
+		SAFE_RELEASE(mStagingBuffer);
+
+		BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_Texture);
+	}
+
+	void D3D11TextureCore::initialize()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		switch (mProperties.getTextureType())
+		{
+		case TEX_TYPE_1D:
+			create1DTex();
+			break;
+		case TEX_TYPE_2D:
+		case TEX_TYPE_CUBE_MAP:
+			create2DTex();
+			break;
+		case TEX_TYPE_3D:
+			create3DTex();
+			break;
+		default:
+			BS_EXCEPT(RenderingAPIException, "Unknown texture type");
+		}
+
+		BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_Texture);
+		TextureCore::initialize();
+	}
+
+	void D3D11TextureCore::copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 destFace, UINT32 destMipLevel, const SPtr<TextureCore>& target)
+	{
+		D3D11TextureCore* other = static_cast<D3D11TextureCore*>(target.get());
+
+		UINT32 srcResIdx = D3D11CalcSubresource(srcMipLevel, srcFace, mProperties.getNumMipmaps() + 1);
+		UINT32 destResIdx = D3D11CalcSubresource(destMipLevel, destFace, target->getProperties().getNumMipmaps() + 1);
+
+		D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr());
+		D3D11Device& device = rs->getPrimaryDevice();
+
+		bool srcHasMultisample = mProperties.getMultisampleCount() > 1;
+		bool destHasMultisample = target->getProperties().getMultisampleCount() > 1;
+
+		if (srcHasMultisample && destHasMultisample && mProperties.getMultisampleCount() != target->getProperties().getMultisampleCount()) // Resolving from MS to non-MS texture
+		{
+			device.getImmediateContext()->ResolveSubresource(other->getDX11Resource(), destResIdx, mTex, srcResIdx, mDXGIFormat);
+		}
+		else
+		{
+			device.getImmediateContext()->CopySubresourceRegion(other->getDX11Resource(), destResIdx, 0, 0, 0, mTex, srcResIdx, nullptr);
+
+			if (device.hasError())
+			{
+				String errorDescription = device.getErrorDescription();
+				BS_EXCEPT(RenderingAPIException, "D3D11 device cannot copy subresource\nError Description:" + errorDescription);
+			}
+		}
+	}
+
+	PixelData D3D11TextureCore::lockImpl(GpuLockOptions options, UINT32 mipLevel, UINT32 face)
+	{
+		if (mProperties.getMultisampleCount() > 1)
+			BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
+
+#if BS_PROFILING_ENABLED
+		if (options == GBL_READ_ONLY || options == GBL_READ_WRITE)
+		{
+			BS_INC_RENDER_STAT_CAT(ResRead, RenderStatObject_Texture);
+		}
+
+		if (options == GBL_READ_WRITE || options == GBL_WRITE_ONLY || options == GBL_WRITE_ONLY_DISCARD || options == GBL_WRITE_ONLY_NO_OVERWRITE)
+		{
+			BS_INC_RENDER_STAT_CAT(ResWrite, RenderStatObject_Texture);
+		}
+#endif
+
+		UINT32 mipWidth = mProperties.getWidth() >> mipLevel;
+		UINT32 mipHeight = mProperties.getHeight() >> mipLevel;
+		UINT32 mipDepth = mProperties.getDepth() >> mipLevel;
+
+		PixelData lockedArea(mipWidth, mipHeight, mipDepth, mProperties.getFormat());
+
+		D3D11_MAP flags = D3D11Mappings::getLockOptions(options);
+
+		UINT32 rowPitch, slicePitch;
+
+		if(flags == D3D11_MAP_READ || flags == D3D11_MAP_READ_WRITE)
+		{
+			UINT8* data = (UINT8*)mapstagingbuffer(flags, face, mipLevel, rowPitch, slicePitch);
+			lockedArea.setExternalBuffer(data);
+			lockedArea.setRowPitch(rowPitch);
+			lockedArea.setSlicePitch(slicePitch);
+			mLockedForReading = true;
+		}
+		else
+		{
+			if (mProperties.getUsage() == TU_DYNAMIC)
+			{
+				UINT8* data = (UINT8*)map(mTex, flags, face, mipLevel, rowPitch, slicePitch);
+				lockedArea.setExternalBuffer(data);
+				lockedArea.setRowPitch(rowPitch);
+				lockedArea.setSlicePitch(slicePitch);
+			}
+			else
+				lockedArea.setExternalBuffer((UINT8*)mapstaticbuffer(lockedArea, mipLevel, face));
+
+			mLockedForReading = false;
+		}
+
+		return lockedArea;
+	}
+
+	void D3D11TextureCore::unlockImpl()
+	{
+		if(mLockedForReading)
+			unmapstagingbuffer();
+		else
+		{
+			if (mProperties.getUsage() == TU_DYNAMIC)
+				unmap(mTex);
+			else
+				unmapstaticbuffer();
+		}
+	}
+
+	void D3D11TextureCore::readData(PixelData& dest, UINT32 mipLevel, UINT32 face)
+	{
+		if (mProperties.getMultisampleCount() > 1)
+			BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
+
+		PixelData myData = lock(GBL_READ_ONLY, mipLevel, face);
+
+#if BS_DEBUG_MODE
+		if(dest.getConsecutiveSize() != myData.getConsecutiveSize())
+		{
+			unlock();
+			BS_EXCEPT(InternalErrorException, "Buffer sizes don't match");
+		}
+#endif
+
+		PixelUtil::bulkPixelConversion(myData, dest);
+
+		unlock();
+	}
+
+	void D3D11TextureCore::writeData(const PixelData& src, UINT32 mipLevel, UINT32 face, bool discardWholeBuffer)
+	{
+		PixelFormat format = mProperties.getFormat();
+
+		if (mProperties.getMultisampleCount() > 1)
+			BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
+
+		if ((mProperties.getUsage() & TU_DYNAMIC) != 0)
+		{
+			PixelData myData = lock(discardWholeBuffer ? GBL_WRITE_ONLY_DISCARD : GBL_WRITE_ONLY, mipLevel, face);
+			PixelUtil::bulkPixelConversion(src, myData);
+			unlock();
+		}
+		else if ((mProperties.getUsage() & TU_DEPTHSTENCIL) == 0)
+		{
+			mipLevel = Math::clamp(mipLevel, (UINT32)mipLevel, mProperties.getNumMipmaps());
+			face = Math::clamp(face, (UINT32)0, mProperties.getDepth() - 1);
+
+			if(mProperties.getTextureType() == TEX_TYPE_3D)
+				face = 0;
+
+			D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr());
+			D3D11Device& device = rs->getPrimaryDevice();
+
+			UINT subresourceIdx = D3D11CalcSubresource(mipLevel, face, mProperties.getNumMipmaps() + 1);
+			UINT32 rowWidth = D3D11Mappings::getSizeInBytes(format, src.getWidth());
+			UINT32 sliceWidth = D3D11Mappings::getSizeInBytes(format, src.getWidth(), src.getHeight());
+
+			device.getImmediateContext()->UpdateSubresource(mTex, subresourceIdx, nullptr, src.getData(), rowWidth, sliceWidth);
+
+			if (device.hasError())
+			{
+				String errorDescription = device.getErrorDescription();
+				BS_EXCEPT(RenderingAPIException, "D3D11 device cannot map texture\nError Description:" + errorDescription);
+			}
+
+			BS_INC_RENDER_STAT_CAT(ResWrite, RenderStatObject_Texture);
+		}
+		else
+		{
+			BS_EXCEPT(RenderingAPIException, "Trying to write into a buffer with unsupported usage: " + toString(mProperties.getUsage()));
+		}
+	}
+
+	void D3D11TextureCore::create1DTex()
+	{
+		UINT32 width = mProperties.getWidth();
+		int usage = mProperties.getUsage();
+		UINT32 numMips = mProperties.getNumMipmaps();
+		PixelFormat format = mProperties.getFormat();
+		bool hwGamma = mProperties.isHardwareGammaEnabled();
+		TextureType texType = mProperties.getTextureType();
+		PixelFormat closestFormat = D3D11Mappings::getClosestSupportedPF(format, hwGamma);
+
+		// We must have those defined here
+		assert(width > 0);
+
+		// Determine which D3D11 pixel format we'll use
+		HRESULT hr;
+		DXGI_FORMAT d3dPF = D3D11Mappings::getPF(closestFormat, hwGamma);
+
+		if (format != D3D11Mappings::getPF(d3dPF))
+		{
+			BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(format));
+		}
+
+		mDXGIColorFormat = d3dPF;
+		mDXGIDepthStencilFormat = d3dPF;
+
+		// TODO - Consider making this a parameter eventually
+		bool readableDepth = true;
+
+		D3D11_TEXTURE1D_DESC desc;
+		desc.Width = static_cast<UINT32>(width);
+		desc.ArraySize		= 1;
+		desc.Format			= d3dPF;
+		desc.MiscFlags		= 0;
+
+		if((usage & TU_RENDERTARGET) != 0)
+		{
+			desc.Usage			= D3D11_USAGE_DEFAULT;
+			desc.BindFlags		= D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
+			desc.CPUAccessFlags = 0;
+			desc.MipLevels		= 1;
+		}
+		else if ((usage & TU_DEPTHSTENCIL) != 0)
+		{
+			desc.Usage			= D3D11_USAGE_DEFAULT;
+			
+			if(readableDepth)
+				desc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
+			else
+				desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
+
+			desc.CPUAccessFlags = 0;
+			desc.MipLevels		= 1;
+			desc.Format			= D3D11Mappings::getTypelessDepthStencilPF(closestFormat);
+
+			mDXGIColorFormat = D3D11Mappings::getShaderResourceDepthStencilPF(closestFormat); 
+			mDXGIDepthStencilFormat = d3dPF;
+		}
+		else
+		{
+			desc.Usage			= D3D11Mappings::getUsage((GpuBufferUsage)usage);
+			desc.BindFlags		= D3D11_BIND_SHADER_RESOURCE;
+			desc.CPUAccessFlags = D3D11Mappings::getAccessFlags((GpuBufferUsage)usage);
+
+			// Determine total number of mipmaps including main one (d3d11 convention)
+			desc.MipLevels = (numMips == MIP_UNLIMITED || (1U << numMips) > width) ? 0 : numMips + 1;
+		}
+
+		if ((usage & TU_LOADSTORE) != 0)
+			desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
+
+		// Create the texture
+		D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr());
+		D3D11Device& device = rs->getPrimaryDevice();
+		hr = device.getD3D11Device()->CreateTexture1D(&desc, nullptr, &m1DTex);
+
+		// Check result and except if failed
+		if (FAILED(hr) || device.hasError())
+		{
+			String errorDescription = device.getErrorDescription();
+			BS_EXCEPT(RenderingAPIException, "Error creating texture\nError Description:" + errorDescription);
+		}
+
+		hr = m1DTex->QueryInterface(__uuidof(ID3D11Resource), (void **)&mTex);
+
+		if(FAILED(hr) || device.hasError())
+		{
+			String errorDescription = device.getErrorDescription();
+			BS_EXCEPT(RenderingAPIException, "Can't get base texture\nError Description:" + errorDescription);
+		}
+
+		m1DTex->GetDesc(&desc);
+
+		if(numMips != (desc.MipLevels - 1))
+		{
+			BS_EXCEPT(RenderingAPIException, "Driver returned different number of mip maps than requested. " \
+				"Requested: " + toString(numMips) + ". Got: " + toString(desc.MipLevels - 1) + ".");
+		}
+
+		mDXGIFormat = desc.Format;
+		mDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
+
+		// Create texture view
+		if ((usage & TU_DEPTHSTENCIL) == 0 || readableDepth)
+		{
+			ZeroMemory(&mSRVDesc, sizeof(mSRVDesc));
+			mSRVDesc.Format = mDXGIColorFormat;
+			mSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D; 
+			mSRVDesc.Texture1D.MipLevels = desc.MipLevels;
+			hr = device.getD3D11Device()->CreateShaderResourceView(m1DTex, &mSRVDesc, &mShaderResourceView);
+
+			if (FAILED(hr) || device.hasError())
+			{
+				String errorDescription = device.getErrorDescription();
+				BS_EXCEPT(RenderingAPIException, "D3D11 device can't create shader resource view.\nError Description:" + errorDescription);
+			}
+		}
+	}
+
+	void D3D11TextureCore::create2DTex()
+	{
+		UINT32 width = mProperties.getWidth();
+		UINT32 height = mProperties.getHeight();
+		int usage = mProperties.getUsage();
+		UINT32 numMips = mProperties.getNumMipmaps();
+		PixelFormat format = mProperties.getFormat();
+		bool hwGamma = mProperties.isHardwareGammaEnabled();
+		UINT32 sampleCount = mProperties.getMultisampleCount();
+		TextureType texType = mProperties.getTextureType();
+		PixelFormat closestFormat = D3D11Mappings::getClosestSupportedPF(format, hwGamma);
+
+		// TODO - Consider making this a parameter eventually
+		bool readableDepth = true;
+
+		// We must have those defined here
+		assert(width > 0 || height > 0);
+
+		// Determine which D3D11 pixel format we'll use
+		HRESULT hr;
+		DXGI_FORMAT d3dPF = D3D11Mappings::getPF(closestFormat, hwGamma);
+
+		if (format != D3D11Mappings::getPF(d3dPF))
+		{
+			BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(format));
+		}
+
+		mDXGIColorFormat = d3dPF;
+		mDXGIDepthStencilFormat = d3dPF;
+
+		D3D11_TEXTURE2D_DESC desc;
+		desc.Width			= static_cast<UINT32>(width);
+		desc.Height			= static_cast<UINT32>(height);
+		desc.ArraySize		= 1;
+		desc.Format			= d3dPF;
+		desc.MiscFlags		= 0;
+
+		if((usage & TU_RENDERTARGET) != 0)
+		{
+			desc.Usage			= D3D11_USAGE_DEFAULT;
+			desc.BindFlags		= D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; // TODO - Add flags to allow RT be created without shader resource flags (might be more optimal)
+			desc.CPUAccessFlags = 0;
+			desc.MipLevels		= 1;
+
+			DXGI_SAMPLE_DESC sampleDesc;
+			D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr());
+			rs->determineMultisampleSettings(sampleCount, d3dPF, &sampleDesc);
+			desc.SampleDesc		= sampleDesc;
+
+			if (texType == TEX_TYPE_CUBE_MAP)
+			{
+				BS_EXCEPT(NotImplementedException, "Cube map not yet supported as a render target."); // TODO: Will be once I add proper texture array support
+			}
+		}
+		else if((usage & TU_DEPTHSTENCIL) != 0)
+		{
+			desc.Usage			= D3D11_USAGE_DEFAULT;
+			desc.CPUAccessFlags = 0;
+			desc.MipLevels		= 1;
+			desc.Format			= D3D11Mappings::getTypelessDepthStencilPF(closestFormat);
+
+			if(readableDepth)
+				desc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
+			else
+				desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
+
+			DXGI_SAMPLE_DESC sampleDesc;
+			D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr());
+			rs->determineMultisampleSettings(sampleCount, d3dPF, &sampleDesc);
+			desc.SampleDesc		= sampleDesc;
+
+			if (texType == TEX_TYPE_CUBE_MAP)
+			{
+				BS_EXCEPT(NotImplementedException, "Cube map not yet supported as a depth stencil target."); // TODO: Will be once I add proper texture array support
+			}
+
+			mDXGIColorFormat = D3D11Mappings::getShaderResourceDepthStencilPF(closestFormat);
+			mDXGIDepthStencilFormat = d3dPF;
+		}
+		else
+		{
+			desc.Usage = D3D11Mappings::getUsage((GpuBufferUsage)usage);
+			desc.BindFlags		= D3D11_BIND_SHADER_RESOURCE;
+			desc.CPUAccessFlags = D3D11Mappings::getAccessFlags((GpuBufferUsage)usage);
+
+			// Determine total number of mipmaps including main one (d3d11 convention)
+			desc.MipLevels		= (numMips == MIP_UNLIMITED || (1U << numMips) > width) ? 0 : numMips + 1;
+
+			DXGI_SAMPLE_DESC sampleDesc;
+			sampleDesc.Count	= 1;
+			sampleDesc.Quality	= 0;
+			desc.SampleDesc		= sampleDesc;
+		}
+
+		if (texType == TEX_TYPE_CUBE_MAP)
+        {
+            desc.MiscFlags      |= D3D11_RESOURCE_MISC_TEXTURECUBE;
+            desc.ArraySize       = 6;
+        }
+
+		if ((usage & TU_LOADSTORE) != 0)
+			desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
+
+		// Create the texture
+		D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr());
+		D3D11Device& device = rs->getPrimaryDevice();
+		hr = device.getD3D11Device()->CreateTexture2D(&desc, nullptr, &m2DTex);
+
+		// Check result and except if failed
+		if (FAILED(hr) || device.hasError())
+		{
+			String errorDescription = device.getErrorDescription();
+			BS_EXCEPT(RenderingAPIException, "Error creating texture\nError Description:" + errorDescription);
+		}
+
+		hr = m2DTex->QueryInterface(__uuidof(ID3D11Resource), (void **)&mTex);
+
+		if(FAILED(hr) || device.hasError())
+		{
+			String errorDescription = device.getErrorDescription();
+			BS_EXCEPT(RenderingAPIException, "Can't get base texture\nError Description:" + errorDescription);
+		}
+
+		m2DTex->GetDesc(&desc);
+
+		if(numMips != (desc.MipLevels - 1))
+		{
+			BS_EXCEPT(RenderingAPIException, "Driver returned different number of mip maps than requested. " \
+				"Requested: " + toString(numMips) + ". Got: " + toString(desc.MipLevels - 1) + ".");
+		}
+
+		mDXGIFormat = desc.Format;
+
+		// Create shader texture view
+		if((usage & TU_DEPTHSTENCIL) == 0 || readableDepth)
+		{
+			ZeroMemory(&mSRVDesc, sizeof(mSRVDesc));
+			mSRVDesc.Format = mDXGIColorFormat;
+
+			if((usage & TU_RENDERTARGET) != 0 && (usage & TU_DEPTHSTENCIL) != 0)
+			{
+				if (sampleCount > 1)
+				{
+					mSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
+					mSRVDesc.Texture2D.MostDetailedMip = 0;
+					mSRVDesc.Texture2D.MipLevels = desc.MipLevels;
+				}
+				else
+				{
+					mSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+					mSRVDesc.Texture2D.MostDetailedMip = 0;
+					mSRVDesc.Texture2D.MipLevels = desc.MipLevels;
+				}
+			}
+			else
+			{
+				switch (texType)
+				{
+				case TEX_TYPE_CUBE_MAP:
+					mSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
+					mSRVDesc.TextureCube.MipLevels = desc.MipLevels;
+					mSRVDesc.TextureCube.MostDetailedMip = 0;
+					break;
+
+				case TEX_TYPE_2D:
+					mSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+					mSRVDesc.Texture2D.MostDetailedMip = 0;
+					mSRVDesc.Texture2D.MipLevels = desc.MipLevels;
+					break;
+				}
+			}
+
+			mDimension = mSRVDesc.ViewDimension;
+			hr = device.getD3D11Device()->CreateShaderResourceView(m2DTex, &mSRVDesc, &mShaderResourceView);
+
+			if (FAILED(hr) || device.hasError())
+			{
+				String errorDescription = device.getErrorDescription();
+				BS_EXCEPT(RenderingAPIException, "D3D11 device can't create shader resource view.\nError Description:" + errorDescription);
+			}
+		}
+		else
+		{
+			if (sampleCount > 1)
+				mDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
+			else
+				mDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+		}
+	}
+
+	void D3D11TextureCore::create3DTex()
+	{
+		UINT32 width = mProperties.getWidth();
+		UINT32 height = mProperties.getHeight();
+		UINT32 depth = mProperties.getDepth();
+		int usage = mProperties.getUsage();
+		UINT32 numMips = mProperties.getNumMipmaps();
+		PixelFormat format = mProperties.getFormat();
+		bool hwGamma = mProperties.isHardwareGammaEnabled();
+		PixelFormat closestFormat = D3D11Mappings::getClosestSupportedPF(format, hwGamma);
+
+		// TODO - Consider making this a parameter eventually
+		bool readableDepth = true;
+
+		// We must have those defined here
+		assert(width > 0 && height > 0 && depth > 0);
+
+		// Determine which D3D11 pixel format we'll use
+		HRESULT hr;
+		DXGI_FORMAT d3dPF = D3D11Mappings::getPF(closestFormat, hwGamma);
+		
+		if (format != D3D11Mappings::getPF(d3dPF))
+		{
+			BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(format));
+		}
+
+		mDXGIColorFormat = d3dPF;
+		mDXGIDepthStencilFormat = d3dPF;
+
+		D3D11_TEXTURE3D_DESC desc;
+		desc.Width = static_cast<UINT32>(width);
+		desc.Height = static_cast<UINT32>(height);
+		desc.Depth = static_cast<UINT32>(depth);
+		desc.Format			= d3dPF;
+		desc.MiscFlags		= 0;
+
+		if ((mProperties.getUsage() & TU_RENDERTARGET) != 0)
+		{
+			desc.Usage			= D3D11_USAGE_DEFAULT;
+			desc.BindFlags		= D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
+			desc.CPUAccessFlags = 0;
+			desc.MipLevels		= 1;
+		}
+		else if ((mProperties.getUsage() & TU_DEPTHSTENCIL) != 0)
+		{
+			desc.Usage			= D3D11_USAGE_DEFAULT;
+			desc.CPUAccessFlags = 0;
+			desc.MipLevels		= 1;
+
+			if (readableDepth)
+				desc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
+			else
+				desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
+
+			mDXGIColorFormat = D3D11Mappings::getShaderResourceDepthStencilPF(closestFormat);
+			mDXGIDepthStencilFormat = d3dPF;
+		}
+		else
+		{
+			desc.Usage			= D3D11Mappings::getUsage((GpuBufferUsage)usage);
+			desc.BindFlags		= D3D11_BIND_SHADER_RESOURCE;
+			desc.CPUAccessFlags = D3D11Mappings::getAccessFlags((GpuBufferUsage)usage);
+
+			// Determine total number of mipmaps including main one (d3d11 convention)
+			desc.MipLevels		= (numMips == MIP_UNLIMITED || (1U << numMips)
+				> std::max(std::max(width, height), depth)) ? 0 : numMips + 1;
+		}
+
+		if ((usage & TU_LOADSTORE) != 0)
+			desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
+
+		// Create the texture
+		D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr());
+		D3D11Device& device = rs->getPrimaryDevice();
+		hr = device.getD3D11Device()->CreateTexture3D(&desc, nullptr, &m3DTex);
+
+		// Check result and except if failed
+		if (FAILED(hr) || device.hasError())
+		{
+			String errorDescription = device.getErrorDescription();
+			BS_EXCEPT(RenderingAPIException, "Error creating texture\nError Description:" + errorDescription);
+		}
+
+		hr = m3DTex->QueryInterface(__uuidof(ID3D11Resource), (void **)&mTex);
+
+		if(FAILED(hr) || device.hasError())
+		{
+			String errorDescription = device.getErrorDescription();
+			BS_EXCEPT(RenderingAPIException, "Can't get base texture\nError Description:" + errorDescription);
+		}
+
+		// Create texture view
+		m3DTex->GetDesc(&desc);
+
+		if (mProperties.getNumMipmaps() != (desc.MipLevels - 1))
+		{
+			BS_EXCEPT(RenderingAPIException, "Driver returned different number of mip maps than requested. " \
+				"Requested: " + toString(mProperties.getNumMipmaps()) + ". Got: " + toString(desc.MipLevels - 1) + ".");
+		}
+
+		mDXGIFormat = desc.Format;
+		mDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
+
+		if ((usage & TU_DEPTHSTENCIL) == 0 || readableDepth)
+		{
+			ZeroMemory(&mSRVDesc, sizeof(mSRVDesc));
+			mSRVDesc.Format = mDXGIColorFormat;
+			mSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
+			mSRVDesc.Texture3D.MostDetailedMip = 0;
+			mSRVDesc.Texture3D.MipLevels = desc.MipLevels;
+
+			hr = device.getD3D11Device()->CreateShaderResourceView(m2DTex, &mSRVDesc, &mShaderResourceView);
+
+			if (FAILED(hr) || device.hasError())
+			{
+				String errorDescription = device.getErrorDescription();
+				BS_EXCEPT(RenderingAPIException, "D3D11 device can't create shader resource view.\nError Description:" + errorDescription);
+			}
+		}
+	}
+
+	void* D3D11TextureCore::map(ID3D11Resource* res, D3D11_MAP flags, UINT32 mipLevel, UINT32 face, UINT32& rowPitch, UINT32& slicePitch)
+	{
+		D3D11_MAPPED_SUBRESOURCE pMappedResource;
+		pMappedResource.pData = nullptr;
+
+		mipLevel = Math::clamp(mipLevel, (UINT32)mipLevel, mProperties.getNumMipmaps());
+		face = Math::clamp(face, (UINT32)0, mProperties.getDepth() - 1);
+
+		if (mProperties.getTextureType() == TEX_TYPE_3D)
+			face = 0;
+
+		D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr());
+		D3D11Device& device = rs->getPrimaryDevice();
+
+		mLockedSubresourceIdx = D3D11CalcSubresource(mipLevel, face, mProperties.getNumMipmaps() + 1);
+		device.getImmediateContext()->Map(res, mLockedSubresourceIdx, flags, 0, &pMappedResource);
+
+		if (device.hasError())
+		{
+			String errorDescription = device.getErrorDescription();
+			BS_EXCEPT(RenderingAPIException, "D3D11 device cannot map texture\nError Description:" + errorDescription);
+		}
+
+		UINT32 bytesPerPixel = PixelUtil::getNumElemBytes(mProperties.getFormat());
+		rowPitch = pMappedResource.RowPitch / bytesPerPixel;
+		slicePitch = pMappedResource.DepthPitch / bytesPerPixel;
+
+		return pMappedResource.pData;
+	}
+
+	void D3D11TextureCore::unmap(ID3D11Resource* res)
+	{
+		D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr());
+		D3D11Device& device = rs->getPrimaryDevice();
+		device.getImmediateContext()->Unmap(res, mLockedSubresourceIdx);
+
+		if (device.hasError())
+		{
+			String errorDescription = device.getErrorDescription();
+			BS_EXCEPT(RenderingAPIException, "D3D11 device unmap resource\nError Description:" + errorDescription);
+		}
+	}
+
+	void* D3D11TextureCore::mapstagingbuffer(D3D11_MAP flags, UINT32 mipLevel, UINT32 face, UINT32& rowPitch, UINT32& slicePitch)
+	{
+		// Note: I am creating and destroying a staging resource every time a texture is read. 
+		// Consider offering a flag on init that will keep this active all the time (at the cost of double memory).
+		// Reading is slow operation anyway so I don't believe doing it as we are now will influence it much.
+
+		if(!mStagingBuffer)
+			createStagingBuffer(); 
+
+		D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr());
+		D3D11Device& device = rs->getPrimaryDevice();
+		device.getImmediateContext()->CopyResource(mStagingBuffer, mTex);
+
+		return map(mStagingBuffer, flags, face, mipLevel, rowPitch, slicePitch);
+	}
+
+	void D3D11TextureCore::unmapstagingbuffer()
+	{
+		unmap(mStagingBuffer);
+		SAFE_RELEASE(mStagingBuffer);
+	}
+
+	void* D3D11TextureCore::mapstaticbuffer(PixelData lock, UINT32 mipLevel, UINT32 face)
+	{
+		UINT32 sizeOfImage = lock.getConsecutiveSize();
+		mLockedSubresourceIdx = D3D11CalcSubresource(mipLevel, face, mProperties.getNumMipmaps()+1);
+
+		mStaticBuffer = bs_new<PixelData>(lock.getWidth(), lock.getHeight(), lock.getDepth(), lock.getFormat());
+		mStaticBuffer->allocateInternalBuffer();
+
+		return mStaticBuffer->getData();
+	}
+
+	void D3D11TextureCore::unmapstaticbuffer()
+	{
+		UINT32 rowWidth = D3D11Mappings::getSizeInBytes(mStaticBuffer->getFormat(), mStaticBuffer->getWidth());
+		UINT32 sliceWidth = D3D11Mappings::getSizeInBytes(mStaticBuffer->getFormat(), mStaticBuffer->getWidth(), mStaticBuffer->getHeight());
+
+		D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr());
+		D3D11Device& device = rs->getPrimaryDevice();
+		device.getImmediateContext()->UpdateSubresource(mTex, mLockedSubresourceIdx, nullptr, mStaticBuffer->getData(), rowWidth, sliceWidth);
+
+		if (device.hasError())
+		{
+			String errorDescription = device.getErrorDescription();
+			BS_EXCEPT(RenderingAPIException, "D3D11 device cannot map texture\nError Description:" + errorDescription);
+		}
+
+		if(mStaticBuffer != nullptr)
+			bs_delete(mStaticBuffer);
+	}
+
+	void D3D11TextureCore::createStagingBuffer()
+	{
+		D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr());
+		D3D11Device& device = rs->getPrimaryDevice();
+		switch (mProperties.getTextureType())
+		{
+		case TEX_TYPE_1D:
+			{
+				D3D11_TEXTURE1D_DESC desc;
+				m1DTex->GetDesc(&desc);
+
+				desc.BindFlags = 0;
+				desc.MiscFlags = 0;
+				desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ;
+				desc.Usage = D3D11_USAGE_STAGING;
+
+				device.getD3D11Device()->CreateTexture1D(&desc, nullptr, (ID3D11Texture1D**)(&mStagingBuffer));
+			} 					
+			break;
+		case TEX_TYPE_2D:
+		case TEX_TYPE_CUBE_MAP:
+			{
+				D3D11_TEXTURE2D_DESC desc;
+				m2DTex->GetDesc(&desc);
+
+				desc.BindFlags = 0;
+				desc.MiscFlags = 0;
+				desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ;
+				desc.Usage = D3D11_USAGE_STAGING;
+
+				device.getD3D11Device()->CreateTexture2D(&desc, nullptr, (ID3D11Texture2D**)(&mStagingBuffer));
+			}
+			break;
+		case TEX_TYPE_3D:
+			{
+				D3D11_TEXTURE3D_DESC desc;
+				m3DTex->GetDesc(&desc);
+
+				desc.BindFlags = 0;
+				desc.MiscFlags = 0;
+				desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ;
+				desc.Usage = D3D11_USAGE_STAGING;
+
+				device.getD3D11Device()->CreateTexture3D(&desc, nullptr, (ID3D11Texture3D**)(&mStagingBuffer));
+			}
+			break;
+		}
+	}
+
+	TextureViewPtr D3D11TextureCore::createView(const SPtr<TextureCore>& texture, const TEXTURE_VIEW_DESC& desc)
+	{
+		return bs_shared_ptr<D3D11TextureView>(new (bs_alloc<D3D11TextureView>()) D3D11TextureView(texture, desc));
+	}
 }

+ 250 - 242
BansheeD3D11RenderAPI/Source/BsD3D11TextureView.cpp

@@ -1,243 +1,251 @@
-#include "BsD3D11TextureView.h"
-#include "BsD3D11RenderAPI.h"
-#include "BsD3D11Device.h"
-#include "BsD3D11Texture.h"
-#include "BsRenderStats.h"
-#include "BsException.h"
-
-namespace BansheeEngine
-{
-	D3D11TextureView::D3D11TextureView(const SPtr<TextureCore>& texture, const TEXTURE_VIEW_DESC& desc)
-		:TextureView(texture, desc), mSRV(nullptr), mUAV(nullptr), mDSV(nullptr), mRTV(nullptr)
-	{
-		D3D11TextureCore* d3d11Texture = static_cast<D3D11TextureCore*>(mOwnerTexture.get());
-
-		if ((mDesc.usage & GVU_RANDOMWRITE) != 0)
-			mUAV = createUAV(d3d11Texture, mDesc.mostDetailMip, mDesc.firstArraySlice, mDesc.numArraySlices);
-		else if ((mDesc.usage & GVU_RENDERTARGET) != 0)
-			mRTV = createRTV(d3d11Texture, mDesc.mostDetailMip, mDesc.firstArraySlice, mDesc.numArraySlices);
-		else if ((mDesc.usage & GVU_DEPTHSTENCIL) != 0)
-			mDSV = createDSV(d3d11Texture, mDesc.mostDetailMip, mDesc.firstArraySlice, mDesc.numArraySlices);
-		else
-			mSRV = createSRV(d3d11Texture, mDesc.mostDetailMip, mDesc.numMips, mDesc.firstArraySlice, mDesc.numArraySlices);
-	}
-
-	D3D11TextureView::~D3D11TextureView()
-	{
-		SAFE_RELEASE(mSRV);
-		SAFE_RELEASE(mUAV);
-		SAFE_RELEASE(mDSV);
-		SAFE_RELEASE(mRTV);
-	}
-
-	ID3D11ShaderResourceView* D3D11TextureView::createSRV(D3D11TextureCore* texture, 
-		UINT32 mostDetailMip, UINT32 numMips, UINT32 firstArraySlice, UINT32 numArraySlices)
-	{
-		D3D11_SHADER_RESOURCE_VIEW_DESC desc;
-		ZeroMemory(&desc, sizeof(desc));
-
-		const TextureProperties& texProps = texture->getProperties();
-		switch (texProps.getTextureType())
-		{
-		case TEX_TYPE_1D:
-			desc.Texture1D.MipLevels = numMips;
-			desc.Texture1D.MostDetailedMip = mostDetailMip;
-			desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
-			break;
-		case TEX_TYPE_2D:
-			if (texProps.getMultisampleCount() > 1)
-			{
-				desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
-			}
-			else
-			{
-				desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
-				desc.Texture2D.MipLevels = numMips;
-				desc.Texture2D.MostDetailedMip = mostDetailMip;
-			}
-			break;
-		case TEX_TYPE_3D:
-			desc.Texture3D.MipLevels = numMips;
-			desc.Texture3D.MostDetailedMip = mostDetailMip;
-			desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
-			break;
-		case TEX_TYPE_CUBE_MAP:
-			desc.TextureCube.MipLevels = numMips;
-			desc.TextureCube.MostDetailedMip = mostDetailMip;
-			desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
-			break;
-		default:
-			BS_EXCEPT(InvalidParametersException, "Invalid texture type for this view type.");
-		}
-
-		desc.Format = texture->getDXGIFormat();
-
-		ID3D11ShaderResourceView* srv = nullptr;
-
-		D3D11RenderAPI* d3d11rs = static_cast<D3D11RenderAPI*>(D3D11RenderAPI::instancePtr());
-		HRESULT hr = d3d11rs->getPrimaryDevice().getD3D11Device()->CreateShaderResourceView(texture->getDX11Resource(), &desc, &srv);
-
-		if (FAILED(hr) || d3d11rs->getPrimaryDevice().hasError())
-		{
-			String msg = d3d11rs->getPrimaryDevice().getErrorDescription();
-			BS_EXCEPT(RenderingAPIException, "Cannot create ShaderResourceView: " + msg);
-		}
-
-		return srv;
-	}
-
-	ID3D11RenderTargetView* D3D11TextureView::createRTV(D3D11TextureCore* texture,
-		UINT32 mipSlice, UINT32 firstArraySlice, UINT32 numArraySlices)
-	{
-		D3D11_RENDER_TARGET_VIEW_DESC desc;
-		ZeroMemory(&desc, sizeof(desc));
-
-		const TextureProperties& texProps = texture->getProperties();
-		switch (texProps.getTextureType())
-		{
-		case TEX_TYPE_1D:
-			desc.Texture1D.MipSlice = mipSlice;
-			desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D;
-			break;
-		case TEX_TYPE_2D:
-			if (texProps.getMultisampleCount() > 1)
-			{
-				desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
-			}
-			else
-			{
-				desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
-				desc.Texture2D.MipSlice = mipSlice;
-			}
-			break;
-		case TEX_TYPE_3D:
-			desc.Texture3D.MipSlice = mipSlice;
-			desc.Texture3D.FirstWSlice = firstArraySlice;
-			desc.Texture3D.WSize = numArraySlices;
-			desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
-			break;
-		case TEX_TYPE_CUBE_MAP:
-			desc.Texture2DArray.FirstArraySlice = firstArraySlice;
-			desc.Texture2DArray.ArraySize = numArraySlices;
-			desc.Texture2DArray.MipSlice = mipSlice;
-			desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
-			break;
-		default:
-			BS_EXCEPT(InvalidParametersException, "Invalid texture type for this view type.");
-		}
-
-		desc.Format = texture->getDXGIFormat();
-
-		ID3D11RenderTargetView* rtv = nullptr;
-
-		D3D11RenderAPI* d3d11rs = static_cast<D3D11RenderAPI*>(D3D11RenderAPI::instancePtr());
-		HRESULT hr = d3d11rs->getPrimaryDevice().getD3D11Device()->CreateRenderTargetView(texture->getDX11Resource(), &desc, &rtv);
-
-		if (FAILED(hr) || d3d11rs->getPrimaryDevice().hasError())
-		{
-			String msg = d3d11rs->getPrimaryDevice().getErrorDescription();
-			BS_EXCEPT(RenderingAPIException, "Cannot create RenderTargetView: " + msg);
-		}
-
-		return rtv;
-	}
-
-	ID3D11UnorderedAccessView* D3D11TextureView::createUAV(D3D11TextureCore* texture,
-		UINT32 mipSlice, UINT32 firstArraySlice, UINT32 numArraySlices)
-	{
-		D3D11_UNORDERED_ACCESS_VIEW_DESC desc;
-		ZeroMemory(&desc, sizeof(desc));
-
-		switch(texture->getProperties().getTextureType())
-		{
-		case TEX_TYPE_1D:
-			desc.Texture1D.MipSlice = mipSlice;
-			desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE1D;
-			break;
-		case TEX_TYPE_2D:
-			desc.Texture2D.MipSlice = mipSlice;
-			desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
-			break;
-		case TEX_TYPE_3D:
-			desc.Texture3D.MipSlice = mipSlice;
-			desc.Texture3D.FirstWSlice = firstArraySlice;
-			desc.Texture3D.WSize = numArraySlices;
-			desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
-			break;
-		case TEX_TYPE_CUBE_MAP:
-			desc.Texture2DArray.FirstArraySlice = firstArraySlice;
-			desc.Texture2DArray.ArraySize = numArraySlices;
-			desc.Texture2DArray.MipSlice = mipSlice;
-			desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
-			break;
-		default:
-			BS_EXCEPT(InvalidParametersException, "Invalid texture type for this view type.");
-		}
-
-		desc.Format = texture->getDXGIFormat();
-
-		ID3D11UnorderedAccessView* uav = nullptr;
-
-		D3D11RenderAPI* d3d11rs = static_cast<D3D11RenderAPI*>(D3D11RenderAPI::instancePtr());
-		HRESULT hr = d3d11rs->getPrimaryDevice().getD3D11Device()->CreateUnorderedAccessView(texture->getDX11Resource(), &desc, &uav);
-
-		if (FAILED(hr) || d3d11rs->getPrimaryDevice().hasError())
-		{
-			String msg = d3d11rs->getPrimaryDevice().getErrorDescription();
-			BS_EXCEPT(RenderingAPIException, "Cannot create UnorderedAccessView: " + msg);
-		}
-
-		return uav;
-	}
-
-	ID3D11DepthStencilView* D3D11TextureView::createDSV(D3D11TextureCore* texture,
-		UINT32 mipSlice, UINT32 firstArraySlice, UINT32 numArraySlices)
-	{
-		D3D11_DEPTH_STENCIL_VIEW_DESC desc;
-		ZeroMemory(&desc, sizeof(desc));
-
-		const TextureProperties& texProps = texture->getProperties();
-		switch (texProps.getTextureType())
-		{
-		case TEX_TYPE_1D:
-			desc.Texture1D.MipSlice = mipSlice;
-			desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1D;
-			break;
-		case TEX_TYPE_2D:
-			if (texProps.getMultisampleCount() > 1)
-			{
-				desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
-			}
-			else
-			{
-				desc.Texture2D.MipSlice = mipSlice;
-				desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
-			}
-			break;
-		case TEX_TYPE_3D:
-		case TEX_TYPE_CUBE_MAP:
-			desc.Texture2DArray.FirstArraySlice = firstArraySlice;
-			desc.Texture2DArray.ArraySize = numArraySlices;
-			desc.Texture2DArray.MipSlice = mipSlice;
-			desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
-			break;
-		default:
-			BS_EXCEPT(InvalidParametersException, "Invalid texture type for this view type.");
-		}
-
-		desc.Format = texture->getDXGIFormat();
-
-		ID3D11DepthStencilView* dsv = nullptr;
-
-		D3D11RenderAPI* d3d11rs = static_cast<D3D11RenderAPI*>(D3D11RenderAPI::instancePtr());
-		HRESULT hr = d3d11rs->getPrimaryDevice().getD3D11Device()->CreateDepthStencilView(texture->getDX11Resource(), &desc, &dsv);
-
-		if (FAILED(hr) || d3d11rs->getPrimaryDevice().hasError())
-		{
-			String msg = d3d11rs->getPrimaryDevice().getErrorDescription();
-			BS_EXCEPT(RenderingAPIException, "Cannot create DepthStencilView: " + msg);
-		}
-
-		return dsv;
-	}
+#include "BsD3D11TextureView.h"
+#include "BsD3D11RenderAPI.h"
+#include "BsD3D11Device.h"
+#include "BsD3D11Texture.h"
+#include "BsRenderStats.h"
+#include "BsD3D11Mappings.h"
+#include "BsException.h"
+
+namespace BansheeEngine
+{
+	D3D11TextureView::D3D11TextureView(const SPtr<TextureCore>& texture, const TEXTURE_VIEW_DESC& desc)
+		:TextureView(texture, desc), mSRV(nullptr), mUAV(nullptr), mDSV(nullptr), mRTV(nullptr), mRODSV(nullptr)
+	{
+		D3D11TextureCore* d3d11Texture = static_cast<D3D11TextureCore*>(mOwnerTexture.get());
+
+		if ((mDesc.usage & GVU_RANDOMWRITE) != 0)
+			mUAV = createUAV(d3d11Texture, mDesc.mostDetailMip, mDesc.firstArraySlice, mDesc.numArraySlices);
+		else if ((mDesc.usage & GVU_RENDERTARGET) != 0)
+			mRTV = createRTV(d3d11Texture, mDesc.mostDetailMip, mDesc.firstArraySlice, mDesc.numArraySlices);
+		else if ((mDesc.usage & GVU_DEPTHSTENCIL) != 0)
+		{
+			mDSV = createDSV(d3d11Texture, mDesc.mostDetailMip, mDesc.firstArraySlice, mDesc.numArraySlices, false);
+			mRODSV = createDSV(d3d11Texture, mDesc.mostDetailMip, mDesc.firstArraySlice, mDesc.numArraySlices, true);
+		}
+		else
+			mSRV = createSRV(d3d11Texture, mDesc.mostDetailMip, mDesc.numMips, mDesc.firstArraySlice, mDesc.numArraySlices);
+	}
+
+	D3D11TextureView::~D3D11TextureView()
+	{
+		SAFE_RELEASE(mSRV);
+		SAFE_RELEASE(mUAV);
+		SAFE_RELEASE(mDSV);
+		SAFE_RELEASE(mRODSV);
+		SAFE_RELEASE(mRTV);
+	}
+
+	ID3D11ShaderResourceView* D3D11TextureView::createSRV(D3D11TextureCore* texture, 
+		UINT32 mostDetailMip, UINT32 numMips, UINT32 firstArraySlice, UINT32 numArraySlices)
+	{
+		D3D11_SHADER_RESOURCE_VIEW_DESC desc;
+		ZeroMemory(&desc, sizeof(desc));
+
+		const TextureProperties& texProps = texture->getProperties();
+		switch (texProps.getTextureType())
+		{
+		case TEX_TYPE_1D:
+			desc.Texture1D.MipLevels = numMips;
+			desc.Texture1D.MostDetailedMip = mostDetailMip;
+			desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
+			break;
+		case TEX_TYPE_2D:
+			if (texProps.getMultisampleCount() > 1)
+			{
+				desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
+			}
+			else
+			{
+				desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+				desc.Texture2D.MipLevels = numMips;
+				desc.Texture2D.MostDetailedMip = mostDetailMip;
+			}
+			break;
+		case TEX_TYPE_3D:
+			desc.Texture3D.MipLevels = numMips;
+			desc.Texture3D.MostDetailedMip = mostDetailMip;
+			desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
+			break;
+		case TEX_TYPE_CUBE_MAP:
+			desc.TextureCube.MipLevels = numMips;
+			desc.TextureCube.MostDetailedMip = mostDetailMip;
+			desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
+			break;
+		default:
+			BS_EXCEPT(InvalidParametersException, "Invalid texture type for this view type.");
+		}
+
+		desc.Format = texture->getColorFormat();
+
+		ID3D11ShaderResourceView* srv = nullptr;
+
+		D3D11RenderAPI* d3d11rs = static_cast<D3D11RenderAPI*>(D3D11RenderAPI::instancePtr());
+		HRESULT hr = d3d11rs->getPrimaryDevice().getD3D11Device()->CreateShaderResourceView(texture->getDX11Resource(), &desc, &srv);
+
+		if (FAILED(hr) || d3d11rs->getPrimaryDevice().hasError())
+		{
+			String msg = d3d11rs->getPrimaryDevice().getErrorDescription();
+			BS_EXCEPT(RenderingAPIException, "Cannot create ShaderResourceView: " + msg);
+		}
+
+		return srv;
+	}
+
+	ID3D11RenderTargetView* D3D11TextureView::createRTV(D3D11TextureCore* texture,
+		UINT32 mipSlice, UINT32 firstArraySlice, UINT32 numArraySlices)
+	{
+		D3D11_RENDER_TARGET_VIEW_DESC desc;
+		ZeroMemory(&desc, sizeof(desc));
+
+		const TextureProperties& texProps = texture->getProperties();
+		switch (texProps.getTextureType())
+		{
+		case TEX_TYPE_1D:
+			desc.Texture1D.MipSlice = mipSlice;
+			desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D;
+			break;
+		case TEX_TYPE_2D:
+			if (texProps.getMultisampleCount() > 1)
+			{
+				desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
+			}
+			else
+			{
+				desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+				desc.Texture2D.MipSlice = mipSlice;
+			}
+			break;
+		case TEX_TYPE_3D:
+			desc.Texture3D.MipSlice = mipSlice;
+			desc.Texture3D.FirstWSlice = firstArraySlice;
+			desc.Texture3D.WSize = numArraySlices;
+			desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
+			break;
+		case TEX_TYPE_CUBE_MAP:
+			desc.Texture2DArray.FirstArraySlice = firstArraySlice;
+			desc.Texture2DArray.ArraySize = numArraySlices;
+			desc.Texture2DArray.MipSlice = mipSlice;
+			desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+			break;
+		default:
+			BS_EXCEPT(InvalidParametersException, "Invalid texture type for this view type.");
+		}
+
+		desc.Format = texture->getColorFormat();
+
+		ID3D11RenderTargetView* rtv = nullptr;
+
+		D3D11RenderAPI* d3d11rs = static_cast<D3D11RenderAPI*>(D3D11RenderAPI::instancePtr());
+		HRESULT hr = d3d11rs->getPrimaryDevice().getD3D11Device()->CreateRenderTargetView(texture->getDX11Resource(), &desc, &rtv);
+
+		if (FAILED(hr) || d3d11rs->getPrimaryDevice().hasError())
+		{
+			String msg = d3d11rs->getPrimaryDevice().getErrorDescription();
+			BS_EXCEPT(RenderingAPIException, "Cannot create RenderTargetView: " + msg);
+		}
+
+		return rtv;
+	}
+
+	ID3D11UnorderedAccessView* D3D11TextureView::createUAV(D3D11TextureCore* texture,
+		UINT32 mipSlice, UINT32 firstArraySlice, UINT32 numArraySlices)
+	{
+		D3D11_UNORDERED_ACCESS_VIEW_DESC desc;
+		ZeroMemory(&desc, sizeof(desc));
+
+		switch(texture->getProperties().getTextureType())
+		{
+		case TEX_TYPE_1D:
+			desc.Texture1D.MipSlice = mipSlice;
+			desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE1D;
+			break;
+		case TEX_TYPE_2D:
+			desc.Texture2D.MipSlice = mipSlice;
+			desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
+			break;
+		case TEX_TYPE_3D:
+			desc.Texture3D.MipSlice = mipSlice;
+			desc.Texture3D.FirstWSlice = firstArraySlice;
+			desc.Texture3D.WSize = numArraySlices;
+			desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
+			break;
+		case TEX_TYPE_CUBE_MAP:
+			desc.Texture2DArray.FirstArraySlice = firstArraySlice;
+			desc.Texture2DArray.ArraySize = numArraySlices;
+			desc.Texture2DArray.MipSlice = mipSlice;
+			desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
+			break;
+		default:
+			BS_EXCEPT(InvalidParametersException, "Invalid texture type for this view type.");
+		}
+
+		desc.Format = texture->getDXGIFormat();
+
+		ID3D11UnorderedAccessView* uav = nullptr;
+
+		D3D11RenderAPI* d3d11rs = static_cast<D3D11RenderAPI*>(D3D11RenderAPI::instancePtr());
+		HRESULT hr = d3d11rs->getPrimaryDevice().getD3D11Device()->CreateUnorderedAccessView(texture->getDX11Resource(), &desc, &uav);
+
+		if (FAILED(hr) || d3d11rs->getPrimaryDevice().hasError())
+		{
+			String msg = d3d11rs->getPrimaryDevice().getErrorDescription();
+			BS_EXCEPT(RenderingAPIException, "Cannot create UnorderedAccessView: " + msg);
+		}
+
+		return uav;
+	}
+
+	ID3D11DepthStencilView* D3D11TextureView::createDSV(D3D11TextureCore* texture,
+		UINT32 mipSlice, UINT32 firstArraySlice, UINT32 numArraySlices, bool readOnly)
+	{
+		D3D11_DEPTH_STENCIL_VIEW_DESC desc;
+		ZeroMemory(&desc, sizeof(desc));
+
+		const TextureProperties& texProps = texture->getProperties();
+		switch (texProps.getTextureType())
+		{
+		case TEX_TYPE_1D:
+			desc.Texture1D.MipSlice = mipSlice;
+			desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1D;
+			break;
+		case TEX_TYPE_2D:
+			if (texProps.getMultisampleCount() > 1)
+			{
+				desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
+			}
+			else
+			{
+				desc.Texture2D.MipSlice = mipSlice;
+				desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
+			}
+			break;
+		case TEX_TYPE_3D:
+		case TEX_TYPE_CUBE_MAP:
+			desc.Texture2DArray.FirstArraySlice = firstArraySlice;
+			desc.Texture2DArray.ArraySize = numArraySlices;
+			desc.Texture2DArray.MipSlice = mipSlice;
+			desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
+			break;
+		default:
+			BS_EXCEPT(InvalidParametersException, "Invalid texture type for this view type.");
+		}
+
+		if (readOnly)
+			desc.Flags = D3D11_DSV_READ_ONLY_DEPTH | D3D11_DSV_READ_ONLY_STENCIL;
+
+		desc.Format = texture->getDepthStencilFormat();
+
+		ID3D11DepthStencilView* dsv = nullptr;
+
+		D3D11RenderAPI* d3d11rs = static_cast<D3D11RenderAPI*>(D3D11RenderAPI::instancePtr());
+		HRESULT hr = d3d11rs->getPrimaryDevice().getD3D11Device()->CreateDepthStencilView(texture->getDX11Resource(), &desc, &dsv);
+
+		if (FAILED(hr) || d3d11rs->getPrimaryDevice().hasError())
+		{
+			String msg = d3d11rs->getPrimaryDevice().getErrorDescription();
+			BS_EXCEPT(RenderingAPIException, "Cannot create DepthStencilView: " + msg);
+		}
+
+		return dsv;
+	}
 }

+ 596 - 596
BansheeD3D9RenderAPI/Include/BsD3D9RenderAPI.h

@@ -1,597 +1,597 @@
-#pragma once
-
-#include "BsD3D9Prerequisites.h"
-#include "BsRenderAPI.h"
-#include "BsRenderAPICapabilities.h"
-#include "BsD3D9Mappings.h"
-
-namespace BansheeEngine 
-{
-	/**
-	 * @brief	Implementation of a render system using DirectX 9. Provides abstracted
-	 *			access to various low level DX9 methods.
-	 */
-	class BS_D3D9_EXPORT D3D9RenderAPI : public RenderAPICore
-	{
-	public:
-		/**
-		 * @brief	Constructs a new instance of the render system using the provided module instance.
-		 */
-		D3D9RenderAPI(HINSTANCE hInstance);
-		~D3D9RenderAPI();
-
-		/**
-		 * @copydoc RenderAPICore::getName()
-		 */
-		const StringID& getName() const override;
-
-		/**
-		 * @copydoc RenderAPICore::getShadingLanguageName()
-		 */
-		const String& getShadingLanguageName() const override;
-
-		/**
-		 * @copydoc RenderAPICore::setRenderTarget()
-		 */
-		void setRenderTarget(const SPtr<RenderTargetCore>& target) override;
-
-		/**
-		 * @copydoc RenderAPICore::bindGpuProgram()
-		 */
-		void bindGpuProgram(const SPtr<GpuProgramCore>& prg) override;
-
-		/**
-		 * @copydoc RenderAPICore::unbindGpuProgram()
-		 */
-		void unbindGpuProgram(GpuProgramType gptype) override;
-
-		/**
-		 * @copydoc RenderAPICore::setConstantBuffers()
-		 */
-		void setConstantBuffers(GpuProgramType gptype, const SPtr<GpuParamsCore>& params) override;
-
-		/**
-		 * @copydoc RenderAPICore::setVertexBuffers()
-		 */
-		void setVertexBuffers(UINT32 index, SPtr<VertexBufferCore>* buffers, UINT32 numBuffers) override;
-
-		/**
-		 * @copydoc RenderAPICore::setIndexBuffer()
-		 */
-		void setIndexBuffer(const SPtr<IndexBufferCore>& buffer) override;
-
-		/**
-		 * @copydoc RenderAPICore::setVertexDeclaration()
-		 */
-		void setVertexDeclaration(const SPtr<VertexDeclarationCore>& vertexDeclaration) override;
-
-		/**
-		 * @copydoc RenderAPICore::setDrawOperation()
-		 */
-		void setDrawOperation(DrawOperationType op) override;
-
-		/**
-		 * @copydoc RenderAPICore::setTexture()
-		 */
-		void setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr) override;
-
-		/**
-		 * @copydoc RenderAPICore::setLoadStoreTexture()
-		 */
-		void setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr,
-			const TextureSurface& surface) override;
-
-		/**
-		 * @copydoc RenderAPICore::setSamplerState()
-		 */
-		void setSamplerState(GpuProgramType gptype, UINT16 unit, const SPtr<SamplerStateCore>& state) override;
-
-		/**
-		 * @copydoc RenderAPICore::setBlendState()
-		 */
-		void setBlendState(const SPtr<BlendStateCore>& blendState) override;
-
-		/**
-		 * @copydoc RenderAPICore::setRasterizerState()
-		 */
-		void setRasterizerState(const SPtr<RasterizerStateCore>& rasterizerState) override;
-
-		/**
-		 * @copydoc RenderAPICore::setDepthStencilState()
-		 */
-		void setDepthStencilState(const SPtr<DepthStencilStateCore>& depthStencilState, UINT32 stencilRefValue) override;
-
-		/**
-		 * @copydoc RenderAPICore::setViewport()
-		 */
-		void setViewport(const Rect2& vp) override;
-
-		/**
-		 * @copydoc RenderAPICore::beginFrame()
-		 */
-		void beginFrame() override;
-
-		/**
-		 * @copydoc RenderAPICore::endFrame()
-		 */
-		void endFrame() override;
-
-		/**
-		 * @copydoc RenderAPICore::draw()
-		 */
-		void draw(UINT32 vertexOffset, UINT32 vertexCount) override;
-
-		/**
-		 * @copydoc RenderAPICore::drawIndexed()
-		 */
-		void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount) override;
-
-		/**
-		 * @copydoc RenderAPICore::setScissorRect()
-		 */
-		void setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom) override;
-
-		/**
-		 * @copydoc RenderAPICore::clearRenderTarget()
-		 */
-		void clearRenderTarget(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0) override;
-
-		/**
-		 * @copydoc RenderAPICore::clearViewport()
-		 */
-		void clearViewport(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0) override;
-
-		/**
-		 * @copydoc RenderAPICore::convertProjectionMatrix()
-		 */
-		void convertProjectionMatrix(const Matrix4& matrix, Matrix4& dest) override;
-
-		/**
-		 * @copydoc	RenderAPICore::getHorizontalTexelOffset
-		 */
-		float getHorizontalTexelOffset() override;
-
-		/**
-		 * @copydoc	RenderAPICore::getVerticalTexelOffset
-		 */
-		float getVerticalTexelOffset() override;
-
-		/**
-		 * @copydoc	RenderAPICore::getMinimumDepthInputValue
-		 */
-		float getMinimumDepthInputValue() override;
-
-		/**
-		 * @copydoc	RenderAPICore::getMaximumDepthInputValue
-		 */
-		float getMaximumDepthInputValue() override;
-
-		/**
-		 * @copydoc	RenderAPICore::getColorVertexElementType
-		 */
-		VertexElementType getColorVertexElementType() const override;
-
-		/**
-		 * @copydoc	RenderAPICore::getColorVertexElementType
-		 */
-		bool getVertexColorFlipRequired() const override { return true; }
-
-		/**
-		 * @copydoc RenderAPICore::generateParamBlockDesc()
-		 */
-		GpuParamBlockDesc generateParamBlockDesc(const String& name, Vector<GpuParamDataDesc>& params) override;
-
-		/************************************************************************/
-		/* 				Internal use by DX9 RenderAPI only                   */
-		/************************************************************************/
-
-		/**
-		 * @brief	Returns the resource manager instance.
-		 */
-		static D3D9ResourceManager* getResourceManager();
-
-		/**
-		 * @brief	Returns the device manager instance.
-		 */
-		static D3D9DeviceManager* getDeviceManager();
-
-		/**
-		 * @brief	Returns the internal DirectX 9 device object.
-		 */
-		static IDirect3D9* getDirect3D9();
-
-		/**
-		 * @brief	Returns the number of devices that resources should be created on.
-		 */
-		static UINT	getResourceCreationDeviceCount();
-
-		/**
-		 * @brief	Returns DirectX 9 device used for resource creation at the specified index.
-		 */
-		static IDirect3DDevice9* getResourceCreationDevice(UINT index);
-
-		/**
-		 * @brief	Returns the currently active DirectX 9 device.
-		 */
-		static IDirect3DDevice9* getActiveD3D9Device();
-
-		/**
-		 * @brief	Converts engine multisample options into DirectX 9 specific ones.
-		 *			Also test for multi-sample support on the device and returns nearest
-		 *			supported type if requested type is not available.
-		 *
-		 * @param	d3d9Device				Device to check for multisampling.
-		 * @param	multisampleCount		Number of requested samples.
-		 * @param	d3dPixelFormat			Pixel format used by the render target.
-		 * @param	fullscreen				Are we testing multisampling for a full-screen render target.
-		 * @param	outMultisampleType		Output parameter containing DirectX type representing valid multisample type.
-		 * @param	outMultisampleQuality	Output parameter containing multisample quality.
-		 */
-		void determineMultisampleSettings(IDirect3DDevice9* d3d9Device, UINT32 multisampleCount, D3DFORMAT d3dPixelFormat,
-			bool fullScreen, D3DMULTISAMPLE_TYPE* outMultisampleType, DWORD* outMultisampleQuality) const;
-
-		/**
-		 * @brief	Register a newly open window with the render system.
-		 */
-		void registerWindow(RenderWindowCore& renderWindow);
-
-	private:
-		friend class D3D9Texture;
-		friend class D3D9RenderWindow;
-		friend class D3D9Device;
-		friend class D3D9TextureManager;
-		friend class D3D9TextureCoreManager;
-		friend class D3D9DeviceManager;
-		friend class D3D9RenderWindowManager;
-		friend class D3D9RenderWindowCoreManager;
-
-		/**
-		 * @copydoc	RenderAPICore::initializePrepare
-		 */
-		void initializePrepare() override;
-
-		/**
-		 * @copydoc	RenderAPICore::initializeFinalize
-		 */
-		void initializeFinalize(const SPtr<RenderWindowCore>& primaryWindow) override;
-
-		/**
-		 * @copydoc	RenderAPICore::destroy_internal
-		 */
-		void destroyCore() override;
-
-		/**
-		 * @brief	Returns a list of available drivers and their properties.
-		 */
-		D3D9DriverList* getDirect3DDrivers() const;
-				
-		/**
-		 * @brief	Sets DirectX 9 render state option.
-		 */
-		HRESULT setRenderState(D3DRENDERSTATETYPE state, DWORD value);
-
-		/**
-		 * @brief	Sets DirectX 9 sampler state option for a sampler at the specified index.
-		 */
-		HRESULT setSamplerState(DWORD sampler, D3DSAMPLERSTATETYPE type, DWORD value);
-
-		/**
-		 * @brief	Sets DirectX 9 texture state option for a texture unit at the specified index.
-		 */
-		HRESULT setTextureStageState(DWORD stage, D3DTEXTURESTAGESTATETYPE type, DWORD value);
-
-		/**
-		 * @brief	Set a floating point render state option.
-		 */
-		HRESULT setFloatRenderState(D3DRENDERSTATETYPE state, float value)
-		{
-			return setRenderState(state, *((LPDWORD)(&value)));
-		}
-
-		/**
-		 * @brief	Returns currently active anisotropy level for the provided texture unit.
-		 */
-		DWORD getCurrentAnisotropy(UINT32 unit);
-
-		/**
-		 * @brief	Updates active render system capabilities. Requires active render window to check
-		 *			certain capabilities.
-		 *
-		 * @note	Also performs an initialization step when called the first time.
-		 */
-		RenderAPICapabilities* updateRenderSystemCapabilities(D3D9RenderWindowCore* renderWindow);
-
-		/**
-		 * @brief	Updates render system capabilities with vertex shader related data.
-		 */
-        void updateVertexShaderCaps(RenderAPICapabilities* rsc) const;
-
-		/**
-		 * @brief	Updates render system capabilities with pixel shader related data.
-		 */
-        void updatePixelShaderCaps(RenderAPICapabilities* rsc) const;
-
-		/**
-		 * @copydoc	RenderAPICore::setClipPlanesImpl
-		 */
-		void setClipPlanesImpl(const PlaneList& clipPlanes) override;
-
-		/**
-		 * @brief	Converts a HRESULT error number into an error description.
-		 */
-		String getErrorDescription(long errorNumber) const;
-
-		/**
-		 * @brief	Sets a clip plane with the specified index.
-		 */
-		void setClipPlane(UINT16 index, float A, float B, float C, float D);
-
-		/**
-		 * @brief	Enables or disables a clip plane at the specified index.
-		 */
-		void enableClipPlane(UINT16 index, bool enable);
-
-		/**
-		 * @brief	Returns current module instance.
-		 */
-		HINSTANCE getInstanceHandle() const { return mhInstance; }
-
-		/**
-		 * @brief	Returns the D3D9 specific mode used for drawing, depending on the
-		 * 			currently set draw operation.
-		 */
-		D3DPRIMITIVETYPE getD3D9PrimitiveType() const;
-
-		/************************************************************************/
-		/* 							Sampler states                     			*/
-		/************************************************************************/
-
-		/**
-		 * @brief	Sets the texture addressing mode for a texture unit. This determines
-		 *			how are UV address values outside of [0, 1] range handled when sampling
-		 *			from texture.
-		 */
-		void setTextureAddressingMode(UINT16 stage, const UVWAddressingMode& uvw);
-
-		/**
-		 * @brief	Allows you to specify how is the texture bound to the specified texture unit filtered.
-		 *			Different filter types are used for different situations like magnifying or minifying a texture.
-		 */
-		void setTextureFiltering(UINT16 unit, FilterType ftype, FilterOptions filter);
-
-		/**
-		 * @brief	Sets anisotropy value for the specified texture unit.
-		 */
-		void setTextureAnisotropy(UINT16 unit, unsigned int maxAnisotropy);
-
-		/**
-		 * @brief	Sets the texture border color for a texture unit. Border color
-		 *			determines color returned by the texture sampler when border addressing mode
-		 *			is used and texture address is outside of [0, 1] range.
-		 */
-		void setTextureBorderColor(UINT16 stage, const Color& color);
-
-		/**
-		 * @brief	Sets the mipmap bias value for a given texture unit. 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.
-		 */
-		void setTextureMipmapBias(UINT16 unit, float bias);
-
-		/************************************************************************/
-		/* 								Blend states                      		*/
-		/************************************************************************/
-
-		/**
-		 * @brief	Sets up blending mode that allows you to combine new pixels with pixels already in the render target.
-		 *			Final pixel value = (renderTargetPixel * sourceFactor) op (pixel * destFactor).
-		 */
-		void setSceneBlending(BlendFactor sourceFactor, BlendFactor destFactor, BlendOperation op);
-
-		/**
-		* @brief	Sets up blending mode that allows you to combine new pixels with pixels already in the render target.
-		*			Allows you to set up separate blend operations for alpha values.
-		*	
-		*			Final pixel value = (renderTargetPixel * sourceFactor) op (pixel * destFactor). (And the same for alpha)
-		*/
-		void setSceneBlending(BlendFactor sourceFactor, BlendFactor destFactor, BlendFactor sourceFactorAlpha, 
-			BlendFactor destFactorAlpha, BlendOperation op, BlendOperation alphaOp);
-
-		/**
-		 * @brief	Sets alpha test that allows you to reject pixels that fail the comparison function
-		 *			versus the provided reference value.
-		 */
-		void setAlphaTest(CompareFunction func, unsigned char value);
-
-		/**
-		 * @brief	Enable alpha to coverage. 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.
-		 */
-		void setAlphaToCoverage(bool enabled);
-
-		/**
-		 * @brief	Enables or disables writing to certain color channels of the render target.
-		 */
-		void setColorBufferWriteEnabled(bool red, bool green, bool blue, bool alpha);
-
-		/************************************************************************/
-		/* 								Rasterizer states                  		*/
-		/************************************************************************/
-
-		/**
-		 * @brief	Sets vertex winding order. Normally you would use this to cull back facing
-		 *			polygons.
-		 */
-		void setCullingMode(CullingMode mode);
-
-		/**
-		 * @brief	Sets the polygon rasterization mode. Determines how are polygons interpreted.
-		 */
-		void setPolygonMode(PolygonMode level);
-
-		/**
-		 * @brief	Sets a depth bias that will offset the depth values of new pixels by the specified amount.
-		 *			Final depth bias value is a combination of the constant depth bias and slope depth bias.
-		 *			Slope depth bias has more effect the higher the slope of the rendered polygon.
-		 *
-		 * @note	This is useful if you want to avoid z fighting for objects at the same or similar depth.
-		 */
-		void setDepthBias(float constantBias, float slopeScaleBias);
-
-		/**
-		 * @brief	Scissor test allows you to mask off rendering in all but a given rectangular area
-		 * 			identified by the rectangle set by setScissorRect().
-		 */
-		void setScissorTestEnable(bool enable);
-
-		/**
-		 * @brief	Only applies when rendering to a multisample render target.
-		 * 			If disabled all of the samples will be taken from the center of the pixel,
-		 * 			effectively making the image aliased. Default value is true where samples are
-		 * 			picked randomly within the pixel.
-		 */
-		void setMultisampleAntialiasEnable(bool enable);
-
-		/**
-		 * @brief	Only applies when rendering to a non-multisample render target.
-		 * 			If enabled, lines will be antialiased. Default state is disabled.
-		 */
-		void setAntialiasedLineEnable(bool enable);
-
-		/************************************************************************/
-		/* 						Depth stencil state                      		*/
-		/************************************************************************/
-		
-		/**
-		 * @brief	Should new pixels perform depth testing using the set depth comparison function before
-		 *			being written.
-		 */
-		void setDepthBufferCheckEnabled(bool enabled = true);
-
-		/**
-		 * @brief	Should new pixels write to the depth buffer.
-		 */
-		void setDepthBufferWriteEnabled(bool enabled = true);
-
-		/**
-		 * @brief	Sets comparison function used for depth testing. Determines how are new and existing
-		 *			pixel values compared - if comparison function returns true the new pixel is written.
-		 */
-		void setDepthBufferFunction(CompareFunction func = CMPF_LESS_EQUAL);
-
-		/**
-		 * @brief	Turns stencil tests on or off. By default this is disabled.
-		 *			Stencil testing allow you to mask out a part of the rendered image by using
-		 *			various stencil operations provided.
-		 */
-		void setStencilCheckEnabled(bool enabled);
-
-		/**
-		 * @brief	Allows you to set stencil operations that are performed when stencil test passes or fails.
-		 *
-		 * @param	stencilFailOp	Operation executed when stencil test fails.
-		 * @param	depthFailOp		Operation executed when stencil test succeeds but depth test fails.
-		 * @param	passOp			Operation executed when stencil test succeeds and depth test succeeds.
-		 * @param	front			Should the stencil operations be applied to front or back facing polygons.
-		 */
-		void setStencilBufferOperations(StencilOperation stencilFailOp = SOP_KEEP,
-			StencilOperation depthFailOp = SOP_KEEP, StencilOperation passOp = SOP_KEEP,
-			bool ccw = true);
-
-		/**
-		 * @brief	Sets a stencil buffer comparison function. The result of this will cause one of 3 actions 
-		 *			depending on whether the test fails, succeeds but with the depth buffer check still failing, 
-		 *			or succeeds with the depth buffer check passing too.
-		 *
-		 * @param func	Comparison function that determines whether a stencil test fails or passes. Reference value
-		 *				gets compared to the value already in the buffer using this function.
-		 * @param ccw	If set to true, the stencil operations will be applied to counterclockwise
-		 *				faces. Otherwise they will be applied to clockwise faces.
-		 */
-		void setStencilBufferFunc(CompareFunction func = CMPF_ALWAYS_PASS, bool ccw = true);
-
-		/**
-		 * @brief	The bitmask applied to both the stencil value and the reference value
-		 *			before comparison.
-		 */
-		void setStencilBufferReadMask(UINT32 mask = 0xFFFFFFFF);
-
-		/**
-		 * @brief	The bitmask applied to the stencil value before writing it to the stencil buffer.
-		 */
-		void setStencilBufferWriteMask(UINT32 mask = 0xFFFFFFFF);
-
-		/**
-		 * @brief	Sets a reference values used for stencil buffer comparisons. 
-		 * 			Actual comparison function and stencil operations are set by setting the DepthStencilState.
-		 */
-		void setStencilRefValue(UINT32 refValue);
-
-		/**
-		 * @brief	Clears an area of the currently active render target.
-		 *
-		 * @param	buffers			Combination of one or more elements of FrameBufferType
-		 *							denoting which buffers are to be cleared.
-		 * @param	color			(optional) The color to clear the color buffer with, if enabled.
-		 * @param	depth			(optional) The value to initialize the depth buffer with, if enabled.
-		 * @param	stencil			(optional) The value to initialize the stencil buffer with, if enabled.
-		 * @param	clearArea		(optional) Area in pixels to clear.
-		 */
-		void clearArea(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0, const Rect2I& clearArea = Rect2I::EMPTY);
-
-		/**
-		 * @brief	Recalculates actual viewport dimensions based on currently 
-		 *			set viewport normalized dimensions and render target and applies
-		 *			them for further rendering.
-		 */
-		void applyViewport();
-
-		/**
-		 * @brief	Triggered when device has been lost.
-		 */
-		void notifyOnDeviceLost(D3D9Device* device);
-
-		/**
-		 * @brief	Triggered when device is being reset.
-		 */
-		void notifyOnDeviceReset(D3D9Device* device);
-
-	private:
-		/**
-		 * @brief	Holds texture unit settings.
-		 */
-		struct sD3DTextureStageDesc
-		{
-			D3D9Mappings::D3DTexType texType;
-			size_t coordIndex;
-			IDirect3DBaseTexture9 *pTex;
-			IDirect3DBaseTexture9 *pVertexTex;
-		};
-
-		static D3D9RenderAPI* msD3D9RenderSystem;
-
-		IDirect3D9*	mpD3D;
-		D3D9HLSLProgramFactory* mHLSLProgramFactory;
-		D3D9ResourceManager* mResourceManager;
-		D3D9DeviceManager* mDeviceManager;
-
-		mutable D3D9DriverList* mDriverList;
-		D3D9Driver* mActiveD3DDriver;
-
-		UINT32 mNumTexStages;
-		sD3DTextureStageDesc* mTexStageDesc;
-
-		bool mIsFrameInProgress;
-		bool mRestoreFrameOnReset;
-
-		HINSTANCE mhInstance;
-
-		Rect2 mViewportNorm;
-		UINT32 mViewportLeft, mViewportTop, mViewportWidth, mViewportHeight;
-		RECT mScissorRect;
-
-		DrawOperationType mCurrentDrawOperation;
-	};
+#pragma once
+
+#include "BsD3D9Prerequisites.h"
+#include "BsRenderAPI.h"
+#include "BsRenderAPICapabilities.h"
+#include "BsD3D9Mappings.h"
+
+namespace BansheeEngine 
+{
+	/**
+	 * @brief	Implementation of a render system using DirectX 9. Provides abstracted
+	 *			access to various low level DX9 methods.
+	 */
+	class BS_D3D9_EXPORT D3D9RenderAPI : public RenderAPICore
+	{
+	public:
+		/**
+		 * @brief	Constructs a new instance of the render system using the provided module instance.
+		 */
+		D3D9RenderAPI(HINSTANCE hInstance);
+		~D3D9RenderAPI();
+
+		/**
+		 * @copydoc RenderAPICore::getName()
+		 */
+		const StringID& getName() const override;
+
+		/**
+		 * @copydoc RenderAPICore::getShadingLanguageName()
+		 */
+		const String& getShadingLanguageName() const override;
+
+		/**
+		 * @copydoc RenderAPICore::setRenderTarget()
+		 */
+		void setRenderTarget(const SPtr<RenderTargetCore>& target, bool readOnlyDepthStencil = false) override;
+
+		/**
+		 * @copydoc RenderAPICore::bindGpuProgram()
+		 */
+		void bindGpuProgram(const SPtr<GpuProgramCore>& prg) override;
+
+		/**
+		 * @copydoc RenderAPICore::unbindGpuProgram()
+		 */
+		void unbindGpuProgram(GpuProgramType gptype) override;
+
+		/**
+		 * @copydoc RenderAPICore::setConstantBuffers()
+		 */
+		void setConstantBuffers(GpuProgramType gptype, const SPtr<GpuParamsCore>& params) override;
+
+		/**
+		 * @copydoc RenderAPICore::setVertexBuffers()
+		 */
+		void setVertexBuffers(UINT32 index, SPtr<VertexBufferCore>* buffers, UINT32 numBuffers) override;
+
+		/**
+		 * @copydoc RenderAPICore::setIndexBuffer()
+		 */
+		void setIndexBuffer(const SPtr<IndexBufferCore>& buffer) override;
+
+		/**
+		 * @copydoc RenderAPICore::setVertexDeclaration()
+		 */
+		void setVertexDeclaration(const SPtr<VertexDeclarationCore>& vertexDeclaration) override;
+
+		/**
+		 * @copydoc RenderAPICore::setDrawOperation()
+		 */
+		void setDrawOperation(DrawOperationType op) override;
+
+		/**
+		 * @copydoc RenderAPICore::setTexture()
+		 */
+		void setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr) override;
+
+		/**
+		 * @copydoc RenderAPICore::setLoadStoreTexture()
+		 */
+		void setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr,
+			const TextureSurface& surface) override;
+
+		/**
+		 * @copydoc RenderAPICore::setSamplerState()
+		 */
+		void setSamplerState(GpuProgramType gptype, UINT16 unit, const SPtr<SamplerStateCore>& state) override;
+
+		/**
+		 * @copydoc RenderAPICore::setBlendState()
+		 */
+		void setBlendState(const SPtr<BlendStateCore>& blendState) override;
+
+		/**
+		 * @copydoc RenderAPICore::setRasterizerState()
+		 */
+		void setRasterizerState(const SPtr<RasterizerStateCore>& rasterizerState) override;
+
+		/**
+		 * @copydoc RenderAPICore::setDepthStencilState()
+		 */
+		void setDepthStencilState(const SPtr<DepthStencilStateCore>& depthStencilState, UINT32 stencilRefValue) override;
+
+		/**
+		 * @copydoc RenderAPICore::setViewport()
+		 */
+		void setViewport(const Rect2& vp) override;
+
+		/**
+		 * @copydoc RenderAPICore::beginFrame()
+		 */
+		void beginFrame() override;
+
+		/**
+		 * @copydoc RenderAPICore::endFrame()
+		 */
+		void endFrame() override;
+
+		/**
+		 * @copydoc RenderAPICore::draw()
+		 */
+		void draw(UINT32 vertexOffset, UINT32 vertexCount) override;
+
+		/**
+		 * @copydoc RenderAPICore::drawIndexed()
+		 */
+		void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount) override;
+
+		/**
+		 * @copydoc RenderAPICore::setScissorRect()
+		 */
+		void setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom) override;
+
+		/**
+		 * @copydoc RenderAPICore::clearRenderTarget()
+		 */
+		void clearRenderTarget(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0) override;
+
+		/**
+		 * @copydoc RenderAPICore::clearViewport()
+		 */
+		void clearViewport(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0) override;
+
+		/**
+		 * @copydoc RenderAPICore::convertProjectionMatrix()
+		 */
+		void convertProjectionMatrix(const Matrix4& matrix, Matrix4& dest) override;
+
+		/**
+		 * @copydoc	RenderAPICore::getHorizontalTexelOffset
+		 */
+		float getHorizontalTexelOffset() override;
+
+		/**
+		 * @copydoc	RenderAPICore::getVerticalTexelOffset
+		 */
+		float getVerticalTexelOffset() override;
+
+		/**
+		 * @copydoc	RenderAPICore::getMinimumDepthInputValue
+		 */
+		float getMinimumDepthInputValue() override;
+
+		/**
+		 * @copydoc	RenderAPICore::getMaximumDepthInputValue
+		 */
+		float getMaximumDepthInputValue() override;
+
+		/**
+		 * @copydoc	RenderAPICore::getColorVertexElementType
+		 */
+		VertexElementType getColorVertexElementType() const override;
+
+		/**
+		 * @copydoc	RenderAPICore::getColorVertexElementType
+		 */
+		bool getVertexColorFlipRequired() const override { return true; }
+
+		/**
+		 * @copydoc RenderAPICore::generateParamBlockDesc()
+		 */
+		GpuParamBlockDesc generateParamBlockDesc(const String& name, Vector<GpuParamDataDesc>& params) override;
+
+		/************************************************************************/
+		/* 				Internal use by DX9 RenderAPI only                   */
+		/************************************************************************/
+
+		/**
+		 * @brief	Returns the resource manager instance.
+		 */
+		static D3D9ResourceManager* getResourceManager();
+
+		/**
+		 * @brief	Returns the device manager instance.
+		 */
+		static D3D9DeviceManager* getDeviceManager();
+
+		/**
+		 * @brief	Returns the internal DirectX 9 device object.
+		 */
+		static IDirect3D9* getDirect3D9();
+
+		/**
+		 * @brief	Returns the number of devices that resources should be created on.
+		 */
+		static UINT	getResourceCreationDeviceCount();
+
+		/**
+		 * @brief	Returns DirectX 9 device used for resource creation at the specified index.
+		 */
+		static IDirect3DDevice9* getResourceCreationDevice(UINT index);
+
+		/**
+		 * @brief	Returns the currently active DirectX 9 device.
+		 */
+		static IDirect3DDevice9* getActiveD3D9Device();
+
+		/**
+		 * @brief	Converts engine multisample options into DirectX 9 specific ones.
+		 *			Also test for multi-sample support on the device and returns nearest
+		 *			supported type if requested type is not available.
+		 *
+		 * @param	d3d9Device				Device to check for multisampling.
+		 * @param	multisampleCount		Number of requested samples.
+		 * @param	d3dPixelFormat			Pixel format used by the render target.
+		 * @param	fullscreen				Are we testing multisampling for a full-screen render target.
+		 * @param	outMultisampleType		Output parameter containing DirectX type representing valid multisample type.
+		 * @param	outMultisampleQuality	Output parameter containing multisample quality.
+		 */
+		void determineMultisampleSettings(IDirect3DDevice9* d3d9Device, UINT32 multisampleCount, D3DFORMAT d3dPixelFormat,
+			bool fullScreen, D3DMULTISAMPLE_TYPE* outMultisampleType, DWORD* outMultisampleQuality) const;
+
+		/**
+		 * @brief	Register a newly open window with the render system.
+		 */
+		void registerWindow(RenderWindowCore& renderWindow);
+
+	private:
+		friend class D3D9Texture;
+		friend class D3D9RenderWindow;
+		friend class D3D9Device;
+		friend class D3D9TextureManager;
+		friend class D3D9TextureCoreManager;
+		friend class D3D9DeviceManager;
+		friend class D3D9RenderWindowManager;
+		friend class D3D9RenderWindowCoreManager;
+
+		/**
+		 * @copydoc	RenderAPICore::initializePrepare
+		 */
+		void initializePrepare() override;
+
+		/**
+		 * @copydoc	RenderAPICore::initializeFinalize
+		 */
+		void initializeFinalize(const SPtr<RenderWindowCore>& primaryWindow) override;
+
+		/**
+		 * @copydoc	RenderAPICore::destroy_internal
+		 */
+		void destroyCore() override;
+
+		/**
+		 * @brief	Returns a list of available drivers and their properties.
+		 */
+		D3D9DriverList* getDirect3DDrivers() const;
+				
+		/**
+		 * @brief	Sets DirectX 9 render state option.
+		 */
+		HRESULT setRenderState(D3DRENDERSTATETYPE state, DWORD value);
+
+		/**
+		 * @brief	Sets DirectX 9 sampler state option for a sampler at the specified index.
+		 */
+		HRESULT setSamplerState(DWORD sampler, D3DSAMPLERSTATETYPE type, DWORD value);
+
+		/**
+		 * @brief	Sets DirectX 9 texture state option for a texture unit at the specified index.
+		 */
+		HRESULT setTextureStageState(DWORD stage, D3DTEXTURESTAGESTATETYPE type, DWORD value);
+
+		/**
+		 * @brief	Set a floating point render state option.
+		 */
+		HRESULT setFloatRenderState(D3DRENDERSTATETYPE state, float value)
+		{
+			return setRenderState(state, *((LPDWORD)(&value)));
+		}
+
+		/**
+		 * @brief	Returns currently active anisotropy level for the provided texture unit.
+		 */
+		DWORD getCurrentAnisotropy(UINT32 unit);
+
+		/**
+		 * @brief	Updates active render system capabilities. Requires active render window to check
+		 *			certain capabilities.
+		 *
+		 * @note	Also performs an initialization step when called the first time.
+		 */
+		RenderAPICapabilities* updateRenderSystemCapabilities(D3D9RenderWindowCore* renderWindow);
+
+		/**
+		 * @brief	Updates render system capabilities with vertex shader related data.
+		 */
+        void updateVertexShaderCaps(RenderAPICapabilities* rsc) const;
+
+		/**
+		 * @brief	Updates render system capabilities with pixel shader related data.
+		 */
+        void updatePixelShaderCaps(RenderAPICapabilities* rsc) const;
+
+		/**
+		 * @copydoc	RenderAPICore::setClipPlanesImpl
+		 */
+		void setClipPlanesImpl(const PlaneList& clipPlanes) override;
+
+		/**
+		 * @brief	Converts a HRESULT error number into an error description.
+		 */
+		String getErrorDescription(long errorNumber) const;
+
+		/**
+		 * @brief	Sets a clip plane with the specified index.
+		 */
+		void setClipPlane(UINT16 index, float A, float B, float C, float D);
+
+		/**
+		 * @brief	Enables or disables a clip plane at the specified index.
+		 */
+		void enableClipPlane(UINT16 index, bool enable);
+
+		/**
+		 * @brief	Returns current module instance.
+		 */
+		HINSTANCE getInstanceHandle() const { return mhInstance; }
+
+		/**
+		 * @brief	Returns the D3D9 specific mode used for drawing, depending on the
+		 * 			currently set draw operation.
+		 */
+		D3DPRIMITIVETYPE getD3D9PrimitiveType() const;
+
+		/************************************************************************/
+		/* 							Sampler states                     			*/
+		/************************************************************************/
+
+		/**
+		 * @brief	Sets the texture addressing mode for a texture unit. This determines
+		 *			how are UV address values outside of [0, 1] range handled when sampling
+		 *			from texture.
+		 */
+		void setTextureAddressingMode(UINT16 stage, const UVWAddressingMode& uvw);
+
+		/**
+		 * @brief	Allows you to specify how is the texture bound to the specified texture unit filtered.
+		 *			Different filter types are used for different situations like magnifying or minifying a texture.
+		 */
+		void setTextureFiltering(UINT16 unit, FilterType ftype, FilterOptions filter);
+
+		/**
+		 * @brief	Sets anisotropy value for the specified texture unit.
+		 */
+		void setTextureAnisotropy(UINT16 unit, unsigned int maxAnisotropy);
+
+		/**
+		 * @brief	Sets the texture border color for a texture unit. Border color
+		 *			determines color returned by the texture sampler when border addressing mode
+		 *			is used and texture address is outside of [0, 1] range.
+		 */
+		void setTextureBorderColor(UINT16 stage, const Color& color);
+
+		/**
+		 * @brief	Sets the mipmap bias value for a given texture unit. 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.
+		 */
+		void setTextureMipmapBias(UINT16 unit, float bias);
+
+		/************************************************************************/
+		/* 								Blend states                      		*/
+		/************************************************************************/
+
+		/**
+		 * @brief	Sets up blending mode that allows you to combine new pixels with pixels already in the render target.
+		 *			Final pixel value = (renderTargetPixel * sourceFactor) op (pixel * destFactor).
+		 */
+		void setSceneBlending(BlendFactor sourceFactor, BlendFactor destFactor, BlendOperation op);
+
+		/**
+		* @brief	Sets up blending mode that allows you to combine new pixels with pixels already in the render target.
+		*			Allows you to set up separate blend operations for alpha values.
+		*	
+		*			Final pixel value = (renderTargetPixel * sourceFactor) op (pixel * destFactor). (And the same for alpha)
+		*/
+		void setSceneBlending(BlendFactor sourceFactor, BlendFactor destFactor, BlendFactor sourceFactorAlpha, 
+			BlendFactor destFactorAlpha, BlendOperation op, BlendOperation alphaOp);
+
+		/**
+		 * @brief	Sets alpha test that allows you to reject pixels that fail the comparison function
+		 *			versus the provided reference value.
+		 */
+		void setAlphaTest(CompareFunction func, unsigned char value);
+
+		/**
+		 * @brief	Enable alpha to coverage. 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.
+		 */
+		void setAlphaToCoverage(bool enabled);
+
+		/**
+		 * @brief	Enables or disables writing to certain color channels of the render target.
+		 */
+		void setColorBufferWriteEnabled(bool red, bool green, bool blue, bool alpha);
+
+		/************************************************************************/
+		/* 								Rasterizer states                  		*/
+		/************************************************************************/
+
+		/**
+		 * @brief	Sets vertex winding order. Normally you would use this to cull back facing
+		 *			polygons.
+		 */
+		void setCullingMode(CullingMode mode);
+
+		/**
+		 * @brief	Sets the polygon rasterization mode. Determines how are polygons interpreted.
+		 */
+		void setPolygonMode(PolygonMode level);
+
+		/**
+		 * @brief	Sets a depth bias that will offset the depth values of new pixels by the specified amount.
+		 *			Final depth bias value is a combination of the constant depth bias and slope depth bias.
+		 *			Slope depth bias has more effect the higher the slope of the rendered polygon.
+		 *
+		 * @note	This is useful if you want to avoid z fighting for objects at the same or similar depth.
+		 */
+		void setDepthBias(float constantBias, float slopeScaleBias);
+
+		/**
+		 * @brief	Scissor test allows you to mask off rendering in all but a given rectangular area
+		 * 			identified by the rectangle set by setScissorRect().
+		 */
+		void setScissorTestEnable(bool enable);
+
+		/**
+		 * @brief	Only applies when rendering to a multisample render target.
+		 * 			If disabled all of the samples will be taken from the center of the pixel,
+		 * 			effectively making the image aliased. Default value is true where samples are
+		 * 			picked randomly within the pixel.
+		 */
+		void setMultisampleAntialiasEnable(bool enable);
+
+		/**
+		 * @brief	Only applies when rendering to a non-multisample render target.
+		 * 			If enabled, lines will be antialiased. Default state is disabled.
+		 */
+		void setAntialiasedLineEnable(bool enable);
+
+		/************************************************************************/
+		/* 						Depth stencil state                      		*/
+		/************************************************************************/
+		
+		/**
+		 * @brief	Should new pixels perform depth testing using the set depth comparison function before
+		 *			being written.
+		 */
+		void setDepthBufferCheckEnabled(bool enabled = true);
+
+		/**
+		 * @brief	Should new pixels write to the depth buffer.
+		 */
+		void setDepthBufferWriteEnabled(bool enabled = true);
+
+		/**
+		 * @brief	Sets comparison function used for depth testing. Determines how are new and existing
+		 *			pixel values compared - if comparison function returns true the new pixel is written.
+		 */
+		void setDepthBufferFunction(CompareFunction func = CMPF_LESS_EQUAL);
+
+		/**
+		 * @brief	Turns stencil tests on or off. By default this is disabled.
+		 *			Stencil testing allow you to mask out a part of the rendered image by using
+		 *			various stencil operations provided.
+		 */
+		void setStencilCheckEnabled(bool enabled);
+
+		/**
+		 * @brief	Allows you to set stencil operations that are performed when stencil test passes or fails.
+		 *
+		 * @param	stencilFailOp	Operation executed when stencil test fails.
+		 * @param	depthFailOp		Operation executed when stencil test succeeds but depth test fails.
+		 * @param	passOp			Operation executed when stencil test succeeds and depth test succeeds.
+		 * @param	front			Should the stencil operations be applied to front or back facing polygons.
+		 */
+		void setStencilBufferOperations(StencilOperation stencilFailOp = SOP_KEEP,
+			StencilOperation depthFailOp = SOP_KEEP, StencilOperation passOp = SOP_KEEP,
+			bool ccw = true);
+
+		/**
+		 * @brief	Sets a stencil buffer comparison function. The result of this will cause one of 3 actions 
+		 *			depending on whether the test fails, succeeds but with the depth buffer check still failing, 
+		 *			or succeeds with the depth buffer check passing too.
+		 *
+		 * @param func	Comparison function that determines whether a stencil test fails or passes. Reference value
+		 *				gets compared to the value already in the buffer using this function.
+		 * @param ccw	If set to true, the stencil operations will be applied to counterclockwise
+		 *				faces. Otherwise they will be applied to clockwise faces.
+		 */
+		void setStencilBufferFunc(CompareFunction func = CMPF_ALWAYS_PASS, bool ccw = true);
+
+		/**
+		 * @brief	The bitmask applied to both the stencil value and the reference value
+		 *			before comparison.
+		 */
+		void setStencilBufferReadMask(UINT32 mask = 0xFFFFFFFF);
+
+		/**
+		 * @brief	The bitmask applied to the stencil value before writing it to the stencil buffer.
+		 */
+		void setStencilBufferWriteMask(UINT32 mask = 0xFFFFFFFF);
+
+		/**
+		 * @brief	Sets a reference values used for stencil buffer comparisons. 
+		 * 			Actual comparison function and stencil operations are set by setting the DepthStencilState.
+		 */
+		void setStencilRefValue(UINT32 refValue);
+
+		/**
+		 * @brief	Clears an area of the currently active render target.
+		 *
+		 * @param	buffers			Combination of one or more elements of FrameBufferType
+		 *							denoting which buffers are to be cleared.
+		 * @param	color			(optional) The color to clear the color buffer with, if enabled.
+		 * @param	depth			(optional) The value to initialize the depth buffer with, if enabled.
+		 * @param	stencil			(optional) The value to initialize the stencil buffer with, if enabled.
+		 * @param	clearArea		(optional) Area in pixels to clear.
+		 */
+		void clearArea(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0, const Rect2I& clearArea = Rect2I::EMPTY);
+
+		/**
+		 * @brief	Recalculates actual viewport dimensions based on currently 
+		 *			set viewport normalized dimensions and render target and applies
+		 *			them for further rendering.
+		 */
+		void applyViewport();
+
+		/**
+		 * @brief	Triggered when device has been lost.
+		 */
+		void notifyOnDeviceLost(D3D9Device* device);
+
+		/**
+		 * @brief	Triggered when device is being reset.
+		 */
+		void notifyOnDeviceReset(D3D9Device* device);
+
+	private:
+		/**
+		 * @brief	Holds texture unit settings.
+		 */
+		struct sD3DTextureStageDesc
+		{
+			D3D9Mappings::D3DTexType texType;
+			size_t coordIndex;
+			IDirect3DBaseTexture9 *pTex;
+			IDirect3DBaseTexture9 *pVertexTex;
+		};
+
+		static D3D9RenderAPI* msD3D9RenderSystem;
+
+		IDirect3D9*	mpD3D;
+		D3D9HLSLProgramFactory* mHLSLProgramFactory;
+		D3D9ResourceManager* mResourceManager;
+		D3D9DeviceManager* mDeviceManager;
+
+		mutable D3D9DriverList* mDriverList;
+		D3D9Driver* mActiveD3DDriver;
+
+		UINT32 mNumTexStages;
+		sD3DTextureStageDesc* mTexStageDesc;
+
+		bool mIsFrameInProgress;
+		bool mRestoreFrameOnReset;
+
+		HINSTANCE mhInstance;
+
+		Rect2 mViewportNorm;
+		UINT32 mViewportLeft, mViewportTop, mViewportWidth, mViewportHeight;
+		RECT mScissorRect;
+
+		DrawOperationType mCurrentDrawOperation;
+	};
 }

+ 2316 - 2316
BansheeD3D9RenderAPI/Source/BsD3D9RenderAPI.cpp

@@ -1,2317 +1,2317 @@
-#include "BsD3D9RenderAPI.h"
-#include "BsD3D9Prerequisites.h"
-#include "BsD3D9DriverList.h"
-#include "BsD3D9Driver.h"
-#include "BsD3D9RenderWindow.h"
-#include "BsD3D9TextureManager.h"
-#include "BsD3D9Texture.h"
-#include "BsMath.h"
-#include "BsD3D9HardwareBufferManager.h"
-#include "BsD3D9IndexBuffer.h"
-#include "BsD3D9VertexBuffer.h"
-#include "BsD3D9VertexDeclaration.h"
-#include "BsD3D9GpuProgram.h"
-#include "BsD3D9HLSLProgramFactory.h"
-#include "BsD3D9OcclusionQuery.h"
-#include "BsD3D9DeviceManager.h"
-#include "BsD3D9ResourceManager.h"
-#include "BsD3D9RenderWindowManager.h"
-#include "BsGpuProgramManager.h"
-#include "BsRenderStateManager.h"
-#include "BsAsyncOp.h"
-#include "BsBlendState.h"
-#include "BsRasterizerState.h"
-#include "BsDepthStencilState.h"
-#include "BsGpuParams.h"
-#include "BsGpuParamDesc.h"
-#include "BsGpuParamBlockBuffer.h"
-#include "BsCoreThread.h"
-#include "BsD3D9QueryManager.h"
-#include "BsDebug.h"
-#include "BsRenderStats.h"
-
-namespace BansheeEngine 
-{
-	D3D9RenderAPI* D3D9RenderAPI::msD3D9RenderSystem = nullptr;
-
-	D3D9RenderAPI::D3D9RenderAPI(HINSTANCE hInstance)
-		: mTexStageDesc(nullptr), mNumTexStages(0), mCurrentDrawOperation(DOT_TRIANGLE_LIST), 
-		mViewportLeft(0), mViewportTop(0), mViewportWidth(0), mViewportHeight(0),
-		mIsFrameInProgress(false), mRestoreFrameOnReset(false), mhInstance(hInstance),
-		mpD3D(nullptr), mDriverList(nullptr), mActiveD3DDriver(nullptr), mHLSLProgramFactory(nullptr),
-		mDeviceManager(nullptr), mResourceManager(nullptr), mViewportNorm(0.0f, 0.0f, 1.0f, 1.0f)
-	{
-		msD3D9RenderSystem = this;
-
-		mScissorRect.left = 0;
-		mScissorRect.right = 1280;
-		mScissorRect.top = 0;
-		mScissorRect.bottom = 720;
-	}
-
-	D3D9RenderAPI::~D3D9RenderAPI()
-	{
-
-	}
-
-	const StringID& D3D9RenderAPI::getName() const
-	{
-		static StringID strName("D3D9RenderAPI");
-		return strName;
-	}
-
-	const String& D3D9RenderAPI::getShadingLanguageName() const
-	{
-		static String strName("hlsl9");
-		return strName;
-	}
-
-	void D3D9RenderAPI::initializePrepare()
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		// Create the resource manager.
-		mResourceManager = bs_new<D3D9ResourceManager>();
-
-		// Create our Direct3D object
-		if((mpD3D = Direct3DCreate9(D3D_SDK_VERSION)) == nullptr)
-			BS_EXCEPT(InternalErrorException, "Failed to create Direct3D9 object");
-
-		// Init using current settings
-		mActiveD3DDriver = getDirect3DDrivers()->item(0); // TODO - We always use the first driver
-
-		if(mActiveD3DDriver == nullptr)
-			BS_EXCEPT(InvalidParametersException, "Problems finding requested Direct3D driver!" );
-
-		// get driver version
-		mDriverVersion.major = HIWORD(mActiveD3DDriver->getAdapterIdentifier().DriverVersion.HighPart);
-		mDriverVersion.minor = LOWORD(mActiveD3DDriver->getAdapterIdentifier().DriverVersion.HighPart);
-		mDriverVersion.release = HIWORD(mActiveD3DDriver->getAdapterIdentifier().DriverVersion.LowPart);
-		mDriverVersion.build = LOWORD(mActiveD3DDriver->getAdapterIdentifier().DriverVersion.LowPart);
-
-		mVideoModeInfo = getDirect3DDrivers()->getVideoModeInfo();
-
-		// Create the device manager.
-		mDeviceManager = bs_new<D3D9DeviceManager>();
-
-		// Also create hardware buffer manager		
-		HardwareBufferManager::startUp();
-		HardwareBufferCoreManager::startUp<D3D9HardwareBufferCoreManager>();
-
-		// Create & register HLSL factory		
-		mHLSLProgramFactory = bs_new<D3D9HLSLProgramFactory>();
-
-		// Create render window manager
-		RenderWindowManager::startUp<D3D9RenderWindowManager>(this);
-		RenderWindowCoreManager::startUp<D3D9RenderWindowCoreManager>(this);
-
-		// Create render state manager
-		RenderStateCoreManager::startUp();
-
-		RenderAPICore::initializePrepare();
-	}
-
-	void D3D9RenderAPI::initializeFinalize(const SPtr<RenderWindowCore>& primaryWindow)
-	{
-		D3D9RenderWindowCore* d3d9window = static_cast<D3D9RenderWindowCore*>(primaryWindow.get());
-		updateRenderSystemCapabilities(d3d9window);
-
-		// Create the texture manager for use by others		
-		TextureManager::startUp<D3D9TextureManager>();
-		TextureCoreManager::startUp<D3D9TextureCoreManager>();
-
-		QueryManager::startUp<D3D9QueryManager>();
-
-		RenderAPICore::initializeFinalize(primaryWindow);
-	}
-
-	void D3D9RenderAPI::destroyCore()
-	{
-		if(mTexStageDesc != nullptr)
-		{
-			bs_deleteN(mTexStageDesc, mNumTexStages);
-			mTexStageDesc = nullptr;
-		}
-
-		RenderAPICore::destroyCore();
-
-		if(mDeviceManager != nullptr)
-		{
-			bs_delete(mDeviceManager);
-			mDeviceManager = nullptr;
-		}
-
-		if(mDriverList != nullptr)
-		{
-			bs_delete(mDriverList);
-			mDriverList = nullptr;
-		}
-		mActiveD3DDriver = NULL;	
-
-		QueryManager::shutDown();
-		TextureCoreManager::shutDown();
-		TextureManager::shutDown();
-		HardwareBufferCoreManager::shutDown();
-		HardwareBufferManager::shutDown();
-		RenderWindowCoreManager::shutDown();
-		RenderWindowManager::shutDown();
-		RenderStateCoreManager::shutDown();
-
-		// Deleting the HLSL program factory
-		if (mHLSLProgramFactory)
-		{
-			GpuProgramCoreManager::instance().removeFactory(mHLSLProgramFactory);
-			bs_delete(mHLSLProgramFactory);
-			mHLSLProgramFactory = 0;
-		}
-
-		SAFE_RELEASE(mpD3D);
-
-		if(mResourceManager != nullptr)
-		{
-			bs_delete(mResourceManager);
-			mResourceManager = nullptr;
-		}
-
-		msD3D9RenderSystem = NULL;
-	}
-
-	void D3D9RenderAPI::registerWindow(RenderWindowCore& renderWindow)
-	{		
-		THROW_IF_NOT_CORE_THREAD;
-
-		D3D9RenderWindowCore* d3d9renderWindow = static_cast<D3D9RenderWindowCore*>(&renderWindow);
-
-		String msg;
-
-		mResourceManager->lockDeviceAccess();
-		mDeviceManager->linkRenderWindow(d3d9renderWindow);
-
-		mResourceManager->unlockDeviceAccess();
-	}	
-
-	void D3D9RenderAPI::bindGpuProgram(const SPtr<GpuProgramCore>& prg)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		HRESULT hr;
-		switch (prg->getProperties().getType())
-		{
-		case GPT_VERTEX_PROGRAM:
-			hr = getActiveD3D9Device()->SetVertexShader(
-				static_cast<D3D9GpuVertexProgramCore*>(prg.get())->getVertexShader());
-			if (FAILED(hr))
-			{
-				BS_EXCEPT(RenderingAPIException, "Error calling SetVertexShader");
-			}
-			break;
-		case GPT_FRAGMENT_PROGRAM:
-			hr = getActiveD3D9Device()->SetPixelShader(
-				static_cast<D3D9GpuFragmentProgramCore*>(prg.get())->getPixelShader());
-			if (FAILED(hr))
-			{
-				BS_EXCEPT(RenderingAPIException, "Error calling SetPixelShader");
-			}
-			break;
-		};
-
-		// Make sure texcoord index is equal to stage value, As SDK Doc suggests:
-		// "When rendering using vertex shaders, each stage's texture coordinate index must be set to its default value."
-		// This solves such an errors when working with the Debug runtime -
-		// "Direct3D9: (ERROR) :Stage 1 - Texture coordinate index in the stage must be equal to the stage index when programmable vertex pipeline is used".
-		for (unsigned int nStage=0; nStage < 8; ++nStage)
-			setTextureStageState(nStage, D3DTSS_TEXCOORDINDEX, nStage);
-
-		BS_INC_RENDER_STAT(NumGpuProgramBinds);
-
-		RenderAPICore::bindGpuProgram(prg);
-	}
-
-	void D3D9RenderAPI::unbindGpuProgram(GpuProgramType gptype)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		HRESULT hr;
-		switch(gptype)
-		{
-		case GPT_VERTEX_PROGRAM:
-			hr = getActiveD3D9Device()->SetVertexShader(NULL);
-			if (FAILED(hr))
-			{
-				BS_EXCEPT(RenderingAPIException, "Error resetting SetVertexShader to NULL");
-			}
-			break;
-		case GPT_FRAGMENT_PROGRAM:
-			hr = getActiveD3D9Device()->SetPixelShader(NULL);
-			if (FAILED(hr))
-			{
-				BS_EXCEPT(RenderingAPIException, "Error resetting SetPixelShader to NULL");
-			}
-			break;
-		};
-
-		BS_INC_RENDER_STAT(NumGpuProgramBinds);
-
-		RenderAPICore::unbindGpuProgram(gptype);
-	}
-
-	void D3D9RenderAPI::setConstantBuffers(GpuProgramType gptype, const SPtr<GpuParamsCore>& bindableParams)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		bindableParams->updateHardwareBuffers();
-		const GpuParamDesc& paramDesc = bindableParams->getParamDesc();
-
-		// Read all the buffer data so we can assign it. Not the most efficient way of accessing data
-		// but it is required in order to have standardized buffer interface.
-		UnorderedMap<UINT32, UINT8*> bufferData;
-
-		for(auto& curParam : paramDesc.params)
-		{
-			UINT32 paramBlockSlot = curParam.second.paramBlockSlot;
-			auto iterFind = bufferData.find(paramBlockSlot);
-
-			if(iterFind == bufferData.end())
-			{
-				SPtr<GpuParamBlockBufferCore> paramBlock = bindableParams->getParamBlockBuffer(paramBlockSlot);
-
-				UINT8* data = (UINT8*)bs_alloc(paramBlock->getSize());
-				paramBlock->readFromGPU(data);
-
-				bufferData[paramBlockSlot] = data;
-			}
-		}
-
-		HRESULT hr;
-
-		switch(gptype)
-		{
-		case GPT_VERTEX_PROGRAM:
-			{
-				for(auto iter = paramDesc.params.begin(); iter != paramDesc.params.end(); ++iter)
-				{
-					const GpuParamDataDesc& paramDesc = iter->second;
-
-					const UINT8* ptrData = bufferData[paramDesc.paramBlockSlot] + paramDesc.cpuMemOffset * sizeof(UINT32);
-
-					switch(paramDesc.type)
-					{
-					case GPDT_FLOAT1:
-					case GPDT_FLOAT2:
-					case GPDT_FLOAT3:
-					case GPDT_FLOAT4:
-					case GPDT_MATRIX_2X2:
-					case GPDT_MATRIX_2X3:
-					case GPDT_MATRIX_2X4:
-					case GPDT_MATRIX_3X2:
-					case GPDT_MATRIX_3X3:
-					case GPDT_MATRIX_3X4:
-					case GPDT_MATRIX_4X2:
-					case GPDT_MATRIX_4X3:
-					case GPDT_MATRIX_4X4:
-						{
-							UINT32 slotCount = (paramDesc.elementSize / 4) * paramDesc.arraySize;
-							assert (paramDesc.elementSize % 4 == 0 && "Should not have any elements less than 4 wide for D3D9");
-
-							if (FAILED(hr = getActiveD3D9Device()->SetVertexShaderConstantF(paramDesc.gpuMemOffset, (const float*)ptrData, slotCount))) 
-								BS_EXCEPT(RenderingAPIException, "Unable to upload vertex shader float parameters.");
-							break;
-						}
-					case GPDT_INT1:
-					case GPDT_INT2:
-					case GPDT_INT3:
-					case GPDT_INT4:
-						{
-							UINT32 slotCount = (paramDesc.elementSize / 4) * paramDesc.arraySize;
-							assert (paramDesc.elementSize % 4 == 0 && "Should not have any elements less than 4 wide for D3D9");
-
-							if (FAILED(hr = getActiveD3D9Device()->SetVertexShaderConstantI(paramDesc.gpuMemOffset, (const INT32*)ptrData, slotCount))) 
-								BS_EXCEPT(RenderingAPIException, "Unable to upload vertex shader int parameters.");
-							break;
-						}
-					case GPDT_BOOL:
-						if (FAILED(hr = getActiveD3D9Device()->SetVertexShaderConstantB(paramDesc.gpuMemOffset, (const BOOL*)ptrData, paramDesc.arraySize))) 
-							BS_EXCEPT(RenderingAPIException, "Unable to upload vertex shader bool parameters.");
-						break;
-					}
-				}
-			}
-			break;
-		case GPT_FRAGMENT_PROGRAM:
-			{
-				for(auto iter = paramDesc.params.begin(); iter != paramDesc.params.end(); ++iter)
-				{
-					const GpuParamDataDesc& paramDesc = iter->second;
-
-					const UINT8* ptrData = bufferData[paramDesc.paramBlockSlot] + paramDesc.cpuMemOffset * sizeof(UINT32);
-
-					switch(paramDesc.type)
-					{
-					case GPDT_FLOAT1:
-					case GPDT_FLOAT2:
-					case GPDT_FLOAT3:
-					case GPDT_FLOAT4:
-					case GPDT_MATRIX_2X2:
-					case GPDT_MATRIX_2X3:
-					case GPDT_MATRIX_2X4:
-					case GPDT_MATRIX_3X2:
-					case GPDT_MATRIX_3X3:
-					case GPDT_MATRIX_3X4:
-					case GPDT_MATRIX_4X2:
-					case GPDT_MATRIX_4X3:
-					case GPDT_MATRIX_4X4:
-						{
-							UINT32 slotCount = (paramDesc.elementSize / 4) * paramDesc.arraySize;
-							assert (paramDesc.elementSize % 4 == 0 && "Should not have any elements less than 4 wide for D3D9");
-
-							if (FAILED(hr = getActiveD3D9Device()->SetPixelShaderConstantF(paramDesc.gpuMemOffset, (const float*)ptrData, slotCount))) 
-								BS_EXCEPT(RenderingAPIException, "Unable to upload pixel shader float parameters.");
-							break;
-						}
-					case GPDT_INT1:
-					case GPDT_INT2:
-					case GPDT_INT3:
-					case GPDT_INT4:
-						{
-							UINT32 slotCount = (paramDesc.elementSize / 4) * paramDesc.arraySize;
-							assert (paramDesc.elementSize % 4 == 0 && "Should not have any elements less than 4 wide for D3D9");
-
-							if (FAILED(hr = getActiveD3D9Device()->SetPixelShaderConstantI(paramDesc.gpuMemOffset, (const INT32*)ptrData, slotCount))) 
-								BS_EXCEPT(RenderingAPIException, "Unable to upload pixel shader int parameters.");
-							break;
-						}
-					case GPDT_BOOL:
-						if (FAILED(hr = getActiveD3D9Device()->SetPixelShaderConstantB(paramDesc.gpuMemOffset, (const BOOL*)ptrData, paramDesc.arraySize))) 
-							BS_EXCEPT(RenderingAPIException, "Unable to upload pixel shader bool parameters.");
-						break;
-					}
-				}
-			}
-			break;
-		};
-
-		for(auto& curBufferData : bufferData)
-		{
-			bs_free(curBufferData.second);
-		}
-
-		BS_INC_RENDER_STAT(NumGpuParamBufferBinds);
-	}
-
-	void D3D9RenderAPI::setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& tex)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		if (tex != nullptr && !tex->isBindableAsShaderResource())
-			BS_EXCEPT(InvalidParametersException, "Texture you have specified cannot be bound to a shader.");
-
-		if(gptype != GPT_FRAGMENT_PROGRAM && gptype != GPT_VERTEX_PROGRAM)
-		{
-			LOGWRN("D3D9 cannot assign textures to this gpu program type: " + toString(gptype));
-			return;
-		}
-
-		if(gptype == GPT_VERTEX_PROGRAM)
-		{
-			unit = D3DVERTEXTEXTURESAMPLER0 + unit; // Vertex stage uses special samplers
-		}
-
-		HRESULT hr;
-		SPtr<D3D9TextureCore> dt = std::static_pointer_cast<D3D9TextureCore>(tex);
-		if (enabled && (dt != nullptr))
-		{
-			IDirect3DBaseTexture9 *pTex = dt->getTexture_internal();
-			if (mTexStageDesc[unit].pTex != pTex)
-			{
-				hr = getActiveD3D9Device()->SetTexture(static_cast<DWORD>(unit), pTex);
-				if( hr != S_OK )
-				{
-					String str = "Unable to set texture in D3D9";
-					BS_EXCEPT(RenderingAPIException, str);
-				}
-
-				// set stage desc.
-				mTexStageDesc[unit].pTex = pTex;
-				mTexStageDesc[unit].texType = D3D9Mappings::get(dt->getProperties().getTextureType());
-
-				// Set gamma now too
-				if (dt->isHardwareGammaReadToBeUsed())
-				{
-					setSamplerState(static_cast<DWORD>(unit), D3DSAMP_SRGBTEXTURE, TRUE);
-				}
-				else
-				{
-					setSamplerState(static_cast<DWORD>(unit), D3DSAMP_SRGBTEXTURE, FALSE);
-				}
-
-				BS_INC_RENDER_STAT(NumTextureBinds);
-				BS_INC_RENDER_STAT(NumSamplerBinds);
-			}
-		}
-		else
-		{
-			if (mTexStageDesc[unit].pTex != 0)
-			{
-				hr = getActiveD3D9Device()->SetTexture(static_cast<DWORD>(unit), 0);
-				if( hr != S_OK )
-				{
-					String str = "Unable to disable texture '" + toString(unit) + "' in D3D9";
-					BS_EXCEPT(RenderingAPIException, str);
-				}
-
-				BS_INC_RENDER_STAT(NumTextureBinds);
-			}
-
-			hr = setTextureStageState(static_cast<DWORD>(unit), D3DTSS_COLOROP, D3DTOP_DISABLE);
-			if( hr != S_OK )
-			{
-				String str = "Unable to disable texture '" + toString(unit) + "' in D3D9";
-				BS_EXCEPT(RenderingAPIException, str);
-			}
-
-			// set stage desc. to defaults
-			mTexStageDesc[unit].pTex = 0;
-			mTexStageDesc[unit].coordIndex = 0;
-			mTexStageDesc[unit].texType = D3D9Mappings::D3D_TEX_TYPE_NORMAL;
-		}
-	}
-
-	void D3D9RenderAPI::setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr,
-		const TextureSurface& surface)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		LOGWRN("Texture random load/store not supported on DX9.");
-	}
-
-	void D3D9RenderAPI::setSamplerState(GpuProgramType gptype, UINT16 unit, const SPtr<SamplerStateCore>& state)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		if(gptype != GPT_FRAGMENT_PROGRAM && gptype != GPT_VERTEX_PROGRAM)
-		{
-			LOGWRN("D3D9 doesn't support this gpu program type: " + toString(gptype));
-			return;
-		}
-
-		if(gptype == GPT_VERTEX_PROGRAM)
-		{
-			unit = D3DVERTEXTEXTURESAMPLER0 + unit; // Vertex stage uses special samplers
-		}
-
-		const SamplerProperties& sampProps = state->getProperties();
-
-		// Set texture layer filtering
-		setTextureFiltering(unit, FT_MIN, sampProps.getTextureFiltering(FT_MIN));
-		setTextureFiltering(unit, FT_MAG, sampProps.getTextureFiltering(FT_MAG));
-		setTextureFiltering(unit, FT_MIP, sampProps.getTextureFiltering(FT_MIP));
-
-		// Set texture layer filtering
-		if (sampProps.getTextureAnisotropy() > 0)
-			setTextureAnisotropy(unit, sampProps.getTextureAnisotropy());
-
-		// Set mipmap biasing
-		setTextureMipmapBias(unit, sampProps.getTextureMipmapBias());
-
-		// Texture addressing mode
-		const UVWAddressingMode& uvw = sampProps.getTextureAddressingMode();
-		setTextureAddressingMode(unit, uvw);
-
-		// Set border color
-		setTextureBorderColor(unit, sampProps.getBorderColor());
-
-		BS_INC_RENDER_STAT(NumSamplerBinds);
-	}
-
-	void D3D9RenderAPI::setBlendState(const SPtr<BlendStateCore>& blendState)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		const BlendProperties& stateProps = blendState->getProperties();
-
-		// Alpha to coverage
-		setAlphaToCoverage(stateProps.getAlphaToCoverageEnabled());
-
-		// Blend states
-		// DirectX 9 doesn't allow us to specify blend state per render target, so we just use the first one.
-		if (stateProps.getBlendEnabled(0))
-		{
-			setSceneBlending(stateProps.getSrcBlend(0), stateProps.getDstBlend(0), stateProps.getAlphaSrcBlend(0), stateProps.getAlphaDstBlend(0)
-				, stateProps.getBlendOperation(0), stateProps.getAlphaBlendOperation(0));
-		}
-		else
-		{
-			setSceneBlending(BF_ONE, BF_ZERO, BO_ADD);
-		}
-
-		// Color write mask
-		UINT8 writeMask = stateProps.getRenderTargetWriteMask(0);
-		setColorBufferWriteEnabled((writeMask & 0x1) != 0, (writeMask & 0x2) != 0, (writeMask & 0x4) != 0, (writeMask & 0x8) != 0);
-
-		BS_INC_RENDER_STAT(NumBlendStateChanges);
-	}
-
-	void D3D9RenderAPI::setRasterizerState(const SPtr<RasterizerStateCore>& rasterizerState)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		const RasterizerProperties& stateProps = rasterizerState->getProperties();
-
-		setDepthBias(stateProps.getDepthBias(), stateProps.getSlopeScaledDepthBias());
-
-		setCullingMode(stateProps.getCullMode());
-
-		setPolygonMode(stateProps.getPolygonMode());
-
-		setScissorTestEnable(stateProps.getScissorEnable());
-
-		setMultisampleAntialiasEnable(stateProps.getMultisampleEnable());
-
-		setAntialiasedLineEnable(stateProps.getAntialiasedLineEnable());
-
-		BS_INC_RENDER_STAT(NumRasterizerStateChanges);
-	}
-
-	void D3D9RenderAPI::setDepthStencilState(const SPtr<DepthStencilStateCore>& depthStencilState, UINT32 stencilRefValue)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		const DepthStencilProperties& stateProps = depthStencilState->getProperties();
-
-		// Set stencil buffer options
-		setStencilCheckEnabled(stateProps.getStencilEnable());
-
-		setStencilBufferOperations(stateProps.getStencilFrontFailOp(), stateProps.getStencilFrontZFailOp(), stateProps.getStencilFrontPassOp(), true);
-		setStencilBufferFunc(stateProps.getStencilFrontCompFunc(), true);
-
-		setStencilBufferOperations(stateProps.getStencilBackFailOp(), stateProps.getStencilBackZFailOp(), stateProps.getStencilBackPassOp(), false);
-		setStencilBufferFunc(stateProps.getStencilBackCompFunc(), false);
-
-		setStencilBufferReadMask(stateProps.getStencilReadMask());
-		setStencilBufferWriteMask(stateProps.getStencilWriteMask());
-
-		// Set depth buffer options
-		setDepthBufferCheckEnabled(stateProps.getDepthReadEnable());
-		setDepthBufferWriteEnabled(stateProps.getDepthWriteEnable());
-		setDepthBufferFunction(stateProps.getDepthComparisonFunc());
-
-		// Set stencil ref value
-		setStencilRefValue(stencilRefValue);
-
-		BS_INC_RENDER_STAT(NumDepthStencilStateChanges);
-	}
-
-	void D3D9RenderAPI::setTextureMipmapBias(UINT16 unit, float bias)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		if (mCurrentCapabilities->hasCapability(RSC_MIPMAP_LOD_BIAS))
-		{
-			// ugh - have to pass float data through DWORD with no conversion
-			HRESULT hr = setSamplerState(static_cast<DWORD>(unit), D3DSAMP_MIPMAPLODBIAS, 
-				*(DWORD*)&bias);
-			if(FAILED(hr))
-				BS_EXCEPT(RenderingAPIException, "Unable to set texture mipmap bias");
-		}
-	}
-
-	void D3D9RenderAPI::setTextureAddressingMode( UINT16 stage, 
-		const UVWAddressingMode& uvw )
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		HRESULT hr;
-		if( FAILED( hr = setSamplerState( static_cast<DWORD>(stage), D3DSAMP_ADDRESSU, D3D9Mappings::get(uvw.u, mDeviceManager->getActiveDevice()->getD3D9DeviceCaps()) ) ) )
-			BS_EXCEPT(RenderingAPIException, "Failed to set texture addressing mode for U" );
-		if( FAILED( hr = setSamplerState( static_cast<DWORD>(stage), D3DSAMP_ADDRESSV, D3D9Mappings::get(uvw.v, mDeviceManager->getActiveDevice()->getD3D9DeviceCaps()) ) ) )
-			BS_EXCEPT(RenderingAPIException, "Failed to set texture addressing mode for V");
-		if( FAILED( hr = setSamplerState( static_cast<DWORD>(stage), D3DSAMP_ADDRESSW, D3D9Mappings::get(uvw.w, mDeviceManager->getActiveDevice()->getD3D9DeviceCaps()) ) ) )
-			BS_EXCEPT(RenderingAPIException, "Failed to set texture addressing mode for W");
-	}
-
-	void D3D9RenderAPI::setTextureBorderColor(UINT16 stage, const Color& colour)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		HRESULT hr;
-		if( FAILED( hr = setSamplerState( static_cast<DWORD>(stage), D3DSAMP_BORDERCOLOR, colour.getAsBGRA()) ) )
-			BS_EXCEPT(RenderingAPIException, "Failed to set texture border colour");
-	}
-
-	void D3D9RenderAPI::setSceneBlending( BlendFactor sourceFactor, BlendFactor destFactor, BlendOperation op )
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		HRESULT hr;
-		if( sourceFactor == BF_ONE && destFactor == BF_ZERO)
-		{
-			if (FAILED(hr = setRenderState(D3DRS_ALPHABLENDENABLE, FALSE)))
-				BS_EXCEPT(RenderingAPIException, "Failed to set alpha blending option");
-		}
-		else
-		{
-			if (FAILED(hr = setRenderState(D3DRS_ALPHABLENDENABLE, TRUE)))
-				BS_EXCEPT(RenderingAPIException, "Failed to set alpha blending option");
-			if (FAILED(hr = setRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE)))
-				BS_EXCEPT(RenderingAPIException, "Failed to set separate alpha blending option");
-			if( FAILED( hr = setRenderState( D3DRS_SRCBLEND, D3D9Mappings::get(sourceFactor) ) ) )
-				BS_EXCEPT(RenderingAPIException, "Failed to set source blend");
-			if( FAILED( hr = setRenderState( D3DRS_DESTBLEND, D3D9Mappings::get(destFactor) ) ) )
-				BS_EXCEPT(RenderingAPIException, "Failed to set destination blend");
-		}
-
-		if (FAILED(hr = setRenderState(D3DRS_BLENDOP, D3D9Mappings::get(op))))
-			BS_EXCEPT(RenderingAPIException, "Failed to set scene blending operation option");
-		if (FAILED(hr = setRenderState(D3DRS_BLENDOPALPHA, D3D9Mappings::get(op))))
-			BS_EXCEPT(RenderingAPIException, "Failed to set scene blending operation option");
-	}
-
-	void D3D9RenderAPI::setSceneBlending( BlendFactor sourceFactor, BlendFactor destFactor, BlendFactor sourceFactorAlpha, 
-		BlendFactor destFactorAlpha, BlendOperation op, BlendOperation alphaOp )
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		HRESULT hr;
-		if( sourceFactor == BF_ONE && destFactor == BF_ZERO && 
-			sourceFactorAlpha == BF_ONE && destFactorAlpha == BF_ZERO)
-		{
-			if (FAILED(hr = setRenderState(D3DRS_ALPHABLENDENABLE, FALSE)))
-				BS_EXCEPT(RenderingAPIException, "Failed to set alpha blending option");
-		}
-		else
-		{
-			if (FAILED(hr = setRenderState(D3DRS_ALPHABLENDENABLE, TRUE)))
-				BS_EXCEPT(RenderingAPIException, "Failed to set alpha blending option");
-			if (FAILED(hr = setRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE)))
-				BS_EXCEPT(RenderingAPIException, "Failed to set separate alpha blending option");
-			if( FAILED( hr = setRenderState( D3DRS_SRCBLEND, D3D9Mappings::get(sourceFactor) ) ) )
-				BS_EXCEPT(RenderingAPIException, "Failed to set source blend");
-			if( FAILED( hr = setRenderState( D3DRS_DESTBLEND, D3D9Mappings::get(destFactor) ) ) )
-				BS_EXCEPT(RenderingAPIException, "Failed to set destination blend");
-			if( FAILED( hr = setRenderState( D3DRS_SRCBLENDALPHA, D3D9Mappings::get(sourceFactorAlpha) ) ) )
-				BS_EXCEPT(RenderingAPIException, "Failed to set alpha source blend");
-			if( FAILED( hr = setRenderState( D3DRS_DESTBLENDALPHA, D3D9Mappings::get(destFactorAlpha) ) ) )
-				BS_EXCEPT(RenderingAPIException, "Failed to set alpha destination blend");
-		}
-
-		if (FAILED(hr = setRenderState(D3DRS_BLENDOP, D3D9Mappings::get(op))))
-			BS_EXCEPT(RenderingAPIException, "Failed to set scene blending operation option");
-		if (FAILED(hr = setRenderState(D3DRS_BLENDOPALPHA, D3D9Mappings::get(alphaOp))))
-			BS_EXCEPT(RenderingAPIException, "Failed to set alpha scene blending operation option");
-	}
-
-	void D3D9RenderAPI::setAlphaTest(CompareFunction func, unsigned char value)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		HRESULT hr;
-
-		if (func != CMPF_ALWAYS_PASS)
-		{
-			if( FAILED( hr = setRenderState( D3DRS_ALPHATESTENABLE,  TRUE ) ) )
-				BS_EXCEPT(RenderingAPIException, "Failed to enable alpha testing");
-		}
-		else
-		{
-			if( FAILED( hr = setRenderState( D3DRS_ALPHATESTENABLE,  FALSE ) ) )
-				BS_EXCEPT(RenderingAPIException, "Failed to disable alpha testing");
-		}
-		// Set always just be sure
-		if( FAILED( hr = setRenderState( D3DRS_ALPHAFUNC, D3D9Mappings::get(func) ) ) )
-			BS_EXCEPT(RenderingAPIException, "Failed to set alpha reject function");
-		if( FAILED( hr = setRenderState( D3DRS_ALPHAREF, value ) ) )
-			BS_EXCEPT(RenderingAPIException, "Failed to set render state D3DRS_ALPHAREF");
-	}
-
-	void D3D9RenderAPI::setAlphaToCoverage(bool enable)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		HRESULT hr;
-		static bool lasta2c = false;
-
-		// Alpha to coverage
-		if (getCapabilities()->hasCapability(RSC_ALPHA_TO_COVERAGE))
-		{
-			// Vendor-specific hacks on renderstate, gotta love 'em
-			if (getCapabilities()->getVendor() == GPU_NVIDIA)
-			{
-				if (enable)
-				{
-					if( FAILED( hr = setRenderState( D3DRS_ADAPTIVETESS_Y,  (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C') ) ) )
-						BS_EXCEPT(RenderingAPIException, "Failed to set alpha to coverage option");
-				}
-				else
-				{
-					if( FAILED( hr = setRenderState( D3DRS_ADAPTIVETESS_Y,  D3DFMT_UNKNOWN ) ) )
-						BS_EXCEPT(RenderingAPIException, "Failed to set alpha to coverage option");
-				}
-
-			}
-			else if ((getCapabilities()->getVendor() == GPU_AMD))
-			{
-				if (enable)
-				{
-					if( FAILED( hr = setRenderState( D3DRS_POINTSIZE,  MAKEFOURCC('A','2','M','1') ) ) )
-						BS_EXCEPT(RenderingAPIException, "Failed to set alpha to coverage option");
-				}
-				else
-				{
-					// discovered this through trial and error, seems to work
-					if( FAILED( hr = setRenderState( D3DRS_POINTSIZE,  MAKEFOURCC('A','2','M','0') ) ) )
-						BS_EXCEPT(RenderingAPIException, "Failed to set alpha to coverage option");
-				}
-			}
-
-			lasta2c = enable;
-		}
-	}
-
-	void D3D9RenderAPI::setCullingMode(CullingMode mode)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		mCullingMode = mode;
-		HRESULT hr;
-
-		if( FAILED (hr = setRenderState(D3DRS_CULLMODE, 
-			D3D9Mappings::get(mode, false))) )
-			BS_EXCEPT(RenderingAPIException, "Failed to set culling mode");
-	}
-
-	void D3D9RenderAPI::setDepthBufferCheckEnabled(bool enabled)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		HRESULT hr;
-
-		if( enabled )
-			hr = setRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
-		else
-			hr = setRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
-
-		if(FAILED(hr))
-			BS_EXCEPT(RenderingAPIException, "Error setting depth buffer test state");
-	}
-
-	void D3D9RenderAPI::setDepthBufferWriteEnabled(bool enabled)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		HRESULT hr;
-
-		if( FAILED( hr = setRenderState( D3DRS_ZWRITEENABLE, enabled ) ) )
-			BS_EXCEPT(RenderingAPIException, "Error setting depth buffer write state");
-	}
-
-	void D3D9RenderAPI::setDepthBufferFunction(CompareFunction func)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		HRESULT hr;
-		if( FAILED( hr = setRenderState( D3DRS_ZFUNC, D3D9Mappings::get(func) ) ) )
-			BS_EXCEPT(RenderingAPIException, "Error setting depth buffer test function");
-	}
-
-	void D3D9RenderAPI::setDepthBias(float constantBias, float slopeScaleBias)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		if ((mDeviceManager->getActiveDevice()->getD3D9DeviceCaps().RasterCaps & D3DPRASTERCAPS_DEPTHBIAS) != 0)
-		{
-			// Negate bias since D3D is backward
-			constantBias = -constantBias;
-			HRESULT hr = setRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&constantBias));
-			if (FAILED(hr))
-				BS_EXCEPT(RenderingAPIException, "Error setting constant depth bias");
-		}
-
-		if ((mDeviceManager->getActiveDevice()->getD3D9DeviceCaps().RasterCaps & D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS) != 0)
-		{
-			// Negate bias since D3D is backward
-			slopeScaleBias = -slopeScaleBias;
-			HRESULT hr = setRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&slopeScaleBias));
-			if (FAILED(hr))
-				BS_EXCEPT(RenderingAPIException, "Error setting slope scale depth bias");
-		}
-
-
-	}
-
-	void D3D9RenderAPI::setColorBufferWriteEnabled(bool red, bool green, bool blue, bool alpha)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		DWORD val = 0;
-		if (red) 
-			val |= D3DCOLORWRITEENABLE_RED;
-		if (green)
-			val |= D3DCOLORWRITEENABLE_GREEN;
-		if (blue)
-			val |= D3DCOLORWRITEENABLE_BLUE;
-		if (alpha)
-			val |= D3DCOLORWRITEENABLE_ALPHA;
-
-		HRESULT hr = setRenderState(D3DRS_COLORWRITEENABLE, val); 
-		if (FAILED(hr))
-			BS_EXCEPT(RenderingAPIException, "Error setting colour write enable flags");
-	}
-
-	void D3D9RenderAPI::setPolygonMode(PolygonMode level)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		HRESULT hr = setRenderState(D3DRS_FILLMODE, D3D9Mappings::get(level));
-		if (FAILED(hr))
-			BS_EXCEPT(RenderingAPIException, "Error setting polygon mode.");
-	}
-
-	void D3D9RenderAPI::setStencilCheckEnabled(bool enabled)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		// Allow stencilling
-		HRESULT hr = setRenderState(D3DRS_STENCILENABLE, enabled);
-		if (FAILED(hr))
-			BS_EXCEPT(RenderingAPIException, "Error enabling / disabling stencilling.");
-
-		if (mCurrentCapabilities->hasCapability(RSC_TWO_SIDED_STENCIL))
-		{
-			hr = setRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
-
-			if (FAILED(hr))
-				BS_EXCEPT(RenderingAPIException, "Error setting 2-sided stencil mode.");
-		}
-		else
-		{
-			hr = setRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
-
-			if (FAILED(hr))
-				BS_EXCEPT(RenderingAPIException, "Error setting 1-sided stencil mode.");
-		}
-	}
-
-	void D3D9RenderAPI::setStencilBufferOperations(StencilOperation stencilFailOp, StencilOperation depthFailOp, StencilOperation passOp, bool ccw)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		HRESULT hr;
-
-		// 2-sided operation
-		if (ccw)
-		{
-			// fail op
-			hr = setRenderState(D3DRS_CCW_STENCILFAIL, D3D9Mappings::get(stencilFailOp));
-			if (FAILED(hr))
-				BS_EXCEPT(RenderingAPIException, "Error setting stencil fail operation (ccw).");
-
-			// depth fail op
-			hr = setRenderState(D3DRS_CCW_STENCILZFAIL, D3D9Mappings::get(depthFailOp));
-			if (FAILED(hr))
-				BS_EXCEPT(RenderingAPIException, "Error setting stencil depth fail operation (ccw).");
-
-			// pass op
-			hr = setRenderState(D3DRS_CCW_STENCILPASS, D3D9Mappings::get(passOp));
-			if (FAILED(hr))
-				BS_EXCEPT(RenderingAPIException, "Error setting stencil pass operation (ccw).");
-		}
-		else
-		{
-			// fail op
-			hr = setRenderState(D3DRS_STENCILFAIL, D3D9Mappings::get(stencilFailOp, true));
-			if (FAILED(hr))
-				BS_EXCEPT(RenderingAPIException, "Error setting stencil fail operation (cw).");
-
-			// depth fail op
-			hr = setRenderState(D3DRS_STENCILZFAIL, D3D9Mappings::get(depthFailOp, true));
-			if (FAILED(hr))
-				BS_EXCEPT(RenderingAPIException, "Error setting stencil depth fail operation (cw).");
-
-			// pass op
-			hr = setRenderState(D3DRS_STENCILPASS, D3D9Mappings::get(passOp, true));
-			if (FAILED(hr))
-				BS_EXCEPT(RenderingAPIException, "Error setting stencil pass operation (cw).");
-		}
-	}
-
-	void D3D9RenderAPI::setStencilBufferFunc(CompareFunction func, bool ccw)
-	{
-		HRESULT hr;
-		
-		if(ccw)
-			hr = setRenderState(D3DRS_CCW_STENCILFUNC, D3D9Mappings::get(func));
-		else
-			hr = setRenderState(D3DRS_STENCILFUNC, D3D9Mappings::get(func));
-
-		if (FAILED(hr))
-			BS_EXCEPT(RenderingAPIException, "Error setting stencil buffer test function.");
-	}
-
-	void D3D9RenderAPI::setStencilBufferReadMask(UINT32 mask)
-	{
-		HRESULT hr = setRenderState(D3DRS_STENCILMASK, mask);
-
-		if (FAILED(hr))
-			BS_EXCEPT(RenderingAPIException, "Error setting stencil buffer mask.");
-	}
-
-	void D3D9RenderAPI::setStencilBufferWriteMask(UINT32 mask)
-	{
-		HRESULT hr = setRenderState(D3DRS_STENCILWRITEMASK, mask);
-
-		if (FAILED(hr))
-			BS_EXCEPT(RenderingAPIException, "Error setting stencil buffer write mask.");
-	}
-
-	void D3D9RenderAPI::setStencilRefValue(UINT32 refValue)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		HRESULT hr = setRenderState(D3DRS_STENCILREF, refValue);
-		if (FAILED(hr))
-			BS_EXCEPT(RenderingAPIException, "Error setting stencil buffer reference value.");
-	}
-
-	void D3D9RenderAPI::setTextureFiltering(UINT16 unit, FilterType ftype, FilterOptions filter)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		HRESULT hr;
-		D3D9Mappings::D3DTexType texType = mTexStageDesc[unit].texType;
-		hr = setSamplerState( static_cast<DWORD>(unit), D3D9Mappings::get(ftype), 
-			D3D9Mappings::get(ftype, filter, mDeviceManager->getActiveDevice()->getD3D9DeviceCaps(), texType));
-
-		if (FAILED(hr))
-			BS_EXCEPT(RenderingAPIException, "Failed to set texture filter ");
-	}
-
-
-	void D3D9RenderAPI::setTextureAnisotropy(UINT16 unit, unsigned int maxAnisotropy)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		if (static_cast<DWORD>(maxAnisotropy) > mDeviceManager->getActiveDevice()->getD3D9DeviceCaps().MaxAnisotropy)
-			maxAnisotropy = mDeviceManager->getActiveDevice()->getD3D9DeviceCaps().MaxAnisotropy;
-
-		if (getCurrentAnisotropy(unit) != maxAnisotropy)
-			setSamplerState( static_cast<DWORD>(unit), D3DSAMP_MAXANISOTROPY, maxAnisotropy );
-	}
-
-	void D3D9RenderAPI::setRenderTarget(const SPtr<RenderTargetCore>& target)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		mActiveRenderTarget = target;
-		const RenderTargetProperties& rtProps = target->getProperties();
-
-		HRESULT hr;
-
-		// Possibly change device if the target is a window
-		if (rtProps.isWindow())
-		{
-			D3D9RenderWindowCore* window = static_cast<D3D9RenderWindowCore*>(target.get());
-			mDeviceManager->setActiveRenderTargetDevice(window->_getDevice());
-			window->_validateDevice();
-		}
-
-		// Retrieve render surfaces
-		UINT32 maxRenderTargets = mCurrentCapabilities->getNumMultiRenderTargets();
-		IDirect3DSurface9** pBack = bs_newN<IDirect3DSurface9*>(maxRenderTargets);
-		memset(pBack, 0, sizeof(IDirect3DSurface9*) * maxRenderTargets);
-		target->getCustomAttribute("DDBACKBUFFER", pBack);
-		if (!pBack[0])
-		{
-			bs_deleteN(pBack, maxRenderTargets);
-			return;
-		}
-
-		IDirect3DSurface9* pDepth = NULL;
-
-		if (!pDepth)
-			target->getCustomAttribute("D3DZBUFFER", &pDepth);
-		
-		// Bind render targets
-		for(UINT32 x = 0; x < maxRenderTargets; ++x)
-		{
-			hr = getActiveD3D9Device()->SetRenderTarget(x, pBack[x]);
-			if (FAILED(hr))
-			{
-				String msg = DXGetErrorDescription(hr);
-				BS_EXCEPT(RenderingAPIException, "Failed to setRenderTarget : " + msg);
-			}
-		}
-
-		bs_deleteN(pBack, maxRenderTargets);
-
-		hr = getActiveD3D9Device()->SetDepthStencilSurface(pDepth);
-		if (FAILED(hr))
-		{
-			String msg = DXGetErrorDescription(hr);
-			BS_EXCEPT(RenderingAPIException, "Failed to setDepthStencil : " + msg);
-		}
-
-		// Set sRGB write mode
-		setRenderState(D3DRS_SRGBWRITEENABLE, rtProps.isHwGammaEnabled());
-		applyViewport();
-
-		BS_INC_RENDER_STAT(NumRenderTargetChanges);
-	}
-
-	void D3D9RenderAPI::setViewport(const Rect2& vp)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		mViewportNorm = vp;
-		applyViewport();
-	}
-
-	void D3D9RenderAPI::beginFrame()
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		HRESULT hr;
-		if(FAILED(hr = getActiveD3D9Device()->BeginScene()))
-		{
-			String msg = DXGetErrorDescription(hr);
-			BS_EXCEPT(RenderingAPIException, "Error beginning frame :" + msg);
-		}
-
- 		mDeviceManager->getActiveDevice()->clearDeviceStreams();
-		mIsFrameInProgress = true;
-	}
-
-	void D3D9RenderAPI::endFrame()
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		HRESULT hr;
-		if(FAILED(hr = getActiveD3D9Device()->EndScene()))
-			BS_EXCEPT(RenderingAPIException, "Error ending frame");
-
-		mIsFrameInProgress = false;
-	}
-
-	void D3D9RenderAPI::setVertexDeclaration(const SPtr<VertexDeclarationCore>& decl)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		std::shared_ptr<D3D9VertexDeclarationCore> d3ddecl = std::static_pointer_cast<D3D9VertexDeclarationCore>(decl);
-
-		HRESULT hr;
-		if (FAILED(hr = getActiveD3D9Device()->SetVertexDeclaration(d3ddecl->getD3DVertexDeclaration())))
-		{
-			BS_EXCEPT(RenderingAPIException, "Unable to set D3D9 vertex declaration");
-		}
-	}
-
-	void D3D9RenderAPI::setVertexBuffers(UINT32 index, SPtr<VertexBufferCore>* buffers, UINT32 numBuffers)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		UINT32 maxBoundVertexBuffers = mCurrentCapabilities->getMaxBoundVertexBuffers();
-		if(index < 0 || (index + numBuffers) > maxBoundVertexBuffers)
-			BS_EXCEPT(InvalidParametersException, "Invalid vertex index: " + toString(index) + ". Valid range is 0 .. " + toString(maxBoundVertexBuffers - 1));
-
-		HRESULT hr;
-
-		for(UINT32 i = 0; i < numBuffers; i++)
-		{
-			if(buffers[i] != nullptr)
-			{
-				SPtr<D3D9VertexBufferCore> d3d9buf = std::static_pointer_cast<D3D9VertexBufferCore>(buffers[i]);
-				const VertexBufferProperties& vbProps = d3d9buf->getProperties();
-
-				hr = getActiveD3D9Device()->SetStreamSource(
-					static_cast<UINT>(index + i),
-					d3d9buf->getD3D9VertexBuffer(),
-					0,
-					static_cast<UINT>(vbProps.getVertexSize()) // stride
-					);
-			}
-			else
-			{
-				hr = getActiveD3D9Device()->SetStreamSource(static_cast<UINT>(index + i), nullptr, 0, 0);
-			}
-
-			if (FAILED(hr))
-				BS_EXCEPT(RenderingAPIException, "Unable to set D3D9 stream source for buffer binding");
-
-			BS_INC_RENDER_STAT(NumVertexBufferBinds);
-		}
-	}
-
-	void D3D9RenderAPI::setIndexBuffer(const SPtr<IndexBufferCore>& buffer)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		SPtr<D3D9IndexBufferCore> d3dIdxBuf = std::static_pointer_cast<D3D9IndexBufferCore>(buffer);
-
-		HRESULT hr = getActiveD3D9Device()->SetIndices( d3dIdxBuf->getD3DIndexBuffer() );
-		if (FAILED(hr))
-			BS_EXCEPT(RenderingAPIException, "Failed to set index buffer");
-
-		BS_INC_RENDER_STAT(NumIndexBufferBinds);
-	}
-
-	void D3D9RenderAPI::setDrawOperation(DrawOperationType op)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		mCurrentDrawOperation = op;
-	}
-
-	void D3D9RenderAPI::draw(UINT32 vertexOffset, UINT32 vertexCount)
-	{
-		UINT32 primCount = vertexCountToPrimCount(mCurrentDrawOperation, vertexCount);
-
-		HRESULT hr = getActiveD3D9Device()->DrawPrimitive(getD3D9PrimitiveType(), static_cast<UINT>(vertexOffset), static_cast<UINT>(primCount)); 
-
-		if(FAILED(hr))
-		{
-			String msg = DXGetErrorDescription(hr);
-			BS_EXCEPT(RenderingAPIException, "Failed to DrawPrimitive : " + msg);
-		}
-
-		BS_INC_RENDER_STAT(NumDrawCalls);
-		BS_ADD_RENDER_STAT(NumVertices, vertexCount);
-		BS_ADD_RENDER_STAT(NumPrimitives, primCount);
-	}
-
-	void D3D9RenderAPI::drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount)
-	{
-		UINT32 primCount = vertexCountToPrimCount(mCurrentDrawOperation, indexCount);
-
-		// do indexed draw operation
-		HRESULT hr = getActiveD3D9Device()->DrawIndexedPrimitive(
-			getD3D9PrimitiveType(), 
-			static_cast<UINT>(vertexOffset), 
-			0, 
-			static_cast<UINT>(vertexCount), 
-			static_cast<UINT>(startIndex), 
-			static_cast<UINT>(primCount)
-			);
-
-		if(FAILED(hr))
-		{
-			String msg = DXGetErrorDescription(hr);
-			BS_EXCEPT(RenderingAPIException, "Failed to DrawIndexedPrimitive : " + msg);
-		}
-
-		BS_INC_RENDER_STAT(NumDrawCalls);
-		BS_ADD_RENDER_STAT(NumVertices, vertexCount);
-		BS_ADD_RENDER_STAT(NumPrimitives, primCount);
-	}
-
-	void D3D9RenderAPI::setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		mScissorRect.left = static_cast<LONG>(left);
-		mScissorRect.top = static_cast<LONG>(top);
-		mScissorRect.bottom = static_cast<LONG>(bottom);
-		mScissorRect.right = static_cast<LONG>(right);
-	}
-
-	void D3D9RenderAPI::setScissorTestEnable(bool enable)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		HRESULT hr;
-		if (enable)
-		{
-			if (FAILED(hr = setRenderState(D3DRS_SCISSORTESTENABLE, TRUE)))
-			{
-				BS_EXCEPT(RenderingAPIException, "Unable to enable scissor rendering state; " + getErrorDescription(hr));
-			}
-
-			if (FAILED(hr = getActiveD3D9Device()->SetScissorRect(&mScissorRect)))
-			{
-				BS_EXCEPT(RenderingAPIException, "Unable to set scissor rectangle; " + getErrorDescription(hr));
-			}
-		}
-		else
-		{
-			if (FAILED(hr = setRenderState(D3DRS_SCISSORTESTENABLE, FALSE)))
-			{
-				BS_EXCEPT(RenderingAPIException, "Unable to disable scissor rendering state; " + getErrorDescription(hr));
-			}
-		}
-	}
-
-	void D3D9RenderAPI::setMultisampleAntialiasEnable(bool enable)
-	{
-		HRESULT hr;
-		if(enable)
-		{
-			if (FAILED(hr = setRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE)))
-			{
-				BS_EXCEPT(RenderingAPIException, "Unable to enable multisample antialiasing. Error description: " + getErrorDescription(hr));
-			}
-		}
-		else
-		{
-			if (FAILED(hr = setRenderState(D3DRS_MULTISAMPLEANTIALIAS, FALSE)))
-			{
-				BS_EXCEPT(RenderingAPIException, "Unable to disable multisample antialiasing. Error description: " + getErrorDescription(hr));
-			}
-		}
-	}
-
-	void D3D9RenderAPI::setAntialiasedLineEnable(bool enable)
-	{
-		HRESULT hr;
-		if(enable)
-		{
-			if (FAILED(hr = setRenderState(D3DRS_ANTIALIASEDLINEENABLE, TRUE)))
-			{
-				BS_EXCEPT(RenderingAPIException, "Unable to enable line antialiasing. Error description: " + getErrorDescription(hr));
-			}
-		}
-		else
-		{
-			if (FAILED(hr = setRenderState(D3DRS_ANTIALIASEDLINEENABLE, FALSE)))
-			{
-				BS_EXCEPT(RenderingAPIException, "Unable to disable line antialiasing. Error description: " + getErrorDescription(hr));
-			}
-		}
-	}
-
-	void D3D9RenderAPI::clearRenderTarget(UINT32 buffers, const Color& color, float depth, UINT16 stencil)
-	{
-		if(mActiveRenderTarget == nullptr)
-			return;
-
-		const RenderTargetProperties& rtProps = mActiveRenderTarget->getProperties();
-		Rect2I clearRect(0, 0, rtProps.getWidth(), rtProps.getHeight());
-
-		clearArea(buffers, color, depth, stencil, clearRect);
-	}
-
-	void D3D9RenderAPI::clearViewport(UINT32 buffers, const Color& color, float depth, UINT16 stencil)
-	{
-		Rect2I clearRect(mViewportLeft, mViewportTop, mViewportWidth, mViewportHeight);
-
-		clearArea(buffers, color, depth, stencil, clearRect);
-	}
-
-	void D3D9RenderAPI::clearArea(UINT32 buffers, const Color& color, float depth, UINT16 stencil, const Rect2I& clearRect)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		if(mActiveRenderTarget == nullptr)
-			return;
-
-		DWORD flags = 0;
-		if (buffers & FBT_COLOR)
-		{
-			flags |= D3DCLEAR_TARGET;
-		}
-		if (buffers & FBT_DEPTH)
-		{
-			flags |= D3DCLEAR_ZBUFFER;
-		}
-
-		// Only try to clear the stencil buffer if supported
-		if (buffers & FBT_STENCIL)
-		{
-			flags |= D3DCLEAR_STENCIL;
-		}
-
-		const RenderTargetProperties& rtProps = mActiveRenderTarget->getProperties();
-
-		bool clearEntireTarget = clearRect.width == 0 || clearRect.height == 0;
-		clearEntireTarget |= (clearRect.x == 0 && clearRect.y == 0 && clearRect.width == rtProps.getWidth() && clearRect.height == rtProps.getHeight());
-
-		if(!clearEntireTarget)
-		{
-			D3DRECT clearD3DRect;
-			clearD3DRect.x1 = (LONG)Math::clamp(clearRect.x, 0, (INT32)rtProps.getWidth() - 1);
-			clearD3DRect.x2 = (LONG)Math::clamp((INT32)clearD3DRect.x1 + clearRect.width, 0, (INT32)rtProps.getWidth() - 1);
-
-			clearD3DRect.y1 = (LONG)Math::clamp(clearRect.y, 0, (INT32)rtProps.getHeight() - 1);
-			clearD3DRect.y2 = (LONG)Math::clamp((INT32)clearD3DRect.y1 + clearRect.height, 0, (INT32)rtProps.getHeight() - 1);
-
-			HRESULT hr;
-			if(FAILED(hr = getActiveD3D9Device()->Clear(1, &clearD3DRect, flags, color.getAsBGRA(), depth, stencil)))
-			{
-				String msg = DXGetErrorDescription(hr);
-				BS_EXCEPT(RenderingAPIException, "Error clearing frame buffer : " + msg);
-			}
-		}
-		else
-		{
-			HRESULT hr;
-			if(FAILED(hr = getActiveD3D9Device()->Clear(0, nullptr, flags, color.getAsBGRA(), depth, stencil)))
-			{
-				String msg = DXGetErrorDescription(hr);
-				BS_EXCEPT(RenderingAPIException, "Error clearing frame buffer : " + msg);
-			}
-		}
-
-		BS_INC_RENDER_STAT(NumClears);
-	}
-
-	IDirect3D9*	D3D9RenderAPI::getDirect3D9()
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		return msD3D9RenderSystem->mpD3D;
-	}
-
-	UINT D3D9RenderAPI::getResourceCreationDeviceCount()
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		D3D9ResourceCreationPolicy creationPolicy = msD3D9RenderSystem->mResourceManager->getCreationPolicy();
-
-		if (creationPolicy == RCP_CREATE_ON_ACTIVE_DEVICE)
-		{
-			return 1;
-		}
-		else if (creationPolicy == RCP_CREATE_ON_ALL_DEVICES)
-		{
-			return msD3D9RenderSystem->mDeviceManager->getDeviceCount();
-		}
-
-		BS_EXCEPT(InvalidParametersException, "Invalid resource creation policy.");
-
-		return 0;
-	}
-
-	IDirect3DDevice9* D3D9RenderAPI::getResourceCreationDevice(UINT index)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		D3D9ResourceCreationPolicy creationPolicy = msD3D9RenderSystem->mResourceManager->getCreationPolicy();
-		IDirect3DDevice9* d3d9Device = NULL;
-
-		if (creationPolicy == RCP_CREATE_ON_ACTIVE_DEVICE)
-		{
-			d3d9Device = msD3D9RenderSystem->getActiveD3D9Device();
-		}
-		else if (creationPolicy == RCP_CREATE_ON_ALL_DEVICES) 
-		{
-			d3d9Device = msD3D9RenderSystem->mDeviceManager->getDevice(index)->getD3D9Device();
-		}
-		else
-		{
-			BS_EXCEPT(InvalidParametersException, "Invalid resource creation policy.");
-		}
-
-		return d3d9Device;
-	}
-
-	IDirect3DDevice9* D3D9RenderAPI::getActiveD3D9Device()
-	{	
-		THROW_IF_NOT_CORE_THREAD;
-
-		D3D9Device* activeDevice = msD3D9RenderSystem->mDeviceManager->getActiveDevice();
-		IDirect3DDevice9* d3d9Device;
-
-		d3d9Device = activeDevice->getD3D9Device();
-
-		if (d3d9Device == nullptr)
-			BS_EXCEPT(InvalidParametersException, "Current d3d9 device is null.");
-
-		return d3d9Device;
-	}	
-
-	D3D9ResourceManager* D3D9RenderAPI::getResourceManager()
-	{
-		// No need to check if we're on core thread as this is synced up internally
-
-		return msD3D9RenderSystem->mResourceManager;
-	}
-
-	D3D9DeviceManager* D3D9RenderAPI::getDeviceManager()
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		return msD3D9RenderSystem->mDeviceManager;
-	}
-
-	/************************************************************************/
-	/* 								UTILITY METHODS                    		*/
-	/************************************************************************/
-
-	float D3D9RenderAPI::getHorizontalTexelOffset()
-	{
-		// D3D considers the origin to be in the center of a pixel
-		return -0.5f;
-	}
-
-	float D3D9RenderAPI::getVerticalTexelOffset()
-	{
-		// D3D considers the origin to be in the center of a pixel
-		return -0.5f;
-	}
-
-	float D3D9RenderAPI::getMinimumDepthInputValue()
-	{
-		// Range [0.0f, 1.0f]
-		return 0.0f;
-	}
-
-	float D3D9RenderAPI::getMaximumDepthInputValue()
-	{
-		// Range [0.0f, 1.0f]
-		return 1.0f;
-	}
-
-	VertexElementType D3D9RenderAPI::getColorVertexElementType() const
-	{
-		return VET_COLOR_ARGB;
-	}
-
-	void D3D9RenderAPI::convertProjectionMatrix(const Matrix4& matrix, Matrix4& dest)
-	{
-		dest = matrix;
-
-		// Convert depth range from [-1,+1] to [0,1]
-		dest[2][0] = (dest[2][0] + dest[3][0]) / 2;
-		dest[2][1] = (dest[2][1] + dest[3][1]) / 2;
-		dest[2][2] = (dest[2][2] + dest[3][2]) / 2;
-		dest[2][3] = (dest[2][3] + dest[3][3]) / 2;
-	}
-
-	GpuParamBlockDesc D3D9RenderAPI::generateParamBlockDesc(const String& name, Vector<GpuParamDataDesc>& params)
-	{
-		GpuParamBlockDesc block;
-		block.blockSize = 0;
-		block.isShareable = true;
-		block.name = name;
-		block.slot = 0;
-
-		// DX9 doesn't natively support parameter blocks but Banshee's emulation expects everything to be 16 byte aligned.
-		// Iterate in reverse order because DX9's shader reflection API reports the variables in reverse order then they
-		// appear in code, and we want to match the auto-generated buffers that result from that layout.
-		for (auto riter = params.rbegin(); riter != params.rend(); ++riter)
-		{
-			GpuParamDataDesc& param = *riter;
-
-			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[param.type];
-			UINT32 size = typeInfo.size / 4;
-
-			UINT32 alignOffset = size % 4;
-			if (alignOffset != 0)
-				size += 4 - alignOffset;
-
-			param.elementSize = size;
-			param.arrayElementStride = size;
-			param.cpuMemOffset = block.blockSize;
-			param.gpuMemOffset = 0;
-			param.paramBlockSlot = 0;
-
-			if (param.arraySize > 0)
-				block.blockSize += size * param.arraySize;
-			else
-				block.blockSize += size;
-		}
-
-		return block;
-	}
-
-	/************************************************************************/
-	/* 								PRIVATE		                     		*/
-	/************************************************************************/
-
-	D3D9DriverList* D3D9RenderAPI::getDirect3DDrivers() const
-	{
-		if( !mDriverList )
-			mDriverList = bs_new<D3D9DriverList>();
-
-		return mDriverList;
-	}
-
-	D3DPRIMITIVETYPE D3D9RenderAPI::getD3D9PrimitiveType() const
-	{
-		switch(mCurrentDrawOperation)
-		{
-		case DOT_POINT_LIST:
-			return D3DPT_POINTLIST;
-		case DOT_LINE_LIST:
-			return D3DPT_LINELIST;
-		case DOT_LINE_STRIP:
-			return D3DPT_LINESTRIP;
-		case DOT_TRIANGLE_LIST:
-			return D3DPT_TRIANGLELIST;
-		case DOT_TRIANGLE_STRIP:
-			return D3DPT_TRIANGLESTRIP;
-		case DOT_TRIANGLE_FAN:
-			return D3DPT_TRIANGLEFAN;
-		}
-
-		return D3DPT_TRIANGLELIST;
-	}
-
-	RenderAPICapabilities* D3D9RenderAPI::updateRenderSystemCapabilities(D3D9RenderWindowCore* renderWindow)
-	{			
-		RenderAPICapabilities* rsc = mCurrentCapabilities;
-		if (rsc == nullptr)
-			rsc = bs_new<RenderAPICapabilities>();
-
-		rsc->setDriverVersion(mDriverVersion);
-		rsc->setDeviceName(mActiveD3DDriver->getDriverDescription());
-		rsc->setRenderAPIName(getName());
-
-		// Init caps to maximum.		
-		rsc->setCapability(RSC_ANISOTROPY);
-		rsc->setCapability(RSC_AUTOMIPMAP);
-		rsc->setCapability(RSC_CUBEMAPPING);			
-		rsc->setCapability(RSC_TWO_SIDED_STENCIL);		
-		rsc->setCapability(RSC_STENCIL_WRAP);
-		rsc->setCapability(RSC_HWOCCLUSION);		
-		rsc->setCapability(RSC_USER_CLIP_PLANES);			
-		rsc->setCapability(RSC_VERTEX_FORMAT_UBYTE4);			
-		rsc->setCapability(RSC_TEXTURE_3D);			
-		rsc->setCapability(RSC_NON_POWER_OF_2_TEXTURES);
-		rsc->setNumMultiRenderTargets(BS_MAX_MULTIPLE_RENDER_TARGETS);
-		rsc->setCapability(RSC_MRT_DIFFERENT_BIT_DEPTHS);		
-		rsc->setCapability(RSC_POINT_SPRITES);			
-		rsc->setCapability(RSC_POINT_EXTENDED_PARAMETERS);								
-		rsc->setMaxPointSize(10.0);
-		rsc->setCapability(RSC_MIPMAP_LOD_BIAS);				
-		rsc->setCapability(RSC_PERSTAGECONSTANT);
-		rsc->setStencilBufferBitDepth(8);
-		rsc->setCapability(RSC_ADVANCED_BLEND_OPERATIONS);
-
-		for (UINT32 i=0; i < mDeviceManager->getDeviceCount(); ++i)
-		{
-			D3D9Device* device			 = mDeviceManager->getDevice(i);
-			IDirect3DDevice9* d3d9Device = device->getD3D9Device();
-
-			IDirect3DSurface9* pSurf;
-
-
-			// Check for hardware stencil support
-			d3d9Device->GetDepthStencilSurface(&pSurf);
-
-			if (pSurf != nullptr)
-			{
-				D3DSURFACE_DESC surfDesc;
-
-				pSurf->GetDesc(&surfDesc);
-				pSurf->Release();
-			}																	
-
-			// Check for hardware occlusion support
-			HRESULT hr = d3d9Device->CreateQuery(D3DQUERYTYPE_OCCLUSION,  NULL);
-
-			if (FAILED(hr))
-				rsc->unsetCapability(RSC_HWOCCLUSION);
-		}
-
-		// Update RS caps using the minimum value found in adapter list.
-		for (unsigned int i=0; i < mDriverList->count(); ++i)
-		{
-			D3D9Driver* pCurDriver       = mDriverList->item(i);			
-			const D3DCAPS9& rkCurCaps    = pCurDriver->getD3D9DeviceCaps();
-
-			rsc->setNumTextureUnits(GPT_FRAGMENT_PROGRAM, 16); // We don't support anything lower than SM3, and 16 is the sampler count determined by the specification
-
-			rsc->setMaxBoundVertexBuffers(static_cast<UINT32>(rkCurCaps.MaxStreams));
-
-			// Check for Anisotropy.
-			if (rkCurCaps.MaxAnisotropy <= 1)
-				rsc->unsetCapability(RSC_ANISOTROPY);
-
-			// Check automatic mipmap generation.
-			if ((rkCurCaps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP) == 0)
-				rsc->unsetCapability(RSC_AUTOMIPMAP);
-
-			// Two-sided stencil
-			if ((rkCurCaps.StencilCaps & D3DSTENCILCAPS_TWOSIDED) == 0)
-				rsc->unsetCapability(RSC_TWO_SIDED_STENCIL);
-
-			// stencil wrap
-			if ((rkCurCaps.StencilCaps & D3DSTENCILCAPS_INCR) == 0 ||
-				(rkCurCaps.StencilCaps & D3DSTENCILCAPS_DECR) == 0)
-				rsc->unsetCapability(RSC_STENCIL_WRAP);
-
-			// User clip planes
-			if (rkCurCaps.MaxUserClipPlanes == 0)			
-				rsc->unsetCapability(RSC_USER_CLIP_PLANES);			
-
-			// UBYTE4 type?
-			if ((rkCurCaps.DeclTypes & D3DDTCAPS_UBYTE4) == 0)			
-				rsc->unsetCapability(RSC_VERTEX_FORMAT_UBYTE4);	
-
-			// Check cube map support.
-			if ((rkCurCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP) == 0)
-				rsc->unsetCapability(RSC_CUBEMAPPING);
-
-			// 3D textures?
-			if ((rkCurCaps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP) == 0)			
-				rsc->unsetCapability(RSC_TEXTURE_3D);			
-
-			if (rkCurCaps.TextureCaps & D3DPTEXTURECAPS_POW2)
-			{
-				// Conditional support for non POW2
-				if (!(rkCurCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL))							
-					rsc->unsetCapability(RSC_NON_POWER_OF_2_TEXTURES);				
-			}	
-
-			// Number of render targets
-			if (rkCurCaps.NumSimultaneousRTs < rsc->getNumMultiRenderTargets())
-			{
-				rsc->setNumMultiRenderTargets(std::min((UINT16)rkCurCaps.NumSimultaneousRTs, (UINT16)BS_MAX_MULTIPLE_RENDER_TARGETS));
-			}	
-
-			if((rkCurCaps.PrimitiveMiscCaps & D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS) == 0)
-			{
-				rsc->unsetCapability(RSC_MRT_DIFFERENT_BIT_DEPTHS);
-			}
-
-			// Point sprites 
-			if (rkCurCaps.MaxPointSize <= 1.0f)
-			{
-				rsc->unsetCapability(RSC_POINT_SPRITES);
-				// sprites and extended parameters go together in D3D
-				rsc->unsetCapability(RSC_POINT_EXTENDED_PARAMETERS);				
-			}
-
-			// Take the minimum point size.
-			if (rkCurCaps.MaxPointSize < rsc->getMaxPointSize())
-				rsc->setMaxPointSize(rkCurCaps.MaxPointSize);	
-
-			// Mipmap LOD biasing?
-			if ((rkCurCaps.RasterCaps & D3DPRASTERCAPS_MIPMAPLODBIAS) == 0)			
-				rsc->unsetCapability(RSC_MIPMAP_LOD_BIAS);			
-
-
-			// Do we support per-stage src_manual constants?
-			// HACK - ATI drivers seem to be buggy and don't support per-stage constants properly?
-			// TODO: move this to RSC
-			if((rkCurCaps.PrimitiveMiscCaps & D3DPMISCCAPS_PERSTAGECONSTANT) == 0)
-				rsc->unsetCapability(RSC_PERSTAGECONSTANT);
-
-			// Advanced blend operations? min max subtract rev 
-			if((rkCurCaps.PrimitiveMiscCaps & D3DPMISCCAPS_BLENDOP) == 0)
-				rsc->unsetCapability(RSC_ADVANCED_BLEND_OPERATIONS);
-		}				
-
-		// We always support compression, D3DX will decompress if device does not support
-		rsc->setCapability(RSC_TEXTURE_COMPRESSION);
-		rsc->setCapability(RSC_TEXTURE_COMPRESSION_DXT);
-
-		updateVertexShaderCaps(rsc);
-		updatePixelShaderCaps(rsc);
-
-		// Adapter details
-		const D3DADAPTER_IDENTIFIER9& adapterID = mActiveD3DDriver->getAdapterIdentifier();
-
-		// determine vendor
-		// Full list of vendors here: http://www.pcidatabase.com/vendors.php?sort=id
-		switch(adapterID.VendorId)
-		{
-		case 0x10DE:
-			rsc->setVendor(GPU_NVIDIA);
-			break;
-		case 0x1002:
-			rsc->setVendor(GPU_AMD);
-			break;
-		case 0x163C:
-		case 0x8086:
-			rsc->setVendor(GPU_INTEL);
-			break;
-		default:
-			rsc->setVendor(GPU_UNKNOWN);
-			break;
-		};
-
-		rsc->setCapability(RSC_INFINITE_FAR_PLANE);
-
-		// We always support rendertextures bigger than the frame buffer
-		rsc->setCapability(RSC_HWRENDER_TO_TEXTURE);
-
-		// Determine if any floating point texture format is supported
-		D3DFORMAT floatFormats[6] = {D3DFMT_R16F, D3DFMT_G16R16F, 
-			D3DFMT_A16B16G16R16F, D3DFMT_R32F, D3DFMT_G32R32F, 
-			D3DFMT_A32B32G32R32F};
-		IDirect3DSurface9* bbSurf;
-		renderWindow->getCustomAttribute("DDBACKBUFFER", &bbSurf);
-		D3DSURFACE_DESC bbSurfDesc;
-		bbSurf->GetDesc(&bbSurfDesc);
-
-		for (int i = 0; i < 6; ++i)
-		{
-			if (SUCCEEDED(mpD3D->CheckDeviceFormat(mActiveD3DDriver->getAdapterNumber(), 
-				D3DDEVTYPE_HAL, bbSurfDesc.Format, 
-				0, D3DRTYPE_TEXTURE, floatFormats[i])))
-			{
-				rsc->setCapability(RSC_TEXTURE_FLOAT);
-				break;
-			}
-
-		}
-
-		// Vertex textures
-		if (rsc->isShaderProfileSupported("vs_3_0"))
-		{
-			rsc->setCapability(RSC_VERTEX_TEXTURE_FETCH);
-			rsc->setNumTextureUnits(GPT_VERTEX_PROGRAM, 4);
-			rsc->setNumCombinedTextureUnits(rsc->getNumTextureUnits(GPT_FRAGMENT_PROGRAM) +
-				rsc->getNumTextureUnits(GPT_VERTEX_PROGRAM));
-		}		
-		else
-		{
-			rsc->setNumCombinedTextureUnits(rsc->getNumTextureUnits(GPT_FRAGMENT_PROGRAM));
-		}
-
-		// Check alpha to coverage support
-		// this varies per vendor! But at least SM3 is required
-		if (rsc->isShaderProfileSupported("ps_3_0"))
-		{
-			// NVIDIA needs a separate check
-			if (rsc->getVendor() == GPU_NVIDIA)
-			{
-				if (mpD3D->CheckDeviceFormat(
-					D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,D3DRTYPE_SURFACE, 
-					(D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C')) == S_OK)
-				{
-					rsc->setCapability(RSC_ALPHA_TO_COVERAGE);
-				}
-
-			}
-			else if (rsc->getVendor() == GPU_AMD)
-			{
-				// There is no check on ATI, we have to assume SM3 == support
-				rsc->setCapability(RSC_ALPHA_TO_COVERAGE);
-			}
-
-			// no other cards have Dx9 hacks for alpha to coverage, as far as I know
-		}
-
-
-		if (mCurrentCapabilities == nullptr)
-		{		
-			mCurrentCapabilities = rsc;
-			mCurrentCapabilities->addShaderProfile("hlsl");
-
-			if (mCurrentCapabilities->isShaderProfileSupported("hlsl"))
-				GpuProgramCoreManager::instance().addFactory(mHLSLProgramFactory);
-
-			mNumTexStages = mCurrentCapabilities->getNumCombinedTextureUnits();
-			mTexStageDesc = bs_newN<sD3DTextureStageDesc>(mNumTexStages);
-
-			// set stages desc. to defaults
-			for (UINT32 n = 0; n < mNumTexStages; n++)
-			{
-				mTexStageDesc[n].coordIndex = 0;
-				mTexStageDesc[n].texType = D3D9Mappings::D3D_TEX_TYPE_NORMAL;
-				mTexStageDesc[n].pTex = 0;
-				mTexStageDesc[n].pVertexTex = 0;
-			}
-		}
-
-		return rsc;
-	}
-
-	void D3D9RenderAPI::updateVertexShaderCaps(RenderAPICapabilities* rsc) const
-	{
-		UINT16 major = 0xFF;
-		UINT16 minor = 0xFF;
-		D3DCAPS9 minVSCaps;
-
-		// Find the device with the lowest vertex shader caps.
-		for (unsigned int i=0; i < mDriverList->count(); ++i)
-		{
-			D3D9Driver* pCurDriver      = mDriverList->item(i);			
-			const D3DCAPS9& rkCurCaps   = pCurDriver->getD3D9DeviceCaps();
-			UINT16 currMajor			= static_cast<UINT16>((rkCurCaps.VertexShaderVersion & 0x0000FF00) >> 8);
-			UINT16 currMinor			= static_cast<UINT16>(rkCurCaps.VertexShaderVersion & 0x000000FF);
-
-			if (currMajor < major)	
-			{
-				major = currMajor;
-				minor = currMinor;
-				minVSCaps = rkCurCaps;
-			}
-			else if (currMajor == major && currMinor < minor)
-			{
-				minor = currMinor;
-				minVSCaps = rkCurCaps;
-			}			
-		}
-
-		// In case we didn't found any vertex shader support
-		// try the IDirect3DDevice9 caps instead of the IDirect3D9
-		// software vertex processing is reported there
-		if (major == 0 && minor == 0)
-		{
-			IDirect3DDevice9* lpD3DDevice9 = getActiveD3D9Device();
-			D3DCAPS9 d3dDeviceCaps9;
-			lpD3DDevice9->GetDeviceCaps(&d3dDeviceCaps9);
-			major = static_cast<UINT16>((d3dDeviceCaps9.VertexShaderVersion & 0x0000FF00) >> 8);
-			minor = static_cast<UINT16>(d3dDeviceCaps9.VertexShaderVersion & 0x000000FF);
-		}
-
-		bool vs2x = false;
-		bool vs2a = false;
-
-		// Special case detection for vs_2_x/a support
-		if (major >= 2)
-		{
-			if ((minVSCaps.VS20Caps.Caps & D3DVS20CAPS_PREDICATION) &&
-				(minVSCaps.VS20Caps.DynamicFlowControlDepth > 0) &&
-				(minVSCaps.VS20Caps.NumTemps >= 12))
-			{
-				vs2x = true;
-			}
-
-			if ((minVSCaps.VS20Caps.Caps & D3DVS20CAPS_PREDICATION) &&
-				(minVSCaps.VS20Caps.DynamicFlowControlDepth > 0) &&
-				(minVSCaps.VS20Caps.NumTemps >= 13))
-			{
-				vs2a = true;
-			}
-		}
-
-		// Populate max param count
-		switch (major)
-		{
-		case 1:
-			// No boolean params allowed
-			rsc->setVertexProgramConstantBoolCount(0);
-			// No integer params allowed
-			rsc->setVertexProgramConstantIntCount(0);
-			// float params, always 4D
-			rsc->setVertexProgramConstantFloatCount(static_cast<UINT16>(minVSCaps.MaxVertexShaderConst));
-
-			break;
-		case 2:
-			// 16 boolean params allowed
-			rsc->setVertexProgramConstantBoolCount(16);
-			// 16 integer params allowed, 4D
-			rsc->setVertexProgramConstantIntCount(16);
-			// float params, always 4D
-			rsc->setVertexProgramConstantFloatCount(static_cast<UINT16>(minVSCaps.MaxVertexShaderConst));
-			break;
-		case 3:
-			// 16 boolean params allowed
-			rsc->setVertexProgramConstantBoolCount(16);
-			// 16 integer params allowed, 4D
-			rsc->setVertexProgramConstantIntCount(16);
-			// float params, always 4D
-			rsc->setVertexProgramConstantFloatCount(static_cast<UINT16>(minVSCaps.MaxVertexShaderConst));
-			break;
-		}
-
-		// populate syntax codes in program manager (no breaks in this one so it falls through)
-		switch(major)
-		{
-		case 3:
-			rsc->addShaderProfile("vs_3_0");
-			rsc->addGpuProgramProfile(GPP_VS_3_0, "vs_3_0");
-		case 2:
-			if (vs2x)
-			{
-				rsc->addShaderProfile("vs_2_x");
-				rsc->addGpuProgramProfile(GPP_VS_2_x, "vs_2_x");
-			}
-			if (vs2a)
-			{
-				rsc->addShaderProfile("vs_2_a");
-				rsc->addGpuProgramProfile(GPP_VS_2_a, "vs_2_a");
-			}
-
-			rsc->addShaderProfile("vs_2_0");
-			rsc->addGpuProgramProfile(GPP_VS_2_0, "vs_2_0");
-		case 1:
-			rsc->addShaderProfile("vs_1_1");
-			rsc->addGpuProgramProfile(GPP_VS_1_1, "vs_1_1");
-		}
-	}
-
-	void D3D9RenderAPI::updatePixelShaderCaps(RenderAPICapabilities* rsc) const
-	{
-		UINT16 major = 0xFF;
-		UINT16 minor = 0xFF;
-		D3DCAPS9 minPSCaps;
-
-		// Find the device with the lowest pixel shader caps.
-		for (unsigned int i=0; i < mDriverList->count(); ++i)
-		{
-			D3D9Driver* pCurDriver      = mDriverList->item(i);			
-			const D3DCAPS9& currCaps    = pCurDriver->getD3D9DeviceCaps();
-			UINT16 currMajor			= static_cast<UINT16>((currCaps.PixelShaderVersion & 0x0000FF00) >> 8);
-			UINT16 currMinor			= static_cast<UINT16>(currCaps.PixelShaderVersion & 0x000000FF);
-
-			if (currMajor < major)	
-			{
-				major = currMajor;
-				minor = currMinor;
-				minPSCaps = currCaps;
-			}
-			else if (currMajor == major && currMinor < minor)
-			{
-				minor = currMinor;
-				minPSCaps = currCaps;
-			}			
-		}
-
-		bool ps2a = false;
-		bool ps2b = false;
-		bool ps2x = false;
-
-		// Special case detection for ps_2_x/a/b support
-		if (major >= 2)
-		{
-			if ((minPSCaps.PS20Caps.Caps & D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT) &&
-				(minPSCaps.PS20Caps.NumTemps >= 32))
-			{
-				ps2b = true;
-			}
-
-			if ((minPSCaps.PS20Caps.Caps & D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT) &&
-				(minPSCaps.PS20Caps.Caps & D3DPS20CAPS_NODEPENDENTREADLIMIT) &&
-				(minPSCaps.PS20Caps.Caps & D3DPS20CAPS_ARBITRARYSWIZZLE) &&
-				(minPSCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) &&
-				(minPSCaps.PS20Caps.Caps & D3DPS20CAPS_PREDICATION) &&
-				(minPSCaps.PS20Caps.NumTemps >= 22))
-			{
-				ps2a = true;
-			}
-
-			// Does this enough?
-			if (ps2a || ps2b)
-			{
-				ps2x = true;
-			}
-		}
-
-		switch (major)
-		{
-		case 1:
-			// no boolean params allowed
-			rsc->setFragmentProgramConstantBoolCount(0);
-			// no integer params allowed
-			rsc->setFragmentProgramConstantIntCount(0);
-			// float params, always 4D
-			rsc->setFragmentProgramConstantFloatCount(8);
-			break;
-		case 2:
-			// 16 boolean params allowed
-			rsc->setFragmentProgramConstantBoolCount(16);
-			// 16 integer params allowed, 4D
-			rsc->setFragmentProgramConstantIntCount(16);
-			// float params, always 4D
-			rsc->setFragmentProgramConstantFloatCount(32);
-			break;
-		case 3:
-			// 16 boolean params allowed
-			rsc->setFragmentProgramConstantBoolCount(16);
-			// 16 integer params allowed, 4D
-			rsc->setFragmentProgramConstantIntCount(16);
-			// float params, always 4D
-			rsc->setFragmentProgramConstantFloatCount(224);
-			break;
-		}
-
-		// populate syntax codes in program manager (no breaks in this one so it falls through)
-		switch(major)
-		{
-		case 3:
-			if (minor > 0)
-			{
-				rsc->addShaderProfile("ps_3_x");
-				rsc->addGpuProgramProfile(GPP_FS_3_x, "ps_3_x");
-			}
-
-			rsc->addShaderProfile("ps_3_0");
-			rsc->addGpuProgramProfile(GPP_FS_3_0, "ps_3_0");
-		case 2:
-			if (ps2x)
-			{
-				rsc->addShaderProfile("ps_2_x");
-				rsc->addGpuProgramProfile(GPP_FS_2_x, "ps_2_x");
-			}
-			if (ps2a)
-			{
-				rsc->addShaderProfile("ps_2_a");
-				rsc->addGpuProgramProfile(GPP_FS_2_a, "ps_2_a");
-			}
-			if (ps2b)
-			{
-				rsc->addShaderProfile("ps_2_b");
-				rsc->addGpuProgramProfile(GPP_FS_2_b, "ps_2_b");
-			}
-
-			rsc->addShaderProfile("ps_2_0");
-			rsc->addGpuProgramProfile(GPP_FS_2_0, "ps_2_0");
-		case 1:
-			if (major > 1 || minor >= 4)
-			{
-				rsc->addShaderProfile("ps_1_4");
-				rsc->addGpuProgramProfile(GPP_FS_1_4, "ps_1_4");
-			}
-			if (major > 1 || minor >= 3)
-			{
-				rsc->addShaderProfile("ps_1_3");
-				rsc->addGpuProgramProfile(GPP_FS_1_3, "ps_1_3");
-			}
-			if (major > 1 || minor >= 2)
-			{
-				rsc->addShaderProfile("ps_1_2");
-				rsc->addGpuProgramProfile(GPP_FS_1_2, "ps_1_2");
-			}
-
-			rsc->addShaderProfile("ps_1_1");
-			rsc->addGpuProgramProfile(GPP_FS_1_1, "ps_1_1");
-		}
-	}
-
-	String D3D9RenderAPI::getErrorDescription(long errorNumber) const
-	{
-		const String errMsg = DXGetErrorDescription(errorNumber);
-		return errMsg;
-	}
-
-	void D3D9RenderAPI::setClipPlane (UINT16 index, float A, float B, float C, float D)
-	{
-		float plane[4] = { A, B, C, D };
-		getActiveD3D9Device()->SetClipPlane (index, plane);
-	}
-
-	void D3D9RenderAPI::enableClipPlane (UINT16 index, bool enable)
-	{
-		DWORD prev;
-		getActiveD3D9Device()->GetRenderState(D3DRS_CLIPPLANEENABLE, &prev);
-		setRenderState(D3DRS_CLIPPLANEENABLE, enable?
-			(prev | (1 << index)) : (prev & ~(1 << index)));
-	}
-
-	void D3D9RenderAPI::notifyOnDeviceLost(D3D9Device* device)
-	{	
-		if (mIsFrameInProgress)
-		{
-			endFrame();
-			mRestoreFrameOnReset = true;
-		}
-	}
-
-	void D3D9RenderAPI::notifyOnDeviceReset(D3D9Device* device)
-	{		
-		// Reset state attributes.	
-		mVertexProgramBound = false;
-		mFragmentProgramBound = false;
-
-		if (mRestoreFrameOnReset)
-		{
-			beginFrame();
-			mRestoreFrameOnReset = false;
-		}
-	}
-
-	void D3D9RenderAPI::determineMultisampleSettings(IDirect3DDevice9* d3d9Device, UINT32 multisampleCount, D3DFORMAT d3dPixelFormat, 
-		bool fullScreen, D3DMULTISAMPLE_TYPE *outMultisampleType, DWORD *outMultisampleQuality) const
-	{
-		bool tryCSAA = false; // Note: Disabled for now, but leaving the code for later so it might be useful
-		enum CSAAMode { CSAA_Normal, CSAA_Quality };
-		CSAAMode csaaMode = CSAA_Normal;
-
-		D3D9DriverList* driverList = getDirect3DDrivers();
-		D3D9Driver* deviceDriver = mActiveD3DDriver;
-		D3D9Device* device = mDeviceManager->getDeviceFromD3D9Device(d3d9Device);
-
-		for (UINT32 i = 0; i < driverList->count(); ++i)
-		{
-			D3D9Driver* currDriver = driverList->item(i);
-
-			if (currDriver->getAdapterNumber() == device->getAdapterNumber())
-			{
-				deviceDriver = currDriver;
-				break;
-			}
-		}
-
-		UINT32 origNumSamples = multisampleCount;
-		bool foundValid = false;
-		while (!foundValid)
-		{
-			// Deal with special cases
-			if (tryCSAA)
-			{
-				switch(multisampleCount)
-				{
-				case 8:
-					if (csaaMode == CSAA_Quality)
-					{
-						*outMultisampleType = D3DMULTISAMPLE_8_SAMPLES;
-						*outMultisampleQuality = 0;
-					}
-					else
-					{
-						*outMultisampleType = D3DMULTISAMPLE_4_SAMPLES;
-						*outMultisampleQuality = 2;
-					}
-					break;
-				case 16:
-					if (csaaMode == CSAA_Quality)
-					{
-						*outMultisampleType = D3DMULTISAMPLE_8_SAMPLES;
-						*outMultisampleQuality = 2;
-					}
-					else
-					{
-						*outMultisampleType = D3DMULTISAMPLE_4_SAMPLES;
-						*outMultisampleQuality = 4;
-					}
-					break;
-				}
-			}
-			else // !CSAA
-			{
-				*outMultisampleType = D3DMULTISAMPLE_NONE;
-				*outMultisampleQuality = 0;
-			}
-
-
-			HRESULT hr;
-			DWORD outQuality;
-			hr = mpD3D->CheckDeviceMultiSampleType( 
-				deviceDriver->getAdapterNumber(), 
-				D3DDEVTYPE_HAL, 
-				d3dPixelFormat, 
-				!fullScreen, 
-				*outMultisampleType, 
-				&outQuality);
-
-			if (SUCCEEDED(hr) && 
-				(!tryCSAA || outQuality > *outMultisampleQuality))
-			{
-				foundValid = true;
-			}
-			else
-			{
-				// Downgrade
-				if (tryCSAA && multisampleCount == 8)
-				{
-					// For CSAA, we'll try downgrading with quality mode at all samples.
-					// then try without quality, then drop CSAA
-					if (csaaMode == CSAA_Quality)
-					{
-						// Drop quality first
-						csaaMode = CSAA_Normal;
-					}
-					else
-					{
-						// Drop CSAA entirely 
-						tryCSAA = false;
-					}
-
-					// Return to original requested samples
-					multisampleCount = origNumSamples;
-				}
-				else
-				{
-					// Drop samples
-					multisampleCount--;
-
-					if (multisampleCount == 1)
-					{
-						// Ran out of options, no multisampling
-						multisampleCount = 0;
-						foundValid = true;
-					}
-				}
-			}
-		}
-	}
-
-	void D3D9RenderAPI::setClipPlanesImpl(const PlaneList& clipPlanes)
-	{
-		size_t i;
-		size_t numClipPlanes;
-		D3DXPLANE dx9ClipPlane;
-		DWORD mask = 0;
-		HRESULT hr;
-
-		numClipPlanes = clipPlanes.size();
-		for (i = 0; i < numClipPlanes; ++i)
-		{
-			const Plane& plane = clipPlanes[i];
-
-			dx9ClipPlane.a = plane.normal.x;
-			dx9ClipPlane.b = plane.normal.y;
-			dx9ClipPlane.c = plane.normal.z;
-			dx9ClipPlane.d = plane.d;
-
-			// TODO Low priority - Transform planes to clip space?
-
-			hr = getActiveD3D9Device()->SetClipPlane(static_cast<DWORD>(i), dx9ClipPlane);
-			if (FAILED(hr))
-			{
-				BS_EXCEPT(RenderingAPIException, "Unable to set clip plane");
-			}
-
-			mask |= (1 << i);
-		}
-
-		hr = setRenderState(D3DRS_CLIPPLANEENABLE, mask);
-		if (FAILED(hr))
-		{
-			BS_EXCEPT(RenderingAPIException, "Unable to set render state for clip planes");
-		}
-	}
-
-	HRESULT D3D9RenderAPI::setRenderState(D3DRENDERSTATETYPE state, DWORD value)
-	{
-		return getActiveD3D9Device()->SetRenderState(state, value);
-	}
-
-	HRESULT D3D9RenderAPI::setSamplerState(DWORD sampler, D3DSAMPLERSTATETYPE type, DWORD value)
-	{
-		return getActiveD3D9Device()->SetSamplerState(sampler, type, value);
-	}
-
-	HRESULT D3D9RenderAPI::setTextureStageState(DWORD stage, D3DTEXTURESTAGESTATETYPE type, DWORD value)
-	{
-		if (stage < 8)
-			return getActiveD3D9Device()->SetTextureStageState(stage, type, value);
-		else
-			return D3D_OK;
-	}
-
-	DWORD D3D9RenderAPI::getCurrentAnisotropy(UINT32 unit)
-	{
-		DWORD oldVal;
-		getActiveD3D9Device()->GetSamplerState(static_cast<DWORD>(unit), D3DSAMP_MAXANISOTROPY, &oldVal);
-		return oldVal;
-	}
-
-	void D3D9RenderAPI::applyViewport()
-	{
-		if (mActiveRenderTarget == nullptr)
-			return;
-
-		const RenderTargetProperties& rtProps = mActiveRenderTarget->getProperties();
-		D3DVIEWPORT9 d3dvp;
-		HRESULT hr;
-
-		setCullingMode(mCullingMode);
-
-		// Set viewport dimensions
-		mViewportLeft = (UINT32)(rtProps.getWidth() * mViewportNorm.x);
-		mViewportTop = (UINT32)(rtProps.getHeight() * mViewportNorm.y);
-		mViewportWidth = (UINT32)(rtProps.getWidth() * mViewportNorm.width);
-		mViewportHeight = (UINT32)(rtProps.getHeight() * mViewportNorm.height);
-
-		d3dvp.X = mViewportLeft;
-		d3dvp.Y = mViewportTop;
-		d3dvp.Width = mViewportWidth;
-		d3dvp.Height = mViewportHeight;
-		if (rtProps.requiresTextureFlipping())
-		{
-			// Convert "top-left" to "bottom-left"
-			d3dvp.Y = rtProps.getHeight() - d3dvp.Height - d3dvp.Y;
-		}
-
-		// Z-values from 0.0 to 1.0 (TODO: standardise with OpenGL)
-		d3dvp.MinZ = 0.0f;
-		d3dvp.MaxZ = 1.0f;
-
-		if (FAILED(hr = getActiveD3D9Device()->SetViewport(&d3dvp)))
-			BS_EXCEPT(RenderingAPIException, "Failed to set viewport.");
-	}
+#include "BsD3D9RenderAPI.h"
+#include "BsD3D9Prerequisites.h"
+#include "BsD3D9DriverList.h"
+#include "BsD3D9Driver.h"
+#include "BsD3D9RenderWindow.h"
+#include "BsD3D9TextureManager.h"
+#include "BsD3D9Texture.h"
+#include "BsMath.h"
+#include "BsD3D9HardwareBufferManager.h"
+#include "BsD3D9IndexBuffer.h"
+#include "BsD3D9VertexBuffer.h"
+#include "BsD3D9VertexDeclaration.h"
+#include "BsD3D9GpuProgram.h"
+#include "BsD3D9HLSLProgramFactory.h"
+#include "BsD3D9OcclusionQuery.h"
+#include "BsD3D9DeviceManager.h"
+#include "BsD3D9ResourceManager.h"
+#include "BsD3D9RenderWindowManager.h"
+#include "BsGpuProgramManager.h"
+#include "BsRenderStateManager.h"
+#include "BsAsyncOp.h"
+#include "BsBlendState.h"
+#include "BsRasterizerState.h"
+#include "BsDepthStencilState.h"
+#include "BsGpuParams.h"
+#include "BsGpuParamDesc.h"
+#include "BsGpuParamBlockBuffer.h"
+#include "BsCoreThread.h"
+#include "BsD3D9QueryManager.h"
+#include "BsDebug.h"
+#include "BsRenderStats.h"
+
+namespace BansheeEngine 
+{
+	D3D9RenderAPI* D3D9RenderAPI::msD3D9RenderSystem = nullptr;
+
+	D3D9RenderAPI::D3D9RenderAPI(HINSTANCE hInstance)
+		: mTexStageDesc(nullptr), mNumTexStages(0), mCurrentDrawOperation(DOT_TRIANGLE_LIST), 
+		mViewportLeft(0), mViewportTop(0), mViewportWidth(0), mViewportHeight(0),
+		mIsFrameInProgress(false), mRestoreFrameOnReset(false), mhInstance(hInstance),
+		mpD3D(nullptr), mDriverList(nullptr), mActiveD3DDriver(nullptr), mHLSLProgramFactory(nullptr),
+		mDeviceManager(nullptr), mResourceManager(nullptr), mViewportNorm(0.0f, 0.0f, 1.0f, 1.0f)
+	{
+		msD3D9RenderSystem = this;
+
+		mScissorRect.left = 0;
+		mScissorRect.right = 1280;
+		mScissorRect.top = 0;
+		mScissorRect.bottom = 720;
+	}
+
+	D3D9RenderAPI::~D3D9RenderAPI()
+	{
+
+	}
+
+	const StringID& D3D9RenderAPI::getName() const
+	{
+		static StringID strName("D3D9RenderAPI");
+		return strName;
+	}
+
+	const String& D3D9RenderAPI::getShadingLanguageName() const
+	{
+		static String strName("hlsl9");
+		return strName;
+	}
+
+	void D3D9RenderAPI::initializePrepare()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		// Create the resource manager.
+		mResourceManager = bs_new<D3D9ResourceManager>();
+
+		// Create our Direct3D object
+		if((mpD3D = Direct3DCreate9(D3D_SDK_VERSION)) == nullptr)
+			BS_EXCEPT(InternalErrorException, "Failed to create Direct3D9 object");
+
+		// Init using current settings
+		mActiveD3DDriver = getDirect3DDrivers()->item(0); // TODO - We always use the first driver
+
+		if(mActiveD3DDriver == nullptr)
+			BS_EXCEPT(InvalidParametersException, "Problems finding requested Direct3D driver!" );
+
+		// get driver version
+		mDriverVersion.major = HIWORD(mActiveD3DDriver->getAdapterIdentifier().DriverVersion.HighPart);
+		mDriverVersion.minor = LOWORD(mActiveD3DDriver->getAdapterIdentifier().DriverVersion.HighPart);
+		mDriverVersion.release = HIWORD(mActiveD3DDriver->getAdapterIdentifier().DriverVersion.LowPart);
+		mDriverVersion.build = LOWORD(mActiveD3DDriver->getAdapterIdentifier().DriverVersion.LowPart);
+
+		mVideoModeInfo = getDirect3DDrivers()->getVideoModeInfo();
+
+		// Create the device manager.
+		mDeviceManager = bs_new<D3D9DeviceManager>();
+
+		// Also create hardware buffer manager		
+		HardwareBufferManager::startUp();
+		HardwareBufferCoreManager::startUp<D3D9HardwareBufferCoreManager>();
+
+		// Create & register HLSL factory		
+		mHLSLProgramFactory = bs_new<D3D9HLSLProgramFactory>();
+
+		// Create render window manager
+		RenderWindowManager::startUp<D3D9RenderWindowManager>(this);
+		RenderWindowCoreManager::startUp<D3D9RenderWindowCoreManager>(this);
+
+		// Create render state manager
+		RenderStateCoreManager::startUp();
+
+		RenderAPICore::initializePrepare();
+	}
+
+	void D3D9RenderAPI::initializeFinalize(const SPtr<RenderWindowCore>& primaryWindow)
+	{
+		D3D9RenderWindowCore* d3d9window = static_cast<D3D9RenderWindowCore*>(primaryWindow.get());
+		updateRenderSystemCapabilities(d3d9window);
+
+		// Create the texture manager for use by others		
+		TextureManager::startUp<D3D9TextureManager>();
+		TextureCoreManager::startUp<D3D9TextureCoreManager>();
+
+		QueryManager::startUp<D3D9QueryManager>();
+
+		RenderAPICore::initializeFinalize(primaryWindow);
+	}
+
+	void D3D9RenderAPI::destroyCore()
+	{
+		if(mTexStageDesc != nullptr)
+		{
+			bs_deleteN(mTexStageDesc, mNumTexStages);
+			mTexStageDesc = nullptr;
+		}
+
+		RenderAPICore::destroyCore();
+
+		if(mDeviceManager != nullptr)
+		{
+			bs_delete(mDeviceManager);
+			mDeviceManager = nullptr;
+		}
+
+		if(mDriverList != nullptr)
+		{
+			bs_delete(mDriverList);
+			mDriverList = nullptr;
+		}
+		mActiveD3DDriver = NULL;	
+
+		QueryManager::shutDown();
+		TextureCoreManager::shutDown();
+		TextureManager::shutDown();
+		HardwareBufferCoreManager::shutDown();
+		HardwareBufferManager::shutDown();
+		RenderWindowCoreManager::shutDown();
+		RenderWindowManager::shutDown();
+		RenderStateCoreManager::shutDown();
+
+		// Deleting the HLSL program factory
+		if (mHLSLProgramFactory)
+		{
+			GpuProgramCoreManager::instance().removeFactory(mHLSLProgramFactory);
+			bs_delete(mHLSLProgramFactory);
+			mHLSLProgramFactory = 0;
+		}
+
+		SAFE_RELEASE(mpD3D);
+
+		if(mResourceManager != nullptr)
+		{
+			bs_delete(mResourceManager);
+			mResourceManager = nullptr;
+		}
+
+		msD3D9RenderSystem = NULL;
+	}
+
+	void D3D9RenderAPI::registerWindow(RenderWindowCore& renderWindow)
+	{		
+		THROW_IF_NOT_CORE_THREAD;
+
+		D3D9RenderWindowCore* d3d9renderWindow = static_cast<D3D9RenderWindowCore*>(&renderWindow);
+
+		String msg;
+
+		mResourceManager->lockDeviceAccess();
+		mDeviceManager->linkRenderWindow(d3d9renderWindow);
+
+		mResourceManager->unlockDeviceAccess();
+	}	
+
+	void D3D9RenderAPI::bindGpuProgram(const SPtr<GpuProgramCore>& prg)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		HRESULT hr;
+		switch (prg->getProperties().getType())
+		{
+		case GPT_VERTEX_PROGRAM:
+			hr = getActiveD3D9Device()->SetVertexShader(
+				static_cast<D3D9GpuVertexProgramCore*>(prg.get())->getVertexShader());
+			if (FAILED(hr))
+			{
+				BS_EXCEPT(RenderingAPIException, "Error calling SetVertexShader");
+			}
+			break;
+		case GPT_FRAGMENT_PROGRAM:
+			hr = getActiveD3D9Device()->SetPixelShader(
+				static_cast<D3D9GpuFragmentProgramCore*>(prg.get())->getPixelShader());
+			if (FAILED(hr))
+			{
+				BS_EXCEPT(RenderingAPIException, "Error calling SetPixelShader");
+			}
+			break;
+		};
+
+		// Make sure texcoord index is equal to stage value, As SDK Doc suggests:
+		// "When rendering using vertex shaders, each stage's texture coordinate index must be set to its default value."
+		// This solves such an errors when working with the Debug runtime -
+		// "Direct3D9: (ERROR) :Stage 1 - Texture coordinate index in the stage must be equal to the stage index when programmable vertex pipeline is used".
+		for (unsigned int nStage=0; nStage < 8; ++nStage)
+			setTextureStageState(nStage, D3DTSS_TEXCOORDINDEX, nStage);
+
+		BS_INC_RENDER_STAT(NumGpuProgramBinds);
+
+		RenderAPICore::bindGpuProgram(prg);
+	}
+
+	void D3D9RenderAPI::unbindGpuProgram(GpuProgramType gptype)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		HRESULT hr;
+		switch(gptype)
+		{
+		case GPT_VERTEX_PROGRAM:
+			hr = getActiveD3D9Device()->SetVertexShader(NULL);
+			if (FAILED(hr))
+			{
+				BS_EXCEPT(RenderingAPIException, "Error resetting SetVertexShader to NULL");
+			}
+			break;
+		case GPT_FRAGMENT_PROGRAM:
+			hr = getActiveD3D9Device()->SetPixelShader(NULL);
+			if (FAILED(hr))
+			{
+				BS_EXCEPT(RenderingAPIException, "Error resetting SetPixelShader to NULL");
+			}
+			break;
+		};
+
+		BS_INC_RENDER_STAT(NumGpuProgramBinds);
+
+		RenderAPICore::unbindGpuProgram(gptype);
+	}
+
+	void D3D9RenderAPI::setConstantBuffers(GpuProgramType gptype, const SPtr<GpuParamsCore>& bindableParams)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		bindableParams->updateHardwareBuffers();
+		const GpuParamDesc& paramDesc = bindableParams->getParamDesc();
+
+		// Read all the buffer data so we can assign it. Not the most efficient way of accessing data
+		// but it is required in order to have standardized buffer interface.
+		UnorderedMap<UINT32, UINT8*> bufferData;
+
+		for(auto& curParam : paramDesc.params)
+		{
+			UINT32 paramBlockSlot = curParam.second.paramBlockSlot;
+			auto iterFind = bufferData.find(paramBlockSlot);
+
+			if(iterFind == bufferData.end())
+			{
+				SPtr<GpuParamBlockBufferCore> paramBlock = bindableParams->getParamBlockBuffer(paramBlockSlot);
+
+				UINT8* data = (UINT8*)bs_alloc(paramBlock->getSize());
+				paramBlock->readFromGPU(data);
+
+				bufferData[paramBlockSlot] = data;
+			}
+		}
+
+		HRESULT hr;
+
+		switch(gptype)
+		{
+		case GPT_VERTEX_PROGRAM:
+			{
+				for(auto iter = paramDesc.params.begin(); iter != paramDesc.params.end(); ++iter)
+				{
+					const GpuParamDataDesc& paramDesc = iter->second;
+
+					const UINT8* ptrData = bufferData[paramDesc.paramBlockSlot] + paramDesc.cpuMemOffset * sizeof(UINT32);
+
+					switch(paramDesc.type)
+					{
+					case GPDT_FLOAT1:
+					case GPDT_FLOAT2:
+					case GPDT_FLOAT3:
+					case GPDT_FLOAT4:
+					case GPDT_MATRIX_2X2:
+					case GPDT_MATRIX_2X3:
+					case GPDT_MATRIX_2X4:
+					case GPDT_MATRIX_3X2:
+					case GPDT_MATRIX_3X3:
+					case GPDT_MATRIX_3X4:
+					case GPDT_MATRIX_4X2:
+					case GPDT_MATRIX_4X3:
+					case GPDT_MATRIX_4X4:
+						{
+							UINT32 slotCount = (paramDesc.elementSize / 4) * paramDesc.arraySize;
+							assert (paramDesc.elementSize % 4 == 0 && "Should not have any elements less than 4 wide for D3D9");
+
+							if (FAILED(hr = getActiveD3D9Device()->SetVertexShaderConstantF(paramDesc.gpuMemOffset, (const float*)ptrData, slotCount))) 
+								BS_EXCEPT(RenderingAPIException, "Unable to upload vertex shader float parameters.");
+							break;
+						}
+					case GPDT_INT1:
+					case GPDT_INT2:
+					case GPDT_INT3:
+					case GPDT_INT4:
+						{
+							UINT32 slotCount = (paramDesc.elementSize / 4) * paramDesc.arraySize;
+							assert (paramDesc.elementSize % 4 == 0 && "Should not have any elements less than 4 wide for D3D9");
+
+							if (FAILED(hr = getActiveD3D9Device()->SetVertexShaderConstantI(paramDesc.gpuMemOffset, (const INT32*)ptrData, slotCount))) 
+								BS_EXCEPT(RenderingAPIException, "Unable to upload vertex shader int parameters.");
+							break;
+						}
+					case GPDT_BOOL:
+						if (FAILED(hr = getActiveD3D9Device()->SetVertexShaderConstantB(paramDesc.gpuMemOffset, (const BOOL*)ptrData, paramDesc.arraySize))) 
+							BS_EXCEPT(RenderingAPIException, "Unable to upload vertex shader bool parameters.");
+						break;
+					}
+				}
+			}
+			break;
+		case GPT_FRAGMENT_PROGRAM:
+			{
+				for(auto iter = paramDesc.params.begin(); iter != paramDesc.params.end(); ++iter)
+				{
+					const GpuParamDataDesc& paramDesc = iter->second;
+
+					const UINT8* ptrData = bufferData[paramDesc.paramBlockSlot] + paramDesc.cpuMemOffset * sizeof(UINT32);
+
+					switch(paramDesc.type)
+					{
+					case GPDT_FLOAT1:
+					case GPDT_FLOAT2:
+					case GPDT_FLOAT3:
+					case GPDT_FLOAT4:
+					case GPDT_MATRIX_2X2:
+					case GPDT_MATRIX_2X3:
+					case GPDT_MATRIX_2X4:
+					case GPDT_MATRIX_3X2:
+					case GPDT_MATRIX_3X3:
+					case GPDT_MATRIX_3X4:
+					case GPDT_MATRIX_4X2:
+					case GPDT_MATRIX_4X3:
+					case GPDT_MATRIX_4X4:
+						{
+							UINT32 slotCount = (paramDesc.elementSize / 4) * paramDesc.arraySize;
+							assert (paramDesc.elementSize % 4 == 0 && "Should not have any elements less than 4 wide for D3D9");
+
+							if (FAILED(hr = getActiveD3D9Device()->SetPixelShaderConstantF(paramDesc.gpuMemOffset, (const float*)ptrData, slotCount))) 
+								BS_EXCEPT(RenderingAPIException, "Unable to upload pixel shader float parameters.");
+							break;
+						}
+					case GPDT_INT1:
+					case GPDT_INT2:
+					case GPDT_INT3:
+					case GPDT_INT4:
+						{
+							UINT32 slotCount = (paramDesc.elementSize / 4) * paramDesc.arraySize;
+							assert (paramDesc.elementSize % 4 == 0 && "Should not have any elements less than 4 wide for D3D9");
+
+							if (FAILED(hr = getActiveD3D9Device()->SetPixelShaderConstantI(paramDesc.gpuMemOffset, (const INT32*)ptrData, slotCount))) 
+								BS_EXCEPT(RenderingAPIException, "Unable to upload pixel shader int parameters.");
+							break;
+						}
+					case GPDT_BOOL:
+						if (FAILED(hr = getActiveD3D9Device()->SetPixelShaderConstantB(paramDesc.gpuMemOffset, (const BOOL*)ptrData, paramDesc.arraySize))) 
+							BS_EXCEPT(RenderingAPIException, "Unable to upload pixel shader bool parameters.");
+						break;
+					}
+				}
+			}
+			break;
+		};
+
+		for(auto& curBufferData : bufferData)
+		{
+			bs_free(curBufferData.second);
+		}
+
+		BS_INC_RENDER_STAT(NumGpuParamBufferBinds);
+	}
+
+	void D3D9RenderAPI::setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& tex)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		if (tex != nullptr && !tex->isBindableAsShaderResource())
+			BS_EXCEPT(InvalidParametersException, "Texture you have specified cannot be bound to a shader.");
+
+		if(gptype != GPT_FRAGMENT_PROGRAM && gptype != GPT_VERTEX_PROGRAM)
+		{
+			LOGWRN("D3D9 cannot assign textures to this gpu program type: " + toString(gptype));
+			return;
+		}
+
+		if(gptype == GPT_VERTEX_PROGRAM)
+		{
+			unit = D3DVERTEXTEXTURESAMPLER0 + unit; // Vertex stage uses special samplers
+		}
+
+		HRESULT hr;
+		SPtr<D3D9TextureCore> dt = std::static_pointer_cast<D3D9TextureCore>(tex);
+		if (enabled && (dt != nullptr))
+		{
+			IDirect3DBaseTexture9 *pTex = dt->getTexture_internal();
+			if (mTexStageDesc[unit].pTex != pTex)
+			{
+				hr = getActiveD3D9Device()->SetTexture(static_cast<DWORD>(unit), pTex);
+				if( hr != S_OK )
+				{
+					String str = "Unable to set texture in D3D9";
+					BS_EXCEPT(RenderingAPIException, str);
+				}
+
+				// set stage desc.
+				mTexStageDesc[unit].pTex = pTex;
+				mTexStageDesc[unit].texType = D3D9Mappings::get(dt->getProperties().getTextureType());
+
+				// Set gamma now too
+				if (dt->isHardwareGammaReadToBeUsed())
+				{
+					setSamplerState(static_cast<DWORD>(unit), D3DSAMP_SRGBTEXTURE, TRUE);
+				}
+				else
+				{
+					setSamplerState(static_cast<DWORD>(unit), D3DSAMP_SRGBTEXTURE, FALSE);
+				}
+
+				BS_INC_RENDER_STAT(NumTextureBinds);
+				BS_INC_RENDER_STAT(NumSamplerBinds);
+			}
+		}
+		else
+		{
+			if (mTexStageDesc[unit].pTex != 0)
+			{
+				hr = getActiveD3D9Device()->SetTexture(static_cast<DWORD>(unit), 0);
+				if( hr != S_OK )
+				{
+					String str = "Unable to disable texture '" + toString(unit) + "' in D3D9";
+					BS_EXCEPT(RenderingAPIException, str);
+				}
+
+				BS_INC_RENDER_STAT(NumTextureBinds);
+			}
+
+			hr = setTextureStageState(static_cast<DWORD>(unit), D3DTSS_COLOROP, D3DTOP_DISABLE);
+			if( hr != S_OK )
+			{
+				String str = "Unable to disable texture '" + toString(unit) + "' in D3D9";
+				BS_EXCEPT(RenderingAPIException, str);
+			}
+
+			// set stage desc. to defaults
+			mTexStageDesc[unit].pTex = 0;
+			mTexStageDesc[unit].coordIndex = 0;
+			mTexStageDesc[unit].texType = D3D9Mappings::D3D_TEX_TYPE_NORMAL;
+		}
+	}
+
+	void D3D9RenderAPI::setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr,
+		const TextureSurface& surface)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		LOGWRN("Texture random load/store not supported on DX9.");
+	}
+
+	void D3D9RenderAPI::setSamplerState(GpuProgramType gptype, UINT16 unit, const SPtr<SamplerStateCore>& state)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		if(gptype != GPT_FRAGMENT_PROGRAM && gptype != GPT_VERTEX_PROGRAM)
+		{
+			LOGWRN("D3D9 doesn't support this gpu program type: " + toString(gptype));
+			return;
+		}
+
+		if(gptype == GPT_VERTEX_PROGRAM)
+		{
+			unit = D3DVERTEXTEXTURESAMPLER0 + unit; // Vertex stage uses special samplers
+		}
+
+		const SamplerProperties& sampProps = state->getProperties();
+
+		// Set texture layer filtering
+		setTextureFiltering(unit, FT_MIN, sampProps.getTextureFiltering(FT_MIN));
+		setTextureFiltering(unit, FT_MAG, sampProps.getTextureFiltering(FT_MAG));
+		setTextureFiltering(unit, FT_MIP, sampProps.getTextureFiltering(FT_MIP));
+
+		// Set texture layer filtering
+		if (sampProps.getTextureAnisotropy() > 0)
+			setTextureAnisotropy(unit, sampProps.getTextureAnisotropy());
+
+		// Set mipmap biasing
+		setTextureMipmapBias(unit, sampProps.getTextureMipmapBias());
+
+		// Texture addressing mode
+		const UVWAddressingMode& uvw = sampProps.getTextureAddressingMode();
+		setTextureAddressingMode(unit, uvw);
+
+		// Set border color
+		setTextureBorderColor(unit, sampProps.getBorderColor());
+
+		BS_INC_RENDER_STAT(NumSamplerBinds);
+	}
+
+	void D3D9RenderAPI::setBlendState(const SPtr<BlendStateCore>& blendState)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		const BlendProperties& stateProps = blendState->getProperties();
+
+		// Alpha to coverage
+		setAlphaToCoverage(stateProps.getAlphaToCoverageEnabled());
+
+		// Blend states
+		// DirectX 9 doesn't allow us to specify blend state per render target, so we just use the first one.
+		if (stateProps.getBlendEnabled(0))
+		{
+			setSceneBlending(stateProps.getSrcBlend(0), stateProps.getDstBlend(0), stateProps.getAlphaSrcBlend(0), stateProps.getAlphaDstBlend(0)
+				, stateProps.getBlendOperation(0), stateProps.getAlphaBlendOperation(0));
+		}
+		else
+		{
+			setSceneBlending(BF_ONE, BF_ZERO, BO_ADD);
+		}
+
+		// Color write mask
+		UINT8 writeMask = stateProps.getRenderTargetWriteMask(0);
+		setColorBufferWriteEnabled((writeMask & 0x1) != 0, (writeMask & 0x2) != 0, (writeMask & 0x4) != 0, (writeMask & 0x8) != 0);
+
+		BS_INC_RENDER_STAT(NumBlendStateChanges);
+	}
+
+	void D3D9RenderAPI::setRasterizerState(const SPtr<RasterizerStateCore>& rasterizerState)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		const RasterizerProperties& stateProps = rasterizerState->getProperties();
+
+		setDepthBias(stateProps.getDepthBias(), stateProps.getSlopeScaledDepthBias());
+
+		setCullingMode(stateProps.getCullMode());
+
+		setPolygonMode(stateProps.getPolygonMode());
+
+		setScissorTestEnable(stateProps.getScissorEnable());
+
+		setMultisampleAntialiasEnable(stateProps.getMultisampleEnable());
+
+		setAntialiasedLineEnable(stateProps.getAntialiasedLineEnable());
+
+		BS_INC_RENDER_STAT(NumRasterizerStateChanges);
+	}
+
+	void D3D9RenderAPI::setDepthStencilState(const SPtr<DepthStencilStateCore>& depthStencilState, UINT32 stencilRefValue)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		const DepthStencilProperties& stateProps = depthStencilState->getProperties();
+
+		// Set stencil buffer options
+		setStencilCheckEnabled(stateProps.getStencilEnable());
+
+		setStencilBufferOperations(stateProps.getStencilFrontFailOp(), stateProps.getStencilFrontZFailOp(), stateProps.getStencilFrontPassOp(), true);
+		setStencilBufferFunc(stateProps.getStencilFrontCompFunc(), true);
+
+		setStencilBufferOperations(stateProps.getStencilBackFailOp(), stateProps.getStencilBackZFailOp(), stateProps.getStencilBackPassOp(), false);
+		setStencilBufferFunc(stateProps.getStencilBackCompFunc(), false);
+
+		setStencilBufferReadMask(stateProps.getStencilReadMask());
+		setStencilBufferWriteMask(stateProps.getStencilWriteMask());
+
+		// Set depth buffer options
+		setDepthBufferCheckEnabled(stateProps.getDepthReadEnable());
+		setDepthBufferWriteEnabled(stateProps.getDepthWriteEnable());
+		setDepthBufferFunction(stateProps.getDepthComparisonFunc());
+
+		// Set stencil ref value
+		setStencilRefValue(stencilRefValue);
+
+		BS_INC_RENDER_STAT(NumDepthStencilStateChanges);
+	}
+
+	void D3D9RenderAPI::setTextureMipmapBias(UINT16 unit, float bias)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		if (mCurrentCapabilities->hasCapability(RSC_MIPMAP_LOD_BIAS))
+		{
+			// ugh - have to pass float data through DWORD with no conversion
+			HRESULT hr = setSamplerState(static_cast<DWORD>(unit), D3DSAMP_MIPMAPLODBIAS, 
+				*(DWORD*)&bias);
+			if(FAILED(hr))
+				BS_EXCEPT(RenderingAPIException, "Unable to set texture mipmap bias");
+		}
+	}
+
+	void D3D9RenderAPI::setTextureAddressingMode( UINT16 stage, 
+		const UVWAddressingMode& uvw )
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		HRESULT hr;
+		if( FAILED( hr = setSamplerState( static_cast<DWORD>(stage), D3DSAMP_ADDRESSU, D3D9Mappings::get(uvw.u, mDeviceManager->getActiveDevice()->getD3D9DeviceCaps()) ) ) )
+			BS_EXCEPT(RenderingAPIException, "Failed to set texture addressing mode for U" );
+		if( FAILED( hr = setSamplerState( static_cast<DWORD>(stage), D3DSAMP_ADDRESSV, D3D9Mappings::get(uvw.v, mDeviceManager->getActiveDevice()->getD3D9DeviceCaps()) ) ) )
+			BS_EXCEPT(RenderingAPIException, "Failed to set texture addressing mode for V");
+		if( FAILED( hr = setSamplerState( static_cast<DWORD>(stage), D3DSAMP_ADDRESSW, D3D9Mappings::get(uvw.w, mDeviceManager->getActiveDevice()->getD3D9DeviceCaps()) ) ) )
+			BS_EXCEPT(RenderingAPIException, "Failed to set texture addressing mode for W");
+	}
+
+	void D3D9RenderAPI::setTextureBorderColor(UINT16 stage, const Color& colour)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		HRESULT hr;
+		if( FAILED( hr = setSamplerState( static_cast<DWORD>(stage), D3DSAMP_BORDERCOLOR, colour.getAsBGRA()) ) )
+			BS_EXCEPT(RenderingAPIException, "Failed to set texture border colour");
+	}
+
+	void D3D9RenderAPI::setSceneBlending( BlendFactor sourceFactor, BlendFactor destFactor, BlendOperation op )
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		HRESULT hr;
+		if( sourceFactor == BF_ONE && destFactor == BF_ZERO)
+		{
+			if (FAILED(hr = setRenderState(D3DRS_ALPHABLENDENABLE, FALSE)))
+				BS_EXCEPT(RenderingAPIException, "Failed to set alpha blending option");
+		}
+		else
+		{
+			if (FAILED(hr = setRenderState(D3DRS_ALPHABLENDENABLE, TRUE)))
+				BS_EXCEPT(RenderingAPIException, "Failed to set alpha blending option");
+			if (FAILED(hr = setRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE)))
+				BS_EXCEPT(RenderingAPIException, "Failed to set separate alpha blending option");
+			if( FAILED( hr = setRenderState( D3DRS_SRCBLEND, D3D9Mappings::get(sourceFactor) ) ) )
+				BS_EXCEPT(RenderingAPIException, "Failed to set source blend");
+			if( FAILED( hr = setRenderState( D3DRS_DESTBLEND, D3D9Mappings::get(destFactor) ) ) )
+				BS_EXCEPT(RenderingAPIException, "Failed to set destination blend");
+		}
+
+		if (FAILED(hr = setRenderState(D3DRS_BLENDOP, D3D9Mappings::get(op))))
+			BS_EXCEPT(RenderingAPIException, "Failed to set scene blending operation option");
+		if (FAILED(hr = setRenderState(D3DRS_BLENDOPALPHA, D3D9Mappings::get(op))))
+			BS_EXCEPT(RenderingAPIException, "Failed to set scene blending operation option");
+	}
+
+	void D3D9RenderAPI::setSceneBlending( BlendFactor sourceFactor, BlendFactor destFactor, BlendFactor sourceFactorAlpha, 
+		BlendFactor destFactorAlpha, BlendOperation op, BlendOperation alphaOp )
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		HRESULT hr;
+		if( sourceFactor == BF_ONE && destFactor == BF_ZERO && 
+			sourceFactorAlpha == BF_ONE && destFactorAlpha == BF_ZERO)
+		{
+			if (FAILED(hr = setRenderState(D3DRS_ALPHABLENDENABLE, FALSE)))
+				BS_EXCEPT(RenderingAPIException, "Failed to set alpha blending option");
+		}
+		else
+		{
+			if (FAILED(hr = setRenderState(D3DRS_ALPHABLENDENABLE, TRUE)))
+				BS_EXCEPT(RenderingAPIException, "Failed to set alpha blending option");
+			if (FAILED(hr = setRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE)))
+				BS_EXCEPT(RenderingAPIException, "Failed to set separate alpha blending option");
+			if( FAILED( hr = setRenderState( D3DRS_SRCBLEND, D3D9Mappings::get(sourceFactor) ) ) )
+				BS_EXCEPT(RenderingAPIException, "Failed to set source blend");
+			if( FAILED( hr = setRenderState( D3DRS_DESTBLEND, D3D9Mappings::get(destFactor) ) ) )
+				BS_EXCEPT(RenderingAPIException, "Failed to set destination blend");
+			if( FAILED( hr = setRenderState( D3DRS_SRCBLENDALPHA, D3D9Mappings::get(sourceFactorAlpha) ) ) )
+				BS_EXCEPT(RenderingAPIException, "Failed to set alpha source blend");
+			if( FAILED( hr = setRenderState( D3DRS_DESTBLENDALPHA, D3D9Mappings::get(destFactorAlpha) ) ) )
+				BS_EXCEPT(RenderingAPIException, "Failed to set alpha destination blend");
+		}
+
+		if (FAILED(hr = setRenderState(D3DRS_BLENDOP, D3D9Mappings::get(op))))
+			BS_EXCEPT(RenderingAPIException, "Failed to set scene blending operation option");
+		if (FAILED(hr = setRenderState(D3DRS_BLENDOPALPHA, D3D9Mappings::get(alphaOp))))
+			BS_EXCEPT(RenderingAPIException, "Failed to set alpha scene blending operation option");
+	}
+
+	void D3D9RenderAPI::setAlphaTest(CompareFunction func, unsigned char value)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		HRESULT hr;
+
+		if (func != CMPF_ALWAYS_PASS)
+		{
+			if( FAILED( hr = setRenderState( D3DRS_ALPHATESTENABLE,  TRUE ) ) )
+				BS_EXCEPT(RenderingAPIException, "Failed to enable alpha testing");
+		}
+		else
+		{
+			if( FAILED( hr = setRenderState( D3DRS_ALPHATESTENABLE,  FALSE ) ) )
+				BS_EXCEPT(RenderingAPIException, "Failed to disable alpha testing");
+		}
+		// Set always just be sure
+		if( FAILED( hr = setRenderState( D3DRS_ALPHAFUNC, D3D9Mappings::get(func) ) ) )
+			BS_EXCEPT(RenderingAPIException, "Failed to set alpha reject function");
+		if( FAILED( hr = setRenderState( D3DRS_ALPHAREF, value ) ) )
+			BS_EXCEPT(RenderingAPIException, "Failed to set render state D3DRS_ALPHAREF");
+	}
+
+	void D3D9RenderAPI::setAlphaToCoverage(bool enable)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		HRESULT hr;
+		static bool lasta2c = false;
+
+		// Alpha to coverage
+		if (getCapabilities()->hasCapability(RSC_ALPHA_TO_COVERAGE))
+		{
+			// Vendor-specific hacks on renderstate, gotta love 'em
+			if (getCapabilities()->getVendor() == GPU_NVIDIA)
+			{
+				if (enable)
+				{
+					if( FAILED( hr = setRenderState( D3DRS_ADAPTIVETESS_Y,  (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C') ) ) )
+						BS_EXCEPT(RenderingAPIException, "Failed to set alpha to coverage option");
+				}
+				else
+				{
+					if( FAILED( hr = setRenderState( D3DRS_ADAPTIVETESS_Y,  D3DFMT_UNKNOWN ) ) )
+						BS_EXCEPT(RenderingAPIException, "Failed to set alpha to coverage option");
+				}
+
+			}
+			else if ((getCapabilities()->getVendor() == GPU_AMD))
+			{
+				if (enable)
+				{
+					if( FAILED( hr = setRenderState( D3DRS_POINTSIZE,  MAKEFOURCC('A','2','M','1') ) ) )
+						BS_EXCEPT(RenderingAPIException, "Failed to set alpha to coverage option");
+				}
+				else
+				{
+					// discovered this through trial and error, seems to work
+					if( FAILED( hr = setRenderState( D3DRS_POINTSIZE,  MAKEFOURCC('A','2','M','0') ) ) )
+						BS_EXCEPT(RenderingAPIException, "Failed to set alpha to coverage option");
+				}
+			}
+
+			lasta2c = enable;
+		}
+	}
+
+	void D3D9RenderAPI::setCullingMode(CullingMode mode)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		mCullingMode = mode;
+		HRESULT hr;
+
+		if( FAILED (hr = setRenderState(D3DRS_CULLMODE, 
+			D3D9Mappings::get(mode, false))) )
+			BS_EXCEPT(RenderingAPIException, "Failed to set culling mode");
+	}
+
+	void D3D9RenderAPI::setDepthBufferCheckEnabled(bool enabled)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		HRESULT hr;
+
+		if( enabled )
+			hr = setRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
+		else
+			hr = setRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
+
+		if(FAILED(hr))
+			BS_EXCEPT(RenderingAPIException, "Error setting depth buffer test state");
+	}
+
+	void D3D9RenderAPI::setDepthBufferWriteEnabled(bool enabled)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		HRESULT hr;
+
+		if( FAILED( hr = setRenderState( D3DRS_ZWRITEENABLE, enabled ) ) )
+			BS_EXCEPT(RenderingAPIException, "Error setting depth buffer write state");
+	}
+
+	void D3D9RenderAPI::setDepthBufferFunction(CompareFunction func)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		HRESULT hr;
+		if( FAILED( hr = setRenderState( D3DRS_ZFUNC, D3D9Mappings::get(func) ) ) )
+			BS_EXCEPT(RenderingAPIException, "Error setting depth buffer test function");
+	}
+
+	void D3D9RenderAPI::setDepthBias(float constantBias, float slopeScaleBias)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		if ((mDeviceManager->getActiveDevice()->getD3D9DeviceCaps().RasterCaps & D3DPRASTERCAPS_DEPTHBIAS) != 0)
+		{
+			// Negate bias since D3D is backward
+			constantBias = -constantBias;
+			HRESULT hr = setRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&constantBias));
+			if (FAILED(hr))
+				BS_EXCEPT(RenderingAPIException, "Error setting constant depth bias");
+		}
+
+		if ((mDeviceManager->getActiveDevice()->getD3D9DeviceCaps().RasterCaps & D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS) != 0)
+		{
+			// Negate bias since D3D is backward
+			slopeScaleBias = -slopeScaleBias;
+			HRESULT hr = setRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&slopeScaleBias));
+			if (FAILED(hr))
+				BS_EXCEPT(RenderingAPIException, "Error setting slope scale depth bias");
+		}
+
+
+	}
+
+	void D3D9RenderAPI::setColorBufferWriteEnabled(bool red, bool green, bool blue, bool alpha)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		DWORD val = 0;
+		if (red) 
+			val |= D3DCOLORWRITEENABLE_RED;
+		if (green)
+			val |= D3DCOLORWRITEENABLE_GREEN;
+		if (blue)
+			val |= D3DCOLORWRITEENABLE_BLUE;
+		if (alpha)
+			val |= D3DCOLORWRITEENABLE_ALPHA;
+
+		HRESULT hr = setRenderState(D3DRS_COLORWRITEENABLE, val); 
+		if (FAILED(hr))
+			BS_EXCEPT(RenderingAPIException, "Error setting colour write enable flags");
+	}
+
+	void D3D9RenderAPI::setPolygonMode(PolygonMode level)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		HRESULT hr = setRenderState(D3DRS_FILLMODE, D3D9Mappings::get(level));
+		if (FAILED(hr))
+			BS_EXCEPT(RenderingAPIException, "Error setting polygon mode.");
+	}
+
+	void D3D9RenderAPI::setStencilCheckEnabled(bool enabled)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		// Allow stencilling
+		HRESULT hr = setRenderState(D3DRS_STENCILENABLE, enabled);
+		if (FAILED(hr))
+			BS_EXCEPT(RenderingAPIException, "Error enabling / disabling stencilling.");
+
+		if (mCurrentCapabilities->hasCapability(RSC_TWO_SIDED_STENCIL))
+		{
+			hr = setRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
+
+			if (FAILED(hr))
+				BS_EXCEPT(RenderingAPIException, "Error setting 2-sided stencil mode.");
+		}
+		else
+		{
+			hr = setRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
+
+			if (FAILED(hr))
+				BS_EXCEPT(RenderingAPIException, "Error setting 1-sided stencil mode.");
+		}
+	}
+
+	void D3D9RenderAPI::setStencilBufferOperations(StencilOperation stencilFailOp, StencilOperation depthFailOp, StencilOperation passOp, bool ccw)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		HRESULT hr;
+
+		// 2-sided operation
+		if (ccw)
+		{
+			// fail op
+			hr = setRenderState(D3DRS_CCW_STENCILFAIL, D3D9Mappings::get(stencilFailOp));
+			if (FAILED(hr))
+				BS_EXCEPT(RenderingAPIException, "Error setting stencil fail operation (ccw).");
+
+			// depth fail op
+			hr = setRenderState(D3DRS_CCW_STENCILZFAIL, D3D9Mappings::get(depthFailOp));
+			if (FAILED(hr))
+				BS_EXCEPT(RenderingAPIException, "Error setting stencil depth fail operation (ccw).");
+
+			// pass op
+			hr = setRenderState(D3DRS_CCW_STENCILPASS, D3D9Mappings::get(passOp));
+			if (FAILED(hr))
+				BS_EXCEPT(RenderingAPIException, "Error setting stencil pass operation (ccw).");
+		}
+		else
+		{
+			// fail op
+			hr = setRenderState(D3DRS_STENCILFAIL, D3D9Mappings::get(stencilFailOp, true));
+			if (FAILED(hr))
+				BS_EXCEPT(RenderingAPIException, "Error setting stencil fail operation (cw).");
+
+			// depth fail op
+			hr = setRenderState(D3DRS_STENCILZFAIL, D3D9Mappings::get(depthFailOp, true));
+			if (FAILED(hr))
+				BS_EXCEPT(RenderingAPIException, "Error setting stencil depth fail operation (cw).");
+
+			// pass op
+			hr = setRenderState(D3DRS_STENCILPASS, D3D9Mappings::get(passOp, true));
+			if (FAILED(hr))
+				BS_EXCEPT(RenderingAPIException, "Error setting stencil pass operation (cw).");
+		}
+	}
+
+	void D3D9RenderAPI::setStencilBufferFunc(CompareFunction func, bool ccw)
+	{
+		HRESULT hr;
+		
+		if(ccw)
+			hr = setRenderState(D3DRS_CCW_STENCILFUNC, D3D9Mappings::get(func));
+		else
+			hr = setRenderState(D3DRS_STENCILFUNC, D3D9Mappings::get(func));
+
+		if (FAILED(hr))
+			BS_EXCEPT(RenderingAPIException, "Error setting stencil buffer test function.");
+	}
+
+	void D3D9RenderAPI::setStencilBufferReadMask(UINT32 mask)
+	{
+		HRESULT hr = setRenderState(D3DRS_STENCILMASK, mask);
+
+		if (FAILED(hr))
+			BS_EXCEPT(RenderingAPIException, "Error setting stencil buffer mask.");
+	}
+
+	void D3D9RenderAPI::setStencilBufferWriteMask(UINT32 mask)
+	{
+		HRESULT hr = setRenderState(D3DRS_STENCILWRITEMASK, mask);
+
+		if (FAILED(hr))
+			BS_EXCEPT(RenderingAPIException, "Error setting stencil buffer write mask.");
+	}
+
+	void D3D9RenderAPI::setStencilRefValue(UINT32 refValue)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		HRESULT hr = setRenderState(D3DRS_STENCILREF, refValue);
+		if (FAILED(hr))
+			BS_EXCEPT(RenderingAPIException, "Error setting stencil buffer reference value.");
+	}
+
+	void D3D9RenderAPI::setTextureFiltering(UINT16 unit, FilterType ftype, FilterOptions filter)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		HRESULT hr;
+		D3D9Mappings::D3DTexType texType = mTexStageDesc[unit].texType;
+		hr = setSamplerState( static_cast<DWORD>(unit), D3D9Mappings::get(ftype), 
+			D3D9Mappings::get(ftype, filter, mDeviceManager->getActiveDevice()->getD3D9DeviceCaps(), texType));
+
+		if (FAILED(hr))
+			BS_EXCEPT(RenderingAPIException, "Failed to set texture filter ");
+	}
+
+
+	void D3D9RenderAPI::setTextureAnisotropy(UINT16 unit, unsigned int maxAnisotropy)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		if (static_cast<DWORD>(maxAnisotropy) > mDeviceManager->getActiveDevice()->getD3D9DeviceCaps().MaxAnisotropy)
+			maxAnisotropy = mDeviceManager->getActiveDevice()->getD3D9DeviceCaps().MaxAnisotropy;
+
+		if (getCurrentAnisotropy(unit) != maxAnisotropy)
+			setSamplerState( static_cast<DWORD>(unit), D3DSAMP_MAXANISOTROPY, maxAnisotropy );
+	}
+
+	void D3D9RenderAPI::setRenderTarget(const SPtr<RenderTargetCore>& target, bool readOnlyDepthStencil)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		mActiveRenderTarget = target;
+		const RenderTargetProperties& rtProps = target->getProperties();
+
+		HRESULT hr;
+
+		// Possibly change device if the target is a window
+		if (rtProps.isWindow())
+		{
+			D3D9RenderWindowCore* window = static_cast<D3D9RenderWindowCore*>(target.get());
+			mDeviceManager->setActiveRenderTargetDevice(window->_getDevice());
+			window->_validateDevice();
+		}
+
+		// Retrieve render surfaces
+		UINT32 maxRenderTargets = mCurrentCapabilities->getNumMultiRenderTargets();
+		IDirect3DSurface9** pBack = bs_newN<IDirect3DSurface9*>(maxRenderTargets);
+		memset(pBack, 0, sizeof(IDirect3DSurface9*) * maxRenderTargets);
+		target->getCustomAttribute("DDBACKBUFFER", pBack);
+		if (!pBack[0])
+		{
+			bs_deleteN(pBack, maxRenderTargets);
+			return;
+		}
+
+		IDirect3DSurface9* pDepth = NULL;
+
+		if (!pDepth)
+			target->getCustomAttribute("D3DZBUFFER", &pDepth);
+		
+		// Bind render targets
+		for(UINT32 x = 0; x < maxRenderTargets; ++x)
+		{
+			hr = getActiveD3D9Device()->SetRenderTarget(x, pBack[x]);
+			if (FAILED(hr))
+			{
+				String msg = DXGetErrorDescription(hr);
+				BS_EXCEPT(RenderingAPIException, "Failed to setRenderTarget : " + msg);
+			}
+		}
+
+		bs_deleteN(pBack, maxRenderTargets);
+
+		hr = getActiveD3D9Device()->SetDepthStencilSurface(pDepth);
+		if (FAILED(hr))
+		{
+			String msg = DXGetErrorDescription(hr);
+			BS_EXCEPT(RenderingAPIException, "Failed to setDepthStencil : " + msg);
+		}
+
+		// Set sRGB write mode
+		setRenderState(D3DRS_SRGBWRITEENABLE, rtProps.isHwGammaEnabled());
+		applyViewport();
+
+		BS_INC_RENDER_STAT(NumRenderTargetChanges);
+	}
+
+	void D3D9RenderAPI::setViewport(const Rect2& vp)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		mViewportNorm = vp;
+		applyViewport();
+	}
+
+	void D3D9RenderAPI::beginFrame()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		HRESULT hr;
+		if(FAILED(hr = getActiveD3D9Device()->BeginScene()))
+		{
+			String msg = DXGetErrorDescription(hr);
+			BS_EXCEPT(RenderingAPIException, "Error beginning frame :" + msg);
+		}
+
+ 		mDeviceManager->getActiveDevice()->clearDeviceStreams();
+		mIsFrameInProgress = true;
+	}
+
+	void D3D9RenderAPI::endFrame()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		HRESULT hr;
+		if(FAILED(hr = getActiveD3D9Device()->EndScene()))
+			BS_EXCEPT(RenderingAPIException, "Error ending frame");
+
+		mIsFrameInProgress = false;
+	}
+
+	void D3D9RenderAPI::setVertexDeclaration(const SPtr<VertexDeclarationCore>& decl)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		std::shared_ptr<D3D9VertexDeclarationCore> d3ddecl = std::static_pointer_cast<D3D9VertexDeclarationCore>(decl);
+
+		HRESULT hr;
+		if (FAILED(hr = getActiveD3D9Device()->SetVertexDeclaration(d3ddecl->getD3DVertexDeclaration())))
+		{
+			BS_EXCEPT(RenderingAPIException, "Unable to set D3D9 vertex declaration");
+		}
+	}
+
+	void D3D9RenderAPI::setVertexBuffers(UINT32 index, SPtr<VertexBufferCore>* buffers, UINT32 numBuffers)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		UINT32 maxBoundVertexBuffers = mCurrentCapabilities->getMaxBoundVertexBuffers();
+		if(index < 0 || (index + numBuffers) > maxBoundVertexBuffers)
+			BS_EXCEPT(InvalidParametersException, "Invalid vertex index: " + toString(index) + ". Valid range is 0 .. " + toString(maxBoundVertexBuffers - 1));
+
+		HRESULT hr;
+
+		for(UINT32 i = 0; i < numBuffers; i++)
+		{
+			if(buffers[i] != nullptr)
+			{
+				SPtr<D3D9VertexBufferCore> d3d9buf = std::static_pointer_cast<D3D9VertexBufferCore>(buffers[i]);
+				const VertexBufferProperties& vbProps = d3d9buf->getProperties();
+
+				hr = getActiveD3D9Device()->SetStreamSource(
+					static_cast<UINT>(index + i),
+					d3d9buf->getD3D9VertexBuffer(),
+					0,
+					static_cast<UINT>(vbProps.getVertexSize()) // stride
+					);
+			}
+			else
+			{
+				hr = getActiveD3D9Device()->SetStreamSource(static_cast<UINT>(index + i), nullptr, 0, 0);
+			}
+
+			if (FAILED(hr))
+				BS_EXCEPT(RenderingAPIException, "Unable to set D3D9 stream source for buffer binding");
+
+			BS_INC_RENDER_STAT(NumVertexBufferBinds);
+		}
+	}
+
+	void D3D9RenderAPI::setIndexBuffer(const SPtr<IndexBufferCore>& buffer)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		SPtr<D3D9IndexBufferCore> d3dIdxBuf = std::static_pointer_cast<D3D9IndexBufferCore>(buffer);
+
+		HRESULT hr = getActiveD3D9Device()->SetIndices( d3dIdxBuf->getD3DIndexBuffer() );
+		if (FAILED(hr))
+			BS_EXCEPT(RenderingAPIException, "Failed to set index buffer");
+
+		BS_INC_RENDER_STAT(NumIndexBufferBinds);
+	}
+
+	void D3D9RenderAPI::setDrawOperation(DrawOperationType op)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		mCurrentDrawOperation = op;
+	}
+
+	void D3D9RenderAPI::draw(UINT32 vertexOffset, UINT32 vertexCount)
+	{
+		UINT32 primCount = vertexCountToPrimCount(mCurrentDrawOperation, vertexCount);
+
+		HRESULT hr = getActiveD3D9Device()->DrawPrimitive(getD3D9PrimitiveType(), static_cast<UINT>(vertexOffset), static_cast<UINT>(primCount)); 
+
+		if(FAILED(hr))
+		{
+			String msg = DXGetErrorDescription(hr);
+			BS_EXCEPT(RenderingAPIException, "Failed to DrawPrimitive : " + msg);
+		}
+
+		BS_INC_RENDER_STAT(NumDrawCalls);
+		BS_ADD_RENDER_STAT(NumVertices, vertexCount);
+		BS_ADD_RENDER_STAT(NumPrimitives, primCount);
+	}
+
+	void D3D9RenderAPI::drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount)
+	{
+		UINT32 primCount = vertexCountToPrimCount(mCurrentDrawOperation, indexCount);
+
+		// do indexed draw operation
+		HRESULT hr = getActiveD3D9Device()->DrawIndexedPrimitive(
+			getD3D9PrimitiveType(), 
+			static_cast<UINT>(vertexOffset), 
+			0, 
+			static_cast<UINT>(vertexCount), 
+			static_cast<UINT>(startIndex), 
+			static_cast<UINT>(primCount)
+			);
+
+		if(FAILED(hr))
+		{
+			String msg = DXGetErrorDescription(hr);
+			BS_EXCEPT(RenderingAPIException, "Failed to DrawIndexedPrimitive : " + msg);
+		}
+
+		BS_INC_RENDER_STAT(NumDrawCalls);
+		BS_ADD_RENDER_STAT(NumVertices, vertexCount);
+		BS_ADD_RENDER_STAT(NumPrimitives, primCount);
+	}
+
+	void D3D9RenderAPI::setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		mScissorRect.left = static_cast<LONG>(left);
+		mScissorRect.top = static_cast<LONG>(top);
+		mScissorRect.bottom = static_cast<LONG>(bottom);
+		mScissorRect.right = static_cast<LONG>(right);
+	}
+
+	void D3D9RenderAPI::setScissorTestEnable(bool enable)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		HRESULT hr;
+		if (enable)
+		{
+			if (FAILED(hr = setRenderState(D3DRS_SCISSORTESTENABLE, TRUE)))
+			{
+				BS_EXCEPT(RenderingAPIException, "Unable to enable scissor rendering state; " + getErrorDescription(hr));
+			}
+
+			if (FAILED(hr = getActiveD3D9Device()->SetScissorRect(&mScissorRect)))
+			{
+				BS_EXCEPT(RenderingAPIException, "Unable to set scissor rectangle; " + getErrorDescription(hr));
+			}
+		}
+		else
+		{
+			if (FAILED(hr = setRenderState(D3DRS_SCISSORTESTENABLE, FALSE)))
+			{
+				BS_EXCEPT(RenderingAPIException, "Unable to disable scissor rendering state; " + getErrorDescription(hr));
+			}
+		}
+	}
+
+	void D3D9RenderAPI::setMultisampleAntialiasEnable(bool enable)
+	{
+		HRESULT hr;
+		if(enable)
+		{
+			if (FAILED(hr = setRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE)))
+			{
+				BS_EXCEPT(RenderingAPIException, "Unable to enable multisample antialiasing. Error description: " + getErrorDescription(hr));
+			}
+		}
+		else
+		{
+			if (FAILED(hr = setRenderState(D3DRS_MULTISAMPLEANTIALIAS, FALSE)))
+			{
+				BS_EXCEPT(RenderingAPIException, "Unable to disable multisample antialiasing. Error description: " + getErrorDescription(hr));
+			}
+		}
+	}
+
+	void D3D9RenderAPI::setAntialiasedLineEnable(bool enable)
+	{
+		HRESULT hr;
+		if(enable)
+		{
+			if (FAILED(hr = setRenderState(D3DRS_ANTIALIASEDLINEENABLE, TRUE)))
+			{
+				BS_EXCEPT(RenderingAPIException, "Unable to enable line antialiasing. Error description: " + getErrorDescription(hr));
+			}
+		}
+		else
+		{
+			if (FAILED(hr = setRenderState(D3DRS_ANTIALIASEDLINEENABLE, FALSE)))
+			{
+				BS_EXCEPT(RenderingAPIException, "Unable to disable line antialiasing. Error description: " + getErrorDescription(hr));
+			}
+		}
+	}
+
+	void D3D9RenderAPI::clearRenderTarget(UINT32 buffers, const Color& color, float depth, UINT16 stencil)
+	{
+		if(mActiveRenderTarget == nullptr)
+			return;
+
+		const RenderTargetProperties& rtProps = mActiveRenderTarget->getProperties();
+		Rect2I clearRect(0, 0, rtProps.getWidth(), rtProps.getHeight());
+
+		clearArea(buffers, color, depth, stencil, clearRect);
+	}
+
+	void D3D9RenderAPI::clearViewport(UINT32 buffers, const Color& color, float depth, UINT16 stencil)
+	{
+		Rect2I clearRect(mViewportLeft, mViewportTop, mViewportWidth, mViewportHeight);
+
+		clearArea(buffers, color, depth, stencil, clearRect);
+	}
+
+	void D3D9RenderAPI::clearArea(UINT32 buffers, const Color& color, float depth, UINT16 stencil, const Rect2I& clearRect)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		if(mActiveRenderTarget == nullptr)
+			return;
+
+		DWORD flags = 0;
+		if (buffers & FBT_COLOR)
+		{
+			flags |= D3DCLEAR_TARGET;
+		}
+		if (buffers & FBT_DEPTH)
+		{
+			flags |= D3DCLEAR_ZBUFFER;
+		}
+
+		// Only try to clear the stencil buffer if supported
+		if (buffers & FBT_STENCIL)
+		{
+			flags |= D3DCLEAR_STENCIL;
+		}
+
+		const RenderTargetProperties& rtProps = mActiveRenderTarget->getProperties();
+
+		bool clearEntireTarget = clearRect.width == 0 || clearRect.height == 0;
+		clearEntireTarget |= (clearRect.x == 0 && clearRect.y == 0 && clearRect.width == rtProps.getWidth() && clearRect.height == rtProps.getHeight());
+
+		if(!clearEntireTarget)
+		{
+			D3DRECT clearD3DRect;
+			clearD3DRect.x1 = (LONG)Math::clamp(clearRect.x, 0, (INT32)rtProps.getWidth() - 1);
+			clearD3DRect.x2 = (LONG)Math::clamp((INT32)clearD3DRect.x1 + clearRect.width, 0, (INT32)rtProps.getWidth() - 1);
+
+			clearD3DRect.y1 = (LONG)Math::clamp(clearRect.y, 0, (INT32)rtProps.getHeight() - 1);
+			clearD3DRect.y2 = (LONG)Math::clamp((INT32)clearD3DRect.y1 + clearRect.height, 0, (INT32)rtProps.getHeight() - 1);
+
+			HRESULT hr;
+			if(FAILED(hr = getActiveD3D9Device()->Clear(1, &clearD3DRect, flags, color.getAsBGRA(), depth, stencil)))
+			{
+				String msg = DXGetErrorDescription(hr);
+				BS_EXCEPT(RenderingAPIException, "Error clearing frame buffer : " + msg);
+			}
+		}
+		else
+		{
+			HRESULT hr;
+			if(FAILED(hr = getActiveD3D9Device()->Clear(0, nullptr, flags, color.getAsBGRA(), depth, stencil)))
+			{
+				String msg = DXGetErrorDescription(hr);
+				BS_EXCEPT(RenderingAPIException, "Error clearing frame buffer : " + msg);
+			}
+		}
+
+		BS_INC_RENDER_STAT(NumClears);
+	}
+
+	IDirect3D9*	D3D9RenderAPI::getDirect3D9()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		return msD3D9RenderSystem->mpD3D;
+	}
+
+	UINT D3D9RenderAPI::getResourceCreationDeviceCount()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		D3D9ResourceCreationPolicy creationPolicy = msD3D9RenderSystem->mResourceManager->getCreationPolicy();
+
+		if (creationPolicy == RCP_CREATE_ON_ACTIVE_DEVICE)
+		{
+			return 1;
+		}
+		else if (creationPolicy == RCP_CREATE_ON_ALL_DEVICES)
+		{
+			return msD3D9RenderSystem->mDeviceManager->getDeviceCount();
+		}
+
+		BS_EXCEPT(InvalidParametersException, "Invalid resource creation policy.");
+
+		return 0;
+	}
+
+	IDirect3DDevice9* D3D9RenderAPI::getResourceCreationDevice(UINT index)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		D3D9ResourceCreationPolicy creationPolicy = msD3D9RenderSystem->mResourceManager->getCreationPolicy();
+		IDirect3DDevice9* d3d9Device = NULL;
+
+		if (creationPolicy == RCP_CREATE_ON_ACTIVE_DEVICE)
+		{
+			d3d9Device = msD3D9RenderSystem->getActiveD3D9Device();
+		}
+		else if (creationPolicy == RCP_CREATE_ON_ALL_DEVICES) 
+		{
+			d3d9Device = msD3D9RenderSystem->mDeviceManager->getDevice(index)->getD3D9Device();
+		}
+		else
+		{
+			BS_EXCEPT(InvalidParametersException, "Invalid resource creation policy.");
+		}
+
+		return d3d9Device;
+	}
+
+	IDirect3DDevice9* D3D9RenderAPI::getActiveD3D9Device()
+	{	
+		THROW_IF_NOT_CORE_THREAD;
+
+		D3D9Device* activeDevice = msD3D9RenderSystem->mDeviceManager->getActiveDevice();
+		IDirect3DDevice9* d3d9Device;
+
+		d3d9Device = activeDevice->getD3D9Device();
+
+		if (d3d9Device == nullptr)
+			BS_EXCEPT(InvalidParametersException, "Current d3d9 device is null.");
+
+		return d3d9Device;
+	}	
+
+	D3D9ResourceManager* D3D9RenderAPI::getResourceManager()
+	{
+		// No need to check if we're on core thread as this is synced up internally
+
+		return msD3D9RenderSystem->mResourceManager;
+	}
+
+	D3D9DeviceManager* D3D9RenderAPI::getDeviceManager()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		return msD3D9RenderSystem->mDeviceManager;
+	}
+
+	/************************************************************************/
+	/* 								UTILITY METHODS                    		*/
+	/************************************************************************/
+
+	float D3D9RenderAPI::getHorizontalTexelOffset()
+	{
+		// D3D considers the origin to be in the center of a pixel
+		return -0.5f;
+	}
+
+	float D3D9RenderAPI::getVerticalTexelOffset()
+	{
+		// D3D considers the origin to be in the center of a pixel
+		return -0.5f;
+	}
+
+	float D3D9RenderAPI::getMinimumDepthInputValue()
+	{
+		// Range [0.0f, 1.0f]
+		return 0.0f;
+	}
+
+	float D3D9RenderAPI::getMaximumDepthInputValue()
+	{
+		// Range [0.0f, 1.0f]
+		return 1.0f;
+	}
+
+	VertexElementType D3D9RenderAPI::getColorVertexElementType() const
+	{
+		return VET_COLOR_ARGB;
+	}
+
+	void D3D9RenderAPI::convertProjectionMatrix(const Matrix4& matrix, Matrix4& dest)
+	{
+		dest = matrix;
+
+		// Convert depth range from [-1,+1] to [0,1]
+		dest[2][0] = (dest[2][0] + dest[3][0]) / 2;
+		dest[2][1] = (dest[2][1] + dest[3][1]) / 2;
+		dest[2][2] = (dest[2][2] + dest[3][2]) / 2;
+		dest[2][3] = (dest[2][3] + dest[3][3]) / 2;
+	}
+
+	GpuParamBlockDesc D3D9RenderAPI::generateParamBlockDesc(const String& name, Vector<GpuParamDataDesc>& params)
+	{
+		GpuParamBlockDesc block;
+		block.blockSize = 0;
+		block.isShareable = true;
+		block.name = name;
+		block.slot = 0;
+
+		// DX9 doesn't natively support parameter blocks but Banshee's emulation expects everything to be 16 byte aligned.
+		// Iterate in reverse order because DX9's shader reflection API reports the variables in reverse order then they
+		// appear in code, and we want to match the auto-generated buffers that result from that layout.
+		for (auto riter = params.rbegin(); riter != params.rend(); ++riter)
+		{
+			GpuParamDataDesc& param = *riter;
+
+			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[param.type];
+			UINT32 size = typeInfo.size / 4;
+
+			UINT32 alignOffset = size % 4;
+			if (alignOffset != 0)
+				size += 4 - alignOffset;
+
+			param.elementSize = size;
+			param.arrayElementStride = size;
+			param.cpuMemOffset = block.blockSize;
+			param.gpuMemOffset = 0;
+			param.paramBlockSlot = 0;
+
+			if (param.arraySize > 0)
+				block.blockSize += size * param.arraySize;
+			else
+				block.blockSize += size;
+		}
+
+		return block;
+	}
+
+	/************************************************************************/
+	/* 								PRIVATE		                     		*/
+	/************************************************************************/
+
+	D3D9DriverList* D3D9RenderAPI::getDirect3DDrivers() const
+	{
+		if( !mDriverList )
+			mDriverList = bs_new<D3D9DriverList>();
+
+		return mDriverList;
+	}
+
+	D3DPRIMITIVETYPE D3D9RenderAPI::getD3D9PrimitiveType() const
+	{
+		switch(mCurrentDrawOperation)
+		{
+		case DOT_POINT_LIST:
+			return D3DPT_POINTLIST;
+		case DOT_LINE_LIST:
+			return D3DPT_LINELIST;
+		case DOT_LINE_STRIP:
+			return D3DPT_LINESTRIP;
+		case DOT_TRIANGLE_LIST:
+			return D3DPT_TRIANGLELIST;
+		case DOT_TRIANGLE_STRIP:
+			return D3DPT_TRIANGLESTRIP;
+		case DOT_TRIANGLE_FAN:
+			return D3DPT_TRIANGLEFAN;
+		}
+
+		return D3DPT_TRIANGLELIST;
+	}
+
+	RenderAPICapabilities* D3D9RenderAPI::updateRenderSystemCapabilities(D3D9RenderWindowCore* renderWindow)
+	{			
+		RenderAPICapabilities* rsc = mCurrentCapabilities;
+		if (rsc == nullptr)
+			rsc = bs_new<RenderAPICapabilities>();
+
+		rsc->setDriverVersion(mDriverVersion);
+		rsc->setDeviceName(mActiveD3DDriver->getDriverDescription());
+		rsc->setRenderAPIName(getName());
+
+		// Init caps to maximum.		
+		rsc->setCapability(RSC_ANISOTROPY);
+		rsc->setCapability(RSC_AUTOMIPMAP);
+		rsc->setCapability(RSC_CUBEMAPPING);			
+		rsc->setCapability(RSC_TWO_SIDED_STENCIL);		
+		rsc->setCapability(RSC_STENCIL_WRAP);
+		rsc->setCapability(RSC_HWOCCLUSION);		
+		rsc->setCapability(RSC_USER_CLIP_PLANES);			
+		rsc->setCapability(RSC_VERTEX_FORMAT_UBYTE4);			
+		rsc->setCapability(RSC_TEXTURE_3D);			
+		rsc->setCapability(RSC_NON_POWER_OF_2_TEXTURES);
+		rsc->setNumMultiRenderTargets(BS_MAX_MULTIPLE_RENDER_TARGETS);
+		rsc->setCapability(RSC_MRT_DIFFERENT_BIT_DEPTHS);		
+		rsc->setCapability(RSC_POINT_SPRITES);			
+		rsc->setCapability(RSC_POINT_EXTENDED_PARAMETERS);								
+		rsc->setMaxPointSize(10.0);
+		rsc->setCapability(RSC_MIPMAP_LOD_BIAS);				
+		rsc->setCapability(RSC_PERSTAGECONSTANT);
+		rsc->setStencilBufferBitDepth(8);
+		rsc->setCapability(RSC_ADVANCED_BLEND_OPERATIONS);
+
+		for (UINT32 i=0; i < mDeviceManager->getDeviceCount(); ++i)
+		{
+			D3D9Device* device			 = mDeviceManager->getDevice(i);
+			IDirect3DDevice9* d3d9Device = device->getD3D9Device();
+
+			IDirect3DSurface9* pSurf;
+
+
+			// Check for hardware stencil support
+			d3d9Device->GetDepthStencilSurface(&pSurf);
+
+			if (pSurf != nullptr)
+			{
+				D3DSURFACE_DESC surfDesc;
+
+				pSurf->GetDesc(&surfDesc);
+				pSurf->Release();
+			}																	
+
+			// Check for hardware occlusion support
+			HRESULT hr = d3d9Device->CreateQuery(D3DQUERYTYPE_OCCLUSION,  NULL);
+
+			if (FAILED(hr))
+				rsc->unsetCapability(RSC_HWOCCLUSION);
+		}
+
+		// Update RS caps using the minimum value found in adapter list.
+		for (unsigned int i=0; i < mDriverList->count(); ++i)
+		{
+			D3D9Driver* pCurDriver       = mDriverList->item(i);			
+			const D3DCAPS9& rkCurCaps    = pCurDriver->getD3D9DeviceCaps();
+
+			rsc->setNumTextureUnits(GPT_FRAGMENT_PROGRAM, 16); // We don't support anything lower than SM3, and 16 is the sampler count determined by the specification
+
+			rsc->setMaxBoundVertexBuffers(static_cast<UINT32>(rkCurCaps.MaxStreams));
+
+			// Check for Anisotropy.
+			if (rkCurCaps.MaxAnisotropy <= 1)
+				rsc->unsetCapability(RSC_ANISOTROPY);
+
+			// Check automatic mipmap generation.
+			if ((rkCurCaps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP) == 0)
+				rsc->unsetCapability(RSC_AUTOMIPMAP);
+
+			// Two-sided stencil
+			if ((rkCurCaps.StencilCaps & D3DSTENCILCAPS_TWOSIDED) == 0)
+				rsc->unsetCapability(RSC_TWO_SIDED_STENCIL);
+
+			// stencil wrap
+			if ((rkCurCaps.StencilCaps & D3DSTENCILCAPS_INCR) == 0 ||
+				(rkCurCaps.StencilCaps & D3DSTENCILCAPS_DECR) == 0)
+				rsc->unsetCapability(RSC_STENCIL_WRAP);
+
+			// User clip planes
+			if (rkCurCaps.MaxUserClipPlanes == 0)			
+				rsc->unsetCapability(RSC_USER_CLIP_PLANES);			
+
+			// UBYTE4 type?
+			if ((rkCurCaps.DeclTypes & D3DDTCAPS_UBYTE4) == 0)			
+				rsc->unsetCapability(RSC_VERTEX_FORMAT_UBYTE4);	
+
+			// Check cube map support.
+			if ((rkCurCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP) == 0)
+				rsc->unsetCapability(RSC_CUBEMAPPING);
+
+			// 3D textures?
+			if ((rkCurCaps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP) == 0)			
+				rsc->unsetCapability(RSC_TEXTURE_3D);			
+
+			if (rkCurCaps.TextureCaps & D3DPTEXTURECAPS_POW2)
+			{
+				// Conditional support for non POW2
+				if (!(rkCurCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL))							
+					rsc->unsetCapability(RSC_NON_POWER_OF_2_TEXTURES);				
+			}	
+
+			// Number of render targets
+			if (rkCurCaps.NumSimultaneousRTs < rsc->getNumMultiRenderTargets())
+			{
+				rsc->setNumMultiRenderTargets(std::min((UINT16)rkCurCaps.NumSimultaneousRTs, (UINT16)BS_MAX_MULTIPLE_RENDER_TARGETS));
+			}	
+
+			if((rkCurCaps.PrimitiveMiscCaps & D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS) == 0)
+			{
+				rsc->unsetCapability(RSC_MRT_DIFFERENT_BIT_DEPTHS);
+			}
+
+			// Point sprites 
+			if (rkCurCaps.MaxPointSize <= 1.0f)
+			{
+				rsc->unsetCapability(RSC_POINT_SPRITES);
+				// sprites and extended parameters go together in D3D
+				rsc->unsetCapability(RSC_POINT_EXTENDED_PARAMETERS);				
+			}
+
+			// Take the minimum point size.
+			if (rkCurCaps.MaxPointSize < rsc->getMaxPointSize())
+				rsc->setMaxPointSize(rkCurCaps.MaxPointSize);	
+
+			// Mipmap LOD biasing?
+			if ((rkCurCaps.RasterCaps & D3DPRASTERCAPS_MIPMAPLODBIAS) == 0)			
+				rsc->unsetCapability(RSC_MIPMAP_LOD_BIAS);			
+
+
+			// Do we support per-stage src_manual constants?
+			// HACK - ATI drivers seem to be buggy and don't support per-stage constants properly?
+			// TODO: move this to RSC
+			if((rkCurCaps.PrimitiveMiscCaps & D3DPMISCCAPS_PERSTAGECONSTANT) == 0)
+				rsc->unsetCapability(RSC_PERSTAGECONSTANT);
+
+			// Advanced blend operations? min max subtract rev 
+			if((rkCurCaps.PrimitiveMiscCaps & D3DPMISCCAPS_BLENDOP) == 0)
+				rsc->unsetCapability(RSC_ADVANCED_BLEND_OPERATIONS);
+		}				
+
+		// We always support compression, D3DX will decompress if device does not support
+		rsc->setCapability(RSC_TEXTURE_COMPRESSION);
+		rsc->setCapability(RSC_TEXTURE_COMPRESSION_DXT);
+
+		updateVertexShaderCaps(rsc);
+		updatePixelShaderCaps(rsc);
+
+		// Adapter details
+		const D3DADAPTER_IDENTIFIER9& adapterID = mActiveD3DDriver->getAdapterIdentifier();
+
+		// determine vendor
+		// Full list of vendors here: http://www.pcidatabase.com/vendors.php?sort=id
+		switch(adapterID.VendorId)
+		{
+		case 0x10DE:
+			rsc->setVendor(GPU_NVIDIA);
+			break;
+		case 0x1002:
+			rsc->setVendor(GPU_AMD);
+			break;
+		case 0x163C:
+		case 0x8086:
+			rsc->setVendor(GPU_INTEL);
+			break;
+		default:
+			rsc->setVendor(GPU_UNKNOWN);
+			break;
+		};
+
+		rsc->setCapability(RSC_INFINITE_FAR_PLANE);
+
+		// We always support rendertextures bigger than the frame buffer
+		rsc->setCapability(RSC_HWRENDER_TO_TEXTURE);
+
+		// Determine if any floating point texture format is supported
+		D3DFORMAT floatFormats[6] = {D3DFMT_R16F, D3DFMT_G16R16F, 
+			D3DFMT_A16B16G16R16F, D3DFMT_R32F, D3DFMT_G32R32F, 
+			D3DFMT_A32B32G32R32F};
+		IDirect3DSurface9* bbSurf;
+		renderWindow->getCustomAttribute("DDBACKBUFFER", &bbSurf);
+		D3DSURFACE_DESC bbSurfDesc;
+		bbSurf->GetDesc(&bbSurfDesc);
+
+		for (int i = 0; i < 6; ++i)
+		{
+			if (SUCCEEDED(mpD3D->CheckDeviceFormat(mActiveD3DDriver->getAdapterNumber(), 
+				D3DDEVTYPE_HAL, bbSurfDesc.Format, 
+				0, D3DRTYPE_TEXTURE, floatFormats[i])))
+			{
+				rsc->setCapability(RSC_TEXTURE_FLOAT);
+				break;
+			}
+
+		}
+
+		// Vertex textures
+		if (rsc->isShaderProfileSupported("vs_3_0"))
+		{
+			rsc->setCapability(RSC_VERTEX_TEXTURE_FETCH);
+			rsc->setNumTextureUnits(GPT_VERTEX_PROGRAM, 4);
+			rsc->setNumCombinedTextureUnits(rsc->getNumTextureUnits(GPT_FRAGMENT_PROGRAM) +
+				rsc->getNumTextureUnits(GPT_VERTEX_PROGRAM));
+		}		
+		else
+		{
+			rsc->setNumCombinedTextureUnits(rsc->getNumTextureUnits(GPT_FRAGMENT_PROGRAM));
+		}
+
+		// Check alpha to coverage support
+		// this varies per vendor! But at least SM3 is required
+		if (rsc->isShaderProfileSupported("ps_3_0"))
+		{
+			// NVIDIA needs a separate check
+			if (rsc->getVendor() == GPU_NVIDIA)
+			{
+				if (mpD3D->CheckDeviceFormat(
+					D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,D3DRTYPE_SURFACE, 
+					(D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C')) == S_OK)
+				{
+					rsc->setCapability(RSC_ALPHA_TO_COVERAGE);
+				}
+
+			}
+			else if (rsc->getVendor() == GPU_AMD)
+			{
+				// There is no check on ATI, we have to assume SM3 == support
+				rsc->setCapability(RSC_ALPHA_TO_COVERAGE);
+			}
+
+			// no other cards have Dx9 hacks for alpha to coverage, as far as I know
+		}
+
+
+		if (mCurrentCapabilities == nullptr)
+		{		
+			mCurrentCapabilities = rsc;
+			mCurrentCapabilities->addShaderProfile("hlsl");
+
+			if (mCurrentCapabilities->isShaderProfileSupported("hlsl"))
+				GpuProgramCoreManager::instance().addFactory(mHLSLProgramFactory);
+
+			mNumTexStages = mCurrentCapabilities->getNumCombinedTextureUnits();
+			mTexStageDesc = bs_newN<sD3DTextureStageDesc>(mNumTexStages);
+
+			// set stages desc. to defaults
+			for (UINT32 n = 0; n < mNumTexStages; n++)
+			{
+				mTexStageDesc[n].coordIndex = 0;
+				mTexStageDesc[n].texType = D3D9Mappings::D3D_TEX_TYPE_NORMAL;
+				mTexStageDesc[n].pTex = 0;
+				mTexStageDesc[n].pVertexTex = 0;
+			}
+		}
+
+		return rsc;
+	}
+
+	void D3D9RenderAPI::updateVertexShaderCaps(RenderAPICapabilities* rsc) const
+	{
+		UINT16 major = 0xFF;
+		UINT16 minor = 0xFF;
+		D3DCAPS9 minVSCaps;
+
+		// Find the device with the lowest vertex shader caps.
+		for (unsigned int i=0; i < mDriverList->count(); ++i)
+		{
+			D3D9Driver* pCurDriver      = mDriverList->item(i);			
+			const D3DCAPS9& rkCurCaps   = pCurDriver->getD3D9DeviceCaps();
+			UINT16 currMajor			= static_cast<UINT16>((rkCurCaps.VertexShaderVersion & 0x0000FF00) >> 8);
+			UINT16 currMinor			= static_cast<UINT16>(rkCurCaps.VertexShaderVersion & 0x000000FF);
+
+			if (currMajor < major)	
+			{
+				major = currMajor;
+				minor = currMinor;
+				minVSCaps = rkCurCaps;
+			}
+			else if (currMajor == major && currMinor < minor)
+			{
+				minor = currMinor;
+				minVSCaps = rkCurCaps;
+			}			
+		}
+
+		// In case we didn't found any vertex shader support
+		// try the IDirect3DDevice9 caps instead of the IDirect3D9
+		// software vertex processing is reported there
+		if (major == 0 && minor == 0)
+		{
+			IDirect3DDevice9* lpD3DDevice9 = getActiveD3D9Device();
+			D3DCAPS9 d3dDeviceCaps9;
+			lpD3DDevice9->GetDeviceCaps(&d3dDeviceCaps9);
+			major = static_cast<UINT16>((d3dDeviceCaps9.VertexShaderVersion & 0x0000FF00) >> 8);
+			minor = static_cast<UINT16>(d3dDeviceCaps9.VertexShaderVersion & 0x000000FF);
+		}
+
+		bool vs2x = false;
+		bool vs2a = false;
+
+		// Special case detection for vs_2_x/a support
+		if (major >= 2)
+		{
+			if ((minVSCaps.VS20Caps.Caps & D3DVS20CAPS_PREDICATION) &&
+				(minVSCaps.VS20Caps.DynamicFlowControlDepth > 0) &&
+				(minVSCaps.VS20Caps.NumTemps >= 12))
+			{
+				vs2x = true;
+			}
+
+			if ((minVSCaps.VS20Caps.Caps & D3DVS20CAPS_PREDICATION) &&
+				(minVSCaps.VS20Caps.DynamicFlowControlDepth > 0) &&
+				(minVSCaps.VS20Caps.NumTemps >= 13))
+			{
+				vs2a = true;
+			}
+		}
+
+		// Populate max param count
+		switch (major)
+		{
+		case 1:
+			// No boolean params allowed
+			rsc->setVertexProgramConstantBoolCount(0);
+			// No integer params allowed
+			rsc->setVertexProgramConstantIntCount(0);
+			// float params, always 4D
+			rsc->setVertexProgramConstantFloatCount(static_cast<UINT16>(minVSCaps.MaxVertexShaderConst));
+
+			break;
+		case 2:
+			// 16 boolean params allowed
+			rsc->setVertexProgramConstantBoolCount(16);
+			// 16 integer params allowed, 4D
+			rsc->setVertexProgramConstantIntCount(16);
+			// float params, always 4D
+			rsc->setVertexProgramConstantFloatCount(static_cast<UINT16>(minVSCaps.MaxVertexShaderConst));
+			break;
+		case 3:
+			// 16 boolean params allowed
+			rsc->setVertexProgramConstantBoolCount(16);
+			// 16 integer params allowed, 4D
+			rsc->setVertexProgramConstantIntCount(16);
+			// float params, always 4D
+			rsc->setVertexProgramConstantFloatCount(static_cast<UINT16>(minVSCaps.MaxVertexShaderConst));
+			break;
+		}
+
+		// populate syntax codes in program manager (no breaks in this one so it falls through)
+		switch(major)
+		{
+		case 3:
+			rsc->addShaderProfile("vs_3_0");
+			rsc->addGpuProgramProfile(GPP_VS_3_0, "vs_3_0");
+		case 2:
+			if (vs2x)
+			{
+				rsc->addShaderProfile("vs_2_x");
+				rsc->addGpuProgramProfile(GPP_VS_2_x, "vs_2_x");
+			}
+			if (vs2a)
+			{
+				rsc->addShaderProfile("vs_2_a");
+				rsc->addGpuProgramProfile(GPP_VS_2_a, "vs_2_a");
+			}
+
+			rsc->addShaderProfile("vs_2_0");
+			rsc->addGpuProgramProfile(GPP_VS_2_0, "vs_2_0");
+		case 1:
+			rsc->addShaderProfile("vs_1_1");
+			rsc->addGpuProgramProfile(GPP_VS_1_1, "vs_1_1");
+		}
+	}
+
+	void D3D9RenderAPI::updatePixelShaderCaps(RenderAPICapabilities* rsc) const
+	{
+		UINT16 major = 0xFF;
+		UINT16 minor = 0xFF;
+		D3DCAPS9 minPSCaps;
+
+		// Find the device with the lowest pixel shader caps.
+		for (unsigned int i=0; i < mDriverList->count(); ++i)
+		{
+			D3D9Driver* pCurDriver      = mDriverList->item(i);			
+			const D3DCAPS9& currCaps    = pCurDriver->getD3D9DeviceCaps();
+			UINT16 currMajor			= static_cast<UINT16>((currCaps.PixelShaderVersion & 0x0000FF00) >> 8);
+			UINT16 currMinor			= static_cast<UINT16>(currCaps.PixelShaderVersion & 0x000000FF);
+
+			if (currMajor < major)	
+			{
+				major = currMajor;
+				minor = currMinor;
+				minPSCaps = currCaps;
+			}
+			else if (currMajor == major && currMinor < minor)
+			{
+				minor = currMinor;
+				minPSCaps = currCaps;
+			}			
+		}
+
+		bool ps2a = false;
+		bool ps2b = false;
+		bool ps2x = false;
+
+		// Special case detection for ps_2_x/a/b support
+		if (major >= 2)
+		{
+			if ((minPSCaps.PS20Caps.Caps & D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT) &&
+				(minPSCaps.PS20Caps.NumTemps >= 32))
+			{
+				ps2b = true;
+			}
+
+			if ((minPSCaps.PS20Caps.Caps & D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT) &&
+				(minPSCaps.PS20Caps.Caps & D3DPS20CAPS_NODEPENDENTREADLIMIT) &&
+				(minPSCaps.PS20Caps.Caps & D3DPS20CAPS_ARBITRARYSWIZZLE) &&
+				(minPSCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) &&
+				(minPSCaps.PS20Caps.Caps & D3DPS20CAPS_PREDICATION) &&
+				(minPSCaps.PS20Caps.NumTemps >= 22))
+			{
+				ps2a = true;
+			}
+
+			// Does this enough?
+			if (ps2a || ps2b)
+			{
+				ps2x = true;
+			}
+		}
+
+		switch (major)
+		{
+		case 1:
+			// no boolean params allowed
+			rsc->setFragmentProgramConstantBoolCount(0);
+			// no integer params allowed
+			rsc->setFragmentProgramConstantIntCount(0);
+			// float params, always 4D
+			rsc->setFragmentProgramConstantFloatCount(8);
+			break;
+		case 2:
+			// 16 boolean params allowed
+			rsc->setFragmentProgramConstantBoolCount(16);
+			// 16 integer params allowed, 4D
+			rsc->setFragmentProgramConstantIntCount(16);
+			// float params, always 4D
+			rsc->setFragmentProgramConstantFloatCount(32);
+			break;
+		case 3:
+			// 16 boolean params allowed
+			rsc->setFragmentProgramConstantBoolCount(16);
+			// 16 integer params allowed, 4D
+			rsc->setFragmentProgramConstantIntCount(16);
+			// float params, always 4D
+			rsc->setFragmentProgramConstantFloatCount(224);
+			break;
+		}
+
+		// populate syntax codes in program manager (no breaks in this one so it falls through)
+		switch(major)
+		{
+		case 3:
+			if (minor > 0)
+			{
+				rsc->addShaderProfile("ps_3_x");
+				rsc->addGpuProgramProfile(GPP_FS_3_x, "ps_3_x");
+			}
+
+			rsc->addShaderProfile("ps_3_0");
+			rsc->addGpuProgramProfile(GPP_FS_3_0, "ps_3_0");
+		case 2:
+			if (ps2x)
+			{
+				rsc->addShaderProfile("ps_2_x");
+				rsc->addGpuProgramProfile(GPP_FS_2_x, "ps_2_x");
+			}
+			if (ps2a)
+			{
+				rsc->addShaderProfile("ps_2_a");
+				rsc->addGpuProgramProfile(GPP_FS_2_a, "ps_2_a");
+			}
+			if (ps2b)
+			{
+				rsc->addShaderProfile("ps_2_b");
+				rsc->addGpuProgramProfile(GPP_FS_2_b, "ps_2_b");
+			}
+
+			rsc->addShaderProfile("ps_2_0");
+			rsc->addGpuProgramProfile(GPP_FS_2_0, "ps_2_0");
+		case 1:
+			if (major > 1 || minor >= 4)
+			{
+				rsc->addShaderProfile("ps_1_4");
+				rsc->addGpuProgramProfile(GPP_FS_1_4, "ps_1_4");
+			}
+			if (major > 1 || minor >= 3)
+			{
+				rsc->addShaderProfile("ps_1_3");
+				rsc->addGpuProgramProfile(GPP_FS_1_3, "ps_1_3");
+			}
+			if (major > 1 || minor >= 2)
+			{
+				rsc->addShaderProfile("ps_1_2");
+				rsc->addGpuProgramProfile(GPP_FS_1_2, "ps_1_2");
+			}
+
+			rsc->addShaderProfile("ps_1_1");
+			rsc->addGpuProgramProfile(GPP_FS_1_1, "ps_1_1");
+		}
+	}
+
+	String D3D9RenderAPI::getErrorDescription(long errorNumber) const
+	{
+		const String errMsg = DXGetErrorDescription(errorNumber);
+		return errMsg;
+	}
+
+	void D3D9RenderAPI::setClipPlane (UINT16 index, float A, float B, float C, float D)
+	{
+		float plane[4] = { A, B, C, D };
+		getActiveD3D9Device()->SetClipPlane (index, plane);
+	}
+
+	void D3D9RenderAPI::enableClipPlane (UINT16 index, bool enable)
+	{
+		DWORD prev;
+		getActiveD3D9Device()->GetRenderState(D3DRS_CLIPPLANEENABLE, &prev);
+		setRenderState(D3DRS_CLIPPLANEENABLE, enable?
+			(prev | (1 << index)) : (prev & ~(1 << index)));
+	}
+
+	void D3D9RenderAPI::notifyOnDeviceLost(D3D9Device* device)
+	{	
+		if (mIsFrameInProgress)
+		{
+			endFrame();
+			mRestoreFrameOnReset = true;
+		}
+	}
+
+	void D3D9RenderAPI::notifyOnDeviceReset(D3D9Device* device)
+	{		
+		// Reset state attributes.	
+		mVertexProgramBound = false;
+		mFragmentProgramBound = false;
+
+		if (mRestoreFrameOnReset)
+		{
+			beginFrame();
+			mRestoreFrameOnReset = false;
+		}
+	}
+
+	void D3D9RenderAPI::determineMultisampleSettings(IDirect3DDevice9* d3d9Device, UINT32 multisampleCount, D3DFORMAT d3dPixelFormat, 
+		bool fullScreen, D3DMULTISAMPLE_TYPE *outMultisampleType, DWORD *outMultisampleQuality) const
+	{
+		bool tryCSAA = false; // Note: Disabled for now, but leaving the code for later so it might be useful
+		enum CSAAMode { CSAA_Normal, CSAA_Quality };
+		CSAAMode csaaMode = CSAA_Normal;
+
+		D3D9DriverList* driverList = getDirect3DDrivers();
+		D3D9Driver* deviceDriver = mActiveD3DDriver;
+		D3D9Device* device = mDeviceManager->getDeviceFromD3D9Device(d3d9Device);
+
+		for (UINT32 i = 0; i < driverList->count(); ++i)
+		{
+			D3D9Driver* currDriver = driverList->item(i);
+
+			if (currDriver->getAdapterNumber() == device->getAdapterNumber())
+			{
+				deviceDriver = currDriver;
+				break;
+			}
+		}
+
+		UINT32 origNumSamples = multisampleCount;
+		bool foundValid = false;
+		while (!foundValid)
+		{
+			// Deal with special cases
+			if (tryCSAA)
+			{
+				switch(multisampleCount)
+				{
+				case 8:
+					if (csaaMode == CSAA_Quality)
+					{
+						*outMultisampleType = D3DMULTISAMPLE_8_SAMPLES;
+						*outMultisampleQuality = 0;
+					}
+					else
+					{
+						*outMultisampleType = D3DMULTISAMPLE_4_SAMPLES;
+						*outMultisampleQuality = 2;
+					}
+					break;
+				case 16:
+					if (csaaMode == CSAA_Quality)
+					{
+						*outMultisampleType = D3DMULTISAMPLE_8_SAMPLES;
+						*outMultisampleQuality = 2;
+					}
+					else
+					{
+						*outMultisampleType = D3DMULTISAMPLE_4_SAMPLES;
+						*outMultisampleQuality = 4;
+					}
+					break;
+				}
+			}
+			else // !CSAA
+			{
+				*outMultisampleType = D3DMULTISAMPLE_NONE;
+				*outMultisampleQuality = 0;
+			}
+
+
+			HRESULT hr;
+			DWORD outQuality;
+			hr = mpD3D->CheckDeviceMultiSampleType( 
+				deviceDriver->getAdapterNumber(), 
+				D3DDEVTYPE_HAL, 
+				d3dPixelFormat, 
+				!fullScreen, 
+				*outMultisampleType, 
+				&outQuality);
+
+			if (SUCCEEDED(hr) && 
+				(!tryCSAA || outQuality > *outMultisampleQuality))
+			{
+				foundValid = true;
+			}
+			else
+			{
+				// Downgrade
+				if (tryCSAA && multisampleCount == 8)
+				{
+					// For CSAA, we'll try downgrading with quality mode at all samples.
+					// then try without quality, then drop CSAA
+					if (csaaMode == CSAA_Quality)
+					{
+						// Drop quality first
+						csaaMode = CSAA_Normal;
+					}
+					else
+					{
+						// Drop CSAA entirely 
+						tryCSAA = false;
+					}
+
+					// Return to original requested samples
+					multisampleCount = origNumSamples;
+				}
+				else
+				{
+					// Drop samples
+					multisampleCount--;
+
+					if (multisampleCount == 1)
+					{
+						// Ran out of options, no multisampling
+						multisampleCount = 0;
+						foundValid = true;
+					}
+				}
+			}
+		}
+	}
+
+	void D3D9RenderAPI::setClipPlanesImpl(const PlaneList& clipPlanes)
+	{
+		size_t i;
+		size_t numClipPlanes;
+		D3DXPLANE dx9ClipPlane;
+		DWORD mask = 0;
+		HRESULT hr;
+
+		numClipPlanes = clipPlanes.size();
+		for (i = 0; i < numClipPlanes; ++i)
+		{
+			const Plane& plane = clipPlanes[i];
+
+			dx9ClipPlane.a = plane.normal.x;
+			dx9ClipPlane.b = plane.normal.y;
+			dx9ClipPlane.c = plane.normal.z;
+			dx9ClipPlane.d = plane.d;
+
+			// TODO Low priority - Transform planes to clip space?
+
+			hr = getActiveD3D9Device()->SetClipPlane(static_cast<DWORD>(i), dx9ClipPlane);
+			if (FAILED(hr))
+			{
+				BS_EXCEPT(RenderingAPIException, "Unable to set clip plane");
+			}
+
+			mask |= (1 << i);
+		}
+
+		hr = setRenderState(D3DRS_CLIPPLANEENABLE, mask);
+		if (FAILED(hr))
+		{
+			BS_EXCEPT(RenderingAPIException, "Unable to set render state for clip planes");
+		}
+	}
+
+	HRESULT D3D9RenderAPI::setRenderState(D3DRENDERSTATETYPE state, DWORD value)
+	{
+		return getActiveD3D9Device()->SetRenderState(state, value);
+	}
+
+	HRESULT D3D9RenderAPI::setSamplerState(DWORD sampler, D3DSAMPLERSTATETYPE type, DWORD value)
+	{
+		return getActiveD3D9Device()->SetSamplerState(sampler, type, value);
+	}
+
+	HRESULT D3D9RenderAPI::setTextureStageState(DWORD stage, D3DTEXTURESTAGESTATETYPE type, DWORD value)
+	{
+		if (stage < 8)
+			return getActiveD3D9Device()->SetTextureStageState(stage, type, value);
+		else
+			return D3D_OK;
+	}
+
+	DWORD D3D9RenderAPI::getCurrentAnisotropy(UINT32 unit)
+	{
+		DWORD oldVal;
+		getActiveD3D9Device()->GetSamplerState(static_cast<DWORD>(unit), D3DSAMP_MAXANISOTROPY, &oldVal);
+		return oldVal;
+	}
+
+	void D3D9RenderAPI::applyViewport()
+	{
+		if (mActiveRenderTarget == nullptr)
+			return;
+
+		const RenderTargetProperties& rtProps = mActiveRenderTarget->getProperties();
+		D3DVIEWPORT9 d3dvp;
+		HRESULT hr;
+
+		setCullingMode(mCullingMode);
+
+		// Set viewport dimensions
+		mViewportLeft = (UINT32)(rtProps.getWidth() * mViewportNorm.x);
+		mViewportTop = (UINT32)(rtProps.getHeight() * mViewportNorm.y);
+		mViewportWidth = (UINT32)(rtProps.getWidth() * mViewportNorm.width);
+		mViewportHeight = (UINT32)(rtProps.getHeight() * mViewportNorm.height);
+
+		d3dvp.X = mViewportLeft;
+		d3dvp.Y = mViewportTop;
+		d3dvp.Width = mViewportWidth;
+		d3dvp.Height = mViewportHeight;
+		if (rtProps.requiresTextureFlipping())
+		{
+			// Convert "top-left" to "bottom-left"
+			d3dvp.Y = rtProps.getHeight() - d3dvp.Height - d3dvp.Y;
+		}
+
+		// Z-values from 0.0 to 1.0 (TODO: standardise with OpenGL)
+		d3dvp.MinZ = 0.0f;
+		d3dvp.MaxZ = 1.0f;
+
+		if (FAILED(hr = getActiveD3D9Device()->SetViewport(&d3dvp)))
+			BS_EXCEPT(RenderingAPIException, "Failed to set viewport.");
+	}
 }

+ 1 - 1
BansheeEngine/Source/BsLight.cpp

@@ -180,7 +180,7 @@ namespace BansheeEngine
 			UINT32* indexData = meshData->getIndices32();
 			UINT8* positionData = meshData->getElementData(VES_POSITION);
 
-			Sphere localSphere(Vector3::ZERO, mRange);
+			Sphere localSphere(Vector3::ZERO, 1.0f);
 			ShapeMeshes3D::solidSphere(localSphere, positionData, nullptr, 0,
 				vertexDesc->getVertexStride(), indexData, 0, 1);
 

+ 605 - 605
BansheeGLRenderAPI/Include/BsGLRenderAPI.h

@@ -1,605 +1,605 @@
-#pragma once
-
-#include "BsGLPrerequisites.h"
-#include "BsRenderAPI.h"
-#include "BsGLHardwareBufferManager.h"
-#include "BsGLSLProgramFactory.h"
-#include "BsVector4.h"
-
-namespace BansheeEngine 
-{
-	/**
-	 * @brief	Implementation of a render system using OpenGL. Provides abstracted
-	 *			access to various low level OpenGL methods.
-	 */
-    class BS_RSGL_EXPORT GLRenderAPI : public RenderAPICore
-    {
-    public:
-        GLRenderAPI();
-        ~GLRenderAPI();
-
-		/**
-		 * @copydoc RenderAPICore::getName()
-		 */
-		const StringID& getName() const override;
-
-		/**
-		 * @copydoc RenderAPICore::getShadingLanguageName()
-		 */
-		const String& getShadingLanguageName() const override;
-
-		/**
-		 * @copydoc RenderAPICore::setRenderTarget()
-		 */
-		void setRenderTarget(const SPtr<RenderTargetCore>& target) override;
-
-        /**
-		 * @copydoc RenderAPICore::setVertexBuffers()
-		 */
-		void setVertexBuffers(UINT32 index, SPtr<VertexBufferCore>* buffers, UINT32 numBuffers) override;
-
-		/**
-		 * @copydoc RenderAPICore::setIndexBuffer()
-		 */
-		void setIndexBuffer(const SPtr<IndexBufferCore>& buffer) override;
-
-		/**
-		 * @copydoc RenderAPICore::setVertexDeclaration()
-		 */
-		void setVertexDeclaration(const SPtr<VertexDeclarationCore>& vertexDeclaration) override;
-
-		/**
-		 * @copydoc RenderAPICore::setDrawOperation()
-		 */
-		void setDrawOperation(DrawOperationType op) override;
-
-        /**
-		 * @copydoc RenderAPICore::setScissorRect()
-		 */
-		void setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom) override;
-
-		/**
-		 * @copydoc RenderAPICore::setTexture()
-		 */
-		void setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& tex) override;
-
-		/**
-		 * @copydoc	RenderAPICore::setLoadStoreTexture
-		 */
-		void setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr,
-			const TextureSurface& surface) override;
-        
-		/**
-		 * @copydoc RenderAPICore::setSamplerState()
-		 */
-		void setSamplerState(GpuProgramType gptype, UINT16 unit, const SPtr<SamplerStateCore>& state) override;
-
-		/**
-		 * @copydoc RenderAPICore::setBlendState()
-		 */
-		void setBlendState(const SPtr<BlendStateCore>& blendState) override;
-
-		/**
-		 * @copydoc RenderAPICore::setRasterizerState()
-		 */
-		void setRasterizerState(const SPtr<RasterizerStateCore>& rasterizerState) override;
-
-		/**
-		 * @copydoc RenderAPICore::setDepthStencilState()
-		 */
-		void setDepthStencilState(const SPtr<DepthStencilStateCore>& depthStencilState, UINT32 stencilRefValue) override;
-
-		/**
-		 * @copydoc RenderAPICore::setViewport()
-		 */
-		void setViewport(const Rect2& area) override;
-
-		/**
-		 * @copydoc RenderAPICore::bindGpuProgram()
-		 */
-		void bindGpuProgram(const SPtr<GpuProgramCore>& prg) override;
-
-		/**
-		 * @copydoc RenderAPICore::unbindGpuProgram()
-		 */
-		void unbindGpuProgram(GpuProgramType gptype) override;
-
-		/**
-		 * @copydoc RenderAPICore::setConstantBuffers()
-		 */
-		void setConstantBuffers(GpuProgramType gptype, const SPtr<GpuParamsCore>& params) override;
-
-		/**
-		 * @copydoc RenderAPICore::beginFrame()
-		 */
-		void beginFrame() override;
-
-		/**
-		 * @copydoc RenderAPICore::endFrame()
-		 */
-		void endFrame() override;
-
-		/**
-		 * @copydoc RenderAPICore::draw()
-		 */
-		void draw(UINT32 vertexOffset, UINT32 vertexCount) override;
-
-		/**
-		 * @copydoc RenderAPICore::drawIndexed()
-		 */
-		void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount) override;
-
-		/**
-		 * @copydoc RenderAPICore::clearRenderTarget()
-		 */
-		void clearRenderTarget(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0) override;
-
-		/**
-		 * @copydoc RenderAPICore::clearViewport()
-		 */
-		void clearViewport(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0) override;
-
-        /**
-		 * @copydoc RenderAPICore::getColorVertexElementType()
-		 */
-		VertexElementType getColorVertexElementType() const override;
-
-		/**
-		 * @copydoc RenderAPICore::getHorizontalTexelOffset()
-		 */
-		float getHorizontalTexelOffset() override;
-
-		/**
-		 * @copydoc RenderAPICore::getVerticalTexelOffset()
-		 */
-		float getVerticalTexelOffset() override;
-
-		/**
-		 * @copydoc RenderAPICore::getMinimumDepthInputValue()
-		 */
-		float getMinimumDepthInputValue() override;
-
-		 /**
-		 * @copydoc RenderAPICore::getMaximumDepthInputValue()
-		 */
-		float getMaximumDepthInputValue() override;
-
-		/**
-		 * @copydoc RenderAPICore::convertProjectionMatrix()
-		 */
-		void convertProjectionMatrix(const Matrix4& matrix, Matrix4& dest) override;
-
-		/**
-		 * @copydoc RenderAPICore::getGpuProgramHasColumnMajorMatrices
-		 */
-		bool getGpuProgramHasColumnMajorMatrices() const override;
-
-		/**
-		 * @copydoc RenderAPICore::generateParamBlockDesc()
-		 */
-		GpuParamBlockDesc generateParamBlockDesc(const String& name, Vector<GpuParamDataDesc>& params) override;
-
-		/************************************************************************/
-		/* 				Internal use by OpenGL RenderSystem only                */
-		/************************************************************************/
-
-		/**
-		 * @brief	Query has the main context been initialized.
-		 */
-		bool _isContextInitialized() const { return mGLInitialised; }
-
-		/**
-		 * @brief	Returns main context. Caller must ensure the context has been initialized.
-		 */
-		SPtr<GLContext> getMainContext() const { return mMainContext; } 
-
-		/**
-		 * @brief	Returns a support object you may use for creating
-		 */
-		GLSupport* getGLSupport() const { return mGLSupport; }
-
-	protected:
-		/**
-		 * @copydoc	RenderAPICore::initializePrepare
-		 */
-		void initializePrepare() override;
-
-		/**
-		 * @copydoc	RenderAPICore::initializeFinalize
-		 */
-		void initializeFinalize(const SPtr<RenderWindowCore>& primaryWindow) override;
-
-		/**
-		 * @copydoc	RenderAPICore::destroy_internal().
-		 */
-		void destroyCore() override;
-
-		/**
-		* @brief	Call before doing a draw operation, this method sets everything up.
-		*/
-		void beginDraw();
-
-		/**
-		* @brief	Needs to accompany every beginDraw after you are done with a single draw operation.
-		*/
-		void endDraw();
-
-		/**
-		 * @brief	Clear a part of a render target.
-		 */
-		void clearArea(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0, const Rect2I& clearArea = Rect2I::EMPTY);
-
-		/**
-		 * @brief	Set up clip planes against which all geometry will get clipped.
-		 */
-		void setClipPlanesImpl(const PlaneList& clipPlanes) override;
-
-		/**
-		 * @brief	Set up a clip plane at a specific clip plane index. If enabled,
-		 *			geometry will be clipped against the positive side of the plane.
-		 *
-		 * @note	Valid index range is [0, 5].
-		 */
-        void setClipPlane(UINT16 index, float A, float B, float C, float D);
-
-		/**
-		 * @brief	Enable or disable clipping against a clip plane at the specified index.
-		 *
-		 * @note	Valid index range is [0, 5].
-		 */
-        void enableClipPlane (UINT16 index, bool enable);
-
-		/**
-		* @brief	Changes the currently active texture unit. Any texture related operations
-		*			will then be performed on this unit.
-		*/
-		bool activateGLTextureUnit(UINT16 unit);
-
-		/**
-		 * @brief	Changes the active GPU program.
-		 */
-		void setActiveProgram(GpuProgramType gptype, const SPtr<GLSLGpuProgramCore>& program);
-
-		/**
-		 * @brief	Retrieves the active GPU program of the specified type.
-		 */
-		SPtr<GLSLGpuProgramCore> getActiveProgram(GpuProgramType gptype) const;
-
-		/**
-		 * @brief	Converts Banshee blend mode to OpenGL blend mode.
-		 */
-		GLint getBlendMode(BlendFactor blendMode) const;
-
-		/**
-		* @brief	Converts Banshee texture addressing mode to OpenGL texture addressing mode.
-		*/
-		GLint getTextureAddressingMode(TextureAddressingMode tam) const;
-
-		/**
-		 * @brief	Gets a combined min/mip filter value usable by OpenGL from the currently
-		 *			set min and mip filters.
-		 */
-		GLuint getCombinedMinMipFilter() const;
-
-		/**
-		* @brief	OpenGL shares all texture slots, but the engine prefers to keep textures
-		* 			separate per-stage. This will convert texture unit that is set per stage
-		* 			into a global texture unit usable by OpenGL.
-		*/
-		UINT32 getGLTextureUnit(GpuProgramType gptype, UINT32 unit);
-
-		/**
-		* @brief	OpenGL shares all buffer bindings, but the engine prefers to keep buffers
-		* 			separate per-stage. This will convert block buffer binding that is set per stage
-		* 			into a global block buffer binding usable by OpenGL.
-		*/
-		UINT32 getGLUniformBlockBinding(GpuProgramType gptype, UINT32 binding);
-
-		/**
-		* @brief	Returns the OpenGL specific mode used for drawing, depending on the
-		* 			currently set draw operation;
-		*/
-		GLint getGLDrawMode() const;
-
-		/**
-		 * @brief	Creates render system capabilities that specify which features are
-		 *			or aren't supported.
-		 */
-		RenderAPICapabilities* createRenderSystemCapabilities() const;
-
-		/**
-		 * @brief	Finish initialization by setting up any systems dependant on render system
-		 *			capabilities.
-		 */
-		void initFromCaps(RenderAPICapabilities* caps);
-
-		/**
-		 * @brief	Switch the currently used OpenGL context. You will need to re-bind
-		 *			any previously bound values manually. (e.g. textures, gpu programs and such)
-		 */
-		void switchContext(const SPtr<GLContext>& context);
-
-		/************************************************************************/
-		/* 								Sampler states                     		*/
-		/************************************************************************/
-
-		/**
-		 * @brief	Sets the texture addressing mode for a texture unit. This determines
-		 *			how are UV address values outside of [0, 1] range handled when sampling
-		 *			from texture.
-		 */
-        void setTextureAddressingMode(UINT16 stage, const UVWAddressingMode& uvw);
-
-		/**
-		 * @brief	Sets the texture border color for a texture unit. Border color
-		 *			determines color returned by the texture sampler when border addressing mode
-		 *			is used and texture address is outside of [0, 1] range.
-		 */
-        void setTextureBorderColor(UINT16 stage, const Color& color);
-
-		/**
-		 * @brief	Sets the mipmap bias value for a given texture unit. 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.
-		 */
-		void setTextureMipmapBias(UINT16 unit, float bias);
-
-		/**
-		 * @brief	Allows you to specify how is the texture bound to the specified texture unit filtered.
-		 *			Different filter types are used for different situations like magnifying or minifying a texture.
-		 */
-        void setTextureFiltering(UINT16 unit, FilterType ftype, FilterOptions filter);
-
-		/**
-		 * @brief	Sets anisotropy value for the specified texture unit.
-		 */
-		void setTextureAnisotropy(UINT16 unit, UINT32 maxAnisotropy);
-
-		/**
-		 * @brief	Gets anisotropy value for the specified texture unit.
-		 */
-		GLfloat getCurrentAnisotropy(UINT16 unit);
-
-		/************************************************************************/
-		/* 								Blend states                      		*/
-		/************************************************************************/
-
-		/**
-		 * @brief	Sets up blending mode that allows you to combine new pixels with pixels already in the render target.
-		 *			Final pixel value = (renderTargetPixel * sourceFactor) op (pixel * destFactor).
-		 */
-		void setSceneBlending(BlendFactor sourceFactor, BlendFactor destFactor, BlendOperation op);
-
-		/**
-		* @brief	Sets up blending mode that allows you to combine new pixels with pixels already in the render target.
-		*			Allows you to set up separate blend operations for alpha values.
-		*	
-		*			Final pixel value = (renderTargetPixel * sourceFactor) op (pixel * destFactor). (And the same for alpha)
-		*/
-		void setSceneBlending(BlendFactor sourceFactor, BlendFactor destFactor, BlendFactor sourceFactorAlpha, 
-			BlendFactor destFactorAlpha, BlendOperation op, BlendOperation alphaOp);
-
-		/**
-		 * @brief	Sets alpha test that allows you to reject pixels that fail the comparison function
-		 *			versus the provided reference value.
-		 */
-		void setAlphaTest(CompareFunction func, unsigned char value);
-
-		/**
-		 * @brief	Enable alpha to coverage. 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.
-		 */
-		void setAlphaToCoverage(bool enabled);
-
-		/**
-		 * @brief	Enables or disables writing to certain color channels of the render target.
-		 */
-		void setColorBufferWriteEnabled(bool red, bool green, bool blue, bool alpha);
-
-		/************************************************************************/
-		/* 								Rasterizer states                  		*/
-		/************************************************************************/
-
-		/**
-		 * @brief	Sets vertex winding order. Normally you would use this to cull back facing
-		 *			polygons.
-		 */
-		void setCullingMode(CullingMode mode);
-
-		/**
-		 * @brief	Sets the polygon rasterization mode. Determines how are polygons interpreted.
-		 */
-		void setPolygonMode(PolygonMode level);
-
-		/**
-		 * @brief	Sets a depth bias that will offset the depth values of new pixels by the specified amount.
-		 *			Final depth bias value is a combination of the constant depth bias and slope depth bias.
-		 *			Slope depth bias has more effect the higher the slope of the rendered polygon.
-		 *
-		 * @note	This is useful if you want to avoid z fighting for objects at the same or similar depth.
-		 */
-		void setDepthBias(float constantBias, float slopeScaleBias);
-
-		/**
-		 * @brief	Scissor test allows you to mask off rendering in all but a given rectangular area
-		 * 			identified by the rectangle set by setScissorRect().
-		 */
-		void setScissorTestEnable(bool enable);
-
-		/**
-		 * @brief	Enables or disables multisample antialiasing.
-		 */
-		void setMultisamplingEnable(bool enable);
-
-		/**
-		 * @brief	Enables or disables depth clipping (i.e. near/fear plane clipping).
-		 */
-		void setDepthClipEnable(bool enable);
-
-		/**
-		 * @brief	Enables or disables antialiased line rendering.
-		 */
-		void setAntialiasedLineEnable(bool enable);
-
-		/************************************************************************/
-		/* 						Depth stencil state                      		*/
-		/************************************************************************/
-		
-		/**
-		 * @brief	Should new pixels perform depth testing using the set depth comparison function before
-		 *			being written.
-		 */
-		void setDepthBufferCheckEnabled(bool enabled = true);
-
-		/**
-		 * @brief	Should new pixels write to the depth buffer.
-		 */
-		void setDepthBufferWriteEnabled(bool enabled = true);
-
-		/**
-		 * @brief	Sets comparison function used for depth testing. Determines how are new and existing
-		 *			pixel values compared - if comparison function returns true the new pixel is written.
-		 */
-		void setDepthBufferFunction(CompareFunction func = CMPF_LESS_EQUAL);
-
-		/**
-		 * @brief	Turns stencil tests on or off. By default this is disabled.
-		 *			Stencil testing allow you to mask out a part of the rendered image by using
-		 *			various stencil operations provided.
-		 */
-		void setStencilCheckEnabled(bool enabled);
-
-		/**
-		 * @brief	Allows you to set stencil operations that are performed when stencil test passes or fails.
-		 *
-		 * @param	stencilFailOp	Operation executed when stencil test fails.
-		 * @param	depthFailOp		Operation executed when stencil test succeeds but depth test fails.
-		 * @param	passOp			Operation executed when stencil test succeeds and depth test succeeds.
-		 * @param	front			Should the stencil operations be applied to front or back facing polygons.
-		 */
-		void setStencilBufferOperations(StencilOperation stencilFailOp = SOP_KEEP,
-			StencilOperation depthFailOp = SOP_KEEP, StencilOperation passOp = SOP_KEEP,
-			bool front = true);
-
-		/**
-		 * @brief	Sets a stencil buffer comparison function. The result of this will cause one of 3 actions 
-		 *			depending on whether the test fails, succeeds but with the depth buffer check still failing, 
-		 *			or succeeds with the depth buffer check passing too.
-		 *
-		 * @param func	Comparison function that determines whether a stencil test fails or passes. Reference value
-		 *				gets compared to the value already in the buffer using this function.
-		 * @param mask	The bitmask applied to both the stencil value and the reference value
-		 *				before comparison
-		 * @param ccw	If set to true, the stencil operations will be applied to counterclockwise
-		 *				faces. Otherwise they will be applied to clockwise faces.
-		 */
-		void setStencilBufferFunc(CompareFunction func = CMPF_ALWAYS_PASS, UINT32 mask = 0xFFFFFFFF, bool front = true);
-
-		/**
-		 * @brief	The bitmask applied to the stencil value before writing it to the stencil buffer.
-		 */
-		void setStencilBufferWriteMask(UINT32 mask = 0xFFFFFFFF);
-
-		/**
-		 * @brief	Sets a reference values used for stencil buffer comparisons. 
-		 * 			Actual comparison function and stencil operations are set by setting the DepthStencilState.
-		 */
-		void setStencilRefValue(UINT32 refValue);
-
-		/************************************************************************/
-		/* 							UTILITY METHODS                      		*/
-		/************************************************************************/
-
-		/**
-		 * @brief	Recalculates actual viewport dimensions based on currently 
-		 *			set viewport normalized dimensions and render target and applies
-		 *			them for further rendering.
-		 */
-		void applyViewport();
-
-		/**
-		 * @brief	Converts the provided matrix m into a representation usable by OpenGL.
-		 */
-		void makeGLMatrix(GLfloat gl_matrix[16], const Matrix4& m);
-
-		/**
-		 * @brief	Converts the engine depth/stencil compare function into OpenGL representation.
-		 */
-		GLint convertCompareFunction(CompareFunction func) const;
-
-		/**
-		 * @brief	Convers the engine stencil operation in OpenGL representation. Optionally inverts
-		 *			the operation (increment becomes decrement, etc.).
-		 */
-		GLint convertStencilOp(StencilOperation op, bool invert = false) const;
-
-		/**
-		 * @brief	Checks if there are any OpenGL errors and prints them to the log.
-		 */
-		bool checkForErrors() const;
-
-	private:
-		Rect2 mViewportNorm;
-		UINT32 mScissorTop, mScissorBottom, mScissorLeft, mScissorRight;
-		UINT32 mViewportLeft, mViewportTop, mViewportWidth, mViewportHeight;
-
-		UINT32 mStencilReadMask;
-		UINT32 mStencilWriteMask;
-		UINT32 mStencilRefValue;
-		CompareFunction mStencilCompareFront;
-		CompareFunction mStencilCompareBack;
-
-		// View matrix to set world against
-		Matrix4 mViewMatrix;
-
-		// Last min & mip filtering options, so we can combine them
-		FilterOptions mMinFilter;
-		FilterOptions mMipFilter;
-
-		// Holds texture type settings for every stage
-		UINT32	mNumTextureTypes;
-		GLenum* mTextureTypes;
-
-		bool mDepthWrite;
-		bool mColorWrite[4];
-
-		GLSupport* mGLSupport;
-		bool mGLInitialised;
-
-		GLSLProgramFactory* mGLSLProgramFactory;
-		GLSLProgramPipelineManager* mProgramPipelineManager;
-
-		SPtr<GLSLGpuProgramCore> mCurrentVertexProgram;
-		SPtr<GLSLGpuProgramCore> mCurrentFragmentProgram;
-		SPtr<GLSLGpuProgramCore> mCurrentGeometryProgram;
-		SPtr<GLSLGpuProgramCore> mCurrentHullProgram;
-		SPtr<GLSLGpuProgramCore> mCurrentDomainProgram;
-
-		const GLSLProgramPipeline* mActivePipeline;
-
-		UINT32 mFragmentTexOffset;
-		UINT32 mVertexTexOffset;
-		UINT32 mGeometryTexOffset;
-
-		UINT32 mFragmentUBOffset;
-		UINT32 mVertexUBOffset;
-		UINT32 mGeometryUBOffset;
-		UINT32 mHullUBOffset;
-		UINT32 mDomainUBOffset;
-		UINT32 mComputeUBOffset;
-
-		Vector<SPtr<VertexBufferCore>> mBoundVertexBuffers;
-		SPtr<VertexDeclarationCore> mBoundVertexDeclaration;
-		SPtr<IndexBufferCore> mBoundIndexBuffer;
-		DrawOperationType mCurrentDrawOperation;
-
-		SPtr<GLContext> mMainContext;
-		SPtr<GLContext> mCurrentContext;
-
-		bool mDrawCallInProgress;
-
-		UINT16 mActiveTextureUnit;
-    };
-}
+#pragma once
+
+#include "BsGLPrerequisites.h"
+#include "BsRenderAPI.h"
+#include "BsGLHardwareBufferManager.h"
+#include "BsGLSLProgramFactory.h"
+#include "BsVector4.h"
+
+namespace BansheeEngine 
+{
+	/**
+	 * @brief	Implementation of a render system using OpenGL. Provides abstracted
+	 *			access to various low level OpenGL methods.
+	 */
+    class BS_RSGL_EXPORT GLRenderAPI : public RenderAPICore
+    {
+    public:
+        GLRenderAPI();
+        ~GLRenderAPI();
+
+		/**
+		 * @copydoc RenderAPICore::getName()
+		 */
+		const StringID& getName() const override;
+
+		/**
+		 * @copydoc RenderAPICore::getShadingLanguageName()
+		 */
+		const String& getShadingLanguageName() const override;
+
+		/**
+		 * @copydoc RenderAPICore::setRenderTarget()
+		 */
+		void setRenderTarget(const SPtr<RenderTargetCore>& target, bool readOnlyDepthStencil = false) override;
+
+        /**
+		 * @copydoc RenderAPICore::setVertexBuffers()
+		 */
+		void setVertexBuffers(UINT32 index, SPtr<VertexBufferCore>* buffers, UINT32 numBuffers) override;
+
+		/**
+		 * @copydoc RenderAPICore::setIndexBuffer()
+		 */
+		void setIndexBuffer(const SPtr<IndexBufferCore>& buffer) override;
+
+		/**
+		 * @copydoc RenderAPICore::setVertexDeclaration()
+		 */
+		void setVertexDeclaration(const SPtr<VertexDeclarationCore>& vertexDeclaration) override;
+
+		/**
+		 * @copydoc RenderAPICore::setDrawOperation()
+		 */
+		void setDrawOperation(DrawOperationType op) override;
+
+        /**
+		 * @copydoc RenderAPICore::setScissorRect()
+		 */
+		void setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom) override;
+
+		/**
+		 * @copydoc RenderAPICore::setTexture()
+		 */
+		void setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& tex) override;
+
+		/**
+		 * @copydoc	RenderAPICore::setLoadStoreTexture
+		 */
+		void setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr,
+			const TextureSurface& surface) override;
+        
+		/**
+		 * @copydoc RenderAPICore::setSamplerState()
+		 */
+		void setSamplerState(GpuProgramType gptype, UINT16 unit, const SPtr<SamplerStateCore>& state) override;
+
+		/**
+		 * @copydoc RenderAPICore::setBlendState()
+		 */
+		void setBlendState(const SPtr<BlendStateCore>& blendState) override;
+
+		/**
+		 * @copydoc RenderAPICore::setRasterizerState()
+		 */
+		void setRasterizerState(const SPtr<RasterizerStateCore>& rasterizerState) override;
+
+		/**
+		 * @copydoc RenderAPICore::setDepthStencilState()
+		 */
+		void setDepthStencilState(const SPtr<DepthStencilStateCore>& depthStencilState, UINT32 stencilRefValue) override;
+
+		/**
+		 * @copydoc RenderAPICore::setViewport()
+		 */
+		void setViewport(const Rect2& area) override;
+
+		/**
+		 * @copydoc RenderAPICore::bindGpuProgram()
+		 */
+		void bindGpuProgram(const SPtr<GpuProgramCore>& prg) override;
+
+		/**
+		 * @copydoc RenderAPICore::unbindGpuProgram()
+		 */
+		void unbindGpuProgram(GpuProgramType gptype) override;
+
+		/**
+		 * @copydoc RenderAPICore::setConstantBuffers()
+		 */
+		void setConstantBuffers(GpuProgramType gptype, const SPtr<GpuParamsCore>& params) override;
+
+		/**
+		 * @copydoc RenderAPICore::beginFrame()
+		 */
+		void beginFrame() override;
+
+		/**
+		 * @copydoc RenderAPICore::endFrame()
+		 */
+		void endFrame() override;
+
+		/**
+		 * @copydoc RenderAPICore::draw()
+		 */
+		void draw(UINT32 vertexOffset, UINT32 vertexCount) override;
+
+		/**
+		 * @copydoc RenderAPICore::drawIndexed()
+		 */
+		void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount) override;
+
+		/**
+		 * @copydoc RenderAPICore::clearRenderTarget()
+		 */
+		void clearRenderTarget(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0) override;
+
+		/**
+		 * @copydoc RenderAPICore::clearViewport()
+		 */
+		void clearViewport(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0) override;
+
+        /**
+		 * @copydoc RenderAPICore::getColorVertexElementType()
+		 */
+		VertexElementType getColorVertexElementType() const override;
+
+		/**
+		 * @copydoc RenderAPICore::getHorizontalTexelOffset()
+		 */
+		float getHorizontalTexelOffset() override;
+
+		/**
+		 * @copydoc RenderAPICore::getVerticalTexelOffset()
+		 */
+		float getVerticalTexelOffset() override;
+
+		/**
+		 * @copydoc RenderAPICore::getMinimumDepthInputValue()
+		 */
+		float getMinimumDepthInputValue() override;
+
+		 /**
+		 * @copydoc RenderAPICore::getMaximumDepthInputValue()
+		 */
+		float getMaximumDepthInputValue() override;
+
+		/**
+		 * @copydoc RenderAPICore::convertProjectionMatrix()
+		 */
+		void convertProjectionMatrix(const Matrix4& matrix, Matrix4& dest) override;
+
+		/**
+		 * @copydoc RenderAPICore::getGpuProgramHasColumnMajorMatrices
+		 */
+		bool getGpuProgramHasColumnMajorMatrices() const override;
+
+		/**
+		 * @copydoc RenderAPICore::generateParamBlockDesc()
+		 */
+		GpuParamBlockDesc generateParamBlockDesc(const String& name, Vector<GpuParamDataDesc>& params) override;
+
+		/************************************************************************/
+		/* 				Internal use by OpenGL RenderSystem only                */
+		/************************************************************************/
+
+		/**
+		 * @brief	Query has the main context been initialized.
+		 */
+		bool _isContextInitialized() const { return mGLInitialised; }
+
+		/**
+		 * @brief	Returns main context. Caller must ensure the context has been initialized.
+		 */
+		SPtr<GLContext> getMainContext() const { return mMainContext; } 
+
+		/**
+		 * @brief	Returns a support object you may use for creating
+		 */
+		GLSupport* getGLSupport() const { return mGLSupport; }
+
+	protected:
+		/**
+		 * @copydoc	RenderAPICore::initializePrepare
+		 */
+		void initializePrepare() override;
+
+		/**
+		 * @copydoc	RenderAPICore::initializeFinalize
+		 */
+		void initializeFinalize(const SPtr<RenderWindowCore>& primaryWindow) override;
+
+		/**
+		 * @copydoc	RenderAPICore::destroy_internal().
+		 */
+		void destroyCore() override;
+
+		/**
+		* @brief	Call before doing a draw operation, this method sets everything up.
+		*/
+		void beginDraw();
+
+		/**
+		* @brief	Needs to accompany every beginDraw after you are done with a single draw operation.
+		*/
+		void endDraw();
+
+		/**
+		 * @brief	Clear a part of a render target.
+		 */
+		void clearArea(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0, const Rect2I& clearArea = Rect2I::EMPTY);
+
+		/**
+		 * @brief	Set up clip planes against which all geometry will get clipped.
+		 */
+		void setClipPlanesImpl(const PlaneList& clipPlanes) override;
+
+		/**
+		 * @brief	Set up a clip plane at a specific clip plane index. If enabled,
+		 *			geometry will be clipped against the positive side of the plane.
+		 *
+		 * @note	Valid index range is [0, 5].
+		 */
+        void setClipPlane(UINT16 index, float A, float B, float C, float D);
+
+		/**
+		 * @brief	Enable or disable clipping against a clip plane at the specified index.
+		 *
+		 * @note	Valid index range is [0, 5].
+		 */
+        void enableClipPlane (UINT16 index, bool enable);
+
+		/**
+		* @brief	Changes the currently active texture unit. Any texture related operations
+		*			will then be performed on this unit.
+		*/
+		bool activateGLTextureUnit(UINT16 unit);
+
+		/**
+		 * @brief	Changes the active GPU program.
+		 */
+		void setActiveProgram(GpuProgramType gptype, const SPtr<GLSLGpuProgramCore>& program);
+
+		/**
+		 * @brief	Retrieves the active GPU program of the specified type.
+		 */
+		SPtr<GLSLGpuProgramCore> getActiveProgram(GpuProgramType gptype) const;
+
+		/**
+		 * @brief	Converts Banshee blend mode to OpenGL blend mode.
+		 */
+		GLint getBlendMode(BlendFactor blendMode) const;
+
+		/**
+		* @brief	Converts Banshee texture addressing mode to OpenGL texture addressing mode.
+		*/
+		GLint getTextureAddressingMode(TextureAddressingMode tam) const;
+
+		/**
+		 * @brief	Gets a combined min/mip filter value usable by OpenGL from the currently
+		 *			set min and mip filters.
+		 */
+		GLuint getCombinedMinMipFilter() const;
+
+		/**
+		* @brief	OpenGL shares all texture slots, but the engine prefers to keep textures
+		* 			separate per-stage. This will convert texture unit that is set per stage
+		* 			into a global texture unit usable by OpenGL.
+		*/
+		UINT32 getGLTextureUnit(GpuProgramType gptype, UINT32 unit);
+
+		/**
+		* @brief	OpenGL shares all buffer bindings, but the engine prefers to keep buffers
+		* 			separate per-stage. This will convert block buffer binding that is set per stage
+		* 			into a global block buffer binding usable by OpenGL.
+		*/
+		UINT32 getGLUniformBlockBinding(GpuProgramType gptype, UINT32 binding);
+
+		/**
+		* @brief	Returns the OpenGL specific mode used for drawing, depending on the
+		* 			currently set draw operation;
+		*/
+		GLint getGLDrawMode() const;
+
+		/**
+		 * @brief	Creates render system capabilities that specify which features are
+		 *			or aren't supported.
+		 */
+		RenderAPICapabilities* createRenderSystemCapabilities() const;
+
+		/**
+		 * @brief	Finish initialization by setting up any systems dependant on render system
+		 *			capabilities.
+		 */
+		void initFromCaps(RenderAPICapabilities* caps);
+
+		/**
+		 * @brief	Switch the currently used OpenGL context. You will need to re-bind
+		 *			any previously bound values manually. (e.g. textures, gpu programs and such)
+		 */
+		void switchContext(const SPtr<GLContext>& context);
+
+		/************************************************************************/
+		/* 								Sampler states                     		*/
+		/************************************************************************/
+
+		/**
+		 * @brief	Sets the texture addressing mode for a texture unit. This determines
+		 *			how are UV address values outside of [0, 1] range handled when sampling
+		 *			from texture.
+		 */
+        void setTextureAddressingMode(UINT16 stage, const UVWAddressingMode& uvw);
+
+		/**
+		 * @brief	Sets the texture border color for a texture unit. Border color
+		 *			determines color returned by the texture sampler when border addressing mode
+		 *			is used and texture address is outside of [0, 1] range.
+		 */
+        void setTextureBorderColor(UINT16 stage, const Color& color);
+
+		/**
+		 * @brief	Sets the mipmap bias value for a given texture unit. 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.
+		 */
+		void setTextureMipmapBias(UINT16 unit, float bias);
+
+		/**
+		 * @brief	Allows you to specify how is the texture bound to the specified texture unit filtered.
+		 *			Different filter types are used for different situations like magnifying or minifying a texture.
+		 */
+        void setTextureFiltering(UINT16 unit, FilterType ftype, FilterOptions filter);
+
+		/**
+		 * @brief	Sets anisotropy value for the specified texture unit.
+		 */
+		void setTextureAnisotropy(UINT16 unit, UINT32 maxAnisotropy);
+
+		/**
+		 * @brief	Gets anisotropy value for the specified texture unit.
+		 */
+		GLfloat getCurrentAnisotropy(UINT16 unit);
+
+		/************************************************************************/
+		/* 								Blend states                      		*/
+		/************************************************************************/
+
+		/**
+		 * @brief	Sets up blending mode that allows you to combine new pixels with pixels already in the render target.
+		 *			Final pixel value = (renderTargetPixel * sourceFactor) op (pixel * destFactor).
+		 */
+		void setSceneBlending(BlendFactor sourceFactor, BlendFactor destFactor, BlendOperation op);
+
+		/**
+		* @brief	Sets up blending mode that allows you to combine new pixels with pixels already in the render target.
+		*			Allows you to set up separate blend operations for alpha values.
+		*	
+		*			Final pixel value = (renderTargetPixel * sourceFactor) op (pixel * destFactor). (And the same for alpha)
+		*/
+		void setSceneBlending(BlendFactor sourceFactor, BlendFactor destFactor, BlendFactor sourceFactorAlpha, 
+			BlendFactor destFactorAlpha, BlendOperation op, BlendOperation alphaOp);
+
+		/**
+		 * @brief	Sets alpha test that allows you to reject pixels that fail the comparison function
+		 *			versus the provided reference value.
+		 */
+		void setAlphaTest(CompareFunction func, unsigned char value);
+
+		/**
+		 * @brief	Enable alpha to coverage. 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.
+		 */
+		void setAlphaToCoverage(bool enabled);
+
+		/**
+		 * @brief	Enables or disables writing to certain color channels of the render target.
+		 */
+		void setColorBufferWriteEnabled(bool red, bool green, bool blue, bool alpha);
+
+		/************************************************************************/
+		/* 								Rasterizer states                  		*/
+		/************************************************************************/
+
+		/**
+		 * @brief	Sets vertex winding order. Normally you would use this to cull back facing
+		 *			polygons.
+		 */
+		void setCullingMode(CullingMode mode);
+
+		/**
+		 * @brief	Sets the polygon rasterization mode. Determines how are polygons interpreted.
+		 */
+		void setPolygonMode(PolygonMode level);
+
+		/**
+		 * @brief	Sets a depth bias that will offset the depth values of new pixels by the specified amount.
+		 *			Final depth bias value is a combination of the constant depth bias and slope depth bias.
+		 *			Slope depth bias has more effect the higher the slope of the rendered polygon.
+		 *
+		 * @note	This is useful if you want to avoid z fighting for objects at the same or similar depth.
+		 */
+		void setDepthBias(float constantBias, float slopeScaleBias);
+
+		/**
+		 * @brief	Scissor test allows you to mask off rendering in all but a given rectangular area
+		 * 			identified by the rectangle set by setScissorRect().
+		 */
+		void setScissorTestEnable(bool enable);
+
+		/**
+		 * @brief	Enables or disables multisample antialiasing.
+		 */
+		void setMultisamplingEnable(bool enable);
+
+		/**
+		 * @brief	Enables or disables depth clipping (i.e. near/fear plane clipping).
+		 */
+		void setDepthClipEnable(bool enable);
+
+		/**
+		 * @brief	Enables or disables antialiased line rendering.
+		 */
+		void setAntialiasedLineEnable(bool enable);
+
+		/************************************************************************/
+		/* 						Depth stencil state                      		*/
+		/************************************************************************/
+		
+		/**
+		 * @brief	Should new pixels perform depth testing using the set depth comparison function before
+		 *			being written.
+		 */
+		void setDepthBufferCheckEnabled(bool enabled = true);
+
+		/**
+		 * @brief	Should new pixels write to the depth buffer.
+		 */
+		void setDepthBufferWriteEnabled(bool enabled = true);
+
+		/**
+		 * @brief	Sets comparison function used for depth testing. Determines how are new and existing
+		 *			pixel values compared - if comparison function returns true the new pixel is written.
+		 */
+		void setDepthBufferFunction(CompareFunction func = CMPF_LESS_EQUAL);
+
+		/**
+		 * @brief	Turns stencil tests on or off. By default this is disabled.
+		 *			Stencil testing allow you to mask out a part of the rendered image by using
+		 *			various stencil operations provided.
+		 */
+		void setStencilCheckEnabled(bool enabled);
+
+		/**
+		 * @brief	Allows you to set stencil operations that are performed when stencil test passes or fails.
+		 *
+		 * @param	stencilFailOp	Operation executed when stencil test fails.
+		 * @param	depthFailOp		Operation executed when stencil test succeeds but depth test fails.
+		 * @param	passOp			Operation executed when stencil test succeeds and depth test succeeds.
+		 * @param	front			Should the stencil operations be applied to front or back facing polygons.
+		 */
+		void setStencilBufferOperations(StencilOperation stencilFailOp = SOP_KEEP,
+			StencilOperation depthFailOp = SOP_KEEP, StencilOperation passOp = SOP_KEEP,
+			bool front = true);
+
+		/**
+		 * @brief	Sets a stencil buffer comparison function. The result of this will cause one of 3 actions 
+		 *			depending on whether the test fails, succeeds but with the depth buffer check still failing, 
+		 *			or succeeds with the depth buffer check passing too.
+		 *
+		 * @param func	Comparison function that determines whether a stencil test fails or passes. Reference value
+		 *				gets compared to the value already in the buffer using this function.
+		 * @param mask	The bitmask applied to both the stencil value and the reference value
+		 *				before comparison
+		 * @param ccw	If set to true, the stencil operations will be applied to counterclockwise
+		 *				faces. Otherwise they will be applied to clockwise faces.
+		 */
+		void setStencilBufferFunc(CompareFunction func = CMPF_ALWAYS_PASS, UINT32 mask = 0xFFFFFFFF, bool front = true);
+
+		/**
+		 * @brief	The bitmask applied to the stencil value before writing it to the stencil buffer.
+		 */
+		void setStencilBufferWriteMask(UINT32 mask = 0xFFFFFFFF);
+
+		/**
+		 * @brief	Sets a reference values used for stencil buffer comparisons. 
+		 * 			Actual comparison function and stencil operations are set by setting the DepthStencilState.
+		 */
+		void setStencilRefValue(UINT32 refValue);
+
+		/************************************************************************/
+		/* 							UTILITY METHODS                      		*/
+		/************************************************************************/
+
+		/**
+		 * @brief	Recalculates actual viewport dimensions based on currently 
+		 *			set viewport normalized dimensions and render target and applies
+		 *			them for further rendering.
+		 */
+		void applyViewport();
+
+		/**
+		 * @brief	Converts the provided matrix m into a representation usable by OpenGL.
+		 */
+		void makeGLMatrix(GLfloat gl_matrix[16], const Matrix4& m);
+
+		/**
+		 * @brief	Converts the engine depth/stencil compare function into OpenGL representation.
+		 */
+		GLint convertCompareFunction(CompareFunction func) const;
+
+		/**
+		 * @brief	Convers the engine stencil operation in OpenGL representation. Optionally inverts
+		 *			the operation (increment becomes decrement, etc.).
+		 */
+		GLint convertStencilOp(StencilOperation op, bool invert = false) const;
+
+		/**
+		 * @brief	Checks if there are any OpenGL errors and prints them to the log.
+		 */
+		bool checkForErrors() const;
+
+	private:
+		Rect2 mViewportNorm;
+		UINT32 mScissorTop, mScissorBottom, mScissorLeft, mScissorRight;
+		UINT32 mViewportLeft, mViewportTop, mViewportWidth, mViewportHeight;
+
+		UINT32 mStencilReadMask;
+		UINT32 mStencilWriteMask;
+		UINT32 mStencilRefValue;
+		CompareFunction mStencilCompareFront;
+		CompareFunction mStencilCompareBack;
+
+		// View matrix to set world against
+		Matrix4 mViewMatrix;
+
+		// Last min & mip filtering options, so we can combine them
+		FilterOptions mMinFilter;
+		FilterOptions mMipFilter;
+
+		// Holds texture type settings for every stage
+		UINT32	mNumTextureTypes;
+		GLenum* mTextureTypes;
+
+		bool mDepthWrite;
+		bool mColorWrite[4];
+
+		GLSupport* mGLSupport;
+		bool mGLInitialised;
+
+		GLSLProgramFactory* mGLSLProgramFactory;
+		GLSLProgramPipelineManager* mProgramPipelineManager;
+
+		SPtr<GLSLGpuProgramCore> mCurrentVertexProgram;
+		SPtr<GLSLGpuProgramCore> mCurrentFragmentProgram;
+		SPtr<GLSLGpuProgramCore> mCurrentGeometryProgram;
+		SPtr<GLSLGpuProgramCore> mCurrentHullProgram;
+		SPtr<GLSLGpuProgramCore> mCurrentDomainProgram;
+
+		const GLSLProgramPipeline* mActivePipeline;
+
+		UINT32 mFragmentTexOffset;
+		UINT32 mVertexTexOffset;
+		UINT32 mGeometryTexOffset;
+
+		UINT32 mFragmentUBOffset;
+		UINT32 mVertexUBOffset;
+		UINT32 mGeometryUBOffset;
+		UINT32 mHullUBOffset;
+		UINT32 mDomainUBOffset;
+		UINT32 mComputeUBOffset;
+
+		Vector<SPtr<VertexBufferCore>> mBoundVertexBuffers;
+		SPtr<VertexDeclarationCore> mBoundVertexDeclaration;
+		SPtr<IndexBufferCore> mBoundIndexBuffer;
+		DrawOperationType mCurrentDrawOperation;
+
+		SPtr<GLContext> mMainContext;
+		SPtr<GLContext> mCurrentContext;
+
+		bool mDrawCallInProgress;
+
+		UINT16 mActiveTextureUnit;
+    };
+}

+ 1 - 1
BansheeGLRenderAPI/Source/BsGLRenderAPI.cpp

@@ -544,7 +544,7 @@ namespace BansheeEngine
 		applyViewport();
 	}
 
-	void GLRenderAPI::setRenderTarget(const SPtr<RenderTargetCore>& target)
+	void GLRenderAPI::setRenderTarget(const SPtr<RenderTargetCore>& target, bool readOnlyDepthStencil)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 

+ 11 - 29
RenderBeast/Include/BsLightRendering.h

@@ -15,28 +15,20 @@ namespace BansheeEngine
 		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatConeTransform)
 	BS_PARAM_BLOCK_END
 
-	/**
-	 * Manipulates PerLight parameter buffer used in various shaders.
-	 */
+	/** Manipulates PerLight parameter buffer used in various shaders. */
 	class PerLightParams
 	{
 	public:
-		/**
-		 * Updates data in the parameter buffer from the data in the provided light.
-		 */
+		/** Updates data in the parameter buffer from the data in the provided light. */
 		void setParameters(const LightCore* light);
 
-		/**
-		 * Returns the internal parameter buffer that can be bound to the pipeline.
-		 */
+		/** Returns the internal parameter buffer that can be bound to the pipeline. */
 		const SPtr<GpuParamBlockBufferCore>& getBuffer() const;
 	private:
 		PerLightParamBuffer mBuffer;
 	};
 
-	/**
-	 * Shader that renders directional light sources during deferred rendering light pass. 
-	 */
+	/** Shader that renders directional light sources during deferred rendering light pass. */
 	class DirectionalLightMat : public RendererMaterial<DirectionalLightMat>
 	{
 		RMAT_DEF("DeferredDirectionalLightPass.bsl");
@@ -44,14 +36,10 @@ namespace BansheeEngine
 	public:
 		DirectionalLightMat();
 
-		/**
-		 * Binds the gbuffer used for rendering the light.
-		 */
-		void setGBuffer(const SPtr<RenderTargets>& gbuffer);
+		/** Updates parameters that are common for all lights. */
+		void setStaticParameters(const SPtr<RenderTargets>& gbuffer, const SPtr<GpuParamBlockBufferCore>& perCamera);
 
-		/**
-		 * Updates the parameter buffers used by the material.
-		 */
+		/** Updates the parameter buffers used by the material. */
 		void setParameters(const LightCore* light);
 	private:
 		PerLightParams mParams; // Note: Should this buffer be shared between both point and directional lights?
@@ -60,9 +48,7 @@ namespace BansheeEngine
 		MaterialParamTextureCore mGBufferDepth;
 	};
 
-	/**
-	 * Shader that renders point (radial & spot) light sources during deferred rendering light pass. 
-	 */
+	/** Shader that renders point (radial & spot) light sources during deferred rendering light pass. */
 	class PointLightMat : public RendererMaterial<PointLightMat>
 	{
 		RMAT_DEF("DeferredPointLightPass.bsl");
@@ -70,14 +56,10 @@ namespace BansheeEngine
 	public:
 		PointLightMat();
 
-		/**
-		 * Binds the gbuffer used for rendering the light.
-		 */
-		void setGBuffer(const SPtr<RenderTargets>& gbuffer);
+		/** Updates parameters that are common for all lights.  */
+		void setStaticParameters(const SPtr<RenderTargets>& gbuffer, const SPtr<GpuParamBlockBufferCore>& perCamera);
 
-		/**
-		 * Updates the parameter buffers used by the material.
-		 */
+		/** Updates the parameter buffers used by the material. */
 		void setParameters(const LightCore* light);
 	private:
 		PerLightParams mParams; // Note: Should this buffer be shared between both point and directional lights?

+ 314 - 306
RenderBeast/Include/BsRenderBeast.h

@@ -1,307 +1,315 @@
-#pragma once
-
-#include "BsRenderBeastPrerequisites.h"
-#include "BsRenderer.h"
-#include "BsBounds.h"
-#include "BsRenderableElement.h"
-#include "BsSamplerOverrides.h"
-#include "BsRendererMaterial.h"
-#include "BsLightRendering.h"
-
-namespace BansheeEngine
-{
-	class BeastRenderableElement;
-
-	/**
-	 * Semantics that may be used for signaling the renderer
-	 * for what is a certain shader parameter used for.
-	 */
-	static StringID RPS_GBufferA = "GBufferA";
-	static StringID RPS_GBufferB = "GBufferB";
-	static StringID RPS_GBufferDepth = "GBufferDepth";
-
-	/** Basic shader that is used when no other is available. */
-	class DefaultMaterial : public RendererMaterial<DefaultMaterial> { RMAT_DEF("Default.bsl"); };
-
-	/**
-	 * @brief	Data used by the renderer when rendering renderable handlers.
-	 */
-	struct RenderableData
-	{
-		RenderableCore* renderable;
-		Vector<BeastRenderableElement> elements;
-		RenderableHandler* controller;
-	};
-
-	/**
-	 * @brief	Data bound to the shader when rendering a specific renderable.
-	 */
-	struct RenderableShaderData
-	{
-		Matrix4 worldTransform;
-		Matrix4 invWorldTransform;
-		Matrix4 worldNoScaleTransform;
-		Matrix4 invWorldNoScaleTransform;
-		float worldDeterminantSign;
-	};
-
-	/**
-	 * @brief	Data bound to the shader when rendering a with a specific camera.
-	 */
-	struct CameraShaderData
-	{
-		Vector3 viewDir;
-		Vector3 viewOrigin;
-		Matrix4 view;
-		Matrix4 proj;
-		Matrix4 viewProj;
-		Matrix4 invProj;
-		Vector2 deviceZToWorldZ;
-		Vector4 clipToUVScaleOffset;
-	};
-
-	/**
-	 * @copydoc	RenderableElement
-	 *
-	 * Contains additional data specific to RenderBeast renderer.
-	 */
-	class BS_BSRND_EXPORT BeastRenderableElement : public RenderableElement
-	{
-	public:
-		/**
-		 * @brief	Optional overrides for material sampler states.
-		 *			Used when renderer wants to override certain sampling
-		 *			properties on a global scale (e.g. filtering most commonly).
-		 */
-		MaterialSamplerOverrides* samplerOverrides;
-
-		/**
-		 * @brief	Id of the owner renderable.
-		 */
-		UINT32 renderableId;
-	};
-
-	/**
-	 * @brief	Default renderer for Banshee. Performs frustum culling, sorting and 
-	 *			renders objects in custom ways determine by renderable handlers.
-	 *
-	 * @note	Sim thread unless otherwise noted.
-	 */
-	class BS_BSRND_EXPORT RenderBeast : public Renderer
-	{
-		/**
-		 * @brief	Render data for a single render target.
-		 */
-		struct RenderTargetData
-		{
-			SPtr<RenderTargetCore> target;
-			Vector<const CameraCore*> cameras;
-		};
-
-		/**
-		 * @brief	Data used by the renderer for a camera.
-		 */
-		struct CameraData
-		{
-			RenderQueuePtr opaqueQueue;
-			RenderQueuePtr transparentQueue;
-
-			SPtr<RenderTargets> target;
-		};
-
-		/**
-		 * @brief	Data used by the renderer for lights.
-		 */
-		struct LightData
-		{
-			LightCore* internal;
-		};
-
-	public:
-		RenderBeast();
-		~RenderBeast() { }
-
-		/**
-		 * @copydoc	Renderer::getName
-		 */
-		virtual const StringID& getName() const override;
-
-		/**
-		 * @copydoc	Renderer::renderAll
-		 */
-		virtual void renderAll() override;
-
-		/**
-		 * @brief	Sets options used for controlling the rendering.
-		 */
-		void setOptions(const SPtr<CoreRendererOptions>& options) override;
-
-		/**
-		 * @brief	Returns current set of options used for controlling the rendering.
-		 */
-		SPtr<CoreRendererOptions> getOptions() const override;
-
-		/**
-		 * @copydoc	Renderer::initialize
-		 */
-		virtual void initialize() override;
-
-		/**
-		 * @copydoc	Renderer::destroy
-		 */
-		virtual void destroy() override;
-
-	private:
-		/**
-		 * @copydoc	Renderer::_notifyCameraAdded
-		 */
-		void _notifyCameraAdded(const CameraCore* camera) override;
-
-		/**
-		 * @copydoc	Renderer::_notifyCameraRemoved
-		 */
-		void _notifyCameraRemoved(const CameraCore* camera) override;
-
-		/**
-		 * @copydoc	Renderer::_notifyLightAdded
-		 */
-		void _notifyLightAdded(LightCore* light) override;
-
-		/**
-		 * @copydoc	Renderer::_notifyLightUpdated
-		 */
-		void _notifyLightUpdated(LightCore* light) override;
-
-		/**
-		 * @copydoc	Renderer::_notifyLightRemoved
-		 */
-		void _notifyLightRemoved(LightCore* light) override;
-
-		/**
-		 * @copydoc	Renderer::_notifyRenderableAdded
-		 */
-		void _notifyRenderableAdded(RenderableCore* renderable) override;
-
-		/**
-		 * @copydoc	Renderer::_notifyRenderableUpdated
-		 */
-		void _notifyRenderableUpdated(RenderableCore* renderable) override;
-
-		/**
-		 * @copydoc	Renderer::_notifyRenderableRemoved
-		 */
-		void _notifyRenderableRemoved(RenderableCore* renderable) override;
-
-		/**
-		 * @brief	Updates the render options on the core thread.
-		 *
-		 * @note	Core thread only.
-		 */
-		void syncRenderOptions(const RenderBeastOptions& options);
-
-		/**
-		 * @brief	Performs rendering over all camera proxies.
-		 *
-		 * @param	time	Current frame time in milliseconds.
-		 *
-		 * @note	Core thread only.
-		 */
-		void renderAllCore(float time);
-
-		/**
-		 * @brief	Populates camera render queues by determining visible renderable object.
-		 *
-		 * @param	camera	The camera to determine visibility for.
-		 */
-		void determineVisible(const CameraCore& camera);
-
-		/**
-		 * @brief	Renders all objects visible by the provided camera.
-		 *
-		 * @param	rtData	Render target data containing the camera to render.
-		 * @param	camIdx	Index of the camera to render.
-		 * 					
-		 * @note	Core thread only.
-		 */
-		void render(RenderTargetData& rtData, UINT32 camIdx);
-
-		/**
-		 * @brief	Creates data used by the renderer on the core thread.
-		 */
-		void initializeCore();
-
-		/**
-		 * @brief	Destroys data used by the renderer on the core thread.
-		 */
-		void destroyCore();
-
-		/**
-		 * @brief	Checks all sampler overrides in case material sampler states changed,
-		 *			and updates them.
-		 *
-		 * @param	force	If true, all sampler overrides will be updated, regardless of a change
-		 *					in the material was detected or not.
-		 */
-		void refreshSamplerOverrides(bool force = false);
-
-		/**
-		 * @brief	Extracts the necessary values from the projection matrix that allow you to transform
-		 * 			device Z value into world Z value.
-		 * 			
-		 * @param	projMatrix	Projection matrix that was used to create the device Z value to transform.
-		 * 						
-		 * @returns	Returns two values that can be used to transform device z to world z using this formula:
-		 * 			z = 1 / (deviceZ * x - y)
-		 */
-		static Vector2 getDeviceZTransform(const Matrix4& projMatrix);
-
-		/**
-		 * @brief	Populates the provided camera shader data object with data from the provided camera. The object can
-		 * 			then be used for populating per-camera parameter buffers.
-		 * 			
-		 * @note	Core thread.
-		 */
-		static CameraShaderData getCameraShaderData(const CameraCore& camera);
-
-		/**
-		 * @brief	Activates the specified pass on the pipeline.
-		 *
-		 * @param	pass			Pass to activate.
-		 * 
-		 * @note	Core thread.
-		 */
-		static void setPass(const SPtr<PassCore>& pass);
-
-		/**
-		 * @brief	Sets parameters (textures, samplers, buffers) for the currently active pass.
-		 *
-		 * @param	passParams			Structure containing parameters for all stages of the pass.
-		 * @param	samplerOverrides	Optional samplers to use instead of the those in the pass parameters.
-		 *								Number of samplers must match number in pass parameters.						
-		 * @note	Core thread.
-		 */
-		static void setPassParams(const SPtr<PassParametersCore>& passParams, const PassSamplerOverrides* samplerOverrides);
-
-		Vector<RenderTargetData> mRenderTargets; // Core thread
-		UnorderedMap<const CameraCore*, CameraData> mCameraData; // Core thread
-		UnorderedMap<SPtr<MaterialCore>, MaterialSamplerOverrides*> mSamplerOverrides; // Core thread
-
-		Vector<RenderableData> mRenderables; // Core thread
-		Vector<RenderableShaderData> mRenderableShaderData; // Core thread
-		Vector<Bounds> mWorldBounds; // Core thread
-
-		Vector<LightData> mDirectionalLights; // Core thread
-		Vector<LightData> mPointLights; // Core thread
-		Vector<Sphere> mLightWorldBounds; // Core thread
-
-		SPtr<RenderBeastOptions> mCoreOptions; // Core thread
-
-		DefaultMaterial* mDefaultMaterial; // Core thread
-		PointLightMat* mPointLightMat; // Core thread
-		DirectionalLightMat* mDirLightMat; // Core thread
-
-		StaticRenderableHandler* mStaticHandler;
-		SPtr<RenderBeastOptions> mOptions;
-		bool mOptionsDirty;
-	};
+#pragma once
+
+#include "BsRenderBeastPrerequisites.h"
+#include "BsRenderer.h"
+#include "BsBounds.h"
+#include "BsRenderableElement.h"
+#include "BsSamplerOverrides.h"
+#include "BsRendererMaterial.h"
+#include "BsLightRendering.h"
+
+namespace BansheeEngine
+{
+	class BeastRenderableElement;
+
+	/**
+	 * Semantics that may be used for signaling the renderer
+	 * for what is a certain shader parameter used for.
+	 */
+	static StringID RPS_GBufferA = "GBufferA";
+	static StringID RPS_GBufferB = "GBufferB";
+	static StringID RPS_GBufferDepth = "GBufferDepth";
+
+	/** Basic shader that is used when no other is available. */
+	class DefaultMaterial : public RendererMaterial<DefaultMaterial> { RMAT_DEF("Default.bsl"); };
+
+	/**
+	 * @brief	Data used by the renderer when rendering renderable handlers.
+	 */
+	struct RenderableData
+	{
+		RenderableCore* renderable;
+		Vector<BeastRenderableElement> elements;
+		RenderableHandler* controller;
+	};
+
+	/**
+	 * @brief	Data bound to the shader when rendering a specific renderable.
+	 */
+	struct RenderableShaderData
+	{
+		Matrix4 worldTransform;
+		Matrix4 invWorldTransform;
+		Matrix4 worldNoScaleTransform;
+		Matrix4 invWorldNoScaleTransform;
+		float worldDeterminantSign;
+	};
+
+	/**
+	 * @brief	Data bound to the shader when rendering a with a specific camera.
+	 */
+	struct CameraShaderData
+	{
+		Vector3 viewDir;
+		Vector3 viewOrigin;
+		Matrix4 view;
+		Matrix4 proj;
+		Matrix4 viewProj;
+		Matrix4 invProj;
+		Matrix4 invViewProj;
+		Vector2 deviceZToWorldZ;
+		Vector4 clipToUVScaleOffset;
+	};
+
+	/**
+	 * @copydoc	RenderableElement
+	 *
+	 * Contains additional data specific to RenderBeast renderer.
+	 */
+	class BS_BSRND_EXPORT BeastRenderableElement : public RenderableElement
+	{
+	public:
+		/**
+		 * @brief	Optional overrides for material sampler states.
+		 *			Used when renderer wants to override certain sampling
+		 *			properties on a global scale (e.g. filtering most commonly).
+		 */
+		MaterialSamplerOverrides* samplerOverrides;
+
+		/**
+		 * @brief	Id of the owner renderable.
+		 */
+		UINT32 renderableId;
+	};
+
+	/**
+	 * @brief	Default renderer for Banshee. Performs frustum culling, sorting and 
+	 *			renders objects in custom ways determine by renderable handlers.
+	 *
+	 * @note	Sim thread unless otherwise noted.
+	 */
+	class BS_BSRND_EXPORT RenderBeast : public Renderer
+	{
+		/**
+		 * @brief	Render data for a single render target.
+		 */
+		struct RenderTargetData
+		{
+			SPtr<RenderTargetCore> target;
+			Vector<const CameraCore*> cameras;
+		};
+
+		/**
+		 * @brief	Data used by the renderer for a camera.
+		 */
+		struct CameraData
+		{
+			RenderQueuePtr opaqueQueue;
+			RenderQueuePtr transparentQueue;
+
+			SPtr<RenderTargets> target;
+		};
+
+		/**
+		 * @brief	Data used by the renderer for lights.
+		 */
+		struct LightData
+		{
+			LightCore* internal;
+		};
+
+	public:
+		RenderBeast();
+		~RenderBeast() { }
+
+		/**
+		 * @copydoc	Renderer::getName
+		 */
+		virtual const StringID& getName() const override;
+
+		/**
+		 * @copydoc	Renderer::renderAll
+		 */
+		virtual void renderAll() override;
+
+		/**
+		 * @brief	Sets options used for controlling the rendering.
+		 */
+		void setOptions(const SPtr<CoreRendererOptions>& options) override;
+
+		/**
+		 * @brief	Returns current set of options used for controlling the rendering.
+		 */
+		SPtr<CoreRendererOptions> getOptions() const override;
+
+		/**
+		 * @copydoc	Renderer::initialize
+		 */
+		virtual void initialize() override;
+
+		/**
+		 * @copydoc	Renderer::destroy
+		 */
+		virtual void destroy() override;
+
+	private:
+		/**
+		 * @copydoc	Renderer::_notifyCameraAdded
+		 */
+		void _notifyCameraAdded(const CameraCore* camera) override;
+
+		/**
+		 * @copydoc	Renderer::_notifyCameraRemoved
+		 */
+		void _notifyCameraRemoved(const CameraCore* camera) override;
+
+		/**
+		 * @copydoc	Renderer::_notifyLightAdded
+		 */
+		void _notifyLightAdded(LightCore* light) override;
+
+		/**
+		 * @copydoc	Renderer::_notifyLightUpdated
+		 */
+		void _notifyLightUpdated(LightCore* light) override;
+
+		/**
+		 * @copydoc	Renderer::_notifyLightRemoved
+		 */
+		void _notifyLightRemoved(LightCore* light) override;
+
+		/**
+		 * @copydoc	Renderer::_notifyRenderableAdded
+		 */
+		void _notifyRenderableAdded(RenderableCore* renderable) override;
+
+		/**
+		 * @copydoc	Renderer::_notifyRenderableUpdated
+		 */
+		void _notifyRenderableUpdated(RenderableCore* renderable) override;
+
+		/**
+		 * @copydoc	Renderer::_notifyRenderableRemoved
+		 */
+		void _notifyRenderableRemoved(RenderableCore* renderable) override;
+
+		/**
+		 * @brief	Updates the render options on the core thread.
+		 *
+		 * @note	Core thread only.
+		 */
+		void syncRenderOptions(const RenderBeastOptions& options);
+
+		/**
+		 * @brief	Performs rendering over all camera proxies.
+		 *
+		 * @param	time	Current frame time in milliseconds.
+		 *
+		 * @note	Core thread only.
+		 */
+		void renderAllCore(float time);
+
+		/**
+		 * @brief	Populates camera render queues by determining visible renderable object.
+		 *
+		 * @param	camera	The camera to determine visibility for.
+		 */
+		void determineVisible(const CameraCore& camera);
+
+		/**
+		 * @brief	Renders all objects visible by the provided camera.
+		 *
+		 * @param	rtData	Render target data containing the camera to render.
+		 * @param	camIdx	Index of the camera to render.
+		 * 					
+		 * @note	Core thread only.
+		 */
+		void render(RenderTargetData& rtData, UINT32 camIdx);
+
+		/**
+		 * @brief	Creates data used by the renderer on the core thread.
+		 */
+		void initializeCore();
+
+		/**
+		 * @brief	Destroys data used by the renderer on the core thread.
+		 */
+		void destroyCore();
+
+		/**
+		 * @brief	Checks all sampler overrides in case material sampler states changed,
+		 *			and updates them.
+		 *
+		 * @param	force	If true, all sampler overrides will be updated, regardless of a change
+		 *					in the material was detected or not.
+		 */
+		void refreshSamplerOverrides(bool force = false);
+
+		/**
+		 * @brief	Extracts the necessary values from the projection matrix that allow you to transform
+		 * 			device Z value into world Z value.
+		 * 			
+		 * @param	projMatrix	Projection matrix that was used to create the device Z value to transform.
+		 * 						
+		 * @returns	Returns two values that can be used to transform device z to world z using this formula:
+		 * 			z = deviceZ * x - y.
+		 */
+		static Vector2 getDeviceZTransform();
+
+		/**
+		 * @brief	Populates the provided camera shader data object with data from the provided camera. The object can
+		 * 			then be used for populating per-camera parameter buffers.
+		 * 			
+		 * @note	Core thread.
+		 */
+		static CameraShaderData getCameraShaderData(const CameraCore& camera);
+
+		/**
+		 * @brief	Activates the specified pass on the pipeline.
+		 *
+		 * @param	pass			Pass to activate.
+		 * 
+		 * @note	Core thread.
+		 */
+		static void setPass(const SPtr<PassCore>& pass);
+
+		/**
+		 * @brief	Sets parameters (textures, samplers, buffers) for the currently active pass.
+		 *
+		 * @param	passParams			Structure containing parameters for all stages of the pass.
+		 * @param	samplerOverrides	Optional samplers to use instead of the those in the pass parameters.
+		 *								Number of samplers must match number in pass parameters.						
+		 * @note	Core thread.
+		 */
+		static void setPassParams(const SPtr<PassParametersCore>& passParams, const PassSamplerOverrides* samplerOverrides);
+
+		// Core thread only fields
+		Vector<RenderTargetData> mRenderTargets;
+		UnorderedMap<const CameraCore*, CameraData> mCameraData;
+		UnorderedMap<SPtr<MaterialCore>, MaterialSamplerOverrides*> mSamplerOverrides;
+
+		Vector<RenderableData> mRenderables;
+		Vector<RenderableShaderData> mRenderableShaderData;
+		Vector<Bounds> mWorldBounds;
+
+		Vector<LightData> mDirectionalLights;
+		Vector<LightData> mPointLights;
+		Vector<Sphere> mLightWorldBounds;
+
+		SPtr<DepthStencilStateCore> mPointLightInGeomDSState;
+		SPtr<DepthStencilStateCore> mPointLightOutGeomDSState;
+		SPtr<RasterizerStateCore> mPointLightInGeomRState;
+		SPtr<RasterizerStateCore> mPointLightOutGeomRState;
+
+		SPtr<RenderBeastOptions> mCoreOptions;
+
+		DefaultMaterial* mDefaultMaterial;
+		PointLightMat* mPointLightMat;
+		DirectionalLightMat* mDirLightMat;
+
+		// Sim thread only fields
+		StaticRenderableHandler* mStaticHandler;
+		SPtr<RenderBeastOptions> mOptions;
+		bool mOptionsDirty;
+	};
 }

+ 77 - 86
RenderBeast/Include/BsStaticRenderableHandler.h

@@ -1,87 +1,78 @@
-#pragma once
-
-#include "BsRenderBeastPrerequisites.h"
-#include "BsRenderableHandler.h"
-#include "BsGpuParamDesc.h"
-#include "BsGpuParam.h"
-#include "BsRenderableElement.h"
-#include "BsRenderBeast.h"
-#include "BsParamBlocks.h"
-
-namespace BansheeEngine
-{
-	BS_PARAM_BLOCK_BEGIN(PerFrameParamBuffer)
-		BS_PARAM_BLOCK_ENTRY(float, gTime)
-	BS_PARAM_BLOCK_END
-
-	BS_PARAM_BLOCK_BEGIN(PerCameraParamBuffer)
-		BS_PARAM_BLOCK_ENTRY(Vector3, gViewDir)
-		BS_PARAM_BLOCK_ENTRY(Vector3, gViewOrigin)
-		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatViewProj)
-		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatView)
-		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatProj)
-		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatInvProj)
-		BS_PARAM_BLOCK_ENTRY(Vector2, gDeviceZToWorldZ)
-		BS_PARAM_BLOCK_ENTRY(Vector4, gClipToUVScaleOffset)
-	BS_PARAM_BLOCK_END
-
-	BS_PARAM_BLOCK_BEGIN(PerObjectParamBuffer)
-		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatWorldViewProj)
-		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatWorld)
-		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatInvWorld)
-		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatWorldNoScale)
-		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatInvWorldNoScale)
-		BS_PARAM_BLOCK_ENTRY(float, gWorldDeterminantSign)
-	BS_PARAM_BLOCK_END
-
-	/**
-	 * @brief	Renderable handler that manages initializing, updating and 
-	 * 			rendering of static renderable objects.
-	 */
-	class BS_BSRND_EXPORT StaticRenderableHandler : public RenderableHandler
-	{
-	public:
-		/**
-		 * @brief	Contains lit tex renderable data unique for each object.
-		 */
-		struct PerObjectData
-		{
-			Vector<RenderableElement::BufferBindInfo> perObjectBuffers;
-		};
-
-		StaticRenderableHandler();
-
-		/**
-		 * @copydoc	RenderableController::initializeRenderElem
-		 */
-		void initializeRenderElem(RenderableElement& element) override;
-
-		/**
-		 * @copydoc	RenderableController::bindPerObjectBuffers
-		 */
-		void bindPerObjectBuffers(const RenderableElement& element) override;
-
-		/**
-		 * @brief	Updates global per frame parameter buffers with new values. 
-		 *			To be called at the start of every frame.
-		 */
-		void updatePerFrameBuffers(float time);
-
-		/**
-		 * @brief	Updates global per frame parameter buffers with new values. 
-		 *			To be called at the start of rendering for every camera.
-		 */
-		void updatePerCameraBuffers(const CameraShaderData& cameraData);
-
-		/**
-		 * @brief	Updates object specific parameter buffers with new values.
-		 *			To be called whenever object specific values change.
-		 */
-		void updatePerObjectBuffers(RenderableElement& element, const RenderableShaderData& data, const Matrix4& wvpMatrix);
-
-	protected:
-		PerFrameParamBuffer mPerFrameParams;
-		PerCameraParamBuffer mPerCameraParams;
-		PerObjectParamBuffer mPerObjectParams;
-	};
+#pragma once
+
+#include "BsRenderBeastPrerequisites.h"
+#include "BsRenderableHandler.h"
+#include "BsGpuParamDesc.h"
+#include "BsGpuParam.h"
+#include "BsRenderableElement.h"
+#include "BsRenderBeast.h"
+#include "BsParamBlocks.h"
+
+namespace BansheeEngine
+{
+	BS_PARAM_BLOCK_BEGIN(PerFrameParamBuffer)
+		BS_PARAM_BLOCK_ENTRY(float, gTime)
+	BS_PARAM_BLOCK_END
+
+	BS_PARAM_BLOCK_BEGIN(PerCameraParamBuffer)
+		BS_PARAM_BLOCK_ENTRY(Vector3, gViewDir)
+		BS_PARAM_BLOCK_ENTRY(Vector3, gViewOrigin)
+		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatViewProj)
+		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatView)
+		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatProj)
+		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatInvProj)
+		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatInvViewProj)
+		BS_PARAM_BLOCK_ENTRY(Vector2, gDeviceZToWorldZ)
+		BS_PARAM_BLOCK_ENTRY(Vector4, gClipToUVScaleOffset)
+	BS_PARAM_BLOCK_END
+
+	BS_PARAM_BLOCK_BEGIN(PerObjectParamBuffer)
+		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatWorldViewProj)
+		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatWorld)
+		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatInvWorld)
+		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatWorldNoScale)
+		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatInvWorldNoScale)
+		BS_PARAM_BLOCK_ENTRY(float, gWorldDeterminantSign)
+	BS_PARAM_BLOCK_END
+
+	/** Renderable handler that manages initializing, updating and rendering of static renderable objects. */
+	class BS_BSRND_EXPORT StaticRenderableHandler : public RenderableHandler
+	{
+	public:
+		/** Contains lit tex renderable data unique for each object. */
+		struct PerObjectData
+		{
+			Vector<RenderableElement::BufferBindInfo> perObjectBuffers;
+		};
+
+		StaticRenderableHandler();
+
+		/** @copydoc RenderableController::initializeRenderElem */
+		void initializeRenderElem(RenderableElement& element) override;
+
+		/** @copydoc RenderableController::bindPerObjectBuffers */
+		void bindPerObjectBuffers(const RenderableElement& element) override;
+
+		/** Updates global per frame parameter buffers with new values. To be called at the start of every frame. */
+		void updatePerFrameBuffers(float time);
+
+		/**
+		 * Updates global per frame parameter buffers with new values. To be called at the start of rendering for every 
+		 * camera.
+		 */
+		void updatePerCameraBuffers(const CameraShaderData& cameraData);
+
+		/**
+		 * Updates object specific parameter buffers with new values. To be called whenever object specific values change.
+		 */
+		void updatePerObjectBuffers(RenderableElement& element, const RenderableShaderData& data, const Matrix4& wvpMatrix);
+
+		/** Returns a buffer that stores per-camera parameters. */
+		const PerCameraParamBuffer& getPerCameraParams() const { return mPerCameraParams; }
+
+	protected:
+		PerFrameParamBuffer mPerFrameParams;
+		PerCameraParamBuffer mPerCameraParams;
+		PerObjectParamBuffer mPerObjectParams;
+	};
 }

+ 6 - 2
RenderBeast/Source/BsLightRendering.cpp

@@ -81,11 +81,13 @@ namespace BansheeEngine
 		}
 	}
 
-	void DirectionalLightMat::setGBuffer(const SPtr<RenderTargets>& gbuffer)
+	void DirectionalLightMat::setStaticParameters(const SPtr<RenderTargets>& gbuffer, const SPtr<GpuParamBlockBufferCore>& perCamera)
 	{
 		mGBufferA.set(gbuffer->getTextureA());
 		mGBufferB.set(gbuffer->getTextureB());
 		mGBufferDepth.set(gbuffer->getTextureDepth());
+
+		mMaterial->setParamBlockBuffer("PerCamera", perCamera);
 	}
 
 	void DirectionalLightMat::setParameters(const LightCore* light)
@@ -109,11 +111,13 @@ namespace BansheeEngine
 		}
 	}
 
-	void PointLightMat::setGBuffer(const SPtr<RenderTargets>& gbuffer)
+	void PointLightMat::setStaticParameters(const SPtr<RenderTargets>& gbuffer, const SPtr<GpuParamBlockBufferCore>& perCamera)
 	{
 		mGBufferA.set(gbuffer->getTextureA());
 		mGBufferB.set(gbuffer->getTextureB());
 		mGBufferDepth.set(gbuffer->getTextureDepth());
+
+		mMaterial->setParamBlockBuffer("PerCamera", perCamera);
 	}
 
 	void PointLightMat::setParameters(const LightCore* light)

+ 65 - 20
RenderBeast/Source/BsRenderBeast.cpp

@@ -1,7 +1,5 @@
 #include "BsRenderBeast.h"
 #include "BsCCamera.h"
-#include "BsSceneObject.h"
-#include "BsSceneManager.h"
 #include "BsCRenderable.h"
 #include "BsMaterial.h"
 #include "BsMesh.h"
@@ -14,19 +12,14 @@
 #include "BsViewport.h"
 #include "BsRenderTarget.h"
 #include "BsRenderQueue.h"
-#include "BsGUIManager.h"
 #include "BsCoreThread.h"
 #include "BsGpuParams.h"
 #include "BsProfilerCPU.h"
 #include "BsShader.h"
-#include "BsTechnique.h"
-#include "BsHardwareBufferManager.h"
 #include "BsGpuParamBlockBuffer.h"
-#include "BsShader.h"
 #include "BsStaticRenderableHandler.h"
 #include "BsTime.h"
 #include "BsRenderableElement.h"
-#include "BsFrameAlloc.h"
 #include "BsCoreObjectManager.h"
 #include "BsRenderBeastOptions.h"
 #include "BsSamplerOverrides.h"
@@ -34,6 +27,7 @@
 #include "BsRenderTexturePool.h"
 #include "BsRenderTargets.h"
 #include "BsRendererUtility.h"
+#include "BsRenderStateManager.h"
 
 using namespace std::placeholders;
 
@@ -78,6 +72,29 @@ namespace BansheeEngine
 		mPointLightMat = bs_new<PointLightMat>();
 		mDirLightMat = bs_new<DirectionalLightMat>();
 
+		// TODO - Replace these manually assigned states with two different versions of point light shader once I implement
+		// a preprocessor parser for BSL
+		DEPTH_STENCIL_STATE_DESC inGeomDSDesc;
+		inGeomDSDesc.depthWriteEnable = false;
+		inGeomDSDesc.depthReadEnable = false;
+
+		mPointLightInGeomDSState = RenderStateCoreManager::instance().createDepthStencilState(inGeomDSDesc);
+
+		DEPTH_STENCIL_STATE_DESC outGeomDSDesc;
+		outGeomDSDesc.depthWriteEnable = false;
+
+		mPointLightOutGeomDSState = RenderStateCoreManager::instance().createDepthStencilState(outGeomDSDesc);
+
+		RASTERIZER_STATE_DESC inGeomRDesc;
+		inGeomRDesc.cullMode = CULL_CLOCKWISE;
+
+		mPointLightInGeomRState = RenderStateCoreManager::instance().createRasterizerState(inGeomRDesc);
+
+		RASTERIZER_STATE_DESC outGeomRDesc;
+		outGeomRDesc.cullMode = CULL_COUNTERCLOCKWISE;
+
+		mPointLightOutGeomRState = RenderStateCoreManager::instance().createRasterizerState(outGeomRDesc);
+
 		RenderTexturePool::startUp();
 	}
 
@@ -569,11 +586,13 @@ namespace BansheeEngine
 			camData.target->bindSceneColor();
 
 			// Render light pass
+			SPtr<GpuParamBlockBufferCore> perCameraBuffer = mStaticHandler->getPerCameraParams().getBuffer();
+
 			SPtr<MaterialCore> dirMaterial = mDirLightMat->getMaterial();
 			SPtr<PassCore> dirPass = dirMaterial->getPass(0);
 
 			setPass(dirPass);
-			mDirLightMat->setGBuffer(camData.target);
+			mDirLightMat->setStaticParameters(camData.target, perCameraBuffer);
 
 			for (auto& light : mDirectionalLights)
 			{
@@ -590,8 +609,9 @@ namespace BansheeEngine
 			SPtr<MaterialCore> pointMaterial = mPointLightMat->getMaterial();
 			SPtr<PassCore> pointPass = pointMaterial->getPass(0);
 
+			// TODO - Possibly use instanced drawing here as only two meshes are drawn with various properties
 			setPass(pointPass);
-			mPointLightMat->setGBuffer(camData.target);
+			mPointLightMat->setStaticParameters(camData.target, perCameraBuffer);
 
 			// TODO - Cull lights based on visibility, right now I just iterate over all of them. 
 			for (auto& light : mPointLights)
@@ -601,8 +621,30 @@ namespace BansheeEngine
 
 				mPointLightMat->setParameters(light.internal);
 
+				float distToLight = (light.internal->getBounds().getCenter() - camera->getPosition()).squaredLength();
+				float boundRadius = light.internal->getBounds().getRadius() * 1.05f + camera->getNearClipDistance() * 2.0f;
+
+				// TODO - Replace these manually assigned states with two different versions of point light shader once I implement
+				// a preprocessor parser for BSL
+				RenderAPICore& rapi = RenderAPICore::instance();
+
+				bool cameraInLightGeometry = distToLight < boundRadius * boundRadius;
+				if(cameraInLightGeometry)
+				{
+					// Draw back faces with no depth testing
+					rapi.setDepthStencilState(mPointLightInGeomDSState, 0);
+					rapi.setRasterizerState(mPointLightInGeomRState);
+
+				}
+				else
+				{
+					// Draw front faces with depth testing
+					rapi.setDepthStencilState(mPointLightOutGeomDSState, 0);
+					rapi.setRasterizerState(mPointLightOutGeomRState);
+				}
+
 				// TODO - Bind parameters to the pipeline manually as I don't need to re-bind gbuffer textures for every light
-				setPassParams(dirMaterial->getPassParameters(0), nullptr);
+				setPassParams(pointMaterial->getPassParameters(0), nullptr);
 				SPtr<MeshCore> mesh = light.internal->getMesh();
 				gRendererUtility().draw(mesh, mesh->getProperties().getSubMesh(0));
 			}
@@ -759,11 +801,13 @@ namespace BansheeEngine
 		cameraData.transparentQueue->sort();
 	}
 
-	Vector2 RenderBeast::getDeviceZTransform(const Matrix4& projMatrix)
+	Vector2 RenderBeast::getDeviceZTransform()
 	{
+		RenderAPICore& rapi = RenderAPICore::instance();
+
 		Vector2 output;
-		output.x = 1.0f / projMatrix[2][2];
-		output.y = projMatrix[2][3] / projMatrix[2][2];
+		output.x = rapi.getMaximumDepthInputValue() - rapi.getMinimumDepthInputValue();
+		output.y = -rapi.getMinimumDepthInputValue();
 
 		return output;
 	}
@@ -775,25 +819,26 @@ namespace BansheeEngine
 		data.view = camera.getViewMatrix();
 		data.viewProj = data.proj * data.view;
 		data.invProj = data.proj.inverse();
+		data.invViewProj = data.viewProj.inverse();
 		data.viewDir = camera.getForward();
 		data.viewOrigin = camera.getPosition();
-		data.deviceZToWorldZ = getDeviceZTransform(data.proj);
+		data.deviceZToWorldZ = getDeviceZTransform();
 
 		SPtr<ViewportCore> viewport = camera.getViewport();
 		SPtr<RenderTargetCore> rt = viewport->getTarget();
 
-		float halfWidth = viewport->getWidth() / 2.0f;
-		float halfHeight = viewport->getHeight() / 2.0f;
+		float halfWidth = viewport->getWidth() * 0.5f;
+		float halfHeight = viewport->getHeight() * 0.5f;
 
 		float rtWidth = (float)rt->getProperties().getWidth();
 		float rtHeight = (float)rt->getProperties().getHeight();
 
 		RenderAPICore& rapi = RenderAPICore::instance();
 
-		data.clipToUVScaleOffset.x = (halfWidth / 2.0f) / rtWidth;
-		data.clipToUVScaleOffset.y = (halfHeight / 2.0f) / rtHeight;
-		data.clipToUVScaleOffset.z = (viewport->getX() + halfWidth + rapi.getHorizontalTexelOffset()) / rtWidth;
-		data.clipToUVScaleOffset.w = (viewport->getY() + halfHeight + rapi.getHorizontalTexelOffset()) / rtHeight;
+		data.clipToUVScaleOffset.x = halfWidth / rtWidth;
+		data.clipToUVScaleOffset.y = -halfHeight / rtHeight;
+		data.clipToUVScaleOffset.z = viewport->getX() / rtWidth + (halfWidth + rapi.getHorizontalTexelOffset()) / rtWidth;
+		data.clipToUVScaleOffset.w = viewport->getY() / rtHeight + (halfHeight + rapi.getVerticalTexelOffset()) / rtHeight;
 
 		return data;
 	}

+ 198 - 198
RenderBeast/Source/BsRenderTargets.cpp

@@ -1,199 +1,199 @@
-#include "BsRenderTargets.h"
-#include "BsRenderTexturePool.h"
-#include "BsViewport.h"
-#include "BsRenderAPI.h"
-#include "BsTextureManager.h"
-
-namespace BansheeEngine
-{
-	RenderTargets::RenderTargets(const SPtr<ViewportCore>& viewport, bool hdr, UINT32 numSamples)
-		:mNumSamples(numSamples), mHDR(hdr), mViewport(viewport)
-	{
-		if (hdr)
-			mDiffuseFormat = PF_FLOAT_R11G11B10;
-		else
-			mDiffuseFormat = PF_B8G8R8X8;
-
-		mNormalFormat = PF_UNORM_R10G10B10A2;
-	}
-
-	SPtr<RenderTargets> RenderTargets::create(const SPtr<ViewportCore>& viewport, bool hdr, UINT32 numSamples)
-	{
-		return bs_shared_ptr<RenderTargets>(new (bs_alloc<RenderTargets>()) RenderTargets(viewport, hdr, numSamples));
-	}
-
-	void RenderTargets::allocate()
-	{
-		RenderTexturePool& texPool = RenderTexturePool::instance();
-
-		UINT32 width = getWidth();
-		UINT32 height = getHeight();
-
-		SPtr<PooledRenderTexture> newAlbedoRT = texPool.get(mDiffuseFormat, width, height, false, mNumSamples);
-		SPtr<PooledRenderTexture> newNormalRT = texPool.get(mNormalFormat, width, height, false, mNumSamples);
-		SPtr<PooledRenderTexture> newDepthRT = texPool.get(PF_D24S8, width, height, false, mNumSamples);
-
-		SPtr<PooledRenderTexture> newColorRT = nullptr;
-
-		// See if I can use the final output color target for gbuffer rendering, this saves a little memory
-		SPtr<RenderTargetCore> resolvedRT = mViewport->getTarget();
-		const RenderTargetProperties& resolvedRTProps = resolvedRT->getProperties();
-
-		bool useResolvedColor = !resolvedRTProps.isWindow() &&
-			mViewport->getWidth() == getWidth() &&
-			mViewport->getHeight() == getHeight() &&
-			((resolvedRTProps.getMultisampleCount() <= 1) == (mNumSamples <= 1) ||
-			resolvedRTProps.getMultisampleCount() == mNumSamples);
-
-		if (!useResolvedColor)
-			newColorRT = texPool.get(PF_B8G8R8X8, width, height, false, mNumSamples);
-
-		bool rebuildTargets = newColorRT != mSceneColorTex || newAlbedoRT != mAlbedoTex || newNormalRT != mNormalTex || newDepthRT != mDepthTex;
-
-		mSceneColorTex = newColorRT;
-		mAlbedoTex = newAlbedoRT;
-		mNormalTex = newNormalRT;
-		mDepthTex = newDepthRT;
-
-		if (mGBufferRT == nullptr || mSceneColorRT == nullptr || rebuildTargets)
-		{
-			MULTI_RENDER_TEXTURE_CORE_DESC gbufferDesc;
-			gbufferDesc.colorSurfaces.resize(3);
-
-			SPtr<TextureCore> sceneColorTex = nullptr;
-
-			if (newColorRT != nullptr)
-				sceneColorTex = newColorRT->texture;
-			else // Re-using output scene color texture
-			{
-				SPtr<RenderTextureCore> resolvedRTex = std::static_pointer_cast<RenderTextureCore>(resolvedRT);
-				sceneColorTex = resolvedRTex->getBindableColorTexture();
-			}
-
-			gbufferDesc.colorSurfaces[0].texture = sceneColorTex;
-			gbufferDesc.colorSurfaces[0].face = 0;
-			gbufferDesc.colorSurfaces[0].mipLevel = 0;
-
-			gbufferDesc.colorSurfaces[1].texture = mAlbedoTex->texture;
-			gbufferDesc.colorSurfaces[1].face = 0;
-			gbufferDesc.colorSurfaces[1].mipLevel = 0;
-
-			gbufferDesc.colorSurfaces[2].texture = mNormalTex->texture;
-			gbufferDesc.colorSurfaces[2].face = 0;
-			gbufferDesc.colorSurfaces[2].mipLevel = 0;
-
-			gbufferDesc.depthStencilSurface.texture = mDepthTex->texture;
-			gbufferDesc.depthStencilSurface.face = 0;
-			gbufferDesc.depthStencilSurface.mipLevel = 0;
-
-			mGBufferRT = TextureCoreManager::instance().createMultiRenderTexture(gbufferDesc);
-
-			RENDER_TEXTURE_CORE_DESC sceneColorDesc;
-			sceneColorDesc.colorSurface.texture = sceneColorTex;
-			sceneColorDesc.colorSurface.face = 0;
-			sceneColorDesc.colorSurface.mipLevel = 0;
-
-			sceneColorDesc.depthStencilSurface.texture = mDepthTex->texture;
-			sceneColorDesc.depthStencilSurface.face = 0;
-			sceneColorDesc.depthStencilSurface.mipLevel = 0;
-
-			mSceneColorRT = TextureCoreManager::instance().createRenderTexture(sceneColorDesc);
-		}
-	}
-
-	void RenderTargets::release()
-	{
-		RenderAPICore& rapi = RenderAPICore::instance();
-		rapi.setRenderTarget(nullptr);
-
-		RenderTexturePool& texPool = RenderTexturePool::instance();
-
-		if (mSceneColorTex != nullptr)
-			texPool.release(mSceneColorTex);
-
-		texPool.release(mAlbedoTex);
-		texPool.release(mNormalTex);
-		texPool.release(mDepthTex);
-	}
-
-	void RenderTargets::bindGBuffer()
-	{
-		RenderAPICore& rapi = RenderAPICore::instance();
-		rapi.setRenderTarget(mGBufferRT);
-
-		Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
-		rapi.setViewport(area);
-
-		UINT32 clearBuffers = FBT_COLOR | FBT_DEPTH | FBT_STENCIL;
-		RenderAPICore::instance().clearViewport(clearBuffers, Color::ZERO, 1.0f, 0);
-	}
-
-	void RenderTargets::bindSceneColor()
-	{
-		RenderAPICore& rapi = RenderAPICore::instance();
-		rapi.setRenderTarget(mSceneColorRT);
-
-		Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
-		rapi.setViewport(area);
-	}
-
-	void RenderTargets::resolve()
-	{
-		// Prepare final render target
-		SPtr<RenderTargetCore> target = mViewport->getTarget();
-
-		RenderAPICore::instance().setRenderTarget(target);
-		RenderAPICore::instance().setViewport(mViewport->getNormArea());
-
-		// If using a separate scene color texture clear the final render target
-		if (mSceneColorTex == nullptr)
-		{
-			// Do nothing as final render target is already our scene color target
-		}
-		else
-		{
-			UINT32 clearBuffers = 0;
-			if (mViewport->getRequiresColorClear())
-				clearBuffers |= FBT_COLOR;
-
-			if (mViewport->getRequiresDepthClear())
-				clearBuffers |= FBT_DEPTH;
-
-			if (mViewport->getRequiresStencilClear())
-				clearBuffers |= FBT_STENCIL;
-
-			if (clearBuffers != 0)
-			{
-				RenderAPICore::instance().clearViewport(clearBuffers, mViewport->getClearColor(),
-					mViewport->getClearDepthValue(), mViewport->getClearStencilValue());
-			}
-
-			// TODO - Copy from internal scene color to final scene color
-		}
-	}
-
-	SPtr<TextureCore> RenderTargets::getTextureA() const
-	{
-		return mAlbedoTex->texture;
-	}
-
-	SPtr<TextureCore> RenderTargets::getTextureB() const
-	{
-		return mNormalTex->texture;
-	}
-
-	SPtr<TextureCore> RenderTargets::getTextureDepth() const
-	{
-		return mDepthTex->texture;
-	}
-
-	UINT32 RenderTargets::getWidth() const
-	{
-		return (UINT32)mViewport->getWidth();
-	}
-
-	UINT32 RenderTargets::getHeight() const
-	{
-		return (UINT32)mViewport->getHeight();
-	}
+#include "BsRenderTargets.h"
+#include "BsRenderTexturePool.h"
+#include "BsViewport.h"
+#include "BsRenderAPI.h"
+#include "BsTextureManager.h"
+
+namespace BansheeEngine
+{
+	RenderTargets::RenderTargets(const SPtr<ViewportCore>& viewport, bool hdr, UINT32 numSamples)
+		:mNumSamples(numSamples), mHDR(hdr), mViewport(viewport)
+	{
+		if (hdr)
+			mDiffuseFormat = PF_FLOAT_R11G11B10;
+		else
+			mDiffuseFormat = PF_B8G8R8X8;
+
+		mNormalFormat = PF_UNORM_R10G10B10A2;
+	}
+
+	SPtr<RenderTargets> RenderTargets::create(const SPtr<ViewportCore>& viewport, bool hdr, UINT32 numSamples)
+	{
+		return bs_shared_ptr<RenderTargets>(new (bs_alloc<RenderTargets>()) RenderTargets(viewport, hdr, numSamples));
+	}
+
+	void RenderTargets::allocate()
+	{
+		RenderTexturePool& texPool = RenderTexturePool::instance();
+
+		UINT32 width = getWidth();
+		UINT32 height = getHeight();
+
+		SPtr<PooledRenderTexture> newAlbedoRT = texPool.get(mDiffuseFormat, width, height, false, mNumSamples);
+		SPtr<PooledRenderTexture> newNormalRT = texPool.get(mNormalFormat, width, height, false, mNumSamples);
+		SPtr<PooledRenderTexture> newDepthRT = texPool.get(PF_D24S8, width, height, false, mNumSamples);
+
+		SPtr<PooledRenderTexture> newColorRT = nullptr;
+
+		// See if I can use the final output color target for gbuffer rendering, this saves a little memory
+		SPtr<RenderTargetCore> resolvedRT = mViewport->getTarget();
+		const RenderTargetProperties& resolvedRTProps = resolvedRT->getProperties();
+
+		bool useResolvedColor = !resolvedRTProps.isWindow() &&
+			mViewport->getWidth() == getWidth() &&
+			mViewport->getHeight() == getHeight() &&
+			((resolvedRTProps.getMultisampleCount() <= 1) == (mNumSamples <= 1) ||
+			resolvedRTProps.getMultisampleCount() == mNumSamples);
+
+		if (!useResolvedColor)
+			newColorRT = texPool.get(PF_B8G8R8X8, width, height, false, mNumSamples);
+
+		bool rebuildTargets = newColorRT != mSceneColorTex || newAlbedoRT != mAlbedoTex || newNormalRT != mNormalTex || newDepthRT != mDepthTex;
+
+		mSceneColorTex = newColorRT;
+		mAlbedoTex = newAlbedoRT;
+		mNormalTex = newNormalRT;
+		mDepthTex = newDepthRT;
+
+		if (mGBufferRT == nullptr || mSceneColorRT == nullptr || rebuildTargets)
+		{
+			MULTI_RENDER_TEXTURE_CORE_DESC gbufferDesc;
+			gbufferDesc.colorSurfaces.resize(3);
+
+			SPtr<TextureCore> sceneColorTex = nullptr;
+
+			if (newColorRT != nullptr)
+				sceneColorTex = newColorRT->texture;
+			else // Re-using output scene color texture
+			{
+				SPtr<RenderTextureCore> resolvedRTex = std::static_pointer_cast<RenderTextureCore>(resolvedRT);
+				sceneColorTex = resolvedRTex->getBindableColorTexture();
+			}
+
+			gbufferDesc.colorSurfaces[0].texture = sceneColorTex;
+			gbufferDesc.colorSurfaces[0].face = 0;
+			gbufferDesc.colorSurfaces[0].mipLevel = 0;
+
+			gbufferDesc.colorSurfaces[1].texture = mAlbedoTex->texture;
+			gbufferDesc.colorSurfaces[1].face = 0;
+			gbufferDesc.colorSurfaces[1].mipLevel = 0;
+
+			gbufferDesc.colorSurfaces[2].texture = mNormalTex->texture;
+			gbufferDesc.colorSurfaces[2].face = 0;
+			gbufferDesc.colorSurfaces[2].mipLevel = 0;
+
+			gbufferDesc.depthStencilSurface.texture = mDepthTex->texture;
+			gbufferDesc.depthStencilSurface.face = 0;
+			gbufferDesc.depthStencilSurface.mipLevel = 0;
+
+			mGBufferRT = TextureCoreManager::instance().createMultiRenderTexture(gbufferDesc);
+
+			RENDER_TEXTURE_CORE_DESC sceneColorDesc;
+			sceneColorDesc.colorSurface.texture = sceneColorTex;
+			sceneColorDesc.colorSurface.face = 0;
+			sceneColorDesc.colorSurface.mipLevel = 0;
+
+			sceneColorDesc.depthStencilSurface.texture = mDepthTex->texture;
+			sceneColorDesc.depthStencilSurface.face = 0;
+			sceneColorDesc.depthStencilSurface.mipLevel = 0;
+
+			mSceneColorRT = TextureCoreManager::instance().createRenderTexture(sceneColorDesc);
+		}
+	}
+
+	void RenderTargets::release()
+	{
+		RenderAPICore& rapi = RenderAPICore::instance();
+		rapi.setRenderTarget(nullptr);
+
+		RenderTexturePool& texPool = RenderTexturePool::instance();
+
+		if (mSceneColorTex != nullptr)
+			texPool.release(mSceneColorTex);
+
+		texPool.release(mAlbedoTex);
+		texPool.release(mNormalTex);
+		texPool.release(mDepthTex);
+	}
+
+	void RenderTargets::bindGBuffer()
+	{
+		RenderAPICore& rapi = RenderAPICore::instance();
+		rapi.setRenderTarget(mGBufferRT);
+
+		Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
+		rapi.setViewport(area);
+
+		UINT32 clearBuffers = FBT_COLOR | FBT_DEPTH | FBT_STENCIL;
+		RenderAPICore::instance().clearViewport(clearBuffers, Color::ZERO, 1.0f, 0);
+	}
+
+	void RenderTargets::bindSceneColor()
+	{
+		RenderAPICore& rapi = RenderAPICore::instance();
+		rapi.setRenderTarget(mSceneColorRT, true);
+
+		Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
+		rapi.setViewport(area);
+	}
+
+	void RenderTargets::resolve()
+	{
+		// Prepare final render target
+		SPtr<RenderTargetCore> target = mViewport->getTarget();
+
+		RenderAPICore::instance().setRenderTarget(target);
+		RenderAPICore::instance().setViewport(mViewport->getNormArea());
+
+		// If using a separate scene color texture clear the final render target
+		if (mSceneColorTex == nullptr)
+		{
+			// Do nothing as final render target is already our scene color target
+		}
+		else
+		{
+			UINT32 clearBuffers = 0;
+			if (mViewport->getRequiresColorClear())
+				clearBuffers |= FBT_COLOR;
+
+			if (mViewport->getRequiresDepthClear())
+				clearBuffers |= FBT_DEPTH;
+
+			if (mViewport->getRequiresStencilClear())
+				clearBuffers |= FBT_STENCIL;
+
+			if (clearBuffers != 0)
+			{
+				RenderAPICore::instance().clearViewport(clearBuffers, mViewport->getClearColor(),
+					mViewport->getClearDepthValue(), mViewport->getClearStencilValue());
+			}
+
+			// TODO - Copy from internal scene color to final scene color
+		}
+	}
+
+	SPtr<TextureCore> RenderTargets::getTextureA() const
+	{
+		return mAlbedoTex->texture;
+	}
+
+	SPtr<TextureCore> RenderTargets::getTextureB() const
+	{
+		return mNormalTex->texture;
+	}
+
+	SPtr<TextureCore> RenderTargets::getTextureDepth() const
+	{
+		return mDepthTex->texture;
+	}
+
+	UINT32 RenderTargets::getWidth() const
+	{
+		return (UINT32)mViewport->getWidth();
+	}
+
+	UINT32 RenderTargets::getHeight() const
+	{
+		return (UINT32)mViewport->getHeight();
+	}
 }

+ 134 - 133
RenderBeast/Source/BsStaticRenderableHandler.cpp

@@ -1,134 +1,135 @@
-#include "BsStaticRenderableHandler.h"
-#include "BsShader.h"
-#include "BsGpuParams.h"
-#include "BsRenderBeast.h"
-#include "BsMaterial.h"
-
-namespace BansheeEngine
-{
-	StaticRenderableHandler::StaticRenderableHandler()
-	{ }
-
-	void StaticRenderableHandler::initializeRenderElem(RenderableElement& element)
-	{
-		element.rendererData = PerObjectData();
-		PerObjectData* rendererData = any_cast_unsafe<PerObjectData>(&element.rendererData);
-
-		SPtr<ShaderCore> shader = element.material->getShader();
-		if (shader == nullptr)
-		{
-			LOGWRN("Missing shader on material.");
-			return;
-		}
-
-		const Map<String, SHADER_PARAM_BLOCK_DESC>& paramBlockDescs = shader->getParamBlocks();
-		String perFrameBlockName;
-		String perCameraBlockName;
-		String perObjectBlockName;
-
-		for (auto& paramBlockDesc : paramBlockDescs)
-		{
-			if (paramBlockDesc.second.rendererSemantic == RBS_PerFrame)
-				perFrameBlockName = paramBlockDesc.second.name;
-			else if (paramBlockDesc.second.rendererSemantic == RBS_PerCamera)
-				perCameraBlockName = paramBlockDesc.second.name;
-			else if (paramBlockDesc.second.rendererSemantic == RBS_PerObject)
-				perObjectBlockName = paramBlockDesc.second.name;
-		}
-
-		UINT32 numPasses = element.material->getNumPasses();
-		for (UINT32 i = 0; i < numPasses; i++)
-		{
-			SPtr<PassParametersCore> passParams = element.material->getPassParameters(i);
-
-			for (UINT32 j = 0; j < PassParametersCore::NUM_PARAMS; j++)
-			{
-				SPtr<GpuParamsCore> gpuParams = passParams->getParamByIdx(j);
-				if (gpuParams == nullptr)
-					continue;
-
-				const GpuParamDesc& paramsDesc = gpuParams->getParamDesc();
-
-				if (perFrameBlockName != "")
-				{
-					auto findIter = paramsDesc.paramBlocks.find(perFrameBlockName);
-					if (findIter != paramsDesc.paramBlocks.end())
-					{
-						// TODO - We only compare block sizes but not actual contents. Should I check them too?
-						//        Probably shouldn't concern myself with that here, instead check that on a higher level.
-						if (findIter->second.blockSize == mPerFrameParams.getDesc().blockSize)
-						{
-							UINT32 slotIdx = findIter->second.slot;
-							element.rendererBuffers.push_back(RenderableElement::BufferBindInfo(i, j, slotIdx, mPerFrameParams.getBuffer()));
-						}
-					}
-				}
-
-				if (perCameraBlockName != "")
-				{
-					auto findIter = paramsDesc.paramBlocks.find(perCameraBlockName);
-					if (findIter != paramsDesc.paramBlocks.end())
-					{
-						if (findIter->second.blockSize == mPerCameraParams.getDesc().blockSize)
-						{
-							UINT32 slotIdx = findIter->second.slot;
-							element.rendererBuffers.push_back(RenderableElement::BufferBindInfo(i, j, slotIdx, mPerCameraParams.getBuffer()));
-						}
-					}
-				}
-
-				if (perObjectBlockName != "")
-				{
-					auto findIter = paramsDesc.paramBlocks.find(perObjectBlockName);
-					if (findIter != paramsDesc.paramBlocks.end())
-					{
-						if (findIter->second.blockSize == mPerObjectParams.getDesc().blockSize)
-						{
-							UINT32 slotIdx = findIter->second.slot;
-							rendererData->perObjectBuffers.push_back(RenderableElement::BufferBindInfo(i, j, slotIdx, mPerObjectParams.getBuffer()));
-						}
-					}
-				}
-			}
-		}
-	}
-
-	void StaticRenderableHandler::bindPerObjectBuffers(const RenderableElement& element)
-	{
-		const PerObjectData* rendererData = any_cast_unsafe<PerObjectData>(&element.rendererData);
-		for (auto& perObjectBuffer : rendererData->perObjectBuffers)
-		{
-			SPtr<GpuParamsCore> params = element.material->getPassParameters(perObjectBuffer.passIdx)->getParamByIdx(perObjectBuffer.paramsIdx);
-
-			params->setParamBlockBuffer(perObjectBuffer.slotIdx, perObjectBuffer.buffer);
-		}
-	}
-
-	void StaticRenderableHandler::updatePerFrameBuffers(float time)
-	{
-		mPerFrameParams.gTime.set(time);
-	}
-
-	void StaticRenderableHandler::updatePerCameraBuffers(const CameraShaderData& cameraData)
-	{
-		mPerCameraParams.gViewDir.set(cameraData.viewDir);
-		mPerCameraParams.gViewOrigin.set(cameraData.viewOrigin);
-		mPerCameraParams.gMatView.set(cameraData.view);
-		mPerCameraParams.gMatProj.set(cameraData.proj);
-		mPerCameraParams.gMatViewProj.set(cameraData.viewProj);
-		mPerCameraParams.gMatInvProj.set(cameraData.invProj);
-		mPerCameraParams.gDeviceZToWorldZ.set(cameraData.deviceZToWorldZ);
-		mPerCameraParams.gClipToUVScaleOffset.set(cameraData.clipToUVScaleOffset);
-	}
-
-	void StaticRenderableHandler::updatePerObjectBuffers(RenderableElement& element, const RenderableShaderData& data, const Matrix4& wvpMatrix)
-	{
-		// TODO - If I kept all the values in the same structure maybe a simple memcpy directly into the constant buffer would be better (i.e. faster)?
-		mPerObjectParams.gMatWorld.set(data.worldTransform);
-		mPerObjectParams.gMatInvWorld.set(data.invWorldTransform);
-		mPerObjectParams.gMatWorldNoScale.set(data.worldNoScaleTransform);
-		mPerObjectParams.gMatInvWorldNoScale.set(data.invWorldNoScaleTransform);
-		mPerObjectParams.gWorldDeterminantSign.set(data.worldDeterminantSign);
-		mPerObjectParams.gMatWorldViewProj.set(wvpMatrix);
-	}
+#include "BsStaticRenderableHandler.h"
+#include "BsShader.h"
+#include "BsGpuParams.h"
+#include "BsRenderBeast.h"
+#include "BsMaterial.h"
+
+namespace BansheeEngine
+{
+	StaticRenderableHandler::StaticRenderableHandler()
+	{ }
+
+	void StaticRenderableHandler::initializeRenderElem(RenderableElement& element)
+	{
+		element.rendererData = PerObjectData();
+		PerObjectData* rendererData = any_cast_unsafe<PerObjectData>(&element.rendererData);
+
+		SPtr<ShaderCore> shader = element.material->getShader();
+		if (shader == nullptr)
+		{
+			LOGWRN("Missing shader on material.");
+			return;
+		}
+
+		const Map<String, SHADER_PARAM_BLOCK_DESC>& paramBlockDescs = shader->getParamBlocks();
+		String perFrameBlockName;
+		String perCameraBlockName;
+		String perObjectBlockName;
+
+		for (auto& paramBlockDesc : paramBlockDescs)
+		{
+			if (paramBlockDesc.second.rendererSemantic == RBS_PerFrame)
+				perFrameBlockName = paramBlockDesc.second.name;
+			else if (paramBlockDesc.second.rendererSemantic == RBS_PerCamera)
+				perCameraBlockName = paramBlockDesc.second.name;
+			else if (paramBlockDesc.second.rendererSemantic == RBS_PerObject)
+				perObjectBlockName = paramBlockDesc.second.name;
+		}
+
+		UINT32 numPasses = element.material->getNumPasses();
+		for (UINT32 i = 0; i < numPasses; i++)
+		{
+			SPtr<PassParametersCore> passParams = element.material->getPassParameters(i);
+
+			for (UINT32 j = 0; j < PassParametersCore::NUM_PARAMS; j++)
+			{
+				SPtr<GpuParamsCore> gpuParams = passParams->getParamByIdx(j);
+				if (gpuParams == nullptr)
+					continue;
+
+				const GpuParamDesc& paramsDesc = gpuParams->getParamDesc();
+
+				if (perFrameBlockName != "")
+				{
+					auto findIter = paramsDesc.paramBlocks.find(perFrameBlockName);
+					if (findIter != paramsDesc.paramBlocks.end())
+					{
+						// TODO - We only compare block sizes but not actual contents. Should I check them too?
+						//        Probably shouldn't concern myself with that here, instead check that on a higher level.
+						if (findIter->second.blockSize == mPerFrameParams.getDesc().blockSize)
+						{
+							UINT32 slotIdx = findIter->second.slot;
+							element.rendererBuffers.push_back(RenderableElement::BufferBindInfo(i, j, slotIdx, mPerFrameParams.getBuffer()));
+						}
+					}
+				}
+
+				if (perCameraBlockName != "")
+				{
+					auto findIter = paramsDesc.paramBlocks.find(perCameraBlockName);
+					if (findIter != paramsDesc.paramBlocks.end())
+					{
+						if (findIter->second.blockSize == mPerCameraParams.getDesc().blockSize)
+						{
+							UINT32 slotIdx = findIter->second.slot;
+							element.rendererBuffers.push_back(RenderableElement::BufferBindInfo(i, j, slotIdx, mPerCameraParams.getBuffer()));
+						}
+					}
+				}
+
+				if (perObjectBlockName != "")
+				{
+					auto findIter = paramsDesc.paramBlocks.find(perObjectBlockName);
+					if (findIter != paramsDesc.paramBlocks.end())
+					{
+						if (findIter->second.blockSize == mPerObjectParams.getDesc().blockSize)
+						{
+							UINT32 slotIdx = findIter->second.slot;
+							rendererData->perObjectBuffers.push_back(RenderableElement::BufferBindInfo(i, j, slotIdx, mPerObjectParams.getBuffer()));
+						}
+					}
+				}
+			}
+		}
+	}
+
+	void StaticRenderableHandler::bindPerObjectBuffers(const RenderableElement& element)
+	{
+		const PerObjectData* rendererData = any_cast_unsafe<PerObjectData>(&element.rendererData);
+		for (auto& perObjectBuffer : rendererData->perObjectBuffers)
+		{
+			SPtr<GpuParamsCore> params = element.material->getPassParameters(perObjectBuffer.passIdx)->getParamByIdx(perObjectBuffer.paramsIdx);
+
+			params->setParamBlockBuffer(perObjectBuffer.slotIdx, perObjectBuffer.buffer);
+		}
+	}
+
+	void StaticRenderableHandler::updatePerFrameBuffers(float time)
+	{
+		mPerFrameParams.gTime.set(time);
+	}
+
+	void StaticRenderableHandler::updatePerCameraBuffers(const CameraShaderData& cameraData)
+	{
+		mPerCameraParams.gViewDir.set(cameraData.viewDir);
+		mPerCameraParams.gViewOrigin.set(cameraData.viewOrigin);
+		mPerCameraParams.gMatView.set(cameraData.view);
+		mPerCameraParams.gMatProj.set(cameraData.proj);
+		mPerCameraParams.gMatViewProj.set(cameraData.viewProj);
+		mPerCameraParams.gMatInvProj.set(cameraData.invProj);
+		mPerCameraParams.gMatInvViewProj.set(cameraData.invViewProj);
+		mPerCameraParams.gDeviceZToWorldZ.set(cameraData.deviceZToWorldZ);
+		mPerCameraParams.gClipToUVScaleOffset.set(cameraData.clipToUVScaleOffset);
+	}
+
+	void StaticRenderableHandler::updatePerObjectBuffers(RenderableElement& element, const RenderableShaderData& data, const Matrix4& wvpMatrix)
+	{
+		// TODO - If I kept all the values in the same structure maybe a simple memcpy directly into the constant buffer would be better (i.e. faster)?
+		mPerObjectParams.gMatWorld.set(data.worldTransform);
+		mPerObjectParams.gMatInvWorld.set(data.invWorldTransform);
+		mPerObjectParams.gMatWorldNoScale.set(data.worldNoScaleTransform);
+		mPerObjectParams.gMatInvWorldNoScale.set(data.invWorldNoScaleTransform);
+		mPerObjectParams.gWorldDeterminantSign.set(data.worldDeterminantSign);
+		mPerObjectParams.gMatWorldViewProj.set(wvpMatrix);
+	}
 }