Просмотр исходного кода

Refactored render properties so they're in a single class, and added a property for flipped NDC y axis

BearishSun 9 лет назад
Родитель
Сommit
c8500a99d8

+ 111 - 111
Source/BansheeCore/Include/BsParamBlocks.h

@@ -1,112 +1,112 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsGpuParamDesc.h"
-#include "BsGpuParams.h"
-#include "BsRenderAPI.h"
-#include "BsGpuParamBlockBuffer.h"
-
-namespace BansheeEngine
-{
-	/** @cond INTERNAL */
-	/** @addtogroup Renderer
-	 *  @{
-	 */
-
-/** 
- * Starts a new custom parameter block. Custom parameter blocks allow you to create C++ structures that map directly
- * to GPU program buffers (e.g. uniform buffer in OpenGL or constant buffer in DX). Must be followed by BS_PARAM_BLOCK_END.
- */
-#define BS_PARAM_BLOCK_BEGIN(Name)																							\
-	struct Name																												\
-	{																														\
-		Name()																												\
-		{																													\
-			Vector<GpuParamDataDesc> params = getEntries();																	\
-			RenderAPICore& rapi = RenderAPICore::instance();																\
-																															\
-			mBlockDesc = rapi.generateParamBlockDesc(#Name, params);														\
-																															\
-			SPtr<GpuParamDesc> paramsDesc = bs_shared_ptr_new<GpuParamDesc>();												\
-			paramsDesc->paramBlocks[#Name] = mBlockDesc;																	\
-			for (auto& param : params)																						\
-				paramsDesc->params[param.name] = param;																		\
-																															\
-			mParams = GpuParamsCore::create(paramsDesc, rapi.getGpuProgramHasColumnMajorMatrices());						\
-																															\
-			mBuffer = GpuParamBlockBufferCore::create(mBlockDesc.blockSize * sizeof(UINT32));								\
-			mParams->setParamBlockBuffer(#Name, mBuffer);																	\
-			initEntries();																									\
-		}																													\
-																															\
-		const SPtr<GpuParamBlockBufferCore>& getBuffer() const { return mBuffer; }											\
-		const GpuParamBlockDesc& getDesc() const { return mBlockDesc; }														\
-																															\
-	private:																												\
-		struct META_FirstEntry {};																							\
-		static void META_GetPrevEntries(Vector<GpuParamDataDesc>& params, META_FirstEntry id) { }							\
-		void META_InitPrevEntry(const SPtr<GpuParamsCore>& params, META_FirstEntry id) { }									\
-																															\
-		typedef META_FirstEntry 
-
-/**
- * Registers a new entry in a parameter block. Must be called in between BS_PARAM_BLOCK_BEGIN and BS_PARAM_BLOCK_END calls.
- */
-#define BS_PARAM_BLOCK_ENTRY_ARRAY(Type, Name, NumElements)																	\
-		META_Entry_##Name;																									\
-																															\
-		struct META_NextEntry_##Name {};																					\
-		static void META_GetPrevEntries(Vector<GpuParamDataDesc>& params, META_NextEntry_##Name id)							\
-		{																													\
-			META_GetPrevEntries(params, META_Entry_##Name##());																\
-																															\
-			params.push_back(GpuParamDataDesc());																			\
-			GpuParamDataDesc& newEntry = params.back();																		\
-			newEntry.name = #Name;																							\
-			newEntry.type = (GpuParamDataType)TGpuDataParamInfo<Type>::TypeId;												\
-			newEntry.arraySize = NumElements;																				\
-		}																													\
-																															\
-		void META_InitPrevEntry(const SPtr<GpuParamsCore>& params, META_NextEntry_##Name id)								\
-		{																													\
-			META_InitPrevEntry(params, META_Entry_##Name##());																\
-			params->getParam(#Name, Name);																					\
-		}																													\
-																															\
-	public:																													\
-		TGpuDataParam<Type, true> Name;																						\
-																															\
-	private:																												\
-		typedef META_NextEntry_##Name
-
-/** 
- * Registers a new entry in a parameter block. Must be called in between BS_PARAM_BLOCK_BEGIN and BS_PARAM_BLOCK_END calls. 
- */
-#define BS_PARAM_BLOCK_ENTRY(Type, Name) BS_PARAM_BLOCK_ENTRY_ARRAY(Type, Name, 1)
-
-/** Ends parameter block definition. See BS_PARAM_BLOCK_BEGIN. */
-#define BS_PARAM_BLOCK_END																									\
-		META_LastEntry;																										\
-																															\
-		static Vector<GpuParamDataDesc> getEntries()																		\
-		{																													\
-			Vector<GpuParamDataDesc> entries;																				\
-			META_GetPrevEntries(entries, META_LastEntry());																	\
-			return entries;																									\
-		}																													\
-																															\
-		void initEntries()																									\
-		{																													\
-			META_InitPrevEntry(mParams, META_LastEntry());																	\
-		}																													\
-																															\
-		SPtr<GpuParamsCore> mParams;																						\
-		SPtr<GpuParamBlockBufferCore> mBuffer;																				\
-		GpuParamBlockDesc mBlockDesc;																						\
-	};
-
-	/** @} */
-	/** @endcond */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsGpuParamDesc.h"
+#include "BsGpuParams.h"
+#include "BsRenderAPI.h"
+#include "BsGpuParamBlockBuffer.h"
+
+namespace BansheeEngine
+{
+	/** @cond INTERNAL */
+	/** @addtogroup Renderer
+	 *  @{
+	 */
+
+/** 
+ * Starts a new custom parameter block. Custom parameter blocks allow you to create C++ structures that map directly
+ * to GPU program buffers (e.g. uniform buffer in OpenGL or constant buffer in DX). Must be followed by BS_PARAM_BLOCK_END.
+ */
+#define BS_PARAM_BLOCK_BEGIN(Name)																							\
+	struct Name																												\
+	{																														\
+		Name()																												\
+		{																													\
+			Vector<GpuParamDataDesc> params = getEntries();																	\
+			RenderAPICore& rapi = RenderAPICore::instance();																\
+																															\
+			mBlockDesc = rapi.generateParamBlockDesc(#Name, params);														\
+																															\
+			SPtr<GpuParamDesc> paramsDesc = bs_shared_ptr_new<GpuParamDesc>();												\
+			paramsDesc->paramBlocks[#Name] = mBlockDesc;																	\
+			for (auto& param : params)																						\
+				paramsDesc->params[param.name] = param;																		\
+																															\
+			mParams = GpuParamsCore::create(paramsDesc, rapi.getAPIInfo().getGpuProgramHasColumnMajorMatrices());			\
+																															\
+			mBuffer = GpuParamBlockBufferCore::create(mBlockDesc.blockSize * sizeof(UINT32));								\
+			mParams->setParamBlockBuffer(#Name, mBuffer);																	\
+			initEntries();																									\
+		}																													\
+																															\
+		const SPtr<GpuParamBlockBufferCore>& getBuffer() const { return mBuffer; }											\
+		const GpuParamBlockDesc& getDesc() const { return mBlockDesc; }														\
+																															\
+	private:																												\
+		struct META_FirstEntry {};																							\
+		static void META_GetPrevEntries(Vector<GpuParamDataDesc>& params, META_FirstEntry id) { }							\
+		void META_InitPrevEntry(const SPtr<GpuParamsCore>& params, META_FirstEntry id) { }									\
+																															\
+		typedef META_FirstEntry 
+
+/**
+ * Registers a new entry in a parameter block. Must be called in between BS_PARAM_BLOCK_BEGIN and BS_PARAM_BLOCK_END calls.
+ */
+#define BS_PARAM_BLOCK_ENTRY_ARRAY(Type, Name, NumElements)																	\
+		META_Entry_##Name;																									\
+																															\
+		struct META_NextEntry_##Name {};																					\
+		static void META_GetPrevEntries(Vector<GpuParamDataDesc>& params, META_NextEntry_##Name id)							\
+		{																													\
+			META_GetPrevEntries(params, META_Entry_##Name##());																\
+																															\
+			params.push_back(GpuParamDataDesc());																			\
+			GpuParamDataDesc& newEntry = params.back();																		\
+			newEntry.name = #Name;																							\
+			newEntry.type = (GpuParamDataType)TGpuDataParamInfo<Type>::TypeId;												\
+			newEntry.arraySize = NumElements;																				\
+		}																													\
+																															\
+		void META_InitPrevEntry(const SPtr<GpuParamsCore>& params, META_NextEntry_##Name id)								\
+		{																													\
+			META_InitPrevEntry(params, META_Entry_##Name##());																\
+			params->getParam(#Name, Name);																					\
+		}																													\
+																															\
+	public:																													\
+		TGpuDataParam<Type, true> Name;																						\
+																															\
+	private:																												\
+		typedef META_NextEntry_##Name
+
+/** 
+ * Registers a new entry in a parameter block. Must be called in between BS_PARAM_BLOCK_BEGIN and BS_PARAM_BLOCK_END calls. 
+ */
+#define BS_PARAM_BLOCK_ENTRY(Type, Name) BS_PARAM_BLOCK_ENTRY_ARRAY(Type, Name, 1)
+
+/** Ends parameter block definition. See BS_PARAM_BLOCK_BEGIN. */
+#define BS_PARAM_BLOCK_END																									\
+		META_LastEntry;																										\
+																															\
+		static Vector<GpuParamDataDesc> getEntries()																		\
+		{																													\
+			Vector<GpuParamDataDesc> entries;																				\
+			META_GetPrevEntries(entries, META_LastEntry());																	\
+			return entries;																									\
+		}																													\
+																															\
+		void initEntries()																									\
+		{																													\
+			META_InitPrevEntry(mParams, META_LastEntry());																	\
+		}																													\
+																															\
+		SPtr<GpuParamsCore> mParams;																						\
+		SPtr<GpuParamBlockBufferCore> mBuffer;																				\
+		GpuParamBlockDesc mBlockDesc;																						\
+	};
+
+	/** @} */
+	/** @endcond */
 }

+ 505 - 505
Source/BansheeCore/Include/BsRenderAPI.h

@@ -1,506 +1,506 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-#include "BsCorePrerequisites.h"
-#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
-{
-	/** @addtogroup RenderAPI
-	 *  @{
-	 */
-
-	/**
-	 * 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, UINT8 targetMask = 0xFF);
-
-		/** @copydoc RenderAPICore::clearViewport() */
-		static void clearViewport(CoreAccessor& accessor, UINT32 buffers, const Color& color = Color::Black, 
-			float depth = 1.0f, UINT16 stencil = 0, UINT8 targetMask = 0xFF);
-
-		/** @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::dispatchCompute() */
-		static void dispatchCompute(CoreAccessor& accessor, UINT32 numGroupsX, UINT32 numGroupsY = 1, UINT32 numGroupsZ = 1);
-
-		/** @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();
-	};
-
-	/** @cond INTERNAL */
-
-	/**
-	 * 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();
-
-		/**
-		 * Returns the name of the rendering system. 
-		 *
-		 * @note	Thread safe.
-		 */
-		virtual const StringID& getName() const = 0;
-
-		/**
-		 * Gets the name of the primary shading language used by the rendering system.
-		 *
-		 * @note	Thread safe.
-		 */
-		virtual const String& getShadingLanguageName() const = 0;
-
-		/**
-		 * Sets a sampler state for the specified texture unit.
-		 *
-		 * @see		SamplerState
-		 */
-		virtual void setSamplerState(GpuProgramType gptype, UINT16 texUnit, const SPtr<SamplerStateCore>& samplerState) = 0;
-
-		/**
-		 * Sets a blend state used for all active render targets.
-		 *
-		 * @see		BlendState
-		 */
-		virtual void setBlendState(const SPtr<BlendStateCore>& blendState) = 0;
-
-		/**
-		 * Sets a state that controls various rasterizer options. 
-		 *
-		 * @see		RasterizerState
-		 */
-		virtual void setRasterizerState(const SPtr<RasterizerStateCore>& rasterizerState) = 0;
-
-		/**
-		 * Sets a state that controls depth & stencil buffer options.
-		 *
-		 * @see		DepthStencilState
-		 */
-		virtual void setDepthStencilState(const SPtr<DepthStencilStateCore>& depthStencilState, UINT32 stencilRefValue) = 0;
-
-		/**
-		 * 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;
-
-		/**	Turns off a texture unit. */
-		virtual void disableTextureUnit(GpuProgramType gptype, UINT16 texUnit);
-
-		/**	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;
-
-		/**
-		 * Signals that rendering for a specific viewport has started. Any draw calls need to be called between beginFrame()
-		 * and endFrame(). 
-		 */
-		virtual void beginFrame() = 0;
-		
-		/** Ends that rendering to a specific viewport has ended. */
-		virtual void endFrame() = 0;
-
-		/**
-		 * Sets the active viewport that will be used for all render operations.
-		 *
-		 * @param[in]	area	Area of the viewport, in normalized ([0,1] range) coordinates.
-		 */
-		virtual void setViewport(const Rect2& area) = 0;
-
-		/**
-		 * 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;
-
-		/**
-		 * 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;
-
-		/**
-		 * 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;
-
-		/** Sets the draw operation that determines how to interpret the elements of the index or vertex buffers. */
-		virtual void setDrawOperation(DrawOperationType op) = 0;
-
-		/**
-		 * 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;
-
-		/** 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;
-
-		/** 
-		 * Executes the currently bound compute shader. 
-		 *
-		 * @param[in]	numGroupsX	Number of groups to start in the X direction. Must be in range [1, 65535].
-		 * @param[in]	numGroupsY	Number of groups to start in the Y direction. Must be in range [1, 65535].
-		 * @param[in]	numGroupsZ	Number of groups to start in the Z direction. Must be in range [1, 64].
-		 */
-		virtual void dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY = 1, UINT32 numGroupsZ = 1) = 0;
-
-		/** Swap the front and back buffer of the specified render target. */
-		virtual void swapBuffers(const SPtr<RenderTargetCore>& target);
-
-		/**
-		 * Gets the capabilities of the render system.
-		 *
-		 * @note	Thread safe.
-		 */
-		const RenderAPICapabilities* getCapabilities() const;
-
-		/** Returns information about the driver version. */
-		virtual const DriverVersion& getDriverVersion() const;
-
-		/**
-		 * 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);
-
-		/**
-		 * 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;
-
-		/** 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);
-
-		/**	Unbinds a program of a given type. */
-		virtual void unbindGpuProgram(GpuProgramType gptype);
-
-		/**	Query if a GPU program of a given type is currently bound. */
-		virtual bool isGpuProgramBound(GpuProgramType gptype);
-
-		/**	Sets up clip planes that will clip drawn geometry on the negative side of the planes. */
-		virtual void setClipPlanes(const PlaneList& clipPlanes);
-
-		/**	Adds a new clip plane. All drawn geometry will be clipped to this plane. */
-		virtual void addClipPlane(const Plane& p);
-
-		/**	Clears all clip planes. */
-		virtual void resetClipPlanes();
-
-		/**
-		 * 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;
-
-		/**
-		 * Clears the currently active render target.
-		 *
-		 * @param[in]	buffers		Combination of one or more elements of FrameBufferType denoting which buffers are 
-		 *							to be cleared.
-		 * @param[in]	color		(optional) The color to clear the color buffer with, if enabled.
-		 * @param[in]	depth		(optional) The value to initialize the depth buffer with, if enabled.
-		 * @param[in]	stencil		(optional) The value to initialize the stencil buffer with, if enabled.
-		 * @param[in]	targetMask	(optional) In case multiple render targets are bound, this allows you to control
-		 *							which ones to clear (0x01 first, 0x02 second, 0x04 third, etc., and combinations).
-		 */
-		virtual void clearRenderTarget(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, 
-			UINT16 stencil = 0, UINT8 targetMask = 0xFF) = 0;
-
-		/**
-		 * 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[in]	buffers		Combination of one or more elements of FrameBufferType denoting which buffers are to be
-		 *							cleared.
-		 * @param[in]	color		(optional) The color to clear the color buffer with, if enabled.
-		 * @param[in]	depth		(optional) The value to initialize the depth buffer with, if enabled.
-		 * @param[in]	stencil		(optional) The value to initialize the stencil buffer with, if enabled.
-		 * @param[in]	targetMask	(optional) In case multiple render targets are bound, this allows you to control
-		 *							which ones to clear (0x01 first, 0x02 second, 0x04 third, etc., and combinations).
-		 */
-		virtual void clearViewport(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, 
-			UINT16 stencil = 0, UINT8 targetMask = 0xFF) = 0;
-
-		/**
-		 * Change the render target into which we want to draw.
-		 *
-		 * @param[in]	target					Render target to draw to.
-		 * @param[in]	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;
-
-		/**
-		 * Returns information about available output devices and their video modes.
-		 *
-		 * @note	Thread safe.
-		 */
-		const VideoModeInfo& getVideoModeInfo() const { return *mVideoModeInfo; }
-
-		/************************************************************************/
-		/* 								UTILITY METHODS                    		*/
-		/************************************************************************/
-
-		/**
-		 * Gets the native type used for vertex colors.
-		 *
-		 * @note	Thread safe.
-		 */
-		virtual VertexElementType getColorVertexElementType() const = 0;
-
-		/**
-		 * 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;
-
-		/**
-		 * Gets horizontal texel offset used for mapping texels to pixels in this render system.
-		 *
-		 * @note	Thread safe.
-		 */
-		virtual float getHorizontalTexelOffset() = 0;
-
-		/**
-		 * Gets vertical texel offset used for mapping texels to pixels in this render system.
-		 *
-		 * @note		Thread safe.
-		 */
-		virtual float getVerticalTexelOffset() = 0;
-
-		/**
-		 * Gets the minimum (closest) depth value used by this render system.
-		 *
-		 * @note	Thread safe.
-		 */
-		virtual float getMinimumDepthInputValue() = 0;
-
-		/**
-		 * Gets the maximum (farthest) depth value used by this render system.
-		 *
-		 * @note	Thread safe.
-		 */
-		virtual float getMaximumDepthInputValue() = 0;
-
-		/**
-		 * Checks if vertex color needs to be flipped before sent to the shader.
-		 *
-		 * @note	Thread safe.
-		 */
-		virtual bool getVertexColorFlipRequired() const { return false; }
-
-		/** Checks whether GPU programs expect matrices in column major format. */
-		virtual bool getGpuProgramHasColumnMajorMatrices() const { return false; }
-
-		/**
-		 * 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[in]	name	Name to assign the parameter block.
-		 * @param[in]	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.		
-		 * @return				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:
-		/**
-		 * 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.
-		 * @note
-		 * Sim thread.
-		 */
-		RenderWindowPtr initialize(const RENDER_WINDOW_DESC& primaryWindowDesc);
-
-		/**
-		 * 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();
-
-		/**
-		 * 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);
-
-		/**
-		 * Shuts down the render API system and cleans up all resources.
-		 *
-		 * @note	Sim thread.
-		 */
-		void destroy();
-
-		/** 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;
-	};
-
-	/** @endcond */
-	/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+#include "BsCorePrerequisites.h"
+#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
+{
+	/** @addtogroup RenderAPI
+	 *  @{
+	 */
+
+	class RenderAPIInfo;
+
+	/**
+	 * 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, UINT8 targetMask = 0xFF);
+
+		/** @copydoc RenderAPICore::clearViewport() */
+		static void clearViewport(CoreAccessor& accessor, UINT32 buffers, const Color& color = Color::Black, 
+			float depth = 1.0f, UINT16 stencil = 0, UINT8 targetMask = 0xFF);
+
+		/** @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::dispatchCompute() */
+		static void dispatchCompute(CoreAccessor& accessor, UINT32 numGroupsX, UINT32 numGroupsY = 1, UINT32 numGroupsZ = 1);
+
+		/** @copydoc RenderAPICore::getVideoModeInfo */
+		static const VideoModeInfo& getVideoModeInfo();
+
+		/** @copydoc RenderAPICore::convertProjectionMatrix */
+		static void convertProjectionMatrix(const Matrix4& matrix, Matrix4& dest);
+
+		/** @copydoc RenderAPICore::getAPIInfo */
+		static const RenderAPIInfo& getAPIInfo();
+	};
+
+	/** Contains properties specific to a render API implementation. */
+	class RenderAPIInfo
+	{
+	public:
+		RenderAPIInfo(float horzTexelOffset, float vertTexelOffset, float minDepth, float maxDepth, 
+			VertexElementType vertexColorType, bool vertexColorFlip, bool ndcVerticalTopToBottom, bool columnMajorMatrices)
+			: mHorizontalTexelOffset(horzTexelOffset), mVerticalTexelOffset(vertTexelOffset), mMinDepth(minDepth)
+			, mMaxDepth(maxDepth), mVertexColorType(vertexColorType), mVertexColorFlip(vertexColorFlip)
+			, mNDCYAxisDown(ndcVerticalTopToBottom), mColumnMajorMatrices(columnMajorMatrices)
+		{
+			
+		}
+
+		/** Gets the native type used for vertex colors. */
+		VertexElementType getColorVertexElementType() const { return mVertexColorType; }
+
+		/** Gets horizontal texel offset used for mapping texels to pixels in this render system. */
+		float getHorizontalTexelOffset() const { return mHorizontalTexelOffset; }
+
+		/** Gets vertical texel offset used for mapping texels to pixels in this render system. */
+		float getVerticalTexelOffset() const { return mVerticalTexelOffset; }
+
+		/** Gets the minimum (closest) depth value used by this render system. */
+		float getMinimumDepthInputValue() const { return mMinDepth; }
+
+		/** Gets the maximum (farthest) depth value used by this render system. */
+		float getMaximumDepthInputValue() const { return mMaxDepth; }
+
+		/** Checks if vertex color needs to be flipped before sent to the shader. */
+		bool getVertexColorFlipRequired() const { return mVertexColorFlip; }
+
+		/** Checks whether GPU programs expect matrices in column major format. */
+		bool getGpuProgramHasColumnMajorMatrices() const { return mColumnMajorMatrices; }
+		
+		/** 
+		 * Returns true if Y axis in normalized device coordinates points down, false if up. If axis is pointing down the
+		 * NDC at the top is -1, and at the bottom is 1, otherwise reverse.
+		 */
+		bool getNDCYAxisDown() const { return mNDCYAxisDown; }
+
+	private:
+		float mHorizontalTexelOffset = 0.0f;
+		float mVerticalTexelOffset = 0.0f;
+		float mMinDepth = 0.0f;
+		float mMaxDepth = 1.0f;
+		VertexElementType mVertexColorType = VET_COLOR_ABGR;
+		bool mVertexColorFlip = false;
+		bool mNDCYAxisDown = true;
+		bool mColumnMajorMatrices = false;
+	};
+
+	/** @cond INTERNAL */
+
+	/**
+	 * 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();
+
+		/**
+		 * Returns the name of the rendering system. 
+		 *
+		 * @note	Thread safe.
+		 */
+		virtual const StringID& getName() const = 0;
+
+		/**
+		 * Gets the name of the primary shading language used by the rendering system.
+		 *
+		 * @note	Thread safe.
+		 */
+		virtual const String& getShadingLanguageName() const = 0;
+
+		/**
+		 * Sets a sampler state for the specified texture unit.
+		 *
+		 * @see		SamplerState
+		 */
+		virtual void setSamplerState(GpuProgramType gptype, UINT16 texUnit, const SPtr<SamplerStateCore>& samplerState) = 0;
+
+		/**
+		 * Sets a blend state used for all active render targets.
+		 *
+		 * @see		BlendState
+		 */
+		virtual void setBlendState(const SPtr<BlendStateCore>& blendState) = 0;
+
+		/**
+		 * Sets a state that controls various rasterizer options. 
+		 *
+		 * @see		RasterizerState
+		 */
+		virtual void setRasterizerState(const SPtr<RasterizerStateCore>& rasterizerState) = 0;
+
+		/**
+		 * Sets a state that controls depth & stencil buffer options.
+		 *
+		 * @see		DepthStencilState
+		 */
+		virtual void setDepthStencilState(const SPtr<DepthStencilStateCore>& depthStencilState, UINT32 stencilRefValue) = 0;
+
+		/**
+		 * 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;
+
+		/**	Turns off a texture unit. */
+		virtual void disableTextureUnit(GpuProgramType gptype, UINT16 texUnit);
+
+		/**	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;
+
+		/**
+		 * Signals that rendering for a specific viewport has started. Any draw calls need to be called between beginFrame()
+		 * and endFrame(). 
+		 */
+		virtual void beginFrame() = 0;
+		
+		/** Ends that rendering to a specific viewport has ended. */
+		virtual void endFrame() = 0;
+
+		/**
+		 * Sets the active viewport that will be used for all render operations.
+		 *
+		 * @param[in]	area	Area of the viewport, in normalized ([0,1] range) coordinates.
+		 */
+		virtual void setViewport(const Rect2& area) = 0;
+
+		/**
+		 * 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;
+
+		/**
+		 * 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;
+
+		/**
+		 * 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;
+
+		/** Sets the draw operation that determines how to interpret the elements of the index or vertex buffers. */
+		virtual void setDrawOperation(DrawOperationType op) = 0;
+
+		/**
+		 * 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;
+
+		/** 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;
+
+		/** 
+		 * Executes the currently bound compute shader. 
+		 *
+		 * @param[in]	numGroupsX	Number of groups to start in the X direction. Must be in range [1, 65535].
+		 * @param[in]	numGroupsY	Number of groups to start in the Y direction. Must be in range [1, 65535].
+		 * @param[in]	numGroupsZ	Number of groups to start in the Z direction. Must be in range [1, 64].
+		 */
+		virtual void dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY = 1, UINT32 numGroupsZ = 1) = 0;
+
+		/** Swap the front and back buffer of the specified render target. */
+		virtual void swapBuffers(const SPtr<RenderTargetCore>& target);
+
+		/**
+		 * Gets the capabilities of the render system.
+		 *
+		 * @note	Thread safe.
+		 */
+		const RenderAPICapabilities* getCapabilities() const;
+
+		/** Returns information about the driver version. */
+		virtual const DriverVersion& getDriverVersion() const;
+
+		/**
+		 * 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);
+
+		/**
+		 * 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;
+
+		/** 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);
+
+		/**	Unbinds a program of a given type. */
+		virtual void unbindGpuProgram(GpuProgramType gptype);
+
+		/**	Query if a GPU program of a given type is currently bound. */
+		virtual bool isGpuProgramBound(GpuProgramType gptype);
+
+		/**	Sets up clip planes that will clip drawn geometry on the negative side of the planes. */
+		virtual void setClipPlanes(const PlaneList& clipPlanes);
+
+		/**	Adds a new clip plane. All drawn geometry will be clipped to this plane. */
+		virtual void addClipPlane(const Plane& p);
+
+		/**	Clears all clip planes. */
+		virtual void resetClipPlanes();
+
+		/**
+		 * 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;
+
+		/**
+		 * Clears the currently active render target.
+		 *
+		 * @param[in]	buffers		Combination of one or more elements of FrameBufferType denoting which buffers are 
+		 *							to be cleared.
+		 * @param[in]	color		(optional) The color to clear the color buffer with, if enabled.
+		 * @param[in]	depth		(optional) The value to initialize the depth buffer with, if enabled.
+		 * @param[in]	stencil		(optional) The value to initialize the stencil buffer with, if enabled.
+		 * @param[in]	targetMask	(optional) In case multiple render targets are bound, this allows you to control
+		 *							which ones to clear (0x01 first, 0x02 second, 0x04 third, etc., and combinations).
+		 */
+		virtual void clearRenderTarget(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, 
+			UINT16 stencil = 0, UINT8 targetMask = 0xFF) = 0;
+
+		/**
+		 * 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[in]	buffers		Combination of one or more elements of FrameBufferType denoting which buffers are to be
+		 *							cleared.
+		 * @param[in]	color		(optional) The color to clear the color buffer with, if enabled.
+		 * @param[in]	depth		(optional) The value to initialize the depth buffer with, if enabled.
+		 * @param[in]	stencil		(optional) The value to initialize the stencil buffer with, if enabled.
+		 * @param[in]	targetMask	(optional) In case multiple render targets are bound, this allows you to control
+		 *							which ones to clear (0x01 first, 0x02 second, 0x04 third, etc., and combinations).
+		 */
+		virtual void clearViewport(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, 
+			UINT16 stencil = 0, UINT8 targetMask = 0xFF) = 0;
+
+		/**
+		 * Change the render target into which we want to draw.
+		 *
+		 * @param[in]	target					Render target to draw to.
+		 * @param[in]	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;
+
+		/**
+		 * Returns information about available output devices and their video modes.
+		 *
+		 * @note	Thread safe.
+		 */
+		const VideoModeInfo& getVideoModeInfo() const { return *mVideoModeInfo; }
+
+		/************************************************************************/
+		/* 								UTILITY METHODS                    		*/
+		/************************************************************************/
+
+		/**
+		 * 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;
+
+		/** 
+		 * Returns information about the specific API implementation. 
+		 *
+		 * @note	Thread safe.
+		 */
+		virtual const RenderAPIInfo& getAPIInfo() const = 0;
+
+		/**
+		 * 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[in]	name	Name to assign the parameter block.
+		 * @param[in]	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.		
+		 * @return				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:
+		/**
+		 * 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.
+		 * @note
+		 * Sim thread.
+		 */
+		RenderWindowPtr initialize(const RENDER_WINDOW_DESC& primaryWindowDesc);
+
+		/**
+		 * 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();
+
+		/**
+		 * 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);
+
+		/**
+		 * Shuts down the render API system and cleans up all resources.
+		 *
+		 * @note	Sim thread.
+		 */
+		void destroy();
+
+		/** 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;
+	};
+
+	/** @endcond */
+	/** @} */
 }

+ 109 - 109
Source/BansheeCore/Source/BsGpuProgram.cpp

@@ -1,110 +1,110 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsGpuProgram.h"
-#include "BsRenderAPICapabilities.h"
-#include "BsRenderAPI.h"
-#include "BsGpuParams.h"
-#include "BsGpuParamDesc.h"
-#include "BsGpuProgramManager.h"
-#include "BsGpuProgramRTTI.h"
-
-namespace BansheeEngine
-{
-	GpuProgramProperties::GpuProgramProperties(const String& source, const String& entryPoint,
-		GpuProgramType gptype, GpuProgramProfile profile)
-		:mSource(source), mEntryPoint(entryPoint), mType(gptype), mProfile(profile)
-	{ }
-		
-	GpuProgramCore::GpuProgramCore(const String& source, const String& entryPoint,
-		GpuProgramType gptype, GpuProgramProfile profile, bool isAdjacencyInfoRequired)
-		: mProperties(source, entryPoint, gptype, profile), mIsCompiled(false),
-		mNeedsAdjacencyInfo(isAdjacencyInfoRequired)
-	{
-		mParametersDesc = bs_shared_ptr_new<GpuParamDesc>();
-	}
-
-	bool GpuProgramCore::isSupported() const
-    {
-		if (!isRequiredCapabilitiesSupported())
-			return false;
-
-		RenderAPICore* rs = BansheeEngine::RenderAPICore::instancePtr();
-		String profile = rs->getCapabilities()->gpuProgProfileToRSSpecificProfile(getProperties().getProfile());
-
-		return rs->getCapabilities()->isShaderProfileSupported(profile);
-    }
-
-	bool GpuProgramCore::isRequiredCapabilitiesSupported() const
-	{
-		return true;
-	}
-
-	SPtr<GpuParamsCore> GpuProgramCore::createParameters()
-	{
-		return GpuParamsCore::create(mParametersDesc, RenderAPICore::instance().getGpuProgramHasColumnMajorMatrices());
-	}
-
-	SPtr<GpuProgramCore> GpuProgramCore::create(const String& source, const String& entryPoint, const String& language, GpuProgramType gptype,
-		GpuProgramProfile profile, bool requiresAdjacency)
-	{
-		return GpuProgramCoreManager::instance().create(source, entryPoint, language, gptype, profile, requiresAdjacency);
-	}
-
-	GpuProgram::GpuProgram(const String& source, const String& entryPoint, const String& language,
-		GpuProgramType gptype, GpuProgramProfile profile, bool isAdjacencyInfoRequired) 
-		: mProperties(source, entryPoint, gptype, profile), mLanguage(language),
-		 mNeedsAdjacencyInfo(isAdjacencyInfoRequired)
-    {
-
-    }
-
-	bool GpuProgram::isCompiled() const
-	{
-		return getCore()->isCompiled();
-	}
-
-	String GpuProgram::getCompileErrorMessage() const
-	{
-		return getCore()->getCompileErrorMessage();
-	}
-
-	GpuParamsPtr GpuProgram::createParameters()
-	{
-		return GpuParams::create(getCore()->getParamDesc(), RenderAPICore::instance().getGpuProgramHasColumnMajorMatrices());
-	}
-
-	GpuParamDescPtr GpuProgram::getParamDesc() const
-	{
-		return getCore()->getParamDesc();
-	}
-
-	SPtr<GpuProgramCore> GpuProgram::getCore() const
-	{
-		return std::static_pointer_cast<GpuProgramCore>(mCoreSpecific);
-	}
-
-	SPtr<CoreObjectCore> GpuProgram::createCore() const
-	{
-		return GpuProgramCoreManager::instance().createInternal(mProperties.getSource(), mProperties.getEntryPoint(),
-			mLanguage, mProperties.getType(), mProperties.getProfile(), mNeedsAdjacencyInfo);
-	}
-
-	GpuProgramPtr GpuProgram::create(const String& source, const String& entryPoint, const String& language, GpuProgramType gptype,
-		GpuProgramProfile profile, bool requiresAdjacency)
-	{
-		return GpuProgramManager::instance().create(source, entryPoint, language, gptype, profile, requiresAdjacency);
-	}
-
-	/************************************************************************/
-	/* 								SERIALIZATION                      		*/
-	/************************************************************************/
-	RTTITypeBase* GpuProgram::getRTTIStatic()
-	{
-		return GpuProgramRTTI::instance();
-	}
-
-	RTTITypeBase* GpuProgram::getRTTI() const
-	{
-		return GpuProgram::getRTTIStatic();
-	}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsGpuProgram.h"
+#include "BsRenderAPICapabilities.h"
+#include "BsRenderAPI.h"
+#include "BsGpuParams.h"
+#include "BsGpuParamDesc.h"
+#include "BsGpuProgramManager.h"
+#include "BsGpuProgramRTTI.h"
+
+namespace BansheeEngine
+{
+	GpuProgramProperties::GpuProgramProperties(const String& source, const String& entryPoint,
+		GpuProgramType gptype, GpuProgramProfile profile)
+		:mSource(source), mEntryPoint(entryPoint), mType(gptype), mProfile(profile)
+	{ }
+		
+	GpuProgramCore::GpuProgramCore(const String& source, const String& entryPoint,
+		GpuProgramType gptype, GpuProgramProfile profile, bool isAdjacencyInfoRequired)
+		: mProperties(source, entryPoint, gptype, profile), mIsCompiled(false),
+		mNeedsAdjacencyInfo(isAdjacencyInfoRequired)
+	{
+		mParametersDesc = bs_shared_ptr_new<GpuParamDesc>();
+	}
+
+	bool GpuProgramCore::isSupported() const
+    {
+		if (!isRequiredCapabilitiesSupported())
+			return false;
+
+		RenderAPICore* rs = BansheeEngine::RenderAPICore::instancePtr();
+		String profile = rs->getCapabilities()->gpuProgProfileToRSSpecificProfile(getProperties().getProfile());
+
+		return rs->getCapabilities()->isShaderProfileSupported(profile);
+    }
+
+	bool GpuProgramCore::isRequiredCapabilitiesSupported() const
+	{
+		return true;
+	}
+
+	SPtr<GpuParamsCore> GpuProgramCore::createParameters()
+	{
+		return GpuParamsCore::create(mParametersDesc, RenderAPICore::instance().getAPIInfo().getGpuProgramHasColumnMajorMatrices());
+	}
+
+	SPtr<GpuProgramCore> GpuProgramCore::create(const String& source, const String& entryPoint, const String& language, GpuProgramType gptype,
+		GpuProgramProfile profile, bool requiresAdjacency)
+	{
+		return GpuProgramCoreManager::instance().create(source, entryPoint, language, gptype, profile, requiresAdjacency);
+	}
+
+	GpuProgram::GpuProgram(const String& source, const String& entryPoint, const String& language,
+		GpuProgramType gptype, GpuProgramProfile profile, bool isAdjacencyInfoRequired) 
+		: mProperties(source, entryPoint, gptype, profile), mLanguage(language),
+		 mNeedsAdjacencyInfo(isAdjacencyInfoRequired)
+    {
+
+    }
+
+	bool GpuProgram::isCompiled() const
+	{
+		return getCore()->isCompiled();
+	}
+
+	String GpuProgram::getCompileErrorMessage() const
+	{
+		return getCore()->getCompileErrorMessage();
+	}
+
+	GpuParamsPtr GpuProgram::createParameters()
+	{
+		return GpuParams::create(getCore()->getParamDesc(), RenderAPICore::instance().getAPIInfo().getGpuProgramHasColumnMajorMatrices());
+	}
+
+	GpuParamDescPtr GpuProgram::getParamDesc() const
+	{
+		return getCore()->getParamDesc();
+	}
+
+	SPtr<GpuProgramCore> GpuProgram::getCore() const
+	{
+		return std::static_pointer_cast<GpuProgramCore>(mCoreSpecific);
+	}
+
+	SPtr<CoreObjectCore> GpuProgram::createCore() const
+	{
+		return GpuProgramCoreManager::instance().createInternal(mProperties.getSource(), mProperties.getEntryPoint(),
+			mLanguage, mProperties.getType(), mProperties.getProfile(), mNeedsAdjacencyInfo);
+	}
+
+	GpuProgramPtr GpuProgram::create(const String& source, const String& entryPoint, const String& language, GpuProgramType gptype,
+		GpuProgramProfile profile, bool requiresAdjacency)
+	{
+		return GpuProgramManager::instance().create(source, entryPoint, language, gptype, profile, requiresAdjacency);
+	}
+
+	/************************************************************************/
+	/* 								SERIALIZATION                      		*/
+	/************************************************************************/
+	RTTITypeBase* GpuProgram::getRTTIStatic()
+	{
+		return GpuProgramRTTI::instance();
+	}
+
+	RTTITypeBase* GpuProgram::getRTTI() const
+	{
+		return GpuProgram::getRTTIStatic();
+	}
 }

+ 595 - 595
Source/BansheeCore/Source/BsMesh.cpp

@@ -1,596 +1,596 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsMesh.h"
-#include "BsMeshRTTI.h"
-#include "BsMeshData.h"
-#include "BsDebug.h"
-#include "BsHardwareBufferManager.h"
-#include "BsMeshManager.h"
-#include "BsCoreThread.h"
-#include "BsAsyncOp.h"
-#include "BsVertexDataDesc.h"
-#include "BsResources.h"
-#include "BsRenderAPI.h"
-
-namespace BansheeEngine
-{
-	MeshCore::MeshCore(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc,
-		const Vector<SubMesh>& subMeshes, int usage, IndexType indexType, MeshDataPtr initialMeshData)
-		:MeshCoreBase(numVertices, numIndices, subMeshes), mVertexData(nullptr), mIndexBuffer(nullptr), 
-		mVertexDesc(vertexDesc), mUsage(usage), mIndexType(indexType), mTempInitialMeshData(initialMeshData)
-	{ }
-
-	MeshCore::~MeshCore()
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		mVertexData = nullptr;
-		mIndexBuffer = nullptr;
-		mVertexDesc = nullptr;
-		mTempInitialMeshData = nullptr;
-	}
-
-	void MeshCore::initialize()
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		bool isDynamic = (mUsage & MU_DYNAMIC) != 0;
-
-		mIndexBuffer = HardwareBufferCoreManager::instance().createIndexBuffer(mIndexType,
-			mProperties.mNumIndices, isDynamic ? GBU_DYNAMIC : GBU_STATIC);
-
-		mVertexData = std::shared_ptr<VertexData>(bs_new<VertexData>());
-
-		mVertexData->vertexCount = mProperties.mNumVertices;
-
-		List<VertexElement> elements = mVertexDesc->createElements();
-		mVertexData->vertexDeclaration = HardwareBufferCoreManager::instance().createVertexDeclaration(elements);
-
-		for (UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)
-		{
-			if (!mVertexDesc->hasStream(i))
-				continue;
-
-			SPtr<VertexBufferCore> vertexBuffer = HardwareBufferCoreManager::instance().createVertexBuffer(
-				mVertexData->vertexDeclaration->getProperties().getVertexSize(i),
-				mVertexData->vertexCount,
-				isDynamic ? GBU_DYNAMIC : GBU_STATIC);
-
-			mVertexData->setBuffer(i, vertexBuffer);
-		}
-
-		// TODO Low priority - DX11 (and maybe OpenGL)? allow an optimization that allows you to set
-		// buffer data upon buffer construction, instead of setting it in a second step like I do here
-		if (mTempInitialMeshData != nullptr)
-		{
-			writeSubresource(0, *mTempInitialMeshData, isDynamic);
-			mTempInitialMeshData = nullptr;
-		}
-
-		MeshCoreBase::initialize();
-	}
-
-	std::shared_ptr<VertexData> MeshCore::getVertexData() const
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		return mVertexData;
-	}
-
-	SPtr<IndexBufferCore> MeshCore::getIndexBuffer() const
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		return mIndexBuffer;
-	}
-
-	SPtr<VertexDataDesc> MeshCore::getVertexDesc() const
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		return mVertexDesc;
-	}
-
-	void MeshCore::writeSubresource(UINT32 subresourceIdx, const MeshData& meshData, bool discardEntireBuffer, bool performUpdateBounds)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		if (discardEntireBuffer)
-		{
-			if ((mUsage & MU_STATIC) != 0)
-			{
-				LOGWRN("Buffer discard is enabled but buffer was not created as dynamic. Disabling discard.");
-				discardEntireBuffer = false;
-			}
-		}
-		else
-		{
-			if ((mUsage & MU_DYNAMIC) != 0)
-			{
-				LOGWRN("Buffer discard is not enabled but buffer was created as dynamic. Enabling discard.");
-				discardEntireBuffer = true;
-			}
-		}
-
-		// Indices
-		const IndexBufferProperties& ibProps = mIndexBuffer->getProperties();
-
-		UINT32 indicesSize = meshData.getIndexBufferSize();
-		UINT8* srcIdxData = meshData.getIndexData();
-
-		if (meshData.getIndexElementSize() != ibProps.getIndexSize())
-		{
-			BS_EXCEPT(InvalidParametersException, "Provided index size doesn't match meshes index size. Needed: " +
-				toString(ibProps.getIndexSize()) + ". Got: " + toString(meshData.getIndexElementSize()));
-		}
-
-		if (indicesSize > mIndexBuffer->getSizeInBytes())
-			BS_EXCEPT(InvalidParametersException, "Index buffer values are being written out of valid range.");
-
-		mIndexBuffer->writeData(0, indicesSize, srcIdxData, discardEntireBuffer ? BufferWriteType::Discard : BufferWriteType::Normal);
-
-		// Vertices
-		for (UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)
-		{
-			if (!mVertexDesc->hasStream(i))
-				continue;
-
-			if (!meshData.getVertexDesc()->hasStream(i))
-				continue;
-
-			// Ensure both have the same sized vertices
-			UINT32 myVertSize = mVertexDesc->getVertexStride(i);
-			UINT32 otherVertSize = meshData.getVertexDesc()->getVertexStride(i);
-			if (myVertSize != otherVertSize)
-			{
-				BS_EXCEPT(InvalidParametersException, "Provided vertex size for stream " + toString(i) + " doesn't match meshes vertex size. Needed: " +
-					toString(myVertSize) + ". Got: " + toString(otherVertSize));
-			}
-
-			SPtr<VertexBufferCore> vertexBuffer = mVertexData->getBuffer(i);
-			const VertexBufferProperties& vbProps = vertexBuffer->getProperties();
-
-			UINT32 bufferSize = meshData.getStreamSize(i);
-			UINT8* srcVertBufferData = meshData.getStreamData(i);
-
-			if (bufferSize > vertexBuffer->getSizeInBytes())
-				BS_EXCEPT(InvalidParametersException, "Vertex buffer values for stream \"" + toString(i) + "\" are being written out of valid range.");
-
-			if (RenderAPICore::instance().getVertexColorFlipRequired())
-			{
-				UINT8* bufferCopy = (UINT8*)bs_alloc(bufferSize);
-				memcpy(bufferCopy, srcVertBufferData, bufferSize); // TODO Low priority - Attempt to avoid this copy
-
-				UINT32 vertexStride = meshData.getVertexDesc()->getVertexStride(i);
-				for (INT32 semanticIdx = 0; semanticIdx < VertexBuffer::MAX_SEMANTIC_IDX; semanticIdx++)
-				{
-					if (!meshData.getVertexDesc()->hasElement(VES_COLOR, semanticIdx, i))
-						continue;
-
-					UINT8* colorData = bufferCopy + mVertexDesc->getElementOffsetFromStream(VES_COLOR, semanticIdx, i);
-					for (UINT32 j = 0; j < mVertexData->vertexCount; j++)
-					{
-						UINT32* curColor = (UINT32*)colorData;
-
-						(*curColor) = ((*curColor) & 0xFF00FF00) | ((*curColor >> 16) & 0x000000FF) | ((*curColor << 16) & 0x00FF0000);
-
-						colorData += vertexStride;
-					}
-				}
-
-				vertexBuffer->writeData(0, bufferSize, bufferCopy, discardEntireBuffer ? BufferWriteType::Discard : BufferWriteType::Normal);
-
-				bs_free(bufferCopy);
-			}
-			else
-			{
-				vertexBuffer->writeData(0, bufferSize, srcVertBufferData, discardEntireBuffer ? BufferWriteType::Discard : BufferWriteType::Normal);
-			}
-		}
-
-		if (performUpdateBounds)
-			updateBounds(meshData);
-	}
-
-	void MeshCore::readSubresource(UINT32 subresourceIdx, MeshData& meshData)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		IndexType indexType = IT_32BIT;
-		if (mIndexBuffer)
-			indexType = mIndexBuffer->getProperties().getType();
-
-		if (mIndexBuffer)
-		{
-			const IndexBufferProperties& ibProps = mIndexBuffer->getProperties();
-
-			if (meshData.getIndexElementSize() != ibProps.getIndexSize())
-			{
-				BS_EXCEPT(InvalidParametersException, "Provided index size doesn't match meshes index size. Needed: " +
-					toString(ibProps.getIndexSize()) + ". Got: " + toString(meshData.getIndexElementSize()));
-			}
-
-			UINT8* idxData = static_cast<UINT8*>(mIndexBuffer->lock(GBL_READ_ONLY));
-			UINT32 idxElemSize = ibProps.getIndexSize();
-
-			UINT8* indices = nullptr;
-
-			if (indexType == IT_16BIT)
-				indices = (UINT8*)meshData.getIndices16();
-			else
-				indices = (UINT8*)meshData.getIndices32();
-
-			UINT32 numIndicesToCopy = std::min(mProperties.mNumIndices, meshData.getNumIndices());
-
-			UINT32 indicesSize = numIndicesToCopy * idxElemSize;
-			if (indicesSize > meshData.getIndexBufferSize())
-				BS_EXCEPT(InvalidParametersException, "Provided buffer doesn't have enough space to store mesh indices.");
-
-			memcpy(indices, idxData, numIndicesToCopy * idxElemSize);
-
-			mIndexBuffer->unlock();
-		}
-
-		if (mVertexData)
-		{
-			auto vertexBuffers = mVertexData->getBuffers();
-
-			UINT32 streamIdx = 0;
-			for (auto iter = vertexBuffers.begin(); iter != vertexBuffers.end(); ++iter)
-			{
-				if (!meshData.getVertexDesc()->hasStream(streamIdx))
-					continue;
-
-				SPtr<VertexBufferCore> vertexBuffer = iter->second;
-				const VertexBufferProperties& vbProps = vertexBuffer->getProperties();
-
-				// Ensure both have the same sized vertices
-				UINT32 myVertSize = mVertexDesc->getVertexStride(streamIdx);
-				UINT32 otherVertSize = meshData.getVertexDesc()->getVertexStride(streamIdx);
-				if (myVertSize != otherVertSize)
-				{
-					BS_EXCEPT(InvalidParametersException, "Provided vertex size for stream " + toString(streamIdx) + " doesn't match meshes vertex size. Needed: " +
-						toString(myVertSize) + ". Got: " + toString(otherVertSize));
-				}
-
-				UINT32 numVerticesToCopy = meshData.getNumVertices();
-				UINT32 bufferSize = vbProps.getVertexSize() * numVerticesToCopy;
-
-				if (bufferSize > vertexBuffer->getSizeInBytes())
-					BS_EXCEPT(InvalidParametersException, "Vertex buffer values for stream \"" + toString(streamIdx) + "\" are being read out of valid range.");
-
-				UINT8* vertDataPtr = static_cast<UINT8*>(vertexBuffer->lock(GBL_READ_ONLY));
-
-				UINT8* dest = meshData.getStreamData(streamIdx);
-				memcpy(dest, vertDataPtr, bufferSize);
-
-				vertexBuffer->unlock();
-
-				streamIdx++;
-			}
-		}
-	}
-
-	void MeshCore::updateBounds(const MeshData& meshData)
-	{
-		mProperties.mBounds = meshData.calculateBounds();
-		
-		// TODO - Sync this to sim-thread possibly?
-	}
-
-	SPtr<MeshCore> MeshCore::create(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc,
-		int usage, DrawOperationType drawOp, IndexType indexType)
-	{
-		SubMesh subMesh(0, numIndices, drawOp);
-
-		SPtr<MeshCore> mesh = bs_shared_ptr<MeshCore>(new (bs_alloc<MeshCore>()) MeshCore(numVertices, numIndices, 
-			vertexDesc, { subMesh }, usage, indexType, nullptr));
-		mesh->_setThisPtr(mesh);
-		mesh->initialize();
-
-		return mesh;
-	}
-
-	SPtr<MeshCore> MeshCore::create(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc,
-		const Vector<SubMesh>& subMeshes, int usage, IndexType indexType)
-	{
-		SPtr<MeshCore> mesh = bs_shared_ptr<MeshCore>(new (bs_alloc<MeshCore>()) MeshCore(numVertices, numIndices,
-			vertexDesc, subMeshes, usage, indexType, nullptr));
-
-		mesh->_setThisPtr(mesh);
-		mesh->initialize();
-
-		return mesh;
-	}
-
-	SPtr<MeshCore> MeshCore::create(const MeshDataPtr& initialMeshData, int usage, DrawOperationType drawOp)
-	{
-		UINT32 numVertices = initialMeshData->getNumVertices();
-		UINT32 numIndices = initialMeshData->getNumIndices();
-		VertexDataDescPtr vertexDesc = initialMeshData->getVertexDesc();
-		SubMesh subMesh(0, numIndices, drawOp);
-		IndexType indexType = initialMeshData->getIndexType();
-		
-		SPtr<MeshCore> mesh = bs_shared_ptr<MeshCore>(new (bs_alloc<MeshCore>()) MeshCore(numVertices, numIndices,
-			vertexDesc, { subMesh }, usage, indexType, initialMeshData));
-
-		mesh->_setThisPtr(mesh);
-		mesh->initialize();
-
-		return mesh;
-	}
-
-	SPtr<MeshCore> MeshCore::create(const MeshDataPtr& initialMeshData, const Vector<SubMesh>& subMeshes, int usage)
-	{
-		UINT32 numVertices = initialMeshData->getNumVertices();
-		UINT32 numIndices = initialMeshData->getNumIndices();
-		VertexDataDescPtr vertexDesc = initialMeshData->getVertexDesc();
-		IndexType indexType = initialMeshData->getIndexType();
-
-		SPtr<MeshCore> mesh = bs_shared_ptr<MeshCore>(new (bs_alloc<MeshCore>()) MeshCore(numVertices, numIndices,
-			vertexDesc, subMeshes, usage, indexType, initialMeshData));
-
-		mesh->_setThisPtr(mesh);
-		mesh->initialize();
-
-		return mesh;
-	}
-
-	Mesh::Mesh(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc, 
-		int usage, DrawOperationType drawOp, IndexType indexType)
-		:MeshBase(numVertices, numIndices, drawOp), mVertexDesc(vertexDesc), mUsage(usage),
-		mIndexType(indexType)
-	{
-
-	}
-
-	Mesh::Mesh(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc,
-		const Vector<SubMesh>& subMeshes, int usage, IndexType indexType)
-		:MeshBase(numVertices, numIndices, subMeshes), mVertexDesc(vertexDesc), mUsage(usage), 
-		mIndexType(indexType)
-	{
-
-	}
-
-	Mesh::Mesh(const MeshDataPtr& initialMeshData, int usage, DrawOperationType drawOp)
-		:MeshBase(initialMeshData->getNumVertices(), initialMeshData->getNumIndices(), drawOp), 
-		mIndexType(initialMeshData->getIndexType()), mVertexDesc(initialMeshData->getVertexDesc()), 
-		mCPUData(initialMeshData), mUsage(usage)
-	{
-
-	}
-
-	Mesh::Mesh(const MeshDataPtr& initialMeshData, const Vector<SubMesh>& subMeshes, int usage)
-		:MeshBase(initialMeshData->getNumVertices(), initialMeshData->getNumIndices(), subMeshes),
-		mIndexType(initialMeshData->getIndexType()), mVertexDesc(initialMeshData->getVertexDesc()), 
-		mCPUData(initialMeshData), mUsage(usage)
-	{
-
-	}
-
-	Mesh::Mesh()
-		:MeshBase(0, 0, DOT_TRIANGLE_LIST), mUsage(MU_STATIC), mIndexType(IT_32BIT)
-	{
-
-	}
-
-	Mesh::~Mesh()
-	{
-		
-	}
-
-	AsyncOp Mesh::writeSubresource(CoreAccessor& accessor, UINT32 subresourceIdx, const MeshDataPtr& data, bool discardEntireBuffer)
-	{
-		updateBounds(*data);
-		updateCPUBuffer(subresourceIdx, *data);
-
-		data->_lock();
-
-		std::function<void(const SPtr<MeshCore>&, UINT32, const MeshDataPtr&, bool, AsyncOp&)> func =
-			[&](const SPtr<MeshCore>& mesh, UINT32 _subresourceIdx, const MeshDataPtr& _meshData, bool _discardEntireBuffer, AsyncOp& asyncOp)
-		{
-			mesh->writeSubresource(_subresourceIdx, *_meshData, _discardEntireBuffer, false);
-			_meshData->_unlock();
-			asyncOp._completeOperation();
-
-		};
-
-		return accessor.queueReturnCommand(std::bind(func, getCore(), subresourceIdx,
-			 data, discardEntireBuffer, std::placeholders::_1));
-	}
-
-	AsyncOp Mesh::readSubresource(CoreAccessor& accessor, UINT32 subresourceIdx, const MeshDataPtr& data)
-	{
-		data->_lock();
-
-		std::function<void(const SPtr<MeshCore>&, UINT32, const MeshDataPtr&, AsyncOp&)> func =
-			[&](const SPtr<MeshCore>& mesh, UINT32 _subresourceIdx, const MeshDataPtr& _meshData, AsyncOp& asyncOp)
-		{
-			mesh->readSubresource(_subresourceIdx, *_meshData);
-			_meshData->_unlock();
-			asyncOp._completeOperation();
-
-		};
-
-		return accessor.queueReturnCommand(std::bind(func, getCore(), subresourceIdx,
-			data, std::placeholders::_1));
-	}
-
-	MeshDataPtr Mesh::allocateSubresourceBuffer(UINT32 subresourceIdx) const
-	{
-		MeshDataPtr meshData = bs_shared_ptr_new<MeshData>(mProperties.mNumVertices, mProperties.mNumIndices, mVertexDesc, mIndexType);
-
-		return meshData;
-	}
-
-	void Mesh::initialize()
-	{
-		if (mCPUData != nullptr)
-			updateBounds(*mCPUData);
-
-		MeshBase::initialize();
-
-		if ((mUsage & MU_CPUCACHED) != 0 && mCPUData == nullptr)
-			createCPUBuffer();
-	}
-
-	void Mesh::updateBounds(const MeshData& meshData)
-	{
-		mProperties.mBounds = meshData.calculateBounds();
-		markCoreDirty();
-	}
-
-	SPtr<MeshCore> Mesh::getCore() const
-	{
-		return std::static_pointer_cast<MeshCore>(mCoreSpecific);
-	}
-
-	SPtr<CoreObjectCore> Mesh::createCore() const
-	{
-		MeshCore* obj = new (bs_alloc<MeshCore>()) MeshCore(mProperties.mNumVertices, mProperties.mNumIndices, 
-			mVertexDesc, mProperties.mSubMeshes, mUsage, mIndexType, mCPUData);
-
-		SPtr<CoreObjectCore> meshCore = bs_shared_ptr<MeshCore>(obj);
-		meshCore->_setThisPtr(meshCore);
-
-		if ((mUsage & MU_CPUCACHED) == 0)
-			mCPUData = nullptr;
-
-		return meshCore;
-	}
-
-	void Mesh::updateCPUBuffer(UINT32 subresourceIdx, const MeshData& pixelData)
-	{
-		if ((mUsage & MU_CPUCACHED) == 0)
-			return;
-
-		if (subresourceIdx > 0)
-		{
-			LOGERR("Invalid subresource index: " + toString(subresourceIdx) + ". Supported range: 0 .. 1.");
-			return;
-		}
-
-		if (pixelData.getNumIndices() != mProperties.getNumIndices() ||
-			pixelData.getNumVertices() != mProperties.getNumVertices() ||
-			pixelData.getIndexType() != mIndexType ||
-			pixelData.getVertexDesc()->getVertexStride() != mVertexDesc->getVertexStride())
-		{
-			LOGERR("Provided buffer is not of valid dimensions or format in order to update this mesh.");
-			return;
-		}
-
-		if (mCPUData->getSize() != pixelData.getSize())
-			BS_EXCEPT(InternalErrorException, "Buffer sizes don't match.");
-
-		UINT8* dest = mCPUData->getData();
-		UINT8* src = pixelData.getData();
-
-		memcpy(dest, src, pixelData.getSize());
-	}
-
-	void Mesh::readData(MeshData& dest)
-	{
-		if ((mUsage & MU_CPUCACHED) == 0)
-		{
-			LOGERR("Attempting to read CPU data from a mesh that is created without CPU caching.");
-			return;
-		}
-
-		if (dest.getNumIndices() != mProperties.getNumIndices() ||
-			dest.getNumVertices() != mProperties.getNumVertices() ||
-			dest.getIndexType() != mIndexType ||
-			dest.getVertexDesc()->getVertexStride() != mVertexDesc->getVertexStride())
-		{
-			LOGERR("Provided buffer is not of valid dimensions or format in order to read from this mesh.");
-			return;
-		}
-		
-		if (mCPUData->getSize() != dest.getSize())
-			BS_EXCEPT(InternalErrorException, "Buffer sizes don't match.");
-
-		UINT8* srcPtr = mCPUData->getData();
-		UINT8* destPtr = dest.getData();
-
-		memcpy(destPtr, srcPtr, dest.getSize());
-	}
-
-	void Mesh::createCPUBuffer()
-	{
-		mCPUData = allocateSubresourceBuffer(0);
-	}
-
-	HMesh Mesh::dummy()
-	{
-		return MeshManager::instance().getDummyMesh();
-	}
-
-	/************************************************************************/
-	/* 								SERIALIZATION                      		*/
-	/************************************************************************/
-
-	RTTITypeBase* Mesh::getRTTIStatic()
-	{
-		return MeshRTTI::instance();
-	}
-
-	RTTITypeBase* Mesh::getRTTI() const
-	{
-		return Mesh::getRTTIStatic();
-	}
-
-	/************************************************************************/
-	/* 								STATICS		                     		*/
-	/************************************************************************/
-
-	HMesh Mesh::create(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc, 
-		int usage, DrawOperationType drawOp, IndexType indexType)
-	{
-		MeshPtr meshPtr = _createPtr(numVertices, numIndices, vertexDesc, usage, drawOp, indexType);
-
-		return static_resource_cast<Mesh>(gResources()._createResourceHandle(meshPtr));
-	}
-
-	HMesh Mesh::create(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc,
-		const Vector<SubMesh>& subMeshes, int usage, IndexType indexType)
-	{
-		MeshPtr meshPtr = _createPtr(numVertices, numIndices, vertexDesc, subMeshes, usage, indexType);
-
-		return static_resource_cast<Mesh>(gResources()._createResourceHandle(meshPtr));
-	}
-
-	HMesh Mesh::create(const MeshDataPtr& initialMeshData, int usage, DrawOperationType drawOp)
-	{
-		MeshPtr meshPtr = _createPtr(initialMeshData, usage, drawOp);
-
-		return static_resource_cast<Mesh>(gResources()._createResourceHandle(meshPtr));
-	}
-
-	HMesh Mesh::create(const MeshDataPtr& initialMeshData, const Vector<SubMesh>& subMeshes, int usage)
-	{
-		MeshPtr meshPtr = _createPtr(initialMeshData, subMeshes, usage);
-
-		return static_resource_cast<Mesh>(gResources()._createResourceHandle(meshPtr));
-	}
-
-	MeshPtr Mesh::_createPtr(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc, 
-		int usage, DrawOperationType drawOp, IndexType indexType)
-	{
-		return MeshManager::instance().create(numVertices, numIndices, vertexDesc, usage, drawOp, indexType);
-	}
-
-	MeshPtr Mesh::_createPtr(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc,
-		const Vector<SubMesh>& subMeshes, int usage, IndexType indexType)
-	{
-		return MeshManager::instance().create(numVertices, numIndices, vertexDesc, subMeshes, usage, indexType);
-	}
-
-	MeshPtr Mesh::_createPtr(const MeshDataPtr& initialMeshData, int usage, DrawOperationType drawOp)
-	{
-		return MeshManager::instance().create(initialMeshData, usage, drawOp);
-	}
-
-	MeshPtr Mesh::_createPtr(const MeshDataPtr& initialMeshData, const Vector<SubMesh>& subMeshes, int usage)
-	{
-		return MeshManager::instance().create(initialMeshData, subMeshes, usage);
-	}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsMesh.h"
+#include "BsMeshRTTI.h"
+#include "BsMeshData.h"
+#include "BsDebug.h"
+#include "BsHardwareBufferManager.h"
+#include "BsMeshManager.h"
+#include "BsCoreThread.h"
+#include "BsAsyncOp.h"
+#include "BsVertexDataDesc.h"
+#include "BsResources.h"
+#include "BsRenderAPI.h"
+
+namespace BansheeEngine
+{
+	MeshCore::MeshCore(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc,
+		const Vector<SubMesh>& subMeshes, int usage, IndexType indexType, MeshDataPtr initialMeshData)
+		:MeshCoreBase(numVertices, numIndices, subMeshes), mVertexData(nullptr), mIndexBuffer(nullptr), 
+		mVertexDesc(vertexDesc), mUsage(usage), mIndexType(indexType), mTempInitialMeshData(initialMeshData)
+	{ }
+
+	MeshCore::~MeshCore()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		mVertexData = nullptr;
+		mIndexBuffer = nullptr;
+		mVertexDesc = nullptr;
+		mTempInitialMeshData = nullptr;
+	}
+
+	void MeshCore::initialize()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		bool isDynamic = (mUsage & MU_DYNAMIC) != 0;
+
+		mIndexBuffer = HardwareBufferCoreManager::instance().createIndexBuffer(mIndexType,
+			mProperties.mNumIndices, isDynamic ? GBU_DYNAMIC : GBU_STATIC);
+
+		mVertexData = std::shared_ptr<VertexData>(bs_new<VertexData>());
+
+		mVertexData->vertexCount = mProperties.mNumVertices;
+
+		List<VertexElement> elements = mVertexDesc->createElements();
+		mVertexData->vertexDeclaration = HardwareBufferCoreManager::instance().createVertexDeclaration(elements);
+
+		for (UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)
+		{
+			if (!mVertexDesc->hasStream(i))
+				continue;
+
+			SPtr<VertexBufferCore> vertexBuffer = HardwareBufferCoreManager::instance().createVertexBuffer(
+				mVertexData->vertexDeclaration->getProperties().getVertexSize(i),
+				mVertexData->vertexCount,
+				isDynamic ? GBU_DYNAMIC : GBU_STATIC);
+
+			mVertexData->setBuffer(i, vertexBuffer);
+		}
+
+		// TODO Low priority - DX11 (and maybe OpenGL)? allow an optimization that allows you to set
+		// buffer data upon buffer construction, instead of setting it in a second step like I do here
+		if (mTempInitialMeshData != nullptr)
+		{
+			writeSubresource(0, *mTempInitialMeshData, isDynamic);
+			mTempInitialMeshData = nullptr;
+		}
+
+		MeshCoreBase::initialize();
+	}
+
+	std::shared_ptr<VertexData> MeshCore::getVertexData() const
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		return mVertexData;
+	}
+
+	SPtr<IndexBufferCore> MeshCore::getIndexBuffer() const
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		return mIndexBuffer;
+	}
+
+	SPtr<VertexDataDesc> MeshCore::getVertexDesc() const
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		return mVertexDesc;
+	}
+
+	void MeshCore::writeSubresource(UINT32 subresourceIdx, const MeshData& meshData, bool discardEntireBuffer, bool performUpdateBounds)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		if (discardEntireBuffer)
+		{
+			if ((mUsage & MU_STATIC) != 0)
+			{
+				LOGWRN("Buffer discard is enabled but buffer was not created as dynamic. Disabling discard.");
+				discardEntireBuffer = false;
+			}
+		}
+		else
+		{
+			if ((mUsage & MU_DYNAMIC) != 0)
+			{
+				LOGWRN("Buffer discard is not enabled but buffer was created as dynamic. Enabling discard.");
+				discardEntireBuffer = true;
+			}
+		}
+
+		// Indices
+		const IndexBufferProperties& ibProps = mIndexBuffer->getProperties();
+
+		UINT32 indicesSize = meshData.getIndexBufferSize();
+		UINT8* srcIdxData = meshData.getIndexData();
+
+		if (meshData.getIndexElementSize() != ibProps.getIndexSize())
+		{
+			BS_EXCEPT(InvalidParametersException, "Provided index size doesn't match meshes index size. Needed: " +
+				toString(ibProps.getIndexSize()) + ". Got: " + toString(meshData.getIndexElementSize()));
+		}
+
+		if (indicesSize > mIndexBuffer->getSizeInBytes())
+			BS_EXCEPT(InvalidParametersException, "Index buffer values are being written out of valid range.");
+
+		mIndexBuffer->writeData(0, indicesSize, srcIdxData, discardEntireBuffer ? BufferWriteType::Discard : BufferWriteType::Normal);
+
+		// Vertices
+		for (UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)
+		{
+			if (!mVertexDesc->hasStream(i))
+				continue;
+
+			if (!meshData.getVertexDesc()->hasStream(i))
+				continue;
+
+			// Ensure both have the same sized vertices
+			UINT32 myVertSize = mVertexDesc->getVertexStride(i);
+			UINT32 otherVertSize = meshData.getVertexDesc()->getVertexStride(i);
+			if (myVertSize != otherVertSize)
+			{
+				BS_EXCEPT(InvalidParametersException, "Provided vertex size for stream " + toString(i) + " doesn't match meshes vertex size. Needed: " +
+					toString(myVertSize) + ". Got: " + toString(otherVertSize));
+			}
+
+			SPtr<VertexBufferCore> vertexBuffer = mVertexData->getBuffer(i);
+			const VertexBufferProperties& vbProps = vertexBuffer->getProperties();
+
+			UINT32 bufferSize = meshData.getStreamSize(i);
+			UINT8* srcVertBufferData = meshData.getStreamData(i);
+
+			if (bufferSize > vertexBuffer->getSizeInBytes())
+				BS_EXCEPT(InvalidParametersException, "Vertex buffer values for stream \"" + toString(i) + "\" are being written out of valid range.");
+
+			if (RenderAPICore::instance().getAPIInfo().getVertexColorFlipRequired())
+			{
+				UINT8* bufferCopy = (UINT8*)bs_alloc(bufferSize);
+				memcpy(bufferCopy, srcVertBufferData, bufferSize); // TODO Low priority - Attempt to avoid this copy
+
+				UINT32 vertexStride = meshData.getVertexDesc()->getVertexStride(i);
+				for (INT32 semanticIdx = 0; semanticIdx < VertexBuffer::MAX_SEMANTIC_IDX; semanticIdx++)
+				{
+					if (!meshData.getVertexDesc()->hasElement(VES_COLOR, semanticIdx, i))
+						continue;
+
+					UINT8* colorData = bufferCopy + mVertexDesc->getElementOffsetFromStream(VES_COLOR, semanticIdx, i);
+					for (UINT32 j = 0; j < mVertexData->vertexCount; j++)
+					{
+						UINT32* curColor = (UINT32*)colorData;
+
+						(*curColor) = ((*curColor) & 0xFF00FF00) | ((*curColor >> 16) & 0x000000FF) | ((*curColor << 16) & 0x00FF0000);
+
+						colorData += vertexStride;
+					}
+				}
+
+				vertexBuffer->writeData(0, bufferSize, bufferCopy, discardEntireBuffer ? BufferWriteType::Discard : BufferWriteType::Normal);
+
+				bs_free(bufferCopy);
+			}
+			else
+			{
+				vertexBuffer->writeData(0, bufferSize, srcVertBufferData, discardEntireBuffer ? BufferWriteType::Discard : BufferWriteType::Normal);
+			}
+		}
+
+		if (performUpdateBounds)
+			updateBounds(meshData);
+	}
+
+	void MeshCore::readSubresource(UINT32 subresourceIdx, MeshData& meshData)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		IndexType indexType = IT_32BIT;
+		if (mIndexBuffer)
+			indexType = mIndexBuffer->getProperties().getType();
+
+		if (mIndexBuffer)
+		{
+			const IndexBufferProperties& ibProps = mIndexBuffer->getProperties();
+
+			if (meshData.getIndexElementSize() != ibProps.getIndexSize())
+			{
+				BS_EXCEPT(InvalidParametersException, "Provided index size doesn't match meshes index size. Needed: " +
+					toString(ibProps.getIndexSize()) + ". Got: " + toString(meshData.getIndexElementSize()));
+			}
+
+			UINT8* idxData = static_cast<UINT8*>(mIndexBuffer->lock(GBL_READ_ONLY));
+			UINT32 idxElemSize = ibProps.getIndexSize();
+
+			UINT8* indices = nullptr;
+
+			if (indexType == IT_16BIT)
+				indices = (UINT8*)meshData.getIndices16();
+			else
+				indices = (UINT8*)meshData.getIndices32();
+
+			UINT32 numIndicesToCopy = std::min(mProperties.mNumIndices, meshData.getNumIndices());
+
+			UINT32 indicesSize = numIndicesToCopy * idxElemSize;
+			if (indicesSize > meshData.getIndexBufferSize())
+				BS_EXCEPT(InvalidParametersException, "Provided buffer doesn't have enough space to store mesh indices.");
+
+			memcpy(indices, idxData, numIndicesToCopy * idxElemSize);
+
+			mIndexBuffer->unlock();
+		}
+
+		if (mVertexData)
+		{
+			auto vertexBuffers = mVertexData->getBuffers();
+
+			UINT32 streamIdx = 0;
+			for (auto iter = vertexBuffers.begin(); iter != vertexBuffers.end(); ++iter)
+			{
+				if (!meshData.getVertexDesc()->hasStream(streamIdx))
+					continue;
+
+				SPtr<VertexBufferCore> vertexBuffer = iter->second;
+				const VertexBufferProperties& vbProps = vertexBuffer->getProperties();
+
+				// Ensure both have the same sized vertices
+				UINT32 myVertSize = mVertexDesc->getVertexStride(streamIdx);
+				UINT32 otherVertSize = meshData.getVertexDesc()->getVertexStride(streamIdx);
+				if (myVertSize != otherVertSize)
+				{
+					BS_EXCEPT(InvalidParametersException, "Provided vertex size for stream " + toString(streamIdx) + " doesn't match meshes vertex size. Needed: " +
+						toString(myVertSize) + ". Got: " + toString(otherVertSize));
+				}
+
+				UINT32 numVerticesToCopy = meshData.getNumVertices();
+				UINT32 bufferSize = vbProps.getVertexSize() * numVerticesToCopy;
+
+				if (bufferSize > vertexBuffer->getSizeInBytes())
+					BS_EXCEPT(InvalidParametersException, "Vertex buffer values for stream \"" + toString(streamIdx) + "\" are being read out of valid range.");
+
+				UINT8* vertDataPtr = static_cast<UINT8*>(vertexBuffer->lock(GBL_READ_ONLY));
+
+				UINT8* dest = meshData.getStreamData(streamIdx);
+				memcpy(dest, vertDataPtr, bufferSize);
+
+				vertexBuffer->unlock();
+
+				streamIdx++;
+			}
+		}
+	}
+
+	void MeshCore::updateBounds(const MeshData& meshData)
+	{
+		mProperties.mBounds = meshData.calculateBounds();
+		
+		// TODO - Sync this to sim-thread possibly?
+	}
+
+	SPtr<MeshCore> MeshCore::create(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc,
+		int usage, DrawOperationType drawOp, IndexType indexType)
+	{
+		SubMesh subMesh(0, numIndices, drawOp);
+
+		SPtr<MeshCore> mesh = bs_shared_ptr<MeshCore>(new (bs_alloc<MeshCore>()) MeshCore(numVertices, numIndices, 
+			vertexDesc, { subMesh }, usage, indexType, nullptr));
+		mesh->_setThisPtr(mesh);
+		mesh->initialize();
+
+		return mesh;
+	}
+
+	SPtr<MeshCore> MeshCore::create(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc,
+		const Vector<SubMesh>& subMeshes, int usage, IndexType indexType)
+	{
+		SPtr<MeshCore> mesh = bs_shared_ptr<MeshCore>(new (bs_alloc<MeshCore>()) MeshCore(numVertices, numIndices,
+			vertexDesc, subMeshes, usage, indexType, nullptr));
+
+		mesh->_setThisPtr(mesh);
+		mesh->initialize();
+
+		return mesh;
+	}
+
+	SPtr<MeshCore> MeshCore::create(const MeshDataPtr& initialMeshData, int usage, DrawOperationType drawOp)
+	{
+		UINT32 numVertices = initialMeshData->getNumVertices();
+		UINT32 numIndices = initialMeshData->getNumIndices();
+		VertexDataDescPtr vertexDesc = initialMeshData->getVertexDesc();
+		SubMesh subMesh(0, numIndices, drawOp);
+		IndexType indexType = initialMeshData->getIndexType();
+		
+		SPtr<MeshCore> mesh = bs_shared_ptr<MeshCore>(new (bs_alloc<MeshCore>()) MeshCore(numVertices, numIndices,
+			vertexDesc, { subMesh }, usage, indexType, initialMeshData));
+
+		mesh->_setThisPtr(mesh);
+		mesh->initialize();
+
+		return mesh;
+	}
+
+	SPtr<MeshCore> MeshCore::create(const MeshDataPtr& initialMeshData, const Vector<SubMesh>& subMeshes, int usage)
+	{
+		UINT32 numVertices = initialMeshData->getNumVertices();
+		UINT32 numIndices = initialMeshData->getNumIndices();
+		VertexDataDescPtr vertexDesc = initialMeshData->getVertexDesc();
+		IndexType indexType = initialMeshData->getIndexType();
+
+		SPtr<MeshCore> mesh = bs_shared_ptr<MeshCore>(new (bs_alloc<MeshCore>()) MeshCore(numVertices, numIndices,
+			vertexDesc, subMeshes, usage, indexType, initialMeshData));
+
+		mesh->_setThisPtr(mesh);
+		mesh->initialize();
+
+		return mesh;
+	}
+
+	Mesh::Mesh(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc, 
+		int usage, DrawOperationType drawOp, IndexType indexType)
+		:MeshBase(numVertices, numIndices, drawOp), mVertexDesc(vertexDesc), mUsage(usage),
+		mIndexType(indexType)
+	{
+
+	}
+
+	Mesh::Mesh(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc,
+		const Vector<SubMesh>& subMeshes, int usage, IndexType indexType)
+		:MeshBase(numVertices, numIndices, subMeshes), mVertexDesc(vertexDesc), mUsage(usage), 
+		mIndexType(indexType)
+	{
+
+	}
+
+	Mesh::Mesh(const MeshDataPtr& initialMeshData, int usage, DrawOperationType drawOp)
+		:MeshBase(initialMeshData->getNumVertices(), initialMeshData->getNumIndices(), drawOp), 
+		mIndexType(initialMeshData->getIndexType()), mVertexDesc(initialMeshData->getVertexDesc()), 
+		mCPUData(initialMeshData), mUsage(usage)
+	{
+
+	}
+
+	Mesh::Mesh(const MeshDataPtr& initialMeshData, const Vector<SubMesh>& subMeshes, int usage)
+		:MeshBase(initialMeshData->getNumVertices(), initialMeshData->getNumIndices(), subMeshes),
+		mIndexType(initialMeshData->getIndexType()), mVertexDesc(initialMeshData->getVertexDesc()), 
+		mCPUData(initialMeshData), mUsage(usage)
+	{
+
+	}
+
+	Mesh::Mesh()
+		:MeshBase(0, 0, DOT_TRIANGLE_LIST), mUsage(MU_STATIC), mIndexType(IT_32BIT)
+	{
+
+	}
+
+	Mesh::~Mesh()
+	{
+		
+	}
+
+	AsyncOp Mesh::writeSubresource(CoreAccessor& accessor, UINT32 subresourceIdx, const MeshDataPtr& data, bool discardEntireBuffer)
+	{
+		updateBounds(*data);
+		updateCPUBuffer(subresourceIdx, *data);
+
+		data->_lock();
+
+		std::function<void(const SPtr<MeshCore>&, UINT32, const MeshDataPtr&, bool, AsyncOp&)> func =
+			[&](const SPtr<MeshCore>& mesh, UINT32 _subresourceIdx, const MeshDataPtr& _meshData, bool _discardEntireBuffer, AsyncOp& asyncOp)
+		{
+			mesh->writeSubresource(_subresourceIdx, *_meshData, _discardEntireBuffer, false);
+			_meshData->_unlock();
+			asyncOp._completeOperation();
+
+		};
+
+		return accessor.queueReturnCommand(std::bind(func, getCore(), subresourceIdx,
+			 data, discardEntireBuffer, std::placeholders::_1));
+	}
+
+	AsyncOp Mesh::readSubresource(CoreAccessor& accessor, UINT32 subresourceIdx, const MeshDataPtr& data)
+	{
+		data->_lock();
+
+		std::function<void(const SPtr<MeshCore>&, UINT32, const MeshDataPtr&, AsyncOp&)> func =
+			[&](const SPtr<MeshCore>& mesh, UINT32 _subresourceIdx, const MeshDataPtr& _meshData, AsyncOp& asyncOp)
+		{
+			mesh->readSubresource(_subresourceIdx, *_meshData);
+			_meshData->_unlock();
+			asyncOp._completeOperation();
+
+		};
+
+		return accessor.queueReturnCommand(std::bind(func, getCore(), subresourceIdx,
+			data, std::placeholders::_1));
+	}
+
+	MeshDataPtr Mesh::allocateSubresourceBuffer(UINT32 subresourceIdx) const
+	{
+		MeshDataPtr meshData = bs_shared_ptr_new<MeshData>(mProperties.mNumVertices, mProperties.mNumIndices, mVertexDesc, mIndexType);
+
+		return meshData;
+	}
+
+	void Mesh::initialize()
+	{
+		if (mCPUData != nullptr)
+			updateBounds(*mCPUData);
+
+		MeshBase::initialize();
+
+		if ((mUsage & MU_CPUCACHED) != 0 && mCPUData == nullptr)
+			createCPUBuffer();
+	}
+
+	void Mesh::updateBounds(const MeshData& meshData)
+	{
+		mProperties.mBounds = meshData.calculateBounds();
+		markCoreDirty();
+	}
+
+	SPtr<MeshCore> Mesh::getCore() const
+	{
+		return std::static_pointer_cast<MeshCore>(mCoreSpecific);
+	}
+
+	SPtr<CoreObjectCore> Mesh::createCore() const
+	{
+		MeshCore* obj = new (bs_alloc<MeshCore>()) MeshCore(mProperties.mNumVertices, mProperties.mNumIndices, 
+			mVertexDesc, mProperties.mSubMeshes, mUsage, mIndexType, mCPUData);
+
+		SPtr<CoreObjectCore> meshCore = bs_shared_ptr<MeshCore>(obj);
+		meshCore->_setThisPtr(meshCore);
+
+		if ((mUsage & MU_CPUCACHED) == 0)
+			mCPUData = nullptr;
+
+		return meshCore;
+	}
+
+	void Mesh::updateCPUBuffer(UINT32 subresourceIdx, const MeshData& pixelData)
+	{
+		if ((mUsage & MU_CPUCACHED) == 0)
+			return;
+
+		if (subresourceIdx > 0)
+		{
+			LOGERR("Invalid subresource index: " + toString(subresourceIdx) + ". Supported range: 0 .. 1.");
+			return;
+		}
+
+		if (pixelData.getNumIndices() != mProperties.getNumIndices() ||
+			pixelData.getNumVertices() != mProperties.getNumVertices() ||
+			pixelData.getIndexType() != mIndexType ||
+			pixelData.getVertexDesc()->getVertexStride() != mVertexDesc->getVertexStride())
+		{
+			LOGERR("Provided buffer is not of valid dimensions or format in order to update this mesh.");
+			return;
+		}
+
+		if (mCPUData->getSize() != pixelData.getSize())
+			BS_EXCEPT(InternalErrorException, "Buffer sizes don't match.");
+
+		UINT8* dest = mCPUData->getData();
+		UINT8* src = pixelData.getData();
+
+		memcpy(dest, src, pixelData.getSize());
+	}
+
+	void Mesh::readData(MeshData& dest)
+	{
+		if ((mUsage & MU_CPUCACHED) == 0)
+		{
+			LOGERR("Attempting to read CPU data from a mesh that is created without CPU caching.");
+			return;
+		}
+
+		if (dest.getNumIndices() != mProperties.getNumIndices() ||
+			dest.getNumVertices() != mProperties.getNumVertices() ||
+			dest.getIndexType() != mIndexType ||
+			dest.getVertexDesc()->getVertexStride() != mVertexDesc->getVertexStride())
+		{
+			LOGERR("Provided buffer is not of valid dimensions or format in order to read from this mesh.");
+			return;
+		}
+		
+		if (mCPUData->getSize() != dest.getSize())
+			BS_EXCEPT(InternalErrorException, "Buffer sizes don't match.");
+
+		UINT8* srcPtr = mCPUData->getData();
+		UINT8* destPtr = dest.getData();
+
+		memcpy(destPtr, srcPtr, dest.getSize());
+	}
+
+	void Mesh::createCPUBuffer()
+	{
+		mCPUData = allocateSubresourceBuffer(0);
+	}
+
+	HMesh Mesh::dummy()
+	{
+		return MeshManager::instance().getDummyMesh();
+	}
+
+	/************************************************************************/
+	/* 								SERIALIZATION                      		*/
+	/************************************************************************/
+
+	RTTITypeBase* Mesh::getRTTIStatic()
+	{
+		return MeshRTTI::instance();
+	}
+
+	RTTITypeBase* Mesh::getRTTI() const
+	{
+		return Mesh::getRTTIStatic();
+	}
+
+	/************************************************************************/
+	/* 								STATICS		                     		*/
+	/************************************************************************/
+
+	HMesh Mesh::create(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc, 
+		int usage, DrawOperationType drawOp, IndexType indexType)
+	{
+		MeshPtr meshPtr = _createPtr(numVertices, numIndices, vertexDesc, usage, drawOp, indexType);
+
+		return static_resource_cast<Mesh>(gResources()._createResourceHandle(meshPtr));
+	}
+
+	HMesh Mesh::create(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc,
+		const Vector<SubMesh>& subMeshes, int usage, IndexType indexType)
+	{
+		MeshPtr meshPtr = _createPtr(numVertices, numIndices, vertexDesc, subMeshes, usage, indexType);
+
+		return static_resource_cast<Mesh>(gResources()._createResourceHandle(meshPtr));
+	}
+
+	HMesh Mesh::create(const MeshDataPtr& initialMeshData, int usage, DrawOperationType drawOp)
+	{
+		MeshPtr meshPtr = _createPtr(initialMeshData, usage, drawOp);
+
+		return static_resource_cast<Mesh>(gResources()._createResourceHandle(meshPtr));
+	}
+
+	HMesh Mesh::create(const MeshDataPtr& initialMeshData, const Vector<SubMesh>& subMeshes, int usage)
+	{
+		MeshPtr meshPtr = _createPtr(initialMeshData, subMeshes, usage);
+
+		return static_resource_cast<Mesh>(gResources()._createResourceHandle(meshPtr));
+	}
+
+	MeshPtr Mesh::_createPtr(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc, 
+		int usage, DrawOperationType drawOp, IndexType indexType)
+	{
+		return MeshManager::instance().create(numVertices, numIndices, vertexDesc, usage, drawOp, indexType);
+	}
+
+	MeshPtr Mesh::_createPtr(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc,
+		const Vector<SubMesh>& subMeshes, int usage, IndexType indexType)
+	{
+		return MeshManager::instance().create(numVertices, numIndices, vertexDesc, subMeshes, usage, indexType);
+	}
+
+	MeshPtr Mesh::_createPtr(const MeshDataPtr& initialMeshData, int usage, DrawOperationType drawOp)
+	{
+		return MeshManager::instance().create(initialMeshData, usage, drawOp);
+	}
+
+	MeshPtr Mesh::_createPtr(const MeshDataPtr& initialMeshData, const Vector<SubMesh>& subMeshes, int usage)
+	{
+		return MeshManager::instance().create(initialMeshData, subMeshes, usage);
+	}
 }

+ 702 - 702
Source/BansheeCore/Source/BsMeshHeap.cpp

@@ -1,703 +1,703 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsMeshHeap.h"
-#include "BsCoreThread.h"
-#include "BsTransientMesh.h"
-#include "BsHardwareBufferManager.h"
-#include "BsVertexDataDesc.h"
-#include "BsVertexData.h"
-#include "BsMeshData.h"
-#include "BsMath.h"
-#include "BsEventQuery.h"
-#include "BsRenderAPI.h"
-
-namespace BansheeEngine
-{
-	const float MeshHeapCore::GrowPercent = 1.5f;
-
-	MeshHeapCore::MeshHeapCore(UINT32 numVertices, UINT32 numIndices,
-		const VertexDataDescPtr& vertexDesc, IndexType indexType)
-		:mNumVertices(numVertices), mNumIndices(numIndices), mIndexType(indexType), 
-		mVertexDesc(vertexDesc), mCPUIndexData(nullptr), mNextQueryId(0)
-	{
-		for (UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)
-		{
-			mCPUVertexData.push_back(nullptr);
-		}
-	}
-
-	MeshHeapCore::~MeshHeapCore()
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		for (auto& cpuVertBuffer : mCPUVertexData)
-			bs_free(cpuVertBuffer);
-
-		if (mCPUIndexData != nullptr)
-			bs_free(mCPUIndexData);
-
-		mVertexData = nullptr;
-		mIndexBuffer = nullptr;
-		mVertexDesc = nullptr;
-	}
-
-	void MeshHeapCore::initialize()
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		growVertexBuffer(mNumVertices);
-		growIndexBuffer(mNumIndices);
-
-		CoreObjectCore::initialize();
-	}
-
-	void MeshHeapCore::alloc(SPtr<TransientMeshCore> mesh, const MeshDataPtr& meshData)
-	{
-		// Find free vertex chunk and grow if needed
-		UINT32 smallestVertFit = 0;
-		UINT32 smallestVertFitIdx = 0;
-
-		while (smallestVertFit == 0)
-		{
-			UINT32 curIdx = 0;
-			for (auto& chunkIdx : mFreeVertChunks)
-			{
-				ChunkData& chunk = mVertChunks[chunkIdx];
-
-				if (chunk.size >= meshData->getNumVertices() && (chunk.size < smallestVertFit || smallestVertFit == 0))
-				{
-					smallestVertFit = chunk.size;
-					smallestVertFitIdx = curIdx;
-				}
-
-				curIdx++;
-			}
-
-			if (smallestVertFit > 0)
-				break;
-
-			UINT32 newNumVertices = mNumVertices;
-			while (newNumVertices < (mNumVertices + meshData->getNumVertices()))
-			{
-				newNumVertices = Math::roundToInt(newNumVertices * GrowPercent);
-			}
-
-			growVertexBuffer(newNumVertices);
-		}
-
-		// Find free index chunk and grow if needed
-		UINT32 smallestIdxFit = 0;
-		UINT32 smallestIdxFitIdx = 0;
-
-		while (smallestIdxFit == 0)
-		{
-			UINT32 curIdx = 0;
-			for (auto& chunkIdx : mFreeIdxChunks)
-			{
-				ChunkData& chunk = mIdxChunks[chunkIdx];
-
-				if (chunk.size >= meshData->getNumIndices() && (chunk.size < smallestIdxFit || smallestIdxFit == 0))
-				{
-					smallestIdxFit = chunk.size;
-					smallestIdxFitIdx = curIdx;
-				}
-
-				curIdx++;
-			}
-
-			if (smallestIdxFit > 0)
-				break;
-
-			UINT32 newNumIndices = mNumIndices;
-			while (newNumIndices < (mNumIndices + meshData->getNumIndices()))
-			{
-				newNumIndices = Math::roundToInt(newNumIndices * GrowPercent);
-			}
-
-			growIndexBuffer(newNumIndices);
-		}
-
-		UINT32 freeVertChunkIdx = 0;
-		UINT32 freeIdxChunkIdx = 0;
-
-		auto freeVertIter = mFreeVertChunks.begin();
-		freeVertChunkIdx = (*freeVertIter);
-		for (UINT32 i = 0; i < smallestVertFitIdx; i++)
-		{
-			freeVertIter++;
-			freeVertChunkIdx = (*freeVertIter);
-		}
-
-		mFreeVertChunks.erase(freeVertIter);
-
-		auto freeIdxIter = mFreeIdxChunks.begin();
-		freeIdxChunkIdx = (*freeIdxIter);
-		for (UINT32 i = 0; i < smallestIdxFitIdx; i++)
-		{
-			freeIdxIter++;
-			freeIdxChunkIdx = (*freeIdxIter);
-		}
-
-		mFreeIdxChunks.erase(freeIdxIter);
-
-		ChunkData& vertChunk = mVertChunks[freeVertChunkIdx];
-		ChunkData& idxChunk = mIdxChunks[freeIdxChunkIdx];
-
-		UINT32 vertChunkStart = vertChunk.start;
-		UINT32 idxChunkStart = idxChunk.start;
-
-		UINT32 remainingNumVerts = vertChunk.size - meshData->getNumVertices();
-		UINT32 remainingNumIdx = idxChunk.size - meshData->getNumIndices();
-
-		vertChunk.size = meshData->getNumVertices();
-		idxChunk.size = meshData->getNumIndices();
-
-		if (remainingNumVerts > 0)
-		{
-			if (!mEmptyVertChunks.empty())
-			{
-				UINT32 emptyChunkIdx = mEmptyVertChunks.top();
-				ChunkData& emptyChunk = mVertChunks[emptyChunkIdx];
-				mEmptyVertChunks.pop();
-
-				emptyChunk.start = vertChunkStart + meshData->getNumVertices();
-				emptyChunk.size = remainingNumVerts;
-			}
-			else
-			{
-				ChunkData newChunk;
-				newChunk.size = remainingNumVerts;
-				newChunk.start = vertChunkStart + meshData->getNumVertices();
-
-				mVertChunks.push_back(newChunk);
-				mFreeVertChunks.push_back((UINT32)(mVertChunks.size() - 1));
-			}
-		}
-
-		if (remainingNumIdx > 0)
-		{
-			if (!mEmptyIdxChunks.empty())
-			{
-				UINT32 emptyChunkIdx = mEmptyIdxChunks.top();
-				ChunkData& emptyChunk = mIdxChunks[emptyChunkIdx];
-				mEmptyIdxChunks.pop();
-
-				emptyChunk.start = idxChunkStart + meshData->getNumIndices();
-				emptyChunk.size = remainingNumIdx;
-			}
-			else
-			{
-				ChunkData newChunk;
-				newChunk.size = remainingNumIdx;
-				newChunk.start = idxChunkStart + meshData->getNumIndices();
-
-				mIdxChunks.push_back(newChunk);
-				mFreeIdxChunks.push_back((UINT32)(mIdxChunks.size() - 1));
-			}
-		}
-
-		AllocatedData newAllocData;
-		newAllocData.vertChunkIdx = freeVertChunkIdx;
-		newAllocData.idxChunkIdx = freeIdxChunkIdx;
-		newAllocData.useFlags = UseFlags::GPUFree;
-		newAllocData.eventQueryIdx = createEventQuery();
-		newAllocData.mesh = mesh;
-
-		mMeshAllocData[mesh->getMeshHeapId()] = newAllocData;
-
-		// Actually copy data
-		for (UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)
-		{
-			if (!mVertexDesc->hasStream(i))
-				continue;
-
-			if (!meshData->getVertexDesc()->hasStream(i))
-				continue;
-
-			// Ensure vertex sizes match
-			UINT32 vertSize = mVertexData->vertexDeclaration->getProperties().getVertexSize(i);
-			UINT32 otherVertSize = meshData->getVertexDesc()->getVertexStride(i);
-			if (otherVertSize != vertSize)
-			{
-				BS_EXCEPT(InvalidParametersException, "Provided vertex size for stream " + toString(i) + " doesn't match meshes vertex size. Needed: " +
-					toString(vertSize) + ". Got: " + toString(otherVertSize));
-			}
-
-			SPtr<VertexBufferCore> vertexBuffer = mVertexData->getBuffer(i);
-			const VertexBufferProperties& vbProps = vertexBuffer->getProperties();
-
-			UINT8* vertDest = mCPUVertexData[i] + vertChunkStart * vertSize;
-			memcpy(vertDest, meshData->getStreamData(i), meshData->getNumVertices() * vertSize);
-
-			if (RenderAPICore::instance().getVertexColorFlipRequired())
-			{
-				UINT32 vertexStride = mVertexDesc->getVertexStride(i);
-				for (INT32 semanticIdx = 0; semanticIdx < VertexBuffer::MAX_SEMANTIC_IDX; semanticIdx++)
-				{
-					if (!mVertexDesc->hasElement(VES_COLOR, semanticIdx, i))
-						continue;
-
-					UINT8* colorData = vertDest + mVertexDesc->getElementOffsetFromStream(VES_COLOR, semanticIdx, i);
-					for (UINT32 j = 0; j < meshData->getNumVertices(); j++)
-					{
-						UINT32* curColor = (UINT32*)colorData;
-
-						(*curColor) = ((*curColor) & 0xFF00FF00) | ((*curColor >> 16) & 0x000000FF) | ((*curColor << 16) & 0x00FF0000);
-
-						colorData += vertexStride;
-					}
-				}
-			}
-
-			vertexBuffer->writeData(vertChunkStart * vertSize, meshData->getNumVertices() * vertSize, vertDest, BufferWriteType::NoOverwrite);
-		}
-
-		const IndexBufferProperties& ibProps = mIndexBuffer->getProperties();
-
-		UINT32 idxSize = ibProps.getIndexSize();
-
-		// Ensure index sizes match
-		if (meshData->getIndexElementSize() != idxSize)
-		{
-			BS_EXCEPT(InvalidParametersException, "Provided index size doesn't match meshes index size. Needed: " +
-				toString(idxSize) + ". Got: " + toString(meshData->getIndexElementSize()));
-		}
-
-		UINT8* idxDest = mCPUIndexData + idxChunkStart * idxSize;
-		memcpy(idxDest, meshData->getIndexData(), meshData->getNumIndices() * idxSize);
-		mIndexBuffer->writeData(idxChunkStart * idxSize, meshData->getNumIndices() * idxSize, idxDest, BufferWriteType::NoOverwrite);
-	}
-
-	void MeshHeapCore::dealloc(SPtr<TransientMeshCore> mesh)
-	{
-		auto findIter = mMeshAllocData.find(mesh->getMeshHeapId());
-		assert(findIter != mMeshAllocData.end());
-
-		AllocatedData& allocData = findIter->second;
-		if (allocData.useFlags == UseFlags::GPUFree)
-		{
-			allocData.useFlags = UseFlags::Free;
-			freeEventQuery(allocData.eventQueryIdx);
-
-			mFreeVertChunks.push_back(allocData.vertChunkIdx);
-			mFreeIdxChunks.push_back(allocData.idxChunkIdx);
-
-			mergeWithNearbyChunks(allocData.vertChunkIdx, allocData.idxChunkIdx);
-
-			mMeshAllocData.erase(findIter);
-		}
-		else if (allocData.useFlags == UseFlags::Used)
-			allocData.useFlags = UseFlags::CPUFree;
-	}
-
-	void MeshHeapCore::growVertexBuffer(UINT32 numVertices)
-	{
-		mNumVertices = numVertices;
-		mVertexData = std::shared_ptr<VertexData>(bs_new<VertexData>());
-
-		mVertexData->vertexCount = mNumVertices;
-		List<VertexElement> elements = mVertexDesc->createElements();
-
-		mVertexData->vertexDeclaration = HardwareBufferCoreManager::instance().createVertexDeclaration(elements);
-
-		// Create buffers and copy data
-		for (UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)
-		{
-			if (!mVertexDesc->hasStream(i))
-				continue;
-
-			UINT32 vertSize = mVertexData->vertexDeclaration->getProperties().getVertexSize(i);
-			SPtr<VertexBufferCore> vertexBuffer = HardwareBufferCoreManager::instance().createVertexBuffer(
-				vertSize, mVertexData->vertexCount, GBU_DYNAMIC);
-
-			mVertexData->setBuffer(i, vertexBuffer);
-
-			// Copy all data to the new buffer
-			UINT8* oldBuffer = mCPUVertexData[i];
-			UINT8* buffer = (UINT8*)bs_alloc(vertSize * numVertices);
-
-			UINT32 destOffset = 0;
-			if (oldBuffer != nullptr)
-			{
-				for (auto& allocData : mMeshAllocData)
-				{
-					ChunkData& oldChunk = mVertChunks[allocData.second.vertChunkIdx];
-
-					UINT8* oldData = oldBuffer + oldChunk.start * vertSize;
-					memcpy(buffer + destOffset * vertSize, oldData, oldChunk.size * vertSize);
-
-					destOffset += oldChunk.size;
-				}
-
-				bs_free(oldBuffer);
-			}
-
-			if (destOffset > 0)
-				vertexBuffer->writeData(0, destOffset * vertSize, buffer, BufferWriteType::NoOverwrite);
-
-			mCPUVertexData[i] = buffer;
-		}
-
-		// Reorder chunks
-		UINT32 destOffset = 0;
-		Vector<ChunkData> newVertChunks;
-		List<UINT32> freeVertChunks;
-
-		for (auto& allocData : mMeshAllocData)
-		{
-			ChunkData& oldChunk = mVertChunks[allocData.second.vertChunkIdx];
-
-			ChunkData newChunk;
-			newChunk.start = destOffset;
-			newChunk.size = oldChunk.size;
-
-			allocData.second.vertChunkIdx = (UINT32)newVertChunks.size();
-			newVertChunks.push_back(newChunk);
-
-			destOffset += oldChunk.size;
-		}
-
-		// Add free chunk
-		if (destOffset != mNumVertices)
-		{
-			ChunkData newChunk;
-			newChunk.start = destOffset;
-			newChunk.size = mNumVertices - destOffset;
-
-			newVertChunks.push_back(newChunk);
-			freeVertChunks.push_back((UINT32)(newVertChunks.size() - 1));
-		}
-
-		mVertChunks = newVertChunks;
-		mFreeVertChunks = freeVertChunks;
-
-		while (!mEmptyVertChunks.empty())
-			mEmptyVertChunks.pop();
-	}
-
-	void MeshHeapCore::growIndexBuffer(UINT32 numIndices)
-	{
-		mNumIndices = numIndices;
-
-		mIndexBuffer = HardwareBufferCoreManager::instance().createIndexBuffer(mIndexType, mNumIndices, GBU_DYNAMIC);
-		const IndexBufferProperties& ibProps = mIndexBuffer->getProperties();
-
-		// Copy all data to the new buffer
-		UINT32 idxSize = ibProps.getIndexSize();
-
-		UINT8* oldBuffer = mCPUIndexData;
-		UINT8* buffer = (UINT8*)bs_alloc(idxSize * numIndices);
-
-		UINT32 destOffset = 0;
-		if (oldBuffer != nullptr)
-		{
-			for (auto& allocData : mMeshAllocData)
-			{
-				ChunkData& oldChunk = mIdxChunks[allocData.second.idxChunkIdx];
-
-				UINT8* oldData = oldBuffer + oldChunk.start * idxSize;
-				memcpy(buffer + destOffset * idxSize, oldData, oldChunk.size * idxSize);
-
-				destOffset += oldChunk.size;
-			}
-
-			bs_free(oldBuffer);
-		}
-
-		if (destOffset > 0)
-			mIndexBuffer->writeData(0, destOffset * idxSize, buffer, BufferWriteType::NoOverwrite);
-
-		mCPUIndexData = buffer;
-
-		// Reorder chunks
-		destOffset = 0;
-		Vector<ChunkData> newIdxChunks;
-		List<UINT32> freeIdxChunks;
-
-		for (auto& allocData : mMeshAllocData)
-		{
-			ChunkData& oldChunk = mIdxChunks[allocData.second.idxChunkIdx];
-
-			ChunkData newChunk;
-			newChunk.start = destOffset;
-			newChunk.size = oldChunk.size;
-
-			allocData.second.idxChunkIdx = (UINT32)newIdxChunks.size();
-			newIdxChunks.push_back(newChunk);
-
-			destOffset += oldChunk.size;
-		}
-
-		// Add free chunk
-		if (destOffset != mNumIndices)
-		{
-			ChunkData newChunk;
-			newChunk.start = destOffset;
-			newChunk.size = mNumIndices - destOffset;
-
-			newIdxChunks.push_back(newChunk);
-			freeIdxChunks.push_back((UINT32)(newIdxChunks.size() - 1));
-		}
-
-		mIdxChunks = newIdxChunks;
-		mFreeIdxChunks = freeIdxChunks;
-
-		while (!mEmptyIdxChunks.empty())
-			mEmptyIdxChunks.pop();
-	}
-
-	UINT32 MeshHeapCore::createEventQuery()
-	{
-		UINT32 idx = 0;
-		if (mFreeEventQueries.size() > 0)
-		{
-			idx = mFreeEventQueries.top();
-			mFreeEventQueries.pop();
-		}
-		else
-		{
-			QueryData newQuery;
-			newQuery.query = EventQuery::create();
-			newQuery.queryId = 0;
-
-			mEventQueries.push_back(newQuery);
-			idx = (UINT32)(mEventQueries.size() - 1);
-		}
-
-		return idx;
-	}
-
-	void MeshHeapCore::freeEventQuery(UINT32 idx)
-	{
-		mEventQueries[idx].query->onTriggered.clear();
-		mEventQueries[idx].queryId = 0;
-		mFreeEventQueries.push(idx);
-	}
-
-	SPtr<VertexData> MeshHeapCore::getVertexData() const
-	{
-		return mVertexData;
-	}
-
-	SPtr<IndexBufferCore> MeshHeapCore::getIndexBuffer() const
-	{
-		return mIndexBuffer;
-	}
-
-	SPtr<VertexDataDesc> MeshHeapCore::getVertexDesc() const
-	{
-		return mVertexDesc;
-	}
-
-	UINT32 MeshHeapCore::getVertexOffset(UINT32 meshId) const
-	{
-		auto findIter = mMeshAllocData.find(meshId);
-		assert(findIter != mMeshAllocData.end());
-
-		UINT32 chunkIdx = findIter->second.vertChunkIdx;
-		return mVertChunks[chunkIdx].start;
-	}
-
-	UINT32 MeshHeapCore::getIndexOffset(UINT32 meshId) const
-	{
-		auto findIter = mMeshAllocData.find(meshId);
-		assert(findIter != mMeshAllocData.end());
-
-		UINT32 chunkIdx = findIter->second.idxChunkIdx;
-		return mIdxChunks[chunkIdx].start;
-	}
-
-	void MeshHeapCore::notifyUsedOnGPU(UINT32 meshId)
-	{
-		auto findIter = mMeshAllocData.find(meshId);
-		assert(findIter != mMeshAllocData.end());
-
-		AllocatedData& allocData = findIter->second;
-		assert(allocData.useFlags != UseFlags::Free);
-
-		if (allocData.useFlags == UseFlags::GPUFree)
-			allocData.useFlags = UseFlags::Used;
-
-		SPtr<MeshHeapCore> thisPtr = std::static_pointer_cast<MeshHeapCore>(getThisPtr());
-
-		QueryData& queryData = mEventQueries[allocData.eventQueryIdx];
-		queryData.queryId = mNextQueryId++;
-		queryData.query->onTriggered.clear();
-		queryData.query->onTriggered.connect(std::bind(&MeshHeapCore::queryTriggered, thisPtr, meshId, queryData.queryId));
-		queryData.query->begin();
-	}
-
-	// Note: Need to use a shared ptr here to ensure MeshHeap doesn't get deallocated sometime during this callback
-	void MeshHeapCore::queryTriggered(SPtr<MeshHeapCore> thisPtr, UINT32 meshId, UINT32 queryId)
-	{
-		auto findIter = thisPtr->mMeshAllocData.find(meshId);
-		assert(findIter != thisPtr->mMeshAllocData.end());
-
-		AllocatedData& allocData = findIter->second;
-
-		// If query ids don't match then it means there either a more recent query or
-		// the buffer was discarded and we are not interested in query result
-		QueryData& queryData = thisPtr->mEventQueries[allocData.eventQueryIdx];
-		if (queryId == queryData.queryId)
-		{
-			assert(allocData.useFlags != UseFlags::Free && allocData.useFlags != UseFlags::GPUFree);
-
-			if (allocData.useFlags == UseFlags::CPUFree)
-			{
-				allocData.useFlags = UseFlags::Free;
-				thisPtr->freeEventQuery(allocData.eventQueryIdx);
-
-				thisPtr->mFreeVertChunks.push_back(allocData.vertChunkIdx);
-				thisPtr->mFreeIdxChunks.push_back(allocData.idxChunkIdx);
-
-				thisPtr->mergeWithNearbyChunks(allocData.vertChunkIdx, allocData.idxChunkIdx);
-
-				thisPtr->mMeshAllocData.erase(findIter);
-			}
-			else
-				allocData.useFlags = UseFlags::GPUFree;
-		}
-
-		queryData.query->onTriggered.clear();
-	}
-
-	void MeshHeapCore::mergeWithNearbyChunks(UINT32 chunkVertIdx, UINT32 chunkIdxIdx)
-	{
-		// Merge vertex chunks
-		ChunkData& vertChunk = mVertChunks[chunkVertIdx];
-		for (auto& freeChunkIdx : mFreeVertChunks)
-		{
-			if (chunkVertIdx == freeChunkIdx)
-				continue;
-
-			ChunkData& curChunk = mVertChunks[freeChunkIdx];
-			if (curChunk.size == 0) // Already merged
-				continue;
-
-			bool merged = false;
-			if (curChunk.start == (vertChunk.start + vertChunk.size))
-			{
-				vertChunk.size += curChunk.size;
-
-				merged = true;
-			}
-			else if ((curChunk.start + curChunk.size) == vertChunk.start)
-			{
-				vertChunk.start = curChunk.start;
-				vertChunk.size += curChunk.size;
-
-				merged = true;
-			}
-
-			if (merged)
-			{
-				// We can't remove the chunk since that would break the indexing scheme, so 
-				// mark it as empty and set size to 0. It will be reused when needed.
-				curChunk.start = 0;
-				curChunk.size = 0;
-				mEmptyVertChunks.push(freeChunkIdx);
-			}
-		}
-
-		// Merge index chunks
-		ChunkData& idxChunk = mIdxChunks[chunkIdxIdx];
-		for (auto& freeChunkIdx : mFreeIdxChunks)
-		{
-			if (chunkIdxIdx == freeChunkIdx)
-				continue;
-
-			ChunkData& curChunk = mIdxChunks[freeChunkIdx];
-			if (curChunk.size == 0) // Already merged
-				continue;
-
-			bool merged = false;
-			if (curChunk.start == (idxChunk.start + idxChunk.size))
-			{
-				idxChunk.size += curChunk.size;
-
-				merged = true;
-			}
-			else if ((curChunk.start + curChunk.size) == idxChunk.start)
-			{
-				idxChunk.start = curChunk.start;
-				idxChunk.size += curChunk.size;
-
-				merged = true;
-			}
-
-			if (merged)
-			{
-				// We can't remove the chunk since that would break the indexing scheme, so 
-				// mark it as empty and set size to 0. It will be reused when needed.
-				curChunk.start = 0;
-				curChunk.size = 0;
-				mEmptyIdxChunks.push(freeChunkIdx);
-			}
-		}
-	}
-
-	MeshHeap::MeshHeap(UINT32 numVertices, UINT32 numIndices, 
-		const VertexDataDescPtr& vertexDesc, IndexType indexType)
-		:mNumVertices(numVertices), mNumIndices(numIndices), mNextFreeId(0), 
-		mIndexType(indexType), mVertexDesc(vertexDesc)
-	{
-	}
-
-	MeshHeapPtr MeshHeap::create(UINT32 numVertices, UINT32 numIndices, 
-		const VertexDataDescPtr& vertexDesc, IndexType indexType)
-	{
-		MeshHeap* meshHeap = new (bs_alloc<MeshHeap>()) MeshHeap(numVertices, numIndices, vertexDesc, indexType); 
-		MeshHeapPtr meshHeapPtr = bs_core_ptr<MeshHeap>(meshHeap);
-
-		meshHeapPtr->_setThisPtr(meshHeapPtr);
-		meshHeapPtr->initialize();
-
-		return meshHeapPtr;
-	}
-
-	TransientMeshPtr MeshHeap::alloc(const MeshDataPtr& meshData, DrawOperationType drawOp)
-	{
-		UINT32 meshIdx = mNextFreeId++;
-
-		MeshHeapPtr thisPtr = std::static_pointer_cast<MeshHeap>(getThisPtr());
-		TransientMesh* transientMesh = new (bs_alloc<TransientMesh>()) TransientMesh(thisPtr, meshIdx, meshData->getNumVertices(), meshData->getNumIndices(), drawOp); 
-		TransientMeshPtr transientMeshPtr = bs_core_ptr<TransientMesh>(transientMesh);
-
-		transientMeshPtr->_setThisPtr(transientMeshPtr);
-		transientMeshPtr->initialize();
-
-		mMeshes[meshIdx] = transientMeshPtr;
-
-		queueGpuCommand(getCore(), std::bind(&MeshHeapCore::alloc, getCore().get(), transientMeshPtr->getCore(), meshData));
-
-		return transientMeshPtr;
-	}
-
-	void MeshHeap::dealloc(const TransientMeshPtr& mesh)
-	{
-		auto iterFind = mMeshes.find(mesh->mId);
-		if(iterFind == mMeshes.end())
-			return;
-
-		mesh->markAsDestroyed();
-		mMeshes.erase(iterFind);
-
-		queueGpuCommand(getCore(), std::bind(&MeshHeapCore::dealloc, getCore().get(), mesh->getCore()));
-	}
-
-	SPtr<MeshHeapCore> MeshHeap::getCore() const
-	{
-		return std::static_pointer_cast<MeshHeapCore>(mCoreSpecific);
-	}
-
-	SPtr<CoreObjectCore> MeshHeap::createCore() const
-	{
-		MeshHeapCore* obj = new (bs_alloc<MeshHeapCore>()) MeshHeapCore(mNumVertices, mNumIndices,
-			mVertexDesc, mIndexType);
-
-		SPtr<MeshHeapCore> corePtr = bs_shared_ptr<MeshHeapCore>(obj);
-		obj->_setThisPtr(corePtr);
-
-		return corePtr;
-	}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsMeshHeap.h"
+#include "BsCoreThread.h"
+#include "BsTransientMesh.h"
+#include "BsHardwareBufferManager.h"
+#include "BsVertexDataDesc.h"
+#include "BsVertexData.h"
+#include "BsMeshData.h"
+#include "BsMath.h"
+#include "BsEventQuery.h"
+#include "BsRenderAPI.h"
+
+namespace BansheeEngine
+{
+	const float MeshHeapCore::GrowPercent = 1.5f;
+
+	MeshHeapCore::MeshHeapCore(UINT32 numVertices, UINT32 numIndices,
+		const VertexDataDescPtr& vertexDesc, IndexType indexType)
+		:mNumVertices(numVertices), mNumIndices(numIndices), mIndexType(indexType), 
+		mVertexDesc(vertexDesc), mCPUIndexData(nullptr), mNextQueryId(0)
+	{
+		for (UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)
+		{
+			mCPUVertexData.push_back(nullptr);
+		}
+	}
+
+	MeshHeapCore::~MeshHeapCore()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		for (auto& cpuVertBuffer : mCPUVertexData)
+			bs_free(cpuVertBuffer);
+
+		if (mCPUIndexData != nullptr)
+			bs_free(mCPUIndexData);
+
+		mVertexData = nullptr;
+		mIndexBuffer = nullptr;
+		mVertexDesc = nullptr;
+	}
+
+	void MeshHeapCore::initialize()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		growVertexBuffer(mNumVertices);
+		growIndexBuffer(mNumIndices);
+
+		CoreObjectCore::initialize();
+	}
+
+	void MeshHeapCore::alloc(SPtr<TransientMeshCore> mesh, const MeshDataPtr& meshData)
+	{
+		// Find free vertex chunk and grow if needed
+		UINT32 smallestVertFit = 0;
+		UINT32 smallestVertFitIdx = 0;
+
+		while (smallestVertFit == 0)
+		{
+			UINT32 curIdx = 0;
+			for (auto& chunkIdx : mFreeVertChunks)
+			{
+				ChunkData& chunk = mVertChunks[chunkIdx];
+
+				if (chunk.size >= meshData->getNumVertices() && (chunk.size < smallestVertFit || smallestVertFit == 0))
+				{
+					smallestVertFit = chunk.size;
+					smallestVertFitIdx = curIdx;
+				}
+
+				curIdx++;
+			}
+
+			if (smallestVertFit > 0)
+				break;
+
+			UINT32 newNumVertices = mNumVertices;
+			while (newNumVertices < (mNumVertices + meshData->getNumVertices()))
+			{
+				newNumVertices = Math::roundToInt(newNumVertices * GrowPercent);
+			}
+
+			growVertexBuffer(newNumVertices);
+		}
+
+		// Find free index chunk and grow if needed
+		UINT32 smallestIdxFit = 0;
+		UINT32 smallestIdxFitIdx = 0;
+
+		while (smallestIdxFit == 0)
+		{
+			UINT32 curIdx = 0;
+			for (auto& chunkIdx : mFreeIdxChunks)
+			{
+				ChunkData& chunk = mIdxChunks[chunkIdx];
+
+				if (chunk.size >= meshData->getNumIndices() && (chunk.size < smallestIdxFit || smallestIdxFit == 0))
+				{
+					smallestIdxFit = chunk.size;
+					smallestIdxFitIdx = curIdx;
+				}
+
+				curIdx++;
+			}
+
+			if (smallestIdxFit > 0)
+				break;
+
+			UINT32 newNumIndices = mNumIndices;
+			while (newNumIndices < (mNumIndices + meshData->getNumIndices()))
+			{
+				newNumIndices = Math::roundToInt(newNumIndices * GrowPercent);
+			}
+
+			growIndexBuffer(newNumIndices);
+		}
+
+		UINT32 freeVertChunkIdx = 0;
+		UINT32 freeIdxChunkIdx = 0;
+
+		auto freeVertIter = mFreeVertChunks.begin();
+		freeVertChunkIdx = (*freeVertIter);
+		for (UINT32 i = 0; i < smallestVertFitIdx; i++)
+		{
+			freeVertIter++;
+			freeVertChunkIdx = (*freeVertIter);
+		}
+
+		mFreeVertChunks.erase(freeVertIter);
+
+		auto freeIdxIter = mFreeIdxChunks.begin();
+		freeIdxChunkIdx = (*freeIdxIter);
+		for (UINT32 i = 0; i < smallestIdxFitIdx; i++)
+		{
+			freeIdxIter++;
+			freeIdxChunkIdx = (*freeIdxIter);
+		}
+
+		mFreeIdxChunks.erase(freeIdxIter);
+
+		ChunkData& vertChunk = mVertChunks[freeVertChunkIdx];
+		ChunkData& idxChunk = mIdxChunks[freeIdxChunkIdx];
+
+		UINT32 vertChunkStart = vertChunk.start;
+		UINT32 idxChunkStart = idxChunk.start;
+
+		UINT32 remainingNumVerts = vertChunk.size - meshData->getNumVertices();
+		UINT32 remainingNumIdx = idxChunk.size - meshData->getNumIndices();
+
+		vertChunk.size = meshData->getNumVertices();
+		idxChunk.size = meshData->getNumIndices();
+
+		if (remainingNumVerts > 0)
+		{
+			if (!mEmptyVertChunks.empty())
+			{
+				UINT32 emptyChunkIdx = mEmptyVertChunks.top();
+				ChunkData& emptyChunk = mVertChunks[emptyChunkIdx];
+				mEmptyVertChunks.pop();
+
+				emptyChunk.start = vertChunkStart + meshData->getNumVertices();
+				emptyChunk.size = remainingNumVerts;
+			}
+			else
+			{
+				ChunkData newChunk;
+				newChunk.size = remainingNumVerts;
+				newChunk.start = vertChunkStart + meshData->getNumVertices();
+
+				mVertChunks.push_back(newChunk);
+				mFreeVertChunks.push_back((UINT32)(mVertChunks.size() - 1));
+			}
+		}
+
+		if (remainingNumIdx > 0)
+		{
+			if (!mEmptyIdxChunks.empty())
+			{
+				UINT32 emptyChunkIdx = mEmptyIdxChunks.top();
+				ChunkData& emptyChunk = mIdxChunks[emptyChunkIdx];
+				mEmptyIdxChunks.pop();
+
+				emptyChunk.start = idxChunkStart + meshData->getNumIndices();
+				emptyChunk.size = remainingNumIdx;
+			}
+			else
+			{
+				ChunkData newChunk;
+				newChunk.size = remainingNumIdx;
+				newChunk.start = idxChunkStart + meshData->getNumIndices();
+
+				mIdxChunks.push_back(newChunk);
+				mFreeIdxChunks.push_back((UINT32)(mIdxChunks.size() - 1));
+			}
+		}
+
+		AllocatedData newAllocData;
+		newAllocData.vertChunkIdx = freeVertChunkIdx;
+		newAllocData.idxChunkIdx = freeIdxChunkIdx;
+		newAllocData.useFlags = UseFlags::GPUFree;
+		newAllocData.eventQueryIdx = createEventQuery();
+		newAllocData.mesh = mesh;
+
+		mMeshAllocData[mesh->getMeshHeapId()] = newAllocData;
+
+		// Actually copy data
+		for (UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)
+		{
+			if (!mVertexDesc->hasStream(i))
+				continue;
+
+			if (!meshData->getVertexDesc()->hasStream(i))
+				continue;
+
+			// Ensure vertex sizes match
+			UINT32 vertSize = mVertexData->vertexDeclaration->getProperties().getVertexSize(i);
+			UINT32 otherVertSize = meshData->getVertexDesc()->getVertexStride(i);
+			if (otherVertSize != vertSize)
+			{
+				BS_EXCEPT(InvalidParametersException, "Provided vertex size for stream " + toString(i) + " doesn't match meshes vertex size. Needed: " +
+					toString(vertSize) + ". Got: " + toString(otherVertSize));
+			}
+
+			SPtr<VertexBufferCore> vertexBuffer = mVertexData->getBuffer(i);
+			const VertexBufferProperties& vbProps = vertexBuffer->getProperties();
+
+			UINT8* vertDest = mCPUVertexData[i] + vertChunkStart * vertSize;
+			memcpy(vertDest, meshData->getStreamData(i), meshData->getNumVertices() * vertSize);
+
+			if (RenderAPICore::instance().getAPIInfo().getVertexColorFlipRequired())
+			{
+				UINT32 vertexStride = mVertexDesc->getVertexStride(i);
+				for (INT32 semanticIdx = 0; semanticIdx < VertexBuffer::MAX_SEMANTIC_IDX; semanticIdx++)
+				{
+					if (!mVertexDesc->hasElement(VES_COLOR, semanticIdx, i))
+						continue;
+
+					UINT8* colorData = vertDest + mVertexDesc->getElementOffsetFromStream(VES_COLOR, semanticIdx, i);
+					for (UINT32 j = 0; j < meshData->getNumVertices(); j++)
+					{
+						UINT32* curColor = (UINT32*)colorData;
+
+						(*curColor) = ((*curColor) & 0xFF00FF00) | ((*curColor >> 16) & 0x000000FF) | ((*curColor << 16) & 0x00FF0000);
+
+						colorData += vertexStride;
+					}
+				}
+			}
+
+			vertexBuffer->writeData(vertChunkStart * vertSize, meshData->getNumVertices() * vertSize, vertDest, BufferWriteType::NoOverwrite);
+		}
+
+		const IndexBufferProperties& ibProps = mIndexBuffer->getProperties();
+
+		UINT32 idxSize = ibProps.getIndexSize();
+
+		// Ensure index sizes match
+		if (meshData->getIndexElementSize() != idxSize)
+		{
+			BS_EXCEPT(InvalidParametersException, "Provided index size doesn't match meshes index size. Needed: " +
+				toString(idxSize) + ". Got: " + toString(meshData->getIndexElementSize()));
+		}
+
+		UINT8* idxDest = mCPUIndexData + idxChunkStart * idxSize;
+		memcpy(idxDest, meshData->getIndexData(), meshData->getNumIndices() * idxSize);
+		mIndexBuffer->writeData(idxChunkStart * idxSize, meshData->getNumIndices() * idxSize, idxDest, BufferWriteType::NoOverwrite);
+	}
+
+	void MeshHeapCore::dealloc(SPtr<TransientMeshCore> mesh)
+	{
+		auto findIter = mMeshAllocData.find(mesh->getMeshHeapId());
+		assert(findIter != mMeshAllocData.end());
+
+		AllocatedData& allocData = findIter->second;
+		if (allocData.useFlags == UseFlags::GPUFree)
+		{
+			allocData.useFlags = UseFlags::Free;
+			freeEventQuery(allocData.eventQueryIdx);
+
+			mFreeVertChunks.push_back(allocData.vertChunkIdx);
+			mFreeIdxChunks.push_back(allocData.idxChunkIdx);
+
+			mergeWithNearbyChunks(allocData.vertChunkIdx, allocData.idxChunkIdx);
+
+			mMeshAllocData.erase(findIter);
+		}
+		else if (allocData.useFlags == UseFlags::Used)
+			allocData.useFlags = UseFlags::CPUFree;
+	}
+
+	void MeshHeapCore::growVertexBuffer(UINT32 numVertices)
+	{
+		mNumVertices = numVertices;
+		mVertexData = std::shared_ptr<VertexData>(bs_new<VertexData>());
+
+		mVertexData->vertexCount = mNumVertices;
+		List<VertexElement> elements = mVertexDesc->createElements();
+
+		mVertexData->vertexDeclaration = HardwareBufferCoreManager::instance().createVertexDeclaration(elements);
+
+		// Create buffers and copy data
+		for (UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)
+		{
+			if (!mVertexDesc->hasStream(i))
+				continue;
+
+			UINT32 vertSize = mVertexData->vertexDeclaration->getProperties().getVertexSize(i);
+			SPtr<VertexBufferCore> vertexBuffer = HardwareBufferCoreManager::instance().createVertexBuffer(
+				vertSize, mVertexData->vertexCount, GBU_DYNAMIC);
+
+			mVertexData->setBuffer(i, vertexBuffer);
+
+			// Copy all data to the new buffer
+			UINT8* oldBuffer = mCPUVertexData[i];
+			UINT8* buffer = (UINT8*)bs_alloc(vertSize * numVertices);
+
+			UINT32 destOffset = 0;
+			if (oldBuffer != nullptr)
+			{
+				for (auto& allocData : mMeshAllocData)
+				{
+					ChunkData& oldChunk = mVertChunks[allocData.second.vertChunkIdx];
+
+					UINT8* oldData = oldBuffer + oldChunk.start * vertSize;
+					memcpy(buffer + destOffset * vertSize, oldData, oldChunk.size * vertSize);
+
+					destOffset += oldChunk.size;
+				}
+
+				bs_free(oldBuffer);
+			}
+
+			if (destOffset > 0)
+				vertexBuffer->writeData(0, destOffset * vertSize, buffer, BufferWriteType::NoOverwrite);
+
+			mCPUVertexData[i] = buffer;
+		}
+
+		// Reorder chunks
+		UINT32 destOffset = 0;
+		Vector<ChunkData> newVertChunks;
+		List<UINT32> freeVertChunks;
+
+		for (auto& allocData : mMeshAllocData)
+		{
+			ChunkData& oldChunk = mVertChunks[allocData.second.vertChunkIdx];
+
+			ChunkData newChunk;
+			newChunk.start = destOffset;
+			newChunk.size = oldChunk.size;
+
+			allocData.second.vertChunkIdx = (UINT32)newVertChunks.size();
+			newVertChunks.push_back(newChunk);
+
+			destOffset += oldChunk.size;
+		}
+
+		// Add free chunk
+		if (destOffset != mNumVertices)
+		{
+			ChunkData newChunk;
+			newChunk.start = destOffset;
+			newChunk.size = mNumVertices - destOffset;
+
+			newVertChunks.push_back(newChunk);
+			freeVertChunks.push_back((UINT32)(newVertChunks.size() - 1));
+		}
+
+		mVertChunks = newVertChunks;
+		mFreeVertChunks = freeVertChunks;
+
+		while (!mEmptyVertChunks.empty())
+			mEmptyVertChunks.pop();
+	}
+
+	void MeshHeapCore::growIndexBuffer(UINT32 numIndices)
+	{
+		mNumIndices = numIndices;
+
+		mIndexBuffer = HardwareBufferCoreManager::instance().createIndexBuffer(mIndexType, mNumIndices, GBU_DYNAMIC);
+		const IndexBufferProperties& ibProps = mIndexBuffer->getProperties();
+
+		// Copy all data to the new buffer
+		UINT32 idxSize = ibProps.getIndexSize();
+
+		UINT8* oldBuffer = mCPUIndexData;
+		UINT8* buffer = (UINT8*)bs_alloc(idxSize * numIndices);
+
+		UINT32 destOffset = 0;
+		if (oldBuffer != nullptr)
+		{
+			for (auto& allocData : mMeshAllocData)
+			{
+				ChunkData& oldChunk = mIdxChunks[allocData.second.idxChunkIdx];
+
+				UINT8* oldData = oldBuffer + oldChunk.start * idxSize;
+				memcpy(buffer + destOffset * idxSize, oldData, oldChunk.size * idxSize);
+
+				destOffset += oldChunk.size;
+			}
+
+			bs_free(oldBuffer);
+		}
+
+		if (destOffset > 0)
+			mIndexBuffer->writeData(0, destOffset * idxSize, buffer, BufferWriteType::NoOverwrite);
+
+		mCPUIndexData = buffer;
+
+		// Reorder chunks
+		destOffset = 0;
+		Vector<ChunkData> newIdxChunks;
+		List<UINT32> freeIdxChunks;
+
+		for (auto& allocData : mMeshAllocData)
+		{
+			ChunkData& oldChunk = mIdxChunks[allocData.second.idxChunkIdx];
+
+			ChunkData newChunk;
+			newChunk.start = destOffset;
+			newChunk.size = oldChunk.size;
+
+			allocData.second.idxChunkIdx = (UINT32)newIdxChunks.size();
+			newIdxChunks.push_back(newChunk);
+
+			destOffset += oldChunk.size;
+		}
+
+		// Add free chunk
+		if (destOffset != mNumIndices)
+		{
+			ChunkData newChunk;
+			newChunk.start = destOffset;
+			newChunk.size = mNumIndices - destOffset;
+
+			newIdxChunks.push_back(newChunk);
+			freeIdxChunks.push_back((UINT32)(newIdxChunks.size() - 1));
+		}
+
+		mIdxChunks = newIdxChunks;
+		mFreeIdxChunks = freeIdxChunks;
+
+		while (!mEmptyIdxChunks.empty())
+			mEmptyIdxChunks.pop();
+	}
+
+	UINT32 MeshHeapCore::createEventQuery()
+	{
+		UINT32 idx = 0;
+		if (mFreeEventQueries.size() > 0)
+		{
+			idx = mFreeEventQueries.top();
+			mFreeEventQueries.pop();
+		}
+		else
+		{
+			QueryData newQuery;
+			newQuery.query = EventQuery::create();
+			newQuery.queryId = 0;
+
+			mEventQueries.push_back(newQuery);
+			idx = (UINT32)(mEventQueries.size() - 1);
+		}
+
+		return idx;
+	}
+
+	void MeshHeapCore::freeEventQuery(UINT32 idx)
+	{
+		mEventQueries[idx].query->onTriggered.clear();
+		mEventQueries[idx].queryId = 0;
+		mFreeEventQueries.push(idx);
+	}
+
+	SPtr<VertexData> MeshHeapCore::getVertexData() const
+	{
+		return mVertexData;
+	}
+
+	SPtr<IndexBufferCore> MeshHeapCore::getIndexBuffer() const
+	{
+		return mIndexBuffer;
+	}
+
+	SPtr<VertexDataDesc> MeshHeapCore::getVertexDesc() const
+	{
+		return mVertexDesc;
+	}
+
+	UINT32 MeshHeapCore::getVertexOffset(UINT32 meshId) const
+	{
+		auto findIter = mMeshAllocData.find(meshId);
+		assert(findIter != mMeshAllocData.end());
+
+		UINT32 chunkIdx = findIter->second.vertChunkIdx;
+		return mVertChunks[chunkIdx].start;
+	}
+
+	UINT32 MeshHeapCore::getIndexOffset(UINT32 meshId) const
+	{
+		auto findIter = mMeshAllocData.find(meshId);
+		assert(findIter != mMeshAllocData.end());
+
+		UINT32 chunkIdx = findIter->second.idxChunkIdx;
+		return mIdxChunks[chunkIdx].start;
+	}
+
+	void MeshHeapCore::notifyUsedOnGPU(UINT32 meshId)
+	{
+		auto findIter = mMeshAllocData.find(meshId);
+		assert(findIter != mMeshAllocData.end());
+
+		AllocatedData& allocData = findIter->second;
+		assert(allocData.useFlags != UseFlags::Free);
+
+		if (allocData.useFlags == UseFlags::GPUFree)
+			allocData.useFlags = UseFlags::Used;
+
+		SPtr<MeshHeapCore> thisPtr = std::static_pointer_cast<MeshHeapCore>(getThisPtr());
+
+		QueryData& queryData = mEventQueries[allocData.eventQueryIdx];
+		queryData.queryId = mNextQueryId++;
+		queryData.query->onTriggered.clear();
+		queryData.query->onTriggered.connect(std::bind(&MeshHeapCore::queryTriggered, thisPtr, meshId, queryData.queryId));
+		queryData.query->begin();
+	}
+
+	// Note: Need to use a shared ptr here to ensure MeshHeap doesn't get deallocated sometime during this callback
+	void MeshHeapCore::queryTriggered(SPtr<MeshHeapCore> thisPtr, UINT32 meshId, UINT32 queryId)
+	{
+		auto findIter = thisPtr->mMeshAllocData.find(meshId);
+		assert(findIter != thisPtr->mMeshAllocData.end());
+
+		AllocatedData& allocData = findIter->second;
+
+		// If query ids don't match then it means there either a more recent query or
+		// the buffer was discarded and we are not interested in query result
+		QueryData& queryData = thisPtr->mEventQueries[allocData.eventQueryIdx];
+		if (queryId == queryData.queryId)
+		{
+			assert(allocData.useFlags != UseFlags::Free && allocData.useFlags != UseFlags::GPUFree);
+
+			if (allocData.useFlags == UseFlags::CPUFree)
+			{
+				allocData.useFlags = UseFlags::Free;
+				thisPtr->freeEventQuery(allocData.eventQueryIdx);
+
+				thisPtr->mFreeVertChunks.push_back(allocData.vertChunkIdx);
+				thisPtr->mFreeIdxChunks.push_back(allocData.idxChunkIdx);
+
+				thisPtr->mergeWithNearbyChunks(allocData.vertChunkIdx, allocData.idxChunkIdx);
+
+				thisPtr->mMeshAllocData.erase(findIter);
+			}
+			else
+				allocData.useFlags = UseFlags::GPUFree;
+		}
+
+		queryData.query->onTriggered.clear();
+	}
+
+	void MeshHeapCore::mergeWithNearbyChunks(UINT32 chunkVertIdx, UINT32 chunkIdxIdx)
+	{
+		// Merge vertex chunks
+		ChunkData& vertChunk = mVertChunks[chunkVertIdx];
+		for (auto& freeChunkIdx : mFreeVertChunks)
+		{
+			if (chunkVertIdx == freeChunkIdx)
+				continue;
+
+			ChunkData& curChunk = mVertChunks[freeChunkIdx];
+			if (curChunk.size == 0) // Already merged
+				continue;
+
+			bool merged = false;
+			if (curChunk.start == (vertChunk.start + vertChunk.size))
+			{
+				vertChunk.size += curChunk.size;
+
+				merged = true;
+			}
+			else if ((curChunk.start + curChunk.size) == vertChunk.start)
+			{
+				vertChunk.start = curChunk.start;
+				vertChunk.size += curChunk.size;
+
+				merged = true;
+			}
+
+			if (merged)
+			{
+				// We can't remove the chunk since that would break the indexing scheme, so 
+				// mark it as empty and set size to 0. It will be reused when needed.
+				curChunk.start = 0;
+				curChunk.size = 0;
+				mEmptyVertChunks.push(freeChunkIdx);
+			}
+		}
+
+		// Merge index chunks
+		ChunkData& idxChunk = mIdxChunks[chunkIdxIdx];
+		for (auto& freeChunkIdx : mFreeIdxChunks)
+		{
+			if (chunkIdxIdx == freeChunkIdx)
+				continue;
+
+			ChunkData& curChunk = mIdxChunks[freeChunkIdx];
+			if (curChunk.size == 0) // Already merged
+				continue;
+
+			bool merged = false;
+			if (curChunk.start == (idxChunk.start + idxChunk.size))
+			{
+				idxChunk.size += curChunk.size;
+
+				merged = true;
+			}
+			else if ((curChunk.start + curChunk.size) == idxChunk.start)
+			{
+				idxChunk.start = curChunk.start;
+				idxChunk.size += curChunk.size;
+
+				merged = true;
+			}
+
+			if (merged)
+			{
+				// We can't remove the chunk since that would break the indexing scheme, so 
+				// mark it as empty and set size to 0. It will be reused when needed.
+				curChunk.start = 0;
+				curChunk.size = 0;
+				mEmptyIdxChunks.push(freeChunkIdx);
+			}
+		}
+	}
+
+	MeshHeap::MeshHeap(UINT32 numVertices, UINT32 numIndices, 
+		const VertexDataDescPtr& vertexDesc, IndexType indexType)
+		:mNumVertices(numVertices), mNumIndices(numIndices), mNextFreeId(0), 
+		mIndexType(indexType), mVertexDesc(vertexDesc)
+	{
+	}
+
+	MeshHeapPtr MeshHeap::create(UINT32 numVertices, UINT32 numIndices, 
+		const VertexDataDescPtr& vertexDesc, IndexType indexType)
+	{
+		MeshHeap* meshHeap = new (bs_alloc<MeshHeap>()) MeshHeap(numVertices, numIndices, vertexDesc, indexType); 
+		MeshHeapPtr meshHeapPtr = bs_core_ptr<MeshHeap>(meshHeap);
+
+		meshHeapPtr->_setThisPtr(meshHeapPtr);
+		meshHeapPtr->initialize();
+
+		return meshHeapPtr;
+	}
+
+	TransientMeshPtr MeshHeap::alloc(const MeshDataPtr& meshData, DrawOperationType drawOp)
+	{
+		UINT32 meshIdx = mNextFreeId++;
+
+		MeshHeapPtr thisPtr = std::static_pointer_cast<MeshHeap>(getThisPtr());
+		TransientMesh* transientMesh = new (bs_alloc<TransientMesh>()) TransientMesh(thisPtr, meshIdx, meshData->getNumVertices(), meshData->getNumIndices(), drawOp); 
+		TransientMeshPtr transientMeshPtr = bs_core_ptr<TransientMesh>(transientMesh);
+
+		transientMeshPtr->_setThisPtr(transientMeshPtr);
+		transientMeshPtr->initialize();
+
+		mMeshes[meshIdx] = transientMeshPtr;
+
+		queueGpuCommand(getCore(), std::bind(&MeshHeapCore::alloc, getCore().get(), transientMeshPtr->getCore(), meshData));
+
+		return transientMeshPtr;
+	}
+
+	void MeshHeap::dealloc(const TransientMeshPtr& mesh)
+	{
+		auto iterFind = mMeshes.find(mesh->mId);
+		if(iterFind == mMeshes.end())
+			return;
+
+		mesh->markAsDestroyed();
+		mMeshes.erase(iterFind);
+
+		queueGpuCommand(getCore(), std::bind(&MeshHeapCore::dealloc, getCore().get(), mesh->getCore()));
+	}
+
+	SPtr<MeshHeapCore> MeshHeap::getCore() const
+	{
+		return std::static_pointer_cast<MeshHeapCore>(mCoreSpecific);
+	}
+
+	SPtr<CoreObjectCore> MeshHeap::createCore() const
+	{
+		MeshHeapCore* obj = new (bs_alloc<MeshHeapCore>()) MeshHeapCore(mNumVertices, mNumIndices,
+			mVertexDesc, mIndexType);
+
+		SPtr<MeshHeapCore> corePtr = bs_shared_ptr<MeshHeapCore>(obj);
+		obj->_setThisPtr(corePtr);
+
+		return corePtr;
+	}
 }

+ 440 - 465
Source/BansheeCore/Source/BsRenderAPI.cpp

@@ -1,466 +1,441 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsRenderAPI.h"
-
-#include "BsCoreThread.h"
-#include "BsViewport.h"
-#include "BsRenderTarget.h"
-#include "BsRenderWindow.h"
-#include "BsResource.h"
-#include "BsMesh.h"
-#include "BsRenderStats.h"
-#include "BsGpuParams.h"
-#include "BsBlendState.h"
-#include "BsDepthStencilState.h"
-#include "BsRasterizerState.h"
-#include "BsGpuParamDesc.h"
-
-using namespace std::placeholders;
-
-namespace BansheeEngine 
-{
-	void RenderAPI::disableTextureUnit(CoreAccessor& accessor, GpuProgramType gptype, UINT16 texUnit)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::disableTextureUnit, RenderAPICore::instancePtr(), gptype, texUnit));
-	}
-
-	void RenderAPI::setTexture(CoreAccessor& accessor, GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr &texPtr)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setTexture, RenderAPICore::instancePtr(), gptype, unit, enabled, texPtr->getCore()));
-	}
-
-	void RenderAPI::setLoadStoreTexture(CoreAccessor& accessor, GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr& texPtr,
-		const TextureSurface& surface)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setLoadStoreTexture, RenderAPICore::instancePtr(), gptype, unit, enabled, texPtr->getCore(),
-			surface));
-	}
-
-	void RenderAPI::setSamplerState(CoreAccessor& accessor, GpuProgramType gptype, UINT16 texUnit, const SamplerStatePtr& samplerState)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setSamplerState, RenderAPICore::instancePtr(), gptype, texUnit, samplerState->getCore()));
-	}
-
-	void RenderAPI::setBlendState(CoreAccessor& accessor, const BlendStatePtr& blendState)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setBlendState, RenderAPICore::instancePtr(), blendState->getCore()));
-	}
-
-	void RenderAPI::setRasterizerState(CoreAccessor& accessor, const RasterizerStatePtr& rasterizerState)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setRasterizerState, RenderAPICore::instancePtr(), rasterizerState->getCore()));
-	}
-
-	void RenderAPI::setDepthStencilState(CoreAccessor& accessor, const DepthStencilStatePtr& depthStencilState, UINT32 stencilRefValue)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setDepthStencilState, RenderAPICore::instancePtr(), depthStencilState->getCore(), stencilRefValue));
-	}
-
-	void RenderAPI::setVertexBuffers(CoreAccessor& accessor, UINT32 index, const Vector<VertexBufferPtr>& buffers)
-	{
-		Vector<SPtr<VertexBufferCore>> coreBuffers(buffers.size());
-		for (UINT32 i = 0; i < (UINT32)buffers.size(); i++)
-			coreBuffers[i] = buffers[i] != nullptr ? buffers[i]->getCore() : nullptr;
-
-		std::function<void(RenderAPICore*, UINT32, const Vector<SPtr<VertexBufferCore>>&)> resizeFunc =
-			[](RenderAPICore* rs, UINT32 idx, const Vector<SPtr<VertexBufferCore>>& _buffers)
-		{
-			rs->setVertexBuffers(idx, (SPtr<VertexBufferCore>*)_buffers.data(), (UINT32)_buffers.size());
-		};
-
-		accessor.queueCommand(std::bind(resizeFunc, RenderAPICore::instancePtr(), index, coreBuffers));
-	}
-
-	void RenderAPI::setIndexBuffer(CoreAccessor& accessor, const IndexBufferPtr& buffer)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setIndexBuffer, RenderAPICore::instancePtr(), buffer->getCore()));
-	}
-
-	void RenderAPI::setVertexDeclaration(CoreAccessor& accessor, const VertexDeclarationPtr& vertexDeclaration)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setVertexDeclaration, RenderAPICore::instancePtr(), vertexDeclaration->getCore()));
-	}
-
-	void RenderAPI::setViewport(CoreAccessor& accessor, const Rect2& vp)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setViewport, RenderAPICore::instancePtr(), vp));
-	}
-
-	void RenderAPI::setDrawOperation(CoreAccessor& accessor, DrawOperationType op)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setDrawOperation, RenderAPICore::instancePtr(), op));
-	}
-
-	void RenderAPI::setClipPlanes(CoreAccessor& accessor, const PlaneList& clipPlanes)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setClipPlanes, RenderAPICore::instancePtr(), clipPlanes));
-	}
-
-	void RenderAPI::addClipPlane(CoreAccessor& accessor, const Plane& p)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::addClipPlane, RenderAPICore::instancePtr(), p));
-	}
-
-	void RenderAPI::resetClipPlanes(CoreAccessor& accessor)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::resetClipPlanes, RenderAPICore::instancePtr()));
-	}
-
-	void RenderAPI::setScissorTest(CoreAccessor& accessor, UINT32 left, UINT32 top, UINT32 right, UINT32 bottom)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setScissorRect, RenderAPICore::instancePtr(), left, top, right, bottom));
-	}
-
-	void RenderAPI::setRenderTarget(CoreAccessor& accessor, const RenderTargetPtr& target, bool readOnlyDepthStencil)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setRenderTarget, 
-			RenderAPICore::instancePtr(), target->getCore(), readOnlyDepthStencil));
-	}
-
-	void RenderAPI::bindGpuProgram(CoreAccessor& accessor, const GpuProgramPtr& prg)
-	{
-		prg->syncToCore(accessor);
-		accessor.queueCommand(std::bind(&RenderAPICore::bindGpuProgram, RenderAPICore::instancePtr(), prg->getCore()));
-	}
-
-	void RenderAPI::unbindGpuProgram(CoreAccessor& accessor, GpuProgramType gptype)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::unbindGpuProgram, RenderAPICore::instancePtr(), gptype));
-	}
-
-	void RenderAPI::setConstantBuffers(CoreAccessor& accessor, GpuProgramType gptype, const GpuParamsPtr& params)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setConstantBuffers, RenderAPICore::instancePtr(), gptype, params->getCore()));
-	}
-
-	void RenderAPI::setGpuParams(CoreAccessor& accessor, GpuProgramType gptype, const GpuParamsPtr& params)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setGpuParams, RenderAPICore::instancePtr(), gptype, params->getCore()));
-	}
-
-	void RenderAPI::beginRender(CoreAccessor& accessor)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::beginFrame, RenderAPICore::instancePtr()));
-	}
-
-	void RenderAPI::endRender(CoreAccessor& accessor)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::endFrame, RenderAPICore::instancePtr()));
-	}
-
-	void RenderAPI::clearRenderTarget(CoreAccessor& accessor, UINT32 buffers, const Color& color, float depth, UINT16 stencil, UINT8 targetMask)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::clearRenderTarget, RenderAPICore::instancePtr(), buffers, color,
-			depth, stencil, targetMask));
-	}
-
-	void RenderAPI::clearViewport(CoreAccessor& accessor, UINT32 buffers, const Color& color, float depth, UINT16 stencil, UINT8 targetMask)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::clearViewport, RenderAPICore::instancePtr(), buffers, color, depth,
-			stencil, targetMask));
-	}
-
-	void RenderAPI::swapBuffers(CoreAccessor& accessor, const RenderTargetPtr& target)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::swapBuffers, RenderAPICore::instancePtr(), target->getCore()));
-	}
-
-	void RenderAPI::draw(CoreAccessor& accessor, UINT32 vertexOffset, UINT32 vertexCount)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::draw, RenderAPICore::instancePtr(), vertexOffset, vertexCount));
-	}
-
-	void RenderAPI::drawIndexed(CoreAccessor& accessor, UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::drawIndexed, RenderAPICore::instancePtr(), startIndex, indexCount, 
-			vertexOffset, vertexCount));
-	}
-
-	void RenderAPI::dispatchCompute(CoreAccessor& accessor, UINT32 numGroupsX, UINT32 numGroupsY, UINT32 numGroupsZ)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::dispatchCompute, RenderAPICore::instancePtr(), numGroupsX, 
-			numGroupsY, numGroupsZ));
-	}
-
-	const VideoModeInfo& RenderAPI::getVideoModeInfo()
-	{
-		return RenderAPICore::instance().getVideoModeInfo();
-	}
-
-	VertexElementType RenderAPI::getColorVertexElementType()
-	{
-		return RenderAPICore::instance().getColorVertexElementType();
-	}
-
-	void RenderAPI::convertProjectionMatrix(const Matrix4& matrix, Matrix4& dest)
-	{
-		RenderAPICore::instance().convertProjectionMatrix(matrix, dest);
-	}
-
-	float RenderAPI::getHorizontalTexelOffset()
-	{
-		return RenderAPICore::instance().getHorizontalTexelOffset();
-	}
-
-	float RenderAPI::getVerticalTexelOffset()
-	{
-		return RenderAPICore::instance().getVerticalTexelOffset();
-	}
-
-	float RenderAPI::getMinimumDepthInputValue()
-	{
-		return RenderAPICore::instance().getMinimumDepthInputValue();
-	}
-
-	float RenderAPI::getMaximumDepthInputValue()
-	{
-		return RenderAPICore::instance().getMaximumDepthInputValue();
-	}
-
-	bool RenderAPI::getVertexColorFlipRequired()
-	{
-		return RenderAPICore::instance().getVertexColorFlipRequired();
-	}
-
-    RenderAPICore::RenderAPICore()
-        : mCullingMode(CULL_COUNTERCLOCKWISE)
-        , mDisabledTexUnitsFrom(0)
-        , mVertexProgramBound(false)
-		, mGeometryProgramBound(false)
-        , mFragmentProgramBound(false)
-		, mDomainProgramBound(false)
-		, mHullProgramBound(false)
-		, mComputeProgramBound(false)
-		, mClipPlanesDirty(true)
-		, mCurrentCapabilities(nullptr)
-    {
-    }
-
-    RenderAPICore::~RenderAPICore()
-    {
-		// Base classes need to call virtual destroy_internal method instead of a destructor
-
-		bs_delete(mCurrentCapabilities);
-		mCurrentCapabilities = nullptr;
-    }
-
-	RenderWindowPtr RenderAPICore::initialize(const RENDER_WINDOW_DESC& primaryWindowDesc)
-	{
-		gCoreThread().queueCommand(std::bind(&RenderAPICore::initializePrepare, this), true);
-
-		RENDER_WINDOW_DESC windowDesc = primaryWindowDesc;
-		RenderWindowPtr renderWindow = RenderWindow::create(windowDesc, nullptr);
-
-		gCoreThread().queueCommand(std::bind(&RenderAPICore::initializeFinalize, this, renderWindow->getCore()), true);
-
-		return renderWindow;
-	}
-
-	void RenderAPICore::initializePrepare()
-	{
-		// Do nothing
-	}
-
-	void RenderAPICore::initializeFinalize(const SPtr<RenderWindowCore>& primaryWindow)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		mVertexProgramBound = false;
-		mGeometryProgramBound = false;
-		mFragmentProgramBound = false;
-		mDomainProgramBound = false;
-		mHullProgramBound = false;
-		mComputeProgramBound = false;
-	}
-
-	void RenderAPICore::destroy()
-	{
-		gCoreAccessor().queueCommand(std::bind(&RenderAPICore::destroyCore, this));
-		gCoreThread().submitAccessors(true);
-	}
-
-	void RenderAPICore::destroyCore()
-	{
-		mActiveRenderTarget = nullptr;
-	}
-
-	const RenderAPICapabilities* RenderAPICore::getCapabilities(void) const 
-	{ 
-		return mCurrentCapabilities; 
-	}
-
-	const DriverVersion& RenderAPICore::getDriverVersion(void) const 
-	{ 
-		THROW_IF_NOT_CORE_THREAD;
-
-		return mDriverVersion; 
-	}
-
-    void RenderAPICore::disableTextureUnit(GpuProgramType gptype, UINT16 texUnit)
-    {
-		THROW_IF_NOT_CORE_THREAD;
-
-		setTexture(gptype, texUnit, false, SPtr<TextureCore>());
-    }
-
-	void RenderAPICore::addClipPlane(const Plane &p)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		mClipPlanes.push_back(p);
-		mClipPlanesDirty = true;
-	}
-
-	void RenderAPICore::setClipPlanes(const PlaneList& clipPlanes)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		if (clipPlanes != mClipPlanes)
-		{
-			mClipPlanes = clipPlanes;
-			mClipPlanesDirty = true;
-		}
-	}
-
-	void RenderAPICore::resetClipPlanes()
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		if (!mClipPlanes.empty())
-		{
-			mClipPlanes.clear();
-			mClipPlanesDirty = true;
-		}
-	}
-
-	void RenderAPICore::bindGpuProgram(const SPtr<GpuProgramCore>& prg)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		switch(prg->getProperties().getType())
-		{
-		case GPT_VERTEX_PROGRAM:
-			if (!mVertexProgramBound && !mClipPlanes.empty())
-				mClipPlanesDirty = true;
-
-			mVertexProgramBound = true;
-			break;
-		case GPT_GEOMETRY_PROGRAM:
-			mGeometryProgramBound = true;
-			break;
-		case GPT_FRAGMENT_PROGRAM:
-			mFragmentProgramBound = true;
-			break;
-		case GPT_DOMAIN_PROGRAM:
-			mDomainProgramBound = true;
-			break;
-		case GPT_HULL_PROGRAM:
-			mHullProgramBound = true;
-			break;
-		case GPT_COMPUTE_PROGRAM:
-			mComputeProgramBound = true;
-			break;
-		}
-	}
-
-	void RenderAPICore::unbindGpuProgram(GpuProgramType gptype)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		switch(gptype)
-		{
-		case GPT_VERTEX_PROGRAM:
-			if (mVertexProgramBound && !mClipPlanes.empty())
-				mClipPlanesDirty = true;
-
-			mVertexProgramBound = false;
-			break;
-		case GPT_GEOMETRY_PROGRAM:
-			mGeometryProgramBound = false;
-			break;
-		case GPT_FRAGMENT_PROGRAM:
-			mFragmentProgramBound = false;
-			break;
-		case GPT_DOMAIN_PROGRAM:
-			mDomainProgramBound = false;
-			break;
-		case GPT_HULL_PROGRAM:
-			mHullProgramBound = false;
-			break;
-		case GPT_COMPUTE_PROGRAM:
-			mComputeProgramBound = false;
-			break;
-		}
-	}
-
-	bool RenderAPICore::isGpuProgramBound(GpuProgramType gptype)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-	    switch(gptype)
-	    {
-        case GPT_VERTEX_PROGRAM:
-            return mVertexProgramBound;
-        case GPT_GEOMETRY_PROGRAM:
-            return mGeometryProgramBound;
-        case GPT_FRAGMENT_PROGRAM:
-            return mFragmentProgramBound;
-		case GPT_DOMAIN_PROGRAM:
-			return mDomainProgramBound;
-		case GPT_HULL_PROGRAM:
-			return mHullProgramBound;
-		case GPT_COMPUTE_PROGRAM:
-			return mComputeProgramBound;
-	    }
-
-        return false;
-	}
-
-	void RenderAPICore::setGpuParams(GpuProgramType gptype, const SPtr<GpuParamsCore>& params)
-	{
-		const GpuParamDesc& paramDesc = params->getParamDesc();
-
-		for (auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
-		{
-			SPtr<SamplerStateCore> samplerState = params->getSamplerState(iter->second.slot);
-
-			if (samplerState == nullptr)
-				setSamplerState(gptype, iter->second.slot, SamplerStateCore::getDefault());
-			else
-				setSamplerState(gptype, iter->second.slot, samplerState);
-		}
-
-		for (auto iter = paramDesc.textures.begin(); iter != paramDesc.textures.end(); ++iter)
-		{
-			SPtr<TextureCore> texture = params->getTexture(iter->second.slot);
-
-			if (!params->isLoadStoreTexture(iter->second.slot))
-			{
-				if (texture == nullptr)
-					setTexture(gptype, iter->second.slot, false, nullptr);
-				else
-					setTexture(gptype, iter->second.slot, true, texture);
-			}
-			else
-			{
-				const TextureSurface& surface = params->getLoadStoreSurface(iter->second.slot);
-
-				if (texture == nullptr)
-					setLoadStoreTexture(gptype, iter->second.slot, false, nullptr, surface);
-				else
-					setLoadStoreTexture(gptype, iter->second.slot, true, texture, surface);
-			}
-		}
-
-		setConstantBuffers(gptype, params);
-	}
-
-	void RenderAPICore::swapBuffers(const SPtr<RenderTargetCore>& target)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		target->swapBuffers();
-
-		BS_INC_RENDER_STAT(NumPresents);
-	}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsRenderAPI.h"
+
+#include "BsCoreThread.h"
+#include "BsViewport.h"
+#include "BsRenderTarget.h"
+#include "BsRenderWindow.h"
+#include "BsResource.h"
+#include "BsMesh.h"
+#include "BsRenderStats.h"
+#include "BsGpuParams.h"
+#include "BsBlendState.h"
+#include "BsDepthStencilState.h"
+#include "BsRasterizerState.h"
+#include "BsGpuParamDesc.h"
+
+using namespace std::placeholders;
+
+namespace BansheeEngine 
+{
+	void RenderAPI::disableTextureUnit(CoreAccessor& accessor, GpuProgramType gptype, UINT16 texUnit)
+	{
+		accessor.queueCommand(std::bind(&RenderAPICore::disableTextureUnit, RenderAPICore::instancePtr(), gptype, texUnit));
+	}
+
+	void RenderAPI::setTexture(CoreAccessor& accessor, GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr &texPtr)
+	{
+		accessor.queueCommand(std::bind(&RenderAPICore::setTexture, RenderAPICore::instancePtr(), gptype, unit, enabled, texPtr->getCore()));
+	}
+
+	void RenderAPI::setLoadStoreTexture(CoreAccessor& accessor, GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr& texPtr,
+		const TextureSurface& surface)
+	{
+		accessor.queueCommand(std::bind(&RenderAPICore::setLoadStoreTexture, RenderAPICore::instancePtr(), gptype, unit, enabled, texPtr->getCore(),
+			surface));
+	}
+
+	void RenderAPI::setSamplerState(CoreAccessor& accessor, GpuProgramType gptype, UINT16 texUnit, const SamplerStatePtr& samplerState)
+	{
+		accessor.queueCommand(std::bind(&RenderAPICore::setSamplerState, RenderAPICore::instancePtr(), gptype, texUnit, samplerState->getCore()));
+	}
+
+	void RenderAPI::setBlendState(CoreAccessor& accessor, const BlendStatePtr& blendState)
+	{
+		accessor.queueCommand(std::bind(&RenderAPICore::setBlendState, RenderAPICore::instancePtr(), blendState->getCore()));
+	}
+
+	void RenderAPI::setRasterizerState(CoreAccessor& accessor, const RasterizerStatePtr& rasterizerState)
+	{
+		accessor.queueCommand(std::bind(&RenderAPICore::setRasterizerState, RenderAPICore::instancePtr(), rasterizerState->getCore()));
+	}
+
+	void RenderAPI::setDepthStencilState(CoreAccessor& accessor, const DepthStencilStatePtr& depthStencilState, UINT32 stencilRefValue)
+	{
+		accessor.queueCommand(std::bind(&RenderAPICore::setDepthStencilState, RenderAPICore::instancePtr(), depthStencilState->getCore(), stencilRefValue));
+	}
+
+	void RenderAPI::setVertexBuffers(CoreAccessor& accessor, UINT32 index, const Vector<VertexBufferPtr>& buffers)
+	{
+		Vector<SPtr<VertexBufferCore>> coreBuffers(buffers.size());
+		for (UINT32 i = 0; i < (UINT32)buffers.size(); i++)
+			coreBuffers[i] = buffers[i] != nullptr ? buffers[i]->getCore() : nullptr;
+
+		std::function<void(RenderAPICore*, UINT32, const Vector<SPtr<VertexBufferCore>>&)> resizeFunc =
+			[](RenderAPICore* rs, UINT32 idx, const Vector<SPtr<VertexBufferCore>>& _buffers)
+		{
+			rs->setVertexBuffers(idx, (SPtr<VertexBufferCore>*)_buffers.data(), (UINT32)_buffers.size());
+		};
+
+		accessor.queueCommand(std::bind(resizeFunc, RenderAPICore::instancePtr(), index, coreBuffers));
+	}
+
+	void RenderAPI::setIndexBuffer(CoreAccessor& accessor, const IndexBufferPtr& buffer)
+	{
+		accessor.queueCommand(std::bind(&RenderAPICore::setIndexBuffer, RenderAPICore::instancePtr(), buffer->getCore()));
+	}
+
+	void RenderAPI::setVertexDeclaration(CoreAccessor& accessor, const VertexDeclarationPtr& vertexDeclaration)
+	{
+		accessor.queueCommand(std::bind(&RenderAPICore::setVertexDeclaration, RenderAPICore::instancePtr(), vertexDeclaration->getCore()));
+	}
+
+	void RenderAPI::setViewport(CoreAccessor& accessor, const Rect2& vp)
+	{
+		accessor.queueCommand(std::bind(&RenderAPICore::setViewport, RenderAPICore::instancePtr(), vp));
+	}
+
+	void RenderAPI::setDrawOperation(CoreAccessor& accessor, DrawOperationType op)
+	{
+		accessor.queueCommand(std::bind(&RenderAPICore::setDrawOperation, RenderAPICore::instancePtr(), op));
+	}
+
+	void RenderAPI::setClipPlanes(CoreAccessor& accessor, const PlaneList& clipPlanes)
+	{
+		accessor.queueCommand(std::bind(&RenderAPICore::setClipPlanes, RenderAPICore::instancePtr(), clipPlanes));
+	}
+
+	void RenderAPI::addClipPlane(CoreAccessor& accessor, const Plane& p)
+	{
+		accessor.queueCommand(std::bind(&RenderAPICore::addClipPlane, RenderAPICore::instancePtr(), p));
+	}
+
+	void RenderAPI::resetClipPlanes(CoreAccessor& accessor)
+	{
+		accessor.queueCommand(std::bind(&RenderAPICore::resetClipPlanes, RenderAPICore::instancePtr()));
+	}
+
+	void RenderAPI::setScissorTest(CoreAccessor& accessor, UINT32 left, UINT32 top, UINT32 right, UINT32 bottom)
+	{
+		accessor.queueCommand(std::bind(&RenderAPICore::setScissorRect, RenderAPICore::instancePtr(), left, top, right, bottom));
+	}
+
+	void RenderAPI::setRenderTarget(CoreAccessor& accessor, const RenderTargetPtr& target, bool readOnlyDepthStencil)
+	{
+		accessor.queueCommand(std::bind(&RenderAPICore::setRenderTarget, 
+			RenderAPICore::instancePtr(), target->getCore(), readOnlyDepthStencil));
+	}
+
+	void RenderAPI::bindGpuProgram(CoreAccessor& accessor, const GpuProgramPtr& prg)
+	{
+		prg->syncToCore(accessor);
+		accessor.queueCommand(std::bind(&RenderAPICore::bindGpuProgram, RenderAPICore::instancePtr(), prg->getCore()));
+	}
+
+	void RenderAPI::unbindGpuProgram(CoreAccessor& accessor, GpuProgramType gptype)
+	{
+		accessor.queueCommand(std::bind(&RenderAPICore::unbindGpuProgram, RenderAPICore::instancePtr(), gptype));
+	}
+
+	void RenderAPI::setConstantBuffers(CoreAccessor& accessor, GpuProgramType gptype, const GpuParamsPtr& params)
+	{
+		accessor.queueCommand(std::bind(&RenderAPICore::setConstantBuffers, RenderAPICore::instancePtr(), gptype, params->getCore()));
+	}
+
+	void RenderAPI::setGpuParams(CoreAccessor& accessor, GpuProgramType gptype, const GpuParamsPtr& params)
+	{
+		accessor.queueCommand(std::bind(&RenderAPICore::setGpuParams, RenderAPICore::instancePtr(), gptype, params->getCore()));
+	}
+
+	void RenderAPI::beginRender(CoreAccessor& accessor)
+	{
+		accessor.queueCommand(std::bind(&RenderAPICore::beginFrame, RenderAPICore::instancePtr()));
+	}
+
+	void RenderAPI::endRender(CoreAccessor& accessor)
+	{
+		accessor.queueCommand(std::bind(&RenderAPICore::endFrame, RenderAPICore::instancePtr()));
+	}
+
+	void RenderAPI::clearRenderTarget(CoreAccessor& accessor, UINT32 buffers, const Color& color, float depth, UINT16 stencil, UINT8 targetMask)
+	{
+		accessor.queueCommand(std::bind(&RenderAPICore::clearRenderTarget, RenderAPICore::instancePtr(), buffers, color,
+			depth, stencil, targetMask));
+	}
+
+	void RenderAPI::clearViewport(CoreAccessor& accessor, UINT32 buffers, const Color& color, float depth, UINT16 stencil, UINT8 targetMask)
+	{
+		accessor.queueCommand(std::bind(&RenderAPICore::clearViewport, RenderAPICore::instancePtr(), buffers, color, depth,
+			stencil, targetMask));
+	}
+
+	void RenderAPI::swapBuffers(CoreAccessor& accessor, const RenderTargetPtr& target)
+	{
+		accessor.queueCommand(std::bind(&RenderAPICore::swapBuffers, RenderAPICore::instancePtr(), target->getCore()));
+	}
+
+	void RenderAPI::draw(CoreAccessor& accessor, UINT32 vertexOffset, UINT32 vertexCount)
+	{
+		accessor.queueCommand(std::bind(&RenderAPICore::draw, RenderAPICore::instancePtr(), vertexOffset, vertexCount));
+	}
+
+	void RenderAPI::drawIndexed(CoreAccessor& accessor, UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount)
+	{
+		accessor.queueCommand(std::bind(&RenderAPICore::drawIndexed, RenderAPICore::instancePtr(), startIndex, indexCount, 
+			vertexOffset, vertexCount));
+	}
+
+	void RenderAPI::dispatchCompute(CoreAccessor& accessor, UINT32 numGroupsX, UINT32 numGroupsY, UINT32 numGroupsZ)
+	{
+		accessor.queueCommand(std::bind(&RenderAPICore::dispatchCompute, RenderAPICore::instancePtr(), numGroupsX, 
+			numGroupsY, numGroupsZ));
+	}
+
+	const VideoModeInfo& RenderAPI::getVideoModeInfo()
+	{
+		return RenderAPICore::instance().getVideoModeInfo();
+	}
+
+	void RenderAPI::convertProjectionMatrix(const Matrix4& matrix, Matrix4& dest)
+	{
+		RenderAPICore::instance().convertProjectionMatrix(matrix, dest);
+	}
+
+	const RenderAPIInfo& RenderAPI::getAPIInfo()
+	{
+		return RenderAPICore::instance().getAPIInfo();
+	}
+
+    RenderAPICore::RenderAPICore()
+        : mCullingMode(CULL_COUNTERCLOCKWISE)
+        , mDisabledTexUnitsFrom(0)
+        , mVertexProgramBound(false)
+		, mGeometryProgramBound(false)
+        , mFragmentProgramBound(false)
+		, mDomainProgramBound(false)
+		, mHullProgramBound(false)
+		, mComputeProgramBound(false)
+		, mClipPlanesDirty(true)
+		, mCurrentCapabilities(nullptr)
+    {
+    }
+
+    RenderAPICore::~RenderAPICore()
+    {
+		// Base classes need to call virtual destroy_internal method instead of a destructor
+
+		bs_delete(mCurrentCapabilities);
+		mCurrentCapabilities = nullptr;
+    }
+
+	RenderWindowPtr RenderAPICore::initialize(const RENDER_WINDOW_DESC& primaryWindowDesc)
+	{
+		gCoreThread().queueCommand(std::bind(&RenderAPICore::initializePrepare, this), true);
+
+		RENDER_WINDOW_DESC windowDesc = primaryWindowDesc;
+		RenderWindowPtr renderWindow = RenderWindow::create(windowDesc, nullptr);
+
+		gCoreThread().queueCommand(std::bind(&RenderAPICore::initializeFinalize, this, renderWindow->getCore()), true);
+
+		return renderWindow;
+	}
+
+	void RenderAPICore::initializePrepare()
+	{
+		// Do nothing
+	}
+
+	void RenderAPICore::initializeFinalize(const SPtr<RenderWindowCore>& primaryWindow)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		mVertexProgramBound = false;
+		mGeometryProgramBound = false;
+		mFragmentProgramBound = false;
+		mDomainProgramBound = false;
+		mHullProgramBound = false;
+		mComputeProgramBound = false;
+	}
+
+	void RenderAPICore::destroy()
+	{
+		gCoreAccessor().queueCommand(std::bind(&RenderAPICore::destroyCore, this));
+		gCoreThread().submitAccessors(true);
+	}
+
+	void RenderAPICore::destroyCore()
+	{
+		mActiveRenderTarget = nullptr;
+	}
+
+	const RenderAPICapabilities* RenderAPICore::getCapabilities(void) const 
+	{ 
+		return mCurrentCapabilities; 
+	}
+
+	const DriverVersion& RenderAPICore::getDriverVersion(void) const 
+	{ 
+		THROW_IF_NOT_CORE_THREAD;
+
+		return mDriverVersion; 
+	}
+
+    void RenderAPICore::disableTextureUnit(GpuProgramType gptype, UINT16 texUnit)
+    {
+		THROW_IF_NOT_CORE_THREAD;
+
+		setTexture(gptype, texUnit, false, SPtr<TextureCore>());
+    }
+
+	void RenderAPICore::addClipPlane(const Plane &p)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		mClipPlanes.push_back(p);
+		mClipPlanesDirty = true;
+	}
+
+	void RenderAPICore::setClipPlanes(const PlaneList& clipPlanes)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		if (clipPlanes != mClipPlanes)
+		{
+			mClipPlanes = clipPlanes;
+			mClipPlanesDirty = true;
+		}
+	}
+
+	void RenderAPICore::resetClipPlanes()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		if (!mClipPlanes.empty())
+		{
+			mClipPlanes.clear();
+			mClipPlanesDirty = true;
+		}
+	}
+
+	void RenderAPICore::bindGpuProgram(const SPtr<GpuProgramCore>& prg)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		switch(prg->getProperties().getType())
+		{
+		case GPT_VERTEX_PROGRAM:
+			if (!mVertexProgramBound && !mClipPlanes.empty())
+				mClipPlanesDirty = true;
+
+			mVertexProgramBound = true;
+			break;
+		case GPT_GEOMETRY_PROGRAM:
+			mGeometryProgramBound = true;
+			break;
+		case GPT_FRAGMENT_PROGRAM:
+			mFragmentProgramBound = true;
+			break;
+		case GPT_DOMAIN_PROGRAM:
+			mDomainProgramBound = true;
+			break;
+		case GPT_HULL_PROGRAM:
+			mHullProgramBound = true;
+			break;
+		case GPT_COMPUTE_PROGRAM:
+			mComputeProgramBound = true;
+			break;
+		}
+	}
+
+	void RenderAPICore::unbindGpuProgram(GpuProgramType gptype)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		switch(gptype)
+		{
+		case GPT_VERTEX_PROGRAM:
+			if (mVertexProgramBound && !mClipPlanes.empty())
+				mClipPlanesDirty = true;
+
+			mVertexProgramBound = false;
+			break;
+		case GPT_GEOMETRY_PROGRAM:
+			mGeometryProgramBound = false;
+			break;
+		case GPT_FRAGMENT_PROGRAM:
+			mFragmentProgramBound = false;
+			break;
+		case GPT_DOMAIN_PROGRAM:
+			mDomainProgramBound = false;
+			break;
+		case GPT_HULL_PROGRAM:
+			mHullProgramBound = false;
+			break;
+		case GPT_COMPUTE_PROGRAM:
+			mComputeProgramBound = false;
+			break;
+		}
+	}
+
+	bool RenderAPICore::isGpuProgramBound(GpuProgramType gptype)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+	    switch(gptype)
+	    {
+        case GPT_VERTEX_PROGRAM:
+            return mVertexProgramBound;
+        case GPT_GEOMETRY_PROGRAM:
+            return mGeometryProgramBound;
+        case GPT_FRAGMENT_PROGRAM:
+            return mFragmentProgramBound;
+		case GPT_DOMAIN_PROGRAM:
+			return mDomainProgramBound;
+		case GPT_HULL_PROGRAM:
+			return mHullProgramBound;
+		case GPT_COMPUTE_PROGRAM:
+			return mComputeProgramBound;
+	    }
+
+        return false;
+	}
+
+	void RenderAPICore::setGpuParams(GpuProgramType gptype, const SPtr<GpuParamsCore>& params)
+	{
+		const GpuParamDesc& paramDesc = params->getParamDesc();
+
+		for (auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
+		{
+			SPtr<SamplerStateCore> samplerState = params->getSamplerState(iter->second.slot);
+
+			if (samplerState == nullptr)
+				setSamplerState(gptype, iter->second.slot, SamplerStateCore::getDefault());
+			else
+				setSamplerState(gptype, iter->second.slot, samplerState);
+		}
+
+		for (auto iter = paramDesc.textures.begin(); iter != paramDesc.textures.end(); ++iter)
+		{
+			SPtr<TextureCore> texture = params->getTexture(iter->second.slot);
+
+			if (!params->isLoadStoreTexture(iter->second.slot))
+			{
+				if (texture == nullptr)
+					setTexture(gptype, iter->second.slot, false, nullptr);
+				else
+					setTexture(gptype, iter->second.slot, true, texture);
+			}
+			else
+			{
+				const TextureSurface& surface = params->getLoadStoreSurface(iter->second.slot);
+
+				if (texture == nullptr)
+					setLoadStoreTexture(gptype, iter->second.slot, false, nullptr, surface);
+				else
+					setLoadStoreTexture(gptype, iter->second.slot, true, texture, surface);
+			}
+		}
+
+		setConstantBuffers(gptype, params);
+	}
+
+	void RenderAPICore::swapBuffers(const SPtr<RenderTargetCore>& target)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		target->swapBuffers();
+
+		BS_INC_RENDER_STAT(NumPresents);
+	}
 }

+ 339 - 340
Source/BansheeCore/Source/BsVertexDeclaration.cpp

@@ -1,341 +1,340 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsVertexDeclaration.h"
-#include "BsVertexDeclarationRTTI.h"
-#include "BsHardwareBufferManager.h"
-#include "BsRenderAPI.h"
-
-namespace BansheeEngine
-{
-	VertexElement::VertexElement(UINT16 source, UINT32 offset,
-		VertexElementType theType, VertexElementSemantic semantic, UINT16 index)
-		: mSource(source), mOffset(offset), mType(theType), mSemantic(semantic), mIndex(index)
-	{
-	}
-
-	UINT32 VertexElement::getSize(void) const
-	{
-		return getTypeSize(mType);
-	}
-
-	UINT32 VertexElement::getTypeSize(VertexElementType etype)
-	{
-		switch(etype)
-		{
-		case VET_COLOR:
-		case VET_COLOR_ABGR:
-		case VET_COLOR_ARGB:
-			return sizeof(RGBA);
-		case VET_FLOAT1:
-			return sizeof(float);
-		case VET_FLOAT2:
-			return sizeof(float)*2;
-		case VET_FLOAT3:
-			return sizeof(float)*3;
-		case VET_FLOAT4:
-			return sizeof(float)*4;
-		case VET_SHORT1:
-			return sizeof(short);
-		case VET_SHORT2:
-			return sizeof(short)*2;
-		case VET_SHORT3:
-			return sizeof(short)*3;
-		case VET_SHORT4:
-			return sizeof(short)*4;
-		case VET_UBYTE4:
-			return sizeof(unsigned char)*4;
-		}
-
-		return 0;
-	}
-
-	unsigned short VertexElement::getTypeCount(VertexElementType etype)
-	{
-		switch (etype)
-		{
-		case VET_COLOR:
-		case VET_COLOR_ABGR:
-		case VET_COLOR_ARGB:
-			return 4;
-		case VET_FLOAT1:
-			return 1;
-		case VET_FLOAT2:
-			return 2;
-		case VET_FLOAT3:
-			return 3;
-		case VET_FLOAT4:
-			return 4;
-		case VET_SHORT1:
-			return 1;
-		case VET_SHORT2:
-			return 2;
-		case VET_SHORT3:
-			return 3;
-		case VET_SHORT4:
-			return 4;
-		case VET_UBYTE4:
-			return 4;
-		}
-
-		BS_EXCEPT(InvalidParametersException, "Invalid type");
-		return 0;
-	}
-
-	VertexElementType VertexElement::getBestColorVertexElementType()
-	{
-		// Use the current render system to determine if possible
-		if (BansheeEngine::RenderAPICore::instancePtr())
-		{
-			return BansheeEngine::RenderAPICore::instancePtr()->getColorVertexElementType();
-		}
-		else
-		{
-			// We can't know the specific type right now, so pick a type
-			// based on platform
-#if BS_PLATFORM == BS_PLATFORM_WIN32
-			return VET_COLOR_ARGB; // prefer D3D format on windows
-#else
-			return VET_COLOR_ABGR; // prefer GL format on everything else
-#endif
-
-		}
-	}
-
-	bool VertexElement::operator== (const VertexElement& rhs) const
-	{
-		if (mType != rhs.mType || mIndex != rhs.mIndex || mOffset != rhs.mOffset ||
-			mSemantic != rhs.mSemantic || mSource != rhs.mSource)
-		{
-			return false;
-		}
-		else
-			return true;
-	}
-
-	bool VertexElement::operator!= (const VertexElement& rhs) const
-	{
-		return !(*this == rhs);
-	}
-
-	VertexDeclarationProperties::VertexDeclarationProperties(const List<VertexElement>& elements)
-	{
-		for (auto& elem : elements)
-		{
-			VertexElementType type = elem.getType();
-
-			if (elem.getType() == VET_COLOR)
-				type = VertexElement::getBestColorVertexElementType();
-
-			mElementList.push_back(VertexElement(elem.getStreamIdx(), elem.getOffset(), type, elem.getSemantic(), elem.getSemanticIdx()));
-		}
-	}
-
-	bool VertexDeclarationProperties::operator== (const VertexDeclarationProperties& rhs) const
-	{
-		if (mElementList.size() != rhs.mElementList.size())
-			return false;
-
-		auto myIter = mElementList.begin();
-		auto theirIter = rhs.mElementList.begin();
-
-		for (; myIter != mElementList.end() && theirIter != rhs.mElementList.end(); ++myIter, ++theirIter)
-		{
-			if (!(*myIter == *theirIter))
-				return false;
-		}
-
-		return true;
-	}
-
-	bool VertexDeclarationProperties::operator!= (const VertexDeclarationProperties& rhs) const
-	{
-		return !(*this == rhs);
-	}
-
-	const VertexElement* VertexDeclarationProperties::getElement(UINT16 index) const
-	{
-		assert(index < mElementList.size() && "Index out of bounds");
-
-		auto iter = mElementList.begin();
-		for (UINT16 i = 0; i < index; ++i)
-			++iter;
-
-		return &(*iter);
-
-	}
-	
-	const VertexElement* VertexDeclarationProperties::findElementBySemantic(VertexElementSemantic sem, UINT16 index) const
-	{
-		for (auto& elem : mElementList)
-		{
-			if (elem.getSemantic() == sem && elem.getSemanticIdx() == index)
-			{
-				return &elem;
-			}
-		}
-
-		return nullptr;
-	}
-
-	List<VertexElement> VertexDeclarationProperties::findElementsBySource(UINT16 source) const
-	{
-		List<VertexElement> retList;
-
-		for (auto& elem : mElementList)
-		{
-			if (elem.getStreamIdx() == source)
-			{
-				retList.push_back(elem);
-			}
-		}
-
-		return retList;
-	}
-
-	UINT32 VertexDeclarationProperties::getVertexSize(UINT16 source) const
-	{
-		UINT32 size = 0;
-
-		for (auto& elem : mElementList)
-		{
-			if (elem.getStreamIdx() == source)
-			{
-				size += elem.getSize();
-			}
-		}
-
-		return size;
-	}
-
-	UINT32 VertexDeclarationCore::NextFreeId = 0;
-
-	VertexDeclarationCore::VertexDeclarationCore(const List<VertexElement>& elements)
-		:mProperties(elements)
-	{
-		
-	}
-
-	void VertexDeclarationCore::initialize()
-	{
-		mId = NextFreeId++;
-		CoreObjectCore::initialize();
-	}
-
-	bool VertexDeclarationCore::isCompatible(const SPtr<VertexDeclarationCore>& shaderDecl)
-	{
-		const List<VertexElement>& shaderElems = shaderDecl->getProperties().getElements();
-		const List<VertexElement>& bufferElems = getProperties().getElements();
-
-		for (auto shaderIter = shaderElems.begin(); shaderIter != shaderElems.end(); ++shaderIter)
-		{
-			const VertexElement* foundElement = nullptr;
-			for (auto bufferIter = bufferElems.begin(); bufferIter != bufferElems.end(); ++bufferIter)
-			{
-				if (shaderIter->getSemantic() == bufferIter->getSemantic() && shaderIter->getSemanticIdx() == bufferIter->getSemanticIdx())
-				{
-					foundElement = &(*bufferIter);
-					break;
-				}
-			}
-
-			if (foundElement == nullptr)
-				return false;
-		}
-
-		return true;
-	}
-
-	Vector<VertexElement> VertexDeclarationCore::getMissingElements(const SPtr<VertexDeclarationCore>& shaderDecl)
-	{
-		Vector<VertexElement> missingElements;
-
-		const List<VertexElement>& shaderElems = shaderDecl->getProperties().getElements();
-		const List<VertexElement>& bufferElems = getProperties().getElements();
-
-		for (auto shaderIter = shaderElems.begin(); shaderIter != shaderElems.end(); ++shaderIter)
-		{
-			const VertexElement* foundElement = nullptr;
-			for (auto bufferIter = bufferElems.begin(); bufferIter != bufferElems.end(); ++bufferIter)
-			{
-				if (shaderIter->getSemantic() == bufferIter->getSemantic() && shaderIter->getSemanticIdx() == bufferIter->getSemanticIdx())
-				{
-					foundElement = &(*bufferIter);
-					break;
-				}
-			}
-
-			if (foundElement == nullptr)
-				missingElements.push_back(*shaderIter);
-		}
-
-		return missingElements;
-	}
-
-	VertexDeclaration::VertexDeclaration(const List<VertexElement>& elements)
-		:mProperties(elements)
-	{
-
-	}
-
-	SPtr<VertexDeclarationCore> VertexDeclaration::getCore() const
-	{
-		return std::static_pointer_cast<VertexDeclarationCore>(mCoreSpecific);
-	}
-
-	SPtr<CoreObjectCore> VertexDeclaration::createCore() const
-	{
-		return HardwareBufferCoreManager::instance().createVertexDeclarationInternal(mProperties.mElementList);
-	}
-
-	VertexDeclarationPtr VertexDeclaration::createVertexDeclaration(const List<VertexElement>& elements)
-	{
-		return HardwareBufferManager::instance().createVertexDeclaration(elements);
-	}
-
-	/************************************************************************/
-	/* 								SERIALIZATION                      		*/
-	/************************************************************************/
-	RTTITypeBase* VertexDeclaration::getRTTIStatic()
-	{
-		return VertexDeclarationRTTI::instance();
-	}
-
-	RTTITypeBase* VertexDeclaration::getRTTI() const
-	{
-		return getRTTIStatic();
-	}
-
-	String toString(const VertexElementSemantic& val)
-	{
-		switch (val)
-		{
-		case VES_POSITION:
-			return "POSITION";
-		case VES_BLEND_WEIGHTS:
-			return "BLEND_WEIGHTS";
-		case VES_BLEND_INDICES:
-			return "BLEND_INDICES";
-		case VES_NORMAL:
-			return "NORMAL";
-		case VES_COLOR:
-			return "COLOR";
-		case VES_TEXCOORD:
-			return "TEXCOORD";
-		case VES_BITANGENT:
-			return "BITANGENT";
-		case VES_TANGENT:
-			return "TANGENT";
-		case VES_POSITIONT:
-			return "POSITIONT";
-		case VES_PSIZE:
-			return "PSIZE";
-		}
-
-		return "";
-	}
-
-	WString toWString(const VertexElementSemantic& val)
-	{
-		return toWString(toString(val));
-	}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsVertexDeclaration.h"
+#include "BsVertexDeclarationRTTI.h"
+#include "BsHardwareBufferManager.h"
+#include "BsRenderAPI.h"
+
+namespace BansheeEngine
+{
+	VertexElement::VertexElement(UINT16 source, UINT32 offset,
+		VertexElementType theType, VertexElementSemantic semantic, UINT16 index)
+		: mSource(source), mOffset(offset), mType(theType), mSemantic(semantic), mIndex(index)
+	{
+	}
+
+	UINT32 VertexElement::getSize(void) const
+	{
+		return getTypeSize(mType);
+	}
+
+	UINT32 VertexElement::getTypeSize(VertexElementType etype)
+	{
+		switch(etype)
+		{
+		case VET_COLOR:
+		case VET_COLOR_ABGR:
+		case VET_COLOR_ARGB:
+			return sizeof(RGBA);
+		case VET_FLOAT1:
+			return sizeof(float);
+		case VET_FLOAT2:
+			return sizeof(float)*2;
+		case VET_FLOAT3:
+			return sizeof(float)*3;
+		case VET_FLOAT4:
+			return sizeof(float)*4;
+		case VET_SHORT1:
+			return sizeof(short);
+		case VET_SHORT2:
+			return sizeof(short)*2;
+		case VET_SHORT3:
+			return sizeof(short)*3;
+		case VET_SHORT4:
+			return sizeof(short)*4;
+		case VET_UBYTE4:
+			return sizeof(unsigned char)*4;
+		}
+
+		return 0;
+	}
+
+	unsigned short VertexElement::getTypeCount(VertexElementType etype)
+	{
+		switch (etype)
+		{
+		case VET_COLOR:
+		case VET_COLOR_ABGR:
+		case VET_COLOR_ARGB:
+			return 4;
+		case VET_FLOAT1:
+			return 1;
+		case VET_FLOAT2:
+			return 2;
+		case VET_FLOAT3:
+			return 3;
+		case VET_FLOAT4:
+			return 4;
+		case VET_SHORT1:
+			return 1;
+		case VET_SHORT2:
+			return 2;
+		case VET_SHORT3:
+			return 3;
+		case VET_SHORT4:
+			return 4;
+		case VET_UBYTE4:
+			return 4;
+		}
+
+		BS_EXCEPT(InvalidParametersException, "Invalid type");
+		return 0;
+	}
+
+	VertexElementType VertexElement::getBestColorVertexElementType()
+	{
+		// Use the current render system to determine if possible
+		if (RenderAPICore::instancePtr() != nullptr)
+		{
+			return RenderAPICore::instance().getAPIInfo().getColorVertexElementType();
+		}
+		else
+		{
+			// We can't know the specific type right now, so pick a type based on platform
+#if BS_PLATFORM == BS_PLATFORM_WIN32
+			return VET_COLOR_ARGB; // prefer D3D format on Windows
+#else
+			return VET_COLOR_ABGR; // prefer GL format on everything else
+#endif
+
+		}
+	}
+
+	bool VertexElement::operator== (const VertexElement& rhs) const
+	{
+		if (mType != rhs.mType || mIndex != rhs.mIndex || mOffset != rhs.mOffset ||
+			mSemantic != rhs.mSemantic || mSource != rhs.mSource)
+		{
+			return false;
+		}
+		else
+			return true;
+	}
+
+	bool VertexElement::operator!= (const VertexElement& rhs) const
+	{
+		return !(*this == rhs);
+	}
+
+	VertexDeclarationProperties::VertexDeclarationProperties(const List<VertexElement>& elements)
+	{
+		for (auto& elem : elements)
+		{
+			VertexElementType type = elem.getType();
+
+			if (elem.getType() == VET_COLOR)
+				type = VertexElement::getBestColorVertexElementType();
+
+			mElementList.push_back(VertexElement(elem.getStreamIdx(), elem.getOffset(), type, elem.getSemantic(), elem.getSemanticIdx()));
+		}
+	}
+
+	bool VertexDeclarationProperties::operator== (const VertexDeclarationProperties& rhs) const
+	{
+		if (mElementList.size() != rhs.mElementList.size())
+			return false;
+
+		auto myIter = mElementList.begin();
+		auto theirIter = rhs.mElementList.begin();
+
+		for (; myIter != mElementList.end() && theirIter != rhs.mElementList.end(); ++myIter, ++theirIter)
+		{
+			if (!(*myIter == *theirIter))
+				return false;
+		}
+
+		return true;
+	}
+
+	bool VertexDeclarationProperties::operator!= (const VertexDeclarationProperties& rhs) const
+	{
+		return !(*this == rhs);
+	}
+
+	const VertexElement* VertexDeclarationProperties::getElement(UINT16 index) const
+	{
+		assert(index < mElementList.size() && "Index out of bounds");
+
+		auto iter = mElementList.begin();
+		for (UINT16 i = 0; i < index; ++i)
+			++iter;
+
+		return &(*iter);
+
+	}
+	
+	const VertexElement* VertexDeclarationProperties::findElementBySemantic(VertexElementSemantic sem, UINT16 index) const
+	{
+		for (auto& elem : mElementList)
+		{
+			if (elem.getSemantic() == sem && elem.getSemanticIdx() == index)
+			{
+				return &elem;
+			}
+		}
+
+		return nullptr;
+	}
+
+	List<VertexElement> VertexDeclarationProperties::findElementsBySource(UINT16 source) const
+	{
+		List<VertexElement> retList;
+
+		for (auto& elem : mElementList)
+		{
+			if (elem.getStreamIdx() == source)
+			{
+				retList.push_back(elem);
+			}
+		}
+
+		return retList;
+	}
+
+	UINT32 VertexDeclarationProperties::getVertexSize(UINT16 source) const
+	{
+		UINT32 size = 0;
+
+		for (auto& elem : mElementList)
+		{
+			if (elem.getStreamIdx() == source)
+			{
+				size += elem.getSize();
+			}
+		}
+
+		return size;
+	}
+
+	UINT32 VertexDeclarationCore::NextFreeId = 0;
+
+	VertexDeclarationCore::VertexDeclarationCore(const List<VertexElement>& elements)
+		:mProperties(elements)
+	{
+		
+	}
+
+	void VertexDeclarationCore::initialize()
+	{
+		mId = NextFreeId++;
+		CoreObjectCore::initialize();
+	}
+
+	bool VertexDeclarationCore::isCompatible(const SPtr<VertexDeclarationCore>& shaderDecl)
+	{
+		const List<VertexElement>& shaderElems = shaderDecl->getProperties().getElements();
+		const List<VertexElement>& bufferElems = getProperties().getElements();
+
+		for (auto shaderIter = shaderElems.begin(); shaderIter != shaderElems.end(); ++shaderIter)
+		{
+			const VertexElement* foundElement = nullptr;
+			for (auto bufferIter = bufferElems.begin(); bufferIter != bufferElems.end(); ++bufferIter)
+			{
+				if (shaderIter->getSemantic() == bufferIter->getSemantic() && shaderIter->getSemanticIdx() == bufferIter->getSemanticIdx())
+				{
+					foundElement = &(*bufferIter);
+					break;
+				}
+			}
+
+			if (foundElement == nullptr)
+				return false;
+		}
+
+		return true;
+	}
+
+	Vector<VertexElement> VertexDeclarationCore::getMissingElements(const SPtr<VertexDeclarationCore>& shaderDecl)
+	{
+		Vector<VertexElement> missingElements;
+
+		const List<VertexElement>& shaderElems = shaderDecl->getProperties().getElements();
+		const List<VertexElement>& bufferElems = getProperties().getElements();
+
+		for (auto shaderIter = shaderElems.begin(); shaderIter != shaderElems.end(); ++shaderIter)
+		{
+			const VertexElement* foundElement = nullptr;
+			for (auto bufferIter = bufferElems.begin(); bufferIter != bufferElems.end(); ++bufferIter)
+			{
+				if (shaderIter->getSemantic() == bufferIter->getSemantic() && shaderIter->getSemanticIdx() == bufferIter->getSemanticIdx())
+				{
+					foundElement = &(*bufferIter);
+					break;
+				}
+			}
+
+			if (foundElement == nullptr)
+				missingElements.push_back(*shaderIter);
+		}
+
+		return missingElements;
+	}
+
+	VertexDeclaration::VertexDeclaration(const List<VertexElement>& elements)
+		:mProperties(elements)
+	{
+
+	}
+
+	SPtr<VertexDeclarationCore> VertexDeclaration::getCore() const
+	{
+		return std::static_pointer_cast<VertexDeclarationCore>(mCoreSpecific);
+	}
+
+	SPtr<CoreObjectCore> VertexDeclaration::createCore() const
+	{
+		return HardwareBufferCoreManager::instance().createVertexDeclarationInternal(mProperties.mElementList);
+	}
+
+	VertexDeclarationPtr VertexDeclaration::createVertexDeclaration(const List<VertexElement>& elements)
+	{
+		return HardwareBufferManager::instance().createVertexDeclaration(elements);
+	}
+
+	/************************************************************************/
+	/* 								SERIALIZATION                      		*/
+	/************************************************************************/
+	RTTITypeBase* VertexDeclaration::getRTTIStatic()
+	{
+		return VertexDeclarationRTTI::instance();
+	}
+
+	RTTITypeBase* VertexDeclaration::getRTTI() const
+	{
+		return getRTTIStatic();
+	}
+
+	String toString(const VertexElementSemantic& val)
+	{
+		switch (val)
+		{
+		case VES_POSITION:
+			return "POSITION";
+		case VES_BLEND_WEIGHTS:
+			return "BLEND_WEIGHTS";
+		case VES_BLEND_INDICES:
+			return "BLEND_INDICES";
+		case VES_NORMAL:
+			return "NORMAL";
+		case VES_COLOR:
+			return "COLOR";
+		case VES_TEXCOORD:
+			return "TEXCOORD";
+		case VES_BITANGENT:
+			return "BITANGENT";
+		case VES_TANGENT:
+			return "TANGENT";
+		case VES_POSITIONT:
+			return "POSITIONT";
+		case VES_PSIZE:
+			return "PSIZE";
+		}
+
+		return "";
+	}
+
+	WString toWString(const VertexElementSemantic& val)
+	{
+		return toWString(toString(val));
+	}
 }

+ 2 - 14
Source/BansheeD3D11RenderAPI/Include/BsD3D11RenderAPI.h

@@ -105,20 +105,8 @@ namespace BansheeEngine
 		/** @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::getAPIInfo */
+		const RenderAPIInfo& getAPIInfo() const override;
 
 		/** @copydoc RenderAPICore::generateParamBlockDesc() */
 		GpuParamBlockDesc generateParamBlockDesc(const String& name, Vector<GpuParamDataDesc>& params) override;

+ 1144 - 1162
Source/BansheeD3D11RenderAPI/Source/BsD3D11RenderAPI.cpp

@@ -1,1163 +1,1145 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsD3D11RenderAPI.h"
-#include "BsD3D11DriverList.h"
-#include "BsD3D11Driver.h"
-#include "BsD3D11Device.h"
-#include "BsD3D11TextureManager.h"
-#include "BsD3D11Texture.h"
-#include "BsD3D11HardwareBufferManager.h"
-#include "BsD3D11RenderWindowManager.h"
-#include "BsD3D11HLSLProgramFactory.h"
-#include "BsD3D11BlendState.h"
-#include "BsD3D11RasterizerState.h"
-#include "BsD3D11DepthStencilState.h"
-#include "BsD3D11SamplerState.h"
-#include "BsD3D11GpuProgram.h"
-#include "BsD3D11Mappings.h"
-#include "BsD3D11VertexBuffer.h"
-#include "BsD3D11IndexBuffer.h"
-#include "BsD3D11RenderStateManager.h"
-#include "BsD3D11GpuParamBlockBuffer.h"
-#include "BsD3D11InputLayoutManager.h"
-#include "BsD3D11TextureView.h"
-#include "BsD3D11RenderUtility.h"
-#include "BsGpuParams.h"
-#include "BsCoreThread.h"
-#include "BsD3D11QueryManager.h"
-#include "BsDebug.h"
-#include "BsException.h"
-#include "BsRenderStats.h"
-#include "BsGpuParamDesc.h"
-
-namespace BansheeEngine
-{
-	D3D11RenderAPI::D3D11RenderAPI()
-		: mDXGIFactory(nullptr), mDevice(nullptr), mDriverList(nullptr)
-		, mActiveD3DDriver(nullptr), mFeatureLevel(D3D_FEATURE_LEVEL_11_0)
-		, mHLSLFactory(nullptr), mIAManager(nullptr)
-		, mStencilRef(0), mActiveDrawOp(DOT_TRIANGLE_LIST)
-		, mViewportNorm(0.0f, 0.0f, 1.0f, 1.0f)
-	{
-		mClipPlanesDirty = false; // DX11 handles clip planes through shaders
-	}
-
-	D3D11RenderAPI::~D3D11RenderAPI()
-	{
-
-	}
-
-	const StringID& D3D11RenderAPI::getName() const
-	{
-		static StringID strName("D3D11RenderAPI");
-		return strName;
-	}
-
-	const String& D3D11RenderAPI::getShadingLanguageName() const
-	{
-		static String strName("hlsl");
-		return strName;
-	}
-
-	void D3D11RenderAPI::initializePrepare()
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		HRESULT hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&mDXGIFactory);
-		if(FAILED(hr))
-			BS_EXCEPT(RenderingAPIException, "Failed to create Direct3D11 DXGIFactory");
-
-		mDriverList = bs_new<D3D11DriverList>(mDXGIFactory);
-		mActiveD3DDriver = mDriverList->item(0); // TODO: Always get first driver, for now
-		mVideoModeInfo = mActiveD3DDriver->getVideoModeInfo();
-
-		IDXGIAdapter* selectedAdapter = mActiveD3DDriver->getDeviceAdapter();
-
-		D3D_FEATURE_LEVEL requestedLevels[] = {
-			D3D_FEATURE_LEVEL_11_0,
-			D3D_FEATURE_LEVEL_10_1,
-			D3D_FEATURE_LEVEL_10_0,
-			D3D_FEATURE_LEVEL_9_3,
-			D3D_FEATURE_LEVEL_9_2,
-			D3D_FEATURE_LEVEL_9_1
-		};
-
-		UINT32 numRequestedLevel = sizeof(requestedLevels) / sizeof(requestedLevels[0]);
-
-		UINT32 deviceFlags = 0;
-
-#if BS_DEBUG_MODE
-		deviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
-#endif
-
-		ID3D11Device* device;
-		hr = D3D11CreateDevice(selectedAdapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr, deviceFlags, 
-			requestedLevels, numRequestedLevel, D3D11_SDK_VERSION, &device, &mFeatureLevel, nullptr);
-
-		if(FAILED(hr))         
-			BS_EXCEPT(RenderingAPIException, "Failed to create Direct3D11 object. D3D11CreateDeviceN returned this error code: " + toString(hr));
-
-		mDevice = bs_new<D3D11Device>(device);
-		
-		// This must query for DirectX 10 interface as this is unsupported for DX11
-		LARGE_INTEGER driverVersion; 
-		if(SUCCEEDED(selectedAdapter->CheckInterfaceSupport(IID_ID3D10Device, &driverVersion)))
-		{
-			mDriverVersion.major =  HIWORD(driverVersion.HighPart);
-			mDriverVersion.minor = LOWORD(driverVersion.HighPart);
-			mDriverVersion.release = HIWORD(driverVersion.LowPart);
-			mDriverVersion.build = LOWORD(driverVersion.LowPart);
-		}
-
-		// Create the texture manager for use by others		
-		TextureManager::startUp<D3D11TextureManager>();
-		TextureCoreManager::startUp<D3D11TextureCoreManager>();
-
-		// Create hardware buffer manager		
-		HardwareBufferManager::startUp();
-		HardwareBufferCoreManager::startUp<D3D11HardwareBufferCoreManager>(std::ref(*mDevice));
-
-		// Create render window manager
-		RenderWindowManager::startUp<D3D11RenderWindowManager>(this);
-		RenderWindowCoreManager::startUp<D3D11RenderWindowCoreManager>(this);
-
-		// Create & register HLSL factory		
-		mHLSLFactory = bs_new<D3D11HLSLProgramFactory>();
-
-		// Create render state manager
-		RenderStateCoreManager::startUp<D3D11RenderStateCoreManager>();
-
-		mCurrentCapabilities = createRenderSystemCapabilities();
-
-		mCurrentCapabilities->addShaderProfile("hlsl");
-		GpuProgramCoreManager::instance().addFactory(mHLSLFactory);
-
-		mIAManager = bs_new<D3D11InputLayoutManager>();
-
-		RenderAPICore::initializePrepare();
-	}
-
-	void D3D11RenderAPI::initializeFinalize(const SPtr<RenderWindowCore>& primaryWindow)
-	{
-		D3D11RenderUtility::startUp(mDevice);
-
-		QueryManager::startUp<D3D11QueryManager>();
-
-		RenderAPICore::initializeFinalize(primaryWindow);
-	}
-
-    void D3D11RenderAPI::destroyCore()
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		for (auto& boundUAV : mBoundUAVs)
-		{
-			if (boundUAV.second != nullptr)
-				boundUAV.first->releaseView(boundUAV.second);
-		}
-
-		QueryManager::shutDown();
-		D3D11RenderUtility::shutDown();
-
-		if(mIAManager != nullptr)
-		{
-			bs_delete(mIAManager);
-			mIAManager = nullptr;
-		}
-
-		if(mHLSLFactory != nullptr)
-		{
-			bs_delete(mHLSLFactory);
-			mHLSLFactory = nullptr;
-		}
-
-		mActiveVertexDeclaration = nullptr;
-		mActiveVertexShader = nullptr;
-		mActiveRenderTarget = nullptr;
-
-		RenderStateCoreManager::shutDown();
-		RenderWindowCoreManager::shutDown();
-		RenderWindowManager::shutDown();
-		HardwareBufferCoreManager::shutDown();
-		HardwareBufferManager::shutDown();
-		TextureCoreManager::shutDown();
-		TextureManager::shutDown();
-
-		SAFE_RELEASE(mDXGIFactory);
-
-		if(mDevice != nullptr)
-		{
-			bs_delete(mDevice);
-			mDevice = nullptr;
-		}
-
-		if(mDriverList != nullptr)
-		{
-			bs_delete(mDriverList);
-			mDriverList = nullptr;
-		}
-
-		mActiveD3DDriver = nullptr;
-
-		RenderAPICore::destroyCore();
-	}
-
-	void D3D11RenderAPI::setSamplerState(GpuProgramType gptype, UINT16 texUnit, const SPtr<SamplerStateCore>& samplerState)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		// TODO - I'm setting up views one by one, it might be more efficient to hold them in an array
-		//  and then set them all up at once before rendering? Needs testing
-
-		ID3D11SamplerState* samplerArray[1];
-		D3D11SamplerStateCore* d3d11SamplerState = static_cast<D3D11SamplerStateCore*>(const_cast<SamplerStateCore*>(samplerState.get()));
-		samplerArray[0] = d3d11SamplerState->getInternal();
-
-		switch(gptype)
-		{
-		case GPT_VERTEX_PROGRAM:
-			mDevice->getImmediateContext()->VSSetSamplers(texUnit, 1, samplerArray);
-			break;
-		case GPT_FRAGMENT_PROGRAM:
-			mDevice->getImmediateContext()->PSSetSamplers(texUnit, 1, samplerArray);
-			break;
-		case GPT_GEOMETRY_PROGRAM:
-			mDevice->getImmediateContext()->GSSetSamplers(texUnit, 1, samplerArray);
-			break;
-		case GPT_DOMAIN_PROGRAM:
-			mDevice->getImmediateContext()->DSSetSamplers(texUnit, 1, samplerArray);
-			break;
-		case GPT_HULL_PROGRAM:
-			mDevice->getImmediateContext()->HSSetSamplers(texUnit, 1, samplerArray);
-			break;
-		case GPT_COMPUTE_PROGRAM:
-			mDevice->getImmediateContext()->CSSetSamplers(texUnit, 1, samplerArray);
-			break;
-		default:
-			BS_EXCEPT(InvalidParametersException, "Unsupported gpu program type: " + toString(gptype));
-		}
-
-		BS_INC_RENDER_STAT(NumSamplerBinds);
-	}
-
-	void D3D11RenderAPI::setBlendState(const SPtr<BlendStateCore>& blendState)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		D3D11BlendStateCore* d3d11BlendState = static_cast<D3D11BlendStateCore*>(const_cast<BlendStateCore*>(blendState.get()));
-		mDevice->getImmediateContext()->OMSetBlendState(d3d11BlendState->getInternal(), nullptr, 0xFFFFFFFF);
-
-		BS_INC_RENDER_STAT(NumBlendStateChanges);
-	}
-
-	void D3D11RenderAPI::setRasterizerState(const SPtr<RasterizerStateCore>& rasterizerState)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		D3D11RasterizerStateCore* d3d11RasterizerState = static_cast<D3D11RasterizerStateCore*>(const_cast<RasterizerStateCore*>(rasterizerState.get()));
-		mDevice->getImmediateContext()->RSSetState(d3d11RasterizerState->getInternal());
-
-		BS_INC_RENDER_STAT(NumRasterizerStateChanges);
-	}
-
-	void D3D11RenderAPI::setDepthStencilState(const SPtr<DepthStencilStateCore>& depthStencilState, UINT32 stencilRefValue)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		D3D11DepthStencilStateCore* d3d11RasterizerState = static_cast<D3D11DepthStencilStateCore*>(const_cast<DepthStencilStateCore*>(depthStencilState.get()));
-		mDevice->getImmediateContext()->OMSetDepthStencilState(d3d11RasterizerState->getInternal(), stencilRefValue);
-
-		BS_INC_RENDER_STAT(NumDepthStencilStateChanges);
-	}
-
-	void D3D11RenderAPI::setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		// TODO - I'm setting up views one by one, it might be more efficient to hold them in an array
-		//  and then set them all up at once before rendering? Needs testing
-
-		ID3D11ShaderResourceView* viewArray[1];
-		if(texPtr != nullptr && enabled)
-		{
-			D3D11TextureCore* d3d11Texture = static_cast<D3D11TextureCore*>(texPtr.get());
-			viewArray[0] = d3d11Texture->getSRV();
-		}
-		else
-			viewArray[0] = nullptr;
-
-		switch(gptype)
-		{
-		case GPT_VERTEX_PROGRAM:
-			mDevice->getImmediateContext()->VSSetShaderResources(unit, 1, viewArray);
-			break;
-		case GPT_FRAGMENT_PROGRAM:
-			mDevice->getImmediateContext()->PSSetShaderResources(unit, 1, viewArray);
-			break;
-		case GPT_GEOMETRY_PROGRAM:
-			mDevice->getImmediateContext()->GSSetShaderResources(unit, 1, viewArray);
-			break;
-		case GPT_DOMAIN_PROGRAM:
-			mDevice->getImmediateContext()->DSSetShaderResources(unit, 1, viewArray);
-			break;
-		case GPT_HULL_PROGRAM:
-			mDevice->getImmediateContext()->HSSetShaderResources(unit, 1, viewArray);
-			break;
-		case GPT_COMPUTE_PROGRAM:
-			mDevice->getImmediateContext()->CSSetShaderResources(unit, 1, viewArray);
-			break;
-		default:
-			BS_EXCEPT(InvalidParametersException, "Unsupported gpu program type: " + toString(gptype));
-		}
-
-		BS_INC_RENDER_STAT(NumTextureBinds);
-	}
-
-	void D3D11RenderAPI::setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr,
-		const TextureSurface& surface)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		// TODO - This hasn't bee tested and might be incorrect. I might need to set UAVs together with render targets,
-		// especially considering DX11 expects number of UAVs to match number of render targets.
-
-		ID3D11UnorderedAccessView* viewArray[1];
-		if (texPtr != nullptr && enabled)
-		{
-			D3D11TextureCore* d3d11Texture = static_cast<D3D11TextureCore*>(texPtr.get());
-			TextureViewPtr texView = TextureCore::requestView(texPtr, surface.mipLevel, 1, 
-				surface.arraySlice, surface.numArraySlices, GVU_RANDOMWRITE);
-
-			D3D11TextureView* d3d11texView = static_cast<D3D11TextureView*>(texView.get());
-			viewArray[0] = d3d11texView->getUAV();
-
-			if (mBoundUAVs[unit].second != nullptr)
-				mBoundUAVs[unit].first->releaseView(mBoundUAVs[unit].second);
-
-			mBoundUAVs[unit] = std::make_pair(texPtr, texView);
-		}
-		else
-		{
-			viewArray[0] = nullptr;
-
-			if (mBoundUAVs[unit].second != nullptr)
-				mBoundUAVs[unit].first->releaseView(mBoundUAVs[unit].second);
-
-			mBoundUAVs[unit] = std::pair<SPtr<TextureCore>, TextureViewPtr>();
-		}
-
-		if (gptype == GPT_FRAGMENT_PROGRAM)
-		{
-			mDevice->getImmediateContext()->OMSetRenderTargetsAndUnorderedAccessViews(
-				D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr, unit, 1, viewArray, nullptr);
-		}
-		else if (gptype == GPT_COMPUTE_PROGRAM)
-		{
-			mDevice->getImmediateContext()->CSSetUnorderedAccessViews(unit, 1, viewArray, nullptr);
-		}
-		else
-			BS_EXCEPT(InvalidParametersException, "Unsupported gpu program type: " + toString(gptype));
-
-		BS_INC_RENDER_STAT(NumTextureBinds);
-	}
-
-	void D3D11RenderAPI::disableTextureUnit(GpuProgramType gptype, UINT16 texUnit)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		setTexture(gptype, texUnit, false, nullptr);
-	}
-
-	void D3D11RenderAPI::beginFrame()
-	{
-		// Not used
-	}
-
-	void D3D11RenderAPI::endFrame()
-	{
-		// Not used
-	}
-
-	void D3D11RenderAPI::setViewport(const Rect2& vp)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		mViewportNorm = vp;
-		applyViewport();
-	}
-
-	void D3D11RenderAPI::applyViewport()
-	{
-		if (mActiveRenderTarget == nullptr)
-			return;
-
-		const RenderTargetProperties& rtProps = mActiveRenderTarget->getProperties();
-
-		// Set viewport dimensions
-		mViewport.TopLeftX = (FLOAT)(rtProps.getWidth() * mViewportNorm.x);
-		mViewport.TopLeftY = (FLOAT)(rtProps.getHeight() * mViewportNorm.y);
-		mViewport.Width = (FLOAT)(rtProps.getWidth() * mViewportNorm.width);
-		mViewport.Height = (FLOAT)(rtProps.getHeight() * mViewportNorm.height);
-
-		if (rtProps.requiresTextureFlipping())
-		{
-			// Convert "top-left" to "bottom-left"
-			mViewport.TopLeftY = rtProps.getHeight() - mViewport.Height - mViewport.TopLeftY;
-		}
-
-		mViewport.MinDepth = 0.0f;
-		mViewport.MaxDepth = 1.0f;
-
-		mDevice->getImmediateContext()->RSSetViewports(1, &mViewport);
-	}
-
-	void D3D11RenderAPI::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));
-
-		ID3D11Buffer* dx11buffers[MAX_BOUND_VERTEX_BUFFERS];
-		UINT32 strides[MAX_BOUND_VERTEX_BUFFERS];
-		UINT32 offsets[MAX_BOUND_VERTEX_BUFFERS];
-
-		for(UINT32 i = 0; i < numBuffers; i++)
-		{
-			SPtr<D3D11VertexBufferCore> vertexBuffer = std::static_pointer_cast<D3D11VertexBufferCore>(buffers[i]);
-			const VertexBufferProperties& vbProps = vertexBuffer->getProperties();
-
-			dx11buffers[i] = vertexBuffer->getD3DVertexBuffer();
-
-			strides[i] = vbProps.getVertexSize();
-			offsets[i] = 0;
-		}
-
-		mDevice->getImmediateContext()->IASetVertexBuffers(index, numBuffers, dx11buffers, strides, offsets);
-
-		BS_INC_RENDER_STAT(NumVertexBufferBinds);
-	}
-
-	void D3D11RenderAPI::setIndexBuffer(const SPtr<IndexBufferCore>& buffer)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		SPtr<D3D11IndexBufferCore> indexBuffer = std::static_pointer_cast<D3D11IndexBufferCore>(buffer);
-
-		DXGI_FORMAT indexFormat = DXGI_FORMAT_R16_UINT;
-		if(indexBuffer->getProperties().getType() == IT_16BIT)
-			indexFormat = DXGI_FORMAT_R16_UINT;
-		else if (indexBuffer->getProperties().getType() == IT_32BIT)
-			indexFormat = DXGI_FORMAT_R32_UINT;
-		else
-			BS_EXCEPT(InternalErrorException, "Unsupported index format: " + toString(indexBuffer->getProperties().getType()));
-
-		mDevice->getImmediateContext()->IASetIndexBuffer(indexBuffer->getD3DIndexBuffer(), indexFormat, 0);
-
-		BS_INC_RENDER_STAT(NumIndexBufferBinds);
-	}
-
-	void D3D11RenderAPI::setVertexDeclaration(const SPtr<VertexDeclarationCore>& vertexDeclaration)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		mActiveVertexDeclaration = vertexDeclaration;
-	}
-
-	void D3D11RenderAPI::setDrawOperation(DrawOperationType op)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		mDevice->getImmediateContext()->IASetPrimitiveTopology(D3D11Mappings::getPrimitiveType(op));
-	}
-
-	void D3D11RenderAPI::bindGpuProgram(const SPtr<GpuProgramCore>& prg)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		switch(prg->getProperties().getType())
-		{
-		case GPT_VERTEX_PROGRAM:
-			{
-				D3D11GpuVertexProgramCore* d3d11GpuProgram = static_cast<D3D11GpuVertexProgramCore*>(prg.get());
-				mDevice->getImmediateContext()->VSSetShader(d3d11GpuProgram->getVertexShader(), nullptr, 0);
-				mActiveVertexShader = std::static_pointer_cast<D3D11GpuProgramCore>(prg);
-				break;
-			}
-		case GPT_FRAGMENT_PROGRAM:
-			{
-				D3D11GpuFragmentProgramCore* d3d11GpuProgram = static_cast<D3D11GpuFragmentProgramCore*>(prg.get());
-				mDevice->getImmediateContext()->PSSetShader(d3d11GpuProgram->getPixelShader(), nullptr, 0);
-				break;
-			}
-		case GPT_GEOMETRY_PROGRAM:
-			{
-				D3D11GpuGeometryProgramCore* d3d11GpuProgram = static_cast<D3D11GpuGeometryProgramCore*>(prg.get());
-				mDevice->getImmediateContext()->GSSetShader(d3d11GpuProgram->getGeometryShader(), nullptr, 0);
-				break;
-			}
-		case GPT_DOMAIN_PROGRAM:
-			{
-				D3D11GpuDomainProgramCore* d3d11GpuProgram = static_cast<D3D11GpuDomainProgramCore*>(prg.get());
-				mDevice->getImmediateContext()->DSSetShader(d3d11GpuProgram->getDomainShader(), nullptr, 0);
-				break;
-			}
-		case GPT_HULL_PROGRAM:
-			{
-				D3D11GpuHullProgramCore* d3d11GpuProgram = static_cast<D3D11GpuHullProgramCore*>(prg.get());
-				mDevice->getImmediateContext()->HSSetShader(d3d11GpuProgram->getHullShader(), nullptr, 0);
-				break;
-			}
-		case GPT_COMPUTE_PROGRAM:
-			{
-				D3D11GpuComputeProgramCore* d3d11GpuProgram = static_cast<D3D11GpuComputeProgramCore*>(prg.get());
-				mDevice->getImmediateContext()->CSSetShader(d3d11GpuProgram->getComputeShader(), nullptr, 0);
-				break;
-			}
-		default:
-			BS_EXCEPT(InvalidParametersException, "Unsupported gpu program type: " + toString(prg->getProperties().getType()));
-		}
-
-		if (mDevice->hasError())
-			BS_EXCEPT(RenderingAPIException, "Failed to bindGpuProgram : " + mDevice->getErrorDescription());
-
-		BS_INC_RENDER_STAT(NumGpuProgramBinds);
-	}
-
-	void D3D11RenderAPI::unbindGpuProgram(GpuProgramType gptype)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		switch(gptype)
-		{
-		case GPT_VERTEX_PROGRAM:
-			mDevice->getImmediateContext()->VSSetShader(nullptr, nullptr, 0);
-			mActiveVertexShader = nullptr;
-			break;
-		case GPT_FRAGMENT_PROGRAM:
-			mDevice->getImmediateContext()->PSSetShader(nullptr, nullptr, 0);
-			break;
-		case GPT_GEOMETRY_PROGRAM:
-			mDevice->getImmediateContext()->GSSetShader(nullptr, nullptr, 0);
-			break;
-		case GPT_DOMAIN_PROGRAM:
-			mDevice->getImmediateContext()->DSSetShader(nullptr, nullptr, 0);
-			break;
-		case GPT_HULL_PROGRAM:
-			mDevice->getImmediateContext()->HSSetShader(nullptr, nullptr, 0);
-			break;
-		case GPT_COMPUTE_PROGRAM:
-			mDevice->getImmediateContext()->CSSetShader(nullptr, nullptr, 0);
-			break;
-		default:
-			BS_EXCEPT(InvalidParametersException, "Unsupported gpu program type: " + toString(gptype));
-		}
-
-		BS_INC_RENDER_STAT(NumGpuProgramBinds);
-	}
-
-	void D3D11RenderAPI::setConstantBuffers(GpuProgramType gptype, const SPtr<GpuParamsCore>& bindableParams)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		bindableParams->updateHardwareBuffers();
-		const GpuParamDesc& paramDesc = bindableParams->getParamDesc();
-
-		// TODO - I assign constant buffers one by one but it might be more efficient to do them all at once?
-		ID3D11Buffer* bufferArray[1];
-		for(auto iter = paramDesc.paramBlocks.begin(); iter != paramDesc.paramBlocks.end(); ++iter)
-		{
-			SPtr<GpuParamBlockBufferCore> currentBlockBuffer = bindableParams->getParamBlockBuffer(iter->second.slot);
-
-			if(currentBlockBuffer != nullptr)
-			{
-				const D3D11GpuParamBlockBufferCore* d3d11paramBlockBuffer = 
-					static_cast<const D3D11GpuParamBlockBufferCore*>(currentBlockBuffer.get());
-				bufferArray[0] = d3d11paramBlockBuffer->getD3D11Buffer();
-			}
-			else
-				bufferArray[0] = nullptr;
-
-			switch(gptype)
-			{
-			case GPT_VERTEX_PROGRAM:
-				mDevice->getImmediateContext()->VSSetConstantBuffers(iter->second.slot, 1, bufferArray);
-				break;
-			case GPT_FRAGMENT_PROGRAM:
-				mDevice->getImmediateContext()->PSSetConstantBuffers(iter->second.slot, 1, bufferArray);
-				break;
-			case GPT_GEOMETRY_PROGRAM:
-				mDevice->getImmediateContext()->GSSetConstantBuffers(iter->second.slot, 1, bufferArray);
-				break;
-			case GPT_HULL_PROGRAM:
-				mDevice->getImmediateContext()->HSSetConstantBuffers(iter->second.slot, 1, bufferArray);
-				break;
-			case GPT_DOMAIN_PROGRAM:
-				mDevice->getImmediateContext()->DSSetConstantBuffers(iter->second.slot, 1, bufferArray);
-				break;
-			case GPT_COMPUTE_PROGRAM:
-				mDevice->getImmediateContext()->CSSetConstantBuffers(iter->second.slot, 1, bufferArray);
-				break;
-			};
-
-			BS_INC_RENDER_STAT(NumGpuParamBufferBinds);
-		}
-
-		if (mDevice->hasError())
-			BS_EXCEPT(RenderingAPIException, "Failed to setConstantBuffers : " + mDevice->getErrorDescription());
-	}
-
-	void D3D11RenderAPI::draw(UINT32 vertexOffset, UINT32 vertexCount)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		applyInputLayout();
-
-		mDevice->getImmediateContext()->Draw(vertexCount, vertexOffset);
-
-#if BS_DEBUG_MODE
-		if(mDevice->hasError())
-			LOGWRN(mDevice->getErrorDescription());
-#endif
-
-		UINT32 primCount = vertexCountToPrimCount(mActiveDrawOp, vertexCount);
-
-		BS_INC_RENDER_STAT(NumDrawCalls);
-		BS_ADD_RENDER_STAT(NumVertices, vertexCount);
-		BS_ADD_RENDER_STAT(NumPrimitives, primCount);
-	}
-
-	void D3D11RenderAPI::drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		applyInputLayout();
-
-		mDevice->getImmediateContext()->DrawIndexed(indexCount, startIndex, vertexOffset);
-
-#if BS_DEBUG_MODE
-		if(mDevice->hasError())
-			LOGWRN(mDevice->getErrorDescription());
-#endif
-
-		UINT32 primCount = vertexCountToPrimCount(mActiveDrawOp, vertexCount);
-
-		BS_INC_RENDER_STAT(NumDrawCalls);
-		BS_ADD_RENDER_STAT(NumVertices, vertexCount);
-		BS_ADD_RENDER_STAT(NumPrimitives, primCount);
-	}
-
-	void D3D11RenderAPI::dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY, UINT32 numGroupsZ)
-	{
-		mDevice->getImmediateContext()->Dispatch(numGroupsX, numGroupsY, numGroupsZ);
-
-#if BS_DEBUG_MODE
-		if (mDevice->hasError())
-			LOGWRN(mDevice->getErrorDescription());
-#endif
-
-		BS_INC_RENDER_STAT(NumComputeCalls);
-	}
-
-	void D3D11RenderAPI::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);
-
-		mDevice->getImmediateContext()->RSSetScissorRects(1, &mScissorRect);
-	}
-
-	void D3D11RenderAPI::clearViewport(UINT32 buffers, const Color& color, float depth, UINT16 stencil, UINT8 targetMask)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		if(mActiveRenderTarget == nullptr)
-			return;
-
-		const RenderTargetProperties& rtProps = mActiveRenderTarget->getProperties();
-
-		Rect2I clearArea((int)mViewport.TopLeftX, (int)mViewport.TopLeftY, (int)mViewport.Width, (int)mViewport.Height);
-
-		bool clearEntireTarget = clearArea.width == 0 || clearArea.height == 0;
-		clearEntireTarget |= (clearArea.x == 0 && clearArea.y == 0 && clearArea.width == rtProps.getWidth() && clearArea.height == rtProps.getHeight());
-
-		if (!clearEntireTarget)
-		{
-			// TODO - Ignoring targetMask here
-			D3D11RenderUtility::instance().drawClearQuad(buffers, color, depth, stencil);
-			BS_INC_RENDER_STAT(NumClears);
-		}
-		else
-			clearRenderTarget(buffers, color, depth, stencil, targetMask);
-	}
-
-	void D3D11RenderAPI::clearRenderTarget(UINT32 buffers, const Color& color, float depth, UINT16 stencil, UINT8 targetMask)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		if(mActiveRenderTarget == nullptr)
-			return;
-
-		// Clear render surfaces
-		if (buffers & FBT_COLOR)
-		{
-			UINT32 maxRenderTargets = mCurrentCapabilities->getNumMultiRenderTargets();
-
-			ID3D11RenderTargetView** views = bs_newN<ID3D11RenderTargetView*>(maxRenderTargets);
-			memset(views, 0, sizeof(ID3D11RenderTargetView*) * maxRenderTargets);
-
-			mActiveRenderTarget->getCustomAttribute("RTV", views);
-			if (!views[0])
-			{
-				bs_deleteN(views, maxRenderTargets);
-				return;
-			}
-
-			float clearColor[4];
-			clearColor[0] = color.r;
-			clearColor[1] = color.g;
-			clearColor[2] = color.b;
-			clearColor[3] = color.a;
-
-			for(UINT32 i = 0; i < maxRenderTargets; i++)
-			{
-				if(views[i] != nullptr && ((1 << i) & targetMask) != 0)
-					mDevice->getImmediateContext()->ClearRenderTargetView(views[i], clearColor);
-			}
-
-			bs_deleteN(views, maxRenderTargets);
-		}
-
-		// Clear depth stencil
-		if((buffers & FBT_DEPTH) != 0 || (buffers & FBT_STENCIL) != 0)
-		{
-			ID3D11DepthStencilView* depthStencilView = nullptr;
-			mActiveRenderTarget->getCustomAttribute("DSV", &depthStencilView);
-
-			D3D11_CLEAR_FLAG clearFlag;
-
-			if((buffers & FBT_DEPTH) != 0 && (buffers & FBT_STENCIL) != 0)
-				clearFlag = (D3D11_CLEAR_FLAG)(D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL);
-			else if((buffers & FBT_STENCIL) != 0)
-				clearFlag = D3D11_CLEAR_STENCIL;
-			else
-				clearFlag = D3D11_CLEAR_DEPTH;
-
-			if(depthStencilView != nullptr)
-				mDevice->getImmediateContext()->ClearDepthStencilView(depthStencilView, clearFlag, depth, (UINT8)stencil);
-		}
-
-		BS_INC_RENDER_STAT(NumClears);
-	}
-
-	void D3D11RenderAPI::setRenderTarget(const SPtr<RenderTargetCore>& target, bool readOnlyDepthStencil)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		mActiveRenderTarget = target;
-
-		UINT32 maxRenderTargets = mCurrentCapabilities->getNumMultiRenderTargets();
-		ID3D11RenderTargetView** views = bs_newN<ID3D11RenderTargetView*>(maxRenderTargets);
-		memset(views, 0, sizeof(ID3D11RenderTargetView*) * maxRenderTargets);
-
-		ID3D11DepthStencilView* depthStencilView = nullptr;
-
-		if (target != nullptr)
-		{
-			target->getCustomAttribute("RTV", views);
-
-			if(readOnlyDepthStencil)
-				target->getCustomAttribute("RODSV", &depthStencilView);
-			else
-				target->getCustomAttribute("DSV", &depthStencilView);
-		}
-
-		// Bind render targets
-		mDevice->getImmediateContext()->OMSetRenderTargets(maxRenderTargets, views, depthStencilView);
-		if (mDevice->hasError())
-			BS_EXCEPT(RenderingAPIException, "Failed to setRenderTarget : " + mDevice->getErrorDescription());
-
-		bs_deleteN(views, maxRenderTargets);
-		applyViewport();
-
-		BS_INC_RENDER_STAT(NumRenderTargetChanges);
-	}
-
-	void D3D11RenderAPI::setClipPlanesImpl(const PlaneList& clipPlanes)
-	{
-		LOGWRN("This call will be ignored. DX11 uses shaders for setting clip planes.");
-	}
-
-	RenderAPICapabilities* D3D11RenderAPI::createRenderSystemCapabilities() const
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		RenderAPICapabilities* rsc = bs_new<RenderAPICapabilities>();
-
-		rsc->setDriverVersion(mDriverVersion);
-		rsc->setDeviceName(mActiveD3DDriver->getDriverDescription());
-		rsc->setRenderAPIName(getName());
-
-		rsc->setStencilBufferBitDepth(8);
-
-		rsc->setCapability(RSC_ANISOTROPY);
-		rsc->setCapability(RSC_AUTOMIPMAP);
-
-		// Cube map
-		rsc->setCapability(RSC_CUBEMAPPING);
-
-		// We always support compression, D3DX will decompress if device does not support
-		rsc->setCapability(RSC_TEXTURE_COMPRESSION);
-		rsc->setCapability(RSC_TEXTURE_COMPRESSION_DXT);
-		rsc->setCapability(RSC_TWO_SIDED_STENCIL);
-		rsc->setCapability(RSC_STENCIL_WRAP);
-		rsc->setCapability(RSC_HWOCCLUSION);
-		rsc->setCapability(RSC_HWOCCLUSION_ASYNCHRONOUS);
-
-		if(mFeatureLevel >= D3D_FEATURE_LEVEL_10_1)
-			rsc->setMaxBoundVertexBuffers(32);
-		else
-			rsc->setMaxBoundVertexBuffers(16);
-
-		if(mFeatureLevel >= D3D_FEATURE_LEVEL_10_0)
-		{
-			rsc->addShaderProfile("ps_4_0");
-			rsc->addShaderProfile("vs_4_0");
-			rsc->addShaderProfile("gs_4_0");
-
-			rsc->addGpuProgramProfile(GPP_FS_4_0, "ps_4_0");
-			rsc->addGpuProgramProfile(GPP_VS_4_0, "vs_4_0");
-			rsc->addGpuProgramProfile(GPP_GS_4_0, "gs_4_0");
-
-			rsc->setNumTextureUnits(GPT_FRAGMENT_PROGRAM, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT);
-			rsc->setNumTextureUnits(GPT_VERTEX_PROGRAM, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT);
-			rsc->setNumTextureUnits(GPT_GEOMETRY_PROGRAM, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT);
-
-			rsc->setNumCombinedTextureUnits(rsc->getNumTextureUnits(GPT_FRAGMENT_PROGRAM)
-				+ rsc->getNumTextureUnits(GPT_VERTEX_PROGRAM) + rsc->getNumTextureUnits(GPT_VERTEX_PROGRAM));
-
-			rsc->setNumGpuParamBlockBuffers(GPT_FRAGMENT_PROGRAM, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
-			rsc->setNumGpuParamBlockBuffers(GPT_VERTEX_PROGRAM, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
-			rsc->setNumGpuParamBlockBuffers(GPT_GEOMETRY_PROGRAM, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
-
-			rsc->setNumCombinedGpuParamBlockBuffers(rsc->getNumGpuParamBlockBuffers(GPT_FRAGMENT_PROGRAM)
-				+ rsc->getNumGpuParamBlockBuffers(GPT_VERTEX_PROGRAM) + rsc->getNumGpuParamBlockBuffers(GPT_VERTEX_PROGRAM));
-		}
-
-		if(mFeatureLevel >= D3D_FEATURE_LEVEL_10_1)
-		{
-			rsc->addShaderProfile("ps_4_1");
-			rsc->addShaderProfile("vs_4_1");
-			rsc->addShaderProfile("gs_4_1");
-
-			rsc->addGpuProgramProfile(GPP_FS_4_1, "ps_4_1");
-			rsc->addGpuProgramProfile(GPP_VS_4_1, "vs_4_1");
-			rsc->addGpuProgramProfile(GPP_GS_4_1, "gs_4_1");
-		}
-
-		if(mFeatureLevel >= D3D_FEATURE_LEVEL_11_0)
-		{
-			rsc->addShaderProfile("ps_5_0");
-			rsc->addShaderProfile("vs_5_0");
-			rsc->addShaderProfile("gs_5_0");
-			rsc->addShaderProfile("cs_5_0");
-			rsc->addShaderProfile("hs_5_0");
-			rsc->addShaderProfile("ds_5_0");
-
-			rsc->addGpuProgramProfile(GPP_FS_5_0, "ps_5_0");
-			rsc->addGpuProgramProfile(GPP_VS_5_0, "vs_5_0");
-			rsc->addGpuProgramProfile(GPP_GS_5_0, "gs_5_0");
-			rsc->addGpuProgramProfile(GPP_CS_5_0, "cs_5_0");
-			rsc->addGpuProgramProfile(GPP_HS_5_0, "hs_5_0");
-			rsc->addGpuProgramProfile(GPP_DS_5_0, "ds_5_0");
-
-			rsc->setNumTextureUnits(GPT_HULL_PROGRAM, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT);
-			rsc->setNumTextureUnits(GPT_DOMAIN_PROGRAM, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT);
-			rsc->setNumTextureUnits(GPT_COMPUTE_PROGRAM, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT);
-
-			rsc->setNumCombinedTextureUnits(rsc->getNumTextureUnits(GPT_FRAGMENT_PROGRAM)
-				+ rsc->getNumTextureUnits(GPT_VERTEX_PROGRAM) + rsc->getNumTextureUnits(GPT_VERTEX_PROGRAM)
-				+ rsc->getNumTextureUnits(GPT_HULL_PROGRAM) + rsc->getNumTextureUnits(GPT_DOMAIN_PROGRAM)
-				+ rsc->getNumTextureUnits(GPT_COMPUTE_PROGRAM));
-
-			rsc->setNumGpuParamBlockBuffers(GPT_HULL_PROGRAM, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
-			rsc->setNumGpuParamBlockBuffers(GPT_DOMAIN_PROGRAM, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
-			rsc->setNumGpuParamBlockBuffers(GPT_COMPUTE_PROGRAM, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
-
-			rsc->setNumCombinedGpuParamBlockBuffers(rsc->getNumGpuParamBlockBuffers(GPT_FRAGMENT_PROGRAM)
-				+ rsc->getNumGpuParamBlockBuffers(GPT_VERTEX_PROGRAM) + rsc->getNumGpuParamBlockBuffers(GPT_VERTEX_PROGRAM)
-				+ rsc->getNumGpuParamBlockBuffers(GPT_HULL_PROGRAM) + rsc->getNumGpuParamBlockBuffers(GPT_DOMAIN_PROGRAM)
-				+ rsc->getNumGpuParamBlockBuffers(GPT_COMPUTE_PROGRAM));
-
-			rsc->setCapability(RSC_SHADER_SUBROUTINE);
-		}
-
-		rsc->setCapability(RSC_USER_CLIP_PLANES);
-		rsc->setCapability(RSC_VERTEX_FORMAT_UBYTE4);
-
-		// Adapter details
-		const DXGI_ADAPTER_DESC& adapterID = mActiveD3DDriver->getAdapterIdentifier();
-
-		// Determine vendor
-		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);
-
-		rsc->setCapability(RSC_TEXTURE_3D);
-		rsc->setCapability(RSC_NON_POWER_OF_2_TEXTURES);
-		rsc->setCapability(RSC_HWRENDER_TO_TEXTURE);
-		rsc->setCapability(RSC_TEXTURE_FLOAT);
-
-		rsc->setNumMultiRenderTargets(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT);
-		rsc->setCapability(RSC_MRT_DIFFERENT_BIT_DEPTHS);
-
-		rsc->setCapability(RSC_POINT_SPRITES);
-		rsc->setCapability(RSC_POINT_EXTENDED_PARAMETERS);
-		rsc->setMaxPointSize(256);
-
-		rsc->setCapability(RSC_VERTEX_TEXTURE_FETCH);
-
-		rsc->setCapability(RSC_MIPMAP_LOD_BIAS);
-
-		rsc->setCapability(RSC_PERSTAGECONSTANT);
-
-		return rsc;
-	}
-
-	void D3D11RenderAPI::determineMultisampleSettings(UINT32 multisampleCount, DXGI_FORMAT format, DXGI_SAMPLE_DESC* outputSampleDesc)
-	{
-		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;
-
-		bool foundValid = false;
-		size_t origNumSamples = multisampleCount;
-		while (!foundValid)
-		{
-			// Deal with special cases
-			if (tryCSAA)
-			{
-				switch(multisampleCount)
-				{
-				case 8:
-					if (csaaMode == CSAA_Quality)
-					{
-						outputSampleDesc->Count = 8;
-						outputSampleDesc->Quality = 8;
-					}
-					else
-					{
-						outputSampleDesc->Count = 4;
-						outputSampleDesc->Quality = 8;
-					}
-					break;
-				case 16:
-					if (csaaMode == CSAA_Quality)
-					{
-						outputSampleDesc->Count = 8;
-						outputSampleDesc->Quality = 16;
-					}
-					else
-					{
-						outputSampleDesc->Count = 4;
-						outputSampleDesc->Quality = 16;
-					}
-					break;
-				}
-			}
-			else // !CSAA
-			{
-				outputSampleDesc->Count = multisampleCount == 0 ? 1 : multisampleCount;
-				outputSampleDesc->Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN;
-			}
-
-
-			HRESULT hr;
-			UINT outQuality;
-			hr = mDevice->getD3D11Device()->CheckMultisampleQualityLevels(format, outputSampleDesc->Count, &outQuality);
-
-			if (SUCCEEDED(hr) && (!tryCSAA || outQuality > outputSampleDesc->Quality))
-			{
-				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 = static_cast<UINT32>(origNumSamples);
-				}
-				else
-				{
-					// Drop samples
-					multisampleCount--;
-
-					if (multisampleCount == 1)
-					{
-						// Ran out of options, no multisampling
-						multisampleCount = 0;
-						foundValid = true;
-					}
-				}
-			}
-		} 
-	}
-
-	VertexElementType D3D11RenderAPI::getColorVertexElementType() const
-	{
-		return VET_COLOR_ABGR;
-	}
-
-	void D3D11RenderAPI::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;
-	}
-
-	float D3D11RenderAPI::getHorizontalTexelOffset()
-	{
-		return 0.0f;
-	}
-
-	float D3D11RenderAPI::getVerticalTexelOffset()
-	{
-		return 0.0f;
-	}
-
-	float D3D11RenderAPI::getMinimumDepthInputValue()
-	{
-		return 0.0f;
-	}
-
-	float D3D11RenderAPI::getMaximumDepthInputValue()
-	{
-		return 1.0f;
-	}
-
-	GpuParamBlockDesc D3D11RenderAPI::generateParamBlockDesc(const String& name, Vector<GpuParamDataDesc>& params)
-	{
-		GpuParamBlockDesc block;
-		block.blockSize = 0;
-		block.isShareable = true;
-		block.name = name;
-		block.slot = 0;
-
-		for (auto& param : params)
-		{
-			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[param.type];
-			UINT32 size = typeInfo.size / 4;
-
-			if (param.arraySize > 1)
-			{
-				// Arrays perform no packing and their elements are always padded and aligned to four component vectors
-				UINT32 alignOffset = size % typeInfo.baseTypeSize;
-				if (alignOffset != 0)
-				{
-					UINT32 padding = (typeInfo.baseTypeSize - alignOffset);
-					size += padding;
-				}
-
-				alignOffset = block.blockSize % typeInfo.baseTypeSize;
-				if (alignOffset != 0)
-				{
-					UINT32 padding = (typeInfo.baseTypeSize - alignOffset);
-					block.blockSize += padding;
-				}
-
-				param.elementSize = size;
-				param.arrayElementStride = size;
-				param.cpuMemOffset = block.blockSize;
-				param.gpuMemOffset = 0;
-
-				block.blockSize += size * param.arraySize;
-			}
-			else
-			{
-				// Pack everything as tightly as possible as long as the data doesn't cross 16 byte boundary
-				UINT32 alignOffset = block.blockSize % 4;
-				if (alignOffset != 0 && size > (4 - alignOffset))
-				{
-					UINT32 padding = (4 - alignOffset);
-					block.blockSize += padding;
-				}
-
-				param.elementSize = size;
-				param.arrayElementStride = size;
-				param.cpuMemOffset = block.blockSize;
-				param.gpuMemOffset = 0;
-
-				block.blockSize += size;
-			}
-
-			param.paramBlockSlot = 0;
-		}
-
-		// Constant buffer size must always be a multiple of 16
-		if (block.blockSize % 4 != 0)
-			block.blockSize += (4 - (block.blockSize % 4));
-
-		return block;
-	}
-
-	/************************************************************************/
-	/* 								PRIVATE		                     		*/
-	/************************************************************************/
-
-	void D3D11RenderAPI::applyInputLayout()
-	{
-		if(mActiveVertexDeclaration == nullptr)
-		{
-			LOGWRN("Cannot apply input layout without a vertex declaration. Set vertex declaration before calling this method.");
-			return;
-		}
-
-		if(mActiveVertexShader == nullptr)
-		{
-			LOGWRN("Cannot apply input layout without a vertex shader. Set vertex shader before calling this method.");
-			return;
-		}
-
-		ID3D11InputLayout* ia = mIAManager->retrieveInputLayout(mActiveVertexShader->getInputDeclaration(), mActiveVertexDeclaration, *mActiveVertexShader);
-
-		mDevice->getImmediateContext()->IASetInputLayout(ia);
-	}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsD3D11RenderAPI.h"
+#include "BsD3D11DriverList.h"
+#include "BsD3D11Driver.h"
+#include "BsD3D11Device.h"
+#include "BsD3D11TextureManager.h"
+#include "BsD3D11Texture.h"
+#include "BsD3D11HardwareBufferManager.h"
+#include "BsD3D11RenderWindowManager.h"
+#include "BsD3D11HLSLProgramFactory.h"
+#include "BsD3D11BlendState.h"
+#include "BsD3D11RasterizerState.h"
+#include "BsD3D11DepthStencilState.h"
+#include "BsD3D11SamplerState.h"
+#include "BsD3D11GpuProgram.h"
+#include "BsD3D11Mappings.h"
+#include "BsD3D11VertexBuffer.h"
+#include "BsD3D11IndexBuffer.h"
+#include "BsD3D11RenderStateManager.h"
+#include "BsD3D11GpuParamBlockBuffer.h"
+#include "BsD3D11InputLayoutManager.h"
+#include "BsD3D11TextureView.h"
+#include "BsD3D11RenderUtility.h"
+#include "BsGpuParams.h"
+#include "BsCoreThread.h"
+#include "BsD3D11QueryManager.h"
+#include "BsDebug.h"
+#include "BsException.h"
+#include "BsRenderStats.h"
+#include "BsGpuParamDesc.h"
+
+namespace BansheeEngine
+{
+	D3D11RenderAPI::D3D11RenderAPI()
+		: mDXGIFactory(nullptr), mDevice(nullptr), mDriverList(nullptr)
+		, mActiveD3DDriver(nullptr), mFeatureLevel(D3D_FEATURE_LEVEL_11_0)
+		, mHLSLFactory(nullptr), mIAManager(nullptr)
+		, mStencilRef(0), mActiveDrawOp(DOT_TRIANGLE_LIST)
+		, mViewportNorm(0.0f, 0.0f, 1.0f, 1.0f)
+	{
+		mClipPlanesDirty = false; // DX11 handles clip planes through shaders
+	}
+
+	D3D11RenderAPI::~D3D11RenderAPI()
+	{
+
+	}
+
+	const StringID& D3D11RenderAPI::getName() const
+	{
+		static StringID strName("D3D11RenderAPI");
+		return strName;
+	}
+
+	const String& D3D11RenderAPI::getShadingLanguageName() const
+	{
+		static String strName("hlsl");
+		return strName;
+	}
+
+	void D3D11RenderAPI::initializePrepare()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		HRESULT hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&mDXGIFactory);
+		if(FAILED(hr))
+			BS_EXCEPT(RenderingAPIException, "Failed to create Direct3D11 DXGIFactory");
+
+		mDriverList = bs_new<D3D11DriverList>(mDXGIFactory);
+		mActiveD3DDriver = mDriverList->item(0); // TODO: Always get first driver, for now
+		mVideoModeInfo = mActiveD3DDriver->getVideoModeInfo();
+
+		IDXGIAdapter* selectedAdapter = mActiveD3DDriver->getDeviceAdapter();
+
+		D3D_FEATURE_LEVEL requestedLevels[] = {
+			D3D_FEATURE_LEVEL_11_0,
+			D3D_FEATURE_LEVEL_10_1,
+			D3D_FEATURE_LEVEL_10_0,
+			D3D_FEATURE_LEVEL_9_3,
+			D3D_FEATURE_LEVEL_9_2,
+			D3D_FEATURE_LEVEL_9_1
+		};
+
+		UINT32 numRequestedLevel = sizeof(requestedLevels) / sizeof(requestedLevels[0]);
+
+		UINT32 deviceFlags = 0;
+
+#if BS_DEBUG_MODE
+		deviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
+#endif
+
+		ID3D11Device* device;
+		hr = D3D11CreateDevice(selectedAdapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr, deviceFlags, 
+			requestedLevels, numRequestedLevel, D3D11_SDK_VERSION, &device, &mFeatureLevel, nullptr);
+
+		if(FAILED(hr))         
+			BS_EXCEPT(RenderingAPIException, "Failed to create Direct3D11 object. D3D11CreateDeviceN returned this error code: " + toString(hr));
+
+		mDevice = bs_new<D3D11Device>(device);
+		
+		// This must query for DirectX 10 interface as this is unsupported for DX11
+		LARGE_INTEGER driverVersion; 
+		if(SUCCEEDED(selectedAdapter->CheckInterfaceSupport(IID_ID3D10Device, &driverVersion)))
+		{
+			mDriverVersion.major =  HIWORD(driverVersion.HighPart);
+			mDriverVersion.minor = LOWORD(driverVersion.HighPart);
+			mDriverVersion.release = HIWORD(driverVersion.LowPart);
+			mDriverVersion.build = LOWORD(driverVersion.LowPart);
+		}
+
+		// Create the texture manager for use by others		
+		TextureManager::startUp<D3D11TextureManager>();
+		TextureCoreManager::startUp<D3D11TextureCoreManager>();
+
+		// Create hardware buffer manager		
+		HardwareBufferManager::startUp();
+		HardwareBufferCoreManager::startUp<D3D11HardwareBufferCoreManager>(std::ref(*mDevice));
+
+		// Create render window manager
+		RenderWindowManager::startUp<D3D11RenderWindowManager>(this);
+		RenderWindowCoreManager::startUp<D3D11RenderWindowCoreManager>(this);
+
+		// Create & register HLSL factory		
+		mHLSLFactory = bs_new<D3D11HLSLProgramFactory>();
+
+		// Create render state manager
+		RenderStateCoreManager::startUp<D3D11RenderStateCoreManager>();
+
+		mCurrentCapabilities = createRenderSystemCapabilities();
+
+		mCurrentCapabilities->addShaderProfile("hlsl");
+		GpuProgramCoreManager::instance().addFactory(mHLSLFactory);
+
+		mIAManager = bs_new<D3D11InputLayoutManager>();
+
+		RenderAPICore::initializePrepare();
+	}
+
+	void D3D11RenderAPI::initializeFinalize(const SPtr<RenderWindowCore>& primaryWindow)
+	{
+		D3D11RenderUtility::startUp(mDevice);
+
+		QueryManager::startUp<D3D11QueryManager>();
+
+		RenderAPICore::initializeFinalize(primaryWindow);
+	}
+
+    void D3D11RenderAPI::destroyCore()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		for (auto& boundUAV : mBoundUAVs)
+		{
+			if (boundUAV.second != nullptr)
+				boundUAV.first->releaseView(boundUAV.second);
+		}
+
+		QueryManager::shutDown();
+		D3D11RenderUtility::shutDown();
+
+		if(mIAManager != nullptr)
+		{
+			bs_delete(mIAManager);
+			mIAManager = nullptr;
+		}
+
+		if(mHLSLFactory != nullptr)
+		{
+			bs_delete(mHLSLFactory);
+			mHLSLFactory = nullptr;
+		}
+
+		mActiveVertexDeclaration = nullptr;
+		mActiveVertexShader = nullptr;
+		mActiveRenderTarget = nullptr;
+
+		RenderStateCoreManager::shutDown();
+		RenderWindowCoreManager::shutDown();
+		RenderWindowManager::shutDown();
+		HardwareBufferCoreManager::shutDown();
+		HardwareBufferManager::shutDown();
+		TextureCoreManager::shutDown();
+		TextureManager::shutDown();
+
+		SAFE_RELEASE(mDXGIFactory);
+
+		if(mDevice != nullptr)
+		{
+			bs_delete(mDevice);
+			mDevice = nullptr;
+		}
+
+		if(mDriverList != nullptr)
+		{
+			bs_delete(mDriverList);
+			mDriverList = nullptr;
+		}
+
+		mActiveD3DDriver = nullptr;
+
+		RenderAPICore::destroyCore();
+	}
+
+	void D3D11RenderAPI::setSamplerState(GpuProgramType gptype, UINT16 texUnit, const SPtr<SamplerStateCore>& samplerState)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		// TODO - I'm setting up views one by one, it might be more efficient to hold them in an array
+		//  and then set them all up at once before rendering? Needs testing
+
+		ID3D11SamplerState* samplerArray[1];
+		D3D11SamplerStateCore* d3d11SamplerState = static_cast<D3D11SamplerStateCore*>(const_cast<SamplerStateCore*>(samplerState.get()));
+		samplerArray[0] = d3d11SamplerState->getInternal();
+
+		switch(gptype)
+		{
+		case GPT_VERTEX_PROGRAM:
+			mDevice->getImmediateContext()->VSSetSamplers(texUnit, 1, samplerArray);
+			break;
+		case GPT_FRAGMENT_PROGRAM:
+			mDevice->getImmediateContext()->PSSetSamplers(texUnit, 1, samplerArray);
+			break;
+		case GPT_GEOMETRY_PROGRAM:
+			mDevice->getImmediateContext()->GSSetSamplers(texUnit, 1, samplerArray);
+			break;
+		case GPT_DOMAIN_PROGRAM:
+			mDevice->getImmediateContext()->DSSetSamplers(texUnit, 1, samplerArray);
+			break;
+		case GPT_HULL_PROGRAM:
+			mDevice->getImmediateContext()->HSSetSamplers(texUnit, 1, samplerArray);
+			break;
+		case GPT_COMPUTE_PROGRAM:
+			mDevice->getImmediateContext()->CSSetSamplers(texUnit, 1, samplerArray);
+			break;
+		default:
+			BS_EXCEPT(InvalidParametersException, "Unsupported gpu program type: " + toString(gptype));
+		}
+
+		BS_INC_RENDER_STAT(NumSamplerBinds);
+	}
+
+	void D3D11RenderAPI::setBlendState(const SPtr<BlendStateCore>& blendState)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		D3D11BlendStateCore* d3d11BlendState = static_cast<D3D11BlendStateCore*>(const_cast<BlendStateCore*>(blendState.get()));
+		mDevice->getImmediateContext()->OMSetBlendState(d3d11BlendState->getInternal(), nullptr, 0xFFFFFFFF);
+
+		BS_INC_RENDER_STAT(NumBlendStateChanges);
+	}
+
+	void D3D11RenderAPI::setRasterizerState(const SPtr<RasterizerStateCore>& rasterizerState)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		D3D11RasterizerStateCore* d3d11RasterizerState = static_cast<D3D11RasterizerStateCore*>(const_cast<RasterizerStateCore*>(rasterizerState.get()));
+		mDevice->getImmediateContext()->RSSetState(d3d11RasterizerState->getInternal());
+
+		BS_INC_RENDER_STAT(NumRasterizerStateChanges);
+	}
+
+	void D3D11RenderAPI::setDepthStencilState(const SPtr<DepthStencilStateCore>& depthStencilState, UINT32 stencilRefValue)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		D3D11DepthStencilStateCore* d3d11RasterizerState = static_cast<D3D11DepthStencilStateCore*>(const_cast<DepthStencilStateCore*>(depthStencilState.get()));
+		mDevice->getImmediateContext()->OMSetDepthStencilState(d3d11RasterizerState->getInternal(), stencilRefValue);
+
+		BS_INC_RENDER_STAT(NumDepthStencilStateChanges);
+	}
+
+	void D3D11RenderAPI::setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		// TODO - I'm setting up views one by one, it might be more efficient to hold them in an array
+		//  and then set them all up at once before rendering? Needs testing
+
+		ID3D11ShaderResourceView* viewArray[1];
+		if(texPtr != nullptr && enabled)
+		{
+			D3D11TextureCore* d3d11Texture = static_cast<D3D11TextureCore*>(texPtr.get());
+			viewArray[0] = d3d11Texture->getSRV();
+		}
+		else
+			viewArray[0] = nullptr;
+
+		switch(gptype)
+		{
+		case GPT_VERTEX_PROGRAM:
+			mDevice->getImmediateContext()->VSSetShaderResources(unit, 1, viewArray);
+			break;
+		case GPT_FRAGMENT_PROGRAM:
+			mDevice->getImmediateContext()->PSSetShaderResources(unit, 1, viewArray);
+			break;
+		case GPT_GEOMETRY_PROGRAM:
+			mDevice->getImmediateContext()->GSSetShaderResources(unit, 1, viewArray);
+			break;
+		case GPT_DOMAIN_PROGRAM:
+			mDevice->getImmediateContext()->DSSetShaderResources(unit, 1, viewArray);
+			break;
+		case GPT_HULL_PROGRAM:
+			mDevice->getImmediateContext()->HSSetShaderResources(unit, 1, viewArray);
+			break;
+		case GPT_COMPUTE_PROGRAM:
+			mDevice->getImmediateContext()->CSSetShaderResources(unit, 1, viewArray);
+			break;
+		default:
+			BS_EXCEPT(InvalidParametersException, "Unsupported gpu program type: " + toString(gptype));
+		}
+
+		BS_INC_RENDER_STAT(NumTextureBinds);
+	}
+
+	void D3D11RenderAPI::setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr,
+		const TextureSurface& surface)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		// TODO - This hasn't bee tested and might be incorrect. I might need to set UAVs together with render targets,
+		// especially considering DX11 expects number of UAVs to match number of render targets.
+
+		ID3D11UnorderedAccessView* viewArray[1];
+		if (texPtr != nullptr && enabled)
+		{
+			D3D11TextureCore* d3d11Texture = static_cast<D3D11TextureCore*>(texPtr.get());
+			TextureViewPtr texView = TextureCore::requestView(texPtr, surface.mipLevel, 1, 
+				surface.arraySlice, surface.numArraySlices, GVU_RANDOMWRITE);
+
+			D3D11TextureView* d3d11texView = static_cast<D3D11TextureView*>(texView.get());
+			viewArray[0] = d3d11texView->getUAV();
+
+			if (mBoundUAVs[unit].second != nullptr)
+				mBoundUAVs[unit].first->releaseView(mBoundUAVs[unit].second);
+
+			mBoundUAVs[unit] = std::make_pair(texPtr, texView);
+		}
+		else
+		{
+			viewArray[0] = nullptr;
+
+			if (mBoundUAVs[unit].second != nullptr)
+				mBoundUAVs[unit].first->releaseView(mBoundUAVs[unit].second);
+
+			mBoundUAVs[unit] = std::pair<SPtr<TextureCore>, TextureViewPtr>();
+		}
+
+		if (gptype == GPT_FRAGMENT_PROGRAM)
+		{
+			mDevice->getImmediateContext()->OMSetRenderTargetsAndUnorderedAccessViews(
+				D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr, unit, 1, viewArray, nullptr);
+		}
+		else if (gptype == GPT_COMPUTE_PROGRAM)
+		{
+			mDevice->getImmediateContext()->CSSetUnorderedAccessViews(unit, 1, viewArray, nullptr);
+		}
+		else
+			BS_EXCEPT(InvalidParametersException, "Unsupported gpu program type: " + toString(gptype));
+
+		BS_INC_RENDER_STAT(NumTextureBinds);
+	}
+
+	void D3D11RenderAPI::disableTextureUnit(GpuProgramType gptype, UINT16 texUnit)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		setTexture(gptype, texUnit, false, nullptr);
+	}
+
+	void D3D11RenderAPI::beginFrame()
+	{
+		// Not used
+	}
+
+	void D3D11RenderAPI::endFrame()
+	{
+		// Not used
+	}
+
+	void D3D11RenderAPI::setViewport(const Rect2& vp)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		mViewportNorm = vp;
+		applyViewport();
+	}
+
+	void D3D11RenderAPI::applyViewport()
+	{
+		if (mActiveRenderTarget == nullptr)
+			return;
+
+		const RenderTargetProperties& rtProps = mActiveRenderTarget->getProperties();
+
+		// Set viewport dimensions
+		mViewport.TopLeftX = (FLOAT)(rtProps.getWidth() * mViewportNorm.x);
+		mViewport.TopLeftY = (FLOAT)(rtProps.getHeight() * mViewportNorm.y);
+		mViewport.Width = (FLOAT)(rtProps.getWidth() * mViewportNorm.width);
+		mViewport.Height = (FLOAT)(rtProps.getHeight() * mViewportNorm.height);
+
+		if (rtProps.requiresTextureFlipping())
+		{
+			// Convert "top-left" to "bottom-left"
+			mViewport.TopLeftY = rtProps.getHeight() - mViewport.Height - mViewport.TopLeftY;
+		}
+
+		mViewport.MinDepth = 0.0f;
+		mViewport.MaxDepth = 1.0f;
+
+		mDevice->getImmediateContext()->RSSetViewports(1, &mViewport);
+	}
+
+	void D3D11RenderAPI::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));
+
+		ID3D11Buffer* dx11buffers[MAX_BOUND_VERTEX_BUFFERS];
+		UINT32 strides[MAX_BOUND_VERTEX_BUFFERS];
+		UINT32 offsets[MAX_BOUND_VERTEX_BUFFERS];
+
+		for(UINT32 i = 0; i < numBuffers; i++)
+		{
+			SPtr<D3D11VertexBufferCore> vertexBuffer = std::static_pointer_cast<D3D11VertexBufferCore>(buffers[i]);
+			const VertexBufferProperties& vbProps = vertexBuffer->getProperties();
+
+			dx11buffers[i] = vertexBuffer->getD3DVertexBuffer();
+
+			strides[i] = vbProps.getVertexSize();
+			offsets[i] = 0;
+		}
+
+		mDevice->getImmediateContext()->IASetVertexBuffers(index, numBuffers, dx11buffers, strides, offsets);
+
+		BS_INC_RENDER_STAT(NumVertexBufferBinds);
+	}
+
+	void D3D11RenderAPI::setIndexBuffer(const SPtr<IndexBufferCore>& buffer)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		SPtr<D3D11IndexBufferCore> indexBuffer = std::static_pointer_cast<D3D11IndexBufferCore>(buffer);
+
+		DXGI_FORMAT indexFormat = DXGI_FORMAT_R16_UINT;
+		if(indexBuffer->getProperties().getType() == IT_16BIT)
+			indexFormat = DXGI_FORMAT_R16_UINT;
+		else if (indexBuffer->getProperties().getType() == IT_32BIT)
+			indexFormat = DXGI_FORMAT_R32_UINT;
+		else
+			BS_EXCEPT(InternalErrorException, "Unsupported index format: " + toString(indexBuffer->getProperties().getType()));
+
+		mDevice->getImmediateContext()->IASetIndexBuffer(indexBuffer->getD3DIndexBuffer(), indexFormat, 0);
+
+		BS_INC_RENDER_STAT(NumIndexBufferBinds);
+	}
+
+	void D3D11RenderAPI::setVertexDeclaration(const SPtr<VertexDeclarationCore>& vertexDeclaration)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		mActiveVertexDeclaration = vertexDeclaration;
+	}
+
+	void D3D11RenderAPI::setDrawOperation(DrawOperationType op)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		mDevice->getImmediateContext()->IASetPrimitiveTopology(D3D11Mappings::getPrimitiveType(op));
+	}
+
+	void D3D11RenderAPI::bindGpuProgram(const SPtr<GpuProgramCore>& prg)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		switch(prg->getProperties().getType())
+		{
+		case GPT_VERTEX_PROGRAM:
+			{
+				D3D11GpuVertexProgramCore* d3d11GpuProgram = static_cast<D3D11GpuVertexProgramCore*>(prg.get());
+				mDevice->getImmediateContext()->VSSetShader(d3d11GpuProgram->getVertexShader(), nullptr, 0);
+				mActiveVertexShader = std::static_pointer_cast<D3D11GpuProgramCore>(prg);
+				break;
+			}
+		case GPT_FRAGMENT_PROGRAM:
+			{
+				D3D11GpuFragmentProgramCore* d3d11GpuProgram = static_cast<D3D11GpuFragmentProgramCore*>(prg.get());
+				mDevice->getImmediateContext()->PSSetShader(d3d11GpuProgram->getPixelShader(), nullptr, 0);
+				break;
+			}
+		case GPT_GEOMETRY_PROGRAM:
+			{
+				D3D11GpuGeometryProgramCore* d3d11GpuProgram = static_cast<D3D11GpuGeometryProgramCore*>(prg.get());
+				mDevice->getImmediateContext()->GSSetShader(d3d11GpuProgram->getGeometryShader(), nullptr, 0);
+				break;
+			}
+		case GPT_DOMAIN_PROGRAM:
+			{
+				D3D11GpuDomainProgramCore* d3d11GpuProgram = static_cast<D3D11GpuDomainProgramCore*>(prg.get());
+				mDevice->getImmediateContext()->DSSetShader(d3d11GpuProgram->getDomainShader(), nullptr, 0);
+				break;
+			}
+		case GPT_HULL_PROGRAM:
+			{
+				D3D11GpuHullProgramCore* d3d11GpuProgram = static_cast<D3D11GpuHullProgramCore*>(prg.get());
+				mDevice->getImmediateContext()->HSSetShader(d3d11GpuProgram->getHullShader(), nullptr, 0);
+				break;
+			}
+		case GPT_COMPUTE_PROGRAM:
+			{
+				D3D11GpuComputeProgramCore* d3d11GpuProgram = static_cast<D3D11GpuComputeProgramCore*>(prg.get());
+				mDevice->getImmediateContext()->CSSetShader(d3d11GpuProgram->getComputeShader(), nullptr, 0);
+				break;
+			}
+		default:
+			BS_EXCEPT(InvalidParametersException, "Unsupported gpu program type: " + toString(prg->getProperties().getType()));
+		}
+
+		if (mDevice->hasError())
+			BS_EXCEPT(RenderingAPIException, "Failed to bindGpuProgram : " + mDevice->getErrorDescription());
+
+		BS_INC_RENDER_STAT(NumGpuProgramBinds);
+	}
+
+	void D3D11RenderAPI::unbindGpuProgram(GpuProgramType gptype)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		switch(gptype)
+		{
+		case GPT_VERTEX_PROGRAM:
+			mDevice->getImmediateContext()->VSSetShader(nullptr, nullptr, 0);
+			mActiveVertexShader = nullptr;
+			break;
+		case GPT_FRAGMENT_PROGRAM:
+			mDevice->getImmediateContext()->PSSetShader(nullptr, nullptr, 0);
+			break;
+		case GPT_GEOMETRY_PROGRAM:
+			mDevice->getImmediateContext()->GSSetShader(nullptr, nullptr, 0);
+			break;
+		case GPT_DOMAIN_PROGRAM:
+			mDevice->getImmediateContext()->DSSetShader(nullptr, nullptr, 0);
+			break;
+		case GPT_HULL_PROGRAM:
+			mDevice->getImmediateContext()->HSSetShader(nullptr, nullptr, 0);
+			break;
+		case GPT_COMPUTE_PROGRAM:
+			mDevice->getImmediateContext()->CSSetShader(nullptr, nullptr, 0);
+			break;
+		default:
+			BS_EXCEPT(InvalidParametersException, "Unsupported gpu program type: " + toString(gptype));
+		}
+
+		BS_INC_RENDER_STAT(NumGpuProgramBinds);
+	}
+
+	void D3D11RenderAPI::setConstantBuffers(GpuProgramType gptype, const SPtr<GpuParamsCore>& bindableParams)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		bindableParams->updateHardwareBuffers();
+		const GpuParamDesc& paramDesc = bindableParams->getParamDesc();
+
+		// TODO - I assign constant buffers one by one but it might be more efficient to do them all at once?
+		ID3D11Buffer* bufferArray[1];
+		for(auto iter = paramDesc.paramBlocks.begin(); iter != paramDesc.paramBlocks.end(); ++iter)
+		{
+			SPtr<GpuParamBlockBufferCore> currentBlockBuffer = bindableParams->getParamBlockBuffer(iter->second.slot);
+
+			if(currentBlockBuffer != nullptr)
+			{
+				const D3D11GpuParamBlockBufferCore* d3d11paramBlockBuffer = 
+					static_cast<const D3D11GpuParamBlockBufferCore*>(currentBlockBuffer.get());
+				bufferArray[0] = d3d11paramBlockBuffer->getD3D11Buffer();
+			}
+			else
+				bufferArray[0] = nullptr;
+
+			switch(gptype)
+			{
+			case GPT_VERTEX_PROGRAM:
+				mDevice->getImmediateContext()->VSSetConstantBuffers(iter->second.slot, 1, bufferArray);
+				break;
+			case GPT_FRAGMENT_PROGRAM:
+				mDevice->getImmediateContext()->PSSetConstantBuffers(iter->second.slot, 1, bufferArray);
+				break;
+			case GPT_GEOMETRY_PROGRAM:
+				mDevice->getImmediateContext()->GSSetConstantBuffers(iter->second.slot, 1, bufferArray);
+				break;
+			case GPT_HULL_PROGRAM:
+				mDevice->getImmediateContext()->HSSetConstantBuffers(iter->second.slot, 1, bufferArray);
+				break;
+			case GPT_DOMAIN_PROGRAM:
+				mDevice->getImmediateContext()->DSSetConstantBuffers(iter->second.slot, 1, bufferArray);
+				break;
+			case GPT_COMPUTE_PROGRAM:
+				mDevice->getImmediateContext()->CSSetConstantBuffers(iter->second.slot, 1, bufferArray);
+				break;
+			};
+
+			BS_INC_RENDER_STAT(NumGpuParamBufferBinds);
+		}
+
+		if (mDevice->hasError())
+			BS_EXCEPT(RenderingAPIException, "Failed to setConstantBuffers : " + mDevice->getErrorDescription());
+	}
+
+	void D3D11RenderAPI::draw(UINT32 vertexOffset, UINT32 vertexCount)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		applyInputLayout();
+
+		mDevice->getImmediateContext()->Draw(vertexCount, vertexOffset);
+
+#if BS_DEBUG_MODE
+		if(mDevice->hasError())
+			LOGWRN(mDevice->getErrorDescription());
+#endif
+
+		UINT32 primCount = vertexCountToPrimCount(mActiveDrawOp, vertexCount);
+
+		BS_INC_RENDER_STAT(NumDrawCalls);
+		BS_ADD_RENDER_STAT(NumVertices, vertexCount);
+		BS_ADD_RENDER_STAT(NumPrimitives, primCount);
+	}
+
+	void D3D11RenderAPI::drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		applyInputLayout();
+
+		mDevice->getImmediateContext()->DrawIndexed(indexCount, startIndex, vertexOffset);
+
+#if BS_DEBUG_MODE
+		if(mDevice->hasError())
+			LOGWRN(mDevice->getErrorDescription());
+#endif
+
+		UINT32 primCount = vertexCountToPrimCount(mActiveDrawOp, vertexCount);
+
+		BS_INC_RENDER_STAT(NumDrawCalls);
+		BS_ADD_RENDER_STAT(NumVertices, vertexCount);
+		BS_ADD_RENDER_STAT(NumPrimitives, primCount);
+	}
+
+	void D3D11RenderAPI::dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY, UINT32 numGroupsZ)
+	{
+		mDevice->getImmediateContext()->Dispatch(numGroupsX, numGroupsY, numGroupsZ);
+
+#if BS_DEBUG_MODE
+		if (mDevice->hasError())
+			LOGWRN(mDevice->getErrorDescription());
+#endif
+
+		BS_INC_RENDER_STAT(NumComputeCalls);
+	}
+
+	void D3D11RenderAPI::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);
+
+		mDevice->getImmediateContext()->RSSetScissorRects(1, &mScissorRect);
+	}
+
+	void D3D11RenderAPI::clearViewport(UINT32 buffers, const Color& color, float depth, UINT16 stencil, UINT8 targetMask)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		if(mActiveRenderTarget == nullptr)
+			return;
+
+		const RenderTargetProperties& rtProps = mActiveRenderTarget->getProperties();
+
+		Rect2I clearArea((int)mViewport.TopLeftX, (int)mViewport.TopLeftY, (int)mViewport.Width, (int)mViewport.Height);
+
+		bool clearEntireTarget = clearArea.width == 0 || clearArea.height == 0;
+		clearEntireTarget |= (clearArea.x == 0 && clearArea.y == 0 && clearArea.width == rtProps.getWidth() && clearArea.height == rtProps.getHeight());
+
+		if (!clearEntireTarget)
+		{
+			// TODO - Ignoring targetMask here
+			D3D11RenderUtility::instance().drawClearQuad(buffers, color, depth, stencil);
+			BS_INC_RENDER_STAT(NumClears);
+		}
+		else
+			clearRenderTarget(buffers, color, depth, stencil, targetMask);
+	}
+
+	void D3D11RenderAPI::clearRenderTarget(UINT32 buffers, const Color& color, float depth, UINT16 stencil, UINT8 targetMask)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		if(mActiveRenderTarget == nullptr)
+			return;
+
+		// Clear render surfaces
+		if (buffers & FBT_COLOR)
+		{
+			UINT32 maxRenderTargets = mCurrentCapabilities->getNumMultiRenderTargets();
+
+			ID3D11RenderTargetView** views = bs_newN<ID3D11RenderTargetView*>(maxRenderTargets);
+			memset(views, 0, sizeof(ID3D11RenderTargetView*) * maxRenderTargets);
+
+			mActiveRenderTarget->getCustomAttribute("RTV", views);
+			if (!views[0])
+			{
+				bs_deleteN(views, maxRenderTargets);
+				return;
+			}
+
+			float clearColor[4];
+			clearColor[0] = color.r;
+			clearColor[1] = color.g;
+			clearColor[2] = color.b;
+			clearColor[3] = color.a;
+
+			for(UINT32 i = 0; i < maxRenderTargets; i++)
+			{
+				if(views[i] != nullptr && ((1 << i) & targetMask) != 0)
+					mDevice->getImmediateContext()->ClearRenderTargetView(views[i], clearColor);
+			}
+
+			bs_deleteN(views, maxRenderTargets);
+		}
+
+		// Clear depth stencil
+		if((buffers & FBT_DEPTH) != 0 || (buffers & FBT_STENCIL) != 0)
+		{
+			ID3D11DepthStencilView* depthStencilView = nullptr;
+			mActiveRenderTarget->getCustomAttribute("DSV", &depthStencilView);
+
+			D3D11_CLEAR_FLAG clearFlag;
+
+			if((buffers & FBT_DEPTH) != 0 && (buffers & FBT_STENCIL) != 0)
+				clearFlag = (D3D11_CLEAR_FLAG)(D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL);
+			else if((buffers & FBT_STENCIL) != 0)
+				clearFlag = D3D11_CLEAR_STENCIL;
+			else
+				clearFlag = D3D11_CLEAR_DEPTH;
+
+			if(depthStencilView != nullptr)
+				mDevice->getImmediateContext()->ClearDepthStencilView(depthStencilView, clearFlag, depth, (UINT8)stencil);
+		}
+
+		BS_INC_RENDER_STAT(NumClears);
+	}
+
+	void D3D11RenderAPI::setRenderTarget(const SPtr<RenderTargetCore>& target, bool readOnlyDepthStencil)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		mActiveRenderTarget = target;
+
+		UINT32 maxRenderTargets = mCurrentCapabilities->getNumMultiRenderTargets();
+		ID3D11RenderTargetView** views = bs_newN<ID3D11RenderTargetView*>(maxRenderTargets);
+		memset(views, 0, sizeof(ID3D11RenderTargetView*) * maxRenderTargets);
+
+		ID3D11DepthStencilView* depthStencilView = nullptr;
+
+		if (target != nullptr)
+		{
+			target->getCustomAttribute("RTV", views);
+
+			if(readOnlyDepthStencil)
+				target->getCustomAttribute("RODSV", &depthStencilView);
+			else
+				target->getCustomAttribute("DSV", &depthStencilView);
+		}
+
+		// Bind render targets
+		mDevice->getImmediateContext()->OMSetRenderTargets(maxRenderTargets, views, depthStencilView);
+		if (mDevice->hasError())
+			BS_EXCEPT(RenderingAPIException, "Failed to setRenderTarget : " + mDevice->getErrorDescription());
+
+		bs_deleteN(views, maxRenderTargets);
+		applyViewport();
+
+		BS_INC_RENDER_STAT(NumRenderTargetChanges);
+	}
+
+	void D3D11RenderAPI::setClipPlanesImpl(const PlaneList& clipPlanes)
+	{
+		LOGWRN("This call will be ignored. DX11 uses shaders for setting clip planes.");
+	}
+
+	RenderAPICapabilities* D3D11RenderAPI::createRenderSystemCapabilities() const
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		RenderAPICapabilities* rsc = bs_new<RenderAPICapabilities>();
+
+		rsc->setDriverVersion(mDriverVersion);
+		rsc->setDeviceName(mActiveD3DDriver->getDriverDescription());
+		rsc->setRenderAPIName(getName());
+
+		rsc->setStencilBufferBitDepth(8);
+
+		rsc->setCapability(RSC_ANISOTROPY);
+		rsc->setCapability(RSC_AUTOMIPMAP);
+
+		// Cube map
+		rsc->setCapability(RSC_CUBEMAPPING);
+
+		// We always support compression, D3DX will decompress if device does not support
+		rsc->setCapability(RSC_TEXTURE_COMPRESSION);
+		rsc->setCapability(RSC_TEXTURE_COMPRESSION_DXT);
+		rsc->setCapability(RSC_TWO_SIDED_STENCIL);
+		rsc->setCapability(RSC_STENCIL_WRAP);
+		rsc->setCapability(RSC_HWOCCLUSION);
+		rsc->setCapability(RSC_HWOCCLUSION_ASYNCHRONOUS);
+
+		if(mFeatureLevel >= D3D_FEATURE_LEVEL_10_1)
+			rsc->setMaxBoundVertexBuffers(32);
+		else
+			rsc->setMaxBoundVertexBuffers(16);
+
+		if(mFeatureLevel >= D3D_FEATURE_LEVEL_10_0)
+		{
+			rsc->addShaderProfile("ps_4_0");
+			rsc->addShaderProfile("vs_4_0");
+			rsc->addShaderProfile("gs_4_0");
+
+			rsc->addGpuProgramProfile(GPP_FS_4_0, "ps_4_0");
+			rsc->addGpuProgramProfile(GPP_VS_4_0, "vs_4_0");
+			rsc->addGpuProgramProfile(GPP_GS_4_0, "gs_4_0");
+
+			rsc->setNumTextureUnits(GPT_FRAGMENT_PROGRAM, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT);
+			rsc->setNumTextureUnits(GPT_VERTEX_PROGRAM, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT);
+			rsc->setNumTextureUnits(GPT_GEOMETRY_PROGRAM, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT);
+
+			rsc->setNumCombinedTextureUnits(rsc->getNumTextureUnits(GPT_FRAGMENT_PROGRAM)
+				+ rsc->getNumTextureUnits(GPT_VERTEX_PROGRAM) + rsc->getNumTextureUnits(GPT_VERTEX_PROGRAM));
+
+			rsc->setNumGpuParamBlockBuffers(GPT_FRAGMENT_PROGRAM, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
+			rsc->setNumGpuParamBlockBuffers(GPT_VERTEX_PROGRAM, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
+			rsc->setNumGpuParamBlockBuffers(GPT_GEOMETRY_PROGRAM, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
+
+			rsc->setNumCombinedGpuParamBlockBuffers(rsc->getNumGpuParamBlockBuffers(GPT_FRAGMENT_PROGRAM)
+				+ rsc->getNumGpuParamBlockBuffers(GPT_VERTEX_PROGRAM) + rsc->getNumGpuParamBlockBuffers(GPT_VERTEX_PROGRAM));
+		}
+
+		if(mFeatureLevel >= D3D_FEATURE_LEVEL_10_1)
+		{
+			rsc->addShaderProfile("ps_4_1");
+			rsc->addShaderProfile("vs_4_1");
+			rsc->addShaderProfile("gs_4_1");
+
+			rsc->addGpuProgramProfile(GPP_FS_4_1, "ps_4_1");
+			rsc->addGpuProgramProfile(GPP_VS_4_1, "vs_4_1");
+			rsc->addGpuProgramProfile(GPP_GS_4_1, "gs_4_1");
+		}
+
+		if(mFeatureLevel >= D3D_FEATURE_LEVEL_11_0)
+		{
+			rsc->addShaderProfile("ps_5_0");
+			rsc->addShaderProfile("vs_5_0");
+			rsc->addShaderProfile("gs_5_0");
+			rsc->addShaderProfile("cs_5_0");
+			rsc->addShaderProfile("hs_5_0");
+			rsc->addShaderProfile("ds_5_0");
+
+			rsc->addGpuProgramProfile(GPP_FS_5_0, "ps_5_0");
+			rsc->addGpuProgramProfile(GPP_VS_5_0, "vs_5_0");
+			rsc->addGpuProgramProfile(GPP_GS_5_0, "gs_5_0");
+			rsc->addGpuProgramProfile(GPP_CS_5_0, "cs_5_0");
+			rsc->addGpuProgramProfile(GPP_HS_5_0, "hs_5_0");
+			rsc->addGpuProgramProfile(GPP_DS_5_0, "ds_5_0");
+
+			rsc->setNumTextureUnits(GPT_HULL_PROGRAM, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT);
+			rsc->setNumTextureUnits(GPT_DOMAIN_PROGRAM, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT);
+			rsc->setNumTextureUnits(GPT_COMPUTE_PROGRAM, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT);
+
+			rsc->setNumCombinedTextureUnits(rsc->getNumTextureUnits(GPT_FRAGMENT_PROGRAM)
+				+ rsc->getNumTextureUnits(GPT_VERTEX_PROGRAM) + rsc->getNumTextureUnits(GPT_VERTEX_PROGRAM)
+				+ rsc->getNumTextureUnits(GPT_HULL_PROGRAM) + rsc->getNumTextureUnits(GPT_DOMAIN_PROGRAM)
+				+ rsc->getNumTextureUnits(GPT_COMPUTE_PROGRAM));
+
+			rsc->setNumGpuParamBlockBuffers(GPT_HULL_PROGRAM, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
+			rsc->setNumGpuParamBlockBuffers(GPT_DOMAIN_PROGRAM, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
+			rsc->setNumGpuParamBlockBuffers(GPT_COMPUTE_PROGRAM, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
+
+			rsc->setNumCombinedGpuParamBlockBuffers(rsc->getNumGpuParamBlockBuffers(GPT_FRAGMENT_PROGRAM)
+				+ rsc->getNumGpuParamBlockBuffers(GPT_VERTEX_PROGRAM) + rsc->getNumGpuParamBlockBuffers(GPT_VERTEX_PROGRAM)
+				+ rsc->getNumGpuParamBlockBuffers(GPT_HULL_PROGRAM) + rsc->getNumGpuParamBlockBuffers(GPT_DOMAIN_PROGRAM)
+				+ rsc->getNumGpuParamBlockBuffers(GPT_COMPUTE_PROGRAM));
+
+			rsc->setCapability(RSC_SHADER_SUBROUTINE);
+		}
+
+		rsc->setCapability(RSC_USER_CLIP_PLANES);
+		rsc->setCapability(RSC_VERTEX_FORMAT_UBYTE4);
+
+		// Adapter details
+		const DXGI_ADAPTER_DESC& adapterID = mActiveD3DDriver->getAdapterIdentifier();
+
+		// Determine vendor
+		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);
+
+		rsc->setCapability(RSC_TEXTURE_3D);
+		rsc->setCapability(RSC_NON_POWER_OF_2_TEXTURES);
+		rsc->setCapability(RSC_HWRENDER_TO_TEXTURE);
+		rsc->setCapability(RSC_TEXTURE_FLOAT);
+
+		rsc->setNumMultiRenderTargets(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT);
+		rsc->setCapability(RSC_MRT_DIFFERENT_BIT_DEPTHS);
+
+		rsc->setCapability(RSC_POINT_SPRITES);
+		rsc->setCapability(RSC_POINT_EXTENDED_PARAMETERS);
+		rsc->setMaxPointSize(256);
+
+		rsc->setCapability(RSC_VERTEX_TEXTURE_FETCH);
+
+		rsc->setCapability(RSC_MIPMAP_LOD_BIAS);
+
+		rsc->setCapability(RSC_PERSTAGECONSTANT);
+
+		return rsc;
+	}
+
+	void D3D11RenderAPI::determineMultisampleSettings(UINT32 multisampleCount, DXGI_FORMAT format, DXGI_SAMPLE_DESC* outputSampleDesc)
+	{
+		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;
+
+		bool foundValid = false;
+		size_t origNumSamples = multisampleCount;
+		while (!foundValid)
+		{
+			// Deal with special cases
+			if (tryCSAA)
+			{
+				switch(multisampleCount)
+				{
+				case 8:
+					if (csaaMode == CSAA_Quality)
+					{
+						outputSampleDesc->Count = 8;
+						outputSampleDesc->Quality = 8;
+					}
+					else
+					{
+						outputSampleDesc->Count = 4;
+						outputSampleDesc->Quality = 8;
+					}
+					break;
+				case 16:
+					if (csaaMode == CSAA_Quality)
+					{
+						outputSampleDesc->Count = 8;
+						outputSampleDesc->Quality = 16;
+					}
+					else
+					{
+						outputSampleDesc->Count = 4;
+						outputSampleDesc->Quality = 16;
+					}
+					break;
+				}
+			}
+			else // !CSAA
+			{
+				outputSampleDesc->Count = multisampleCount == 0 ? 1 : multisampleCount;
+				outputSampleDesc->Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN;
+			}
+
+
+			HRESULT hr;
+			UINT outQuality;
+			hr = mDevice->getD3D11Device()->CheckMultisampleQualityLevels(format, outputSampleDesc->Count, &outQuality);
+
+			if (SUCCEEDED(hr) && (!tryCSAA || outQuality > outputSampleDesc->Quality))
+			{
+				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 = static_cast<UINT32>(origNumSamples);
+				}
+				else
+				{
+					// Drop samples
+					multisampleCount--;
+
+					if (multisampleCount == 1)
+					{
+						// Ran out of options, no multisampling
+						multisampleCount = 0;
+						foundValid = true;
+					}
+				}
+			}
+		} 
+	}
+
+	void D3D11RenderAPI::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;
+	}
+
+	const RenderAPIInfo& D3D11RenderAPI::getAPIInfo() const
+	{
+		static RenderAPIInfo info(0.0f, 0.0f, 0.0f, 1.0f, VET_COLOR_ABGR, false, true, false);
+
+		return info;
+	}
+
+	GpuParamBlockDesc D3D11RenderAPI::generateParamBlockDesc(const String& name, Vector<GpuParamDataDesc>& params)
+	{
+		GpuParamBlockDesc block;
+		block.blockSize = 0;
+		block.isShareable = true;
+		block.name = name;
+		block.slot = 0;
+
+		for (auto& param : params)
+		{
+			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[param.type];
+			UINT32 size = typeInfo.size / 4;
+
+			if (param.arraySize > 1)
+			{
+				// Arrays perform no packing and their elements are always padded and aligned to four component vectors
+				UINT32 alignOffset = size % typeInfo.baseTypeSize;
+				if (alignOffset != 0)
+				{
+					UINT32 padding = (typeInfo.baseTypeSize - alignOffset);
+					size += padding;
+				}
+
+				alignOffset = block.blockSize % typeInfo.baseTypeSize;
+				if (alignOffset != 0)
+				{
+					UINT32 padding = (typeInfo.baseTypeSize - alignOffset);
+					block.blockSize += padding;
+				}
+
+				param.elementSize = size;
+				param.arrayElementStride = size;
+				param.cpuMemOffset = block.blockSize;
+				param.gpuMemOffset = 0;
+
+				block.blockSize += size * param.arraySize;
+			}
+			else
+			{
+				// Pack everything as tightly as possible as long as the data doesn't cross 16 byte boundary
+				UINT32 alignOffset = block.blockSize % 4;
+				if (alignOffset != 0 && size > (4 - alignOffset))
+				{
+					UINT32 padding = (4 - alignOffset);
+					block.blockSize += padding;
+				}
+
+				param.elementSize = size;
+				param.arrayElementStride = size;
+				param.cpuMemOffset = block.blockSize;
+				param.gpuMemOffset = 0;
+
+				block.blockSize += size;
+			}
+
+			param.paramBlockSlot = 0;
+		}
+
+		// Constant buffer size must always be a multiple of 16
+		if (block.blockSize % 4 != 0)
+			block.blockSize += (4 - (block.blockSize % 4));
+
+		return block;
+	}
+
+	/************************************************************************/
+	/* 								PRIVATE		                     		*/
+	/************************************************************************/
+
+	void D3D11RenderAPI::applyInputLayout()
+	{
+		if(mActiveVertexDeclaration == nullptr)
+		{
+			LOGWRN("Cannot apply input layout without a vertex declaration. Set vertex declaration before calling this method.");
+			return;
+		}
+
+		if(mActiveVertexShader == nullptr)
+		{
+			LOGWRN("Cannot apply input layout without a vertex shader. Set vertex shader before calling this method.");
+			return;
+		}
+
+		ID3D11InputLayout* ia = mIAManager->retrieveInputLayout(mActiveVertexShader->getInputDeclaration(), mActiveVertexDeclaration, *mActiveVertexShader);
+
+		mDevice->getImmediateContext()->IASetInputLayout(ia);
+	}
 }

+ 2 - 29
Source/BansheeD3D9RenderAPI/Include/BsD3D9RenderAPI.h

@@ -155,35 +155,8 @@ namespace BansheeEngine
 		 */
 		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::getAPIInfo */
+		const RenderAPIInfo& getAPIInfo() const override;
 
 		/**
 		 * @copydoc RenderAPICore::generateParamBlockDesc()

+ 2306 - 2328
Source/BansheeD3D9RenderAPI/Source/BsD3D9RenderAPI.cpp

@@ -1,2329 +1,2307 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#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::dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY, UINT32 numGroupsZ)
-	{
-		// Not supported on DX9
-	}
-
-	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, UINT8 targetMask)
-	{
-		if(mActiveRenderTarget == nullptr)
-			return;
-
-		if (targetMask != 0xFF)
-			LOGWRN("DirectX 9 ignoring target mask for clearRenderTarget(). Only 0xFF is supported.");
-
-		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, UINT8 targetMask)
-	{
-		if (targetMask != 0xFF)
-			LOGWRN("DirectX 9 ignoring target mask for clearRenderTarget(). Only 0xFF is supported.");
-
-		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.");
-	}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#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::dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY, UINT32 numGroupsZ)
+	{
+		// Not supported on DX9
+	}
+
+	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, UINT8 targetMask)
+	{
+		if(mActiveRenderTarget == nullptr)
+			return;
+
+		if (targetMask != 0xFF)
+			LOGWRN("DirectX 9 ignoring target mask for clearRenderTarget(). Only 0xFF is supported.");
+
+		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, UINT8 targetMask)
+	{
+		if (targetMask != 0xFF)
+			LOGWRN("DirectX 9 ignoring target mask for clearRenderTarget(). Only 0xFF is supported.");
+
+		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                    		*/
+	/************************************************************************/
+
+	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;
+	}
+
+	const RenderAPIInfo& D3D9RenderAPI::getAPIInfo() const
+	{
+		static RenderAPIInfo info(-0.5f, 0.5f, 0.0f, 1.0f, VET_COLOR_ARGB, true, true, false);
+
+		return info;
+	}
+
+	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.");
+	}
 }

+ 1105 - 1104
Source/BansheeEditor/Source/BsGizmoManager.cpp

@@ -1,1105 +1,1106 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsGizmoManager.h"
-#include "BsMesh.h"
-#include "BsAABox.h"
-#include "BsSphere.h"
-#include "BsVertexDataDesc.h"
-#include "BsShapeMeshes3D.h"
-#include "BsMeshHeap.h"
-#include "BsCCamera.h"
-#include "BsSpriteTexture.h"
-#include "BsCoreThread.h"
-#include "BsBuiltinEditorResources.h"
-#include "BsMaterial.h"
-#include "BsGpuParams.h"
-#include "BsRenderAPI.h"
-#include "BsCoreRenderer.h"
-#include "BsRendererUtility.h"
-#include "BsTransientMesh.h"
-#include "BsRendererManager.h"
-#include "BsDrawHelper.h"
-
-using namespace std::placeholders;
-
-namespace BansheeEngine
-{
-	const UINT32 GizmoManager::VERTEX_BUFFER_GROWTH = 4096;
-	const UINT32 GizmoManager::INDEX_BUFFER_GROWTH = 4096 * 2;
-	const UINT32 GizmoManager::SPHERE_QUALITY = 1;
-	const UINT32 GizmoManager::WIRE_SPHERE_QUALITY = 10;
-	const float GizmoManager::MAX_ICON_RANGE = 500.0f;
-	const UINT32 GizmoManager::OPTIMAL_ICON_SIZE = 64;
-	const float GizmoManager::ICON_TEXEL_WORLD_SIZE = 0.05f;
-
-	GizmoManager::GizmoManager()
-		: mPickable(false), mCurrentIdx(0), mTransformDirty(false), mColorDirty(false), mDrawHelper(nullptr)
-		, mPickingDrawHelper(nullptr), mCore(nullptr)
-		
-	{
-		mTransform = Matrix4::IDENTITY;
-		mDrawHelper = bs_new<DrawHelper>();
-		mPickingDrawHelper = bs_new<DrawHelper>();
-
-		mIconVertexDesc = bs_shared_ptr_new<VertexDataDesc>();
-		mIconVertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
-		mIconVertexDesc->addVertElem(VET_FLOAT2, VES_TEXCOORD);
-		mIconVertexDesc->addVertElem(VET_COLOR, VES_COLOR, 0);
-		mIconVertexDesc->addVertElem(VET_COLOR, VES_COLOR, 1);
-
-		mIconMeshHeap = MeshHeap::create(VERTEX_BUFFER_GROWTH, INDEX_BUFFER_GROWTH, mIconVertexDesc);
-
-		HMaterial solidMaterial = BuiltinEditorResources::instance().createSolidGizmoMat();
-		HMaterial wireMaterial = BuiltinEditorResources::instance().createWireGizmoMat();
-		HMaterial iconMaterial = BuiltinEditorResources::instance().createIconGizmoMat();
-		HMaterial textMaterial = BuiltinEditorResources::instance().createTextGizmoMat();
-		HMaterial pickingMaterial = BuiltinEditorResources::instance().createGizmoPickingMat();
-		HMaterial alphaPickingMaterial = BuiltinEditorResources::instance().createAlphaGizmoPickingMat();
-
-		CoreInitData initData;
-
-		initData.solidMat = solidMaterial->getCore();
-		initData.wireMat = wireMaterial->getCore();
-		initData.iconMat = iconMaterial->getCore();
-		initData.textMat = textMaterial->getCore();
-		initData.pickingMat = pickingMaterial->getCore();
-		initData.alphaPickingMat = alphaPickingMaterial->getCore();
-
-		mCore.store(bs_new<GizmoManagerCore>(GizmoManagerCore::PrivatelyConstuct()), std::memory_order_release);
-
-		gCoreAccessor().queueCommand(std::bind(&GizmoManager::initializeCore, this, initData));
-	}
-
-	GizmoManager::~GizmoManager()
-	{
-		mDrawHelper->clearMeshes(mActiveMeshes);
-		mActiveMeshes.clear();
-
-		if (mIconMesh != nullptr)
-			mIconMeshHeap->dealloc(mIconMesh);
-
-		bs_delete(mDrawHelper);
-		bs_delete(mPickingDrawHelper);
-
-		gCoreAccessor().queueCommand(std::bind(&GizmoManager::destroyCore, this, mCore.load(std::memory_order_relaxed)));
-	}
-
-	void GizmoManager::initializeCore(const CoreInitData& initData)
-	{
-		mCore.load(std::memory_order_acquire)->initialize(initData);
-	}
-
-	void GizmoManager::destroyCore(GizmoManagerCore* core)
-	{
-		bs_delete(core);
-	}
-
-	void GizmoManager::startGizmo(const HSceneObject& gizmoParent)
-	{
-		mActiveSO = gizmoParent;
-
-		if(mTransformDirty)
-		{
-			mTransform = Matrix4::IDENTITY;
-			mTransformDirty = false;
-		}
-
-		if(mColorDirty)
-		{
-			mColor = Color();
-			mColorDirty = false;
-		}
-	}
-
-	void GizmoManager::endGizmo()
-	{
-		mActiveSO = nullptr;
-	}
-
-	void GizmoManager::setColor(const Color& color)
-	{
-		mDrawHelper->setColor(color);
-		mColor = color;
-
-		mColorDirty = true;
-	}
-
-	void GizmoManager::setTransform(const Matrix4& transform)
-	{
-		mDrawHelper->setTransform(transform);
-		mTransform = transform;
-
-		mTransformDirty = true;
-	}
-
-	void GizmoManager::drawCube(const Vector3& position, const Vector3& extents)
-	{
-		mSolidCubeData.push_back(CubeData());
-		CubeData& cubeData = mSolidCubeData.back();
-
-		cubeData.idx = mCurrentIdx++;
-		cubeData.position = position;
-		cubeData.extents = extents;
-		cubeData.color = mColor;
-		cubeData.transform = mTransform;
-		cubeData.sceneObject = mActiveSO;
-		cubeData.pickable = mPickable;
-
-		mDrawHelper->cube(position, extents);
-		mIdxToSceneObjectMap[cubeData.idx] = mActiveSO;
-	}
-
-	void GizmoManager::drawSphere(const Vector3& position, float radius)
-	{
-		mSolidSphereData.push_back(SphereData());
-		SphereData& sphereData = mSolidSphereData.back();
-
-		sphereData.idx = mCurrentIdx++;
-		sphereData.position = position;
-		sphereData.radius = radius;
-		sphereData.color = mColor;
-		sphereData.transform = mTransform;
-		sphereData.sceneObject = mActiveSO;
-		sphereData.pickable = mPickable;
-
-		mDrawHelper->sphere(position, radius);
-		mIdxToSceneObjectMap[sphereData.idx] = mActiveSO;
-	}
-
-	void GizmoManager::drawWireCube(const Vector3& position, const Vector3& extents)
-	{
-		mWireCubeData.push_back(CubeData());
-		CubeData& cubeData = mWireCubeData.back();
-
-		cubeData.idx = mCurrentIdx++;
-		cubeData.position = position;
-		cubeData.extents = extents;
-		cubeData.color = mColor;
-		cubeData.transform = mTransform;
-		cubeData.sceneObject = mActiveSO;
-		cubeData.pickable = mPickable;
-
-		mDrawHelper->wireCube(position, extents);
-		mIdxToSceneObjectMap[cubeData.idx] = mActiveSO;
-	}
-
-	void GizmoManager::drawWireSphere(const Vector3& position, float radius)
-	{
-		mWireSphereData.push_back(SphereData());
-		SphereData& sphereData = mWireSphereData.back();
-
-		sphereData.idx = mCurrentIdx++;
-		sphereData.position = position;
-		sphereData.radius = radius;
-		sphereData.color = mColor;
-		sphereData.transform = mTransform;
-		sphereData.sceneObject = mActiveSO;
-		sphereData.pickable = mPickable;
-
-		mDrawHelper->wireSphere(position, radius);
-		mIdxToSceneObjectMap[sphereData.idx] = mActiveSO;
-	}
-
-	void GizmoManager::drawWireCapsule(const Vector3& position, float height, float radius)
-	{
-		float halfHeight = height * 0.5f;
-
-		// Draw capsule sides
-		Vector3 sideNegXBottom = position + Vector3(-radius, -halfHeight, 0.0f);
-		Vector3 sideNegXTop = position + Vector3(-radius, halfHeight, 0.0f);
-
-		Vector3 sidePosXBottom = position + Vector3(radius, -halfHeight, 0.0f);
-		Vector3 sidePosXTop = position + Vector3(radius, halfHeight, 0.0f);
-
-		Vector3 sideNegZBottom = position + Vector3(0.0f, -halfHeight, -radius);
-		Vector3 sideNegZTop = position + Vector3(0.0f, halfHeight, -radius);
-
-		Vector3 sidePosZBottom = position + Vector3(0.0f, -halfHeight, radius);
-		Vector3 sidePosZTop = position + Vector3(0.0f, halfHeight, radius);
-
-		drawLine(sideNegXBottom, sideNegXTop);
-		drawLine(sidePosXBottom, sidePosXTop);
-		drawLine(sideNegZBottom, sideNegZTop);
-		drawLine(sidePosZBottom, sidePosZTop);
-
-		// Draw capsule caps
-		Vector3 topHemisphere = position + Vector3(0.0f, halfHeight, 0.0f);
-		Vector3 botHemisphere = position + Vector3(0.0f, -halfHeight, 0.0f);
-
-		drawWireArc(topHemisphere, Vector3::UNIT_X, radius, Degree(0.0f), Degree(180.0f));
-		drawWireArc(topHemisphere, Vector3::UNIT_Z, radius, Degree(0.0f), Degree(180.0f));
-
-		drawWireArc(botHemisphere, Vector3::UNIT_X, radius, Degree(180.0f), Degree(180.0f));
-		drawWireArc(botHemisphere, Vector3::UNIT_Z, radius, Degree(180.0f), Degree(180.0f));
-	}
-
-	void GizmoManager::drawLine(const Vector3& start, const Vector3& end)
-	{
-		mLineData.push_back(LineData());
-		LineData& lineData = mLineData.back();
-
-		lineData.idx = mCurrentIdx++;
-		lineData.start = start;
-		lineData.end = end;
-		lineData.color = mColor;
-		lineData.transform = mTransform;
-		lineData.sceneObject = mActiveSO;
-		lineData.pickable = mPickable;
-
-		mDrawHelper->line(start, end);
-		mIdxToSceneObjectMap[lineData.idx] = mActiveSO;
-	}
-
-	void GizmoManager::drawLineList(const Vector<Vector3>& linePoints)
-	{
-		mLineListData.push_back(LineListData());
-		LineListData& lineListData = mLineListData.back();
-
-		lineListData.idx = mCurrentIdx++;
-		lineListData.linePoints = linePoints;
-		lineListData.color = mColor;
-		lineListData.transform = mTransform;
-		lineListData.sceneObject = mActiveSO;
-		lineListData.pickable = mPickable;
-
-		mDrawHelper->lineList(linePoints);
-		mIdxToSceneObjectMap[lineListData.idx] = mActiveSO;
-	}
-
-	void GizmoManager::drawWireDisc(const Vector3& position, const Vector3& normal, float radius)
-	{
-		mWireDiscData.push_back(WireDiscData());
-		WireDiscData& wireDiscData = mWireDiscData.back();
-
-		wireDiscData.idx = mCurrentIdx++;
-		wireDiscData.position = position;
-		wireDiscData.normal = normal;
-		wireDiscData.radius = radius;
-		wireDiscData.color = mColor;
-		wireDiscData.transform = mTransform;
-		wireDiscData.sceneObject = mActiveSO;
-		wireDiscData.pickable = mPickable;
-
-		mDrawHelper->wireDisc(position, normal, radius);
-		mIdxToSceneObjectMap[wireDiscData.idx] = mActiveSO;
-	}
-
-	void GizmoManager::drawWireArc(const Vector3& position, const Vector3& normal, float radius, 
-		Degree startAngle, Degree amountAngle)
-	{
-		mWireArcData.push_back(WireArcData());
-		WireArcData& wireArcData = mWireArcData.back();
-
-		wireArcData.idx = mCurrentIdx++;
-		wireArcData.position = position;
-		wireArcData.normal = normal;
-		wireArcData.radius = radius;
-		wireArcData.startAngle = startAngle;
-		wireArcData.amountAngle = amountAngle;
-		wireArcData.color = mColor;
-		wireArcData.transform = mTransform;
-		wireArcData.sceneObject = mActiveSO;
-		wireArcData.pickable = mPickable;
-
-		mDrawHelper->wireArc(position, normal, radius, startAngle, amountAngle);
-		mIdxToSceneObjectMap[wireArcData.idx] = mActiveSO;
-	}
-
-	void GizmoManager::drawFrustum(const Vector3& position, float aspect, Degree FOV, float near, float far)
-	{
-		mFrustumData.push_back(FrustumData());
-		FrustumData& frustumData = mFrustumData.back();
-
-		frustumData.idx = mCurrentIdx++;
-		frustumData.position = position;
-		frustumData.aspect = aspect;
-		frustumData.FOV = FOV;
-		frustumData.near = near;
-		frustumData.far = far;
-		frustumData.color = mColor;
-		frustumData.transform = mTransform;
-		frustumData.sceneObject = mActiveSO;
-		frustumData.pickable = mPickable;
-
-		mDrawHelper->frustum(position, aspect, FOV, near, far);
-		mIdxToSceneObjectMap[frustumData.idx] = mActiveSO;
-	}
-
-	void GizmoManager::drawIcon(Vector3 position, HSpriteTexture image, bool fixedScale)
-	{
-		mIconData.push_back(IconData());
-		IconData& iconData = mIconData.back();
-
-		iconData.idx = mCurrentIdx++;
-		iconData.position = position;
-		iconData.texture = image;
-		iconData.fixedScale = fixedScale;
-		iconData.color = mColor;
-		iconData.transform = mTransform;
-		iconData.sceneObject = mActiveSO;
-		iconData.pickable = mPickable;
-
-		mIdxToSceneObjectMap[iconData.idx] = mActiveSO;
-	}
-
-	void GizmoManager::drawText(const Vector3& position, const WString& text, const HFont& font, UINT32 fontSize)
-	{
-		HFont myFont = font;
-		if (myFont == nullptr)
-			myFont = BuiltinEditorResources::instance().getDefaultFont();
-
-		mTextData.push_back(TextData());
-		TextData& textData = mTextData.back();
-
-		textData.idx = mCurrentIdx++;
-		textData.position = position;
-		textData.text = text;
-		textData.font = myFont;
-		textData.fontSize = fontSize;
-		textData.color = mColor;
-		textData.transform = mTransform;
-		textData.sceneObject = mActiveSO;
-		textData.pickable = mPickable;
-
-		mDrawHelper->text(position, text, myFont, fontSize);
-		mIdxToSceneObjectMap[textData.idx] = mActiveSO;
-	}
-
-	void GizmoManager::update(const CameraPtr& camera)
-	{
-		mDrawHelper->clearMeshes(mActiveMeshes);
-		mActiveMeshes.clear();
-
-		if (mIconMesh != nullptr)
-			mIconMeshHeap->dealloc(mIconMesh);
-
-		IconRenderDataVecPtr iconRenderData;
-
-		mDrawHelper->buildMeshes(DrawHelper::SortType::BackToFront, camera->getPosition());
-		mActiveMeshes = mDrawHelper->getMeshes();
-
-		Vector<GizmoManagerCore::MeshData> proxyData;
-		for (auto& meshData : mActiveMeshes)
-		{
-			SPtr<TextureCore> tex;
-			if (meshData.texture.isLoaded())
-				tex = meshData.texture->getCore();
-
-			if (meshData.type == DrawHelper::MeshType::Solid)
-			{
-				proxyData.push_back(GizmoManagerCore::MeshData(
-					meshData.mesh->getCore(), tex, GizmoManagerCore::MeshType::Solid));
-			}
-			else if (meshData.type == DrawHelper::MeshType::Wire)
-			{
-				proxyData.push_back(GizmoManagerCore::MeshData(
-					meshData.mesh->getCore(), tex, GizmoManagerCore::MeshType::Wire));
-			}
-			else // Text
-			{
-				proxyData.push_back(GizmoManagerCore::MeshData(
-					meshData.mesh->getCore(), tex, GizmoManagerCore::MeshType::Text));
-			}
-		}
-
-		mIconMesh = buildIconMesh(camera, mIconData, false, iconRenderData);
-		SPtr<MeshCoreBase> iconMesh = mIconMesh->getCore();
-
-		GizmoManagerCore* core = mCore.load(std::memory_order_relaxed);
-
-		gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::updateData, core, camera->getCore(),
-			proxyData, iconMesh, iconRenderData));
-	}
-
-	void GizmoManager::renderForPicking(const CameraPtr& camera, std::function<Color(UINT32)> idxToColorCallback)
-	{
-		Vector<IconData> iconData;
-		IconRenderDataVecPtr iconRenderData;
-
-		mPickingDrawHelper->clear();
-
-		for (auto& cubeDataEntry : mSolidCubeData)
-		{
-			if (!cubeDataEntry.pickable)
-				continue;
-
-			mPickingDrawHelper->setColor(idxToColorCallback(cubeDataEntry.idx));
-			mPickingDrawHelper->setTransform(cubeDataEntry.transform);
-
-			mPickingDrawHelper->cube(cubeDataEntry.position, cubeDataEntry.extents);
-		}
-
-		for (auto& cubeDataEntry : mWireCubeData)
-		{
-			if (!cubeDataEntry.pickable)
-				continue;
-
-			mPickingDrawHelper->setColor(idxToColorCallback(cubeDataEntry.idx));
-			mPickingDrawHelper->setTransform(cubeDataEntry.transform);
-
-			mPickingDrawHelper->wireCube(cubeDataEntry.position, cubeDataEntry.extents);
-		}
-
-		for (auto& sphereDataEntry : mSolidSphereData)
-		{
-			if (!sphereDataEntry.pickable)
-				continue;
-
-			mPickingDrawHelper->setColor(idxToColorCallback(sphereDataEntry.idx));
-			mPickingDrawHelper->setTransform(sphereDataEntry.transform);
-
-			mPickingDrawHelper->sphere(sphereDataEntry.position, sphereDataEntry.radius);
-		}
-
-		for (auto& sphereDataEntry : mWireSphereData)
-		{
-			if (!sphereDataEntry.pickable)
-				continue;
-
-			mPickingDrawHelper->setColor(idxToColorCallback(sphereDataEntry.idx));
-			mPickingDrawHelper->setTransform(sphereDataEntry.transform);
-
-			mPickingDrawHelper->wireSphere(sphereDataEntry.position, sphereDataEntry.radius);
-		}
-
-		for (auto& lineDataEntry : mLineData)
-		{
-			if (!lineDataEntry.pickable)
-				continue;
-
-			mPickingDrawHelper->setColor(idxToColorCallback(lineDataEntry.idx));
-			mPickingDrawHelper->setTransform(lineDataEntry.transform);
-
-			mPickingDrawHelper->line(lineDataEntry.start, lineDataEntry.end);
-		}
-
-		for (auto& lineListDataEntry : mLineListData)
-		{
-			if (!lineListDataEntry.pickable)
-				continue;
-
-			mPickingDrawHelper->setColor(idxToColorCallback(lineListDataEntry.idx));
-			mPickingDrawHelper->setTransform(lineListDataEntry.transform);
-
-			mPickingDrawHelper->lineList(lineListDataEntry.linePoints);
-		}
-
-		for (auto& wireDiscDataEntry : mWireDiscData)
-		{
-			if (!wireDiscDataEntry.pickable)
-				continue;
-
-			mPickingDrawHelper->setColor(idxToColorCallback(wireDiscDataEntry.idx));
-			mPickingDrawHelper->setTransform(wireDiscDataEntry.transform);
-
-			mPickingDrawHelper->wireDisc(wireDiscDataEntry.position, wireDiscDataEntry.normal, wireDiscDataEntry.radius);
-		}
-
-		for (auto& wireArcDataEntry : mWireArcData)
-		{
-			if (!wireArcDataEntry.pickable)
-				continue;
-
-			mPickingDrawHelper->setColor(idxToColorCallback(wireArcDataEntry.idx));
-			mPickingDrawHelper->setTransform(wireArcDataEntry.transform);
-
-			mPickingDrawHelper->wireArc(wireArcDataEntry.position, wireArcDataEntry.normal, wireArcDataEntry.radius, 
-				wireArcDataEntry.startAngle, wireArcDataEntry.amountAngle);
-		}
-
-		for (auto& frustumDataEntry : mFrustumData)
-		{
-			if (!frustumDataEntry.pickable)
-				continue;
-
-			mPickingDrawHelper->setColor(idxToColorCallback(frustumDataEntry.idx));
-			mPickingDrawHelper->setTransform(frustumDataEntry.transform);
-
-			mPickingDrawHelper->frustum(frustumDataEntry.position, frustumDataEntry.aspect, frustumDataEntry.FOV, 
-				frustumDataEntry.near, frustumDataEntry.far);
-		}
-
-		for (auto& textDataEntry : mTextData)
-		{
-			if (!textDataEntry.pickable)
-				continue;
-
-			mPickingDrawHelper->setColor(idxToColorCallback(textDataEntry.idx));
-			mPickingDrawHelper->setTransform(textDataEntry.transform);
-
-			mPickingDrawHelper->text(textDataEntry.position, textDataEntry.text, textDataEntry.font,
-				textDataEntry.fontSize);
-		}
-
-		for (auto& iconDataEntry : mIconData)
-		{
-			if (!iconDataEntry.pickable)
-				continue;
-
-			iconData.push_back(iconDataEntry);
-			iconData.back().color = idxToColorCallback(iconDataEntry.idx);
-		}
-
-		mPickingDrawHelper->buildMeshes(DrawHelper::SortType::BackToFront, camera->getPosition());
-		const Vector<DrawHelper::ShapeMeshData>& meshes = mPickingDrawHelper->getMeshes();
-
-		TransientMeshPtr iconMesh = buildIconMesh(camera, iconData, true, iconRenderData);
-
-		// Note: This must be rendered while Scene view is being rendered
-		Matrix4 viewMat = camera->getViewMatrix();
-		Matrix4 projMat = camera->getProjectionMatrixRS();
-		ViewportPtr viewport = camera->getViewport();
-
-		GizmoManagerCore* core = mCore.load(std::memory_order_relaxed);
-
-		for (auto& meshData : meshes)
-		{
-			SPtr<TextureCore> tex;
-			if (meshData.texture.isLoaded())
-				tex = meshData.texture->getCore();
-
-			if(meshData.type == DrawHelper::MeshType::Text)
-			{
-				gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::renderGizmos, core, viewMat, projMat,
-					camera->getForward(), meshData.mesh->getCore(), tex, GizmoMaterial::PickingAlpha));
-			}
-			else
-			{
-				gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::renderGizmos, core, viewMat, projMat,
-					camera->getForward(), meshData.mesh->getCore(), tex, GizmoMaterial::Picking));
-			}
-		}
-
-		Rect2I screenArea = camera->getViewport()->getArea();
-
-		gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::renderIconGizmos,
-			core, screenArea, iconMesh->getCore(), iconRenderData, true));
-
-		mPickingDrawHelper->clearMeshes(meshes);
-		mIconMeshHeap->dealloc(iconMesh);
-	}
-
-	void GizmoManager::clearGizmos()
-	{
-		mSolidCubeData.clear();
-		mWireCubeData.clear();
-		mSolidSphereData.clear();
-		mWireSphereData.clear();
-		mLineData.clear();
-		mLineListData.clear();
-		mWireDiscData.clear();
-		mWireArcData.clear();
-		mFrustumData.clear();
-		mTextData.clear();
-		mIconData.clear();
-		mIdxToSceneObjectMap.clear();
-
-		mDrawHelper->clear();
-
-		mCurrentIdx = 0;
-	}
-
-	void GizmoManager::clearRenderData()
-	{
-		mDrawHelper->clearMeshes(mActiveMeshes);
-		mActiveMeshes.clear();
-
-		if (mIconMesh != nullptr)
-			mIconMeshHeap->dealloc(mIconMesh);
-
-		mIconMesh = nullptr;
-
-		GizmoManagerCore* core = mCore.load(std::memory_order_relaxed);
-		IconRenderDataVecPtr iconRenderData = bs_shared_ptr_new<IconRenderDataVec>();
-		
-		gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::updateData, core, 
-			nullptr, Vector<GizmoManagerCore::MeshData>(), nullptr, iconRenderData));
-	}
-
-	TransientMeshPtr GizmoManager::buildIconMesh(const CameraPtr& camera, const Vector<IconData>& iconData,
-		bool forPicking, GizmoManager::IconRenderDataVecPtr& iconRenderData)
-	{
-		mSortedIconData.clear();
-		
-		if (iconData.size() > mSortedIconData.size())
-			mSortedIconData.resize(iconData.size());
-
-		UINT32 i = 0;
-		for (auto& iconEntry : iconData)
-		{
-			Vector3 viewPoint = camera->worldToViewPoint(iconEntry.position);
-
-			float distance = -viewPoint.z;
-			if (distance < camera->getNearClipDistance()) // Ignore behind clip plane
-				continue;
-
-			if (distance > MAX_ICON_RANGE) // Ignore too far away
-				continue;
-
-			if (!iconEntry.texture.isLoaded()) // Ignore missing texture
-				continue;
-
-			if (forPicking && !iconEntry.pickable)
-				continue;
-
-			SortedIconData& sortedIconData = mSortedIconData[i];
-			sortedIconData.iconIdx = i;
-			sortedIconData.distance = distance;
-			sortedIconData.screenPosition = camera->viewToScreenPoint(viewPoint);
-
-			i++;
-		}
-
-		UINT32 actualNumIcons = i;
-
-		// Sort back to front first, then by texture
-		std::sort(mSortedIconData.begin(), mSortedIconData.begin() + actualNumIcons, 
-			[&](const SortedIconData& a, const SortedIconData& b)
-		{
-			if (a.distance == b.distance)
-			{
-				HTexture texA = iconData[a.iconIdx].texture->getTexture();
-				HTexture texB = iconData[b.iconIdx].texture->getTexture();
-
-				if (texA == texB)
-					return a.iconIdx < b.iconIdx;
-
-				return texA->getInternalID() < texB->getInternalID();
-			}
-			else
-				return a.distance > b.distance;
-		});
-
-		MeshDataPtr meshData = bs_shared_ptr_new<MeshData>(actualNumIcons * 4, actualNumIcons * 6, mIconVertexDesc);
-
-		auto positionIter = meshData->getVec3DataIter(VES_POSITION);
-		auto texcoordIter = meshData->getVec2DataIter(VES_TEXCOORD);
-		auto normalColorIter = meshData->getDWORDDataIter(VES_COLOR, 0);
-		auto fadedColorIter = meshData->getDWORDDataIter(VES_COLOR, 1);
-
-		UINT32* indices = meshData->getIndices32();
-
-		float cameraScale = 1.0f;
-		if (camera->getProjectionType() == PT_ORTHOGRAPHIC)
-			cameraScale = camera->getViewport()->getHeight() / camera->getOrthoWindowHeight();
-		else
-		{
-			Radian vertFOV(Math::tan(camera->getHorzFOV() * 0.5f));
-			cameraScale = (camera->getViewport()->getHeight() * 0.5f) / vertFOV.valueRadians();
-		}
-
-		iconRenderData = bs_shared_ptr_new<IconRenderDataVec>();
-		UINT32 lastTextureIdx = std::numeric_limits<UINT32>::max();
-		HTexture curTexture;
-
-		// Note: This assumes the meshes will be rendered using the same camera
-		// properties as when they are created
-		for (i = 0; i < actualNumIcons; i++)
-		{
-			SortedIconData& sortedIconData = mSortedIconData[i];
-			const IconData& curIconData = iconData[sortedIconData.iconIdx];
-
-			HTexture atlasTexture = curIconData.texture->getTexture();
-
-			if (curTexture != atlasTexture)
-			{
-				UINT32 numIconsPerTexture = i - lastTextureIdx;
-				if (numIconsPerTexture > 0)
-				{
-					iconRenderData->push_back(IconRenderData());
-					IconRenderData& renderData = iconRenderData->back();
-					renderData.count = numIconsPerTexture;
-					renderData.texture = atlasTexture->getCore();
-				}
-
-				lastTextureIdx = i;
-				curTexture = atlasTexture;
-			}
-
-			UINT32 iconWidth = curIconData.texture->getWidth();
-			UINT32 iconHeight = curIconData.texture->getHeight();
-
-			limitIconSize(iconWidth, iconHeight);
-
-			Vector3 position((float)sortedIconData.screenPosition.x, (float)sortedIconData.screenPosition.y, -sortedIconData.distance);
-			Vector3 projPosition = camera->projectPoint(position);
-			position.z = projPosition.z;
-
-			float halfWidth = iconWidth * 0.5f;
-			float halfHeight = iconHeight * 0.5f;
-
-			if (!curIconData.fixedScale)
-			{
-				float iconScale = 1.0f;
-				if (camera->getProjectionType() == PT_ORTHOGRAPHIC)
-					iconScale = cameraScale * ICON_TEXEL_WORLD_SIZE;
-				else
-					iconScale = (cameraScale * ICON_TEXEL_WORLD_SIZE) / sortedIconData.distance;
-
-				halfWidth *= iconScale;
-				halfHeight *= iconScale;
-			}
-
-			Color normalColor, fadedColor;
-			calculateIconColors(curIconData.color, camera, (UINT32)(halfHeight * 2.0f), curIconData.fixedScale, normalColor, fadedColor);
-
-			if (forPicking)
-			{
-				normalColor = curIconData.color;
-				fadedColor = curIconData.color;
-			}
-
-			Vector3 positions[4];
-			positions[0] = position + Vector3(-halfWidth, -halfHeight, 0.0f);
-			positions[1] = position + Vector3(halfWidth, -halfHeight, 0.0f);
-			positions[2] = position + Vector3(halfWidth, halfHeight, 0.0f);
-			positions[3] = position + Vector3(-halfWidth, halfHeight, 0.0f);
-
-			Vector2 uvs[4];
-			uvs[0] = curIconData.texture->transformUV(Vector2(0.0f, 0.0f));
-			uvs[1] = curIconData.texture->transformUV(Vector2(1.0f, 0.0f));
-			uvs[2] = curIconData.texture->transformUV(Vector2(1.0f, 1.0f));
-			uvs[3] = curIconData.texture->transformUV(Vector2(0.0f, 1.0f));
-
-			for (UINT32 j = 0; j < 4; j++)
-			{
-				positionIter.addValue(positions[j]);
-				texcoordIter.addValue(uvs[j]);
-				normalColorIter.addValue(normalColor.getAsRGBA());
-				fadedColorIter.addValue(fadedColor.getAsRGBA());
-			}
-
-			UINT32 vertOffset = i * 4;
-
-			indices[0] = vertOffset + 0;
-			indices[1] = vertOffset + 1;
-			indices[2] = vertOffset + 2;
-			indices[3] = vertOffset + 0;
-			indices[4] = vertOffset + 2;
-			indices[5] = vertOffset + 3;
-
-			indices += 6;
-		}
-
-		return mIconMeshHeap->alloc(meshData, DOT_TRIANGLE_LIST);
-	}
-
-	void GizmoManager::limitIconSize(UINT32& width, UINT32& height)
-	{
-		if (width <= OPTIMAL_ICON_SIZE && height <= OPTIMAL_ICON_SIZE)
-			return;
-
-		float relWidth = OPTIMAL_ICON_SIZE / (float)width;
-		float relHeight = OPTIMAL_ICON_SIZE / (float)height;
-
-		float scale = std::min(relWidth, relHeight);
-
-		width = Math::roundToInt(width * scale);
-		height = Math::roundToInt(height * scale);
-	}
-
-	void GizmoManager::calculateIconColors(const Color& tint, const CameraPtr& camera,
-		UINT32 iconHeight, bool fixedScale, Color& normalColor, Color& fadedColor)
-	{
-		normalColor = tint;
-
-		if (!fixedScale)
-		{
-			float iconToScreenRatio = iconHeight / (float)camera->getViewport()->getHeight();
-
-			if (iconToScreenRatio > 0.3f)
-			{
-				float alpha = 1.0f - Math::lerp01(iconToScreenRatio, 0.3f, 1.0f);
-				normalColor.a *= alpha;
-			}
-			else if (iconToScreenRatio < 0.1f)
-			{
-				float alpha = Math::lerp01(iconToScreenRatio, 0.0f, 0.1f);
-				normalColor.a *= alpha;
-			}
-		}
-
-		fadedColor = normalColor;
-		fadedColor.a *= 0.2f;
-	}
-
-	HSceneObject GizmoManager::getSceneObject(UINT32 gizmoIdx)
-	{
-		auto iterFind = mIdxToSceneObjectMap.find(gizmoIdx);
-
-		if (iterFind != mIdxToSceneObjectMap.end())
-			return iterFind->second;
-
-		return HSceneObject();
-	}
-
-	const float GizmoManagerCore::PICKING_ALPHA_CUTOFF = 0.5f;
-
-	GizmoManagerCore::GizmoManagerCore(const PrivatelyConstuct& dummy)
-	{
-	}
-
-	GizmoManagerCore::~GizmoManagerCore()
-	{
-		CoreRendererPtr activeRenderer = RendererManager::instance().getActive();
-		if (mCamera != nullptr)
-			activeRenderer->_unregisterRenderCallback(mCamera.get(), 20);
-	}
-
-	void GizmoManagerCore::initialize(const GizmoManager::CoreInitData& initData)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		mSolidMaterial.mat = initData.solidMat;
-		mWireMaterial.mat = initData.wireMat;
-		mTextMaterial.mat = initData.textMat;
-		mIconMaterial.mat = initData.iconMat;
-		mPickingMaterial.mat = initData.pickingMat;
-		mAlphaPickingMaterial.mat = initData.alphaPickingMat;
-
-		{
-			SPtr<MaterialCore> mat = mWireMaterial.mat;
-			SPtr<GpuParamsCore> vertParams = mat->getPassParameters(0)->mVertParams;
-
-			vertParams->getParam("matViewProj", mWireMaterial.mViewProj);
-		}
-
-		{
-			SPtr<MaterialCore> mat = mSolidMaterial.mat;
-			SPtr<GpuParamsCore> vertParams = mat->getPassParameters(0)->mVertParams;
-			SPtr<GpuParamsCore> fragParams = mat->getPassParameters(0)->mFragParams;
-
-			vertParams->getParam("matViewProj", mSolidMaterial.mViewProj);
-			fragParams->getParam("viewDir", mSolidMaterial.mViewDir);
-		}
-
-		{
-			SPtr<MaterialCore> mat = mIconMaterial.mat;
-			SPtr<PassParametersCore> pass0Params = mat->getPassParameters(0);
-			SPtr<PassParametersCore> pass1Params = mat->getPassParameters(1);
-
-			SPtr<GpuParamsCore> vertParams0 = pass0Params->mVertParams;
-			SPtr<GpuParamsCore> vertParams1 = pass1Params->mVertParams;
-
-			vertParams0->getParam("matViewProj", mIconMaterial.mViewProj[0]);
-			vertParams1->getParam("matViewProj", mIconMaterial.mViewProj[1]);
-
-			mIconMaterial.mFragParams[0] = pass0Params->mFragParams;
-			mIconMaterial.mFragParams[1] = pass1Params->mFragParams;
-
-			mIconMaterial.mFragParams[0]->getTextureParam("mainTexture", mIconMaterial.mTexture[0]);
-			mIconMaterial.mFragParams[1]->getTextureParam("mainTexture", mIconMaterial.mTexture[1]);
-		}
-
-		{
-			SPtr<MaterialCore> mat = mPickingMaterial.mat;
-			SPtr<GpuParamsCore> vertParams = mat->getPassParameters(0)->mVertParams;
-
-			vertParams->getParam("matViewProj", mPickingMaterial.mViewProj);
-		}
-
-		{
-			SPtr<MaterialCore> mat = mAlphaPickingMaterial.mat;
-			SPtr<PassParametersCore> passParams = mat->getPassParameters(0);
-			SPtr<GpuParamsCore> vertParams = passParams->mVertParams;
-
-			vertParams->getParam("matViewProj", mAlphaPickingMaterial.mViewProj);
-
-			mAlphaPickingMaterial.mFragParams = passParams->mFragParams;
-			mAlphaPickingMaterial.mFragParams->getTextureParam("mainTexture", mAlphaPickingMaterial.mTexture);
-
-			GpuParamFloatCore alphaCutoffParam;
-			mAlphaPickingMaterial.mFragParams->getParam("alphaCutoff", alphaCutoffParam);
-			alphaCutoffParam.set(PICKING_ALPHA_CUTOFF);
-		}
-
-		{
-			SPtr<MaterialCore> mat = mTextMaterial.mat;
-
-			SPtr<PassParametersCore> passParams = mat->getPassParameters(0);
-			SPtr<GpuParamsCore> vertParams = passParams->mVertParams;
-			SPtr<GpuParamsCore> fragParams = passParams->mFragParams;
-
-			vertParams->getParam("matViewProj", mTextMaterial.mViewProj);
-			fragParams->getTextureParam("mainTexture", mTextMaterial.mTexture);
-		}
-	}
-
-	void GizmoManagerCore::updateData(const SPtr<CameraCore>& camera, const Vector<MeshData>& meshes, 
-		const SPtr<MeshCoreBase>& iconMesh, const GizmoManager::IconRenderDataVecPtr& iconRenderData)
-	{
-		if (mCamera != camera)
-		{
-			CoreRendererPtr activeRenderer = RendererManager::instance().getActive();
-			if (mCamera != nullptr)
-				activeRenderer->_unregisterRenderCallback(mCamera.get(), 0);
-
-			if (camera != nullptr)
-				activeRenderer->_registerRenderCallback(camera.get(), 0, std::bind(&GizmoManagerCore::render, this));
-		}
-
-		mCamera = camera;
-		mMeshes = meshes;
-		mIconMesh = iconMesh;
-		mIconRenderData = iconRenderData;
-	}
-
-	void GizmoManagerCore::render()
-	{
-		if (mCamera == nullptr)
-			return;
-
-		SPtr<RenderTargetCore> renderTarget = mCamera->getViewport()->getTarget();
-
-		float width = (float)renderTarget->getProperties().getWidth();
-		float height = (float)renderTarget->getProperties().getHeight();
-
-		Rect2 normArea = mCamera->getViewport()->getNormArea();
-
-		Rect2I screenArea;
-		screenArea.x = (int)(normArea.x * width);
-		screenArea.y = (int)(normArea.y * height);
-		screenArea.width = (int)(normArea.width * width);
-		screenArea.height = (int)(normArea.height * height);
-
-		for (auto& meshData : mMeshes)
-		{
-			GizmoManager::GizmoMaterial material = GizmoManager::GizmoMaterial::Solid;
-			switch(meshData.type)
-			{
-			case MeshType::Solid:
-				material = GizmoManager::GizmoMaterial::Solid;
-				break;
-			case MeshType::Wire:
-				material = GizmoManager::GizmoMaterial::Wire;
-				break;
-			case MeshType::Text:
-				material = GizmoManager::GizmoMaterial::Text;
-				break;
-			}
-
-			renderGizmos(mCamera->getViewMatrix(), mCamera->getProjectionMatrixRS(), mCamera->getForward(), 
-				meshData.mesh, meshData.texture, material);
-		}
-
-		if (mIconMesh != nullptr)
-			renderIconGizmos(screenArea, mIconMesh, mIconRenderData, false);
-	}
-
-	void GizmoManagerCore::renderGizmos(const Matrix4& viewMatrix, const Matrix4& projMatrix, const Vector3& viewDir, 
-		const SPtr<MeshCoreBase>& mesh, const SPtr<TextureCore>& texture, GizmoManager::GizmoMaterial material)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		Matrix4 viewProjMat = projMatrix * viewMatrix;
-
-		switch (material)
-		{
-		case GizmoManager::GizmoMaterial::Solid:
-			mSolidMaterial.mViewProj.set(viewProjMat);
-			mSolidMaterial.mViewDir.set((Vector4)viewDir);
-			gRendererUtility().setPass(mSolidMaterial.mat, 0);
-			gRendererUtility().setPassParams(mSolidMaterial.mat);
-			break;
-		case GizmoManager::GizmoMaterial::Wire:
-			mWireMaterial.mViewProj.set(viewProjMat);
-			gRendererUtility().setPass(mWireMaterial.mat, 0);
-			gRendererUtility().setPassParams(mWireMaterial.mat);
-			break;
-		case GizmoManager::GizmoMaterial::Picking:
-			mPickingMaterial.mViewProj.set(viewProjMat);
-			gRendererUtility().setPass(mPickingMaterial.mat, 0);
-			gRendererUtility().setPassParams(mPickingMaterial.mat);
-			break;
-		case GizmoManager::GizmoMaterial::PickingAlpha:
-			mAlphaPickingMaterial.mViewProj.set(viewProjMat);
-			mAlphaPickingMaterial.mTexture.set(texture);
-			gRendererUtility().setPass(mAlphaPickingMaterial.mat, 0);
-			gRendererUtility().setPassParams(mAlphaPickingMaterial.mat);
-			break;
-		case GizmoManager::GizmoMaterial::Text:
-			mTextMaterial.mViewProj.set(viewProjMat);
-			mTextMaterial.mTexture.set(texture);
-
-			gRendererUtility().setPass(mTextMaterial.mat, 0);
-			gRendererUtility().setPassParams(mTextMaterial.mat);
-			break;
-		}
-		gRendererUtility().draw(mesh, mesh->getProperties().getSubMesh(0));
-	}
-
-	void GizmoManagerCore::renderIconGizmos(Rect2I screenArea, SPtr<MeshCoreBase> mesh, GizmoManager::IconRenderDataVecPtr renderData, bool usePickingMaterial)
-	{
-		RenderAPICore& rs = RenderAPICore::instance();
-		const MeshProperties& meshProps = mesh->getProperties();
-
-		std::shared_ptr<VertexData> vertexData = mesh->getVertexData();
-
-		rs.setVertexDeclaration(vertexData->vertexDeclaration);
-		auto vertexBuffers = vertexData->getBuffers();
-
-		SPtr<VertexBufferCore> vertBuffers[1] = { vertexBuffers.begin()->second };
-		rs.setVertexBuffers(0, vertBuffers, 1);
-
-		SPtr<IndexBufferCore> indexBuffer = mesh->getIndexBuffer();
-		rs.setIndexBuffer(indexBuffer);
-
-		rs.setDrawOperation(DOT_TRIANGLE_LIST);
-
-		// Set up ortho matrix
-		Matrix4 projMat;
-
-		float left = screenArea.x + rs.getHorizontalTexelOffset();
-		float right = screenArea.x + screenArea.width + rs.getHorizontalTexelOffset();
-		float top = screenArea.y + rs.getVerticalTexelOffset();
-		float bottom = screenArea.y + screenArea.height + rs.getVerticalTexelOffset();
-		float near = rs.getMinimumDepthInputValue();
-		float far = rs.getMaximumDepthInputValue();
-
-		// Top/bottom have been swapped because we're moving from window coordinates (origin top left)
-		// to normalized device coordinates (origin bottom left)
-		// Negative near/far because Z is flipped for normalized device coordinates 
-		// (positive Z goes into screen as opposed to view space here we're looking along negative Z)
-		projMat.makeProjectionOrtho(left, right, top, bottom, -near, -far);
-
-		if (!usePickingMaterial)
-		{
-			mIconMaterial.mViewProj[0].set(projMat);
-			mIconMaterial.mViewProj[1].set(projMat);
-
-			for (UINT32 passIdx = 0; passIdx < 2; passIdx++)
-			{
-				gRendererUtility().setPass(mIconMaterial.mat, passIdx);
-
-				UINT32 curIndexOffset = mesh->getIndexOffset();
-				for (auto curRenderData : *renderData)
-				{
-					mIconMaterial.mTexture[passIdx].set(curRenderData.texture);
-					rs.setGpuParams(GPT_FRAGMENT_PROGRAM, mIconMaterial.mFragParams[passIdx]);
-
-					rs.drawIndexed(curIndexOffset, curRenderData.count * 6, mesh->getVertexOffset(), curRenderData.count * 4);
-					curIndexOffset += curRenderData.count * 6;
-				}
-			}
-		}
-		else
-		{
-			mAlphaPickingMaterial.mViewProj.set(projMat);
-
-			gRendererUtility().setPass(mAlphaPickingMaterial.mat, 0);
-
-			UINT32 curIndexOffset = 0;
-			for (auto curRenderData : *renderData)
-			{
-				mAlphaPickingMaterial.mTexture.set(curRenderData.texture);
-				rs.setGpuParams(GPT_FRAGMENT_PROGRAM, mAlphaPickingMaterial.mFragParams);
-
-				rs.drawIndexed(curIndexOffset, curRenderData.count * 6, mesh->getVertexOffset(), curRenderData.count * 4);
-				curIndexOffset += curRenderData.count * 6;
-
-			}
-		}
-
-		mesh->_notifyUsedOnGPU();
-	}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsGizmoManager.h"
+#include "BsMesh.h"
+#include "BsAABox.h"
+#include "BsSphere.h"
+#include "BsVertexDataDesc.h"
+#include "BsShapeMeshes3D.h"
+#include "BsMeshHeap.h"
+#include "BsCCamera.h"
+#include "BsSpriteTexture.h"
+#include "BsCoreThread.h"
+#include "BsBuiltinEditorResources.h"
+#include "BsMaterial.h"
+#include "BsGpuParams.h"
+#include "BsRenderAPI.h"
+#include "BsCoreRenderer.h"
+#include "BsRendererUtility.h"
+#include "BsTransientMesh.h"
+#include "BsRendererManager.h"
+#include "BsDrawHelper.h"
+
+using namespace std::placeholders;
+
+namespace BansheeEngine
+{
+	const UINT32 GizmoManager::VERTEX_BUFFER_GROWTH = 4096;
+	const UINT32 GizmoManager::INDEX_BUFFER_GROWTH = 4096 * 2;
+	const UINT32 GizmoManager::SPHERE_QUALITY = 1;
+	const UINT32 GizmoManager::WIRE_SPHERE_QUALITY = 10;
+	const float GizmoManager::MAX_ICON_RANGE = 500.0f;
+	const UINT32 GizmoManager::OPTIMAL_ICON_SIZE = 64;
+	const float GizmoManager::ICON_TEXEL_WORLD_SIZE = 0.05f;
+
+	GizmoManager::GizmoManager()
+		: mPickable(false), mCurrentIdx(0), mTransformDirty(false), mColorDirty(false), mDrawHelper(nullptr)
+		, mPickingDrawHelper(nullptr), mCore(nullptr)
+		
+	{
+		mTransform = Matrix4::IDENTITY;
+		mDrawHelper = bs_new<DrawHelper>();
+		mPickingDrawHelper = bs_new<DrawHelper>();
+
+		mIconVertexDesc = bs_shared_ptr_new<VertexDataDesc>();
+		mIconVertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
+		mIconVertexDesc->addVertElem(VET_FLOAT2, VES_TEXCOORD);
+		mIconVertexDesc->addVertElem(VET_COLOR, VES_COLOR, 0);
+		mIconVertexDesc->addVertElem(VET_COLOR, VES_COLOR, 1);
+
+		mIconMeshHeap = MeshHeap::create(VERTEX_BUFFER_GROWTH, INDEX_BUFFER_GROWTH, mIconVertexDesc);
+
+		HMaterial solidMaterial = BuiltinEditorResources::instance().createSolidGizmoMat();
+		HMaterial wireMaterial = BuiltinEditorResources::instance().createWireGizmoMat();
+		HMaterial iconMaterial = BuiltinEditorResources::instance().createIconGizmoMat();
+		HMaterial textMaterial = BuiltinEditorResources::instance().createTextGizmoMat();
+		HMaterial pickingMaterial = BuiltinEditorResources::instance().createGizmoPickingMat();
+		HMaterial alphaPickingMaterial = BuiltinEditorResources::instance().createAlphaGizmoPickingMat();
+
+		CoreInitData initData;
+
+		initData.solidMat = solidMaterial->getCore();
+		initData.wireMat = wireMaterial->getCore();
+		initData.iconMat = iconMaterial->getCore();
+		initData.textMat = textMaterial->getCore();
+		initData.pickingMat = pickingMaterial->getCore();
+		initData.alphaPickingMat = alphaPickingMaterial->getCore();
+
+		mCore.store(bs_new<GizmoManagerCore>(GizmoManagerCore::PrivatelyConstuct()), std::memory_order_release);
+
+		gCoreAccessor().queueCommand(std::bind(&GizmoManager::initializeCore, this, initData));
+	}
+
+	GizmoManager::~GizmoManager()
+	{
+		mDrawHelper->clearMeshes(mActiveMeshes);
+		mActiveMeshes.clear();
+
+		if (mIconMesh != nullptr)
+			mIconMeshHeap->dealloc(mIconMesh);
+
+		bs_delete(mDrawHelper);
+		bs_delete(mPickingDrawHelper);
+
+		gCoreAccessor().queueCommand(std::bind(&GizmoManager::destroyCore, this, mCore.load(std::memory_order_relaxed)));
+	}
+
+	void GizmoManager::initializeCore(const CoreInitData& initData)
+	{
+		mCore.load(std::memory_order_acquire)->initialize(initData);
+	}
+
+	void GizmoManager::destroyCore(GizmoManagerCore* core)
+	{
+		bs_delete(core);
+	}
+
+	void GizmoManager::startGizmo(const HSceneObject& gizmoParent)
+	{
+		mActiveSO = gizmoParent;
+
+		if(mTransformDirty)
+		{
+			mTransform = Matrix4::IDENTITY;
+			mTransformDirty = false;
+		}
+
+		if(mColorDirty)
+		{
+			mColor = Color();
+			mColorDirty = false;
+		}
+	}
+
+	void GizmoManager::endGizmo()
+	{
+		mActiveSO = nullptr;
+	}
+
+	void GizmoManager::setColor(const Color& color)
+	{
+		mDrawHelper->setColor(color);
+		mColor = color;
+
+		mColorDirty = true;
+	}
+
+	void GizmoManager::setTransform(const Matrix4& transform)
+	{
+		mDrawHelper->setTransform(transform);
+		mTransform = transform;
+
+		mTransformDirty = true;
+	}
+
+	void GizmoManager::drawCube(const Vector3& position, const Vector3& extents)
+	{
+		mSolidCubeData.push_back(CubeData());
+		CubeData& cubeData = mSolidCubeData.back();
+
+		cubeData.idx = mCurrentIdx++;
+		cubeData.position = position;
+		cubeData.extents = extents;
+		cubeData.color = mColor;
+		cubeData.transform = mTransform;
+		cubeData.sceneObject = mActiveSO;
+		cubeData.pickable = mPickable;
+
+		mDrawHelper->cube(position, extents);
+		mIdxToSceneObjectMap[cubeData.idx] = mActiveSO;
+	}
+
+	void GizmoManager::drawSphere(const Vector3& position, float radius)
+	{
+		mSolidSphereData.push_back(SphereData());
+		SphereData& sphereData = mSolidSphereData.back();
+
+		sphereData.idx = mCurrentIdx++;
+		sphereData.position = position;
+		sphereData.radius = radius;
+		sphereData.color = mColor;
+		sphereData.transform = mTransform;
+		sphereData.sceneObject = mActiveSO;
+		sphereData.pickable = mPickable;
+
+		mDrawHelper->sphere(position, radius);
+		mIdxToSceneObjectMap[sphereData.idx] = mActiveSO;
+	}
+
+	void GizmoManager::drawWireCube(const Vector3& position, const Vector3& extents)
+	{
+		mWireCubeData.push_back(CubeData());
+		CubeData& cubeData = mWireCubeData.back();
+
+		cubeData.idx = mCurrentIdx++;
+		cubeData.position = position;
+		cubeData.extents = extents;
+		cubeData.color = mColor;
+		cubeData.transform = mTransform;
+		cubeData.sceneObject = mActiveSO;
+		cubeData.pickable = mPickable;
+
+		mDrawHelper->wireCube(position, extents);
+		mIdxToSceneObjectMap[cubeData.idx] = mActiveSO;
+	}
+
+	void GizmoManager::drawWireSphere(const Vector3& position, float radius)
+	{
+		mWireSphereData.push_back(SphereData());
+		SphereData& sphereData = mWireSphereData.back();
+
+		sphereData.idx = mCurrentIdx++;
+		sphereData.position = position;
+		sphereData.radius = radius;
+		sphereData.color = mColor;
+		sphereData.transform = mTransform;
+		sphereData.sceneObject = mActiveSO;
+		sphereData.pickable = mPickable;
+
+		mDrawHelper->wireSphere(position, radius);
+		mIdxToSceneObjectMap[sphereData.idx] = mActiveSO;
+	}
+
+	void GizmoManager::drawWireCapsule(const Vector3& position, float height, float radius)
+	{
+		float halfHeight = height * 0.5f;
+
+		// Draw capsule sides
+		Vector3 sideNegXBottom = position + Vector3(-radius, -halfHeight, 0.0f);
+		Vector3 sideNegXTop = position + Vector3(-radius, halfHeight, 0.0f);
+
+		Vector3 sidePosXBottom = position + Vector3(radius, -halfHeight, 0.0f);
+		Vector3 sidePosXTop = position + Vector3(radius, halfHeight, 0.0f);
+
+		Vector3 sideNegZBottom = position + Vector3(0.0f, -halfHeight, -radius);
+		Vector3 sideNegZTop = position + Vector3(0.0f, halfHeight, -radius);
+
+		Vector3 sidePosZBottom = position + Vector3(0.0f, -halfHeight, radius);
+		Vector3 sidePosZTop = position + Vector3(0.0f, halfHeight, radius);
+
+		drawLine(sideNegXBottom, sideNegXTop);
+		drawLine(sidePosXBottom, sidePosXTop);
+		drawLine(sideNegZBottom, sideNegZTop);
+		drawLine(sidePosZBottom, sidePosZTop);
+
+		// Draw capsule caps
+		Vector3 topHemisphere = position + Vector3(0.0f, halfHeight, 0.0f);
+		Vector3 botHemisphere = position + Vector3(0.0f, -halfHeight, 0.0f);
+
+		drawWireArc(topHemisphere, Vector3::UNIT_X, radius, Degree(0.0f), Degree(180.0f));
+		drawWireArc(topHemisphere, Vector3::UNIT_Z, radius, Degree(0.0f), Degree(180.0f));
+
+		drawWireArc(botHemisphere, Vector3::UNIT_X, radius, Degree(180.0f), Degree(180.0f));
+		drawWireArc(botHemisphere, Vector3::UNIT_Z, radius, Degree(180.0f), Degree(180.0f));
+	}
+
+	void GizmoManager::drawLine(const Vector3& start, const Vector3& end)
+	{
+		mLineData.push_back(LineData());
+		LineData& lineData = mLineData.back();
+
+		lineData.idx = mCurrentIdx++;
+		lineData.start = start;
+		lineData.end = end;
+		lineData.color = mColor;
+		lineData.transform = mTransform;
+		lineData.sceneObject = mActiveSO;
+		lineData.pickable = mPickable;
+
+		mDrawHelper->line(start, end);
+		mIdxToSceneObjectMap[lineData.idx] = mActiveSO;
+	}
+
+	void GizmoManager::drawLineList(const Vector<Vector3>& linePoints)
+	{
+		mLineListData.push_back(LineListData());
+		LineListData& lineListData = mLineListData.back();
+
+		lineListData.idx = mCurrentIdx++;
+		lineListData.linePoints = linePoints;
+		lineListData.color = mColor;
+		lineListData.transform = mTransform;
+		lineListData.sceneObject = mActiveSO;
+		lineListData.pickable = mPickable;
+
+		mDrawHelper->lineList(linePoints);
+		mIdxToSceneObjectMap[lineListData.idx] = mActiveSO;
+	}
+
+	void GizmoManager::drawWireDisc(const Vector3& position, const Vector3& normal, float radius)
+	{
+		mWireDiscData.push_back(WireDiscData());
+		WireDiscData& wireDiscData = mWireDiscData.back();
+
+		wireDiscData.idx = mCurrentIdx++;
+		wireDiscData.position = position;
+		wireDiscData.normal = normal;
+		wireDiscData.radius = radius;
+		wireDiscData.color = mColor;
+		wireDiscData.transform = mTransform;
+		wireDiscData.sceneObject = mActiveSO;
+		wireDiscData.pickable = mPickable;
+
+		mDrawHelper->wireDisc(position, normal, radius);
+		mIdxToSceneObjectMap[wireDiscData.idx] = mActiveSO;
+	}
+
+	void GizmoManager::drawWireArc(const Vector3& position, const Vector3& normal, float radius, 
+		Degree startAngle, Degree amountAngle)
+	{
+		mWireArcData.push_back(WireArcData());
+		WireArcData& wireArcData = mWireArcData.back();
+
+		wireArcData.idx = mCurrentIdx++;
+		wireArcData.position = position;
+		wireArcData.normal = normal;
+		wireArcData.radius = radius;
+		wireArcData.startAngle = startAngle;
+		wireArcData.amountAngle = amountAngle;
+		wireArcData.color = mColor;
+		wireArcData.transform = mTransform;
+		wireArcData.sceneObject = mActiveSO;
+		wireArcData.pickable = mPickable;
+
+		mDrawHelper->wireArc(position, normal, radius, startAngle, amountAngle);
+		mIdxToSceneObjectMap[wireArcData.idx] = mActiveSO;
+	}
+
+	void GizmoManager::drawFrustum(const Vector3& position, float aspect, Degree FOV, float near, float far)
+	{
+		mFrustumData.push_back(FrustumData());
+		FrustumData& frustumData = mFrustumData.back();
+
+		frustumData.idx = mCurrentIdx++;
+		frustumData.position = position;
+		frustumData.aspect = aspect;
+		frustumData.FOV = FOV;
+		frustumData.near = near;
+		frustumData.far = far;
+		frustumData.color = mColor;
+		frustumData.transform = mTransform;
+		frustumData.sceneObject = mActiveSO;
+		frustumData.pickable = mPickable;
+
+		mDrawHelper->frustum(position, aspect, FOV, near, far);
+		mIdxToSceneObjectMap[frustumData.idx] = mActiveSO;
+	}
+
+	void GizmoManager::drawIcon(Vector3 position, HSpriteTexture image, bool fixedScale)
+	{
+		mIconData.push_back(IconData());
+		IconData& iconData = mIconData.back();
+
+		iconData.idx = mCurrentIdx++;
+		iconData.position = position;
+		iconData.texture = image;
+		iconData.fixedScale = fixedScale;
+		iconData.color = mColor;
+		iconData.transform = mTransform;
+		iconData.sceneObject = mActiveSO;
+		iconData.pickable = mPickable;
+
+		mIdxToSceneObjectMap[iconData.idx] = mActiveSO;
+	}
+
+	void GizmoManager::drawText(const Vector3& position, const WString& text, const HFont& font, UINT32 fontSize)
+	{
+		HFont myFont = font;
+		if (myFont == nullptr)
+			myFont = BuiltinEditorResources::instance().getDefaultFont();
+
+		mTextData.push_back(TextData());
+		TextData& textData = mTextData.back();
+
+		textData.idx = mCurrentIdx++;
+		textData.position = position;
+		textData.text = text;
+		textData.font = myFont;
+		textData.fontSize = fontSize;
+		textData.color = mColor;
+		textData.transform = mTransform;
+		textData.sceneObject = mActiveSO;
+		textData.pickable = mPickable;
+
+		mDrawHelper->text(position, text, myFont, fontSize);
+		mIdxToSceneObjectMap[textData.idx] = mActiveSO;
+	}
+
+	void GizmoManager::update(const CameraPtr& camera)
+	{
+		mDrawHelper->clearMeshes(mActiveMeshes);
+		mActiveMeshes.clear();
+
+		if (mIconMesh != nullptr)
+			mIconMeshHeap->dealloc(mIconMesh);
+
+		IconRenderDataVecPtr iconRenderData;
+
+		mDrawHelper->buildMeshes(DrawHelper::SortType::BackToFront, camera->getPosition());
+		mActiveMeshes = mDrawHelper->getMeshes();
+
+		Vector<GizmoManagerCore::MeshData> proxyData;
+		for (auto& meshData : mActiveMeshes)
+		{
+			SPtr<TextureCore> tex;
+			if (meshData.texture.isLoaded())
+				tex = meshData.texture->getCore();
+
+			if (meshData.type == DrawHelper::MeshType::Solid)
+			{
+				proxyData.push_back(GizmoManagerCore::MeshData(
+					meshData.mesh->getCore(), tex, GizmoManagerCore::MeshType::Solid));
+			}
+			else if (meshData.type == DrawHelper::MeshType::Wire)
+			{
+				proxyData.push_back(GizmoManagerCore::MeshData(
+					meshData.mesh->getCore(), tex, GizmoManagerCore::MeshType::Wire));
+			}
+			else // Text
+			{
+				proxyData.push_back(GizmoManagerCore::MeshData(
+					meshData.mesh->getCore(), tex, GizmoManagerCore::MeshType::Text));
+			}
+		}
+
+		mIconMesh = buildIconMesh(camera, mIconData, false, iconRenderData);
+		SPtr<MeshCoreBase> iconMesh = mIconMesh->getCore();
+
+		GizmoManagerCore* core = mCore.load(std::memory_order_relaxed);
+
+		gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::updateData, core, camera->getCore(),
+			proxyData, iconMesh, iconRenderData));
+	}
+
+	void GizmoManager::renderForPicking(const CameraPtr& camera, std::function<Color(UINT32)> idxToColorCallback)
+	{
+		Vector<IconData> iconData;
+		IconRenderDataVecPtr iconRenderData;
+
+		mPickingDrawHelper->clear();
+
+		for (auto& cubeDataEntry : mSolidCubeData)
+		{
+			if (!cubeDataEntry.pickable)
+				continue;
+
+			mPickingDrawHelper->setColor(idxToColorCallback(cubeDataEntry.idx));
+			mPickingDrawHelper->setTransform(cubeDataEntry.transform);
+
+			mPickingDrawHelper->cube(cubeDataEntry.position, cubeDataEntry.extents);
+		}
+
+		for (auto& cubeDataEntry : mWireCubeData)
+		{
+			if (!cubeDataEntry.pickable)
+				continue;
+
+			mPickingDrawHelper->setColor(idxToColorCallback(cubeDataEntry.idx));
+			mPickingDrawHelper->setTransform(cubeDataEntry.transform);
+
+			mPickingDrawHelper->wireCube(cubeDataEntry.position, cubeDataEntry.extents);
+		}
+
+		for (auto& sphereDataEntry : mSolidSphereData)
+		{
+			if (!sphereDataEntry.pickable)
+				continue;
+
+			mPickingDrawHelper->setColor(idxToColorCallback(sphereDataEntry.idx));
+			mPickingDrawHelper->setTransform(sphereDataEntry.transform);
+
+			mPickingDrawHelper->sphere(sphereDataEntry.position, sphereDataEntry.radius);
+		}
+
+		for (auto& sphereDataEntry : mWireSphereData)
+		{
+			if (!sphereDataEntry.pickable)
+				continue;
+
+			mPickingDrawHelper->setColor(idxToColorCallback(sphereDataEntry.idx));
+			mPickingDrawHelper->setTransform(sphereDataEntry.transform);
+
+			mPickingDrawHelper->wireSphere(sphereDataEntry.position, sphereDataEntry.radius);
+		}
+
+		for (auto& lineDataEntry : mLineData)
+		{
+			if (!lineDataEntry.pickable)
+				continue;
+
+			mPickingDrawHelper->setColor(idxToColorCallback(lineDataEntry.idx));
+			mPickingDrawHelper->setTransform(lineDataEntry.transform);
+
+			mPickingDrawHelper->line(lineDataEntry.start, lineDataEntry.end);
+		}
+
+		for (auto& lineListDataEntry : mLineListData)
+		{
+			if (!lineListDataEntry.pickable)
+				continue;
+
+			mPickingDrawHelper->setColor(idxToColorCallback(lineListDataEntry.idx));
+			mPickingDrawHelper->setTransform(lineListDataEntry.transform);
+
+			mPickingDrawHelper->lineList(lineListDataEntry.linePoints);
+		}
+
+		for (auto& wireDiscDataEntry : mWireDiscData)
+		{
+			if (!wireDiscDataEntry.pickable)
+				continue;
+
+			mPickingDrawHelper->setColor(idxToColorCallback(wireDiscDataEntry.idx));
+			mPickingDrawHelper->setTransform(wireDiscDataEntry.transform);
+
+			mPickingDrawHelper->wireDisc(wireDiscDataEntry.position, wireDiscDataEntry.normal, wireDiscDataEntry.radius);
+		}
+
+		for (auto& wireArcDataEntry : mWireArcData)
+		{
+			if (!wireArcDataEntry.pickable)
+				continue;
+
+			mPickingDrawHelper->setColor(idxToColorCallback(wireArcDataEntry.idx));
+			mPickingDrawHelper->setTransform(wireArcDataEntry.transform);
+
+			mPickingDrawHelper->wireArc(wireArcDataEntry.position, wireArcDataEntry.normal, wireArcDataEntry.radius, 
+				wireArcDataEntry.startAngle, wireArcDataEntry.amountAngle);
+		}
+
+		for (auto& frustumDataEntry : mFrustumData)
+		{
+			if (!frustumDataEntry.pickable)
+				continue;
+
+			mPickingDrawHelper->setColor(idxToColorCallback(frustumDataEntry.idx));
+			mPickingDrawHelper->setTransform(frustumDataEntry.transform);
+
+			mPickingDrawHelper->frustum(frustumDataEntry.position, frustumDataEntry.aspect, frustumDataEntry.FOV, 
+				frustumDataEntry.near, frustumDataEntry.far);
+		}
+
+		for (auto& textDataEntry : mTextData)
+		{
+			if (!textDataEntry.pickable)
+				continue;
+
+			mPickingDrawHelper->setColor(idxToColorCallback(textDataEntry.idx));
+			mPickingDrawHelper->setTransform(textDataEntry.transform);
+
+			mPickingDrawHelper->text(textDataEntry.position, textDataEntry.text, textDataEntry.font,
+				textDataEntry.fontSize);
+		}
+
+		for (auto& iconDataEntry : mIconData)
+		{
+			if (!iconDataEntry.pickable)
+				continue;
+
+			iconData.push_back(iconDataEntry);
+			iconData.back().color = idxToColorCallback(iconDataEntry.idx);
+		}
+
+		mPickingDrawHelper->buildMeshes(DrawHelper::SortType::BackToFront, camera->getPosition());
+		const Vector<DrawHelper::ShapeMeshData>& meshes = mPickingDrawHelper->getMeshes();
+
+		TransientMeshPtr iconMesh = buildIconMesh(camera, iconData, true, iconRenderData);
+
+		// Note: This must be rendered while Scene view is being rendered
+		Matrix4 viewMat = camera->getViewMatrix();
+		Matrix4 projMat = camera->getProjectionMatrixRS();
+		ViewportPtr viewport = camera->getViewport();
+
+		GizmoManagerCore* core = mCore.load(std::memory_order_relaxed);
+
+		for (auto& meshData : meshes)
+		{
+			SPtr<TextureCore> tex;
+			if (meshData.texture.isLoaded())
+				tex = meshData.texture->getCore();
+
+			if(meshData.type == DrawHelper::MeshType::Text)
+			{
+				gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::renderGizmos, core, viewMat, projMat,
+					camera->getForward(), meshData.mesh->getCore(), tex, GizmoMaterial::PickingAlpha));
+			}
+			else
+			{
+				gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::renderGizmos, core, viewMat, projMat,
+					camera->getForward(), meshData.mesh->getCore(), tex, GizmoMaterial::Picking));
+			}
+		}
+
+		Rect2I screenArea = camera->getViewport()->getArea();
+
+		gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::renderIconGizmos,
+			core, screenArea, iconMesh->getCore(), iconRenderData, true));
+
+		mPickingDrawHelper->clearMeshes(meshes);
+		mIconMeshHeap->dealloc(iconMesh);
+	}
+
+	void GizmoManager::clearGizmos()
+	{
+		mSolidCubeData.clear();
+		mWireCubeData.clear();
+		mSolidSphereData.clear();
+		mWireSphereData.clear();
+		mLineData.clear();
+		mLineListData.clear();
+		mWireDiscData.clear();
+		mWireArcData.clear();
+		mFrustumData.clear();
+		mTextData.clear();
+		mIconData.clear();
+		mIdxToSceneObjectMap.clear();
+
+		mDrawHelper->clear();
+
+		mCurrentIdx = 0;
+	}
+
+	void GizmoManager::clearRenderData()
+	{
+		mDrawHelper->clearMeshes(mActiveMeshes);
+		mActiveMeshes.clear();
+
+		if (mIconMesh != nullptr)
+			mIconMeshHeap->dealloc(mIconMesh);
+
+		mIconMesh = nullptr;
+
+		GizmoManagerCore* core = mCore.load(std::memory_order_relaxed);
+		IconRenderDataVecPtr iconRenderData = bs_shared_ptr_new<IconRenderDataVec>();
+		
+		gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::updateData, core, 
+			nullptr, Vector<GizmoManagerCore::MeshData>(), nullptr, iconRenderData));
+	}
+
+	TransientMeshPtr GizmoManager::buildIconMesh(const CameraPtr& camera, const Vector<IconData>& iconData,
+		bool forPicking, GizmoManager::IconRenderDataVecPtr& iconRenderData)
+	{
+		mSortedIconData.clear();
+		
+		if (iconData.size() > mSortedIconData.size())
+			mSortedIconData.resize(iconData.size());
+
+		UINT32 i = 0;
+		for (auto& iconEntry : iconData)
+		{
+			Vector3 viewPoint = camera->worldToViewPoint(iconEntry.position);
+
+			float distance = -viewPoint.z;
+			if (distance < camera->getNearClipDistance()) // Ignore behind clip plane
+				continue;
+
+			if (distance > MAX_ICON_RANGE) // Ignore too far away
+				continue;
+
+			if (!iconEntry.texture.isLoaded()) // Ignore missing texture
+				continue;
+
+			if (forPicking && !iconEntry.pickable)
+				continue;
+
+			SortedIconData& sortedIconData = mSortedIconData[i];
+			sortedIconData.iconIdx = i;
+			sortedIconData.distance = distance;
+			sortedIconData.screenPosition = camera->viewToScreenPoint(viewPoint);
+
+			i++;
+		}
+
+		UINT32 actualNumIcons = i;
+
+		// Sort back to front first, then by texture
+		std::sort(mSortedIconData.begin(), mSortedIconData.begin() + actualNumIcons, 
+			[&](const SortedIconData& a, const SortedIconData& b)
+		{
+			if (a.distance == b.distance)
+			{
+				HTexture texA = iconData[a.iconIdx].texture->getTexture();
+				HTexture texB = iconData[b.iconIdx].texture->getTexture();
+
+				if (texA == texB)
+					return a.iconIdx < b.iconIdx;
+
+				return texA->getInternalID() < texB->getInternalID();
+			}
+			else
+				return a.distance > b.distance;
+		});
+
+		MeshDataPtr meshData = bs_shared_ptr_new<MeshData>(actualNumIcons * 4, actualNumIcons * 6, mIconVertexDesc);
+
+		auto positionIter = meshData->getVec3DataIter(VES_POSITION);
+		auto texcoordIter = meshData->getVec2DataIter(VES_TEXCOORD);
+		auto normalColorIter = meshData->getDWORDDataIter(VES_COLOR, 0);
+		auto fadedColorIter = meshData->getDWORDDataIter(VES_COLOR, 1);
+
+		UINT32* indices = meshData->getIndices32();
+
+		float cameraScale = 1.0f;
+		if (camera->getProjectionType() == PT_ORTHOGRAPHIC)
+			cameraScale = camera->getViewport()->getHeight() / camera->getOrthoWindowHeight();
+		else
+		{
+			Radian vertFOV(Math::tan(camera->getHorzFOV() * 0.5f));
+			cameraScale = (camera->getViewport()->getHeight() * 0.5f) / vertFOV.valueRadians();
+		}
+
+		iconRenderData = bs_shared_ptr_new<IconRenderDataVec>();
+		UINT32 lastTextureIdx = std::numeric_limits<UINT32>::max();
+		HTexture curTexture;
+
+		// Note: This assumes the meshes will be rendered using the same camera
+		// properties as when they are created
+		for (i = 0; i < actualNumIcons; i++)
+		{
+			SortedIconData& sortedIconData = mSortedIconData[i];
+			const IconData& curIconData = iconData[sortedIconData.iconIdx];
+
+			HTexture atlasTexture = curIconData.texture->getTexture();
+
+			if (curTexture != atlasTexture)
+			{
+				UINT32 numIconsPerTexture = i - lastTextureIdx;
+				if (numIconsPerTexture > 0)
+				{
+					iconRenderData->push_back(IconRenderData());
+					IconRenderData& renderData = iconRenderData->back();
+					renderData.count = numIconsPerTexture;
+					renderData.texture = atlasTexture->getCore();
+				}
+
+				lastTextureIdx = i;
+				curTexture = atlasTexture;
+			}
+
+			UINT32 iconWidth = curIconData.texture->getWidth();
+			UINT32 iconHeight = curIconData.texture->getHeight();
+
+			limitIconSize(iconWidth, iconHeight);
+
+			Vector3 position((float)sortedIconData.screenPosition.x, (float)sortedIconData.screenPosition.y, -sortedIconData.distance);
+			Vector3 projPosition = camera->projectPoint(position);
+			position.z = projPosition.z;
+
+			float halfWidth = iconWidth * 0.5f;
+			float halfHeight = iconHeight * 0.5f;
+
+			if (!curIconData.fixedScale)
+			{
+				float iconScale = 1.0f;
+				if (camera->getProjectionType() == PT_ORTHOGRAPHIC)
+					iconScale = cameraScale * ICON_TEXEL_WORLD_SIZE;
+				else
+					iconScale = (cameraScale * ICON_TEXEL_WORLD_SIZE) / sortedIconData.distance;
+
+				halfWidth *= iconScale;
+				halfHeight *= iconScale;
+			}
+
+			Color normalColor, fadedColor;
+			calculateIconColors(curIconData.color, camera, (UINT32)(halfHeight * 2.0f), curIconData.fixedScale, normalColor, fadedColor);
+
+			if (forPicking)
+			{
+				normalColor = curIconData.color;
+				fadedColor = curIconData.color;
+			}
+
+			Vector3 positions[4];
+			positions[0] = position + Vector3(-halfWidth, -halfHeight, 0.0f);
+			positions[1] = position + Vector3(halfWidth, -halfHeight, 0.0f);
+			positions[2] = position + Vector3(halfWidth, halfHeight, 0.0f);
+			positions[3] = position + Vector3(-halfWidth, halfHeight, 0.0f);
+
+			Vector2 uvs[4];
+			uvs[0] = curIconData.texture->transformUV(Vector2(0.0f, 0.0f));
+			uvs[1] = curIconData.texture->transformUV(Vector2(1.0f, 0.0f));
+			uvs[2] = curIconData.texture->transformUV(Vector2(1.0f, 1.0f));
+			uvs[3] = curIconData.texture->transformUV(Vector2(0.0f, 1.0f));
+
+			for (UINT32 j = 0; j < 4; j++)
+			{
+				positionIter.addValue(positions[j]);
+				texcoordIter.addValue(uvs[j]);
+				normalColorIter.addValue(normalColor.getAsRGBA());
+				fadedColorIter.addValue(fadedColor.getAsRGBA());
+			}
+
+			UINT32 vertOffset = i * 4;
+
+			indices[0] = vertOffset + 0;
+			indices[1] = vertOffset + 1;
+			indices[2] = vertOffset + 2;
+			indices[3] = vertOffset + 0;
+			indices[4] = vertOffset + 2;
+			indices[5] = vertOffset + 3;
+
+			indices += 6;
+		}
+
+		return mIconMeshHeap->alloc(meshData, DOT_TRIANGLE_LIST);
+	}
+
+	void GizmoManager::limitIconSize(UINT32& width, UINT32& height)
+	{
+		if (width <= OPTIMAL_ICON_SIZE && height <= OPTIMAL_ICON_SIZE)
+			return;
+
+		float relWidth = OPTIMAL_ICON_SIZE / (float)width;
+		float relHeight = OPTIMAL_ICON_SIZE / (float)height;
+
+		float scale = std::min(relWidth, relHeight);
+
+		width = Math::roundToInt(width * scale);
+		height = Math::roundToInt(height * scale);
+	}
+
+	void GizmoManager::calculateIconColors(const Color& tint, const CameraPtr& camera,
+		UINT32 iconHeight, bool fixedScale, Color& normalColor, Color& fadedColor)
+	{
+		normalColor = tint;
+
+		if (!fixedScale)
+		{
+			float iconToScreenRatio = iconHeight / (float)camera->getViewport()->getHeight();
+
+			if (iconToScreenRatio > 0.3f)
+			{
+				float alpha = 1.0f - Math::lerp01(iconToScreenRatio, 0.3f, 1.0f);
+				normalColor.a *= alpha;
+			}
+			else if (iconToScreenRatio < 0.1f)
+			{
+				float alpha = Math::lerp01(iconToScreenRatio, 0.0f, 0.1f);
+				normalColor.a *= alpha;
+			}
+		}
+
+		fadedColor = normalColor;
+		fadedColor.a *= 0.2f;
+	}
+
+	HSceneObject GizmoManager::getSceneObject(UINT32 gizmoIdx)
+	{
+		auto iterFind = mIdxToSceneObjectMap.find(gizmoIdx);
+
+		if (iterFind != mIdxToSceneObjectMap.end())
+			return iterFind->second;
+
+		return HSceneObject();
+	}
+
+	const float GizmoManagerCore::PICKING_ALPHA_CUTOFF = 0.5f;
+
+	GizmoManagerCore::GizmoManagerCore(const PrivatelyConstuct& dummy)
+	{
+	}
+
+	GizmoManagerCore::~GizmoManagerCore()
+	{
+		CoreRendererPtr activeRenderer = RendererManager::instance().getActive();
+		if (mCamera != nullptr)
+			activeRenderer->_unregisterRenderCallback(mCamera.get(), 20);
+	}
+
+	void GizmoManagerCore::initialize(const GizmoManager::CoreInitData& initData)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		mSolidMaterial.mat = initData.solidMat;
+		mWireMaterial.mat = initData.wireMat;
+		mTextMaterial.mat = initData.textMat;
+		mIconMaterial.mat = initData.iconMat;
+		mPickingMaterial.mat = initData.pickingMat;
+		mAlphaPickingMaterial.mat = initData.alphaPickingMat;
+
+		{
+			SPtr<MaterialCore> mat = mWireMaterial.mat;
+			SPtr<GpuParamsCore> vertParams = mat->getPassParameters(0)->mVertParams;
+
+			vertParams->getParam("matViewProj", mWireMaterial.mViewProj);
+		}
+
+		{
+			SPtr<MaterialCore> mat = mSolidMaterial.mat;
+			SPtr<GpuParamsCore> vertParams = mat->getPassParameters(0)->mVertParams;
+			SPtr<GpuParamsCore> fragParams = mat->getPassParameters(0)->mFragParams;
+
+			vertParams->getParam("matViewProj", mSolidMaterial.mViewProj);
+			fragParams->getParam("viewDir", mSolidMaterial.mViewDir);
+		}
+
+		{
+			SPtr<MaterialCore> mat = mIconMaterial.mat;
+			SPtr<PassParametersCore> pass0Params = mat->getPassParameters(0);
+			SPtr<PassParametersCore> pass1Params = mat->getPassParameters(1);
+
+			SPtr<GpuParamsCore> vertParams0 = pass0Params->mVertParams;
+			SPtr<GpuParamsCore> vertParams1 = pass1Params->mVertParams;
+
+			vertParams0->getParam("matViewProj", mIconMaterial.mViewProj[0]);
+			vertParams1->getParam("matViewProj", mIconMaterial.mViewProj[1]);
+
+			mIconMaterial.mFragParams[0] = pass0Params->mFragParams;
+			mIconMaterial.mFragParams[1] = pass1Params->mFragParams;
+
+			mIconMaterial.mFragParams[0]->getTextureParam("mainTexture", mIconMaterial.mTexture[0]);
+			mIconMaterial.mFragParams[1]->getTextureParam("mainTexture", mIconMaterial.mTexture[1]);
+		}
+
+		{
+			SPtr<MaterialCore> mat = mPickingMaterial.mat;
+			SPtr<GpuParamsCore> vertParams = mat->getPassParameters(0)->mVertParams;
+
+			vertParams->getParam("matViewProj", mPickingMaterial.mViewProj);
+		}
+
+		{
+			SPtr<MaterialCore> mat = mAlphaPickingMaterial.mat;
+			SPtr<PassParametersCore> passParams = mat->getPassParameters(0);
+			SPtr<GpuParamsCore> vertParams = passParams->mVertParams;
+
+			vertParams->getParam("matViewProj", mAlphaPickingMaterial.mViewProj);
+
+			mAlphaPickingMaterial.mFragParams = passParams->mFragParams;
+			mAlphaPickingMaterial.mFragParams->getTextureParam("mainTexture", mAlphaPickingMaterial.mTexture);
+
+			GpuParamFloatCore alphaCutoffParam;
+			mAlphaPickingMaterial.mFragParams->getParam("alphaCutoff", alphaCutoffParam);
+			alphaCutoffParam.set(PICKING_ALPHA_CUTOFF);
+		}
+
+		{
+			SPtr<MaterialCore> mat = mTextMaterial.mat;
+
+			SPtr<PassParametersCore> passParams = mat->getPassParameters(0);
+			SPtr<GpuParamsCore> vertParams = passParams->mVertParams;
+			SPtr<GpuParamsCore> fragParams = passParams->mFragParams;
+
+			vertParams->getParam("matViewProj", mTextMaterial.mViewProj);
+			fragParams->getTextureParam("mainTexture", mTextMaterial.mTexture);
+		}
+	}
+
+	void GizmoManagerCore::updateData(const SPtr<CameraCore>& camera, const Vector<MeshData>& meshes, 
+		const SPtr<MeshCoreBase>& iconMesh, const GizmoManager::IconRenderDataVecPtr& iconRenderData)
+	{
+		if (mCamera != camera)
+		{
+			CoreRendererPtr activeRenderer = RendererManager::instance().getActive();
+			if (mCamera != nullptr)
+				activeRenderer->_unregisterRenderCallback(mCamera.get(), 0);
+
+			if (camera != nullptr)
+				activeRenderer->_registerRenderCallback(camera.get(), 0, std::bind(&GizmoManagerCore::render, this));
+		}
+
+		mCamera = camera;
+		mMeshes = meshes;
+		mIconMesh = iconMesh;
+		mIconRenderData = iconRenderData;
+	}
+
+	void GizmoManagerCore::render()
+	{
+		if (mCamera == nullptr)
+			return;
+
+		SPtr<RenderTargetCore> renderTarget = mCamera->getViewport()->getTarget();
+
+		float width = (float)renderTarget->getProperties().getWidth();
+		float height = (float)renderTarget->getProperties().getHeight();
+
+		Rect2 normArea = mCamera->getViewport()->getNormArea();
+
+		Rect2I screenArea;
+		screenArea.x = (int)(normArea.x * width);
+		screenArea.y = (int)(normArea.y * height);
+		screenArea.width = (int)(normArea.width * width);
+		screenArea.height = (int)(normArea.height * height);
+
+		for (auto& meshData : mMeshes)
+		{
+			GizmoManager::GizmoMaterial material = GizmoManager::GizmoMaterial::Solid;
+			switch(meshData.type)
+			{
+			case MeshType::Solid:
+				material = GizmoManager::GizmoMaterial::Solid;
+				break;
+			case MeshType::Wire:
+				material = GizmoManager::GizmoMaterial::Wire;
+				break;
+			case MeshType::Text:
+				material = GizmoManager::GizmoMaterial::Text;
+				break;
+			}
+
+			renderGizmos(mCamera->getViewMatrix(), mCamera->getProjectionMatrixRS(), mCamera->getForward(), 
+				meshData.mesh, meshData.texture, material);
+		}
+
+		if (mIconMesh != nullptr)
+			renderIconGizmos(screenArea, mIconMesh, mIconRenderData, false);
+	}
+
+	void GizmoManagerCore::renderGizmos(const Matrix4& viewMatrix, const Matrix4& projMatrix, const Vector3& viewDir, 
+		const SPtr<MeshCoreBase>& mesh, const SPtr<TextureCore>& texture, GizmoManager::GizmoMaterial material)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		Matrix4 viewProjMat = projMatrix * viewMatrix;
+
+		switch (material)
+		{
+		case GizmoManager::GizmoMaterial::Solid:
+			mSolidMaterial.mViewProj.set(viewProjMat);
+			mSolidMaterial.mViewDir.set((Vector4)viewDir);
+			gRendererUtility().setPass(mSolidMaterial.mat, 0);
+			gRendererUtility().setPassParams(mSolidMaterial.mat);
+			break;
+		case GizmoManager::GizmoMaterial::Wire:
+			mWireMaterial.mViewProj.set(viewProjMat);
+			gRendererUtility().setPass(mWireMaterial.mat, 0);
+			gRendererUtility().setPassParams(mWireMaterial.mat);
+			break;
+		case GizmoManager::GizmoMaterial::Picking:
+			mPickingMaterial.mViewProj.set(viewProjMat);
+			gRendererUtility().setPass(mPickingMaterial.mat, 0);
+			gRendererUtility().setPassParams(mPickingMaterial.mat);
+			break;
+		case GizmoManager::GizmoMaterial::PickingAlpha:
+			mAlphaPickingMaterial.mViewProj.set(viewProjMat);
+			mAlphaPickingMaterial.mTexture.set(texture);
+			gRendererUtility().setPass(mAlphaPickingMaterial.mat, 0);
+			gRendererUtility().setPassParams(mAlphaPickingMaterial.mat);
+			break;
+		case GizmoManager::GizmoMaterial::Text:
+			mTextMaterial.mViewProj.set(viewProjMat);
+			mTextMaterial.mTexture.set(texture);
+
+			gRendererUtility().setPass(mTextMaterial.mat, 0);
+			gRendererUtility().setPassParams(mTextMaterial.mat);
+			break;
+		}
+		gRendererUtility().draw(mesh, mesh->getProperties().getSubMesh(0));
+	}
+
+	void GizmoManagerCore::renderIconGizmos(Rect2I screenArea, SPtr<MeshCoreBase> mesh, GizmoManager::IconRenderDataVecPtr renderData, bool usePickingMaterial)
+	{
+		RenderAPICore& rapi = RenderAPICore::instance();
+		const MeshProperties& meshProps = mesh->getProperties();
+
+		std::shared_ptr<VertexData> vertexData = mesh->getVertexData();
+
+		rapi.setVertexDeclaration(vertexData->vertexDeclaration);
+		auto vertexBuffers = vertexData->getBuffers();
+
+		SPtr<VertexBufferCore> vertBuffers[1] = { vertexBuffers.begin()->second };
+		rapi.setVertexBuffers(0, vertBuffers, 1);
+
+		SPtr<IndexBufferCore> indexBuffer = mesh->getIndexBuffer();
+		rapi.setIndexBuffer(indexBuffer);
+
+		rapi.setDrawOperation(DOT_TRIANGLE_LIST);
+
+		// Set up ortho matrix
+		Matrix4 projMat;
+
+		const RenderAPIInfo& rapiInfo = rapi.getAPIInfo();
+		float left = screenArea.x + rapiInfo.getHorizontalTexelOffset();
+		float right = screenArea.x + screenArea.width + rapiInfo.getHorizontalTexelOffset();
+		float top = screenArea.y + rapiInfo.getVerticalTexelOffset();
+		float bottom = screenArea.y + screenArea.height + rapiInfo.getVerticalTexelOffset();
+		float near = rapiInfo.getMinimumDepthInputValue();
+		float far = rapiInfo.getMaximumDepthInputValue();
+
+		// Top/bottom have been swapped because we're moving from window coordinates (origin top left)
+		// to normalized device coordinates (origin bottom left)
+		// Negative near/far because Z is flipped for normalized device coordinates 
+		// (positive Z goes into screen as opposed to view space here we're looking along negative Z)
+		projMat.makeProjectionOrtho(left, right, top, bottom, -near, -far);
+
+		if (!usePickingMaterial)
+		{
+			mIconMaterial.mViewProj[0].set(projMat);
+			mIconMaterial.mViewProj[1].set(projMat);
+
+			for (UINT32 passIdx = 0; passIdx < 2; passIdx++)
+			{
+				gRendererUtility().setPass(mIconMaterial.mat, passIdx);
+
+				UINT32 curIndexOffset = mesh->getIndexOffset();
+				for (auto curRenderData : *renderData)
+				{
+					mIconMaterial.mTexture[passIdx].set(curRenderData.texture);
+					rapi.setGpuParams(GPT_FRAGMENT_PROGRAM, mIconMaterial.mFragParams[passIdx]);
+
+					rapi.drawIndexed(curIndexOffset, curRenderData.count * 6, mesh->getVertexOffset(), curRenderData.count * 4);
+					curIndexOffset += curRenderData.count * 6;
+				}
+			}
+		}
+		else
+		{
+			mAlphaPickingMaterial.mViewProj.set(projMat);
+
+			gRendererUtility().setPass(mAlphaPickingMaterial.mat, 0);
+
+			UINT32 curIndexOffset = 0;
+			for (auto curRenderData : *renderData)
+			{
+				mAlphaPickingMaterial.mTexture.set(curRenderData.texture);
+				rapi.setGpuParams(GPT_FRAGMENT_PROGRAM, mAlphaPickingMaterial.mFragParams);
+
+				rapi.drawIndexed(curIndexOffset, curRenderData.count * 6, mesh->getVertexOffset(), curRenderData.count * 4);
+				curIndexOffset += curRenderData.count * 6;
+
+			}
+		}
+
+		mesh->_notifyUsedOnGPU();
+	}
 }

+ 418 - 415
Source/BansheeEngine/Source/BsRendererUtility.cpp

@@ -1,416 +1,419 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsRendererUtility.h"
-#include "BsRenderAPI.h"
-#include "BsMesh.h"
-#include "BsVertexDataDesc.h"
-#include "BsMaterial.h"
-#include "BsPass.h"
-#include "BsBlendState.h"
-#include "BsDepthStencilState.h"
-#include "BsRasterizerState.h"
-#include "BsGpuParams.h"
-#include "BsGpuParamDesc.h"
-#include "BsShapeMeshes3D.h"
-#include "BsLight.h"
-
-namespace BansheeEngine
-{
-	RendererUtility::RendererUtility()
-	{
-		{
-			VertexDataDescPtr vertexDesc = bs_shared_ptr_new<VertexDataDesc>();
-			vertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
-			vertexDesc->addVertElem(VET_FLOAT2, VES_TEXCOORD);
-
-			mFullScreenQuadMesh = MeshCore::create(4, 6, vertexDesc);
-		}
-
-		{
-			SPtr<VertexDataDesc> vertexDesc = bs_shared_ptr_new<VertexDataDesc>();
-			vertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
-
-			UINT32 numVertices = 0;
-			UINT32 numIndices = 0;
-
-			ShapeMeshes3D::getNumElementsSphere(3, numVertices, numIndices);
-			MeshDataPtr meshData = bs_shared_ptr_new<MeshData>(numVertices, numIndices, vertexDesc);
-
-			UINT32* indexData = meshData->getIndices32();
-			UINT8* positionData = meshData->getElementData(VES_POSITION);
-
-			Sphere localSphere(Vector3::ZERO, 1.0f);
-			ShapeMeshes3D::solidSphere(localSphere, positionData, nullptr, 0,
-				vertexDesc->getVertexStride(), indexData, 0, 3);
-
-			mPointLightStencilMesh = MeshCore::create(meshData);
-		}
-
-		{
-			UINT32 numSides = LightCore::LIGHT_CONE_NUM_SIDES;
-			UINT32 numSlices = LightCore::LIGHT_CONE_NUM_SLICES;
-
-			SPtr<VertexDataDesc> vertexDesc = bs_shared_ptr_new<VertexDataDesc>();
-			vertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
-
-			UINT32 numVertices = numSides * numSlices * 2;
-			UINT32 numIndices = ((numSides * 2) * (numSlices - 1) * 2) * 3;
-
-			MeshDataPtr meshData = bs_shared_ptr_new<MeshData>(numVertices, numIndices, vertexDesc);
-
-			UINT32* indexData = meshData->getIndices32();
-			UINT8* positionData = meshData->getElementData(VES_POSITION);
-			UINT32 stride = vertexDesc->getVertexStride();
-
-			// Dummy vertex positions, actual ones generated in shader
-			for (UINT32 i = 0; i < numVertices; i++)
-			{
-				memcpy(positionData, &Vector3::ZERO, sizeof(Vector3));
-				positionData += stride;
-			}
-
-			// Cone indices
-			UINT32 curIdx = 0;
-			for (UINT32 sliceIdx = 0; sliceIdx < (numSlices - 1); sliceIdx++)
-			{
-				for (UINT32 sideIdx = 0; sideIdx < numSides; sideIdx++)
-				{
-					indexData[curIdx++] = sliceIdx * numSides + sideIdx;
-					indexData[curIdx++] = sliceIdx * numSides + (sideIdx + 1) % numSides;
-					indexData[curIdx++] = (sliceIdx + 1) * numSides + sideIdx;
-
-					indexData[curIdx++] = sliceIdx * numSides + (sideIdx + 1) % numSides;
-					indexData[curIdx++] = (sliceIdx + 1) * numSides + (sideIdx + 1) % numSides;
-					indexData[curIdx++] = (sliceIdx + 1) * numSides + sideIdx;
-				}
-			}
-
-			// Sphere cap indices
-			UINT32 coneOffset = numSides * numSlices;
-			for (UINT32 sliceIdx = 0; sliceIdx < (numSlices - 1); sliceIdx++)
-			{
-				for (UINT32 sideIdx = 0; sideIdx < numSides; sideIdx++)
-				{
-					indexData[curIdx++] = coneOffset + sliceIdx * numSides + sideIdx;
-					indexData[curIdx++] = coneOffset + sliceIdx * numSides + (sideIdx + 1) % numSides;
-					indexData[curIdx++] = coneOffset + (sliceIdx + 1) * numSides + sideIdx;
-
-					indexData[curIdx++] = coneOffset + sliceIdx * numSides + (sideIdx + 1) % numSides;
-					indexData[curIdx++] = coneOffset + (sliceIdx + 1) * numSides + (sideIdx + 1) % numSides;
-					indexData[curIdx++] = coneOffset + (sliceIdx + 1) * numSides + sideIdx;
-				}
-			}
-
-			mSpotLightStencilMesh = MeshCore::create(meshData);
-		}
-
-		// TODO - When I add proper preprocessor support, merge these into a single material
-		mResolveMat = bs_shared_ptr_new<ResolveMat>();
-		mBlitMat = bs_shared_ptr_new<BlitMat>();
-	}
-
-	RendererUtility::~RendererUtility()
-	{
-
-	}
-
-	void RendererUtility::setPass(const SPtr<MaterialCore>& material, UINT32 passIdx)
-	{
-		RenderAPICore& rs = RenderAPICore::instance();
-
-		SPtr<PassCore> pass = material->getPass(passIdx);
-		SPtr<PassParametersCore> passParams = material->getPassParameters(passIdx);
-
-		struct StageData
-		{
-			GpuProgramType type;
-			bool enable;
-			SPtr<GpuParamsCore> params;
-			SPtr<GpuProgramCore> program;
-		};
-
-		const UINT32 numStages = 6;
-		StageData stages[numStages] =
-		{
-			{
-				GPT_VERTEX_PROGRAM, pass->hasVertexProgram(),
-				passParams->mVertParams, pass->getVertexProgram()
-			},
-			{
-				GPT_FRAGMENT_PROGRAM, pass->hasFragmentProgram(),
-				passParams->mFragParams, pass->getFragmentProgram()
-			},
-			{
-				GPT_GEOMETRY_PROGRAM, pass->hasGeometryProgram(),
-				passParams->mGeomParams, pass->getGeometryProgram()
-			},
-			{
-				GPT_HULL_PROGRAM, pass->hasHullProgram(),
-				passParams->mHullParams, pass->getHullProgram()
-			},
-			{
-				GPT_DOMAIN_PROGRAM, pass->hasDomainProgram(),
-				passParams->mDomainParams, pass->getDomainProgram()
-			},
-			{
-				GPT_COMPUTE_PROGRAM, pass->hasComputeProgram(),
-				passParams->mComputeParams, pass->getComputeProgram()
-			}
-		};
-
-		for (UINT32 i = 0; i < numStages; i++)
-		{
-			const StageData& stage = stages[i];
-
-			if (stage.enable)
-			{
-				rs.bindGpuProgram(stage.program);
-				rs.setGpuParams(stage.type, stage.params);
-
-			}
-			else
-				rs.unbindGpuProgram(stage.type);
-		}
-
-		// Set up non-texture related pass settings
-		if (pass->getBlendState() != nullptr)
-			rs.setBlendState(pass->getBlendState());
-		else
-			rs.setBlendState(BlendStateCore::getDefault());
-
-		if (pass->getDepthStencilState() != nullptr)
-			rs.setDepthStencilState(pass->getDepthStencilState(), pass->getStencilRefValue());
-		else
-			rs.setDepthStencilState(DepthStencilStateCore::getDefault(), pass->getStencilRefValue());
-
-		if (pass->getRasterizerState() != nullptr)
-			rs.setRasterizerState(pass->getRasterizerState());
-		else
-			rs.setRasterizerState(RasterizerStateCore::getDefault());
-	}
-
-	void RendererUtility::setPassParams(const SPtr<MaterialCore>& material, UINT32 passIdx)
-	{
-		const SPtr<PassParametersCore>& passParams = material->getPassParameters(passIdx);
-
-		RenderAPICore& rs = RenderAPICore::instance();
-
-		struct StageData
-		{
-			GpuProgramType type;
-			SPtr<GpuParamsCore> params;
-		};
-
-		const UINT32 numStages = 6;
-		StageData stages[numStages] =
-		{
-			{ GPT_VERTEX_PROGRAM, passParams->mVertParams },
-			{ GPT_FRAGMENT_PROGRAM, passParams->mFragParams },
-			{ GPT_GEOMETRY_PROGRAM, passParams->mGeomParams },
-			{ GPT_HULL_PROGRAM, passParams->mHullParams },
-			{ GPT_DOMAIN_PROGRAM, passParams->mDomainParams },
-			{ GPT_COMPUTE_PROGRAM, passParams->mComputeParams }
-		};
-
-		for (UINT32 i = 0; i < numStages; i++)
-		{
-			const StageData& stage = stages[i];
-
-			SPtr<GpuParamsCore> params = stage.params;
-			if (params == nullptr)
-				continue;
-
-			const GpuParamDesc& paramDesc = params->getParamDesc();
-
-			for (auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
-			{
-				SPtr<SamplerStateCore> samplerState = params->getSamplerState(iter->second.slot);
-
-				if (samplerState == nullptr)
-					rs.setSamplerState(stage.type, iter->second.slot, SamplerStateCore::getDefault());
-				else
-					rs.setSamplerState(stage.type, iter->second.slot, samplerState);
-			}
-
-			for (auto iter = paramDesc.textures.begin(); iter != paramDesc.textures.end(); ++iter)
-			{
-				SPtr<TextureCore> texture = params->getTexture(iter->second.slot);
-
-				if (!params->isLoadStoreTexture(iter->second.slot))
-				{
-					if (texture == nullptr)
-						rs.setTexture(stage.type, iter->second.slot, false, nullptr);
-					else
-						rs.setTexture(stage.type, iter->second.slot, true, texture);
-				}
-				else
-				{
-					const TextureSurface& surface = params->getLoadStoreSurface(iter->second.slot);
-
-					if (texture == nullptr)
-						rs.setLoadStoreTexture(stage.type, iter->second.slot, false, nullptr, surface);
-					else
-						rs.setLoadStoreTexture(stage.type, iter->second.slot, true, texture, surface);
-				}
-			}
-
-			rs.setConstantBuffers(stage.type, params);
-		}
-	}
-
-	void RendererUtility::draw(const SPtr<MeshCoreBase>& mesh, const SubMesh& subMesh)
-	{
-		RenderAPICore& rs = RenderAPICore::instance();
-		const MeshProperties& meshProps = mesh->getProperties();
-		std::shared_ptr<VertexData> vertexData = mesh->getVertexData();
-
-		rs.setVertexDeclaration(vertexData->vertexDeclaration);
-		auto& vertexBuffers = vertexData->getBuffers();
-
-		if (vertexBuffers.size() > 0)
-		{
-			SPtr<VertexBufferCore> buffers[MAX_BOUND_VERTEX_BUFFERS];
-
-			UINT32 endSlot = 0;
-			UINT32 startSlot = MAX_BOUND_VERTEX_BUFFERS;
-			for (auto iter = vertexBuffers.begin(); iter != vertexBuffers.end(); ++iter)
-			{
-				if (iter->first >= MAX_BOUND_VERTEX_BUFFERS)
-					BS_EXCEPT(InvalidParametersException, "Buffer index out of range");
-
-				startSlot = std::min(iter->first, startSlot);
-				endSlot = std::max(iter->first, endSlot);
-			}
-
-			for (auto iter = vertexBuffers.begin(); iter != vertexBuffers.end(); ++iter)
-			{
-				buffers[iter->first - startSlot] = iter->second;
-			}
-
-			rs.setVertexBuffers(startSlot, buffers, endSlot - startSlot + 1);
-		}
-
-		rs.setDrawOperation(subMesh.drawOp);
-
-		SPtr<IndexBufferCore> indexBuffer = mesh->getIndexBuffer();
-
-		UINT32 indexCount = subMesh.indexCount;
-
-		rs.setIndexBuffer(indexBuffer);
-		rs.drawIndexed(subMesh.indexOffset + mesh->getIndexOffset(), indexCount, mesh->getVertexOffset(), vertexData->vertexCount);
-
-		mesh->_notifyUsedOnGPU();
-	}
-
-	void RendererUtility::blit(const SPtr<TextureCore>& texture, const Rect2I& area)
-	{
-		auto& texProps = texture->getProperties();
-		SPtr<MaterialCore> mat;
-		if (texProps.getMultisampleCount() > 1)
-		{
-			mat = mResolveMat->getMaterial();
-			mResolveMat->setParameters(texture);
-		}
-		else
-		{
-			mat = mBlitMat->getMaterial();
-			mBlitMat->setParameters(texture);
-		}
-
-		setPass(mat, 0);
-		setPassParams(mat);
-
-		Rect2 fArea((float)area.x, (float)area.y, (float)area.width, (float)area.height);
-		if(area.width == 0 || area.height == 0)
-		{
-			fArea.x = 0.0f;
-			fArea.y = 0.0f;
-			fArea.width = (float)texProps.getWidth();
-			fArea.height = (float)texProps.getHeight();
-		}
-
-		drawScreenQuad(fArea);
-	}
-
-	void RendererUtility::drawScreenQuad(const Rect2& uv, const Vector2I& textureSize)
-	{
-		// Note: Consider drawing the quad using a single large triangle for possibly better performance
-
-		Vector3 vertices[4];
-		vertices[0] = Vector3(-1.0f, 1.0f, 0.0f);
-		vertices[1] = Vector3(1.0f, 1.0f, 0.0f);
-		vertices[2] = Vector3(-1.0f, -1.0f, 0.0f);
-		vertices[3] = Vector3(1.0f, -1.0f, 0.0f);
-
-		Vector2 uvs[4];
-
-		// DX 11
-		uvs[0] = Vector2(uv.x, uv.y);
-		uvs[1] = Vector2(uv.x + uv.width, uv.y);
-		uvs[2] = Vector2(uv.x, uv.y + uv.height);
-		uvs[3] = Vector2(uv.x + uv.width, uv.y + uv.height);
-
-		// OpenGL
-		uvs[0] = Vector2(uv.x, uv.y + uv.height);
-		uvs[1] = Vector2(uv.x + uv.width, uv.y + uv.height);
-		uvs[2] = Vector2(uv.x, uv.y);
-		uvs[3] = Vector2(uv.x + uv.width, uv.y);
-
-		for (int i = 0; i < 4; i++)
-		{
-			uvs[i].x /= (float)textureSize.x;
-			uvs[i].y /= (float)textureSize.y;
-		}
-
-		SPtr<VertexDataDesc> vertexDesc = mFullScreenQuadMesh->getVertexDesc();
-		MeshDataPtr meshData = bs_shared_ptr_new<MeshData>(4, 6, vertexDesc);
-
-		auto vecIter = meshData->getVec3DataIter(VES_POSITION);
-		for (UINT32 i = 0; i < 4; i++)
-			vecIter.addValue(vertices[i]);
-
-		auto uvIter = meshData->getVec2DataIter(VES_TEXCOORD);
-		for (UINT32 i = 0; i < 4; i++)
-			uvIter.addValue(uvs[i]);
-
-		auto indices = meshData->getIndices32();
-		indices[0] = 0;
-		indices[1] = 1;
-		indices[2] = 2;
-		indices[3] = 1;
-		indices[4] = 3;
-		indices[5] = 2;
-
-		mFullScreenQuadMesh->writeSubresource(0, *meshData, true, false);
-		draw(mFullScreenQuadMesh, mFullScreenQuadMesh->getProperties().getSubMesh());
-	}
-
-	RendererUtility& gRendererUtility()
-	{
-		return RendererUtility::instance();
-	}
-
-	BlitMat::BlitMat()
-	{
-		mSource = mMaterial->getParamTexture("gSource");
-	}
-
-	void BlitMat::setParameters(const SPtr<TextureCore>& source)
-	{
-		mSource.set(source);
-	}
-
-	ResolveMat::ResolveMat()
-	{
-		mSource = mMaterial->getParamTexture("gSource");
-		mMaterial->getParam("gNumSamples", mNumSamples);
-	}
-
-	void ResolveMat::setParameters(const SPtr<TextureCore>& source)
-	{
-		mSource.set(source);
-
-		UINT32 sampleCount = source->getProperties().getMultisampleCount();
-		mNumSamples.set(sampleCount);
-	}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsRendererUtility.h"
+#include "BsRenderAPI.h"
+#include "BsMesh.h"
+#include "BsVertexDataDesc.h"
+#include "BsMaterial.h"
+#include "BsPass.h"
+#include "BsBlendState.h"
+#include "BsDepthStencilState.h"
+#include "BsRasterizerState.h"
+#include "BsGpuParams.h"
+#include "BsGpuParamDesc.h"
+#include "BsShapeMeshes3D.h"
+#include "BsLight.h"
+
+namespace BansheeEngine
+{
+	RendererUtility::RendererUtility()
+	{
+		{
+			VertexDataDescPtr vertexDesc = bs_shared_ptr_new<VertexDataDesc>();
+			vertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
+			vertexDesc->addVertElem(VET_FLOAT2, VES_TEXCOORD);
+
+			mFullScreenQuadMesh = MeshCore::create(4, 6, vertexDesc);
+		}
+
+		{
+			SPtr<VertexDataDesc> vertexDesc = bs_shared_ptr_new<VertexDataDesc>();
+			vertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
+
+			UINT32 numVertices = 0;
+			UINT32 numIndices = 0;
+
+			ShapeMeshes3D::getNumElementsSphere(3, numVertices, numIndices);
+			MeshDataPtr meshData = bs_shared_ptr_new<MeshData>(numVertices, numIndices, vertexDesc);
+
+			UINT32* indexData = meshData->getIndices32();
+			UINT8* positionData = meshData->getElementData(VES_POSITION);
+
+			Sphere localSphere(Vector3::ZERO, 1.0f);
+			ShapeMeshes3D::solidSphere(localSphere, positionData, nullptr, 0,
+				vertexDesc->getVertexStride(), indexData, 0, 3);
+
+			mPointLightStencilMesh = MeshCore::create(meshData);
+		}
+
+		{
+			UINT32 numSides = LightCore::LIGHT_CONE_NUM_SIDES;
+			UINT32 numSlices = LightCore::LIGHT_CONE_NUM_SLICES;
+
+			SPtr<VertexDataDesc> vertexDesc = bs_shared_ptr_new<VertexDataDesc>();
+			vertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
+
+			UINT32 numVertices = numSides * numSlices * 2;
+			UINT32 numIndices = ((numSides * 2) * (numSlices - 1) * 2) * 3;
+
+			MeshDataPtr meshData = bs_shared_ptr_new<MeshData>(numVertices, numIndices, vertexDesc);
+
+			UINT32* indexData = meshData->getIndices32();
+			UINT8* positionData = meshData->getElementData(VES_POSITION);
+			UINT32 stride = vertexDesc->getVertexStride();
+
+			// Dummy vertex positions, actual ones generated in shader
+			for (UINT32 i = 0; i < numVertices; i++)
+			{
+				memcpy(positionData, &Vector3::ZERO, sizeof(Vector3));
+				positionData += stride;
+			}
+
+			// Cone indices
+			UINT32 curIdx = 0;
+			for (UINT32 sliceIdx = 0; sliceIdx < (numSlices - 1); sliceIdx++)
+			{
+				for (UINT32 sideIdx = 0; sideIdx < numSides; sideIdx++)
+				{
+					indexData[curIdx++] = sliceIdx * numSides + sideIdx;
+					indexData[curIdx++] = sliceIdx * numSides + (sideIdx + 1) % numSides;
+					indexData[curIdx++] = (sliceIdx + 1) * numSides + sideIdx;
+
+					indexData[curIdx++] = sliceIdx * numSides + (sideIdx + 1) % numSides;
+					indexData[curIdx++] = (sliceIdx + 1) * numSides + (sideIdx + 1) % numSides;
+					indexData[curIdx++] = (sliceIdx + 1) * numSides + sideIdx;
+				}
+			}
+
+			// Sphere cap indices
+			UINT32 coneOffset = numSides * numSlices;
+			for (UINT32 sliceIdx = 0; sliceIdx < (numSlices - 1); sliceIdx++)
+			{
+				for (UINT32 sideIdx = 0; sideIdx < numSides; sideIdx++)
+				{
+					indexData[curIdx++] = coneOffset + sliceIdx * numSides + sideIdx;
+					indexData[curIdx++] = coneOffset + sliceIdx * numSides + (sideIdx + 1) % numSides;
+					indexData[curIdx++] = coneOffset + (sliceIdx + 1) * numSides + sideIdx;
+
+					indexData[curIdx++] = coneOffset + sliceIdx * numSides + (sideIdx + 1) % numSides;
+					indexData[curIdx++] = coneOffset + (sliceIdx + 1) * numSides + (sideIdx + 1) % numSides;
+					indexData[curIdx++] = coneOffset + (sliceIdx + 1) * numSides + sideIdx;
+				}
+			}
+
+			mSpotLightStencilMesh = MeshCore::create(meshData);
+		}
+
+		// TODO - When I add proper preprocessor support, merge these into a single material
+		mResolveMat = bs_shared_ptr_new<ResolveMat>();
+		mBlitMat = bs_shared_ptr_new<BlitMat>();
+	}
+
+	RendererUtility::~RendererUtility()
+	{
+
+	}
+
+	void RendererUtility::setPass(const SPtr<MaterialCore>& material, UINT32 passIdx)
+	{
+		RenderAPICore& rs = RenderAPICore::instance();
+
+		SPtr<PassCore> pass = material->getPass(passIdx);
+		SPtr<PassParametersCore> passParams = material->getPassParameters(passIdx);
+
+		struct StageData
+		{
+			GpuProgramType type;
+			bool enable;
+			SPtr<GpuParamsCore> params;
+			SPtr<GpuProgramCore> program;
+		};
+
+		const UINT32 numStages = 6;
+		StageData stages[numStages] =
+		{
+			{
+				GPT_VERTEX_PROGRAM, pass->hasVertexProgram(),
+				passParams->mVertParams, pass->getVertexProgram()
+			},
+			{
+				GPT_FRAGMENT_PROGRAM, pass->hasFragmentProgram(),
+				passParams->mFragParams, pass->getFragmentProgram()
+			},
+			{
+				GPT_GEOMETRY_PROGRAM, pass->hasGeometryProgram(),
+				passParams->mGeomParams, pass->getGeometryProgram()
+			},
+			{
+				GPT_HULL_PROGRAM, pass->hasHullProgram(),
+				passParams->mHullParams, pass->getHullProgram()
+			},
+			{
+				GPT_DOMAIN_PROGRAM, pass->hasDomainProgram(),
+				passParams->mDomainParams, pass->getDomainProgram()
+			},
+			{
+				GPT_COMPUTE_PROGRAM, pass->hasComputeProgram(),
+				passParams->mComputeParams, pass->getComputeProgram()
+			}
+		};
+
+		for (UINT32 i = 0; i < numStages; i++)
+		{
+			const StageData& stage = stages[i];
+
+			if (stage.enable)
+			{
+				rs.bindGpuProgram(stage.program);
+				rs.setGpuParams(stage.type, stage.params);
+
+			}
+			else
+				rs.unbindGpuProgram(stage.type);
+		}
+
+		// Set up non-texture related pass settings
+		if (pass->getBlendState() != nullptr)
+			rs.setBlendState(pass->getBlendState());
+		else
+			rs.setBlendState(BlendStateCore::getDefault());
+
+		if (pass->getDepthStencilState() != nullptr)
+			rs.setDepthStencilState(pass->getDepthStencilState(), pass->getStencilRefValue());
+		else
+			rs.setDepthStencilState(DepthStencilStateCore::getDefault(), pass->getStencilRefValue());
+
+		if (pass->getRasterizerState() != nullptr)
+			rs.setRasterizerState(pass->getRasterizerState());
+		else
+			rs.setRasterizerState(RasterizerStateCore::getDefault());
+	}
+
+	void RendererUtility::setPassParams(const SPtr<MaterialCore>& material, UINT32 passIdx)
+	{
+		const SPtr<PassParametersCore>& passParams = material->getPassParameters(passIdx);
+
+		RenderAPICore& rs = RenderAPICore::instance();
+
+		struct StageData
+		{
+			GpuProgramType type;
+			SPtr<GpuParamsCore> params;
+		};
+
+		const UINT32 numStages = 6;
+		StageData stages[numStages] =
+		{
+			{ GPT_VERTEX_PROGRAM, passParams->mVertParams },
+			{ GPT_FRAGMENT_PROGRAM, passParams->mFragParams },
+			{ GPT_GEOMETRY_PROGRAM, passParams->mGeomParams },
+			{ GPT_HULL_PROGRAM, passParams->mHullParams },
+			{ GPT_DOMAIN_PROGRAM, passParams->mDomainParams },
+			{ GPT_COMPUTE_PROGRAM, passParams->mComputeParams }
+		};
+
+		for (UINT32 i = 0; i < numStages; i++)
+		{
+			const StageData& stage = stages[i];
+
+			SPtr<GpuParamsCore> params = stage.params;
+			if (params == nullptr)
+				continue;
+
+			const GpuParamDesc& paramDesc = params->getParamDesc();
+
+			for (auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
+			{
+				SPtr<SamplerStateCore> samplerState = params->getSamplerState(iter->second.slot);
+
+				if (samplerState == nullptr)
+					rs.setSamplerState(stage.type, iter->second.slot, SamplerStateCore::getDefault());
+				else
+					rs.setSamplerState(stage.type, iter->second.slot, samplerState);
+			}
+
+			for (auto iter = paramDesc.textures.begin(); iter != paramDesc.textures.end(); ++iter)
+			{
+				SPtr<TextureCore> texture = params->getTexture(iter->second.slot);
+
+				if (!params->isLoadStoreTexture(iter->second.slot))
+				{
+					if (texture == nullptr)
+						rs.setTexture(stage.type, iter->second.slot, false, nullptr);
+					else
+						rs.setTexture(stage.type, iter->second.slot, true, texture);
+				}
+				else
+				{
+					const TextureSurface& surface = params->getLoadStoreSurface(iter->second.slot);
+
+					if (texture == nullptr)
+						rs.setLoadStoreTexture(stage.type, iter->second.slot, false, nullptr, surface);
+					else
+						rs.setLoadStoreTexture(stage.type, iter->second.slot, true, texture, surface);
+				}
+			}
+
+			rs.setConstantBuffers(stage.type, params);
+		}
+	}
+
+	void RendererUtility::draw(const SPtr<MeshCoreBase>& mesh, const SubMesh& subMesh)
+	{
+		RenderAPICore& rs = RenderAPICore::instance();
+		const MeshProperties& meshProps = mesh->getProperties();
+		std::shared_ptr<VertexData> vertexData = mesh->getVertexData();
+
+		rs.setVertexDeclaration(vertexData->vertexDeclaration);
+		auto& vertexBuffers = vertexData->getBuffers();
+
+		if (vertexBuffers.size() > 0)
+		{
+			SPtr<VertexBufferCore> buffers[MAX_BOUND_VERTEX_BUFFERS];
+
+			UINT32 endSlot = 0;
+			UINT32 startSlot = MAX_BOUND_VERTEX_BUFFERS;
+			for (auto iter = vertexBuffers.begin(); iter != vertexBuffers.end(); ++iter)
+			{
+				if (iter->first >= MAX_BOUND_VERTEX_BUFFERS)
+					BS_EXCEPT(InvalidParametersException, "Buffer index out of range");
+
+				startSlot = std::min(iter->first, startSlot);
+				endSlot = std::max(iter->first, endSlot);
+			}
+
+			for (auto iter = vertexBuffers.begin(); iter != vertexBuffers.end(); ++iter)
+			{
+				buffers[iter->first - startSlot] = iter->second;
+			}
+
+			rs.setVertexBuffers(startSlot, buffers, endSlot - startSlot + 1);
+		}
+
+		rs.setDrawOperation(subMesh.drawOp);
+
+		SPtr<IndexBufferCore> indexBuffer = mesh->getIndexBuffer();
+
+		UINT32 indexCount = subMesh.indexCount;
+
+		rs.setIndexBuffer(indexBuffer);
+		rs.drawIndexed(subMesh.indexOffset + mesh->getIndexOffset(), indexCount, mesh->getVertexOffset(), vertexData->vertexCount);
+
+		mesh->_notifyUsedOnGPU();
+	}
+
+	void RendererUtility::blit(const SPtr<TextureCore>& texture, const Rect2I& area)
+	{
+		auto& texProps = texture->getProperties();
+		SPtr<MaterialCore> mat;
+		if (texProps.getMultisampleCount() > 1)
+		{
+			mat = mResolveMat->getMaterial();
+			mResolveMat->setParameters(texture);
+		}
+		else
+		{
+			mat = mBlitMat->getMaterial();
+			mBlitMat->setParameters(texture);
+		}
+
+		setPass(mat, 0);
+		setPassParams(mat);
+
+		Rect2 fArea((float)area.x, (float)area.y, (float)area.width, (float)area.height);
+		if(area.width == 0 || area.height == 0)
+		{
+			fArea.x = 0.0f;
+			fArea.y = 0.0f;
+			fArea.width = (float)texProps.getWidth();
+			fArea.height = (float)texProps.getHeight();
+		}
+
+		drawScreenQuad(fArea);
+	}
+
+	void RendererUtility::drawScreenQuad(const Rect2& uv, const Vector2I& textureSize)
+	{
+		// Note: Consider drawing the quad using a single large triangle for possibly better performance
+
+		Vector3 vertices[4];
+		vertices[0] = Vector3(-1.0f, 1.0f, 0.0f);
+		vertices[1] = Vector3(1.0f, 1.0f, 0.0f);
+		vertices[2] = Vector3(-1.0f, -1.0f, 0.0f);
+		vertices[3] = Vector3(1.0f, -1.0f, 0.0f);
+
+		Vector2 uvs[4];
+
+		if (RenderAPICore::instance().getAPIInfo().getNDCYAxisDown())
+		{
+			uvs[0] = Vector2(uv.x, uv.y);
+			uvs[1] = Vector2(uv.x + uv.width, uv.y);
+			uvs[2] = Vector2(uv.x, uv.y + uv.height);
+			uvs[3] = Vector2(uv.x + uv.width, uv.y + uv.height);
+		}
+		else
+		{
+			uvs[0] = Vector2(uv.x, uv.y + uv.height);
+			uvs[1] = Vector2(uv.x + uv.width, uv.y + uv.height);
+			uvs[2] = Vector2(uv.x, uv.y);
+			uvs[3] = Vector2(uv.x + uv.width, uv.y);
+		}
+
+		for (int i = 0; i < 4; i++)
+		{
+			uvs[i].x /= (float)textureSize.x;
+			uvs[i].y /= (float)textureSize.y;
+		}
+
+		SPtr<VertexDataDesc> vertexDesc = mFullScreenQuadMesh->getVertexDesc();
+		MeshDataPtr meshData = bs_shared_ptr_new<MeshData>(4, 6, vertexDesc);
+
+		auto vecIter = meshData->getVec3DataIter(VES_POSITION);
+		for (UINT32 i = 0; i < 4; i++)
+			vecIter.addValue(vertices[i]);
+
+		auto uvIter = meshData->getVec2DataIter(VES_TEXCOORD);
+		for (UINT32 i = 0; i < 4; i++)
+			uvIter.addValue(uvs[i]);
+
+		auto indices = meshData->getIndices32();
+		indices[0] = 0;
+		indices[1] = 1;
+		indices[2] = 2;
+		indices[3] = 1;
+		indices[4] = 3;
+		indices[5] = 2;
+
+		mFullScreenQuadMesh->writeSubresource(0, *meshData, true, false);
+		draw(mFullScreenQuadMesh, mFullScreenQuadMesh->getProperties().getSubMesh());
+	}
+
+	RendererUtility& gRendererUtility()
+	{
+		return RendererUtility::instance();
+	}
+
+	BlitMat::BlitMat()
+	{
+		mSource = mMaterial->getParamTexture("gSource");
+	}
+
+	void BlitMat::setParameters(const SPtr<TextureCore>& source)
+	{
+		mSource.set(source);
+	}
+
+	ResolveMat::ResolveMat()
+	{
+		mSource = mMaterial->getParamTexture("gSource");
+		mMaterial->getParam("gNumSamples", mNumSamples);
+	}
+
+	void ResolveMat::setParameters(const SPtr<TextureCore>& source)
+	{
+		mSource.set(source);
+
+		UINT32 sampleCount = source->getProperties().getMultisampleCount();
+		mNumSamples.set(sampleCount);
+	}
 }

+ 2 - 29
Source/BansheeGLRenderAPI/Include/BsGLRenderAPI.h

@@ -148,40 +148,13 @@ namespace BansheeEngine
 		void clearViewport(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0, 
 			UINT8 targetMask = 0xFF) 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::getAPIInfo */
+		const RenderAPIInfo& getAPIInfo() const override;
 
 		/**
 		 * @copydoc RenderAPICore::generateParamBlockDesc()

+ 2253 - 2275
Source/BansheeGLRenderAPI/Source/BsGLRenderAPI.cpp

@@ -1,2276 +1,2254 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsGLRenderAPI.h"
-#include "BsRenderAPI.h"
-#include "BsGLTextureManager.h"
-#include "BsGLIndexBuffer.h"
-#include "BsGLUtil.h"
-#include "BsGLSLGpuProgram.h"
-#include "BsException.h"
-#include "BsGLContext.h"
-#include "BsGLSupport.h"
-#include "BsBlendState.h"
-#include "BsRasterizerState.h"
-#include "BsDepthStencilState.h"
-#include "BsGLRenderTexture.h"
-#include "BsGLRenderWindowManager.h"
-#include "BsGLSLProgramPipelineManager.h"
-#include "BsGLVertexArrayObjectManager.h"
-#include "BsRenderStateManager.h"
-#include "BsGpuParams.h"
-#include "BsGLGpuParamBlockBuffer.h"
-#include "BsCoreThread.h"
-#include "BsGLQueryManager.h"
-#include "BsDebug.h"
-#include "BsRenderStats.h"
-#include "BsGpuParamDesc.h"
-
-namespace BansheeEngine 
-{
-	const char* MODULE_NAME = "BansheeGLRenderAPI.dll";
-
-	void __stdcall openGlErrorCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *userParam);
-
-	/************************************************************************/
-	/* 								PUBLIC INTERFACE                   		*/
-	/************************************************************************/
-
-	GLRenderAPI::GLRenderAPI()
-		: mDepthWrite(true),
-		mGLSLProgramFactory(nullptr),
-		mProgramPipelineManager(nullptr),
-		mActivePipeline(nullptr),
-		mActiveTextureUnit(0),
-		mScissorTop(0), mScissorBottom(720), mScissorLeft(0), mScissorRight(1280),
-		mViewportLeft(0), mViewportTop(0), mViewportWidth(0), mViewportHeight(0),
-		mStencilReadMask(0xFFFFFFFF),
-		mStencilWriteMask(0xFFFFFFFF),
-		mStencilCompareFront(CMPF_ALWAYS_PASS),
-		mStencilCompareBack(CMPF_ALWAYS_PASS),
-		mStencilRefValue(0),
-		mFragmentTexOffset(0),
-		mVertexTexOffset(0),
-		mGeometryTexOffset(0),
-		mTextureTypes(nullptr),
-		mNumTextureTypes(0),
-		mFragmentUBOffset(0),
-		mVertexUBOffset(0),
-		mGeometryUBOffset(0),
-		mHullUBOffset(0),
-		mDomainUBOffset(0),
-		mComputeUBOffset(0),
-		mDrawCallInProgress(false),
-		mCurrentDrawOperation(DOT_TRIANGLE_LIST),
-		mViewportNorm(0.0f, 0.0f, 1.0f, 1.0f)
-	{
-		// Get our GLSupport
-		mGLSupport = BansheeEngine::getGLSupport();
-
-		mViewMatrix = Matrix4::IDENTITY;
-
-		mColorWrite[0] = mColorWrite[1] = mColorWrite[2] = mColorWrite[3] = true;
-
-		mCurrentContext = 0;
-		mMainContext = 0;
-
-		mGLInitialised = false;
-
-		mMinFilter = FO_LINEAR;
-		mMipFilter = FO_POINT;
-
-		mProgramPipelineManager = bs_new<GLSLProgramPipelineManager>();
-	}
-
-	GLRenderAPI::~GLRenderAPI()
-	{
-
-	}
-
-	const StringID& GLRenderAPI::getName() const
-	{
-		static StringID strName("GLRenderAPI");
-		return strName;
-	}
-
-	const String& GLRenderAPI::getShadingLanguageName() const
-	{
-		static String strName("glsl");
-		return strName;
-	}
-
-	void GLRenderAPI::initializePrepare()
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		mGLSupport->start();
-		mVideoModeInfo = mGLSupport->getVideoModeInfo();
-
-		RenderWindowManager::startUp<GLRenderWindowManager>(this);
-		RenderWindowCoreManager::startUp<GLRenderWindowCoreManager>(this);
-
-		RenderStateCoreManager::startUp();
-
-		QueryManager::startUp<GLQueryManager>();
-
-		RenderAPICore::initializePrepare();
-	}
-
-	void GLRenderAPI::initializeFinalize(const SPtr<RenderWindowCore>& primaryWindow)
-	{
-		// Get the context from the window and finish initialization
-		SPtr<GLContext> context;
-		primaryWindow->getCustomAttribute("GLCONTEXT", &context);
-
-		// Set main and current context
-		mMainContext = context;
-		mCurrentContext = mMainContext;
-
-		// Set primary context as active
-		if (mCurrentContext)
-			mCurrentContext->setCurrent();
-
-		checkForErrors();
-
-		// Setup GLSupport
-		mGLSupport->initializeExtensions();
-		checkForErrors();
-
-		Vector<BansheeEngine::String> tokens = StringUtil::split(mGLSupport->getGLVersion(), ".");
-
-		if (!tokens.empty())
-		{
-			mDriverVersion.major = parseINT32(tokens[0]);
-			if (tokens.size() > 1)
-				mDriverVersion.minor = parseINT32(tokens[1]);
-			if (tokens.size() > 2)
-				mDriverVersion.release = parseINT32(tokens[2]);
-		}
-		mDriverVersion.build = 0;
-
-		mCurrentCapabilities = createRenderSystemCapabilities();
-		initFromCaps(mCurrentCapabilities);
-		GLVertexArrayObjectManager::startUp();
-		glFrontFace(GL_CW);
-
-		mGLInitialised = true;
-
-		RenderAPICore::initializeFinalize(primaryWindow);
-	}
-
-	void GLRenderAPI::destroyCore()
-	{
-		RenderAPICore::destroyCore();
-
-		// Deleting the GLSL program factory
-		if (mGLSLProgramFactory)
-		{
-			// Remove from manager safely
-			GpuProgramCoreManager::instance().removeFactory(mGLSLProgramFactory);
-			bs_delete(mGLSLProgramFactory);
-			mGLSLProgramFactory = nullptr;
-		}
-
-		// Deleting the hardware buffer manager.  Has to be done before the mGLSupport->stop().
-		HardwareBufferCoreManager::shutDown();
-		HardwareBufferManager::shutDown();
-		GLRTTManager::shutDown();
-
-		mBoundVertexBuffers.clear();
-		mBoundVertexDeclaration = nullptr;
-		mBoundIndexBuffer = nullptr;
-
-		mCurrentVertexProgram = nullptr;
-		mCurrentFragmentProgram = nullptr;
-		mCurrentGeometryProgram = nullptr;
-		mCurrentHullProgram = nullptr;
-		mCurrentDomainProgram = nullptr;
-		mCurrentComputeProgram = nullptr;
-
-		mGLSupport->stop();
-
-		TextureCoreManager::shutDown();
-		TextureManager::shutDown();
-		QueryManager::shutDown();
-		RenderWindowCoreManager::shutDown();
-		RenderWindowManager::shutDown();
-		RenderStateCoreManager::shutDown();
-		GLVertexArrayObjectManager::shutDown(); // Note: Needs to be after QueryManager shutdown as some resources might be waiting for queries to complete
-
-		mGLInitialised = false;
-
-		if(mProgramPipelineManager != nullptr)
-			bs_delete(mProgramPipelineManager);
-
-		if(mGLSupport)
-			bs_delete(mGLSupport);
-
-		if(mTextureTypes != nullptr)
-			bs_deleteN(mTextureTypes, mNumTextureTypes);
-	}
-
-	void GLRenderAPI::bindGpuProgram(const SPtr<GpuProgramCore>& prg)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		SPtr<GLSLGpuProgramCore> glprg = std::static_pointer_cast<GLSLGpuProgramCore>(prg);
-
-		switch (glprg->getProperties().getType())
-		{
-		case GPT_VERTEX_PROGRAM:
-			mCurrentVertexProgram = glprg;
-			break;
-		case GPT_FRAGMENT_PROGRAM:
-			mCurrentFragmentProgram = glprg;
-			break;
-		case GPT_GEOMETRY_PROGRAM:
-			mCurrentGeometryProgram = glprg;
-			break;
-		case GPT_DOMAIN_PROGRAM:
-			mCurrentDomainProgram = glprg;
-			break;
-		case GPT_HULL_PROGRAM:
-			mCurrentHullProgram = glprg;
-			break;
-		case GPT_COMPUTE_PROGRAM:
-			mCurrentComputeProgram = glprg;
-		}
-
-		RenderAPICore::bindGpuProgram(prg);
-	}
-
-	void GLRenderAPI::unbindGpuProgram(GpuProgramType gptype)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		setActiveProgram(gptype, nullptr);
-
-		RenderAPICore::unbindGpuProgram(gptype);
-	}
-
-	void GLRenderAPI::setConstantBuffers(GpuProgramType gptype, const SPtr<GpuParamsCore>& bindableParams)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		bindableParams->updateHardwareBuffers();
-		const GpuParamDesc& paramDesc = bindableParams->getParamDesc();
-		SPtr<GLSLGpuProgramCore> activeProgram = getActiveProgram(gptype);
-		GLuint glProgram = activeProgram->getGLHandle();
-
-		UINT8* uniformBufferData = nullptr;
-
-		UINT32 blockBinding = 0;
-		for(auto iter = paramDesc.paramBlocks.begin(); iter != paramDesc.paramBlocks.end(); ++iter)
-		{
-			SPtr<GpuParamBlockBufferCore> paramBlockBuffer = bindableParams->getParamBlockBuffer(iter->second.slot);
-			if(paramBlockBuffer == nullptr)
-				continue;
-
-			if(iter->second.slot == 0)
-			{
-				// 0 means uniforms are not in block, in which case we handle it specially
-				if (uniformBufferData == nullptr && paramBlockBuffer->getSize() > 0)
-				{
-					uniformBufferData = (UINT8*)bs_alloc(paramBlockBuffer->getSize());
-					paramBlockBuffer->readFromGPU(uniformBufferData); // TODO - Don't read from GPU!? Just read the cached version
-				}
-
-				continue;
-			}
-
-			const GLGpuParamBlockBufferCore* glParamBlockBuffer = static_cast<const GLGpuParamBlockBufferCore*>(paramBlockBuffer.get());
-
-			UINT32 globalBlockBinding = getGLUniformBlockBinding(gptype, blockBinding);
-			glUniformBlockBinding(glProgram, iter->second.slot - 1, globalBlockBinding);
-			glBindBufferRange(GL_UNIFORM_BUFFER, globalBlockBinding, glParamBlockBuffer->getGLHandle(), 0, glParamBlockBuffer->getSize());
-
-			blockBinding++;
-
-			BS_INC_RENDER_STAT(NumGpuParamBufferBinds);
-		}
-
-		bool hasBoundAtLeastOne = false;
-		for(auto iter = paramDesc.params.begin(); iter != paramDesc.params.end(); ++iter)
-		{
-			const GpuParamDataDesc& paramDesc = iter->second;
-
-			if(paramDesc.paramBlockSlot != 0) // 0 means uniforms are not in a block
-				continue;
-
-			const UINT8* ptrData = uniformBufferData + paramDesc.cpuMemOffset * sizeof(UINT32);
-			hasBoundAtLeastOne = true;
-
-			// Note: We don't transpose matrices here even though we don't use column major format
-			// because they are assumed to be pre-transposed in the GpuParams buffer
-			switch(paramDesc.type)
-			{
-			case GPDT_FLOAT1:
-				glProgramUniform1fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLfloat*)ptrData);
-				break;
-			case GPDT_FLOAT2:
-				glProgramUniform2fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLfloat*)ptrData);
-				break;
-			case GPDT_FLOAT3:
-				glProgramUniform3fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLfloat*)ptrData);
-				break;
-			case GPDT_FLOAT4:
-				glProgramUniform4fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLfloat*)ptrData);
-				break;
-			case GPDT_MATRIX_2X2:
-				glProgramUniformMatrix2fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
-					GL_FALSE, (GLfloat*)ptrData);
-				break;
-			case GPDT_MATRIX_2X3:
-				glProgramUniformMatrix3x2fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
-					GL_FALSE, (GLfloat*)ptrData);
-				break;
-			case GPDT_MATRIX_2X4:
-				glProgramUniformMatrix4x2fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
-					GL_FALSE, (GLfloat*)ptrData);
-				break;
-			case GPDT_MATRIX_3X2:
-				glProgramUniformMatrix2x3fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
-					GL_FALSE, (GLfloat*)ptrData);
-				break;
-			case GPDT_MATRIX_3X3:
-				glProgramUniformMatrix3fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
-					GL_FALSE, (GLfloat*)ptrData);
-				break;
-			case GPDT_MATRIX_3X4:
-				glProgramUniformMatrix4x3fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
-					GL_FALSE, (GLfloat*)ptrData);
-				break;
-			case GPDT_MATRIX_4X2:
-				glProgramUniformMatrix2x4fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
-					GL_FALSE, (GLfloat*)ptrData);
-				break;
-			case GPDT_MATRIX_4X3:
-				glProgramUniformMatrix3x4fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
-					GL_FALSE, (GLfloat*)ptrData);
-				break;
-			case GPDT_MATRIX_4X4:
-				glProgramUniformMatrix4fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
-					GL_FALSE, (GLfloat*)ptrData);
-				break;
-			case GPDT_INT1:
-				glProgramUniform1iv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLint*)ptrData);
-				break;
-			case GPDT_INT2:
-				glProgramUniform2iv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLint*)ptrData);
-				break;
-			case GPDT_INT3:
-				glProgramUniform3iv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLint*)ptrData);
-				break;
-			case GPDT_INT4:
-				glProgramUniform4iv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLint*)ptrData);
-				break;
-			case GPDT_BOOL:
-				glProgramUniform1uiv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLuint*)ptrData);
-				break;
-			case GPDT_UNKNOWN:
-				break;
-			}
-		}
-
-		if (hasBoundAtLeastOne)
-			BS_INC_RENDER_STAT(NumGpuParamBufferBinds);
-
-		if(uniformBufferData != nullptr)
-		{
-			bs_free(uniformBufferData);
-		}
-	}
-
-	void GLRenderAPI::setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		unit = getGLTextureUnit(gptype, unit);
-
-		SPtr<GLTextureCore> tex = std::static_pointer_cast<GLTextureCore>(texPtr);
-
-		GLenum lastTextureType = mTextureTypes[unit];
-
-		if (!activateGLTextureUnit(unit))
-			return;
-
-		if (enabled && tex)
-		{
-			mTextureTypes[unit] = tex->getGLTextureTarget();
-			glBindTexture(mTextureTypes[unit], tex->getGLID());
-		}
-		else
-		{
-			// TODO - This doesn't actually disable all textures set on this image unit, only the 2D ones
-			//      - If a non-2D sampler is used, the texture will still be displayed
-
-			glBindTexture(GL_TEXTURE_2D, 0); 
-		}
-
-		activateGLTextureUnit(0);
-
-		BS_INC_RENDER_STAT(NumTextureBinds);
-	}
-
-	void GLRenderAPI::setSamplerState(GpuProgramType gptype, UINT16 unit, const SPtr<SamplerStateCore>& state)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		const SamplerProperties& stateProps = state->getProperties();
-
-		unit = getGLTextureUnit(gptype, unit);
-
-		// Set texture layer filtering
-		setTextureFiltering(unit, FT_MIN, stateProps.getTextureFiltering(FT_MIN));
-		setTextureFiltering(unit, FT_MAG, stateProps.getTextureFiltering(FT_MAG));
-		setTextureFiltering(unit, FT_MIP, stateProps.getTextureFiltering(FT_MIP));
-
-		// Set texture anisotropy
-		setTextureAnisotropy(unit, stateProps.getTextureAnisotropy());
-
-		// Set mipmap biasing
-		setTextureMipmapBias(unit, stateProps.getTextureMipmapBias());
-
-		// Texture addressing mode
-		const UVWAddressingMode& uvw = stateProps.getTextureAddressingMode();
-		setTextureAddressingMode(unit, uvw);
-
-		// Set border color
-		setTextureBorderColor(unit, stateProps.getBorderColor());
-
-		SPtr<GLSLGpuProgramCore> activeProgram = getActiveProgram(gptype);
-		GLuint glProgram = activeProgram->getGLHandle();
-
-		glProgramUniform1i(glProgram, unit, getGLTextureUnit(gptype, unit));
-
-		BS_INC_RENDER_STAT(NumSamplerBinds);
-	}
-
-	void GLRenderAPI::setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr,
-		const TextureSurface& surface)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		// TODO - OpenGL can't bind a certain subset of faces like DX11, only zero, one or all, so I'm ignoring numSlices parameter
-		if (texPtr != nullptr)
-		{
-			SPtr<GLTextureCore> tex = std::static_pointer_cast<GLTextureCore>(texPtr);
-			glBindImageTexture(unit, tex->getGLID(), surface.mipLevel, surface.numArraySlices > 1, 
-				surface.arraySlice, tex->getGLFormat(), GL_READ_WRITE);
-		}
-		else
-			glBindImageTexture(unit, 0, 0, false, 0, 0, GL_READ_WRITE);
-
-		BS_INC_RENDER_STAT(NumTextureBinds);
-	}
-
-	void GLRenderAPI::setBlendState(const SPtr<BlendStateCore>& blendState)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		const BlendProperties& stateProps = blendState->getProperties();
-
-		// Alpha to coverage
-		setAlphaToCoverage(stateProps.getAlphaToCoverageEnabled());
-
-		// Blend states
-		// OpenGL 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 GLRenderAPI::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());
-
-		setMultisamplingEnable(stateProps.getMultisampleEnable());
-
-		setDepthClipEnable(stateProps.getDepthClipEnable());
-
-		setAntialiasedLineEnable(stateProps.getAntialiasedLineEnable());
-
-		BS_INC_RENDER_STAT(NumRasterizerStateChanges);
-	}
-
-	void GLRenderAPI::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(), stateProps.getStencilReadMask(), true);
-
-		setStencilBufferOperations(stateProps.getStencilBackFailOp(), stateProps.getStencilBackZFailOp(), stateProps.getStencilBackPassOp(), false);
-		setStencilBufferFunc(stateProps.getStencilBackCompFunc(), stateProps.getStencilReadMask(), false);
-
-		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 GLRenderAPI::setViewport(const Rect2& area)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		mViewportNorm = area;
-		applyViewport();
-	}
-
-	void GLRenderAPI::setRenderTarget(const SPtr<RenderTargetCore>& target, bool readOnlyDepthStencil)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		// Switch context if different from current one
-		if (target != nullptr)
-		{
-			SPtr<GLContext> newContext;
-			target->getCustomAttribute("GLCONTEXT", &newContext);
-			if (newContext && mCurrentContext != newContext)
-			{
-				switchContext(newContext);
-			}
-		}
-
-		// This must happen after context switch to ensure previous context is still alive
-		mActiveRenderTarget = target;
-
-		GLFrameBufferObject* fbo = nullptr;
-
-		if(target != nullptr)
-			target->getCustomAttribute("FBO", &fbo);
-
-		if (fbo != nullptr)
-		{
-			fbo->bind();
-
-			if (GLEW_EXT_framebuffer_sRGB)
-			{
-				// Enable / disable sRGB states
-				if (target->getProperties().isHwGammaEnabled())
-				{
-					glEnable(GL_FRAMEBUFFER_SRGB_EXT);
-
-					// Note: could test GL_FRAMEBUFFER_SRGB_CAPABLE_EXT here before
-					// enabling, but GL spec says incapable surfaces ignore the setting
-					// anyway. We test the capability to enable isHardwareGammaEnabled.
-				}
-				else
-				{
-					glDisable(GL_FRAMEBUFFER_SRGB_EXT);
-				}
-			}
-		}
-		else
-			glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
-		applyViewport();
-
-		BS_INC_RENDER_STAT(NumRenderTargetChanges);
-	}
-
-	void GLRenderAPI::beginFrame()
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		// Activate the viewport clipping
-		glEnable(GL_SCISSOR_TEST);
-	}
-
-	void GLRenderAPI::endFrame()
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		// Deactivate the viewport clipping.
-		glDisable(GL_SCISSOR_TEST);
-	}
-
-	void GLRenderAPI::setVertexBuffers(UINT32 index, SPtr<VertexBufferCore>* buffers, UINT32 numBuffers)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		if ((index + numBuffers) > (UINT32)mBoundVertexBuffers.size())
-			mBoundVertexBuffers.resize(index + numBuffers);
-
-		for(UINT32 i = 0; i < numBuffers; i++)
-		{
-			mBoundVertexBuffers[index + i] = buffers[i];
-		}
-	}
-
-	void GLRenderAPI::setVertexDeclaration(const SPtr<VertexDeclarationCore>& vertexDeclaration)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		mBoundVertexDeclaration = vertexDeclaration;
-	}
-
-	void GLRenderAPI::setDrawOperation(DrawOperationType op)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		mCurrentDrawOperation = op;
-	}
-
-	void GLRenderAPI::setIndexBuffer(const SPtr<IndexBufferCore>& buffer)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		mBoundIndexBuffer = buffer;
-	}
-
-	void GLRenderAPI::draw(UINT32 vertexOffset, UINT32 vertexCount)
-	{
-		// Find the correct type to render
-		GLint primType = getGLDrawMode();
-		beginDraw();
-
-		glDrawArrays(primType, vertexOffset, vertexCount);
-
-		endDraw();
-
-		UINT32 primCount = vertexCountToPrimCount(mCurrentDrawOperation, vertexCount);
-
-		BS_INC_RENDER_STAT(NumDrawCalls);
-		BS_ADD_RENDER_STAT(NumVertices, vertexCount);
-		BS_ADD_RENDER_STAT(NumPrimitives, primCount);
-	}
-
-	void GLRenderAPI::drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount)
-	{
-		if(mBoundIndexBuffer == nullptr)
-		{
-			LOGWRN("Cannot draw indexed because index buffer is not set.");
-			return;
-		}
-
-		// Find the correct type to render
-		GLint primType = getGLDrawMode();
-
-		beginDraw();
-
-		SPtr<GLIndexBufferCore> indexBuffer = std::static_pointer_cast<GLIndexBufferCore>(mBoundIndexBuffer);
-		const IndexBufferProperties& ibProps = indexBuffer->getProperties();
-		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer->getGLBufferId());
-
-		GLenum indexType = (ibProps.getType() == IT_16BIT) ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
-		glDrawElementsBaseVertex(primType, indexCount, indexType, (GLvoid*)(UINT64)(ibProps.getIndexSize() * startIndex), vertexOffset);
-
-		endDraw();
-		UINT32 primCount = vertexCountToPrimCount(mCurrentDrawOperation, vertexCount);
-
-		BS_INC_RENDER_STAT(NumDrawCalls);
-		BS_ADD_RENDER_STAT(NumVertices, vertexCount);
-		BS_ADD_RENDER_STAT(NumPrimitives, primCount);
-
-		BS_INC_RENDER_STAT(NumIndexBufferBinds);
-	}
-
-	void GLRenderAPI::dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY, UINT32 numGroupsZ)
-	{
-		if (mCurrentComputeProgram == nullptr)
-		{
-			LOGWRN("Cannot dispatch compute without a set compute program.");
-			return;
-		}
-
-		glUseProgram(mCurrentComputeProgram->getGLHandle());
-		glDispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
-
-		BS_INC_RENDER_STAT(NumGpuProgramBinds);
-		BS_INC_RENDER_STAT(NumComputeCalls);
-	}
-
-	void GLRenderAPI::setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		mScissorTop = top;
-		mScissorBottom = bottom;
-		mScissorLeft = left;
-		mScissorRight = right;
-	}
-
-	void GLRenderAPI::clearRenderTarget(UINT32 buffers, const Color& color, float depth, UINT16 stencil, UINT8 targetMask)
-	{
-		if(mActiveRenderTarget == nullptr)
-			return;
-
-		const RenderTargetProperties& rtProps = mActiveRenderTarget->getProperties();
-		Rect2I clearRect(0, 0, rtProps.getWidth(), rtProps.getHeight());
-
-		clearArea(buffers, color, depth, stencil, clearRect, targetMask);
-	}
-
-	void GLRenderAPI::clearViewport(UINT32 buffers, const Color& color, float depth, UINT16 stencil, UINT8 targetMask)
-	{
-		Rect2I clearRect(mViewportLeft, mViewportTop, mViewportWidth, mViewportHeight);
-
-		clearArea(buffers, color, depth, stencil, clearRect, targetMask);
-	}
-
-	void GLRenderAPI::clearArea(UINT32 buffers, const Color& color, float depth, UINT16 stencil, const Rect2I& clearRect, 
-		UINT8 targetMask)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		if(mActiveRenderTarget == nullptr)
-			return;
-
-		bool colorMask = !mColorWrite[0] || !mColorWrite[1] 
-		|| !mColorWrite[2] || !mColorWrite[3]; 
-
-		// Disable scissor test as we want to clear the entire render surface
-		GLboolean scissorTestEnabled = glIsEnabled(GL_SCISSOR_TEST);
-		UINT32 oldScissorTop = mScissorTop;
-		UINT32 oldScissorBottom = mScissorBottom;
-		UINT32 oldScissorLeft = mScissorLeft;
-		UINT32 oldScissorRight = mScissorRight;
-
-		if (scissorTestEnabled)
-		{
-			glDisable(GL_SCISSOR_TEST);
-		}
-
-		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)
-		{
-			setScissorRect(clearRect.x, clearRect.y, clearRect.x + clearRect.width, clearRect.y + clearRect.height);
-			setScissorTestEnable(true);
-		}
-
-		if (buffers & FBT_COLOR)
-		{
-			// Enable buffer for writing if it isn't
-			if (colorMask)
-				glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-		}
-		if (buffers & FBT_DEPTH)
-		{
-			// Enable buffer for writing if it isn't
-			if (!mDepthWrite)
-				glDepthMask(GL_TRUE);
-		}
-		if (buffers & FBT_STENCIL)
-		{
-			// Enable buffer for writing if it isn't
-			glStencilMask(0xFFFFFFFF);
-		}
-
-		if (targetMask == 0xFF)
-		{
-			GLbitfield flags = 0;
-			if (buffers & FBT_COLOR)
-			{
-				flags |= GL_COLOR_BUFFER_BIT;
-
-				glClearColor(color.r, color.g, color.b, color.a);
-			}
-
-			if (buffers & FBT_DEPTH)
-			{
-				flags |= GL_DEPTH_BUFFER_BIT;
-
-				glClearDepth(depth);
-			}
-
-			if (buffers & FBT_STENCIL)
-			{
-				flags |= GL_STENCIL_BUFFER_BIT;
-
-				glClearStencil(stencil);
-			}
-
-			// Clear buffers
-			glClear(flags);
-		}
-		else
-		{
-			GLFrameBufferObject* fbo = nullptr;
-			mActiveRenderTarget->getCustomAttribute("FBO", &fbo);
-
-			if (buffers & FBT_COLOR)
-			{
-				for (UINT32 i = 0; i < BS_MAX_MULTIPLE_RENDER_TARGETS; i++)
-				{
-					if (fbo->hasColorBuffer(i) && ((1 << i) & targetMask) != 0)
-						glClearBufferfv(GL_COLOR, i, (GLfloat*)&color);
-				}
-			}
-
-			if (buffers & FBT_DEPTH)
-			{
-				if (buffers & FBT_STENCIL)
-				{
-					glClearBufferfi(GL_DEPTH_STENCIL, 0, depth, stencil);
-				}
-				else
-				{
-					glClearBufferfv(GL_DEPTH, 0, &depth);
-				}
-			}
-			else if (buffers & FBT_STENCIL)
-			{
-				INT32 stencilClear = (INT32)stencil;
-				glClearBufferiv(GL_STENCIL, 0, &stencilClear);
-			}
-		}
-
-		if (!clearEntireTarget)
-		{
-			setScissorTestEnable(false);
-		}
-
-		// Restore scissor test
-		if (scissorTestEnabled)
-		{
-			glEnable(GL_SCISSOR_TEST);
-
-			mScissorTop = oldScissorTop;
-			mScissorBottom = oldScissorBottom;
-			mScissorLeft = oldScissorLeft;
-			mScissorRight = oldScissorRight;
-		}
-
-		// Reset buffer write state
-		if (!mDepthWrite && (buffers & FBT_DEPTH))
-		{
-			glDepthMask(GL_FALSE);
-		}
-		if (colorMask && (buffers & FBT_COLOR))
-		{
-			glColorMask(mColorWrite[0], mColorWrite[1], mColorWrite[2], mColorWrite[3]);
-		}
-		if (buffers & FBT_STENCIL)
-		{
-			glStencilMask(mStencilWriteMask);
-		}
-
-		BS_INC_RENDER_STAT(NumClears);
-	}
-
-	/************************************************************************/
-	/* 								PRIVATE		                     		*/
-	/************************************************************************/
-
-	void GLRenderAPI::setTextureAddressingMode(UINT16 stage, const UVWAddressingMode& uvw)
-	{
-		if (!activateGLTextureUnit(stage))
-			return;
-
-		glTexParameteri( mTextureTypes[stage], GL_TEXTURE_WRAP_S, 
-			getTextureAddressingMode(uvw.u));
-		glTexParameteri( mTextureTypes[stage], GL_TEXTURE_WRAP_T, 
-			getTextureAddressingMode(uvw.v));
-		glTexParameteri( mTextureTypes[stage], GL_TEXTURE_WRAP_R, 
-			getTextureAddressingMode(uvw.w));
-		activateGLTextureUnit(0);
-	}
-
-	void GLRenderAPI::setTextureBorderColor(UINT16 stage, const Color& colour)
-	{
-		GLfloat border[4] = { colour.r, colour.g, colour.b, colour.a };
-		if (activateGLTextureUnit(stage))
-		{
-			glTexParameterfv(mTextureTypes[stage], GL_TEXTURE_BORDER_COLOR, border);
-			activateGLTextureUnit(0);
-		}
-	}
-
-	void GLRenderAPI::setTextureMipmapBias(UINT16 stage, float bias)
-	{
-		if (mCurrentCapabilities->hasCapability(RSC_MIPMAP_LOD_BIAS))
-		{
-			if (activateGLTextureUnit(stage))
-			{
-				glTexParameterf(mTextureTypes[stage], GL_TEXTURE_LOD_BIAS, bias);
-				activateGLTextureUnit(0);
-			}
-		}
-
-	}
-
-	void GLRenderAPI::setSceneBlending(BlendFactor sourceFactor, BlendFactor destFactor, BlendOperation op )
-	{
-		GLint sourceBlend = getBlendMode(sourceFactor);
-		GLint destBlend = getBlendMode(destFactor);
-		if(sourceFactor == BF_ONE && destFactor == BF_ZERO)
-		{
-			glDisable(GL_BLEND);
-		}
-		else
-		{
-			glEnable(GL_BLEND);
-			glBlendFunc(sourceBlend, destBlend);
-		}
-
-		GLint func = GL_FUNC_ADD;
-		switch(op)
-		{
-		case BO_ADD:
-			func = GL_FUNC_ADD;
-			break;
-		case BO_SUBTRACT:
-			func = GL_FUNC_SUBTRACT;
-			break;
-		case BO_REVERSE_SUBTRACT:
-			func = GL_FUNC_REVERSE_SUBTRACT;
-			break;
-		case BO_MIN:
-			func = GL_MIN;
-			break;
-		case BO_MAX:
-			func = GL_MAX;
-			break;
-		}
-
-		if(GLEW_VERSION_1_4 || GLEW_ARB_imaging)
-		{
-			glBlendEquation(func);
-		}
-		else if(GLEW_EXT_blend_minmax && (func == GL_MIN || func == GL_MAX))
-		{
-			glBlendEquationEXT(func);
-		}
-	}
-
-
-	void GLRenderAPI::setSceneBlending(BlendFactor sourceFactor, BlendFactor destFactor, 
-		BlendFactor sourceFactorAlpha, BlendFactor destFactorAlpha, BlendOperation op, BlendOperation alphaOp)
-	{
-		GLint sourceBlend = getBlendMode(sourceFactor);
-		GLint destBlend = getBlendMode(destFactor);
-		GLint sourceBlendAlpha = getBlendMode(sourceFactorAlpha);
-		GLint destBlendAlpha = getBlendMode(destFactorAlpha);
-
-		if(sourceFactor == BF_ONE && destFactor == BF_ZERO && 
-			sourceFactorAlpha == BF_ONE && destFactorAlpha == BF_ZERO)
-		{
-			glDisable(GL_BLEND);
-		}
-		else
-		{
-			glEnable(GL_BLEND);
-			glBlendFuncSeparate(sourceBlend, destBlend, sourceBlendAlpha, destBlendAlpha);
-		}
-
-		GLint func = GL_FUNC_ADD, alphaFunc = GL_FUNC_ADD;
-
-		switch(op)
-		{
-		case BO_ADD:
-			func = GL_FUNC_ADD;
-			break;
-		case BO_SUBTRACT:
-			func = GL_FUNC_SUBTRACT;
-			break;
-		case BO_REVERSE_SUBTRACT:
-			func = GL_FUNC_REVERSE_SUBTRACT;
-			break;
-		case BO_MIN:
-			func = GL_MIN;
-			break;
-		case BO_MAX:
-			func = GL_MAX;
-			break;
-		}
-
-		switch(alphaOp)
-		{
-		case BO_ADD:
-			alphaFunc = GL_FUNC_ADD;
-			break;
-		case BO_SUBTRACT:
-			alphaFunc = GL_FUNC_SUBTRACT;
-			break;
-		case BO_REVERSE_SUBTRACT:
-			alphaFunc = GL_FUNC_REVERSE_SUBTRACT;
-			break;
-		case BO_MIN:
-			alphaFunc = GL_MIN;
-			break;
-		case BO_MAX:
-			alphaFunc = GL_MAX;
-			break;
-		}
-
-		if(GLEW_VERSION_2_0) {
-			glBlendEquationSeparate(func, alphaFunc);
-		}
-		else if(GLEW_EXT_blend_equation_separate) {
-			glBlendEquationSeparateEXT(func, alphaFunc);
-		}
-	}
-
-	void GLRenderAPI::setAlphaTest(CompareFunction func, unsigned char value)
-	{
-		if(func == CMPF_ALWAYS_PASS)
-		{
-			glDisable(GL_ALPHA_TEST);
-		}
-		else
-		{
-			glEnable(GL_ALPHA_TEST);
-			glAlphaFunc(convertCompareFunction(func), value / 255.0f);
-		}
-	}
-
-	void GLRenderAPI::setAlphaToCoverage(bool enable)
-	{
-		static bool lasta2c = false;
-
-		if (enable != lasta2c && getCapabilities()->hasCapability(RSC_ALPHA_TO_COVERAGE))
-		{
-			if (enable)
-				glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
-			else
-				glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
-
-			lasta2c = enable;
-		}
-	}
-
-	void GLRenderAPI::setScissorTestEnable(bool enable)
-	{
-		const RenderTargetProperties& rtProps = mActiveRenderTarget->getProperties();
-
-		// If request texture flipping, use "upper-left", otherwise use "lower-left"
-		bool flipping = rtProps.requiresTextureFlipping();
-		//  GL measures from the bottom, not the top
-		UINT32 targetHeight = rtProps.getHeight();
-		// Calculate the "lower-left" corner of the viewport
-		GLsizei x = 0, y = 0, w = 0, h = 0;
-
-		if (enable)
-		{
-			glEnable(GL_SCISSOR_TEST);
-			// GL uses width / height rather than right / bottom
-			x = mScissorLeft;
-
-			if (flipping)
-				y = targetHeight - mScissorBottom - 1;
-			else
-				y = mScissorTop;
-
-			w = mScissorRight - mScissorLeft;
-			h = mScissorBottom - mScissorTop;
-
-			glScissor(x, y, w, h);
-		}
-		else
-		{
-			glDisable(GL_SCISSOR_TEST);
-
-			// GL requires you to reset the scissor when disabling
-			w = mViewportWidth;
-			h = mViewportHeight;
-			x = mViewportLeft;
-			y = mViewportTop; 
-
-			glScissor(x, y, w, h);
-		}
-	}
-
-	void GLRenderAPI::setMultisamplingEnable(bool enable)
-	{
-		if (enable)
-			glEnable(GL_MULTISAMPLE);
-		else
-			glDisable(GL_MULTISAMPLE);
-	}
-
-	void GLRenderAPI::setDepthClipEnable(bool enable)
-	{
-		if (enable)
-			glEnable(GL_DEPTH_CLAMP);
-		else
-			glDisable(GL_DEPTH_CLAMP);
-	}
-
-	void GLRenderAPI::setAntialiasedLineEnable(bool enable)
-	{
-		if (enable)
-			glEnable(GL_LINE_SMOOTH);
-		else
-			glDisable(GL_LINE_SMOOTH);
-	}
-
-
-	void GLRenderAPI::setCullingMode(CullingMode mode)
-	{
-		mCullingMode = mode;
-		GLenum cullMode;
-
-		switch( mode )
-		{
-		case CULL_NONE:
-			glDisable(GL_CULL_FACE);
-			return;
-		default:
-		case CULL_CLOCKWISE:
-			cullMode = GL_FRONT;
-			break;
-		case CULL_COUNTERCLOCKWISE:
-			cullMode = GL_BACK;
-			break;
-		}
-
-		glEnable(GL_CULL_FACE);
-		glCullFace(cullMode);
-	}
-
-	void GLRenderAPI::setDepthBufferCheckEnabled(bool enabled)
-	{
-		if (enabled)
-		{
-			glClearDepth(1.0f);
-			glEnable(GL_DEPTH_TEST);
-		}
-		else
-		{
-			glDisable(GL_DEPTH_TEST);
-		}
-	}
-
-	void GLRenderAPI::setDepthBufferWriteEnabled(bool enabled)
-	{
-		GLboolean flag = enabled ? GL_TRUE : GL_FALSE;
-		glDepthMask(flag);  
-
-		mDepthWrite = enabled;
-	}
-
-	void GLRenderAPI::setDepthBufferFunction(CompareFunction func)
-	{
-		glDepthFunc(convertCompareFunction(func));
-	}
-
-	void GLRenderAPI::setDepthBias(float constantBias, float slopeScaleBias)
-	{
-		if (constantBias != 0 || slopeScaleBias != 0)
-		{
-			glEnable(GL_POLYGON_OFFSET_FILL);
-			glEnable(GL_POLYGON_OFFSET_POINT);
-			glEnable(GL_POLYGON_OFFSET_LINE);
-
-			float scaledConstantBias = -constantBias * float((1 << 24) - 1); // Note: Assumes 24-bit depth buffer
-			glPolygonOffset(slopeScaleBias, scaledConstantBias);
-		}
-		else
-		{
-			glDisable(GL_POLYGON_OFFSET_FILL);
-			glDisable(GL_POLYGON_OFFSET_POINT);
-			glDisable(GL_POLYGON_OFFSET_LINE);
-		}
-	}
-
-	void GLRenderAPI::setColorBufferWriteEnabled(bool red, bool green, bool blue, bool alpha)
-	{
-		glColorMask(red, green, blue, alpha);
-		// record this
-		mColorWrite[0] = red;
-		mColorWrite[1] = blue;
-		mColorWrite[2] = green;
-		mColorWrite[3] = alpha;
-	}
-
-	void GLRenderAPI::setPolygonMode(PolygonMode level)
-	{
-		GLenum glmode;
-		switch(level)
-		{
-		case PM_WIREFRAME:
-			glmode = GL_LINE;
-			break;
-		default:
-		case PM_SOLID:
-			glmode = GL_FILL;
-			break;
-		}
-		glPolygonMode(GL_FRONT_AND_BACK, glmode);
-	}
-
-	void GLRenderAPI::setStencilCheckEnabled(bool enabled)
-	{
-		if (enabled)
-			glEnable(GL_STENCIL_TEST);
-		else
-			glDisable(GL_STENCIL_TEST);
-	}
-
-	void GLRenderAPI::setStencilBufferOperations(StencilOperation stencilFailOp,
-		StencilOperation depthFailOp, StencilOperation passOp, bool front)
-	{
-		if (front)
-		{
-			glStencilOpSeparate(GL_FRONT, 
-				convertStencilOp(stencilFailOp),
-				convertStencilOp(depthFailOp), 
-				convertStencilOp(passOp));
-		}
-		else
-		{
-			glStencilOpSeparate(GL_BACK, 
-				convertStencilOp(stencilFailOp, true), 
-				convertStencilOp(depthFailOp, true), 
-				convertStencilOp(passOp, true));
-		}
-	}
-
-	void GLRenderAPI::setStencilBufferFunc(CompareFunction func, UINT32 mask, bool front)
-	{
-		mStencilReadMask = mask;
-
-		if(front)
-		{
-			mStencilCompareFront = func;
-			glStencilFuncSeparate(GL_FRONT, convertCompareFunction(mStencilCompareFront), mStencilRefValue, mStencilReadMask);
-		}
-		else
-		{
-			mStencilCompareBack = func;
-			glStencilFuncSeparate(GL_BACK, convertCompareFunction(mStencilCompareBack), mStencilRefValue, mStencilReadMask);
-		}
-	}
-
-	void GLRenderAPI::setStencilBufferWriteMask(UINT32 mask)
-	{
-		mStencilWriteMask = mask;
-		glStencilMask(mask);
-	}
-
-	void GLRenderAPI::setStencilRefValue(UINT32 refValue)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		mStencilRefValue = refValue;
-
-		glStencilFuncSeparate(GL_FRONT, convertCompareFunction(mStencilCompareFront), mStencilRefValue, mStencilReadMask);
-		glStencilFuncSeparate(GL_BACK, convertCompareFunction(mStencilCompareBack), mStencilRefValue, mStencilReadMask);
-	}
-
-	void GLRenderAPI::setTextureFiltering(UINT16 unit, FilterType ftype, FilterOptions fo)
-	{
-		if (!activateGLTextureUnit(unit))
-			return;
-
-		switch(ftype)
-		{
-		case FT_MIN:
-			mMinFilter = fo;
-			// Combine with existing mip filter
-			glTexParameteri(mTextureTypes[unit], GL_TEXTURE_MIN_FILTER, getCombinedMinMipFilter());
-			break;
-		case FT_MAG:
-			switch (fo)
-			{
-			case FO_ANISOTROPIC: // GL treats linear and aniso the same
-			case FO_LINEAR:
-				glTexParameteri(mTextureTypes[unit], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-				break;
-			case FO_POINT:
-			case FO_NONE:
-				glTexParameteri(mTextureTypes[unit], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-				break;
-			}
-			break;
-		case FT_MIP:
-			mMipFilter = fo;
-			// Combine with existing min filter
-			glTexParameteri(mTextureTypes[unit], GL_TEXTURE_MIN_FILTER, getCombinedMinMipFilter());
-			break;
-		}
-
-		activateGLTextureUnit(0);
-	}
-
-	void GLRenderAPI::setTextureAnisotropy(UINT16 unit, UINT32 maxAnisotropy)
-	{
-		if (!mCurrentCapabilities->hasCapability(RSC_ANISOTROPY))
-			return;
-
-		if (!activateGLTextureUnit(unit))
-			return;
-
-		GLfloat largest_supported_anisotropy = 0;
-		glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy);
-		if (maxAnisotropy > largest_supported_anisotropy)
-			maxAnisotropy = largest_supported_anisotropy ? 
-			static_cast<UINT32>(largest_supported_anisotropy) : 1;
-
-		if(maxAnisotropy < 1)
-			maxAnisotropy = 1;
-
-		if (getCurrentAnisotropy(unit) != maxAnisotropy)
-			glTexParameterf(mTextureTypes[unit], GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)maxAnisotropy);
-
-		activateGLTextureUnit(0);
-	}
-
-	void GLRenderAPI::setClipPlanesImpl(const PlaneList& clipPlanes)
-	{
-		size_t i = 0;
-		size_t numClipPlanes;
-		GLdouble clipPlane[4];
-
-		numClipPlanes = clipPlanes.size();
-		for (i = 0; i < numClipPlanes; ++i)
-		{
-			GLenum clipPlaneId = static_cast<GLenum>(GL_CLIP_PLANE0 + i);
-			const Plane& plane = clipPlanes[i];
-
-			if (i >= 6)
-			{
-				BS_EXCEPT(RenderingAPIException, "Unable to set clip plane");
-			}
-
-			clipPlane[0] = plane.normal.x;
-			clipPlane[1] = plane.normal.y;
-			clipPlane[2] = plane.normal.z;
-			clipPlane[3] = plane.d;
-
-			glClipPlane(clipPlaneId, clipPlane);
-			glEnable(clipPlaneId);
-		}
-
-		// Disable remaining clip planes
-		for (; i < 6; ++i)
-		{
-			glDisable(static_cast<GLenum>(GL_CLIP_PLANE0 + i));
-		}
-	}
-
-	bool GLRenderAPI::activateGLTextureUnit(UINT16 unit)
-	{
-		if (mActiveTextureUnit != unit)
-		{
-			if (unit < getCapabilities()->getNumCombinedTextureUnits())
-			{
-				glActiveTexture(GL_TEXTURE0 + unit);
-				mActiveTextureUnit = unit;
-				return true;
-			}
-			else if (!unit)
-			{
-				// always ok to use the first unit
-				return true;
-			}
-			else
-			{
-				LOGWRN("Provided texture unit index is higher than OpenGL supports. Provided: " + toString(unit) + 
-					". Supported range: 0 .. " + toString(getCapabilities()->getNumCombinedTextureUnits() - 1));
-				return false;
-			}
-		}
-		else
-		{
-			return true;
-		}
-	}
-
-	void GLRenderAPI::beginDraw()
-	{
-		if(mDrawCallInProgress)
-			BS_EXCEPT(InternalErrorException, "Calling beginDraw without finishing previous draw call. Please call endDraw().");
-
-		mDrawCallInProgress = true;
-
-		if(mCurrentVertexProgram == nullptr)
-		{
-			LOGWRN("Cannot render without a set vertex shader.");
-			return;
-		}
-
-		if(mBoundVertexDeclaration == nullptr)
-		{
-			LOGWRN("Cannot render without a set vertex declaration.");
-			return;
-		}
-
-		const GLSLProgramPipeline* pipeline = mProgramPipelineManager->getPipeline(mCurrentVertexProgram.get(), 
-			mCurrentFragmentProgram.get(), mCurrentGeometryProgram.get(), mCurrentHullProgram.get(), mCurrentDomainProgram.get());
-
-		if(mActivePipeline != pipeline)
-		{
-			glBindProgramPipeline(pipeline->glHandle);
-			mActivePipeline = pipeline;
-		}
-
-		const GLVertexArrayObject& vao = GLVertexArrayObjectManager::instance().getVAO(mCurrentVertexProgram, mBoundVertexDeclaration, mBoundVertexBuffers);
-		glBindVertexArray(vao.getGLHandle()); 
-
-		BS_INC_RENDER_STAT(NumVertexBufferBinds);
-		BS_INC_RENDER_STAT(NumGpuProgramBinds);
-	}
-
-	void GLRenderAPI::endDraw()
-	{
-		if(!mDrawCallInProgress)
-			return;
-
-		mDrawCallInProgress = false;
-	}
-
-	GLfloat GLRenderAPI::getCurrentAnisotropy(UINT16 unit)
-	{
-		GLfloat curAniso = 0;
-		glGetTexParameterfv(mTextureTypes[unit], GL_TEXTURE_MAX_ANISOTROPY_EXT, &curAniso);
-
-		return curAniso ? curAniso : 1;
-	}
-
-	GLint GLRenderAPI::convertStencilOp(StencilOperation op, bool invert) const
-	{
-		switch (op)
-		{
-		case SOP_KEEP:
-			return GL_KEEP;
-		case SOP_ZERO:
-			return GL_ZERO;
-		case SOP_REPLACE:
-			return GL_REPLACE;
-		case SOP_INCREMENT:
-			return invert ? GL_DECR : GL_INCR;
-		case SOP_DECREMENT:
-			return invert ? GL_INCR : GL_DECR;
-		case SOP_INCREMENT_WRAP:
-			return invert ? GL_DECR_WRAP_EXT : GL_INCR_WRAP_EXT;
-		case SOP_DECREMENT_WRAP:
-			return invert ? GL_INCR_WRAP_EXT : GL_DECR_WRAP_EXT;
-		case SOP_INVERT:
-			return GL_INVERT;
-		};
-		// to keep compiler happy
-		return SOP_KEEP;
-	}
-
-	GLint GLRenderAPI::convertCompareFunction(CompareFunction func) const
-	{
-		switch (func)
-		{
-		case CMPF_ALWAYS_FAIL:
-			return GL_NEVER;
-		case CMPF_ALWAYS_PASS:
-			return GL_ALWAYS;
-		case CMPF_LESS:
-			return GL_LESS;
-		case CMPF_LESS_EQUAL:
-			return GL_LEQUAL;
-		case CMPF_EQUAL:
-			return GL_EQUAL;
-		case CMPF_NOT_EQUAL:
-			return GL_NOTEQUAL;
-		case CMPF_GREATER_EQUAL:
-			return GL_GEQUAL;
-		case CMPF_GREATER:
-			return GL_GREATER;
-		};
-
-		return GL_ALWAYS;
-	}
-
-	GLuint GLRenderAPI::getCombinedMinMipFilter() const
-	{
-		switch (mMinFilter)
-		{
-		case FO_ANISOTROPIC:
-		case FO_LINEAR:
-			switch (mMipFilter)
-			{
-			case FO_ANISOTROPIC:
-			case FO_LINEAR:
-				// Linear min, linear mip
-				return GL_LINEAR_MIPMAP_LINEAR;
-			case FO_POINT:
-				// Linear min, point mip
-				return GL_LINEAR_MIPMAP_NEAREST;
-			case FO_NONE:
-				// Linear min, no mip
-				return GL_LINEAR;
-			}
-			break;
-		case FO_POINT:
-		case FO_NONE:
-			switch (mMipFilter)
-			{
-			case FO_ANISOTROPIC:
-			case FO_LINEAR:
-				// Nearest min, linear mip
-				return GL_NEAREST_MIPMAP_LINEAR;
-			case FO_POINT:
-				// Nearest min, point mip
-				return GL_NEAREST_MIPMAP_NEAREST;
-			case FO_NONE:
-				// Nearest min, no mip
-				return GL_NEAREST;
-			}
-			break;
-		}
-
-		// Should never get here
-		return 0;
-	}
-
-	GLint GLRenderAPI::getBlendMode(BlendFactor blendMode) const
-	{
-		switch (blendMode)
-		{
-		case BF_ONE:
-			return GL_ONE;
-		case BF_ZERO:
-			return GL_ZERO;
-		case BF_DEST_COLOR:
-			return GL_DST_COLOR;
-		case BF_SOURCE_COLOR:
-			return GL_SRC_COLOR;
-		case BF_INV_DEST_COLOR:
-			return GL_ONE_MINUS_DST_COLOR;
-		case BF_INV_SOURCE_COLOR:
-			return GL_ONE_MINUS_SRC_COLOR;
-		case BF_DEST_ALPHA:
-			return GL_DST_ALPHA;
-		case BF_SOURCE_ALPHA:
-			return GL_SRC_ALPHA;
-		case BF_INV_DEST_ALPHA:
-			return GL_ONE_MINUS_DST_ALPHA;
-		case BF_INV_SOURCE_ALPHA:
-			return GL_ONE_MINUS_SRC_ALPHA;
-		};
-
-		return GL_ONE;
-	}
-
-	GLint GLRenderAPI::getTextureAddressingMode(TextureAddressingMode tam) const
-	{
-		switch (tam)
-		{
-		default:
-		case TAM_WRAP:
-			return GL_REPEAT;
-		case TAM_MIRROR:
-			return GL_MIRRORED_REPEAT;
-		case TAM_CLAMP:
-			return GL_CLAMP_TO_EDGE;
-		case TAM_BORDER:
-			return GL_CLAMP_TO_BORDER;
-		}
-	}
-
-	GLint GLRenderAPI::getGLDrawMode() const
-	{
-		GLint primType;
-
-		// Use adjacency if there is a geometry program and it requested adjacency info
-		bool useAdjacency = (mGeometryProgramBound && mCurrentGeometryProgram->isAdjacencyInfoRequired());
-		switch (mCurrentDrawOperation)
-		{
-		case DOT_POINT_LIST:
-			primType = GL_POINTS;
-			break;
-		case DOT_LINE_LIST:
-			primType = useAdjacency ? GL_LINES_ADJACENCY_EXT : GL_LINES;
-			break;
-		case DOT_LINE_STRIP:
-			primType = useAdjacency ? GL_LINE_STRIP_ADJACENCY_EXT : GL_LINE_STRIP;
-			break;
-		default:
-		case DOT_TRIANGLE_LIST:
-			primType = useAdjacency ? GL_TRIANGLES_ADJACENCY_EXT : GL_TRIANGLES;
-			break;
-		case DOT_TRIANGLE_STRIP:
-			primType = useAdjacency ? GL_TRIANGLE_STRIP_ADJACENCY_EXT : GL_TRIANGLE_STRIP;
-			break;
-		case DOT_TRIANGLE_FAN:
-			primType = GL_TRIANGLE_FAN;
-			break;
-		}
-
-		return primType;
-	}
-
-	UINT32 GLRenderAPI::getGLTextureUnit(GpuProgramType gptype, UINT32 unit)
-	{
-		if (gptype != GPT_VERTEX_PROGRAM && gptype != GPT_FRAGMENT_PROGRAM && gptype != GPT_GEOMETRY_PROGRAM)
-		{
-			BS_EXCEPT(InvalidParametersException, "OpenGL cannot assign textures to this gpu program type: " + toString(gptype));
-		}
-
-		UINT32 numSupportedUnits = mCurrentCapabilities->getNumTextureUnits(gptype);
-		if (unit < 0 || unit >= numSupportedUnits)
-		{
-			BS_EXCEPT(InvalidParametersException, "Invalid texture unit index for the provided stage. Unit index: " + toString(unit) + ". Stage: " +
-				toString(gptype) + ". Supported range is 0 .. " + toString(numSupportedUnits - 1));
-		}
-
-		switch (gptype)
-		{
-		case GPT_FRAGMENT_PROGRAM:
-			return mFragmentTexOffset + unit;
-		case GPT_VERTEX_PROGRAM:
-			return mVertexTexOffset + unit;
-		case GPT_GEOMETRY_PROGRAM:
-			return mGeometryTexOffset + unit;
-		default:
-			BS_EXCEPT(InternalErrorException, "Invalid program type: " + toString(gptype));
-		}
-
-		return 0;
-	}
-
-	UINT32 GLRenderAPI::getGLUniformBlockBinding(GpuProgramType gptype, UINT32 binding)
-	{
-		UINT32 maxNumBindings = mCurrentCapabilities->getNumGpuParamBlockBuffers(gptype);
-		if (binding < 0 || binding >= maxNumBindings)
-		{
-			BS_EXCEPT(InvalidParametersException, "Invalid buffer binding for the provided stage. Buffer binding: " + toString(binding) + ". Stage: " +
-				toString(gptype) + ". Supported range is 0 .. " + toString(maxNumBindings - 1));
-		}
-
-		switch (gptype)
-		{
-		case GPT_FRAGMENT_PROGRAM:
-			return mFragmentUBOffset + binding;
-		case GPT_VERTEX_PROGRAM:
-			return mVertexUBOffset + binding;
-		case GPT_GEOMETRY_PROGRAM:
-			return mGeometryUBOffset + binding;
-		case GPT_HULL_PROGRAM:
-			return mHullUBOffset + binding;
-		case GPT_DOMAIN_PROGRAM:
-			return mDomainUBOffset + binding;
-		case GPT_COMPUTE_PROGRAM:
-			return mComputeUBOffset + binding;
-		default:
-			BS_EXCEPT(InternalErrorException, "Invalid program type: " + toString(gptype));
-		}
-
-		return 0;
-	}
-
-	void GLRenderAPI::setActiveProgram(GpuProgramType gptype, const SPtr<GLSLGpuProgramCore>& program)
-	{
-		switch (gptype)
-		{
-		case GPT_VERTEX_PROGRAM:
-			mCurrentVertexProgram = program;
-			break;
-		case GPT_FRAGMENT_PROGRAM:
-			mCurrentFragmentProgram = program;
-			break;
-		case GPT_GEOMETRY_PROGRAM:
-			mCurrentGeometryProgram = program;
-			break;
-		case GPT_DOMAIN_PROGRAM:
-			mCurrentDomainProgram = program;
-			break;
-		case GPT_HULL_PROGRAM:
-			mCurrentHullProgram = program;
-			break;
-		case GPT_COMPUTE_PROGRAM:
-			mCurrentComputeProgram = program;
-			break;
-		}
-	}
-
-	SPtr<GLSLGpuProgramCore> GLRenderAPI::getActiveProgram(GpuProgramType gptype) const
-	{
-		switch (gptype)
-		{
-		case GPT_VERTEX_PROGRAM:
-			return mCurrentVertexProgram;
-		case GPT_FRAGMENT_PROGRAM:
-			return mCurrentFragmentProgram;
-		case GPT_GEOMETRY_PROGRAM:
-			return mCurrentGeometryProgram;
-		case GPT_DOMAIN_PROGRAM:
-			return mCurrentDomainProgram;
-		case GPT_HULL_PROGRAM:
-			return mCurrentHullProgram;
-		case GPT_COMPUTE_PROGRAM:
-			return mCurrentComputeProgram;
-		default:
-			BS_EXCEPT(InvalidParametersException, "Insupported gpu program type: " + toString(gptype));
-		}
-
-		return nullptr;
-	}
-
-	void GLRenderAPI::initFromCaps(RenderAPICapabilities* caps)
-	{
-		if(caps->getRenderAPIName() != getName())
-		{
-			BS_EXCEPT(InvalidParametersException, 
-				"Trying to initialize GLRenderAPI from RenderSystemCapabilities that do not support OpenGL");
-		}
-
-#if BS_DEBUG_MODE
-		if (mGLSupport->checkExtension("GL_ARB_debug_output"))
-		{
-			glDebugMessageCallback(&openGlErrorCallback, 0);
-			glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
-		}
-#endif
-
-		HardwareBufferManager::startUp();
-		HardwareBufferCoreManager::startUp<GLHardwareBufferCoreManager>();
-
-		// GPU Program Manager setup
-		if(caps->isShaderProfileSupported("glsl"))
-		{
-			mGLSLProgramFactory = bs_new<GLSLProgramFactory>();
-			GpuProgramCoreManager::instance().addFactory(mGLSLProgramFactory);
-		}
-
-		// Check for framebuffer object extension
-		if(caps->hasCapability(RSC_FBO))
-		{
-			if(caps->hasCapability(RSC_HWRENDER_TO_TEXTURE))
-			{
-				// Create FBO manager
-				GLRTTManager::startUp<GLRTTManager>();
-			}
-		}
-		else
-		{
-			BS_EXCEPT(RenderingAPIException, "GPU doesn't support frame buffer objects. OpenGL versions lower than 3.0 are not supported.");
-		}
-
-		mFragmentTexOffset = 0;
-		mVertexTexOffset = caps->getNumTextureUnits(GPT_FRAGMENT_PROGRAM);
-		mGeometryTexOffset = mVertexTexOffset + caps->getNumTextureUnits(GPT_VERTEX_PROGRAM);
-
-		UINT16 numCombinedTexUnits = caps->getNumCombinedTextureUnits();
-
-		UINT32 totalNumTexUnits = caps->getNumTextureUnits(GPT_VERTEX_PROGRAM);
-		totalNumTexUnits += caps->getNumTextureUnits(GPT_FRAGMENT_PROGRAM);
-		totalNumTexUnits += caps->getNumTextureUnits(GPT_GEOMETRY_PROGRAM);
-		totalNumTexUnits += caps->getNumTextureUnits(GPT_HULL_PROGRAM);
-		totalNumTexUnits += caps->getNumTextureUnits(GPT_DOMAIN_PROGRAM);
-		totalNumTexUnits += caps->getNumTextureUnits(GPT_COMPUTE_PROGRAM);
-
-		if(totalNumTexUnits > numCombinedTexUnits)
-			BS_EXCEPT(InternalErrorException, "Number of combined texture units less than the number of individual units!?");
-
-		mNumTextureTypes = numCombinedTexUnits;
-		mTextureTypes = bs_newN<GLenum>(mNumTextureTypes);
-		for(UINT16 i = 0; i < numCombinedTexUnits; i++)
-			mTextureTypes[i] = GL_TEXTURE_2D;
-
-		mVertexUBOffset = 0;
-		UINT32 totalNumUniformBlocks = caps->getNumGpuParamBlockBuffers(GPT_VERTEX_PROGRAM);
-		mFragmentUBOffset = totalNumUniformBlocks;
-		totalNumUniformBlocks += caps->getNumGpuParamBlockBuffers(GPT_FRAGMENT_PROGRAM);
-		mGeometryUBOffset = totalNumUniformBlocks;
-		totalNumUniformBlocks += caps->getNumGpuParamBlockBuffers(GPT_GEOMETRY_PROGRAM);
-		mHullUBOffset = totalNumUniformBlocks;
-		totalNumUniformBlocks += caps->getNumGpuParamBlockBuffers(GPT_HULL_PROGRAM);
-		mDomainUBOffset = totalNumUniformBlocks;
-		totalNumUniformBlocks += caps->getNumGpuParamBlockBuffers(GPT_DOMAIN_PROGRAM);
-		mComputeUBOffset = totalNumUniformBlocks;
-		totalNumUniformBlocks += caps->getNumGpuParamBlockBuffers(GPT_COMPUTE_PROGRAM);
-
-		UINT16 numCombinedUniformBlocks = caps->getNumCombinedGpuParamBlockBuffers();
-
-		if(totalNumUniformBlocks > numCombinedUniformBlocks)
-			BS_EXCEPT(InternalErrorException, "Number of combined uniform block buffers less than the number of individual per-stage buffers!?");
-
-		TextureManager::startUp<GLTextureManager>(std::ref(*mGLSupport));
-		TextureCoreManager::startUp<GLTextureCoreManager>(std::ref(*mGLSupport));
-	}
-
-	void GLRenderAPI::switchContext(const SPtr<GLContext>& context)
-	{
-		// Unbind GPU programs and rebind to new context later, because
-		// scene manager treat render system as ONE 'context' ONLY, and it
-		// cached the GPU programs using state.
-		unbindGpuProgram(GPT_VERTEX_PROGRAM);
-		unbindGpuProgram(GPT_FRAGMENT_PROGRAM);
-		unbindGpuProgram(GPT_GEOMETRY_PROGRAM);
-		unbindGpuProgram(GPT_HULL_PROGRAM);
-		unbindGpuProgram(GPT_DOMAIN_PROGRAM);
-		unbindGpuProgram(GPT_COMPUTE_PROGRAM);
-
-		// It's ready for switching
-		if (mCurrentContext)
-			mCurrentContext->endCurrent();
-
-		mCurrentContext = context;
-		mCurrentContext->setCurrent();
-
-		// Must reset depth/colour write mask to according with user desired, otherwise,
-		// clearFrameBuffer would be wrong because the value we are recorded may be
-		// difference with the really state stored in GL context.
-		glDepthMask(mDepthWrite);
-		glColorMask(mColorWrite[0], mColorWrite[1], mColorWrite[2], mColorWrite[3]);
-		glStencilMask(mStencilWriteMask);
-	}
-
-	RenderAPICapabilities* GLRenderAPI::createRenderSystemCapabilities() const
-	{
-		RenderAPICapabilities* rsc = bs_new<RenderAPICapabilities>();
-
-		rsc->setDriverVersion(mDriverVersion);
-		const char* deviceName = (const char*)glGetString(GL_RENDERER);
-		const char* vendorName = (const char*)glGetString(GL_VENDOR);
-		rsc->setDeviceName(deviceName);
-		rsc->setRenderAPIName(getName());
-
-		// determine vendor
-		if (strstr(vendorName, "NVIDIA"))
-			rsc->setVendor(GPU_NVIDIA);
-		else if (strstr(vendorName, "ATI"))
-			rsc->setVendor(GPU_AMD);
-		else if (strstr(vendorName, "AMD"))
-			rsc->setVendor(GPU_AMD);
-		else if (strstr(vendorName, "Intel"))
-			rsc->setVendor(GPU_INTEL);
-		else
-			rsc->setVendor(GPU_UNKNOWN);
-
-		// Check for hardware mipmapping support.
-		if(GLEW_VERSION_1_4)
-		{
-			rsc->setCapability(RSC_AUTOMIPMAP);
-		}
-
-		// Check for Anisotropy support
-		if (getGLSupport()->checkExtension("GL_EXT_texture_filter_anisotropic"))
-		{
-			rsc->setCapability(RSC_ANISOTROPY);
-		}
-
-		// Check for cube mapping
-		if(GLEW_VERSION_1_3 || 
-			getGLSupport()->checkExtension("GL_ARB_texture_cube_map") ||
-			getGLSupport()->checkExtension("GL_EXT_texture_cube_map"))
-		{
-			rsc->setCapability(RSC_CUBEMAPPING);
-		}
-
-		// Point sprites
-		if (GLEW_VERSION_2_0 || getGLSupport()->checkExtension("GL_ARB_point_sprite"))
-		{
-			rsc->setCapability(RSC_POINT_SPRITES);
-		}
-
-		// Check for hardware stencil support and set bit depth
-		GLint stencil;
-		glGetIntegerv(GL_STENCIL_BITS, &stencil);
-
-		if(stencil)
-		{
-			rsc->setStencilBufferBitDepth(stencil);
-		}
-
-		if (GLEW_VERSION_2_0 || 
-			(getGLSupport()->checkExtension("GL_ARB_shading_language_100") &&
-			getGLSupport()->checkExtension("GL_ARB_shader_objects") &&
-			getGLSupport()->checkExtension("GL_ARB_fragment_shader") &&
-			getGLSupport()->checkExtension("GL_ARB_vertex_shader")))
-		{
-			rsc->addShaderProfile("glsl");
-		}
-
-		// Check if geometry shaders are supported
-		if (GLEW_VERSION_2_0 &&
-			getGLSupport()->checkExtension("GL_EXT_geometry_shader4"))
-		{
-			rsc->setCapability(RSC_GEOMETRY_PROGRAM);
-
-			rsc->setGeometryProgramConstantBoolCount(0);
-			rsc->setGeometryProgramConstantIntCount(0);
-
-			GLint floatConstantCount = 0;
-			glGetIntegerv(GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT, &floatConstantCount);
-			rsc->setGeometryProgramConstantFloatCount(floatConstantCount);
-
-			GLint maxOutputVertices;
-			glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT,&maxOutputVertices);
-			rsc->setGeometryProgramNumOutputVertices(maxOutputVertices);
-		}
-
-		//Check if render to vertex buffer (transform feedback in OpenGL)
-		if (GLEW_VERSION_2_0 && getGLSupport()->checkExtension("GL_EXT_transform_feedback"))
-		{
-			rsc->setCapability(RSC_HWRENDER_TO_VERTEX_BUFFER);
-		}
-
-		// Check for texture compression
-		if (GLEW_VERSION_1_3 || getGLSupport()->checkExtension("GL_ARB_texture_compression"))
-		{   
-			rsc->setCapability(RSC_TEXTURE_COMPRESSION);
-
-			// Check for dxt compression
-			if (getGLSupport()->checkExtension("GL_EXT_texture_compression_s3tc"))
-			{
-				rsc->setCapability(RSC_TEXTURE_COMPRESSION_DXT);
-			}
-
-			// Check for vtc compression
-			if (getGLSupport()->checkExtension("GL_NV_texture_compression_vtc"))
-			{
-				rsc->setCapability(RSC_TEXTURE_COMPRESSION_VTC);
-			}
-		}
-
-		// As are user clipping planes
-		rsc->setCapability(RSC_USER_CLIP_PLANES);
-
-		// 2-sided stencil?
-		if (GLEW_VERSION_2_0 || getGLSupport()->checkExtension("GL_EXT_stencil_two_side"))
-		{
-			rsc->setCapability(RSC_TWO_SIDED_STENCIL);
-		}
-
-		// stencil wrapping?
-		if (GLEW_VERSION_1_4 || getGLSupport()->checkExtension("GL_EXT_stencil_wrap"))
-		{
-			rsc->setCapability(RSC_STENCIL_WRAP);
-		}
-
-		// Check for hardware occlusion support
-		if (GLEW_VERSION_1_5 || getGLSupport()->checkExtension("GL_ARB_occlusion_query"))
-		{
-			rsc->setCapability(RSC_HWOCCLUSION);
-		}
-
-		// UBYTE4 always supported
-		rsc->setCapability(RSC_VERTEX_FORMAT_UBYTE4);
-
-		// Infinite far plane always supported
-		rsc->setCapability(RSC_INFINITE_FAR_PLANE);
-
-		// Check for non-power-of-2 texture support
-		if (getGLSupport()->checkExtension("GL_ARB_texture_non_power_of_two"))
-		{
-			rsc->setCapability(RSC_NON_POWER_OF_2_TEXTURES);
-		}
-
-		// Check for Float textures
-		if (getGLSupport()->checkExtension("GL_ATI_texture_float") || getGLSupport()->checkExtension("GL_ARB_texture_float"))
-		{
-			rsc->setCapability(RSC_TEXTURE_FLOAT);
-		}
-
-		// 3D textures should always be supported
-		rsc->setCapability(RSC_TEXTURE_3D);
-
-		// Check for framebuffer object extension
-		if (getGLSupport()->checkExtension("GL_ARB_framebuffer_object"))
-		{
-			// Probe number of draw buffers
-			// Only makes sense with FBO support, so probe here
-			if (GLEW_VERSION_2_0 || getGLSupport()->checkExtension("GL_ARB_draw_buffers") || getGLSupport()->checkExtension("GL_ATI_draw_buffers"))
-			{
-				GLint buffers;
-				glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &buffers);
-				rsc->setNumMultiRenderTargets(std::min<int>(buffers, (GLint)BS_MAX_MULTIPLE_RENDER_TARGETS));
-				rsc->setCapability(RSC_MRT_DIFFERENT_BIT_DEPTHS);
-
-				rsc->setCapability(RSC_FBO);
-
-			}
-			rsc->setCapability(RSC_HWRENDER_TO_TEXTURE);
-		}
-
-		rsc->setCapability(RSC_HWRENDER_TO_TEXTURE);
-		rsc->setCapability(RSC_PBUFFER);
-
-		// Point size
-		float ps;
-		glGetFloatv(GL_POINT_SIZE_MAX, &ps);
-		rsc->setMaxPointSize(ps);
-
-		// Max number of fragment shader textures
-		GLint units;
-		glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &units);
-		rsc->setNumTextureUnits(GPT_FRAGMENT_PROGRAM, static_cast<UINT16>(units));
-
-		// Max number of vertex shader textures
-		GLint vUnits;
-		glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &vUnits);
-		rsc->setNumTextureUnits(GPT_VERTEX_PROGRAM, static_cast<UINT16>(vUnits));
-		if (vUnits > 0)
-		{
-			rsc->setCapability(RSC_VERTEX_TEXTURE_FETCH);
-		}
-
-		GLint numUniformBlocks;
-		glGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS, &numUniformBlocks);
-		rsc->setNumGpuParamBlockBuffers(GPT_VERTEX_PROGRAM, numUniformBlocks);
-
-		glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS, &numUniformBlocks);
-		rsc->setNumGpuParamBlockBuffers(GPT_FRAGMENT_PROGRAM, numUniformBlocks);
-
-		if (mGLSupport->checkExtension("GL_ARB_geometry_shader4"))
-		{
-			GLint geomUnits;
-			glGetIntegerv(GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, &geomUnits);
-			rsc->setNumTextureUnits(GPT_GEOMETRY_PROGRAM, static_cast<UINT16>(geomUnits));
-
-			glGetIntegerv(GL_MAX_GEOMETRY_UNIFORM_BLOCKS, &numUniformBlocks);
-			rsc->setNumGpuParamBlockBuffers(GPT_GEOMETRY_PROGRAM, numUniformBlocks);
-		}
-
-		if (mGLSupport->checkExtension("GL_ARB_tessellation_shader"))
-		{
-			rsc->setCapability(RSC_TESSELLATION_PROGRAM);
-
-			glGetIntegerv(GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS, &numUniformBlocks);
-			rsc->setNumGpuParamBlockBuffers(GPT_HULL_PROGRAM, numUniformBlocks);
-
-			glGetIntegerv(GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS, &numUniformBlocks);
-			rsc->setNumGpuParamBlockBuffers(GPT_DOMAIN_PROGRAM, numUniformBlocks);
-		}
-
-		if (mGLSupport->checkExtension("GL_ARB_compute_shader")) 
-		{
-			rsc->setCapability(RSC_COMPUTE_PROGRAM);
-
-			GLint computeUnits;
-			glGetIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &computeUnits);
-			rsc->setNumTextureUnits(GPT_COMPUTE_PROGRAM, static_cast<UINT16>(computeUnits));
-
-			glGetIntegerv(GL_MAX_COMPUTE_UNIFORM_BLOCKS, &numUniformBlocks);
-			rsc->setNumGpuParamBlockBuffers(GPT_COMPUTE_PROGRAM, numUniformBlocks);
-		}
-
-		GLint combinedTexUnits;
-		glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &combinedTexUnits);
-		rsc->setNumCombinedTextureUnits(static_cast<UINT16>(combinedTexUnits));
-
-		GLint combinedUniformBlockUnits;
-		glGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS, &combinedUniformBlockUnits);
-		rsc->setNumCombinedGpuParamBlockBuffers(static_cast<UINT16>(combinedUniformBlockUnits));
-
-		// Mipmap LOD biasing
-
-		if (mGLSupport->checkExtension("GL_EXT_texture_lod_bias"))
-			rsc->setCapability(RSC_MIPMAP_LOD_BIAS);
-
-		// Alpha to coverage?
-		if (mGLSupport->checkExtension("GL_ARB_multisample"))
-		{
-			// Alpha to coverage always 'supported' when MSAA is available
-			// although card may ignore it if it doesn't specifically support A2C
-			rsc->setCapability(RSC_ALPHA_TO_COVERAGE);
-		}
-
-		// Advanced blending operations
-		if(GLEW_VERSION_2_0)
-		{
-			rsc->setCapability(RSC_ADVANCED_BLEND_OPERATIONS);
-		}
-
-		return rsc;
-	}
-
-	bool GLRenderAPI::checkForErrors() const
-	{
-		GLenum glErr = glGetError();
-		bool errorsFound = false;
-		String msg;
-		while (glErr != GL_NO_ERROR)
-		{
-			const char* glerrStr = (const char*)gluErrorString(glErr);
-			if (glerrStr)
-			{
-				msg += String(glerrStr);
-			}
-			glErr = glGetError();
-			errorsFound = true;
-		}
-
-		if (errorsFound)
-			LOGWRN("OpenGL error: " + msg);
-
-		return errorsFound;
-	}
-
-	void GLRenderAPI::makeGLMatrix(GLfloat gl_matrix[16], const Matrix4& m)
-	{
-		UINT32 x = 0;
-		for (UINT32 i = 0; i < 4; i++)
-		{
-			for (UINT32 j = 0; j < 4; j++)
-			{
-				gl_matrix[x] = m[j][i];
-				x++;
-			}
-		}
-	}
-
-	void GLRenderAPI::applyViewport()
-	{
-		if (mActiveRenderTarget == nullptr)
-			return;
-
-		const RenderTargetProperties& rtProps = mActiveRenderTarget->getProperties();
-
-		// Calculate the "lower-left" corner of the viewport
-		mViewportLeft = (UINT32)(rtProps.getWidth() * mViewportNorm.x);
-		mViewportTop = (UINT32)(rtProps.getHeight() * mViewportNorm.y);
-		mViewportWidth = (UINT32)(rtProps.getWidth() * mViewportNorm.width);
-		mViewportHeight = (UINT32)(rtProps.getHeight() * mViewportNorm.height);
-
-		if (rtProps.requiresTextureFlipping())
-		{
-			// Convert "upper-left" corner to "lower-left"
-			mViewportTop = rtProps.getHeight() - (mViewportTop + mViewportHeight) - 1;
-		}
-
-		glViewport(mViewportLeft, mViewportTop, mViewportWidth, mViewportHeight);
-
-		// Configure the viewport clipping
-		glScissor(mViewportLeft, mViewportTop, mViewportWidth, mViewportHeight);
-	}
-
-	/************************************************************************/
-	/* 								UTILITY		                     		*/
-	/************************************************************************/
-	float GLRenderAPI::getMinimumDepthInputValue()
-	{
-		return -1.0f;
-	}
-
-	float GLRenderAPI::getMaximumDepthInputValue()
-	{
-		return 1.0f;
-	}
-
-	float GLRenderAPI::getHorizontalTexelOffset()
-	{
-		return 0.0f;
-	}
-
-	float GLRenderAPI::getVerticalTexelOffset()
-	{
-		return 0.0f;
-	}
-
-	VertexElementType GLRenderAPI::getColorVertexElementType() const
-	{
-		return VET_COLOR_ABGR;
-	}
-
-	void GLRenderAPI::convertProjectionMatrix(const Matrix4& matrix, Matrix4& dest)
-	{
-		dest = matrix;
-	}
-
-	bool GLRenderAPI::getGpuProgramHasColumnMajorMatrices() const 
-	{ 
-		return true; 
-	}
-
-	GpuParamBlockDesc GLRenderAPI::generateParamBlockDesc(const String& name, Vector<GpuParamDataDesc>& params)
-	{
-		GpuParamBlockDesc block;
-		block.blockSize = 0;
-		block.isShareable = true;
-		block.name = name;
-		block.slot = 0;
-
-		for (auto& param : params)
-		{
-			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[param.type];
-			UINT32 size = typeInfo.size / 4;
-			UINT32 alignment = typeInfo.alignment / 4;
-
-			// Fix alignment if needed
-			UINT32 alignOffset = block.blockSize % alignment;
-			if (alignOffset != 0)
-			{
-				UINT32 padding = (alignment - alignOffset);
-				block.blockSize += padding;
-			}
-
-			if (param.arraySize > 1)
-			{
-				// Array elements are always padded and aligned to vec4
-				alignOffset = size % typeInfo.baseTypeSize;
-				if (alignOffset != 0)
-				{
-					UINT32 padding = (typeInfo.baseTypeSize - alignOffset);
-					size += padding;
-				}
-
-				alignOffset = block.blockSize % typeInfo.baseTypeSize;
-				if (alignOffset != 0)
-				{
-					UINT32 padding = (typeInfo.baseTypeSize - alignOffset);
-					block.blockSize += padding;
-				}
-
-				param.elementSize = size;
-				param.arrayElementStride = size;
-				param.cpuMemOffset = block.blockSize;
-				param.gpuMemOffset = 0;
-				
-				block.blockSize += size * param.arraySize;
-			}
-			else
-			{
-				param.elementSize = size;
-				param.arrayElementStride = size;
-				param.cpuMemOffset = block.blockSize;
-				param.gpuMemOffset = 0;
-
-				block.blockSize += size;
-			}
-
-			param.paramBlockSlot = 0;
-		}
-
-		// Constant buffer size must always be a multiple of 16
-		if (block.blockSize % 4 != 0)
-			block.blockSize += (4 - (block.blockSize % 4));
-
-		return block;
-	}
-
-	void __stdcall openGlErrorCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *userParam)
-	{
-		if (type != GL_DEBUG_TYPE_PERFORMANCE && type != GL_DEBUG_TYPE_OTHER)
-		{
-			BS_EXCEPT(RenderingAPIException, "OpenGL error: " + String(message));
-		}
-	}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsGLRenderAPI.h"
+#include "BsRenderAPI.h"
+#include "BsGLTextureManager.h"
+#include "BsGLIndexBuffer.h"
+#include "BsGLUtil.h"
+#include "BsGLSLGpuProgram.h"
+#include "BsException.h"
+#include "BsGLContext.h"
+#include "BsGLSupport.h"
+#include "BsBlendState.h"
+#include "BsRasterizerState.h"
+#include "BsDepthStencilState.h"
+#include "BsGLRenderTexture.h"
+#include "BsGLRenderWindowManager.h"
+#include "BsGLSLProgramPipelineManager.h"
+#include "BsGLVertexArrayObjectManager.h"
+#include "BsRenderStateManager.h"
+#include "BsGpuParams.h"
+#include "BsGLGpuParamBlockBuffer.h"
+#include "BsCoreThread.h"
+#include "BsGLQueryManager.h"
+#include "BsDebug.h"
+#include "BsRenderStats.h"
+#include "BsGpuParamDesc.h"
+
+namespace BansheeEngine 
+{
+	const char* MODULE_NAME = "BansheeGLRenderAPI.dll";
+
+	void __stdcall openGlErrorCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *userParam);
+
+	/************************************************************************/
+	/* 								PUBLIC INTERFACE                   		*/
+	/************************************************************************/
+
+	GLRenderAPI::GLRenderAPI()
+		: mDepthWrite(true),
+		mGLSLProgramFactory(nullptr),
+		mProgramPipelineManager(nullptr),
+		mActivePipeline(nullptr),
+		mActiveTextureUnit(0),
+		mScissorTop(0), mScissorBottom(720), mScissorLeft(0), mScissorRight(1280),
+		mViewportLeft(0), mViewportTop(0), mViewportWidth(0), mViewportHeight(0),
+		mStencilReadMask(0xFFFFFFFF),
+		mStencilWriteMask(0xFFFFFFFF),
+		mStencilCompareFront(CMPF_ALWAYS_PASS),
+		mStencilCompareBack(CMPF_ALWAYS_PASS),
+		mStencilRefValue(0),
+		mFragmentTexOffset(0),
+		mVertexTexOffset(0),
+		mGeometryTexOffset(0),
+		mTextureTypes(nullptr),
+		mNumTextureTypes(0),
+		mFragmentUBOffset(0),
+		mVertexUBOffset(0),
+		mGeometryUBOffset(0),
+		mHullUBOffset(0),
+		mDomainUBOffset(0),
+		mComputeUBOffset(0),
+		mDrawCallInProgress(false),
+		mCurrentDrawOperation(DOT_TRIANGLE_LIST),
+		mViewportNorm(0.0f, 0.0f, 1.0f, 1.0f)
+	{
+		// Get our GLSupport
+		mGLSupport = BansheeEngine::getGLSupport();
+
+		mViewMatrix = Matrix4::IDENTITY;
+
+		mColorWrite[0] = mColorWrite[1] = mColorWrite[2] = mColorWrite[3] = true;
+
+		mCurrentContext = 0;
+		mMainContext = 0;
+
+		mGLInitialised = false;
+
+		mMinFilter = FO_LINEAR;
+		mMipFilter = FO_POINT;
+
+		mProgramPipelineManager = bs_new<GLSLProgramPipelineManager>();
+	}
+
+	GLRenderAPI::~GLRenderAPI()
+	{
+
+	}
+
+	const StringID& GLRenderAPI::getName() const
+	{
+		static StringID strName("GLRenderAPI");
+		return strName;
+	}
+
+	const String& GLRenderAPI::getShadingLanguageName() const
+	{
+		static String strName("glsl");
+		return strName;
+	}
+
+	void GLRenderAPI::initializePrepare()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		mGLSupport->start();
+		mVideoModeInfo = mGLSupport->getVideoModeInfo();
+
+		RenderWindowManager::startUp<GLRenderWindowManager>(this);
+		RenderWindowCoreManager::startUp<GLRenderWindowCoreManager>(this);
+
+		RenderStateCoreManager::startUp();
+
+		QueryManager::startUp<GLQueryManager>();
+
+		RenderAPICore::initializePrepare();
+	}
+
+	void GLRenderAPI::initializeFinalize(const SPtr<RenderWindowCore>& primaryWindow)
+	{
+		// Get the context from the window and finish initialization
+		SPtr<GLContext> context;
+		primaryWindow->getCustomAttribute("GLCONTEXT", &context);
+
+		// Set main and current context
+		mMainContext = context;
+		mCurrentContext = mMainContext;
+
+		// Set primary context as active
+		if (mCurrentContext)
+			mCurrentContext->setCurrent();
+
+		checkForErrors();
+
+		// Setup GLSupport
+		mGLSupport->initializeExtensions();
+		checkForErrors();
+
+		Vector<BansheeEngine::String> tokens = StringUtil::split(mGLSupport->getGLVersion(), ".");
+
+		if (!tokens.empty())
+		{
+			mDriverVersion.major = parseINT32(tokens[0]);
+			if (tokens.size() > 1)
+				mDriverVersion.minor = parseINT32(tokens[1]);
+			if (tokens.size() > 2)
+				mDriverVersion.release = parseINT32(tokens[2]);
+		}
+		mDriverVersion.build = 0;
+
+		mCurrentCapabilities = createRenderSystemCapabilities();
+		initFromCaps(mCurrentCapabilities);
+		GLVertexArrayObjectManager::startUp();
+		glFrontFace(GL_CW);
+
+		mGLInitialised = true;
+
+		RenderAPICore::initializeFinalize(primaryWindow);
+	}
+
+	void GLRenderAPI::destroyCore()
+	{
+		RenderAPICore::destroyCore();
+
+		// Deleting the GLSL program factory
+		if (mGLSLProgramFactory)
+		{
+			// Remove from manager safely
+			GpuProgramCoreManager::instance().removeFactory(mGLSLProgramFactory);
+			bs_delete(mGLSLProgramFactory);
+			mGLSLProgramFactory = nullptr;
+		}
+
+		// Deleting the hardware buffer manager.  Has to be done before the mGLSupport->stop().
+		HardwareBufferCoreManager::shutDown();
+		HardwareBufferManager::shutDown();
+		GLRTTManager::shutDown();
+
+		mBoundVertexBuffers.clear();
+		mBoundVertexDeclaration = nullptr;
+		mBoundIndexBuffer = nullptr;
+
+		mCurrentVertexProgram = nullptr;
+		mCurrentFragmentProgram = nullptr;
+		mCurrentGeometryProgram = nullptr;
+		mCurrentHullProgram = nullptr;
+		mCurrentDomainProgram = nullptr;
+		mCurrentComputeProgram = nullptr;
+
+		mGLSupport->stop();
+
+		TextureCoreManager::shutDown();
+		TextureManager::shutDown();
+		QueryManager::shutDown();
+		RenderWindowCoreManager::shutDown();
+		RenderWindowManager::shutDown();
+		RenderStateCoreManager::shutDown();
+		GLVertexArrayObjectManager::shutDown(); // Note: Needs to be after QueryManager shutdown as some resources might be waiting for queries to complete
+
+		mGLInitialised = false;
+
+		if(mProgramPipelineManager != nullptr)
+			bs_delete(mProgramPipelineManager);
+
+		if(mGLSupport)
+			bs_delete(mGLSupport);
+
+		if(mTextureTypes != nullptr)
+			bs_deleteN(mTextureTypes, mNumTextureTypes);
+	}
+
+	void GLRenderAPI::bindGpuProgram(const SPtr<GpuProgramCore>& prg)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		SPtr<GLSLGpuProgramCore> glprg = std::static_pointer_cast<GLSLGpuProgramCore>(prg);
+
+		switch (glprg->getProperties().getType())
+		{
+		case GPT_VERTEX_PROGRAM:
+			mCurrentVertexProgram = glprg;
+			break;
+		case GPT_FRAGMENT_PROGRAM:
+			mCurrentFragmentProgram = glprg;
+			break;
+		case GPT_GEOMETRY_PROGRAM:
+			mCurrentGeometryProgram = glprg;
+			break;
+		case GPT_DOMAIN_PROGRAM:
+			mCurrentDomainProgram = glprg;
+			break;
+		case GPT_HULL_PROGRAM:
+			mCurrentHullProgram = glprg;
+			break;
+		case GPT_COMPUTE_PROGRAM:
+			mCurrentComputeProgram = glprg;
+		}
+
+		RenderAPICore::bindGpuProgram(prg);
+	}
+
+	void GLRenderAPI::unbindGpuProgram(GpuProgramType gptype)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		setActiveProgram(gptype, nullptr);
+
+		RenderAPICore::unbindGpuProgram(gptype);
+	}
+
+	void GLRenderAPI::setConstantBuffers(GpuProgramType gptype, const SPtr<GpuParamsCore>& bindableParams)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		bindableParams->updateHardwareBuffers();
+		const GpuParamDesc& paramDesc = bindableParams->getParamDesc();
+		SPtr<GLSLGpuProgramCore> activeProgram = getActiveProgram(gptype);
+		GLuint glProgram = activeProgram->getGLHandle();
+
+		UINT8* uniformBufferData = nullptr;
+
+		UINT32 blockBinding = 0;
+		for(auto iter = paramDesc.paramBlocks.begin(); iter != paramDesc.paramBlocks.end(); ++iter)
+		{
+			SPtr<GpuParamBlockBufferCore> paramBlockBuffer = bindableParams->getParamBlockBuffer(iter->second.slot);
+			if(paramBlockBuffer == nullptr)
+				continue;
+
+			if(iter->second.slot == 0)
+			{
+				// 0 means uniforms are not in block, in which case we handle it specially
+				if (uniformBufferData == nullptr && paramBlockBuffer->getSize() > 0)
+				{
+					uniformBufferData = (UINT8*)bs_alloc(paramBlockBuffer->getSize());
+					paramBlockBuffer->readFromGPU(uniformBufferData); // TODO - Don't read from GPU!? Just read the cached version
+				}
+
+				continue;
+			}
+
+			const GLGpuParamBlockBufferCore* glParamBlockBuffer = static_cast<const GLGpuParamBlockBufferCore*>(paramBlockBuffer.get());
+
+			UINT32 globalBlockBinding = getGLUniformBlockBinding(gptype, blockBinding);
+			glUniformBlockBinding(glProgram, iter->second.slot - 1, globalBlockBinding);
+			glBindBufferRange(GL_UNIFORM_BUFFER, globalBlockBinding, glParamBlockBuffer->getGLHandle(), 0, glParamBlockBuffer->getSize());
+
+			blockBinding++;
+
+			BS_INC_RENDER_STAT(NumGpuParamBufferBinds);
+		}
+
+		bool hasBoundAtLeastOne = false;
+		for(auto iter = paramDesc.params.begin(); iter != paramDesc.params.end(); ++iter)
+		{
+			const GpuParamDataDesc& paramDesc = iter->second;
+
+			if(paramDesc.paramBlockSlot != 0) // 0 means uniforms are not in a block
+				continue;
+
+			const UINT8* ptrData = uniformBufferData + paramDesc.cpuMemOffset * sizeof(UINT32);
+			hasBoundAtLeastOne = true;
+
+			// Note: We don't transpose matrices here even though we don't use column major format
+			// because they are assumed to be pre-transposed in the GpuParams buffer
+			switch(paramDesc.type)
+			{
+			case GPDT_FLOAT1:
+				glProgramUniform1fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLfloat*)ptrData);
+				break;
+			case GPDT_FLOAT2:
+				glProgramUniform2fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLfloat*)ptrData);
+				break;
+			case GPDT_FLOAT3:
+				glProgramUniform3fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLfloat*)ptrData);
+				break;
+			case GPDT_FLOAT4:
+				glProgramUniform4fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLfloat*)ptrData);
+				break;
+			case GPDT_MATRIX_2X2:
+				glProgramUniformMatrix2fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
+					GL_FALSE, (GLfloat*)ptrData);
+				break;
+			case GPDT_MATRIX_2X3:
+				glProgramUniformMatrix3x2fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
+					GL_FALSE, (GLfloat*)ptrData);
+				break;
+			case GPDT_MATRIX_2X4:
+				glProgramUniformMatrix4x2fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
+					GL_FALSE, (GLfloat*)ptrData);
+				break;
+			case GPDT_MATRIX_3X2:
+				glProgramUniformMatrix2x3fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
+					GL_FALSE, (GLfloat*)ptrData);
+				break;
+			case GPDT_MATRIX_3X3:
+				glProgramUniformMatrix3fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
+					GL_FALSE, (GLfloat*)ptrData);
+				break;
+			case GPDT_MATRIX_3X4:
+				glProgramUniformMatrix4x3fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
+					GL_FALSE, (GLfloat*)ptrData);
+				break;
+			case GPDT_MATRIX_4X2:
+				glProgramUniformMatrix2x4fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
+					GL_FALSE, (GLfloat*)ptrData);
+				break;
+			case GPDT_MATRIX_4X3:
+				glProgramUniformMatrix3x4fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
+					GL_FALSE, (GLfloat*)ptrData);
+				break;
+			case GPDT_MATRIX_4X4:
+				glProgramUniformMatrix4fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
+					GL_FALSE, (GLfloat*)ptrData);
+				break;
+			case GPDT_INT1:
+				glProgramUniform1iv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLint*)ptrData);
+				break;
+			case GPDT_INT2:
+				glProgramUniform2iv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLint*)ptrData);
+				break;
+			case GPDT_INT3:
+				glProgramUniform3iv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLint*)ptrData);
+				break;
+			case GPDT_INT4:
+				glProgramUniform4iv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLint*)ptrData);
+				break;
+			case GPDT_BOOL:
+				glProgramUniform1uiv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLuint*)ptrData);
+				break;
+			case GPDT_UNKNOWN:
+				break;
+			}
+		}
+
+		if (hasBoundAtLeastOne)
+			BS_INC_RENDER_STAT(NumGpuParamBufferBinds);
+
+		if(uniformBufferData != nullptr)
+		{
+			bs_free(uniformBufferData);
+		}
+	}
+
+	void GLRenderAPI::setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		unit = getGLTextureUnit(gptype, unit);
+
+		SPtr<GLTextureCore> tex = std::static_pointer_cast<GLTextureCore>(texPtr);
+
+		GLenum lastTextureType = mTextureTypes[unit];
+
+		if (!activateGLTextureUnit(unit))
+			return;
+
+		if (enabled && tex)
+		{
+			mTextureTypes[unit] = tex->getGLTextureTarget();
+			glBindTexture(mTextureTypes[unit], tex->getGLID());
+		}
+		else
+		{
+			// TODO - This doesn't actually disable all textures set on this image unit, only the 2D ones
+			//      - If a non-2D sampler is used, the texture will still be displayed
+
+			glBindTexture(GL_TEXTURE_2D, 0); 
+		}
+
+		activateGLTextureUnit(0);
+
+		BS_INC_RENDER_STAT(NumTextureBinds);
+	}
+
+	void GLRenderAPI::setSamplerState(GpuProgramType gptype, UINT16 unit, const SPtr<SamplerStateCore>& state)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		const SamplerProperties& stateProps = state->getProperties();
+
+		unit = getGLTextureUnit(gptype, unit);
+
+		// Set texture layer filtering
+		setTextureFiltering(unit, FT_MIN, stateProps.getTextureFiltering(FT_MIN));
+		setTextureFiltering(unit, FT_MAG, stateProps.getTextureFiltering(FT_MAG));
+		setTextureFiltering(unit, FT_MIP, stateProps.getTextureFiltering(FT_MIP));
+
+		// Set texture anisotropy
+		setTextureAnisotropy(unit, stateProps.getTextureAnisotropy());
+
+		// Set mipmap biasing
+		setTextureMipmapBias(unit, stateProps.getTextureMipmapBias());
+
+		// Texture addressing mode
+		const UVWAddressingMode& uvw = stateProps.getTextureAddressingMode();
+		setTextureAddressingMode(unit, uvw);
+
+		// Set border color
+		setTextureBorderColor(unit, stateProps.getBorderColor());
+
+		SPtr<GLSLGpuProgramCore> activeProgram = getActiveProgram(gptype);
+		GLuint glProgram = activeProgram->getGLHandle();
+
+		glProgramUniform1i(glProgram, unit, getGLTextureUnit(gptype, unit));
+
+		BS_INC_RENDER_STAT(NumSamplerBinds);
+	}
+
+	void GLRenderAPI::setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr,
+		const TextureSurface& surface)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		// TODO - OpenGL can't bind a certain subset of faces like DX11, only zero, one or all, so I'm ignoring numSlices parameter
+		if (texPtr != nullptr)
+		{
+			SPtr<GLTextureCore> tex = std::static_pointer_cast<GLTextureCore>(texPtr);
+			glBindImageTexture(unit, tex->getGLID(), surface.mipLevel, surface.numArraySlices > 1, 
+				surface.arraySlice, tex->getGLFormat(), GL_READ_WRITE);
+		}
+		else
+			glBindImageTexture(unit, 0, 0, false, 0, 0, GL_READ_WRITE);
+
+		BS_INC_RENDER_STAT(NumTextureBinds);
+	}
+
+	void GLRenderAPI::setBlendState(const SPtr<BlendStateCore>& blendState)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		const BlendProperties& stateProps = blendState->getProperties();
+
+		// Alpha to coverage
+		setAlphaToCoverage(stateProps.getAlphaToCoverageEnabled());
+
+		// Blend states
+		// OpenGL 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 GLRenderAPI::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());
+
+		setMultisamplingEnable(stateProps.getMultisampleEnable());
+
+		setDepthClipEnable(stateProps.getDepthClipEnable());
+
+		setAntialiasedLineEnable(stateProps.getAntialiasedLineEnable());
+
+		BS_INC_RENDER_STAT(NumRasterizerStateChanges);
+	}
+
+	void GLRenderAPI::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(), stateProps.getStencilReadMask(), true);
+
+		setStencilBufferOperations(stateProps.getStencilBackFailOp(), stateProps.getStencilBackZFailOp(), stateProps.getStencilBackPassOp(), false);
+		setStencilBufferFunc(stateProps.getStencilBackCompFunc(), stateProps.getStencilReadMask(), false);
+
+		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 GLRenderAPI::setViewport(const Rect2& area)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		mViewportNorm = area;
+		applyViewport();
+	}
+
+	void GLRenderAPI::setRenderTarget(const SPtr<RenderTargetCore>& target, bool readOnlyDepthStencil)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		// Switch context if different from current one
+		if (target != nullptr)
+		{
+			SPtr<GLContext> newContext;
+			target->getCustomAttribute("GLCONTEXT", &newContext);
+			if (newContext && mCurrentContext != newContext)
+			{
+				switchContext(newContext);
+			}
+		}
+
+		// This must happen after context switch to ensure previous context is still alive
+		mActiveRenderTarget = target;
+
+		GLFrameBufferObject* fbo = nullptr;
+
+		if(target != nullptr)
+			target->getCustomAttribute("FBO", &fbo);
+
+		if (fbo != nullptr)
+		{
+			fbo->bind();
+
+			if (GLEW_EXT_framebuffer_sRGB)
+			{
+				// Enable / disable sRGB states
+				if (target->getProperties().isHwGammaEnabled())
+				{
+					glEnable(GL_FRAMEBUFFER_SRGB_EXT);
+
+					// Note: could test GL_FRAMEBUFFER_SRGB_CAPABLE_EXT here before
+					// enabling, but GL spec says incapable surfaces ignore the setting
+					// anyway. We test the capability to enable isHardwareGammaEnabled.
+				}
+				else
+				{
+					glDisable(GL_FRAMEBUFFER_SRGB_EXT);
+				}
+			}
+		}
+		else
+			glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+		applyViewport();
+
+		BS_INC_RENDER_STAT(NumRenderTargetChanges);
+	}
+
+	void GLRenderAPI::beginFrame()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		// Activate the viewport clipping
+		glEnable(GL_SCISSOR_TEST);
+	}
+
+	void GLRenderAPI::endFrame()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		// Deactivate the viewport clipping.
+		glDisable(GL_SCISSOR_TEST);
+	}
+
+	void GLRenderAPI::setVertexBuffers(UINT32 index, SPtr<VertexBufferCore>* buffers, UINT32 numBuffers)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		if ((index + numBuffers) > (UINT32)mBoundVertexBuffers.size())
+			mBoundVertexBuffers.resize(index + numBuffers);
+
+		for(UINT32 i = 0; i < numBuffers; i++)
+		{
+			mBoundVertexBuffers[index + i] = buffers[i];
+		}
+	}
+
+	void GLRenderAPI::setVertexDeclaration(const SPtr<VertexDeclarationCore>& vertexDeclaration)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		mBoundVertexDeclaration = vertexDeclaration;
+	}
+
+	void GLRenderAPI::setDrawOperation(DrawOperationType op)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		mCurrentDrawOperation = op;
+	}
+
+	void GLRenderAPI::setIndexBuffer(const SPtr<IndexBufferCore>& buffer)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		mBoundIndexBuffer = buffer;
+	}
+
+	void GLRenderAPI::draw(UINT32 vertexOffset, UINT32 vertexCount)
+	{
+		// Find the correct type to render
+		GLint primType = getGLDrawMode();
+		beginDraw();
+
+		glDrawArrays(primType, vertexOffset, vertexCount);
+
+		endDraw();
+
+		UINT32 primCount = vertexCountToPrimCount(mCurrentDrawOperation, vertexCount);
+
+		BS_INC_RENDER_STAT(NumDrawCalls);
+		BS_ADD_RENDER_STAT(NumVertices, vertexCount);
+		BS_ADD_RENDER_STAT(NumPrimitives, primCount);
+	}
+
+	void GLRenderAPI::drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount)
+	{
+		if(mBoundIndexBuffer == nullptr)
+		{
+			LOGWRN("Cannot draw indexed because index buffer is not set.");
+			return;
+		}
+
+		// Find the correct type to render
+		GLint primType = getGLDrawMode();
+
+		beginDraw();
+
+		SPtr<GLIndexBufferCore> indexBuffer = std::static_pointer_cast<GLIndexBufferCore>(mBoundIndexBuffer);
+		const IndexBufferProperties& ibProps = indexBuffer->getProperties();
+		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer->getGLBufferId());
+
+		GLenum indexType = (ibProps.getType() == IT_16BIT) ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
+		glDrawElementsBaseVertex(primType, indexCount, indexType, (GLvoid*)(UINT64)(ibProps.getIndexSize() * startIndex), vertexOffset);
+
+		endDraw();
+		UINT32 primCount = vertexCountToPrimCount(mCurrentDrawOperation, vertexCount);
+
+		BS_INC_RENDER_STAT(NumDrawCalls);
+		BS_ADD_RENDER_STAT(NumVertices, vertexCount);
+		BS_ADD_RENDER_STAT(NumPrimitives, primCount);
+
+		BS_INC_RENDER_STAT(NumIndexBufferBinds);
+	}
+
+	void GLRenderAPI::dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY, UINT32 numGroupsZ)
+	{
+		if (mCurrentComputeProgram == nullptr)
+		{
+			LOGWRN("Cannot dispatch compute without a set compute program.");
+			return;
+		}
+
+		glUseProgram(mCurrentComputeProgram->getGLHandle());
+		glDispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
+
+		BS_INC_RENDER_STAT(NumGpuProgramBinds);
+		BS_INC_RENDER_STAT(NumComputeCalls);
+	}
+
+	void GLRenderAPI::setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		mScissorTop = top;
+		mScissorBottom = bottom;
+		mScissorLeft = left;
+		mScissorRight = right;
+	}
+
+	void GLRenderAPI::clearRenderTarget(UINT32 buffers, const Color& color, float depth, UINT16 stencil, UINT8 targetMask)
+	{
+		if(mActiveRenderTarget == nullptr)
+			return;
+
+		const RenderTargetProperties& rtProps = mActiveRenderTarget->getProperties();
+		Rect2I clearRect(0, 0, rtProps.getWidth(), rtProps.getHeight());
+
+		clearArea(buffers, color, depth, stencil, clearRect, targetMask);
+	}
+
+	void GLRenderAPI::clearViewport(UINT32 buffers, const Color& color, float depth, UINT16 stencil, UINT8 targetMask)
+	{
+		Rect2I clearRect(mViewportLeft, mViewportTop, mViewportWidth, mViewportHeight);
+
+		clearArea(buffers, color, depth, stencil, clearRect, targetMask);
+	}
+
+	void GLRenderAPI::clearArea(UINT32 buffers, const Color& color, float depth, UINT16 stencil, const Rect2I& clearRect, 
+		UINT8 targetMask)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		if(mActiveRenderTarget == nullptr)
+			return;
+
+		bool colorMask = !mColorWrite[0] || !mColorWrite[1] 
+		|| !mColorWrite[2] || !mColorWrite[3]; 
+
+		// Disable scissor test as we want to clear the entire render surface
+		GLboolean scissorTestEnabled = glIsEnabled(GL_SCISSOR_TEST);
+		UINT32 oldScissorTop = mScissorTop;
+		UINT32 oldScissorBottom = mScissorBottom;
+		UINT32 oldScissorLeft = mScissorLeft;
+		UINT32 oldScissorRight = mScissorRight;
+
+		if (scissorTestEnabled)
+		{
+			glDisable(GL_SCISSOR_TEST);
+		}
+
+		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)
+		{
+			setScissorRect(clearRect.x, clearRect.y, clearRect.x + clearRect.width, clearRect.y + clearRect.height);
+			setScissorTestEnable(true);
+		}
+
+		if (buffers & FBT_COLOR)
+		{
+			// Enable buffer for writing if it isn't
+			if (colorMask)
+				glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+		}
+		if (buffers & FBT_DEPTH)
+		{
+			// Enable buffer for writing if it isn't
+			if (!mDepthWrite)
+				glDepthMask(GL_TRUE);
+		}
+		if (buffers & FBT_STENCIL)
+		{
+			// Enable buffer for writing if it isn't
+			glStencilMask(0xFFFFFFFF);
+		}
+
+		if (targetMask == 0xFF)
+		{
+			GLbitfield flags = 0;
+			if (buffers & FBT_COLOR)
+			{
+				flags |= GL_COLOR_BUFFER_BIT;
+
+				glClearColor(color.r, color.g, color.b, color.a);
+			}
+
+			if (buffers & FBT_DEPTH)
+			{
+				flags |= GL_DEPTH_BUFFER_BIT;
+
+				glClearDepth(depth);
+			}
+
+			if (buffers & FBT_STENCIL)
+			{
+				flags |= GL_STENCIL_BUFFER_BIT;
+
+				glClearStencil(stencil);
+			}
+
+			// Clear buffers
+			glClear(flags);
+		}
+		else
+		{
+			GLFrameBufferObject* fbo = nullptr;
+			mActiveRenderTarget->getCustomAttribute("FBO", &fbo);
+
+			if (buffers & FBT_COLOR)
+			{
+				for (UINT32 i = 0; i < BS_MAX_MULTIPLE_RENDER_TARGETS; i++)
+				{
+					if (fbo->hasColorBuffer(i) && ((1 << i) & targetMask) != 0)
+						glClearBufferfv(GL_COLOR, i, (GLfloat*)&color);
+				}
+			}
+
+			if (buffers & FBT_DEPTH)
+			{
+				if (buffers & FBT_STENCIL)
+				{
+					glClearBufferfi(GL_DEPTH_STENCIL, 0, depth, stencil);
+				}
+				else
+				{
+					glClearBufferfv(GL_DEPTH, 0, &depth);
+				}
+			}
+			else if (buffers & FBT_STENCIL)
+			{
+				INT32 stencilClear = (INT32)stencil;
+				glClearBufferiv(GL_STENCIL, 0, &stencilClear);
+			}
+		}
+
+		if (!clearEntireTarget)
+		{
+			setScissorTestEnable(false);
+		}
+
+		// Restore scissor test
+		if (scissorTestEnabled)
+		{
+			glEnable(GL_SCISSOR_TEST);
+
+			mScissorTop = oldScissorTop;
+			mScissorBottom = oldScissorBottom;
+			mScissorLeft = oldScissorLeft;
+			mScissorRight = oldScissorRight;
+		}
+
+		// Reset buffer write state
+		if (!mDepthWrite && (buffers & FBT_DEPTH))
+		{
+			glDepthMask(GL_FALSE);
+		}
+		if (colorMask && (buffers & FBT_COLOR))
+		{
+			glColorMask(mColorWrite[0], mColorWrite[1], mColorWrite[2], mColorWrite[3]);
+		}
+		if (buffers & FBT_STENCIL)
+		{
+			glStencilMask(mStencilWriteMask);
+		}
+
+		BS_INC_RENDER_STAT(NumClears);
+	}
+
+	/************************************************************************/
+	/* 								PRIVATE		                     		*/
+	/************************************************************************/
+
+	void GLRenderAPI::setTextureAddressingMode(UINT16 stage, const UVWAddressingMode& uvw)
+	{
+		if (!activateGLTextureUnit(stage))
+			return;
+
+		glTexParameteri( mTextureTypes[stage], GL_TEXTURE_WRAP_S, 
+			getTextureAddressingMode(uvw.u));
+		glTexParameteri( mTextureTypes[stage], GL_TEXTURE_WRAP_T, 
+			getTextureAddressingMode(uvw.v));
+		glTexParameteri( mTextureTypes[stage], GL_TEXTURE_WRAP_R, 
+			getTextureAddressingMode(uvw.w));
+		activateGLTextureUnit(0);
+	}
+
+	void GLRenderAPI::setTextureBorderColor(UINT16 stage, const Color& colour)
+	{
+		GLfloat border[4] = { colour.r, colour.g, colour.b, colour.a };
+		if (activateGLTextureUnit(stage))
+		{
+			glTexParameterfv(mTextureTypes[stage], GL_TEXTURE_BORDER_COLOR, border);
+			activateGLTextureUnit(0);
+		}
+	}
+
+	void GLRenderAPI::setTextureMipmapBias(UINT16 stage, float bias)
+	{
+		if (mCurrentCapabilities->hasCapability(RSC_MIPMAP_LOD_BIAS))
+		{
+			if (activateGLTextureUnit(stage))
+			{
+				glTexParameterf(mTextureTypes[stage], GL_TEXTURE_LOD_BIAS, bias);
+				activateGLTextureUnit(0);
+			}
+		}
+
+	}
+
+	void GLRenderAPI::setSceneBlending(BlendFactor sourceFactor, BlendFactor destFactor, BlendOperation op )
+	{
+		GLint sourceBlend = getBlendMode(sourceFactor);
+		GLint destBlend = getBlendMode(destFactor);
+		if(sourceFactor == BF_ONE && destFactor == BF_ZERO)
+		{
+			glDisable(GL_BLEND);
+		}
+		else
+		{
+			glEnable(GL_BLEND);
+			glBlendFunc(sourceBlend, destBlend);
+		}
+
+		GLint func = GL_FUNC_ADD;
+		switch(op)
+		{
+		case BO_ADD:
+			func = GL_FUNC_ADD;
+			break;
+		case BO_SUBTRACT:
+			func = GL_FUNC_SUBTRACT;
+			break;
+		case BO_REVERSE_SUBTRACT:
+			func = GL_FUNC_REVERSE_SUBTRACT;
+			break;
+		case BO_MIN:
+			func = GL_MIN;
+			break;
+		case BO_MAX:
+			func = GL_MAX;
+			break;
+		}
+
+		if(GLEW_VERSION_1_4 || GLEW_ARB_imaging)
+		{
+			glBlendEquation(func);
+		}
+		else if(GLEW_EXT_blend_minmax && (func == GL_MIN || func == GL_MAX))
+		{
+			glBlendEquationEXT(func);
+		}
+	}
+
+
+	void GLRenderAPI::setSceneBlending(BlendFactor sourceFactor, BlendFactor destFactor, 
+		BlendFactor sourceFactorAlpha, BlendFactor destFactorAlpha, BlendOperation op, BlendOperation alphaOp)
+	{
+		GLint sourceBlend = getBlendMode(sourceFactor);
+		GLint destBlend = getBlendMode(destFactor);
+		GLint sourceBlendAlpha = getBlendMode(sourceFactorAlpha);
+		GLint destBlendAlpha = getBlendMode(destFactorAlpha);
+
+		if(sourceFactor == BF_ONE && destFactor == BF_ZERO && 
+			sourceFactorAlpha == BF_ONE && destFactorAlpha == BF_ZERO)
+		{
+			glDisable(GL_BLEND);
+		}
+		else
+		{
+			glEnable(GL_BLEND);
+			glBlendFuncSeparate(sourceBlend, destBlend, sourceBlendAlpha, destBlendAlpha);
+		}
+
+		GLint func = GL_FUNC_ADD, alphaFunc = GL_FUNC_ADD;
+
+		switch(op)
+		{
+		case BO_ADD:
+			func = GL_FUNC_ADD;
+			break;
+		case BO_SUBTRACT:
+			func = GL_FUNC_SUBTRACT;
+			break;
+		case BO_REVERSE_SUBTRACT:
+			func = GL_FUNC_REVERSE_SUBTRACT;
+			break;
+		case BO_MIN:
+			func = GL_MIN;
+			break;
+		case BO_MAX:
+			func = GL_MAX;
+			break;
+		}
+
+		switch(alphaOp)
+		{
+		case BO_ADD:
+			alphaFunc = GL_FUNC_ADD;
+			break;
+		case BO_SUBTRACT:
+			alphaFunc = GL_FUNC_SUBTRACT;
+			break;
+		case BO_REVERSE_SUBTRACT:
+			alphaFunc = GL_FUNC_REVERSE_SUBTRACT;
+			break;
+		case BO_MIN:
+			alphaFunc = GL_MIN;
+			break;
+		case BO_MAX:
+			alphaFunc = GL_MAX;
+			break;
+		}
+
+		if(GLEW_VERSION_2_0) {
+			glBlendEquationSeparate(func, alphaFunc);
+		}
+		else if(GLEW_EXT_blend_equation_separate) {
+			glBlendEquationSeparateEXT(func, alphaFunc);
+		}
+	}
+
+	void GLRenderAPI::setAlphaTest(CompareFunction func, unsigned char value)
+	{
+		if(func == CMPF_ALWAYS_PASS)
+		{
+			glDisable(GL_ALPHA_TEST);
+		}
+		else
+		{
+			glEnable(GL_ALPHA_TEST);
+			glAlphaFunc(convertCompareFunction(func), value / 255.0f);
+		}
+	}
+
+	void GLRenderAPI::setAlphaToCoverage(bool enable)
+	{
+		static bool lasta2c = false;
+
+		if (enable != lasta2c && getCapabilities()->hasCapability(RSC_ALPHA_TO_COVERAGE))
+		{
+			if (enable)
+				glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
+			else
+				glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
+
+			lasta2c = enable;
+		}
+	}
+
+	void GLRenderAPI::setScissorTestEnable(bool enable)
+	{
+		const RenderTargetProperties& rtProps = mActiveRenderTarget->getProperties();
+
+		// If request texture flipping, use "upper-left", otherwise use "lower-left"
+		bool flipping = rtProps.requiresTextureFlipping();
+		//  GL measures from the bottom, not the top
+		UINT32 targetHeight = rtProps.getHeight();
+		// Calculate the "lower-left" corner of the viewport
+		GLsizei x = 0, y = 0, w = 0, h = 0;
+
+		if (enable)
+		{
+			glEnable(GL_SCISSOR_TEST);
+			// GL uses width / height rather than right / bottom
+			x = mScissorLeft;
+
+			if (flipping)
+				y = targetHeight - mScissorBottom - 1;
+			else
+				y = mScissorTop;
+
+			w = mScissorRight - mScissorLeft;
+			h = mScissorBottom - mScissorTop;
+
+			glScissor(x, y, w, h);
+		}
+		else
+		{
+			glDisable(GL_SCISSOR_TEST);
+
+			// GL requires you to reset the scissor when disabling
+			w = mViewportWidth;
+			h = mViewportHeight;
+			x = mViewportLeft;
+			y = mViewportTop; 
+
+			glScissor(x, y, w, h);
+		}
+	}
+
+	void GLRenderAPI::setMultisamplingEnable(bool enable)
+	{
+		if (enable)
+			glEnable(GL_MULTISAMPLE);
+		else
+			glDisable(GL_MULTISAMPLE);
+	}
+
+	void GLRenderAPI::setDepthClipEnable(bool enable)
+	{
+		if (enable)
+			glEnable(GL_DEPTH_CLAMP);
+		else
+			glDisable(GL_DEPTH_CLAMP);
+	}
+
+	void GLRenderAPI::setAntialiasedLineEnable(bool enable)
+	{
+		if (enable)
+			glEnable(GL_LINE_SMOOTH);
+		else
+			glDisable(GL_LINE_SMOOTH);
+	}
+
+
+	void GLRenderAPI::setCullingMode(CullingMode mode)
+	{
+		mCullingMode = mode;
+		GLenum cullMode;
+
+		switch( mode )
+		{
+		case CULL_NONE:
+			glDisable(GL_CULL_FACE);
+			return;
+		default:
+		case CULL_CLOCKWISE:
+			cullMode = GL_FRONT;
+			break;
+		case CULL_COUNTERCLOCKWISE:
+			cullMode = GL_BACK;
+			break;
+		}
+
+		glEnable(GL_CULL_FACE);
+		glCullFace(cullMode);
+	}
+
+	void GLRenderAPI::setDepthBufferCheckEnabled(bool enabled)
+	{
+		if (enabled)
+		{
+			glClearDepth(1.0f);
+			glEnable(GL_DEPTH_TEST);
+		}
+		else
+		{
+			glDisable(GL_DEPTH_TEST);
+		}
+	}
+
+	void GLRenderAPI::setDepthBufferWriteEnabled(bool enabled)
+	{
+		GLboolean flag = enabled ? GL_TRUE : GL_FALSE;
+		glDepthMask(flag);  
+
+		mDepthWrite = enabled;
+	}
+
+	void GLRenderAPI::setDepthBufferFunction(CompareFunction func)
+	{
+		glDepthFunc(convertCompareFunction(func));
+	}
+
+	void GLRenderAPI::setDepthBias(float constantBias, float slopeScaleBias)
+	{
+		if (constantBias != 0 || slopeScaleBias != 0)
+		{
+			glEnable(GL_POLYGON_OFFSET_FILL);
+			glEnable(GL_POLYGON_OFFSET_POINT);
+			glEnable(GL_POLYGON_OFFSET_LINE);
+
+			float scaledConstantBias = -constantBias * float((1 << 24) - 1); // Note: Assumes 24-bit depth buffer
+			glPolygonOffset(slopeScaleBias, scaledConstantBias);
+		}
+		else
+		{
+			glDisable(GL_POLYGON_OFFSET_FILL);
+			glDisable(GL_POLYGON_OFFSET_POINT);
+			glDisable(GL_POLYGON_OFFSET_LINE);
+		}
+	}
+
+	void GLRenderAPI::setColorBufferWriteEnabled(bool red, bool green, bool blue, bool alpha)
+	{
+		glColorMask(red, green, blue, alpha);
+		// record this
+		mColorWrite[0] = red;
+		mColorWrite[1] = blue;
+		mColorWrite[2] = green;
+		mColorWrite[3] = alpha;
+	}
+
+	void GLRenderAPI::setPolygonMode(PolygonMode level)
+	{
+		GLenum glmode;
+		switch(level)
+		{
+		case PM_WIREFRAME:
+			glmode = GL_LINE;
+			break;
+		default:
+		case PM_SOLID:
+			glmode = GL_FILL;
+			break;
+		}
+		glPolygonMode(GL_FRONT_AND_BACK, glmode);
+	}
+
+	void GLRenderAPI::setStencilCheckEnabled(bool enabled)
+	{
+		if (enabled)
+			glEnable(GL_STENCIL_TEST);
+		else
+			glDisable(GL_STENCIL_TEST);
+	}
+
+	void GLRenderAPI::setStencilBufferOperations(StencilOperation stencilFailOp,
+		StencilOperation depthFailOp, StencilOperation passOp, bool front)
+	{
+		if (front)
+		{
+			glStencilOpSeparate(GL_FRONT, 
+				convertStencilOp(stencilFailOp),
+				convertStencilOp(depthFailOp), 
+				convertStencilOp(passOp));
+		}
+		else
+		{
+			glStencilOpSeparate(GL_BACK, 
+				convertStencilOp(stencilFailOp, true), 
+				convertStencilOp(depthFailOp, true), 
+				convertStencilOp(passOp, true));
+		}
+	}
+
+	void GLRenderAPI::setStencilBufferFunc(CompareFunction func, UINT32 mask, bool front)
+	{
+		mStencilReadMask = mask;
+
+		if(front)
+		{
+			mStencilCompareFront = func;
+			glStencilFuncSeparate(GL_FRONT, convertCompareFunction(mStencilCompareFront), mStencilRefValue, mStencilReadMask);
+		}
+		else
+		{
+			mStencilCompareBack = func;
+			glStencilFuncSeparate(GL_BACK, convertCompareFunction(mStencilCompareBack), mStencilRefValue, mStencilReadMask);
+		}
+	}
+
+	void GLRenderAPI::setStencilBufferWriteMask(UINT32 mask)
+	{
+		mStencilWriteMask = mask;
+		glStencilMask(mask);
+	}
+
+	void GLRenderAPI::setStencilRefValue(UINT32 refValue)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		mStencilRefValue = refValue;
+
+		glStencilFuncSeparate(GL_FRONT, convertCompareFunction(mStencilCompareFront), mStencilRefValue, mStencilReadMask);
+		glStencilFuncSeparate(GL_BACK, convertCompareFunction(mStencilCompareBack), mStencilRefValue, mStencilReadMask);
+	}
+
+	void GLRenderAPI::setTextureFiltering(UINT16 unit, FilterType ftype, FilterOptions fo)
+	{
+		if (!activateGLTextureUnit(unit))
+			return;
+
+		switch(ftype)
+		{
+		case FT_MIN:
+			mMinFilter = fo;
+			// Combine with existing mip filter
+			glTexParameteri(mTextureTypes[unit], GL_TEXTURE_MIN_FILTER, getCombinedMinMipFilter());
+			break;
+		case FT_MAG:
+			switch (fo)
+			{
+			case FO_ANISOTROPIC: // GL treats linear and aniso the same
+			case FO_LINEAR:
+				glTexParameteri(mTextureTypes[unit], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+				break;
+			case FO_POINT:
+			case FO_NONE:
+				glTexParameteri(mTextureTypes[unit], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+				break;
+			}
+			break;
+		case FT_MIP:
+			mMipFilter = fo;
+			// Combine with existing min filter
+			glTexParameteri(mTextureTypes[unit], GL_TEXTURE_MIN_FILTER, getCombinedMinMipFilter());
+			break;
+		}
+
+		activateGLTextureUnit(0);
+	}
+
+	void GLRenderAPI::setTextureAnisotropy(UINT16 unit, UINT32 maxAnisotropy)
+	{
+		if (!mCurrentCapabilities->hasCapability(RSC_ANISOTROPY))
+			return;
+
+		if (!activateGLTextureUnit(unit))
+			return;
+
+		GLfloat largest_supported_anisotropy = 0;
+		glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy);
+		if (maxAnisotropy > largest_supported_anisotropy)
+			maxAnisotropy = largest_supported_anisotropy ? 
+			static_cast<UINT32>(largest_supported_anisotropy) : 1;
+
+		if(maxAnisotropy < 1)
+			maxAnisotropy = 1;
+
+		if (getCurrentAnisotropy(unit) != maxAnisotropy)
+			glTexParameterf(mTextureTypes[unit], GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)maxAnisotropy);
+
+		activateGLTextureUnit(0);
+	}
+
+	void GLRenderAPI::setClipPlanesImpl(const PlaneList& clipPlanes)
+	{
+		size_t i = 0;
+		size_t numClipPlanes;
+		GLdouble clipPlane[4];
+
+		numClipPlanes = clipPlanes.size();
+		for (i = 0; i < numClipPlanes; ++i)
+		{
+			GLenum clipPlaneId = static_cast<GLenum>(GL_CLIP_PLANE0 + i);
+			const Plane& plane = clipPlanes[i];
+
+			if (i >= 6)
+			{
+				BS_EXCEPT(RenderingAPIException, "Unable to set clip plane");
+			}
+
+			clipPlane[0] = plane.normal.x;
+			clipPlane[1] = plane.normal.y;
+			clipPlane[2] = plane.normal.z;
+			clipPlane[3] = plane.d;
+
+			glClipPlane(clipPlaneId, clipPlane);
+			glEnable(clipPlaneId);
+		}
+
+		// Disable remaining clip planes
+		for (; i < 6; ++i)
+		{
+			glDisable(static_cast<GLenum>(GL_CLIP_PLANE0 + i));
+		}
+	}
+
+	bool GLRenderAPI::activateGLTextureUnit(UINT16 unit)
+	{
+		if (mActiveTextureUnit != unit)
+		{
+			if (unit < getCapabilities()->getNumCombinedTextureUnits())
+			{
+				glActiveTexture(GL_TEXTURE0 + unit);
+				mActiveTextureUnit = unit;
+				return true;
+			}
+			else if (!unit)
+			{
+				// always ok to use the first unit
+				return true;
+			}
+			else
+			{
+				LOGWRN("Provided texture unit index is higher than OpenGL supports. Provided: " + toString(unit) + 
+					". Supported range: 0 .. " + toString(getCapabilities()->getNumCombinedTextureUnits() - 1));
+				return false;
+			}
+		}
+		else
+		{
+			return true;
+		}
+	}
+
+	void GLRenderAPI::beginDraw()
+	{
+		if(mDrawCallInProgress)
+			BS_EXCEPT(InternalErrorException, "Calling beginDraw without finishing previous draw call. Please call endDraw().");
+
+		mDrawCallInProgress = true;
+
+		if(mCurrentVertexProgram == nullptr)
+		{
+			LOGWRN("Cannot render without a set vertex shader.");
+			return;
+		}
+
+		if(mBoundVertexDeclaration == nullptr)
+		{
+			LOGWRN("Cannot render without a set vertex declaration.");
+			return;
+		}
+
+		const GLSLProgramPipeline* pipeline = mProgramPipelineManager->getPipeline(mCurrentVertexProgram.get(), 
+			mCurrentFragmentProgram.get(), mCurrentGeometryProgram.get(), mCurrentHullProgram.get(), mCurrentDomainProgram.get());
+
+		if(mActivePipeline != pipeline)
+		{
+			glBindProgramPipeline(pipeline->glHandle);
+			mActivePipeline = pipeline;
+		}
+
+		const GLVertexArrayObject& vao = GLVertexArrayObjectManager::instance().getVAO(mCurrentVertexProgram, mBoundVertexDeclaration, mBoundVertexBuffers);
+		glBindVertexArray(vao.getGLHandle()); 
+
+		BS_INC_RENDER_STAT(NumVertexBufferBinds);
+		BS_INC_RENDER_STAT(NumGpuProgramBinds);
+	}
+
+	void GLRenderAPI::endDraw()
+	{
+		if(!mDrawCallInProgress)
+			return;
+
+		mDrawCallInProgress = false;
+	}
+
+	GLfloat GLRenderAPI::getCurrentAnisotropy(UINT16 unit)
+	{
+		GLfloat curAniso = 0;
+		glGetTexParameterfv(mTextureTypes[unit], GL_TEXTURE_MAX_ANISOTROPY_EXT, &curAniso);
+
+		return curAniso ? curAniso : 1;
+	}
+
+	GLint GLRenderAPI::convertStencilOp(StencilOperation op, bool invert) const
+	{
+		switch (op)
+		{
+		case SOP_KEEP:
+			return GL_KEEP;
+		case SOP_ZERO:
+			return GL_ZERO;
+		case SOP_REPLACE:
+			return GL_REPLACE;
+		case SOP_INCREMENT:
+			return invert ? GL_DECR : GL_INCR;
+		case SOP_DECREMENT:
+			return invert ? GL_INCR : GL_DECR;
+		case SOP_INCREMENT_WRAP:
+			return invert ? GL_DECR_WRAP_EXT : GL_INCR_WRAP_EXT;
+		case SOP_DECREMENT_WRAP:
+			return invert ? GL_INCR_WRAP_EXT : GL_DECR_WRAP_EXT;
+		case SOP_INVERT:
+			return GL_INVERT;
+		};
+		// to keep compiler happy
+		return SOP_KEEP;
+	}
+
+	GLint GLRenderAPI::convertCompareFunction(CompareFunction func) const
+	{
+		switch (func)
+		{
+		case CMPF_ALWAYS_FAIL:
+			return GL_NEVER;
+		case CMPF_ALWAYS_PASS:
+			return GL_ALWAYS;
+		case CMPF_LESS:
+			return GL_LESS;
+		case CMPF_LESS_EQUAL:
+			return GL_LEQUAL;
+		case CMPF_EQUAL:
+			return GL_EQUAL;
+		case CMPF_NOT_EQUAL:
+			return GL_NOTEQUAL;
+		case CMPF_GREATER_EQUAL:
+			return GL_GEQUAL;
+		case CMPF_GREATER:
+			return GL_GREATER;
+		};
+
+		return GL_ALWAYS;
+	}
+
+	GLuint GLRenderAPI::getCombinedMinMipFilter() const
+	{
+		switch (mMinFilter)
+		{
+		case FO_ANISOTROPIC:
+		case FO_LINEAR:
+			switch (mMipFilter)
+			{
+			case FO_ANISOTROPIC:
+			case FO_LINEAR:
+				// Linear min, linear mip
+				return GL_LINEAR_MIPMAP_LINEAR;
+			case FO_POINT:
+				// Linear min, point mip
+				return GL_LINEAR_MIPMAP_NEAREST;
+			case FO_NONE:
+				// Linear min, no mip
+				return GL_LINEAR;
+			}
+			break;
+		case FO_POINT:
+		case FO_NONE:
+			switch (mMipFilter)
+			{
+			case FO_ANISOTROPIC:
+			case FO_LINEAR:
+				// Nearest min, linear mip
+				return GL_NEAREST_MIPMAP_LINEAR;
+			case FO_POINT:
+				// Nearest min, point mip
+				return GL_NEAREST_MIPMAP_NEAREST;
+			case FO_NONE:
+				// Nearest min, no mip
+				return GL_NEAREST;
+			}
+			break;
+		}
+
+		// Should never get here
+		return 0;
+	}
+
+	GLint GLRenderAPI::getBlendMode(BlendFactor blendMode) const
+	{
+		switch (blendMode)
+		{
+		case BF_ONE:
+			return GL_ONE;
+		case BF_ZERO:
+			return GL_ZERO;
+		case BF_DEST_COLOR:
+			return GL_DST_COLOR;
+		case BF_SOURCE_COLOR:
+			return GL_SRC_COLOR;
+		case BF_INV_DEST_COLOR:
+			return GL_ONE_MINUS_DST_COLOR;
+		case BF_INV_SOURCE_COLOR:
+			return GL_ONE_MINUS_SRC_COLOR;
+		case BF_DEST_ALPHA:
+			return GL_DST_ALPHA;
+		case BF_SOURCE_ALPHA:
+			return GL_SRC_ALPHA;
+		case BF_INV_DEST_ALPHA:
+			return GL_ONE_MINUS_DST_ALPHA;
+		case BF_INV_SOURCE_ALPHA:
+			return GL_ONE_MINUS_SRC_ALPHA;
+		};
+
+		return GL_ONE;
+	}
+
+	GLint GLRenderAPI::getTextureAddressingMode(TextureAddressingMode tam) const
+	{
+		switch (tam)
+		{
+		default:
+		case TAM_WRAP:
+			return GL_REPEAT;
+		case TAM_MIRROR:
+			return GL_MIRRORED_REPEAT;
+		case TAM_CLAMP:
+			return GL_CLAMP_TO_EDGE;
+		case TAM_BORDER:
+			return GL_CLAMP_TO_BORDER;
+		}
+	}
+
+	GLint GLRenderAPI::getGLDrawMode() const
+	{
+		GLint primType;
+
+		// Use adjacency if there is a geometry program and it requested adjacency info
+		bool useAdjacency = (mGeometryProgramBound && mCurrentGeometryProgram->isAdjacencyInfoRequired());
+		switch (mCurrentDrawOperation)
+		{
+		case DOT_POINT_LIST:
+			primType = GL_POINTS;
+			break;
+		case DOT_LINE_LIST:
+			primType = useAdjacency ? GL_LINES_ADJACENCY_EXT : GL_LINES;
+			break;
+		case DOT_LINE_STRIP:
+			primType = useAdjacency ? GL_LINE_STRIP_ADJACENCY_EXT : GL_LINE_STRIP;
+			break;
+		default:
+		case DOT_TRIANGLE_LIST:
+			primType = useAdjacency ? GL_TRIANGLES_ADJACENCY_EXT : GL_TRIANGLES;
+			break;
+		case DOT_TRIANGLE_STRIP:
+			primType = useAdjacency ? GL_TRIANGLE_STRIP_ADJACENCY_EXT : GL_TRIANGLE_STRIP;
+			break;
+		case DOT_TRIANGLE_FAN:
+			primType = GL_TRIANGLE_FAN;
+			break;
+		}
+
+		return primType;
+	}
+
+	UINT32 GLRenderAPI::getGLTextureUnit(GpuProgramType gptype, UINT32 unit)
+	{
+		if (gptype != GPT_VERTEX_PROGRAM && gptype != GPT_FRAGMENT_PROGRAM && gptype != GPT_GEOMETRY_PROGRAM)
+		{
+			BS_EXCEPT(InvalidParametersException, "OpenGL cannot assign textures to this gpu program type: " + toString(gptype));
+		}
+
+		UINT32 numSupportedUnits = mCurrentCapabilities->getNumTextureUnits(gptype);
+		if (unit < 0 || unit >= numSupportedUnits)
+		{
+			BS_EXCEPT(InvalidParametersException, "Invalid texture unit index for the provided stage. Unit index: " + toString(unit) + ". Stage: " +
+				toString(gptype) + ". Supported range is 0 .. " + toString(numSupportedUnits - 1));
+		}
+
+		switch (gptype)
+		{
+		case GPT_FRAGMENT_PROGRAM:
+			return mFragmentTexOffset + unit;
+		case GPT_VERTEX_PROGRAM:
+			return mVertexTexOffset + unit;
+		case GPT_GEOMETRY_PROGRAM:
+			return mGeometryTexOffset + unit;
+		default:
+			BS_EXCEPT(InternalErrorException, "Invalid program type: " + toString(gptype));
+		}
+
+		return 0;
+	}
+
+	UINT32 GLRenderAPI::getGLUniformBlockBinding(GpuProgramType gptype, UINT32 binding)
+	{
+		UINT32 maxNumBindings = mCurrentCapabilities->getNumGpuParamBlockBuffers(gptype);
+		if (binding < 0 || binding >= maxNumBindings)
+		{
+			BS_EXCEPT(InvalidParametersException, "Invalid buffer binding for the provided stage. Buffer binding: " + toString(binding) + ". Stage: " +
+				toString(gptype) + ". Supported range is 0 .. " + toString(maxNumBindings - 1));
+		}
+
+		switch (gptype)
+		{
+		case GPT_FRAGMENT_PROGRAM:
+			return mFragmentUBOffset + binding;
+		case GPT_VERTEX_PROGRAM:
+			return mVertexUBOffset + binding;
+		case GPT_GEOMETRY_PROGRAM:
+			return mGeometryUBOffset + binding;
+		case GPT_HULL_PROGRAM:
+			return mHullUBOffset + binding;
+		case GPT_DOMAIN_PROGRAM:
+			return mDomainUBOffset + binding;
+		case GPT_COMPUTE_PROGRAM:
+			return mComputeUBOffset + binding;
+		default:
+			BS_EXCEPT(InternalErrorException, "Invalid program type: " + toString(gptype));
+		}
+
+		return 0;
+	}
+
+	void GLRenderAPI::setActiveProgram(GpuProgramType gptype, const SPtr<GLSLGpuProgramCore>& program)
+	{
+		switch (gptype)
+		{
+		case GPT_VERTEX_PROGRAM:
+			mCurrentVertexProgram = program;
+			break;
+		case GPT_FRAGMENT_PROGRAM:
+			mCurrentFragmentProgram = program;
+			break;
+		case GPT_GEOMETRY_PROGRAM:
+			mCurrentGeometryProgram = program;
+			break;
+		case GPT_DOMAIN_PROGRAM:
+			mCurrentDomainProgram = program;
+			break;
+		case GPT_HULL_PROGRAM:
+			mCurrentHullProgram = program;
+			break;
+		case GPT_COMPUTE_PROGRAM:
+			mCurrentComputeProgram = program;
+			break;
+		}
+	}
+
+	SPtr<GLSLGpuProgramCore> GLRenderAPI::getActiveProgram(GpuProgramType gptype) const
+	{
+		switch (gptype)
+		{
+		case GPT_VERTEX_PROGRAM:
+			return mCurrentVertexProgram;
+		case GPT_FRAGMENT_PROGRAM:
+			return mCurrentFragmentProgram;
+		case GPT_GEOMETRY_PROGRAM:
+			return mCurrentGeometryProgram;
+		case GPT_DOMAIN_PROGRAM:
+			return mCurrentDomainProgram;
+		case GPT_HULL_PROGRAM:
+			return mCurrentHullProgram;
+		case GPT_COMPUTE_PROGRAM:
+			return mCurrentComputeProgram;
+		default:
+			BS_EXCEPT(InvalidParametersException, "Insupported gpu program type: " + toString(gptype));
+		}
+
+		return nullptr;
+	}
+
+	void GLRenderAPI::initFromCaps(RenderAPICapabilities* caps)
+	{
+		if(caps->getRenderAPIName() != getName())
+		{
+			BS_EXCEPT(InvalidParametersException, 
+				"Trying to initialize GLRenderAPI from RenderSystemCapabilities that do not support OpenGL");
+		}
+
+#if BS_DEBUG_MODE
+		if (mGLSupport->checkExtension("GL_ARB_debug_output"))
+		{
+			glDebugMessageCallback(&openGlErrorCallback, 0);
+			glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+		}
+#endif
+
+		HardwareBufferManager::startUp();
+		HardwareBufferCoreManager::startUp<GLHardwareBufferCoreManager>();
+
+		// GPU Program Manager setup
+		if(caps->isShaderProfileSupported("glsl"))
+		{
+			mGLSLProgramFactory = bs_new<GLSLProgramFactory>();
+			GpuProgramCoreManager::instance().addFactory(mGLSLProgramFactory);
+		}
+
+		// Check for framebuffer object extension
+		if(caps->hasCapability(RSC_FBO))
+		{
+			if(caps->hasCapability(RSC_HWRENDER_TO_TEXTURE))
+			{
+				// Create FBO manager
+				GLRTTManager::startUp<GLRTTManager>();
+			}
+		}
+		else
+		{
+			BS_EXCEPT(RenderingAPIException, "GPU doesn't support frame buffer objects. OpenGL versions lower than 3.0 are not supported.");
+		}
+
+		mFragmentTexOffset = 0;
+		mVertexTexOffset = caps->getNumTextureUnits(GPT_FRAGMENT_PROGRAM);
+		mGeometryTexOffset = mVertexTexOffset + caps->getNumTextureUnits(GPT_VERTEX_PROGRAM);
+
+		UINT16 numCombinedTexUnits = caps->getNumCombinedTextureUnits();
+
+		UINT32 totalNumTexUnits = caps->getNumTextureUnits(GPT_VERTEX_PROGRAM);
+		totalNumTexUnits += caps->getNumTextureUnits(GPT_FRAGMENT_PROGRAM);
+		totalNumTexUnits += caps->getNumTextureUnits(GPT_GEOMETRY_PROGRAM);
+		totalNumTexUnits += caps->getNumTextureUnits(GPT_HULL_PROGRAM);
+		totalNumTexUnits += caps->getNumTextureUnits(GPT_DOMAIN_PROGRAM);
+		totalNumTexUnits += caps->getNumTextureUnits(GPT_COMPUTE_PROGRAM);
+
+		if(totalNumTexUnits > numCombinedTexUnits)
+			BS_EXCEPT(InternalErrorException, "Number of combined texture units less than the number of individual units!?");
+
+		mNumTextureTypes = numCombinedTexUnits;
+		mTextureTypes = bs_newN<GLenum>(mNumTextureTypes);
+		for(UINT16 i = 0; i < numCombinedTexUnits; i++)
+			mTextureTypes[i] = GL_TEXTURE_2D;
+
+		mVertexUBOffset = 0;
+		UINT32 totalNumUniformBlocks = caps->getNumGpuParamBlockBuffers(GPT_VERTEX_PROGRAM);
+		mFragmentUBOffset = totalNumUniformBlocks;
+		totalNumUniformBlocks += caps->getNumGpuParamBlockBuffers(GPT_FRAGMENT_PROGRAM);
+		mGeometryUBOffset = totalNumUniformBlocks;
+		totalNumUniformBlocks += caps->getNumGpuParamBlockBuffers(GPT_GEOMETRY_PROGRAM);
+		mHullUBOffset = totalNumUniformBlocks;
+		totalNumUniformBlocks += caps->getNumGpuParamBlockBuffers(GPT_HULL_PROGRAM);
+		mDomainUBOffset = totalNumUniformBlocks;
+		totalNumUniformBlocks += caps->getNumGpuParamBlockBuffers(GPT_DOMAIN_PROGRAM);
+		mComputeUBOffset = totalNumUniformBlocks;
+		totalNumUniformBlocks += caps->getNumGpuParamBlockBuffers(GPT_COMPUTE_PROGRAM);
+
+		UINT16 numCombinedUniformBlocks = caps->getNumCombinedGpuParamBlockBuffers();
+
+		if(totalNumUniformBlocks > numCombinedUniformBlocks)
+			BS_EXCEPT(InternalErrorException, "Number of combined uniform block buffers less than the number of individual per-stage buffers!?");
+
+		TextureManager::startUp<GLTextureManager>(std::ref(*mGLSupport));
+		TextureCoreManager::startUp<GLTextureCoreManager>(std::ref(*mGLSupport));
+	}
+
+	void GLRenderAPI::switchContext(const SPtr<GLContext>& context)
+	{
+		// Unbind GPU programs and rebind to new context later, because
+		// scene manager treat render system as ONE 'context' ONLY, and it
+		// cached the GPU programs using state.
+		unbindGpuProgram(GPT_VERTEX_PROGRAM);
+		unbindGpuProgram(GPT_FRAGMENT_PROGRAM);
+		unbindGpuProgram(GPT_GEOMETRY_PROGRAM);
+		unbindGpuProgram(GPT_HULL_PROGRAM);
+		unbindGpuProgram(GPT_DOMAIN_PROGRAM);
+		unbindGpuProgram(GPT_COMPUTE_PROGRAM);
+
+		// It's ready for switching
+		if (mCurrentContext)
+			mCurrentContext->endCurrent();
+
+		mCurrentContext = context;
+		mCurrentContext->setCurrent();
+
+		// Must reset depth/colour write mask to according with user desired, otherwise,
+		// clearFrameBuffer would be wrong because the value we are recorded may be
+		// difference with the really state stored in GL context.
+		glDepthMask(mDepthWrite);
+		glColorMask(mColorWrite[0], mColorWrite[1], mColorWrite[2], mColorWrite[3]);
+		glStencilMask(mStencilWriteMask);
+	}
+
+	RenderAPICapabilities* GLRenderAPI::createRenderSystemCapabilities() const
+	{
+		RenderAPICapabilities* rsc = bs_new<RenderAPICapabilities>();
+
+		rsc->setDriverVersion(mDriverVersion);
+		const char* deviceName = (const char*)glGetString(GL_RENDERER);
+		const char* vendorName = (const char*)glGetString(GL_VENDOR);
+		rsc->setDeviceName(deviceName);
+		rsc->setRenderAPIName(getName());
+
+		// determine vendor
+		if (strstr(vendorName, "NVIDIA"))
+			rsc->setVendor(GPU_NVIDIA);
+		else if (strstr(vendorName, "ATI"))
+			rsc->setVendor(GPU_AMD);
+		else if (strstr(vendorName, "AMD"))
+			rsc->setVendor(GPU_AMD);
+		else if (strstr(vendorName, "Intel"))
+			rsc->setVendor(GPU_INTEL);
+		else
+			rsc->setVendor(GPU_UNKNOWN);
+
+		// Check for hardware mipmapping support.
+		if(GLEW_VERSION_1_4)
+		{
+			rsc->setCapability(RSC_AUTOMIPMAP);
+		}
+
+		// Check for Anisotropy support
+		if (getGLSupport()->checkExtension("GL_EXT_texture_filter_anisotropic"))
+		{
+			rsc->setCapability(RSC_ANISOTROPY);
+		}
+
+		// Check for cube mapping
+		if(GLEW_VERSION_1_3 || 
+			getGLSupport()->checkExtension("GL_ARB_texture_cube_map") ||
+			getGLSupport()->checkExtension("GL_EXT_texture_cube_map"))
+		{
+			rsc->setCapability(RSC_CUBEMAPPING);
+		}
+
+		// Point sprites
+		if (GLEW_VERSION_2_0 || getGLSupport()->checkExtension("GL_ARB_point_sprite"))
+		{
+			rsc->setCapability(RSC_POINT_SPRITES);
+		}
+
+		// Check for hardware stencil support and set bit depth
+		GLint stencil;
+		glGetIntegerv(GL_STENCIL_BITS, &stencil);
+
+		if(stencil)
+		{
+			rsc->setStencilBufferBitDepth(stencil);
+		}
+
+		if (GLEW_VERSION_2_0 || 
+			(getGLSupport()->checkExtension("GL_ARB_shading_language_100") &&
+			getGLSupport()->checkExtension("GL_ARB_shader_objects") &&
+			getGLSupport()->checkExtension("GL_ARB_fragment_shader") &&
+			getGLSupport()->checkExtension("GL_ARB_vertex_shader")))
+		{
+			rsc->addShaderProfile("glsl");
+		}
+
+		// Check if geometry shaders are supported
+		if (GLEW_VERSION_2_0 &&
+			getGLSupport()->checkExtension("GL_EXT_geometry_shader4"))
+		{
+			rsc->setCapability(RSC_GEOMETRY_PROGRAM);
+
+			rsc->setGeometryProgramConstantBoolCount(0);
+			rsc->setGeometryProgramConstantIntCount(0);
+
+			GLint floatConstantCount = 0;
+			glGetIntegerv(GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT, &floatConstantCount);
+			rsc->setGeometryProgramConstantFloatCount(floatConstantCount);
+
+			GLint maxOutputVertices;
+			glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT,&maxOutputVertices);
+			rsc->setGeometryProgramNumOutputVertices(maxOutputVertices);
+		}
+
+		//Check if render to vertex buffer (transform feedback in OpenGL)
+		if (GLEW_VERSION_2_0 && getGLSupport()->checkExtension("GL_EXT_transform_feedback"))
+		{
+			rsc->setCapability(RSC_HWRENDER_TO_VERTEX_BUFFER);
+		}
+
+		// Check for texture compression
+		if (GLEW_VERSION_1_3 || getGLSupport()->checkExtension("GL_ARB_texture_compression"))
+		{   
+			rsc->setCapability(RSC_TEXTURE_COMPRESSION);
+
+			// Check for dxt compression
+			if (getGLSupport()->checkExtension("GL_EXT_texture_compression_s3tc"))
+			{
+				rsc->setCapability(RSC_TEXTURE_COMPRESSION_DXT);
+			}
+
+			// Check for vtc compression
+			if (getGLSupport()->checkExtension("GL_NV_texture_compression_vtc"))
+			{
+				rsc->setCapability(RSC_TEXTURE_COMPRESSION_VTC);
+			}
+		}
+
+		// As are user clipping planes
+		rsc->setCapability(RSC_USER_CLIP_PLANES);
+
+		// 2-sided stencil?
+		if (GLEW_VERSION_2_0 || getGLSupport()->checkExtension("GL_EXT_stencil_two_side"))
+		{
+			rsc->setCapability(RSC_TWO_SIDED_STENCIL);
+		}
+
+		// stencil wrapping?
+		if (GLEW_VERSION_1_4 || getGLSupport()->checkExtension("GL_EXT_stencil_wrap"))
+		{
+			rsc->setCapability(RSC_STENCIL_WRAP);
+		}
+
+		// Check for hardware occlusion support
+		if (GLEW_VERSION_1_5 || getGLSupport()->checkExtension("GL_ARB_occlusion_query"))
+		{
+			rsc->setCapability(RSC_HWOCCLUSION);
+		}
+
+		// UBYTE4 always supported
+		rsc->setCapability(RSC_VERTEX_FORMAT_UBYTE4);
+
+		// Infinite far plane always supported
+		rsc->setCapability(RSC_INFINITE_FAR_PLANE);
+
+		// Check for non-power-of-2 texture support
+		if (getGLSupport()->checkExtension("GL_ARB_texture_non_power_of_two"))
+		{
+			rsc->setCapability(RSC_NON_POWER_OF_2_TEXTURES);
+		}
+
+		// Check for Float textures
+		if (getGLSupport()->checkExtension("GL_ATI_texture_float") || getGLSupport()->checkExtension("GL_ARB_texture_float"))
+		{
+			rsc->setCapability(RSC_TEXTURE_FLOAT);
+		}
+
+		// 3D textures should always be supported
+		rsc->setCapability(RSC_TEXTURE_3D);
+
+		// Check for framebuffer object extension
+		if (getGLSupport()->checkExtension("GL_ARB_framebuffer_object"))
+		{
+			// Probe number of draw buffers
+			// Only makes sense with FBO support, so probe here
+			if (GLEW_VERSION_2_0 || getGLSupport()->checkExtension("GL_ARB_draw_buffers") || getGLSupport()->checkExtension("GL_ATI_draw_buffers"))
+			{
+				GLint buffers;
+				glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &buffers);
+				rsc->setNumMultiRenderTargets(std::min<int>(buffers, (GLint)BS_MAX_MULTIPLE_RENDER_TARGETS));
+				rsc->setCapability(RSC_MRT_DIFFERENT_BIT_DEPTHS);
+
+				rsc->setCapability(RSC_FBO);
+
+			}
+			rsc->setCapability(RSC_HWRENDER_TO_TEXTURE);
+		}
+
+		rsc->setCapability(RSC_HWRENDER_TO_TEXTURE);
+		rsc->setCapability(RSC_PBUFFER);
+
+		// Point size
+		float ps;
+		glGetFloatv(GL_POINT_SIZE_MAX, &ps);
+		rsc->setMaxPointSize(ps);
+
+		// Max number of fragment shader textures
+		GLint units;
+		glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &units);
+		rsc->setNumTextureUnits(GPT_FRAGMENT_PROGRAM, static_cast<UINT16>(units));
+
+		// Max number of vertex shader textures
+		GLint vUnits;
+		glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &vUnits);
+		rsc->setNumTextureUnits(GPT_VERTEX_PROGRAM, static_cast<UINT16>(vUnits));
+		if (vUnits > 0)
+		{
+			rsc->setCapability(RSC_VERTEX_TEXTURE_FETCH);
+		}
+
+		GLint numUniformBlocks;
+		glGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS, &numUniformBlocks);
+		rsc->setNumGpuParamBlockBuffers(GPT_VERTEX_PROGRAM, numUniformBlocks);
+
+		glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS, &numUniformBlocks);
+		rsc->setNumGpuParamBlockBuffers(GPT_FRAGMENT_PROGRAM, numUniformBlocks);
+
+		if (mGLSupport->checkExtension("GL_ARB_geometry_shader4"))
+		{
+			GLint geomUnits;
+			glGetIntegerv(GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, &geomUnits);
+			rsc->setNumTextureUnits(GPT_GEOMETRY_PROGRAM, static_cast<UINT16>(geomUnits));
+
+			glGetIntegerv(GL_MAX_GEOMETRY_UNIFORM_BLOCKS, &numUniformBlocks);
+			rsc->setNumGpuParamBlockBuffers(GPT_GEOMETRY_PROGRAM, numUniformBlocks);
+		}
+
+		if (mGLSupport->checkExtension("GL_ARB_tessellation_shader"))
+		{
+			rsc->setCapability(RSC_TESSELLATION_PROGRAM);
+
+			glGetIntegerv(GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS, &numUniformBlocks);
+			rsc->setNumGpuParamBlockBuffers(GPT_HULL_PROGRAM, numUniformBlocks);
+
+			glGetIntegerv(GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS, &numUniformBlocks);
+			rsc->setNumGpuParamBlockBuffers(GPT_DOMAIN_PROGRAM, numUniformBlocks);
+		}
+
+		if (mGLSupport->checkExtension("GL_ARB_compute_shader")) 
+		{
+			rsc->setCapability(RSC_COMPUTE_PROGRAM);
+
+			GLint computeUnits;
+			glGetIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &computeUnits);
+			rsc->setNumTextureUnits(GPT_COMPUTE_PROGRAM, static_cast<UINT16>(computeUnits));
+
+			glGetIntegerv(GL_MAX_COMPUTE_UNIFORM_BLOCKS, &numUniformBlocks);
+			rsc->setNumGpuParamBlockBuffers(GPT_COMPUTE_PROGRAM, numUniformBlocks);
+		}
+
+		GLint combinedTexUnits;
+		glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &combinedTexUnits);
+		rsc->setNumCombinedTextureUnits(static_cast<UINT16>(combinedTexUnits));
+
+		GLint combinedUniformBlockUnits;
+		glGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS, &combinedUniformBlockUnits);
+		rsc->setNumCombinedGpuParamBlockBuffers(static_cast<UINT16>(combinedUniformBlockUnits));
+
+		// Mipmap LOD biasing
+
+		if (mGLSupport->checkExtension("GL_EXT_texture_lod_bias"))
+			rsc->setCapability(RSC_MIPMAP_LOD_BIAS);
+
+		// Alpha to coverage?
+		if (mGLSupport->checkExtension("GL_ARB_multisample"))
+		{
+			// Alpha to coverage always 'supported' when MSAA is available
+			// although card may ignore it if it doesn't specifically support A2C
+			rsc->setCapability(RSC_ALPHA_TO_COVERAGE);
+		}
+
+		// Advanced blending operations
+		if(GLEW_VERSION_2_0)
+		{
+			rsc->setCapability(RSC_ADVANCED_BLEND_OPERATIONS);
+		}
+
+		return rsc;
+	}
+
+	bool GLRenderAPI::checkForErrors() const
+	{
+		GLenum glErr = glGetError();
+		bool errorsFound = false;
+		String msg;
+		while (glErr != GL_NO_ERROR)
+		{
+			const char* glerrStr = (const char*)gluErrorString(glErr);
+			if (glerrStr)
+			{
+				msg += String(glerrStr);
+			}
+			glErr = glGetError();
+			errorsFound = true;
+		}
+
+		if (errorsFound)
+			LOGWRN("OpenGL error: " + msg);
+
+		return errorsFound;
+	}
+
+	void GLRenderAPI::makeGLMatrix(GLfloat gl_matrix[16], const Matrix4& m)
+	{
+		UINT32 x = 0;
+		for (UINT32 i = 0; i < 4; i++)
+		{
+			for (UINT32 j = 0; j < 4; j++)
+			{
+				gl_matrix[x] = m[j][i];
+				x++;
+			}
+		}
+	}
+
+	void GLRenderAPI::applyViewport()
+	{
+		if (mActiveRenderTarget == nullptr)
+			return;
+
+		const RenderTargetProperties& rtProps = mActiveRenderTarget->getProperties();
+
+		// Calculate the "lower-left" corner of the viewport
+		mViewportLeft = (UINT32)(rtProps.getWidth() * mViewportNorm.x);
+		mViewportTop = (UINT32)(rtProps.getHeight() * mViewportNorm.y);
+		mViewportWidth = (UINT32)(rtProps.getWidth() * mViewportNorm.width);
+		mViewportHeight = (UINT32)(rtProps.getHeight() * mViewportNorm.height);
+
+		if (rtProps.requiresTextureFlipping())
+		{
+			// Convert "upper-left" corner to "lower-left"
+			mViewportTop = rtProps.getHeight() - (mViewportTop + mViewportHeight) - 1;
+		}
+
+		glViewport(mViewportLeft, mViewportTop, mViewportWidth, mViewportHeight);
+
+		// Configure the viewport clipping
+		glScissor(mViewportLeft, mViewportTop, mViewportWidth, mViewportHeight);
+	}
+
+	/************************************************************************/
+	/* 								UTILITY		                     		*/
+	/************************************************************************/
+
+	void GLRenderAPI::convertProjectionMatrix(const Matrix4& matrix, Matrix4& dest)
+	{
+		dest = matrix;
+	}
+
+	const RenderAPIInfo& GLRenderAPI::getAPIInfo() const
+	{
+		static RenderAPIInfo info(0.0f, 0.0f, -1.0f, 1.0f, VET_COLOR_ABGR, false, false, true);
+
+		return info;
+	}
+
+	GpuParamBlockDesc GLRenderAPI::generateParamBlockDesc(const String& name, Vector<GpuParamDataDesc>& params)
+	{
+		GpuParamBlockDesc block;
+		block.blockSize = 0;
+		block.isShareable = true;
+		block.name = name;
+		block.slot = 0;
+
+		for (auto& param : params)
+		{
+			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[param.type];
+			UINT32 size = typeInfo.size / 4;
+			UINT32 alignment = typeInfo.alignment / 4;
+
+			// Fix alignment if needed
+			UINT32 alignOffset = block.blockSize % alignment;
+			if (alignOffset != 0)
+			{
+				UINT32 padding = (alignment - alignOffset);
+				block.blockSize += padding;
+			}
+
+			if (param.arraySize > 1)
+			{
+				// Array elements are always padded and aligned to vec4
+				alignOffset = size % typeInfo.baseTypeSize;
+				if (alignOffset != 0)
+				{
+					UINT32 padding = (typeInfo.baseTypeSize - alignOffset);
+					size += padding;
+				}
+
+				alignOffset = block.blockSize % typeInfo.baseTypeSize;
+				if (alignOffset != 0)
+				{
+					UINT32 padding = (typeInfo.baseTypeSize - alignOffset);
+					block.blockSize += padding;
+				}
+
+				param.elementSize = size;
+				param.arrayElementStride = size;
+				param.cpuMemOffset = block.blockSize;
+				param.gpuMemOffset = 0;
+				
+				block.blockSize += size * param.arraySize;
+			}
+			else
+			{
+				param.elementSize = size;
+				param.arrayElementStride = size;
+				param.cpuMemOffset = block.blockSize;
+				param.gpuMemOffset = 0;
+
+				block.blockSize += size;
+			}
+
+			param.paramBlockSlot = 0;
+		}
+
+		// Constant buffer size must always be a multiple of 16
+		if (block.blockSize % 4 != 0)
+			block.blockSize += (4 - (block.blockSize % 4));
+
+		return block;
+	}
+
+	void __stdcall openGlErrorCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *userParam)
+	{
+		if (type != GL_DEBUG_TYPE_PERFORMANCE && type != GL_DEBUG_TYPE_OTHER)
+		{
+			BS_EXCEPT(RenderingAPIException, "OpenGL error: " + String(message));
+		}
+	}
 }

+ 356 - 356
Source/BansheeSL/Include/BsLexerFX.h

@@ -1,356 +1,356 @@
-#ifndef yyHEADER_H
-#define yyHEADER_H 1
-#define yyIN_HEADER 1
-
-#line 6 "BsLexerFX.h"
-
-#line 8 "BsLexerFX.h"
-
-#define  YY_INT_ALIGNED short int
-
-/* A lexical scanner generated by flex */
-
-#define FLEX_SCANNER
-#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 37
-#if YY_FLEX_SUBMINOR_VERSION > 0
-#define FLEX_BETA
-#endif
-
-/* First, we deal with  platform-specific or compiler-specific issues. */
-
-/* begin standard C headers. */
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-
-/* end standard C headers. */
-
-/* flex integer type definitions */
-
-#ifndef FLEXINT_H
-#define FLEXINT_H
-
-/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
-
-#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
-
-/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
- * if you want the limit (max/min) macros for int types. 
- */
-#ifndef __STDC_LIMIT_MACROS
-#define __STDC_LIMIT_MACROS 1
-#endif
-
-#include <inttypes.h>
-typedef int8_t flex_int8_t;
-typedef uint8_t flex_uint8_t;
-typedef int16_t flex_int16_t;
-typedef uint16_t flex_uint16_t;
-typedef int32_t flex_int32_t;
-typedef uint32_t flex_uint32_t;
-#else
-typedef signed char flex_int8_t;
-typedef short int flex_int16_t;
-typedef int flex_int32_t;
-typedef unsigned char flex_uint8_t; 
-typedef unsigned short int flex_uint16_t;
-typedef unsigned int flex_uint32_t;
-
-/* Limits of integral types. */
-#ifndef INT8_MIN
-#define INT8_MIN               (-128)
-#endif
-#ifndef INT16_MIN
-#define INT16_MIN              (-32767-1)
-#endif
-#ifndef INT32_MIN
-#define INT32_MIN              (-2147483647-1)
-#endif
-#ifndef INT8_MAX
-#define INT8_MAX               (127)
-#endif
-#ifndef INT16_MAX
-#define INT16_MAX              (32767)
-#endif
-#ifndef INT32_MAX
-#define INT32_MAX              (2147483647)
-#endif
-#ifndef UINT8_MAX
-#define UINT8_MAX              (255U)
-#endif
-#ifndef UINT16_MAX
-#define UINT16_MAX             (65535U)
-#endif
-#ifndef UINT32_MAX
-#define UINT32_MAX             (4294967295U)
-#endif
-
-#endif /* ! C99 */
-
-#endif /* ! FLEXINT_H */
-
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else	/* ! __cplusplus */
-
-/* C99 requires __STDC__ to be defined as 1. */
-#if defined (__STDC__)
-
-#define YY_USE_CONST
-
-#endif	/* defined (__STDC__) */
-#endif	/* ! __cplusplus */
-
-#ifdef YY_USE_CONST
-#define yyconst const
-#else
-#define yyconst
-#endif
-
-/* An opaque pointer. */
-#ifndef YY_TYPEDEF_YY_SCANNER_T
-#define YY_TYPEDEF_YY_SCANNER_T
-typedef void* yyscan_t;
-#endif
-
-/* For convenience, these vars (plus the bison vars far below)
-   are macros in the reentrant scanner. */
-#define yyin yyg->yyin_r
-#define yyout yyg->yyout_r
-#define yyextra yyg->yyextra_r
-#define yyleng yyg->yyleng_r
-#define yytext yyg->yytext_r
-#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
-#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
-#define yy_flex_debug yyg->yy_flex_debug_r
-
-/* Size of default input buffer. */
-#ifndef YY_BUF_SIZE
-#define YY_BUF_SIZE 16384
-#endif
-
-#ifndef YY_TYPEDEF_YY_BUFFER_STATE
-#define YY_TYPEDEF_YY_BUFFER_STATE
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-#endif
-
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef size_t yy_size_t;
-#endif
-
-#ifndef YY_STRUCT_YY_BUFFER_STATE
-#define YY_STRUCT_YY_BUFFER_STATE
-struct yy_buffer_state
-	{
-	FILE *yy_input_file;
-
-	char *yy_ch_buf;		/* input buffer */
-	char *yy_buf_pos;		/* current position in input buffer */
-
-	/* Size of input buffer in bytes, not including room for EOB
-	 * characters.
-	 */
-	yy_size_t yy_buf_size;
-
-	/* Number of characters read into yy_ch_buf, not including EOB
-	 * characters.
-	 */
-	yy_size_t yy_n_chars;
-
-	/* Whether we "own" the buffer - i.e., we know we created it,
-	 * and can realloc() it to grow it, and should free() it to
-	 * delete it.
-	 */
-	int yy_is_our_buffer;
-
-	/* Whether this is an "interactive" input source; if so, and
-	 * if we're using stdio for input, then we want to use getc()
-	 * instead of fread(), to make sure we stop fetching input after
-	 * each newline.
-	 */
-	int yy_is_interactive;
-
-	/* Whether we're considered to be at the beginning of a line.
-	 * If so, '^' rules will be active on the next match, otherwise
-	 * not.
-	 */
-	int yy_at_bol;
-
-    int yy_bs_lineno; /**< The line count. */
-    int yy_bs_column; /**< The column count. */
-    
-	/* Whether to try to fill the input buffer when we reach the
-	 * end of it.
-	 */
-	int yy_fill_buffer;
-
-	int yy_buffer_status;
-
-	};
-#endif /* !YY_STRUCT_YY_BUFFER_STATE */
-
-void yyrestart (FILE *input_file ,yyscan_t yyscanner );
-void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
-void yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-void yypop_buffer_state (yyscan_t yyscanner );
-
-YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
-YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
-YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len ,yyscan_t yyscanner );
-
-void *yyalloc (yy_size_t ,yyscan_t yyscanner );
-void *yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
-void yyfree (void * ,yyscan_t yyscanner );
-
-/* Begin user sect3 */
-
-#define yywrap(yyscanner) 1
-#define YY_SKIP_YYWRAP
-
-#define yytext_ptr yytext_r
-
-#ifdef YY_HEADER_EXPORT_START_CONDITIONS
-#define INITIAL 0
-#define INCLUDE 1
-#define CODEBLOCK_HEADER 2
-#define CODEBLOCK_EQUALS 3
-#define CODEBLOCK 4
-#define CODEBLOCK_END 5
-#define DEFINE_COND 6
-#define UNDEF_COND 7
-#define CONDITIONAL_IF 8
-#define CONDITIONAL_IFN 9
-#define CONDITIONAL_ELIF 10
-#define CONDITIONAL_IGNORE 11
-
-#endif
-
-/*windows compatibility case*/
-#include <io.h>
-#define isatty _isatty
-#define fileno _fileno
-    
-#define YY_EXTRA_TYPE struct tagParseState *
-
-int yylex_init (yyscan_t* scanner);
-
-int yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
-
-/* Accessor methods to globals.
-   These are made visible to non-reentrant scanners for convenience. */
-
-int yylex_destroy (yyscan_t yyscanner );
-
-int yyget_debug (yyscan_t yyscanner );
-
-void yyset_debug (int debug_flag ,yyscan_t yyscanner );
-
-YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner );
-
-void yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
-
-FILE *yyget_in (yyscan_t yyscanner );
-
-void yyset_in  (FILE * in_str ,yyscan_t yyscanner );
-
-FILE *yyget_out (yyscan_t yyscanner );
-
-void yyset_out  (FILE * out_str ,yyscan_t yyscanner );
-
-yy_size_t yyget_leng (yyscan_t yyscanner );
-
-char *yyget_text (yyscan_t yyscanner );
-
-int yyget_lineno (yyscan_t yyscanner );
-
-void yyset_lineno (int line_number ,yyscan_t yyscanner );
-
-int yyget_column  (yyscan_t yyscanner );
-
-void yyset_column (int column_no ,yyscan_t yyscanner );
-
-YYSTYPE * yyget_lval (yyscan_t yyscanner );
-
-void yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
-
-       YYLTYPE *yyget_lloc (yyscan_t yyscanner );
-    
-        void yyset_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner );
-    
-/* Macros after this point can all be overridden by user definitions in
- * section 1.
- */
-
-#ifndef YY_SKIP_YYWRAP
-#ifdef __cplusplus
-extern "C" int yywrap (yyscan_t yyscanner );
-#else
-extern int yywrap (yyscan_t yyscanner );
-#endif
-#endif
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
-#endif
-
-#ifndef YY_NO_INPUT
-
-#endif
-
-/* Amount of stuff to slurp up with each read. */
-#ifndef YY_READ_BUF_SIZE
-#define YY_READ_BUF_SIZE 8192
-#endif
-
-/* Number of entries by which start-condition stack grows. */
-#ifndef YY_START_STACK_INCR
-#define YY_START_STACK_INCR 25
-#endif
-
-/* Default declaration of generated scanner - a define so the user can
- * easily add parameters.
- */
-#ifndef YY_DECL
-#define YY_DECL_IS_OURS 1
-
-extern int yylex \
-               (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner);
-
-#define YY_DECL int yylex \
-               (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner)
-#endif /* !YY_DECL */
-
-/* yy_get_previous_state - get the state just before the EOB char was reached */
-
-#undef YY_NEW_FILE
-#undef YY_FLUSH_BUFFER
-#undef yy_set_bol
-#undef yy_new_buffer
-#undef yy_set_interactive
-#undef YY_DO_BEFORE_ACTION
-
-#ifdef YY_DECL_IS_OURS
-#undef YY_DECL_IS_OURS
-#undef YY_DECL
-#endif
-
-#line 378 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-
-
-#line 355 "BsLexerFX.h"
-#undef yyIN_HEADER
-#endif /* yyHEADER_H */
+#ifndef yyHEADER_H
+#define yyHEADER_H 1
+#define yyIN_HEADER 1
+
+#line 6 "BsLexerFX.h"
+
+#line 8 "BsLexerFX.h"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 37
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif	/* defined (__STDC__) */
+#endif	/* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For convenience, these vars (plus the bison vars far below)
+   are macros in the reentrant scanner. */
+#define yyin yyg->yyin_r
+#define yyout yyg->yyout_r
+#define yyextra yyg->yyextra_r
+#define yyleng yyg->yyleng_r
+#define yytext yyg->yytext_r
+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
+#define yy_flex_debug yyg->yy_flex_debug_r
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	yy_size_t yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+void yyrestart (FILE *input_file ,yyscan_t yyscanner );
+void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
+void yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+void yypop_buffer_state (yyscan_t yyscanner );
+
+YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len ,yyscan_t yyscanner );
+
+void *yyalloc (yy_size_t ,yyscan_t yyscanner );
+void *yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
+void yyfree (void * ,yyscan_t yyscanner );
+
+/* Begin user sect3 */
+
+#define yywrap(yyscanner) 1
+#define YY_SKIP_YYWRAP
+
+#define yytext_ptr yytext_r
+
+#ifdef YY_HEADER_EXPORT_START_CONDITIONS
+#define INITIAL 0
+#define INCLUDE 1
+#define CODEBLOCK_HEADER 2
+#define CODEBLOCK_EQUALS 3
+#define CODEBLOCK 4
+#define CODEBLOCK_END 5
+#define DEFINE_COND 6
+#define UNDEF_COND 7
+#define CONDITIONAL_IF 8
+#define CONDITIONAL_IFN 9
+#define CONDITIONAL_ELIF 10
+#define CONDITIONAL_IGNORE 11
+
+#endif
+
+/*windows compatibility case*/
+#include <io.h>
+#define isatty _isatty
+#define fileno _fileno
+    
+#define YY_EXTRA_TYPE struct tagParseState *
+
+int yylex_init (yyscan_t* scanner);
+
+int yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int yylex_destroy (yyscan_t yyscanner );
+
+int yyget_debug (yyscan_t yyscanner );
+
+void yyset_debug (int debug_flag ,yyscan_t yyscanner );
+
+YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner );
+
+void yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *yyget_in (yyscan_t yyscanner );
+
+void yyset_in  (FILE * in_str ,yyscan_t yyscanner );
+
+FILE *yyget_out (yyscan_t yyscanner );
+
+void yyset_out  (FILE * out_str ,yyscan_t yyscanner );
+
+yy_size_t yyget_leng (yyscan_t yyscanner );
+
+char *yyget_text (yyscan_t yyscanner );
+
+int yyget_lineno (yyscan_t yyscanner );
+
+void yyset_lineno (int line_number ,yyscan_t yyscanner );
+
+int yyget_column  (yyscan_t yyscanner );
+
+void yyset_column (int column_no ,yyscan_t yyscanner );
+
+YYSTYPE * yyget_lval (yyscan_t yyscanner );
+
+void yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
+
+       YYLTYPE *yyget_lloc (yyscan_t yyscanner );
+    
+        void yyset_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner );
+    
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap (yyscan_t yyscanner );
+#else
+extern int yywrap (yyscan_t yyscanner );
+#endif
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+#endif
+
+#ifndef YY_NO_INPUT
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int yylex \
+               (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner);
+
+#define YY_DECL int yylex \
+               (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner)
+#endif /* !YY_DECL */
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+#undef YY_NEW_FILE
+#undef YY_FLUSH_BUFFER
+#undef yy_set_bol
+#undef yy_new_buffer
+#undef yy_set_interactive
+#undef YY_DO_BEFORE_ACTION
+
+#ifdef YY_DECL_IS_OURS
+#undef YY_DECL_IS_OURS
+#undef YY_DECL
+#endif
+
+#line 378 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+
+
+#line 355 "BsLexerFX.h"
+#undef yyIN_HEADER
+#endif /* yyHEADER_H */

+ 263 - 263
Source/BansheeSL/Include/BsParserFX.h

@@ -1,263 +1,263 @@
-/* A Bison parser, made by GNU Bison 2.7.  */
-
-/* Skeleton interface for Bison GLR parsers in C
-   
-      Copyright (C) 2002-2012 Free Software Foundation, Inc.
-   
-   This program is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-   
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-   
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-   
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-#ifndef YY_YY_BSPARSERFX_H_INCLUDED
-# define YY_YY_BSPARSERFX_H_INCLUDED
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-#if YYDEBUG
-extern int yydebug;
-#endif
-/* "%code requires" blocks.  */
-/* Line 2579 of glr.c  */
-#line 9 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-
-#include "BsMMAlloc.h"
-#include "BsASTFX.h"
-#include "BsIncludeHandler.h"
-
-#ifndef YY_TYPEDEF_YY_SCANNER_T
-#define YY_TYPEDEF_YY_SCANNER_T
-	typedef void* yyscan_t;
-#endif
-
-typedef struct YYLTYPE {
-	int first_line;
-	int first_column;
-	int last_line;
-	int last_column;
-	char *filename;
-} YYLTYPE;
-#define YYLTYPE_IS_DECLARED 1
-
-#define YYLLOC_DEFAULT(Current, Rhs, N)																\
-	do																								\
-		if (N)																						\
-		{																							\
-			(Current).first_line = YYRHSLOC (Rhs, 1).first_line;									\
-			(Current).first_column = YYRHSLOC (Rhs, 1).first_column;								\
-			(Current).last_line = YYRHSLOC (Rhs, N).last_line;										\
-			(Current).last_column = YYRHSLOC (Rhs, N).last_column;									\
-			(Current).filename = YYRHSLOC (Rhs, 1).filename;										\
-		}																							\
-		else																						\
-		{																							\
-			(Current).first_line = (Current).last_line = YYRHSLOC (Rhs, 0).last_line;				\
-			(Current).first_column = (Current).last_column = YYRHSLOC (Rhs, 0).last_column;			\
-			(Current).filename = NULL;																\
-		}																							\
-	while (0)
-
-#define ADD_PARAMETER(OUTPUT, TYPE, NAME)															\
-			OUTPUT = nodeCreate(parse_state->memContext, NT_Parameter);								\
-			nodePush(parse_state, OUTPUT);															\
-																									\
-			NodeOption paramType;																	\
-			paramType.type = OT_ParamType;															\
-			paramType.value.intValue = TYPE;														\
-																									\
-			NodeOption paramName;																	\
-			paramName.type = OT_Identifier;															\
-			paramName.value.strValue = NAME;														\
-																									\
-			nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &paramType);		\
-			nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &paramName);		\
-
-
-
-/* Line 2579 of glr.c  */
-#line 101 "BsParserFX.h"
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     TOKEN_INTEGER = 258,
-     TOKEN_FLOAT = 259,
-     TOKEN_BOOLEAN = 260,
-     TOKEN_STRING = 261,
-     TOKEN_IDENTIFIER = 262,
-     TOKEN_FILLMODEVALUE = 263,
-     TOKEN_CULLMODEVALUE = 264,
-     TOKEN_COMPFUNCVALUE = 265,
-     TOKEN_OPVALUE = 266,
-     TOKEN_COLORMASK = 267,
-     TOKEN_ADDRMODEVALUE = 268,
-     TOKEN_FILTERVALUE = 269,
-     TOKEN_BLENDOPVALUE = 270,
-     TOKEN_BUFFERUSAGE = 271,
-     TOKEN_FLOATTYPE = 272,
-     TOKEN_FLOAT2TYPE = 273,
-     TOKEN_FLOAT3TYPE = 274,
-     TOKEN_FLOAT4TYPE = 275,
-     TOKEN_INTTYPE = 276,
-     TOKEN_INT2TYPE = 277,
-     TOKEN_INT3TYPE = 278,
-     TOKEN_INT4TYPE = 279,
-     TOKEN_COLORTYPE = 280,
-     TOKEN_MAT2x2TYPE = 281,
-     TOKEN_MAT2x3TYPE = 282,
-     TOKEN_MAT2x4TYPE = 283,
-     TOKEN_MAT3x2TYPE = 284,
-     TOKEN_MAT3x3TYPE = 285,
-     TOKEN_MAT3x4TYPE = 286,
-     TOKEN_MAT4x2TYPE = 287,
-     TOKEN_MAT4x3TYPE = 288,
-     TOKEN_MAT4x4TYPE = 289,
-     TOKEN_SAMPLER1D = 290,
-     TOKEN_SAMPLER2D = 291,
-     TOKEN_SAMPLER3D = 292,
-     TOKEN_SAMPLERCUBE = 293,
-     TOKEN_SAMPLER2DMS = 294,
-     TOKEN_TEXTURE1D = 295,
-     TOKEN_TEXTURE2D = 296,
-     TOKEN_TEXTURE3D = 297,
-     TOKEN_TEXTURECUBE = 298,
-     TOKEN_TEXTURE2DMS = 299,
-     TOKEN_BYTEBUFFER = 300,
-     TOKEN_STRUCTBUFFER = 301,
-     TOKEN_RWTYPEDBUFFER = 302,
-     TOKEN_RWBYTEBUFFER = 303,
-     TOKEN_RWSTRUCTBUFFER = 304,
-     TOKEN_RWAPPENDBUFFER = 305,
-     TOKEN_RWCONSUMEBUFFER = 306,
-     TOKEN_PARAMSBLOCK = 307,
-     TOKEN_AUTO = 308,
-     TOKEN_ALIAS = 309,
-     TOKEN_SHARED = 310,
-     TOKEN_USAGE = 311,
-     TOKEN_SEPARABLE = 312,
-     TOKEN_QUEUE = 313,
-     TOKEN_PRIORITY = 314,
-     TOKEN_TRANSPARENT = 315,
-     TOKEN_PARAMETERS = 316,
-     TOKEN_BLOCKS = 317,
-     TOKEN_TECHNIQUE = 318,
-     TOKEN_RENDERER = 319,
-     TOKEN_LANGUAGE = 320,
-     TOKEN_PASS = 321,
-     TOKEN_VERTEX = 322,
-     TOKEN_FRAGMENT = 323,
-     TOKEN_GEOMETRY = 324,
-     TOKEN_HULL = 325,
-     TOKEN_DOMAIN = 326,
-     TOKEN_COMPUTE = 327,
-     TOKEN_COMMON = 328,
-     TOKEN_STENCILREF = 329,
-     TOKEN_FILLMODE = 330,
-     TOKEN_CULLMODE = 331,
-     TOKEN_DEPTHBIAS = 332,
-     TOKEN_SDEPTHBIAS = 333,
-     TOKEN_DEPTHCLIP = 334,
-     TOKEN_SCISSOR = 335,
-     TOKEN_MULTISAMPLE = 336,
-     TOKEN_AALINE = 337,
-     TOKEN_DEPTHREAD = 338,
-     TOKEN_DEPTHWRITE = 339,
-     TOKEN_COMPAREFUNC = 340,
-     TOKEN_STENCIL = 341,
-     TOKEN_STENCILREADMASK = 342,
-     TOKEN_STENCILWRITEMASK = 343,
-     TOKEN_STENCILOPFRONT = 344,
-     TOKEN_STENCILOPBACK = 345,
-     TOKEN_FAIL = 346,
-     TOKEN_ZFAIL = 347,
-     TOKEN_ALPHATOCOVERAGE = 348,
-     TOKEN_INDEPENDANTBLEND = 349,
-     TOKEN_TARGET = 350,
-     TOKEN_INDEX = 351,
-     TOKEN_BLEND = 352,
-     TOKEN_COLOR = 353,
-     TOKEN_ALPHA = 354,
-     TOKEN_WRITEMASK = 355,
-     TOKEN_SOURCE = 356,
-     TOKEN_DEST = 357,
-     TOKEN_OP = 358,
-     TOKEN_ADDRMODE = 359,
-     TOKEN_MINFILTER = 360,
-     TOKEN_MAGFILTER = 361,
-     TOKEN_MIPFILTER = 362,
-     TOKEN_MAXANISO = 363,
-     TOKEN_MIPBIAS = 364,
-     TOKEN_MIPMIN = 365,
-     TOKEN_MIPMAX = 366,
-     TOKEN_BORDERCOLOR = 367,
-     TOKEN_U = 368,
-     TOKEN_V = 369,
-     TOKEN_W = 370
-   };
-#endif
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-{
-/* Line 2579 of glr.c  */
-#line 73 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-
-	int intValue;
-	float floatValue;
-	float matrixValue[16];
-	int intVectorValue[4];
-	const char* strValue;
-	ASTFXNode* nodePtr;
-	NodeOption nodeOption;
-
-
-/* Line 2579 of glr.c  */
-#line 241 "BsParserFX.h"
-} YYSTYPE;
-# define YYSTYPE_IS_TRIVIAL 1
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-#endif
-
-#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
-typedef struct YYLTYPE
-{
-  int first_line;
-  int first_column;
-  int last_line;
-  int last_column;
-} YYLTYPE;
-# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
-# define YYLTYPE_IS_DECLARED 1
-# define YYLTYPE_IS_TRIVIAL 1
-#endif
-
-
-int yyparse (ParseState* parse_state, yyscan_t scanner);
-
-#endif /* !YY_YY_BSPARSERFX_H_INCLUDED  */
+/* A Bison parser, made by GNU Bison 2.7.  */
+
+/* Skeleton interface for Bison GLR parsers in C
+   
+      Copyright (C) 2002-2012 Free Software Foundation, Inc.
+   
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+   
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+#ifndef YY_YY_BSPARSERFX_H_INCLUDED
+# define YY_YY_BSPARSERFX_H_INCLUDED
+/* Enabling traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int yydebug;
+#endif
+/* "%code requires" blocks.  */
+/* Line 2579 of glr.c  */
+#line 9 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+
+#include "BsMMAlloc.h"
+#include "BsASTFX.h"
+#include "BsIncludeHandler.h"
+
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+	typedef void* yyscan_t;
+#endif
+
+typedef struct YYLTYPE {
+	int first_line;
+	int first_column;
+	int last_line;
+	int last_column;
+	char *filename;
+} YYLTYPE;
+#define YYLTYPE_IS_DECLARED 1
+
+#define YYLLOC_DEFAULT(Current, Rhs, N)																\
+	do																								\
+		if (N)																						\
+		{																							\
+			(Current).first_line = YYRHSLOC (Rhs, 1).first_line;									\
+			(Current).first_column = YYRHSLOC (Rhs, 1).first_column;								\
+			(Current).last_line = YYRHSLOC (Rhs, N).last_line;										\
+			(Current).last_column = YYRHSLOC (Rhs, N).last_column;									\
+			(Current).filename = YYRHSLOC (Rhs, 1).filename;										\
+		}																							\
+		else																						\
+		{																							\
+			(Current).first_line = (Current).last_line = YYRHSLOC (Rhs, 0).last_line;				\
+			(Current).first_column = (Current).last_column = YYRHSLOC (Rhs, 0).last_column;			\
+			(Current).filename = NULL;																\
+		}																							\
+	while (0)
+
+#define ADD_PARAMETER(OUTPUT, TYPE, NAME)															\
+			OUTPUT = nodeCreate(parse_state->memContext, NT_Parameter);								\
+			nodePush(parse_state, OUTPUT);															\
+																									\
+			NodeOption paramType;																	\
+			paramType.type = OT_ParamType;															\
+			paramType.value.intValue = TYPE;														\
+																									\
+			NodeOption paramName;																	\
+			paramName.type = OT_Identifier;															\
+			paramName.value.strValue = NAME;														\
+																									\
+			nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &paramType);		\
+			nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &paramName);		\
+
+
+
+/* Line 2579 of glr.c  */
+#line 101 "BsParserFX.h"
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     TOKEN_INTEGER = 258,
+     TOKEN_FLOAT = 259,
+     TOKEN_BOOLEAN = 260,
+     TOKEN_STRING = 261,
+     TOKEN_IDENTIFIER = 262,
+     TOKEN_FILLMODEVALUE = 263,
+     TOKEN_CULLMODEVALUE = 264,
+     TOKEN_COMPFUNCVALUE = 265,
+     TOKEN_OPVALUE = 266,
+     TOKEN_COLORMASK = 267,
+     TOKEN_ADDRMODEVALUE = 268,
+     TOKEN_FILTERVALUE = 269,
+     TOKEN_BLENDOPVALUE = 270,
+     TOKEN_BUFFERUSAGE = 271,
+     TOKEN_FLOATTYPE = 272,
+     TOKEN_FLOAT2TYPE = 273,
+     TOKEN_FLOAT3TYPE = 274,
+     TOKEN_FLOAT4TYPE = 275,
+     TOKEN_INTTYPE = 276,
+     TOKEN_INT2TYPE = 277,
+     TOKEN_INT3TYPE = 278,
+     TOKEN_INT4TYPE = 279,
+     TOKEN_COLORTYPE = 280,
+     TOKEN_MAT2x2TYPE = 281,
+     TOKEN_MAT2x3TYPE = 282,
+     TOKEN_MAT2x4TYPE = 283,
+     TOKEN_MAT3x2TYPE = 284,
+     TOKEN_MAT3x3TYPE = 285,
+     TOKEN_MAT3x4TYPE = 286,
+     TOKEN_MAT4x2TYPE = 287,
+     TOKEN_MAT4x3TYPE = 288,
+     TOKEN_MAT4x4TYPE = 289,
+     TOKEN_SAMPLER1D = 290,
+     TOKEN_SAMPLER2D = 291,
+     TOKEN_SAMPLER3D = 292,
+     TOKEN_SAMPLERCUBE = 293,
+     TOKEN_SAMPLER2DMS = 294,
+     TOKEN_TEXTURE1D = 295,
+     TOKEN_TEXTURE2D = 296,
+     TOKEN_TEXTURE3D = 297,
+     TOKEN_TEXTURECUBE = 298,
+     TOKEN_TEXTURE2DMS = 299,
+     TOKEN_BYTEBUFFER = 300,
+     TOKEN_STRUCTBUFFER = 301,
+     TOKEN_RWTYPEDBUFFER = 302,
+     TOKEN_RWBYTEBUFFER = 303,
+     TOKEN_RWSTRUCTBUFFER = 304,
+     TOKEN_RWAPPENDBUFFER = 305,
+     TOKEN_RWCONSUMEBUFFER = 306,
+     TOKEN_PARAMSBLOCK = 307,
+     TOKEN_AUTO = 308,
+     TOKEN_ALIAS = 309,
+     TOKEN_SHARED = 310,
+     TOKEN_USAGE = 311,
+     TOKEN_SEPARABLE = 312,
+     TOKEN_QUEUE = 313,
+     TOKEN_PRIORITY = 314,
+     TOKEN_TRANSPARENT = 315,
+     TOKEN_PARAMETERS = 316,
+     TOKEN_BLOCKS = 317,
+     TOKEN_TECHNIQUE = 318,
+     TOKEN_RENDERER = 319,
+     TOKEN_LANGUAGE = 320,
+     TOKEN_PASS = 321,
+     TOKEN_VERTEX = 322,
+     TOKEN_FRAGMENT = 323,
+     TOKEN_GEOMETRY = 324,
+     TOKEN_HULL = 325,
+     TOKEN_DOMAIN = 326,
+     TOKEN_COMPUTE = 327,
+     TOKEN_COMMON = 328,
+     TOKEN_STENCILREF = 329,
+     TOKEN_FILLMODE = 330,
+     TOKEN_CULLMODE = 331,
+     TOKEN_DEPTHBIAS = 332,
+     TOKEN_SDEPTHBIAS = 333,
+     TOKEN_DEPTHCLIP = 334,
+     TOKEN_SCISSOR = 335,
+     TOKEN_MULTISAMPLE = 336,
+     TOKEN_AALINE = 337,
+     TOKEN_DEPTHREAD = 338,
+     TOKEN_DEPTHWRITE = 339,
+     TOKEN_COMPAREFUNC = 340,
+     TOKEN_STENCIL = 341,
+     TOKEN_STENCILREADMASK = 342,
+     TOKEN_STENCILWRITEMASK = 343,
+     TOKEN_STENCILOPFRONT = 344,
+     TOKEN_STENCILOPBACK = 345,
+     TOKEN_FAIL = 346,
+     TOKEN_ZFAIL = 347,
+     TOKEN_ALPHATOCOVERAGE = 348,
+     TOKEN_INDEPENDANTBLEND = 349,
+     TOKEN_TARGET = 350,
+     TOKEN_INDEX = 351,
+     TOKEN_BLEND = 352,
+     TOKEN_COLOR = 353,
+     TOKEN_ALPHA = 354,
+     TOKEN_WRITEMASK = 355,
+     TOKEN_SOURCE = 356,
+     TOKEN_DEST = 357,
+     TOKEN_OP = 358,
+     TOKEN_ADDRMODE = 359,
+     TOKEN_MINFILTER = 360,
+     TOKEN_MAGFILTER = 361,
+     TOKEN_MIPFILTER = 362,
+     TOKEN_MAXANISO = 363,
+     TOKEN_MIPBIAS = 364,
+     TOKEN_MIPMIN = 365,
+     TOKEN_MIPMAX = 366,
+     TOKEN_BORDERCOLOR = 367,
+     TOKEN_U = 368,
+     TOKEN_V = 369,
+     TOKEN_W = 370
+   };
+#endif
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+{
+/* Line 2579 of glr.c  */
+#line 73 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+
+	int intValue;
+	float floatValue;
+	float matrixValue[16];
+	int intVectorValue[4];
+	const char* strValue;
+	ASTFXNode* nodePtr;
+	NodeOption nodeOption;
+
+
+/* Line 2579 of glr.c  */
+#line 241 "BsParserFX.h"
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE
+{
+  int first_line;
+  int first_column;
+  int last_line;
+  int last_column;
+} YYLTYPE;
+# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+
+int yyparse (ParseState* parse_state, yyscan_t scanner);
+
+#endif /* !YY_YY_BSPARSERFX_H_INCLUDED  */

+ 3785 - 3785
Source/BansheeSL/Source/BsLexerFX.c

@@ -1,3785 +1,3785 @@
-#line 2 "BsLexerFX.c"
-
-#line 4 "BsLexerFX.c"
-
-#define  YY_INT_ALIGNED short int
-
-/* A lexical scanner generated by flex */
-
-#define FLEX_SCANNER
-#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 37
-#if YY_FLEX_SUBMINOR_VERSION > 0
-#define FLEX_BETA
-#endif
-
-/* First, we deal with  platform-specific or compiler-specific issues. */
-
-/* begin standard C headers. */
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-
-/* end standard C headers. */
-
-/* flex integer type definitions */
-
-#ifndef FLEXINT_H
-#define FLEXINT_H
-
-/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
-
-#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
-
-/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
- * if you want the limit (max/min) macros for int types. 
- */
-#ifndef __STDC_LIMIT_MACROS
-#define __STDC_LIMIT_MACROS 1
-#endif
-
-#include <inttypes.h>
-typedef int8_t flex_int8_t;
-typedef uint8_t flex_uint8_t;
-typedef int16_t flex_int16_t;
-typedef uint16_t flex_uint16_t;
-typedef int32_t flex_int32_t;
-typedef uint32_t flex_uint32_t;
-#else
-typedef signed char flex_int8_t;
-typedef short int flex_int16_t;
-typedef int flex_int32_t;
-typedef unsigned char flex_uint8_t; 
-typedef unsigned short int flex_uint16_t;
-typedef unsigned int flex_uint32_t;
-
-/* Limits of integral types. */
-#ifndef INT8_MIN
-#define INT8_MIN               (-128)
-#endif
-#ifndef INT16_MIN
-#define INT16_MIN              (-32767-1)
-#endif
-#ifndef INT32_MIN
-#define INT32_MIN              (-2147483647-1)
-#endif
-#ifndef INT8_MAX
-#define INT8_MAX               (127)
-#endif
-#ifndef INT16_MAX
-#define INT16_MAX              (32767)
-#endif
-#ifndef INT32_MAX
-#define INT32_MAX              (2147483647)
-#endif
-#ifndef UINT8_MAX
-#define UINT8_MAX              (255U)
-#endif
-#ifndef UINT16_MAX
-#define UINT16_MAX             (65535U)
-#endif
-#ifndef UINT32_MAX
-#define UINT32_MAX             (4294967295U)
-#endif
-
-#endif /* ! C99 */
-
-#endif /* ! FLEXINT_H */
-
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else	/* ! __cplusplus */
-
-/* C99 requires __STDC__ to be defined as 1. */
-#if defined (__STDC__)
-
-#define YY_USE_CONST
-
-#endif	/* defined (__STDC__) */
-#endif	/* ! __cplusplus */
-
-#ifdef YY_USE_CONST
-#define yyconst const
-#else
-#define yyconst
-#endif
-
-/* Returned upon end-of-file. */
-#define YY_NULL 0
-
-/* Promotes a possibly negative, possibly signed char to an unsigned
- * integer for use as an array index.  If the signed char is negative,
- * we want to instead treat it as an 8-bit unsigned char, hence the
- * double cast.
- */
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
-
-/* An opaque pointer. */
-#ifndef YY_TYPEDEF_YY_SCANNER_T
-#define YY_TYPEDEF_YY_SCANNER_T
-typedef void* yyscan_t;
-#endif
-
-/* For convenience, these vars (plus the bison vars far below)
-   are macros in the reentrant scanner. */
-#define yyin yyg->yyin_r
-#define yyout yyg->yyout_r
-#define yyextra yyg->yyextra_r
-#define yyleng yyg->yyleng_r
-#define yytext yyg->yytext_r
-#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
-#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
-#define yy_flex_debug yyg->yy_flex_debug_r
-
-/* Enter a start condition.  This macro really ought to take a parameter,
- * but we do it the disgusting crufty way forced on us by the ()-less
- * definition of BEGIN.
- */
-#define BEGIN yyg->yy_start = 1 + 2 *
-
-/* Translate the current start state into a value that can be later handed
- * to BEGIN to return to the state.  The YYSTATE alias is for lex
- * compatibility.
- */
-#define YY_START ((yyg->yy_start - 1) / 2)
-#define YYSTATE YY_START
-
-/* Action number for EOF rule of a given start state. */
-#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
-
-/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE yyrestart(yyin ,yyscanner )
-
-#define YY_END_OF_BUFFER_CHAR 0
-
-/* Size of default input buffer. */
-#ifndef YY_BUF_SIZE
-#define YY_BUF_SIZE 16384
-#endif
-
-/* The state buf must be large enough to hold one state per character in the main buffer.
- */
-#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
-
-#ifndef YY_TYPEDEF_YY_BUFFER_STATE
-#define YY_TYPEDEF_YY_BUFFER_STATE
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-#endif
-
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef size_t yy_size_t;
-#endif
-
-#define EOB_ACT_CONTINUE_SCAN 0
-#define EOB_ACT_END_OF_FILE 1
-#define EOB_ACT_LAST_MATCH 2
-
-    /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
-     *       access to the local variable yy_act. Since yyless() is a macro, it would break
-     *       existing scanners that call yyless() from OUTSIDE yylex. 
-     *       One obvious solution it to make yy_act a global. I tried that, and saw
-     *       a 5% performance hit in a non-yylineno scanner, because yy_act is
-     *       normally declared as a register variable-- so it is not worth it.
-     */
-    #define  YY_LESS_LINENO(n) \
-            do { \
-                int yyl;\
-                for ( yyl = n; yyl < yyleng; ++yyl )\
-                    if ( yytext[yyl] == '\n' )\
-                        --yylineno;\
-            }while(0)
-    
-/* Return all but the first "n" matched characters back to the input stream. */
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up yytext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		*yy_cp = yyg->yy_hold_char; \
-		YY_RESTORE_YY_MORE_OFFSET \
-		yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
-		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
-		} \
-	while ( 0 )
-
-#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
-
-#ifndef YY_STRUCT_YY_BUFFER_STATE
-#define YY_STRUCT_YY_BUFFER_STATE
-struct yy_buffer_state
-	{
-	FILE *yy_input_file;
-
-	char *yy_ch_buf;		/* input buffer */
-	char *yy_buf_pos;		/* current position in input buffer */
-
-	/* Size of input buffer in bytes, not including room for EOB
-	 * characters.
-	 */
-	yy_size_t yy_buf_size;
-
-	/* Number of characters read into yy_ch_buf, not including EOB
-	 * characters.
-	 */
-	yy_size_t yy_n_chars;
-
-	/* Whether we "own" the buffer - i.e., we know we created it,
-	 * and can realloc() it to grow it, and should free() it to
-	 * delete it.
-	 */
-	int yy_is_our_buffer;
-
-	/* Whether this is an "interactive" input source; if so, and
-	 * if we're using stdio for input, then we want to use getc()
-	 * instead of fread(), to make sure we stop fetching input after
-	 * each newline.
-	 */
-	int yy_is_interactive;
-
-	/* Whether we're considered to be at the beginning of a line.
-	 * If so, '^' rules will be active on the next match, otherwise
-	 * not.
-	 */
-	int yy_at_bol;
-
-    int yy_bs_lineno; /**< The line count. */
-    int yy_bs_column; /**< The column count. */
-    
-	/* Whether to try to fill the input buffer when we reach the
-	 * end of it.
-	 */
-	int yy_fill_buffer;
-
-	int yy_buffer_status;
-
-#define YY_BUFFER_NEW 0
-#define YY_BUFFER_NORMAL 1
-	/* When an EOF's been seen but there's still some text to process
-	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
-	 * shouldn't try reading from the input source any more.  We might
-	 * still have a bunch of tokens to match, though, because of
-	 * possible backing-up.
-	 *
-	 * When we actually see the EOF, we change the status to "new"
-	 * (via yyrestart()), so that the user can continue scanning by
-	 * just pointing yyin at a new input file.
-	 */
-#define YY_BUFFER_EOF_PENDING 2
-
-	};
-#endif /* !YY_STRUCT_YY_BUFFER_STATE */
-
-/* We provide macros for accessing buffer states in case in the
- * future we want to put the buffer states in a more general
- * "scanner state".
- *
- * Returns the top of the stack, or NULL.
- */
-#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
-                          ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
-                          : NULL)
-
-/* Same as previous macro, but useful when we know that the buffer stack is not
- * NULL or when we need an lvalue. For internal use only.
- */
-#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
-
-void yyrestart (FILE *input_file ,yyscan_t yyscanner );
-void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
-void yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-void yypop_buffer_state (yyscan_t yyscanner );
-
-static void yyensure_buffer_stack (yyscan_t yyscanner );
-static void yy_load_buffer_state (yyscan_t yyscanner );
-static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
-
-#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
-
-YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
-YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
-YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len ,yyscan_t yyscanner );
-
-void *yyalloc (yy_size_t ,yyscan_t yyscanner );
-void *yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
-void yyfree (void * ,yyscan_t yyscanner );
-
-#define yy_new_buffer yy_create_buffer
-
-#define yy_set_interactive(is_interactive) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){ \
-        yyensure_buffer_stack (yyscanner); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
-	}
-
-#define yy_set_bol(at_bol) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){\
-        yyensure_buffer_stack (yyscanner); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
-	}
-
-#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
-
-/* Begin user sect3 */
-
-#define yywrap(yyscanner) 1
-#define YY_SKIP_YYWRAP
-
-typedef unsigned char YY_CHAR;
-
-typedef int yy_state_type;
-
-#define yytext_ptr yytext_r
-
-static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
-static yy_state_type yy_try_NUL_trans (yy_state_type current_state  ,yyscan_t yyscanner);
-static int yy_get_next_buffer (yyscan_t yyscanner );
-static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
-
-/* Done after the current pattern has been matched and before the
- * corresponding action - sets up yytext.
- */
-#define YY_DO_BEFORE_ACTION \
-	yyg->yytext_ptr = yy_bp; \
-	yyleng = (size_t) (yy_cp - yy_bp); \
-	yyg->yy_hold_char = *yy_cp; \
-	*yy_cp = '\0'; \
-	yyg->yy_c_buf_p = yy_cp;
-
-#define YY_NUM_RULES 222
-#define YY_END_OF_BUFFER 223
-/* This struct is not used in this scanner,
-   but its presence is necessary. */
-struct yy_trans_info
-	{
-	flex_int32_t yy_verify;
-	flex_int32_t yy_nxt;
-	};
-static yyconst flex_int16_t yy_accept[835] =
-    {   0,
-        1,    1,  165,  165,  205,  205,  208,  208,    0,    0,
-      218,  218,  169,  169,  173,  173,  177,  177,  181,  181,
-      194,  194,  187,  187,  223,  221,    1,    1,  221,  221,
-      221,  221,    2,    2,  139,  138,  220,  220,  220,  220,
-      137,  220,  220,  220,  220,  220,  220,  220,  220,  220,
-      220,  136,  220,  220,   93,   94,   95,  220,  220,  220,
-      220,  220,  220,  220,  220,  220,  167,  165,  165,  167,
-      206,  205,  205,  204,  209,  208,  208,  207,  212,  212,
-      210,  211,  218,  218,  213,  214,  215,  216,  217,  171,
-      169,  169,  170,  175,  173,  173,  174,  179,  177,  177,
-
-      178,  183,  181,  181,  182,  196,  194,  194,  195,  193,
-      187,  187,  193,    1,    0,    5,    0,    0,    0,    0,
-        2,  219,    0,    2,    0,  220,  220,  220,  220,  220,
-      220,  220,  145,  220,  220,  220,  220,  220,  220,  103,
-      220,  220,  220,  220,  220,  220,  220,  109,  220,  220,
-      220,  220,  144,  143,  112,  220,  220,  220,  220,  220,
-      220,  107,  220,  220,  220,  220,  220,  220,  220,  220,
-      220,   83,  220,  220,  220,  220,  220,  142,  141,  220,
-      140,  220,  220,  220,  220,  220,  220,  220,  220,  220,
-      220,  220,  220,  220,  220,  220,  220,  220,  220,  220,
-
-      220,  220,  220,  220,  220,  220,  220,  220,  220,  220,
-      220,  220,  165,    0,  166,  205,  208,  218,  169,  170,
-      173,  174,  177,  178,  181,  182,  194,  195,  187,    0,
-        0,    0,    0,    0,    0,    0,    0,    2,  219,    4,
-        3,  220,  130,  220,  220,  220,  220,  220,  220,  220,
-      220,  220,  104,  220,  220,  220,  220,  220,  117,  220,
-      220,  220,  220,  220,  220,  220,  220,  220,  149,  111,
-      220,  220,  116,  120,  220,  220,  220,  108,  220,  134,
-      133,  220,  220,  220,  220,  220,  220,  110,  220,  220,
-      121,  220,  220,  220,  220,  220,  220,  148,  220,  147,
-
-      146,  220,  220,  220,  220,  220,  131,  220,  220,  220,
-      220,  220,  220,  220,  220,  220,  220,  220,  220,  220,
-      220,  220,  220,  220,  220,  220,  220,  220,  220,  220,
-        8,  220,  220,  220,  220,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    4,  220,  220,
-      220,  220,  220,  220,  220,  220,  220,  220,  220,  220,
-      220,  220,  220,   56,  220,  126,  220,  220,  220,  220,
-       82,  220,  105,   71,   55,  220,  220,  200,  220,  220,
-      113,  220,  220,  220,  220,  220,  220,  220,  220,  220,
-      220,  220,  220,  220,  106,  220,  220,   53,  220,  220,
-
-      220,  150,  132,  220,  220,  127,  220,  220,  220,  220,
-      220,  220,  220,  220,  220,  220,  220,  220,  220,  220,
-      220,  220,  100,  151,  220,  114,  220,  220,   96,  220,
-      220,  220,    9,   10,   11,  220,  220,  220,  220,    6,
-      220,    0,    0,    0,    0,    0,    0,  185,  184,    0,
-        0,    0,    0,    0,    0,    4,  220,  158,  220,   79,
-      220,  220,   77,   43,  220,  220,  153,   78,  220,  220,
-      220,  220,  220,  128,  220,  220,  220,  220,  220,  220,
-      220,  220,  220,   76,  220,  220,  220,  220,  220,  220,
-      220,  220,  220,  220,  220,  220,  220,  220,  156,  220,
-
-      220,   45,  220,  220,  101,  129,  220,  220,  220,  220,
-      220,  220,  220,  220,  220,  220,  220,  220,  220,  220,
-      220,  220,  220,   72,   97,   16,    7,   12,  220,  220,
-      220,  220,   99,  191,  190,    0,    0,    0,    0,  186,
-      176,    0,    0,  172,   62,  161,  220,  220,  220,  154,
-       50,  220,  220,  203,  220,  220,  220,  220,  220,  122,
-      220,  220,  220,  220,  220,  201,  220,  220,  220,  220,
-      157,  220,  152,  220,  220,  220,  220,   91,   90,  220,
-      220,  220,  102,  220,  159,  220,  220,  220,  220,  220,
-      123,  162,  220,  220,  220,  220,   81,  220,  220,   75,
-
-      220,  220,  220,  220,  197,  220,   13,   14,   15,   17,
-       18,   19,   20,   21,   22,   23,   24,   25,   98,  192,
-      188,    0,  168,  180,    0,  220,  220,  220,  220,  220,
-      220,  202,  220,  119,  124,  163,  220,  220,  220,  220,
-      220,  220,  118,  220,  160,  220,  220,  220,  220,  220,
-      220,  220,  135,  220,  220,  220,  115,  220,  125,  220,
-      220,   60,  220,   66,  220,  220,  220,  220,  220,  220,
-      189,  164,  220,  220,  220,  220,  220,  220,  220,  220,
-      220,  220,  220,  198,  199,  220,   52,  220,   88,  220,
-      220,  220,  220,  155,  220,   46,   51,  220,  220,  220,
-
-      220,  220,  220,  220,  220,  220,  220,  220,  220,  220,
-      220,  220,  220,  220,  220,  220,  220,  220,  220,  220,
-      220,  220,   57,   59,   63,  220,  220,   86,   85,   87,
-      220,  220,  220,   26,   27,   28,  220,  220,   44,  220,
-      220,  220,  220,   48,   31,   32,   33,  220,  220,  220,
-       80,  220,  220,  220,  220,   36,  220,  220,   64,  220,
-       89,  220,   49,  220,  220,  220,  220,  220,  220,   54,
-      220,  220,  220,  220,  220,  220,   84,  220,  220,   92,
-      220,   65,  220,  220,   61,   30,   29,  220,  220,  220,
-      220,  220,  220,   35,   34,   47,  220,  220,   41,   39,
-
-      220,  220,  220,  220,  220,  220,  220,   37,  220,  220,
-       42,  220,  220,   70,  220,  220,  220,  220,   38,  220,
-      220,  220,   69,  220,  220,   40,   73,  220,   58,   67,
-      220,   74,   68,    0
-    } ;
-
-static yyconst flex_int32_t yy_ec[256] =
-    {   0,
-        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
-        1,    1,    2,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    2,    1,    4,    5,    1,    1,    1,    1,    1,
-        1,    1,    6,    1,    7,    8,    9,   10,   11,   12,
-       13,   14,   15,   15,   15,   15,   15,    1,    1,    1,
-       16,    1,    1,    1,   17,   18,   19,   20,   21,   22,
-       23,   24,   25,   26,   27,   28,   29,   30,   31,   32,
-       33,   34,   35,   36,   37,   38,   39,   40,   41,   42,
-        1,    1,    1,    1,   26,    1,   43,   44,   45,   46,
-
-       47,   48,   49,   50,   51,   26,   52,   53,   54,   55,
-       56,   57,   58,   59,   60,   61,   62,   63,   26,   64,
-       65,   26,   66,    1,   67,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1
-    } ;
-
-static yyconst flex_int32_t yy_meta[68] =
-    {   0,
-        1,    1,    2,    1,    1,    1,    1,    1,    1,    3,
-        3,    3,    3,    3,    3,    1,    3,    3,    3,    3,
-        3,    3,    4,    4,    4,    4,    4,    4,    4,    4,
-        4,    4,    4,    4,    4,    4,    4,    4,    4,    4,
-        4,    4,    3,    3,    3,    3,    3,    3,    4,    4,
-        4,    4,    4,    4,    4,    4,    4,    4,    4,    4,
-        4,    4,    4,    4,    4,    1,    1
-    } ;
-
-static yyconst flex_int16_t yy_base[856] =
-    {   0,
-        0,    0,   66,   69,   72,   74,   76,   78,   80,   82,
-       83,   89,  149,  216,  283,  350,  417,  484,  551,  618,
-      685,  752,  102,  106, 1192, 1193,  110,  112, 1187,   70,
-      112, 1181,  126,  159,  216,  182,  149,  154, 1156,  191,
-      162, 1126,   76,    0, 1166,  151,  283,   89,   88,  220,
-     1124,  231,  275,  138,    0, 1138,  242,  107,   36, 1128,
-       90, 1128, 1139, 1131, 1121, 1119, 1193,  180,  189, 1174,
-     1193,  204,  237, 1193, 1193,  241,  253, 1193, 1193, 1193,
-     1193, 1193, 1193,  255, 1193, 1193, 1193, 1193, 1193, 1193,
-      257,  262,    0, 1193,  268,  272,    0, 1193,  278,  300,
-
-        0, 1193,  302,  311,    0, 1193,  313,  321,    0, 1193,
-      325,  327,   36,  330, 1173, 1193, 1129,  131,  145, 1120,
-      327,    0,  357,  365,    0,    0, 1146, 1153, 1147, 1125,
-     1113, 1112,    0, 1134,  221, 1108, 1105, 1126, 1147,    0,
-      293, 1110, 1143, 1125, 1130,  250, 1105,    0, 1133, 1106,
-     1103, 1112,    0, 1137, 1132, 1096, 1098,  234, 1104, 1128,
-     1118, 1126, 1091, 1105,  211,  325,  147, 1091, 1110,  362,
-     1121,    0, 1106, 1115,  284, 1088, 1091,    0, 1120, 1104,
-      365, 1098, 1079, 1105, 1113, 1114, 1112, 1075,  274, 1071,
-     1065,  338, 1067,  341, 1082, 1067, 1064, 1088, 1104, 1069,
-
-     1085, 1075, 1066, 1055, 1062, 1061, 1057, 1051, 1050, 1067,
-     1047, 1065,  385, 1103, 1193,  388,  390,  392,  396,    0,
-      398,    0,  400,    0,  404,    0,  406,    0,  408,  159,
-     1058, 1057,  353, 1058,  388, 1058, 1056,  425,    0,  434,
-        0, 1050,    0, 1065, 1040, 1048, 1050, 1076, 1040, 1049,
-     1047, 1045,    0, 1062, 1034,  358, 1029, 1035, 1048,  425,
-     1069, 1024, 1023, 1040, 1054, 1028, 1027, 1030,    0,    0,
-     1024, 1024, 1037,    0, 1028, 1042, 1052,    0, 1023,    0,
-        0, 1037, 1048, 1052, 1046,  447, 1006,    0,  420, 1041,
-        0, 1030, 1034, 1020, 1002, 1005,  998,    0, 1031,    0,
-
-     1041, 1039, 1010, 1030,  436, 1018,    0,  996,  999,  991,
-     1007,  990,  993,  985,  997,  995,  983,  988,  995,  980,
-     1019, 1007,  977, 1006,  985,  992,  978,  977,  972,  988,
-      450,  453,  971,  982,  979,  417,  981,  425,  975,  977,
-      977,  972,  975,  975,  967,  972,  496, 1193,  963,  986,
-      969,  972,  959,  992,  966,  959,  963,  991,  976,  948,
-      950,  398,  943,    0,  970,    0,  441,  980,  973,  951,
-        0,  949,    0,    0,    0,  945,  951,    0,  963,  415,
-        0,  979,  933,  963,  942,  937,  940,  939,  461,  946,
-      937,  959,  958,  957,    0,  948,  929,    0,  923,  934,
-
-      963,    0,    0,  932,  958,    0,  488,  954,  951,  922,
-      927,  913,  913,  926,  925,  924,  921,  912,  904,  905,
-      918,  916,    0,    0,  915,    0,  908,  900,    0,  900,
-      911,  896,    0,    0,    0,  892,  891,  890,  906,    0,
-      905,  903,  903,  898,  901,  901,  891, 1193, 1193,  897,
-      896,  896,  880,  893,  503,  520,  893,  920,  878,  901,
-      890,  901,    0,  874,  874,  870,    0,    0,  876,  871,
-      868,  874,  910,    0,  903,  907,  899,  502,  868,  875,
-      860,  903,  872,    0,  884,  874,  882,  862,  863,  860,
-      859,  847,  855,  852,  848,  876,  878,  869,  885,  856,
-
-      851,    0,  882,  841,    0,    0,  876,  880,  878,  849,
-      849,  838,  850,  845,  840,  829,  828,  837,  826,  814,
-      847,  753,  787,    0,    0,    0,    0,  511,  514,  525,
-      531,  769,    0, 1193, 1193,  766,  765,  765,  764, 1193,
-     1193,  762,  763, 1193,    0,    0,  748,  751,  788,    0,
-        0,  786,  756,    0,  756,  755,  754,  768,  781,    0,
-      779,  746,  743,  748,  735,    0,  738,  733,  759,  735,
-      770,  739,    0,  726,  726,  724,  723,    0,    0,  765,
-      739,  747,    0,  759,    0,  718,  717,  756,  729,  757,
-        0,    0,  715,  753,  713,  727,    0,  717,  751,    0,
-
-      692,  702,  705,  685,    0,  703,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0, 1193,
-     1193,  697, 1193, 1193,  697,  714,  723,  679,  684,  691,
-      716,    0,  719,    0,    0,    0,  693,  684,  691,  682,
-      671,  666,    0,  684,    0,  682,  681,  671,  679,  678,
-      673,  669,    0,  688,  674,  655,    0,  660,    0,  558,
-      671,    0,  664,  541,  654,  653,  570,  655,  665,  652,
-     1193, 1193,  655,  654,  661,  655,  660,  644,  643,  644,
-      646,  656,  622,    0,    0,  639,    0,  622,    0,  621,
-      620,  635,  620,    0,  617,    0,    0,  655,  654,  653,
-
-      635,  614,  623,  612,  621,  608,  618,  618,  644,  643,
-      642,  624,  613,  611,  606,  611,  593,  607,  598,  594,
-      597,  603,    0,    0,    0,  603,  594,    0,    0,    0,
-      588,  594,  586,    0,  616,    0,  626,  582,    0,  456,
-       87,  591,  593,    0,    0,  611,    0,  621,  583,  590,
-        0,  589,  588,  569,  556,  580,  568,  564,    0,  550,
-        0,  563,    0,  574,  587,  557,  563,  546,  558,    0,
-      542,  555,  566,  579,  538,  539,    0,  538,  537,    0,
-      556,    0,  547,  575,    0,    0,    0,  574,  546,  534,
-      559,  540,  527,    0,    0,    0,  551,  541,    0,    0,
-
-      520,  525,  525,  522,  518,  506,  519,  513,  507,  491,
-        0,  482,  476,    0,   58,  118,  153,  222,    0,  272,
-      266,  275,    0,  344,  354,    0,    0,  406,    0,    0,
-      402,    0,    0, 1193,  819,  823,  827,  831,  835,  839,
-      843,  847,  851,  855,  859,  863,  865,  869,  871,  873,
-      875,  877,  879,  883,  470
-    } ;
-
-static yyconst flex_int16_t yy_def[856] =
-    {   0,
-      834,    1,  835,  835,  836,  836,  837,  837,  838,  838,
-      839,  839,  840,  840,  841,  841,  842,  842,  843,  843,
-      844,  844,  845,  845,  834,  834,  834,  834,  846,  834,
-      834,  834,  834,  834,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  834,  834,  834,  848,
-      834,  834,  834,  834,  834,  834,  834,  834,  834,  834,
-      834,  834,  834,  834,  834,  834,  834,  834,  834,  834,
-      834,  834,  849,  834,  834,  834,  850,  834,  834,  834,
-
-      851,  834,  834,  834,  852,  834,  834,  834,  853,  834,
-      834,  834,  834,  834,  846,  834,  834,  834,  834,  834,
-      834,  854,  834,  834,  855,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  834,  848,  834,  834,  834,  834,  834,  849,
-      834,  850,  834,  851,  834,  852,  834,  853,  834,  834,
-      834,  834,  834,  834,  834,  834,  834,  834,  854,  834,
-      855,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  834,  834,  834,  834,  834,
-      834,  834,  834,  834,  834,  834,  834,  834,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  834,  834,  834,  834,  834,  834,  834,  834,  834,
-      834,  834,  834,  834,  834,  834,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  834,  834,  834,  834,  834,  834,  834,
-      834,  834,  834,  834,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  834,
-      834,  834,  834,  834,  834,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      834,  834,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,    0,  834,  834,  834,  834,  834,  834,
-      834,  834,  834,  834,  834,  834,  834,  834,  834,  834,
-      834,  834,  834,  834,  834
-    } ;
-
-static yyconst flex_int16_t yy_nxt[1261] =
-    {   0,
-       26,   27,   28,   29,   30,   26,   31,   26,   32,   33,
-       34,   34,   34,   34,   34,   26,   35,   36,   37,   38,
-       39,   40,   41,   42,   43,   44,   45,   46,   47,   48,
-       49,   50,   51,   52,   53,   54,   55,   56,   57,   44,
-       44,   58,   59,   44,   60,   44,   44,   61,   44,   44,
-       62,   44,   44,   63,   44,   44,   44,   44,   44,   64,
-       65,   66,   44,   44,   44,   26,   26,   68,   69,   70,
-       68,   69,   70,   72,   73,   72,   73,   76,   77,   76,
-       77,   80,  230,   80,   84,   84,  231,   74,  203,   74,
-       84,   84,   85,   86,   87,   88,   89,  204,   85,   86,
-
-       87,   88,   89,  111,  112,  158,  113,  111,  112,  169,
-      113,  114,  114,  114,  114,  117,  118,  171,  823,  170,
-      119,  121,  121,  121,  121,  121,  121,  201,  202,  769,
-      159,  120,  206,  123,  770,  124,  124,  124,  124,  124,
-      124,   78,  207,   78,  172,   81,   82,   81,   82,   90,
-       91,   92,   90,   90,   90,   90,   90,   90,   90,   90,
-       90,   90,   90,   90,   90,  125,  123,  138,  124,  124,
-      124,  124,  124,  124,  143,  161,  139,  824,  153,  154,
-      193,  213,  213,  233,  194,  234,  162,  140,  144,  125,
-      213,  213,  235,  163,  145,  825,  195,  155,  133,  236,
-
-      146,  285,  196,  286,  141,  216,  216,  149,  156,  147,
-      142,  336,  134,  337,   90,   90,   90,   91,   92,   90,
-       90,   90,   90,   90,   90,   90,   90,   90,   90,   90,
-       90,   90,  127,  150,  135,  128,  173,  136,  216,  216,
-      281,  151,  217,  217,  282,  129,  137,  178,  179,  152,
-      174,  180,  273,  181,  217,  217,  218,  218,  219,  219,
-      826,  130,  175,  219,  219,  182,  198,  249,  131,  221,
-      221,  274,  132,  221,  221,  199,  250,  183,  176,  223,
-      223,   90,   90,   94,   95,   96,   94,   94,   94,   94,
-       94,   94,   94,   94,   94,   94,   94,   94,   94,  164,
-
-      200,  223,  223,  225,  225,  184,  262,  165,  185,  263,
-      186,  187,  225,  225,  227,  227,  309,  188,  827,  189,
-      828,  190,  227,  227,  310,  166,  229,  229,  229,  229,
-      191,  114,  114,  167,  829,  192,  238,  238,  238,  238,
-      238,  238,  294,  295,  168,  255,  256,  257,   94,   94,
-       94,   95,   96,   94,   94,   94,   94,   94,   94,   94,
-       94,   94,   94,   94,   94,   94,  240,  240,  240,  240,
-      240,  240,  123,  283,  124,  124,  124,  124,  124,  124,
-      289,  300,  301,  290,  313,  316,  213,  213,  284,  216,
-      216,  217,  217,  218,  218,  830,  314,  219,  219,  221,
-
-      221,  223,  223,  340,  317,  225,  225,  227,  227,  229,
-      229,  361,  341,  831,  362,   94,   94,   98,   99,  100,
-       98,   98,   98,   98,   98,   98,   98,   98,   98,   98,
-       98,   98,   98,  343,  238,  238,  238,  238,  238,  238,
-      470,  366,  344,  240,  240,  240,  240,  240,  240,  367,
-      392,  832,  406,  833,  347,  348,  393,  474,  368,  471,
-      407,  433,  434,  435,  436,  437,  438,  442,  388,  408,
-      445,  483,  241,  767,  475,  389,  443,  768,  484,  446,
-      347,  348,   98,   98,   98,   99,  100,   98,   98,   98,
-       98,   98,   98,   98,   98,   98,   98,   98,   98,   98,
-
-      390,  455,  455,  492,  506,  456,  456,  456,  456,  456,
-      456,  493,  456,  456,  456,  456,  456,  456,  822,  562,
-      563,  507,  607,  608,  609,  610,  611,  612,  821,  456,
-      456,  456,  456,  456,  456,  564,  613,  614,  615,  820,
-      565,  348,  616,  617,  618,  819,  818,  817,  816,   98,
-       98,  102,  103,  104,  102,  102,  102,  102,  102,  102,
-      102,  102,  102,  102,  102,  102,  102,  348,  698,  699,
-      700,  704,  815,  814,  705,  813,  701,  812,  811,  706,
-      709,  710,  711,  810,  809,  808,  807,  806,  712,  805,
-      804,  803,  802,  801,  800,  799,  798,  797,  796,  795,
-
-      794,  793,  792,  791,  790,  789,  788,  787,  786,  785,
-      784,  783,  782,  781,  780,  779,  102,  102,  102,  103,
-      104,  102,  102,  102,  102,  102,  102,  102,  102,  102,
-      102,  102,  102,  102,  778,  777,  776,  775,  774,  773,
-      772,  771,  766,  765,  764,  763,  762,  761,  760,  759,
-      758,  757,  756,  755,  754,  753,  752,  751,  750,  749,
-      748,  747,  746,  745,  744,  743,  742,  741,  740,  739,
-      738,  737,  736,  735,  734,  733,  732,  731,  730,  729,
-      728,  727,  726,  102,  102,  106,  107,  108,  106,  106,
-      106,  106,  106,  106,  106,  106,  106,  106,  106,  106,
-
-      106,  725,  724,  723,  722,  721,  720,  719,  718,  717,
-      716,  715,  714,  713,  708,  707,  703,  702,  697,  696,
-      695,  694,  693,  692,  691,  690,  689,  688,  687,  686,
-      685,  684,  683,  682,  681,  680,  679,  678,  677,  676,
-      675,  674,  673,  672,  671,  670,  669,  668,  667,  666,
-      106,  106,  106,  107,  108,  106,  106,  106,  106,  106,
-      106,  106,  106,  106,  106,  106,  106,  106,  665,  664,
-      663,  662,  661,  660,  659,  658,  657,  656,  655,  654,
-      653,  652,  651,  650,  649,  648,  647,  646,  645,  644,
-      643,  642,  641,  640,  639,  638,  637,  636,  635,  634,
-
-      633,  632,  631,  630,  629,  628,  627,  626,  625,  624,
-      623,  622,  621,  620,  619,  606,  605,  106,  106,   67,
-       67,   67,   67,   71,   71,   71,   71,   75,   75,   75,
-       75,   79,   79,   79,   79,   83,   83,   83,   83,   93,
-       93,   93,   93,   97,   97,   97,   97,  101,  101,  101,
-      101,  105,  105,  105,  105,  109,  109,  109,  109,  110,
-      110,  110,  110,  115,  604,  115,  115,  126,  126,  214,
-      603,  214,  214,  220,  220,  222,  222,  224,  224,  226,
-      226,  228,  228,  239,  602,  239,  239,  601,  600,  599,
-      598,  597,  596,  595,  594,  593,  592,  591,  590,  589,
-
-      588,  587,  586,  585,  584,  583,  582,  581,  580,  579,
-      578,  577,  576,  575,  574,  573,  572,  571,  570,  569,
-      568,  567,  566,  561,  560,  559,  558,  557,  556,  555,
-      554,  553,  552,  551,  550,  549,  548,  547,  546,  545,
-      544,  543,  542,  541,  540,  539,  538,  537,  536,  535,
-      534,  533,  532,  531,  530,  529,  528,  527,  526,  525,
-      524,  523,  522,  521,  520,  519,  518,  517,  516,  515,
-      514,  513,  512,  511,  510,  509,  508,  505,  504,  503,
-      502,  501,  500,  499,  498,  497,  496,  495,  494,  491,
-      490,  489,  488,  487,  486,  485,  482,  481,  480,  479,
-
-      478,  477,  476,  473,  472,  469,  468,  467,  466,  465,
-      464,  463,  462,  461,  460,  459,  458,  457,  454,  453,
-      452,  451,  450,  449,  448,  447,  444,  441,  440,  439,
-      432,  431,  430,  429,  428,  427,  426,  425,  424,  423,
-      422,  421,  420,  419,  418,  417,  416,  415,  414,  413,
-      412,  411,  410,  409,  405,  404,  403,  402,  401,  400,
-      399,  398,  397,  396,  395,  394,  391,  387,  386,  385,
-      384,  383,  382,  381,  380,  379,  378,  377,  376,  375,
-      374,  373,  372,  371,  370,  369,  365,  364,  363,  360,
-      359,  358,  357,  356,  355,  354,  353,  352,  351,  350,
-
-      349,  346,  345,  342,  339,  338,  215,  335,  334,  333,
-      332,  331,  330,  329,  328,  327,  326,  325,  324,  323,
-      322,  321,  320,  319,  318,  315,  312,  311,  308,  307,
-      306,  305,  304,  303,  302,  299,  298,  297,  296,  293,
-      292,  291,  288,  287,  280,  279,  278,  277,  276,  275,
-      272,  271,  270,  269,  268,  267,  266,  265,  264,  261,
-      260,  259,  258,  254,  253,  252,  251,  248,  247,  246,
-      245,  244,  243,  242,  237,  232,  116,  215,  212,  211,
-      210,  209,  208,  205,  197,  177,  160,  157,  148,  122,
-      116,  834,   25,  834,  834,  834,  834,  834,  834,  834,
-
-      834,  834,  834,  834,  834,  834,  834,  834,  834,  834,
-      834,  834,  834,  834,  834,  834,  834,  834,  834,  834,
-      834,  834,  834,  834,  834,  834,  834,  834,  834,  834,
-      834,  834,  834,  834,  834,  834,  834,  834,  834,  834,
-      834,  834,  834,  834,  834,  834,  834,  834,  834,  834,
-      834,  834,  834,  834,  834,  834,  834,  834,  834,  834
-    } ;
-
-static yyconst flex_int16_t yy_chk[1261] =
-    {   0,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    3,    3,    3,
-        4,    4,    4,    5,    5,    6,    6,    7,    7,    8,
-        8,    9,  113,   10,   11,   11,  113,    5,   59,    6,
-       12,   12,   11,   11,   11,   11,   11,   59,   12,   12,
-
-       12,   12,   12,   23,   23,   43,   23,   24,   24,   48,
-       24,   27,   27,   28,   28,   30,   30,   49,  815,   48,
-       30,   31,   31,   31,   31,   31,   31,   58,   58,  741,
-       43,   30,   61,   33,  741,   33,   33,   33,   33,   33,
-       33,    7,   61,    8,   49,    9,    9,   10,   10,   13,
-       13,   13,   13,   13,   13,   13,   13,   13,   13,   13,
-       13,   13,   13,   13,   13,   33,   34,   37,   34,   34,
-       34,   34,   34,   34,   38,   46,   37,  816,   41,   41,
-       54,   68,   68,  118,   54,  118,   46,   37,   38,   33,
-       69,   69,  119,   46,   38,  817,   54,   41,   36,  119,
-
-       38,  167,   54,  167,   37,   72,   72,   40,   41,   38,
-       37,  230,   36,  230,   13,   13,   14,   14,   14,   14,
-       14,   14,   14,   14,   14,   14,   14,   14,   14,   14,
-       14,   14,   35,   40,   36,   35,   50,   36,   73,   73,
-      165,   40,   76,   76,  165,   35,   36,   52,   52,   40,
-       50,   52,  158,   52,   77,   77,   84,   84,   91,   91,
-      818,   35,   50,   92,   92,   52,   57,  135,   35,   95,
-       95,  158,   35,   96,   96,   57,  135,   52,   50,   99,
-       99,   14,   14,   15,   15,   15,   15,   15,   15,   15,
-       15,   15,   15,   15,   15,   15,   15,   15,   15,   47,
-
-       57,  100,  100,  103,  103,   53,  146,   47,   53,  146,
-       53,   53,  104,  104,  107,  107,  189,   53,  820,   53,
-      821,   53,  108,  108,  189,   47,  111,  111,  112,  112,
-       53,  114,  114,   47,  822,   53,  121,  121,  121,  121,
-      121,  121,  175,  175,   47,  141,  141,  141,   15,   15,
-       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
-       16,   16,   16,   16,   16,   16,  123,  123,  123,  123,
-      123,  123,  124,  166,  124,  124,  124,  124,  124,  124,
-      170,  181,  181,  170,  192,  194,  213,  213,  166,  216,
-      216,  217,  217,  218,  218,  824,  192,  219,  219,  221,
-
-      221,  223,  223,  233,  194,  225,  225,  227,  227,  229,
-      229,  256,  233,  825,  256,   16,   16,   17,   17,   17,
-       17,   17,   17,   17,   17,   17,   17,   17,   17,   17,
-       17,   17,   17,  235,  238,  238,  238,  238,  238,  238,
-      362,  260,  235,  240,  240,  240,  240,  240,  240,  260,
-      289,  828,  305,  831,  240,  240,  289,  367,  260,  362,
-      305,  331,  331,  331,  332,  332,  332,  336,  286,  305,
-      338,  380,  855,  740,  367,  286,  336,  740,  380,  338,
-      240,  240,   17,   17,   18,   18,   18,   18,   18,   18,
-       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
-
-      286,  347,  347,  389,  407,  347,  347,  347,  347,  347,
-      347,  389,  455,  455,  455,  455,  455,  455,  813,  478,
-      478,  407,  528,  528,  528,  529,  529,  529,  812,  456,
-      456,  456,  456,  456,  456,  478,  530,  530,  530,  810,
-      478,  456,  531,  531,  531,  809,  808,  807,  806,   18,
-       18,   19,   19,   19,   19,   19,   19,   19,   19,   19,
-       19,   19,   19,   19,   19,   19,   19,  456,  660,  660,
-      660,  664,  805,  804,  664,  803,  660,  802,  801,  664,
-      667,  667,  667,  798,  797,  793,  792,  791,  667,  790,
-      789,  788,  784,  783,  781,  779,  778,  776,  775,  774,
-
-      773,  772,  771,  769,  768,  767,  766,  765,  764,  762,
-      760,  758,  757,  756,  755,  754,   19,   19,   20,   20,
-       20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
-       20,   20,   20,   20,  753,  752,  750,  749,  748,  746,
-      743,  742,  738,  737,  735,  733,  732,  731,  727,  726,
-      722,  721,  720,  719,  718,  717,  716,  715,  714,  713,
-      712,  711,  710,  709,  708,  707,  706,  705,  704,  703,
-      702,  701,  700,  699,  698,  695,  693,  692,  691,  690,
-      688,  686,  683,   20,   20,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-
-       21,  682,  681,  680,  679,  678,  677,  676,  675,  674,
-      673,  670,  669,  668,  666,  665,  663,  661,  658,  656,
-      655,  654,  652,  651,  650,  649,  648,  647,  646,  644,
-      642,  641,  640,  639,  638,  637,  633,  631,  630,  629,
-      628,  627,  626,  625,  622,  606,  604,  603,  602,  601,
-       21,   21,   22,   22,   22,   22,   22,   22,   22,   22,
-       22,   22,   22,   22,   22,   22,   22,   22,  599,  598,
-      596,  595,  594,  593,  590,  589,  588,  587,  586,  584,
-      582,  581,  580,  577,  576,  575,  574,  572,  571,  570,
-      569,  568,  567,  565,  564,  563,  562,  561,  559,  558,
-
-      557,  556,  555,  553,  552,  549,  548,  547,  543,  542,
-      539,  538,  537,  536,  532,  523,  522,   22,   22,  835,
-      835,  835,  835,  836,  836,  836,  836,  837,  837,  837,
-      837,  838,  838,  838,  838,  839,  839,  839,  839,  840,
-      840,  840,  840,  841,  841,  841,  841,  842,  842,  842,
-      842,  843,  843,  843,  843,  844,  844,  844,  844,  845,
-      845,  845,  845,  846,  521,  846,  846,  847,  847,  848,
-      520,  848,  848,  849,  849,  850,  850,  851,  851,  852,
-      852,  853,  853,  854,  519,  854,  854,  518,  517,  516,
-      515,  514,  513,  512,  511,  510,  509,  508,  507,  504,
-
-      503,  501,  500,  499,  498,  497,  496,  495,  494,  493,
-      492,  491,  490,  489,  488,  487,  486,  485,  483,  482,
-      481,  480,  479,  477,  476,  475,  473,  472,  471,  470,
-      469,  466,  465,  464,  462,  461,  460,  459,  458,  457,
-      454,  453,  452,  451,  450,  447,  446,  445,  444,  443,
-      442,  441,  439,  438,  437,  436,  432,  431,  430,  428,
-      427,  425,  422,  421,  420,  419,  418,  417,  416,  415,
-      414,  413,  412,  411,  410,  409,  408,  405,  404,  401,
-      400,  399,  397,  396,  394,  393,  392,  391,  390,  388,
-      387,  386,  385,  384,  383,  382,  379,  377,  376,  372,
-
-      370,  369,  368,  365,  363,  361,  360,  359,  358,  357,
-      356,  355,  354,  353,  352,  351,  350,  349,  346,  345,
-      344,  343,  342,  341,  340,  339,  337,  335,  334,  333,
-      330,  329,  328,  327,  326,  325,  324,  323,  322,  321,
-      320,  319,  318,  317,  316,  315,  314,  313,  312,  311,
-      310,  309,  308,  306,  304,  303,  302,  301,  299,  297,
-      296,  295,  294,  293,  292,  290,  287,  285,  284,  283,
-      282,  279,  277,  276,  275,  273,  272,  271,  268,  267,
-      266,  265,  264,  263,  262,  261,  259,  258,  257,  255,
-      254,  252,  251,  250,  249,  248,  247,  246,  245,  244,
-
-      242,  237,  236,  234,  232,  231,  214,  212,  211,  210,
-      209,  208,  207,  206,  205,  204,  203,  202,  201,  200,
-      199,  198,  197,  196,  195,  193,  191,  190,  188,  187,
-      186,  185,  184,  183,  182,  180,  179,  177,  176,  174,
-      173,  171,  169,  168,  164,  163,  162,  161,  160,  159,
-      157,  156,  155,  154,  152,  151,  150,  149,  147,  145,
-      144,  143,  142,  139,  138,  137,  136,  134,  132,  131,
-      130,  129,  128,  127,  120,  117,  115,   70,   66,   65,
-       64,   63,   62,   60,   56,   51,   45,   42,   39,   32,
-       29,   25,  834,  834,  834,  834,  834,  834,  834,  834,
-
-      834,  834,  834,  834,  834,  834,  834,  834,  834,  834,
-      834,  834,  834,  834,  834,  834,  834,  834,  834,  834,
-      834,  834,  834,  834,  834,  834,  834,  834,  834,  834,
-      834,  834,  834,  834,  834,  834,  834,  834,  834,  834,
-      834,  834,  834,  834,  834,  834,  834,  834,  834,  834,
-      834,  834,  834,  834,  834,  834,  834,  834,  834,  834
-    } ;
-
-/* Table of booleans, true if rule could match eol. */
-static yyconst flex_int32_t yy_rule_can_match_eol[223] =
-    {   0,
-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 
-    0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 
-    0, 0, 0,     };
-
-/* The intent behind this definition is that it'll catch
- * any uses of REJECT which flex missed.
- */
-#define REJECT reject_used_but_not_detected
-#define yymore() yymore_used_but_not_detected
-#define YY_MORE_ADJ 0
-#define YY_RESTORE_YY_MORE_OFFSET
-#line 1 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-#line 2 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-#include "BsParserFX.h"
-
-#define YY_USER_ACTION yylloc->first_column = yycolumn + 1; yylloc->first_line = yylineno + 1; yycolumn += (int)yyleng; yylloc->filename = getCurrentFilename(yyextra);
-#define YY_USER_INIT yylineno = 0; yycolumn = 0;
-#define YY_NO_UNISTD_H 1
-/* Start conditions */
-
-
-
-
-
-
-
-
-
-
-
-#line 1037 "BsLexerFX.c"
-
-#define INITIAL 0
-#define INCLUDE 1
-#define CODEBLOCK_HEADER 2
-#define CODEBLOCK_EQUALS 3
-#define CODEBLOCK 4
-#define CODEBLOCK_END 5
-#define DEFINE_COND 6
-#define UNDEF_COND 7
-#define CONDITIONAL_IF 8
-#define CONDITIONAL_IFN 9
-#define CONDITIONAL_ELIF 10
-#define CONDITIONAL_IGNORE 11
-
-/*windows compatibility case*/
-#include <io.h>
-#define isatty _isatty
-#define fileno _fileno
-    
-#define YY_EXTRA_TYPE struct tagParseState *
-
-/* Holds the entire state of the reentrant scanner. */
-struct yyguts_t
-    {
-
-    /* User-defined. Not touched by flex. */
-    YY_EXTRA_TYPE yyextra_r;
-
-    /* The rest are the same as the globals declared in the non-reentrant scanner. */
-    FILE *yyin_r, *yyout_r;
-    size_t yy_buffer_stack_top; /**< index of top of stack. */
-    size_t yy_buffer_stack_max; /**< capacity of stack. */
-    YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
-    char yy_hold_char;
-    yy_size_t yy_n_chars;
-    yy_size_t yyleng_r;
-    char *yy_c_buf_p;
-    int yy_init;
-    int yy_start;
-    int yy_did_buffer_switch_on_eof;
-    int yy_start_stack_ptr;
-    int yy_start_stack_depth;
-    int *yy_start_stack;
-    yy_state_type yy_last_accepting_state;
-    char* yy_last_accepting_cpos;
-
-    int yylineno_r;
-    int yy_flex_debug_r;
-
-    char *yytext_r;
-    int yy_more_flag;
-    int yy_more_len;
-
-    YYSTYPE * yylval_r;
-
-    YYLTYPE * yylloc_r;
-
-    }; /* end struct yyguts_t */
-
-static int yy_init_globals (yyscan_t yyscanner );
-
-    /* This must go here because YYSTYPE and YYLTYPE are included
-     * from bison output in section 1.*/
-    #    define yylval yyg->yylval_r
-    
-    #    define yylloc yyg->yylloc_r
-    
-int yylex_init (yyscan_t* scanner);
-
-int yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
-
-/* Accessor methods to globals.
-   These are made visible to non-reentrant scanners for convenience. */
-
-int yylex_destroy (yyscan_t yyscanner );
-
-int yyget_debug (yyscan_t yyscanner );
-
-void yyset_debug (int debug_flag ,yyscan_t yyscanner );
-
-YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner );
-
-void yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
-
-FILE *yyget_in (yyscan_t yyscanner );
-
-void yyset_in  (FILE * in_str ,yyscan_t yyscanner );
-
-FILE *yyget_out (yyscan_t yyscanner );
-
-void yyset_out  (FILE * out_str ,yyscan_t yyscanner );
-
-yy_size_t yyget_leng (yyscan_t yyscanner );
-
-char *yyget_text (yyscan_t yyscanner );
-
-int yyget_lineno (yyscan_t yyscanner );
-
-void yyset_lineno (int line_number ,yyscan_t yyscanner );
-
-int yyget_column  (yyscan_t yyscanner );
-
-void yyset_column (int column_no ,yyscan_t yyscanner );
-
-YYSTYPE * yyget_lval (yyscan_t yyscanner );
-
-void yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
-
-       YYLTYPE *yyget_lloc (yyscan_t yyscanner );
-    
-        void yyset_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner );
-    
-/* Macros after this point can all be overridden by user definitions in
- * section 1.
- */
-
-#ifndef YY_SKIP_YYWRAP
-#ifdef __cplusplus
-extern "C" int yywrap (yyscan_t yyscanner );
-#else
-extern int yywrap (yyscan_t yyscanner );
-#endif
-#endif
-
-    static void yyunput (int c,char *buf_ptr  ,yyscan_t yyscanner);
-    
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
-#endif
-
-#ifndef YY_NO_INPUT
-
-#ifdef __cplusplus
-static int yyinput (yyscan_t yyscanner );
-#else
-static int input (yyscan_t yyscanner );
-#endif
-
-#endif
-
-/* Amount of stuff to slurp up with each read. */
-#ifndef YY_READ_BUF_SIZE
-#define YY_READ_BUF_SIZE 8192
-#endif
-
-/* Copy whatever the last rule matched to the standard output. */
-#ifndef ECHO
-/* This used to be an fputs(), but since the string might contain NUL's,
- * we now use fwrite().
- */
-#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
-#endif
-
-/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
- * is returned in "result".
- */
-#ifndef YY_INPUT
-#define YY_INPUT(buf,result,max_size) \
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
-		{ \
-		int c = '*'; \
-		size_t n; \
-		for ( n = 0; n < max_size && \
-			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
-			buf[n] = (char) c; \
-		if ( c == '\n' ) \
-			buf[n++] = (char) c; \
-		if ( c == EOF && ferror( yyin ) ) \
-			YY_FATAL_ERROR( "input in flex scanner failed" ); \
-		result = n; \
-		} \
-	else \
-		{ \
-		errno=0; \
-		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
-			{ \
-			if( errno != EINTR) \
-				{ \
-				YY_FATAL_ERROR( "input in flex scanner failed" ); \
-				break; \
-				} \
-			errno=0; \
-			clearerr(yyin); \
-			} \
-		}\
-\
-
-#endif
-
-/* No semi-colon after return; correct usage is to write "yyterminate();" -
- * we don't want an extra ';' after the "return" because that will cause
- * some compilers to complain about unreachable statements.
- */
-#ifndef yyterminate
-#define yyterminate() return YY_NULL
-#endif
-
-/* Number of entries by which start-condition stack grows. */
-#ifndef YY_START_STACK_INCR
-#define YY_START_STACK_INCR 25
-#endif
-
-/* Report a fatal error. */
-#ifndef YY_FATAL_ERROR
-#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
-#endif
-
-/* end tables serialization structures and prototypes */
-
-/* Default declaration of generated scanner - a define so the user can
- * easily add parameters.
- */
-#ifndef YY_DECL
-#define YY_DECL_IS_OURS 1
-
-extern int yylex \
-               (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner);
-
-#define YY_DECL int yylex \
-               (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner)
-#endif /* !YY_DECL */
-
-/* Code executed at the beginning of each rule, after yytext and yyleng
- * have been set up.
- */
-#ifndef YY_USER_ACTION
-#define YY_USER_ACTION
-#endif
-
-/* Code executed at the end of each rule. */
-#ifndef YY_BREAK
-#define YY_BREAK break;
-#endif
-
-#define YY_RULE_SETUP \
-	YY_USER_ACTION
-
-/** The main scanner function which does all the work.
- */
-YY_DECL
-{
-	register yy_state_type yy_current_state;
-	register char *yy_cp, *yy_bp;
-	register int yy_act;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-#line 34 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-
-
-#line 1291 "BsLexerFX.c"
-
-    yylval = yylval_param;
-
-    yylloc = yylloc_param;
-
-	if ( !yyg->yy_init )
-		{
-		yyg->yy_init = 1;
-
-#ifdef YY_USER_INIT
-		YY_USER_INIT;
-#endif
-
-		if ( ! yyg->yy_start )
-			yyg->yy_start = 1;	/* first start state */
-
-		if ( ! yyin )
-			yyin = stdin;
-
-		if ( ! yyout )
-			yyout = stdout;
-
-		if ( ! YY_CURRENT_BUFFER ) {
-			yyensure_buffer_stack (yyscanner);
-			YY_CURRENT_BUFFER_LVALUE =
-				yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
-		}
-
-		yy_load_buffer_state(yyscanner );
-		}
-
-	while ( 1 )		/* loops until end-of-file is reached */
-		{
-		yy_cp = yyg->yy_c_buf_p;
-
-		/* Support of yytext. */
-		*yy_cp = yyg->yy_hold_char;
-
-		/* yy_bp points to the position in yy_ch_buf of the start of
-		 * the current run.
-		 */
-		yy_bp = yy_cp;
-
-		yy_current_state = yyg->yy_start;
-yy_match:
-		do
-			{
-			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
-			if ( yy_accept[yy_current_state] )
-				{
-				yyg->yy_last_accepting_state = yy_current_state;
-				yyg->yy_last_accepting_cpos = yy_cp;
-				}
-			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-				{
-				yy_current_state = (int) yy_def[yy_current_state];
-				if ( yy_current_state >= 835 )
-					yy_c = yy_meta[(unsigned int) yy_c];
-				}
-			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-			++yy_cp;
-			}
-		while ( yy_current_state != 834 );
-		yy_cp = yyg->yy_last_accepting_cpos;
-		yy_current_state = yyg->yy_last_accepting_state;
-
-yy_find_action:
-		yy_act = yy_accept[yy_current_state];
-
-		YY_DO_BEFORE_ACTION;
-
-		if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
-			{
-			yy_size_t yyl;
-			for ( yyl = 0; yyl < yyleng; ++yyl )
-				if ( yytext[yyl] == '\n' )
-					   
-    do{ yylineno++;
-        yycolumn=0;
-    }while(0)
-;
-			}
-
-do_action:	/* This label is used only to access EOF actions. */
-
-		switch ( yy_act )
-	{ /* beginning of action switch */
-			case 0: /* must back up */
-			/* undo the effects of YY_DO_BEFORE_ACTION */
-			*yy_cp = yyg->yy_hold_char;
-			yy_cp = yyg->yy_last_accepting_cpos;
-			yy_current_state = yyg->yy_last_accepting_state;
-			goto yy_find_action;
-
-case 1:
-/* rule 1 can match eol */
-YY_RULE_SETUP
-#line 36 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ /* Skip blank */ }
-	YY_BREAK
-case 2:
-YY_RULE_SETUP
-#line 37 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = atoi(yytext); return TOKEN_INTEGER; }
-	YY_BREAK
-case 3:
-YY_RULE_SETUP
-#line 38 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = (int)strtol(yytext, 0, 0); return TOKEN_INTEGER; }
-	YY_BREAK
-case 4:
-YY_RULE_SETUP
-#line 39 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->floatValue = (float)atof(yytext); return TOKEN_FLOAT; }
-	YY_BREAK
-case 5:
-YY_RULE_SETUP
-#line 40 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->strValue = mmalloc_strdup(yyextra->memContext, yytext); return TOKEN_STRING; }
-	YY_BREAK
-case 6:
-YY_RULE_SETUP
-#line 41 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = 1; return TOKEN_BOOLEAN; }
-	YY_BREAK
-case 7:
-YY_RULE_SETUP
-#line 42 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = 0; return TOKEN_BOOLEAN; }
-	YY_BREAK
-/* Value types */
-case 8:
-YY_RULE_SETUP
-#line 46 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_Int; return TOKEN_INTTYPE; } 
-	YY_BREAK
-case 9:
-YY_RULE_SETUP
-#line 47 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_Int2; return TOKEN_INT2TYPE; } 
-	YY_BREAK
-case 10:
-YY_RULE_SETUP
-#line 48 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_Int3; return TOKEN_INT3TYPE; } 
-	YY_BREAK
-case 11:
-YY_RULE_SETUP
-#line 49 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_Int4; return TOKEN_INT4TYPE; }
-	YY_BREAK
-case 12:
-YY_RULE_SETUP
-#line 51 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_Float; return TOKEN_FLOATTYPE; } 
-	YY_BREAK
-case 13:
-YY_RULE_SETUP
-#line 52 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_Float2; return TOKEN_FLOAT2TYPE; } 
-	YY_BREAK
-case 14:
-YY_RULE_SETUP
-#line 53 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_Float3; return TOKEN_FLOAT3TYPE; } 
-	YY_BREAK
-case 15:
-YY_RULE_SETUP
-#line 54 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_Float4; return TOKEN_FLOAT4TYPE; }
-	YY_BREAK
-case 16:
-YY_RULE_SETUP
-#line 55 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_Color; return TOKEN_COLORTYPE; }
-	YY_BREAK
-case 17:
-YY_RULE_SETUP
-#line 57 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_Mat2x2; return TOKEN_MAT2x2TYPE; } 
-	YY_BREAK
-case 18:
-YY_RULE_SETUP
-#line 58 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_Mat2x3; return TOKEN_MAT2x3TYPE; } 
-	YY_BREAK
-case 19:
-YY_RULE_SETUP
-#line 59 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_Mat2x4; return TOKEN_MAT2x4TYPE; }
-	YY_BREAK
-case 20:
-YY_RULE_SETUP
-#line 61 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_Mat3x2; return TOKEN_MAT3x2TYPE; } 
-	YY_BREAK
-case 21:
-YY_RULE_SETUP
-#line 62 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_Mat3x3; return TOKEN_MAT3x3TYPE; } 
-	YY_BREAK
-case 22:
-YY_RULE_SETUP
-#line 63 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_Mat3x4; return TOKEN_MAT3x4TYPE; }
-	YY_BREAK
-case 23:
-YY_RULE_SETUP
-#line 65 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_Mat4x2; return TOKEN_MAT4x2TYPE; } 
-	YY_BREAK
-case 24:
-YY_RULE_SETUP
-#line 66 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_Mat4x3; return TOKEN_MAT4x3TYPE; } 
-	YY_BREAK
-case 25:
-YY_RULE_SETUP
-#line 67 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_Mat4x4; return TOKEN_MAT4x4TYPE; }
-	YY_BREAK
-case 26:
-YY_RULE_SETUP
-#line 69 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_Sampler1D; return TOKEN_SAMPLER1D; } 
-	YY_BREAK
-case 27:
-YY_RULE_SETUP
-#line 70 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_Sampler2D; return TOKEN_SAMPLER2D; } 
-	YY_BREAK
-case 28:
-YY_RULE_SETUP
-#line 71 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_Sampler3D; return TOKEN_SAMPLER3D; } 
-	YY_BREAK
-case 29:
-YY_RULE_SETUP
-#line 72 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_SamplerCUBE; return TOKEN_SAMPLERCUBE; } 
-	YY_BREAK
-case 30:
-YY_RULE_SETUP
-#line 73 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_Sampler2DMS; return TOKEN_SAMPLER2DMS; }
-	YY_BREAK
-case 31:
-YY_RULE_SETUP
-#line 75 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_Texture1D; return TOKEN_TEXTURE1D; } 
-	YY_BREAK
-case 32:
-YY_RULE_SETUP
-#line 76 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_Texture2D; return TOKEN_TEXTURE2D; } 
-	YY_BREAK
-case 33:
-YY_RULE_SETUP
-#line 77 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_Texture3D; return TOKEN_TEXTURE3D; } 
-	YY_BREAK
-case 34:
-YY_RULE_SETUP
-#line 78 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_TextureCUBE; return TOKEN_TEXTURECUBE; } 
-	YY_BREAK
-case 35:
-YY_RULE_SETUP
-#line 79 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_Texture2DMS; return TOKEN_TEXTURE2DMS; }
-	YY_BREAK
-case 36:
-YY_RULE_SETUP
-#line 81 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_ByteBuffer; return TOKEN_BYTEBUFFER; } 
-	YY_BREAK
-case 37:
-YY_RULE_SETUP
-#line 82 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_StructBuffer; return TOKEN_STRUCTBUFFER; } 
-	YY_BREAK
-case 38:
-YY_RULE_SETUP
-#line 84 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_TypedBufferRW; return TOKEN_RWTYPEDBUFFER; } 
-	YY_BREAK
-case 39:
-YY_RULE_SETUP
-#line 85 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_ByteBufferRW; return TOKEN_RWBYTEBUFFER; }
-	YY_BREAK
-case 40:
-YY_RULE_SETUP
-#line 86 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_StructBufferRW; return TOKEN_RWSTRUCTBUFFER; } 
-	YY_BREAK
-case 41:
-YY_RULE_SETUP
-#line 87 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_AppendBuffer; return TOKEN_RWAPPENDBUFFER; } 
-	YY_BREAK
-case 42:
-YY_RULE_SETUP
-#line 88 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = PT_ConsumeBuffer; return TOKEN_RWCONSUMEBUFFER; }
-	YY_BREAK
-case 43:
-YY_RULE_SETUP
-#line 90 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_PARAMSBLOCK; }
-	YY_BREAK
-/* Shader keywords */
-case 44:
-YY_RULE_SETUP
-#line 93 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_SEPARABLE; }
-	YY_BREAK
-case 45:
-YY_RULE_SETUP
-#line 94 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_QUEUE; }
-	YY_BREAK
-case 46:
-YY_RULE_SETUP
-#line 95 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_PRIORITY; }
-	YY_BREAK
-case 47:
-YY_RULE_SETUP
-#line 96 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_TRANSPARENT; }
-	YY_BREAK
-case 48:
-YY_RULE_SETUP
-#line 97 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_TECHNIQUE; }
-	YY_BREAK
-case 49:
-YY_RULE_SETUP
-#line 98 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_PARAMETERS; }
-	YY_BREAK
-case 50:
-YY_RULE_SETUP
-#line 99 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_BLOCKS; }
-	YY_BREAK
-/* Technique keywords */
-case 51:
-YY_RULE_SETUP
-#line 102 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_RENDERER; }
-	YY_BREAK
-case 52:
-YY_RULE_SETUP
-#line 103 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_LANGUAGE; }
-	YY_BREAK
-case 53:
-YY_RULE_SETUP
-#line 104 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_PASS; }
-	YY_BREAK
-/* Pass keywords */
-case 54:
-YY_RULE_SETUP
-#line 107 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_STENCILREF; }
-	YY_BREAK
-/* Rasterizer state keywords */
-case 55:
-YY_RULE_SETUP
-#line 110 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_FILLMODE; }
-	YY_BREAK
-case 56:
-YY_RULE_SETUP
-#line 111 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_CULLMODE; }
-	YY_BREAK
-case 57:
-YY_RULE_SETUP
-#line 112 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_DEPTHBIAS; }
-	YY_BREAK
-case 58:
-YY_RULE_SETUP
-#line 113 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_SDEPTHBIAS; }
-	YY_BREAK
-case 59:
-YY_RULE_SETUP
-#line 114 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_DEPTHCLIP; }
-	YY_BREAK
-case 60:
-YY_RULE_SETUP
-#line 115 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_SCISSOR; }
-	YY_BREAK
-case 61:
-YY_RULE_SETUP
-#line 116 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_MULTISAMPLE; }
-	YY_BREAK
-case 62:
-YY_RULE_SETUP
-#line 117 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_AALINE; }
-	YY_BREAK
-/* Depth-stencil state keywords */
-case 63:
-YY_RULE_SETUP
-#line 120 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_DEPTHREAD; }
-	YY_BREAK
-case 64:
-YY_RULE_SETUP
-#line 121 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_DEPTHWRITE; }
-	YY_BREAK
-case 65:
-YY_RULE_SETUP
-#line 122 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_COMPAREFUNC; }
-	YY_BREAK
-case 66:
-YY_RULE_SETUP
-#line 123 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_STENCIL; }
-	YY_BREAK
-case 67:
-YY_RULE_SETUP
-#line 124 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_STENCILREADMASK; }
-	YY_BREAK
-case 68:
-YY_RULE_SETUP
-#line 125 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_STENCILWRITEMASK; }
-	YY_BREAK
-case 69:
-YY_RULE_SETUP
-#line 126 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_STENCILOPFRONT; }
-	YY_BREAK
-case 70:
-YY_RULE_SETUP
-#line 127 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_STENCILOPBACK; }
-	YY_BREAK
-case 71:
-YY_RULE_SETUP
-#line 128 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_FAIL; }
-	YY_BREAK
-case 72:
-YY_RULE_SETUP
-#line 129 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_ZFAIL; }
-	YY_BREAK
-/* Blend state keywords */
-case 73:
-YY_RULE_SETUP
-#line 132 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_ALPHATOCOVERAGE; }
-	YY_BREAK
-case 74:
-YY_RULE_SETUP
-#line 133 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_INDEPENDANTBLEND; }
-	YY_BREAK
-case 75:
-YY_RULE_SETUP
-#line 134 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_TARGET; }
-	YY_BREAK
-case 76:
-YY_RULE_SETUP
-#line 135 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_INDEX; }
-	YY_BREAK
-case 77:
-YY_RULE_SETUP
-#line 136 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_BLEND; }
-	YY_BREAK
-case 78:
-YY_RULE_SETUP
-#line 137 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_COLOR; }
-	YY_BREAK
-case 79:
-YY_RULE_SETUP
-#line 138 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_ALPHA; }
-	YY_BREAK
-case 80:
-YY_RULE_SETUP
-#line 139 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_WRITEMASK; }
-	YY_BREAK
-case 81:
-YY_RULE_SETUP
-#line 140 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_SOURCE; }
-	YY_BREAK
-case 82:
-YY_RULE_SETUP
-#line 141 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_DEST; }
-	YY_BREAK
-case 83:
-YY_RULE_SETUP
-#line 142 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_OP; }
-	YY_BREAK
-/* Sampler state keywords */
-case 84:
-YY_RULE_SETUP
-#line 145 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_ADDRMODE; }
-	YY_BREAK
-case 85:
-YY_RULE_SETUP
-#line 146 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_MINFILTER; }
-	YY_BREAK
-case 86:
-YY_RULE_SETUP
-#line 147 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_MAGFILTER; }
-	YY_BREAK
-case 87:
-YY_RULE_SETUP
-#line 148 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_MIPFILTER; }
-	YY_BREAK
-case 88:
-YY_RULE_SETUP
-#line 149 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_MAXANISO; }
-	YY_BREAK
-case 89:
-YY_RULE_SETUP
-#line 150 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_MIPBIAS; }
-	YY_BREAK
-case 90:
-YY_RULE_SETUP
-#line 151 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_MIPMIN; }
-	YY_BREAK
-case 91:
-YY_RULE_SETUP
-#line 152 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_MIPMAX; }
-	YY_BREAK
-case 92:
-YY_RULE_SETUP
-#line 153 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_BORDERCOLOR; }
-	YY_BREAK
-case 93:
-YY_RULE_SETUP
-#line 154 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_U; }
-	YY_BREAK
-case 94:
-YY_RULE_SETUP
-#line 155 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_V; }
-	YY_BREAK
-case 95:
-YY_RULE_SETUP
-#line 156 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_W; }
-	YY_BREAK
-/* Qualifiers */
-case 96:
-YY_RULE_SETUP
-#line 159 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_AUTO; }
-	YY_BREAK
-case 97:
-YY_RULE_SETUP
-#line 160 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_ALIAS; }
-	YY_BREAK
-case 98:
-YY_RULE_SETUP
-#line 161 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_SHARED; }
-	YY_BREAK
-case 99:
-YY_RULE_SETUP
-#line 162 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return TOKEN_USAGE; }
-	YY_BREAK
-/* State values */
-case 100:
-YY_RULE_SETUP
-#line 165 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = FMV_Wire; return TOKEN_FILLMODEVALUE; }
-	YY_BREAK
-case 101:
-YY_RULE_SETUP
-#line 166 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = FMV_Solid; return TOKEN_FILLMODEVALUE; }
-	YY_BREAK
-case 102:
-YY_RULE_SETUP
-#line 168 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = CMV_None; return TOKEN_CULLMODEVALUE; }
-	YY_BREAK
-case 103:
-YY_RULE_SETUP
-#line 169 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = CMV_CW; return TOKEN_CULLMODEVALUE; }
-	YY_BREAK
-case 104:
-YY_RULE_SETUP
-#line 170 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = CMV_CCW; return TOKEN_CULLMODEVALUE; }
-	YY_BREAK
-case 105:
-YY_RULE_SETUP
-#line 172 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = CFV_Fail; return TOKEN_COMPFUNCVALUE; }
-	YY_BREAK
-case 106:
-YY_RULE_SETUP
-#line 173 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = CFV_Pass; return TOKEN_COMPFUNCVALUE; }
-	YY_BREAK
-case 107:
-YY_RULE_SETUP
-#line 174 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = CFV_LT; return TOKEN_COMPFUNCVALUE; }
-	YY_BREAK
-case 108:
-YY_RULE_SETUP
-#line 175 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = CFV_LTE; return TOKEN_COMPFUNCVALUE; }
-	YY_BREAK
-case 109:
-YY_RULE_SETUP
-#line 176 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = CFV_EQ; return TOKEN_COMPFUNCVALUE; }
-	YY_BREAK
-case 110:
-YY_RULE_SETUP
-#line 177 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = CFV_NEQ; return TOKEN_COMPFUNCVALUE; }
-	YY_BREAK
-case 111:
-YY_RULE_SETUP
-#line 178 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = CFV_GTE; return TOKEN_COMPFUNCVALUE; }
-	YY_BREAK
-case 112:
-YY_RULE_SETUP
-#line 179 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = CFV_GT; return TOKEN_COMPFUNCVALUE; }
-	YY_BREAK
-case 113:
-YY_RULE_SETUP
-#line 181 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = OV_Keep; return TOKEN_OPVALUE; }
-	YY_BREAK
-case 114:
-YY_RULE_SETUP
-#line 182 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = OV_Zero; return TOKEN_OPVALUE; }
-	YY_BREAK
-case 115:
-YY_RULE_SETUP
-#line 183 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = OV_Replace; return TOKEN_OPVALUE; }
-	YY_BREAK
-case 116:
-YY_RULE_SETUP
-#line 184 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = OV_Incr; return TOKEN_OPVALUE; }
-	YY_BREAK
-case 117:
-YY_RULE_SETUP
-#line 185 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = OV_Decr; return TOKEN_OPVALUE; }
-	YY_BREAK
-case 118:
-YY_RULE_SETUP
-#line 186 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = OV_IncrWrap; return TOKEN_OPVALUE; }
-	YY_BREAK
-case 119:
-YY_RULE_SETUP
-#line 187 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = OV_DecrWrap; return TOKEN_OPVALUE; }
-	YY_BREAK
-case 120:
-YY_RULE_SETUP
-#line 188 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = OV_Invert; return TOKEN_OPVALUE; }
-	YY_BREAK
-case 121:
-YY_RULE_SETUP
-#line 189 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = OV_One; return TOKEN_OPVALUE; }
-	YY_BREAK
-case 122:
-YY_RULE_SETUP
-#line 190 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = OV_DestColor; return TOKEN_OPVALUE; }
-	YY_BREAK
-case 123:
-YY_RULE_SETUP
-#line 191 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = OV_SrcColor; return TOKEN_OPVALUE; }
-	YY_BREAK
-case 124:
-YY_RULE_SETUP
-#line 192 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = OV_InvDestColor; return TOKEN_OPVALUE; }
-	YY_BREAK
-case 125:
-YY_RULE_SETUP
-#line 193 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = OV_InvSrcColor; return TOKEN_OPVALUE; }
-	YY_BREAK
-case 126:
-YY_RULE_SETUP
-#line 194 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = OV_DestAlpha; return TOKEN_OPVALUE; }
-	YY_BREAK
-case 127:
-YY_RULE_SETUP
-#line 195 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = OV_SrcAlpha; return TOKEN_OPVALUE; }
-	YY_BREAK
-case 128:
-YY_RULE_SETUP
-#line 196 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = OV_InvDestAlpha; return TOKEN_OPVALUE; }
-	YY_BREAK
-case 129:
-YY_RULE_SETUP
-#line 197 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = OV_InvSrcAlpha; return TOKEN_OPVALUE; }
-	YY_BREAK
-case 130:
-YY_RULE_SETUP
-#line 199 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = BOV_Add; return TOKEN_BLENDOPVALUE; }
-	YY_BREAK
-case 131:
-YY_RULE_SETUP
-#line 200 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = BOV_Subtract; return TOKEN_BLENDOPVALUE; }
-	YY_BREAK
-case 132:
-YY_RULE_SETUP
-#line 201 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = BOV_RevSubtract; return TOKEN_BLENDOPVALUE; }
-	YY_BREAK
-case 133:
-YY_RULE_SETUP
-#line 202 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = BOV_Min; return TOKEN_BLENDOPVALUE; }
-	YY_BREAK
-case 134:
-YY_RULE_SETUP
-#line 203 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = BOV_Max; return TOKEN_BLENDOPVALUE; }
-	YY_BREAK
-case 135:
-YY_RULE_SETUP
-#line 205 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = 0x0; return TOKEN_COLORMASK; }
-	YY_BREAK
-case 136:
-YY_RULE_SETUP
-#line 206 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = 0x1; return TOKEN_COLORMASK; }
-	YY_BREAK
-case 137:
-YY_RULE_SETUP
-#line 207 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = 0x2; return TOKEN_COLORMASK; }
-	YY_BREAK
-case 138:
-YY_RULE_SETUP
-#line 208 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = 0x4; return TOKEN_COLORMASK; }
-	YY_BREAK
-case 139:
-YY_RULE_SETUP
-#line 209 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = 0x8; return TOKEN_COLORMASK; }
-	YY_BREAK
-case 140:
-YY_RULE_SETUP
-#line 210 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = 0x3; return TOKEN_COLORMASK; }
-	YY_BREAK
-case 141:
-YY_RULE_SETUP
-#line 211 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = 0x5; return TOKEN_COLORMASK; }
-	YY_BREAK
-case 142:
-YY_RULE_SETUP
-#line 212 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = 0x9; return TOKEN_COLORMASK; }
-	YY_BREAK
-case 143:
-YY_RULE_SETUP
-#line 213 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = 0x6; return TOKEN_COLORMASK; }
-	YY_BREAK
-case 144:
-YY_RULE_SETUP
-#line 214 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = 0xA; return TOKEN_COLORMASK; }
-	YY_BREAK
-case 145:
-YY_RULE_SETUP
-#line 215 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = 0xC; return TOKEN_COLORMASK; }
-	YY_BREAK
-case 146:
-YY_RULE_SETUP
-#line 216 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = 0x7; return TOKEN_COLORMASK; }
-	YY_BREAK
-case 147:
-YY_RULE_SETUP
-#line 217 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = 0xB; return TOKEN_COLORMASK; }
-	YY_BREAK
-case 148:
-YY_RULE_SETUP
-#line 218 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = 0xD; return TOKEN_COLORMASK; }
-	YY_BREAK
-case 149:
-YY_RULE_SETUP
-#line 219 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = 0xE; return TOKEN_COLORMASK; }
-	YY_BREAK
-case 150:
-YY_RULE_SETUP
-#line 220 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = 0xF; return TOKEN_COLORMASK; }
-	YY_BREAK
-case 151:
-YY_RULE_SETUP
-#line 222 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = AMV_Wrap; return TOKEN_ADDRMODEVALUE; }
-	YY_BREAK
-case 152:
-YY_RULE_SETUP
-#line 223 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = AMV_Mirror; return TOKEN_ADDRMODEVALUE; }
-	YY_BREAK
-case 153:
-YY_RULE_SETUP
-#line 224 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = AMV_Clamp; return TOKEN_ADDRMODEVALUE; }
-	YY_BREAK
-case 154:
-YY_RULE_SETUP
-#line 225 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = AMV_Border; return TOKEN_ADDRMODEVALUE; }
-	YY_BREAK
-case 155:
-YY_RULE_SETUP
-#line 227 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = FV_None; return TOKEN_FILTERVALUE; }
-	YY_BREAK
-case 156:
-YY_RULE_SETUP
-#line 228 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = FV_Point; return TOKEN_FILTERVALUE; }
-	YY_BREAK
-case 157:
-YY_RULE_SETUP
-#line 229 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = FV_Linear; return TOKEN_FILTERVALUE; }
-	YY_BREAK
-case 158:
-YY_RULE_SETUP
-#line 230 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = FV_Anisotropic; return TOKEN_FILTERVALUE; }
-	YY_BREAK
-case 159:
-YY_RULE_SETUP
-#line 231 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = FV_PointCmp; return TOKEN_FILTERVALUE; }
-	YY_BREAK
-case 160:
-YY_RULE_SETUP
-#line 232 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = FV_LinearCmp; return TOKEN_FILTERVALUE; }
-	YY_BREAK
-case 161:
-YY_RULE_SETUP
-#line 233 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = FV_AnisotropicCmp; return TOKEN_FILTERVALUE; }
-	YY_BREAK
-case 162:
-YY_RULE_SETUP
-#line 235 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = BUV_Static; return TOKEN_BUFFERUSAGE; }
-	YY_BREAK
-case 163:
-YY_RULE_SETUP
-#line 236 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = BUV_Dynamic; return TOKEN_BUFFERUSAGE; }
-	YY_BREAK
-/* Preprocessor */
-case 164:
-YY_RULE_SETUP
-#line 239 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ BEGIN(INCLUDE); }
-	YY_BREAK
-case 165:
-/* rule 165 can match eol */
-YY_RULE_SETUP
-#line 241 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ /* Skip blank */ }
-	YY_BREAK
-case 166:
-YY_RULE_SETUP
-#line 242 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{
-	int size = 0;
-	char* includeBuffer = includePush(yyextra, yytext, yylineno, yycolumn, &size);
-	if(!includeBuffer)
-		yyterminate();
-
-	YY_BUFFER_STATE currentBuffer = YY_CURRENT_BUFFER;
-	YY_BUFFER_STATE newBuffer = yy_scan_buffer(includeBuffer,size,yyscanner);
-
-	yy_switch_to_buffer(currentBuffer,yyscanner);
-	yypush_buffer_state(newBuffer,yyscanner);
-
-	yylineno = 0; 
-	yycolumn = 0;
-
-	BEGIN(INITIAL);
-	}
-	YY_BREAK
-case 167:
-YY_RULE_SETUP
-#line 259 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return yytext[0]; }
-	YY_BREAK
-case YY_STATE_EOF(INITIAL):
-case YY_STATE_EOF(INCLUDE):
-case YY_STATE_EOF(CODEBLOCK_HEADER):
-case YY_STATE_EOF(CODEBLOCK_EQUALS):
-case YY_STATE_EOF(CODEBLOCK):
-case YY_STATE_EOF(CODEBLOCK_END):
-case YY_STATE_EOF(DEFINE_COND):
-case YY_STATE_EOF(UNDEF_COND):
-case YY_STATE_EOF(CONDITIONAL_IF):
-case YY_STATE_EOF(CONDITIONAL_IFN):
-case YY_STATE_EOF(CONDITIONAL_ELIF):
-case YY_STATE_EOF(CONDITIONAL_IGNORE):
-#line 261 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{
-	if(!yyextra->includeStack)
-		yyterminate();
-
-	yypop_buffer_state(yyscanner);
-	includePop(yyextra);
-}
-	YY_BREAK
-case 168:
-YY_RULE_SETUP
-#line 269 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ BEGIN(DEFINE_COND); }
-	YY_BREAK
-case 169:
-/* rule 169 can match eol */
-YY_RULE_SETUP
-#line 270 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ /* Skip blank */ }
-	YY_BREAK
-case 170:
-YY_RULE_SETUP
-#line 271 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ addDefine(yyextra, yytext); BEGIN(INITIAL); }
-	YY_BREAK
-case 171:
-YY_RULE_SETUP
-#line 272 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return yytext[0]; }
-	YY_BREAK
-case 172:
-YY_RULE_SETUP
-#line 274 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ BEGIN(UNDEF_COND); }
-	YY_BREAK
-case 173:
-/* rule 173 can match eol */
-YY_RULE_SETUP
-#line 275 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ /* Skip blank */ }
-	YY_BREAK
-case 174:
-YY_RULE_SETUP
-#line 276 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ removeDefine(yyextra, yytext); BEGIN(INITIAL); }
-	YY_BREAK
-case 175:
-YY_RULE_SETUP
-#line 277 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return yytext[0]; }
-	YY_BREAK
-case 176:
-YY_RULE_SETUP
-#line 279 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ BEGIN(CONDITIONAL_IF); }
-	YY_BREAK
-case 177:
-/* rule 177 can match eol */
-YY_RULE_SETUP
-#line 280 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ /* Skip blank */ }
-	YY_BREAK
-case 178:
-YY_RULE_SETUP
-#line 281 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ 
-	int isEnabled = pushConditional(yyextra, hasDefine(yyextra, yytext));
-	if(!isEnabled)
-		BEGIN(CONDITIONAL_IGNORE);
-	else
-		BEGIN(INITIAL);
-}
-	YY_BREAK
-case 179:
-YY_RULE_SETUP
-#line 288 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return yytext[0]; }
-	YY_BREAK
-case 180:
-YY_RULE_SETUP
-#line 290 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ BEGIN(CONDITIONAL_IFN); }
-	YY_BREAK
-case 181:
-/* rule 181 can match eol */
-YY_RULE_SETUP
-#line 291 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ /* Skip blank */ }
-	YY_BREAK
-case 182:
-YY_RULE_SETUP
-#line 292 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ 
-	int isEnabled = pushConditional(yyextra, !hasDefine(yyextra, yytext));
-	if(!isEnabled)
-		BEGIN(CONDITIONAL_IGNORE);
-	else
-		BEGIN(INITIAL);
-}
-	YY_BREAK
-case 183:
-YY_RULE_SETUP
-#line 299 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return yytext[0]; }
-	YY_BREAK
-case 184:
-YY_RULE_SETUP
-#line 301 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ BEGIN(CONDITIONAL_IGNORE); }
-	YY_BREAK
-case 185:
-YY_RULE_SETUP
-#line 302 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ BEGIN(CONDITIONAL_IGNORE); }
-	YY_BREAK
-case 186:
-YY_RULE_SETUP
-#line 304 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ popConditional(yyextra); }
-	YY_BREAK
-case 187:
-/* rule 187 can match eol */
-YY_RULE_SETUP
-#line 306 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ /* Skip */ }
-	YY_BREAK
-case 188:
-YY_RULE_SETUP
-#line 307 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ pushConditional(yyextra, 0); }
-	YY_BREAK
-case 189:
-YY_RULE_SETUP
-#line 308 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ pushConditional(yyextra, 0); }
-	YY_BREAK
-case 190:
-YY_RULE_SETUP
-#line 309 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ 
-	if(switchConditional(yyextra))
-		BEGIN(INITIAL);
-}
-	YY_BREAK
-case 191:
-YY_RULE_SETUP
-#line 313 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ BEGIN(CONDITIONAL_ELIF); }
-	YY_BREAK
-case 192:
-YY_RULE_SETUP
-#line 314 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ 
-	if(popConditional(yyextra))
-		BEGIN(INITIAL);
-}
-	YY_BREAK
-case 193:
-YY_RULE_SETUP
-#line 318 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ /* Skip */ }
-	YY_BREAK
-case 194:
-/* rule 194 can match eol */
-YY_RULE_SETUP
-#line 320 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ /* Skip blank */ }
-	YY_BREAK
-case 195:
-YY_RULE_SETUP
-#line 321 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ 
-	int isEnabled = setConditional(yyextra, hasDefine(yyextra, yytext));
-	if(!isEnabled)
-		BEGIN(CONDITIONAL_IGNORE);
-	else
-		BEGIN(INITIAL);
-}
-	YY_BREAK
-case 196:
-YY_RULE_SETUP
-#line 328 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return yytext[0]; }
-	YY_BREAK
-/* Code blocks */
-case 197:
-YY_RULE_SETUP
-#line 331 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ BEGIN(CODEBLOCK_HEADER); return TOKEN_VERTEX; }
-	YY_BREAK
-case 198:
-YY_RULE_SETUP
-#line 332 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ BEGIN(CODEBLOCK_HEADER); return TOKEN_FRAGMENT; }
-	YY_BREAK
-case 199:
-YY_RULE_SETUP
-#line 333 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ BEGIN(CODEBLOCK_HEADER); return TOKEN_GEOMETRY; }
-	YY_BREAK
-case 200:
-YY_RULE_SETUP
-#line 334 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ BEGIN(CODEBLOCK_HEADER); return TOKEN_HULL; }
-	YY_BREAK
-case 201:
-YY_RULE_SETUP
-#line 335 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ BEGIN(CODEBLOCK_HEADER); return TOKEN_DOMAIN; }
-	YY_BREAK
-case 202:
-YY_RULE_SETUP
-#line 336 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ BEGIN(CODEBLOCK_HEADER); return TOKEN_COMPUTE; }
-	YY_BREAK
-case 203:
-YY_RULE_SETUP
-#line 337 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ BEGIN(CODEBLOCK_HEADER); return TOKEN_COMMON; }
-	YY_BREAK
-/* Track when the code block begins, insert all code block characters into our own buffer, record a sequential index */
-/* of all code blocks in the text, and track bracket open/closed state so we know when we're done with the code block. */
-/* And finally output a sequential code block index to the parser (it shouldn't be aware of anything else in the block). */
-case 204:
-YY_RULE_SETUP
-#line 342 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ BEGIN(CODEBLOCK_EQUALS); return yytext[0]; }
-	YY_BREAK
-case 205:
-/* rule 205 can match eol */
-YY_RULE_SETUP
-#line 343 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ /* Skip blank */ }
-	YY_BREAK
-case 206:
-YY_RULE_SETUP
-#line 344 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return yytext[0]; }
-	YY_BREAK
-case 207:
-YY_RULE_SETUP
-#line 346 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ BEGIN(CODEBLOCK); beginCodeBlock(yyextra); yyextra->numOpenBrackets = 1; return yytext[0]; }
-	YY_BREAK
-case 208:
-/* rule 208 can match eol */
-YY_RULE_SETUP
-#line 347 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ /* Skip blank */ }
-	YY_BREAK
-case 209:
-YY_RULE_SETUP
-#line 348 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return yytext[0]; }
-	YY_BREAK
-case 210:
-YY_RULE_SETUP
-#line 350 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yyextra->numOpenBrackets++; appendCodeBlock(yyextra, yytext, 1); }
-	YY_BREAK
-case 211:
-YY_RULE_SETUP
-#line 351 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ 
-	yyextra->numOpenBrackets--; 
-
-	if(yyextra->numOpenBrackets == 0)
-	{
-		BEGIN(CODEBLOCK_END);
-		unput('0');
-	}
-	else
-		appendCodeBlock(yyextra, yytext, 1);
-}
-	YY_BREAK
-case 212:
-/* rule 212 can match eol */
-YY_RULE_SETUP
-#line 362 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ appendCodeBlock(yyextra, yytext, 1); }
-	YY_BREAK
-/* Logic for manually inserting "Index = codeBlockIndex;". We insert arbitrary numbers which allows us to sequentially */
-/* output all the tokens we need. We use only single-character values so we don't override anything in the text buffer */
-/* (since the starting value was also a single character "{"). */
-case 213:
-YY_RULE_SETUP
-#line 367 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ unput('1'); return TOKEN_INDEX; }
-	YY_BREAK
-case 214:
-YY_RULE_SETUP
-#line 368 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ unput('2'); return '='; }
-	YY_BREAK
-case 215:
-YY_RULE_SETUP
-#line 369 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->intValue = getCodeBlockIndex(yyextra); unput('3'); return TOKEN_INTEGER; }
-	YY_BREAK
-case 216:
-YY_RULE_SETUP
-#line 370 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ unput('4'); return ';'; }
-	YY_BREAK
-case 217:
-YY_RULE_SETUP
-#line 371 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ BEGIN(INITIAL); return '}'; }
-	YY_BREAK
-case 218:
-/* rule 218 can match eol */
-YY_RULE_SETUP
-#line 372 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ /* Never reached */ }
-	YY_BREAK
-/* Catch all rules */
-case 219:
-YY_RULE_SETUP
-#line 375 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ }
-	YY_BREAK
-case 220:
-YY_RULE_SETUP
-#line 376 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ yylval->strValue = mmalloc_strdup(yyextra->memContext, yytext); return TOKEN_IDENTIFIER; }
-	YY_BREAK
-case 221:
-YY_RULE_SETUP
-#line 377 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-{ return yytext[0]; }
-	YY_BREAK
-case 222:
-YY_RULE_SETUP
-#line 379 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-YY_FATAL_ERROR( "flex scanner jammed" );
-	YY_BREAK
-#line 2598 "BsLexerFX.c"
-
-	case YY_END_OF_BUFFER:
-		{
-		/* Amount of text matched not including the EOB char. */
-		int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
-
-		/* Undo the effects of YY_DO_BEFORE_ACTION. */
-		*yy_cp = yyg->yy_hold_char;
-		YY_RESTORE_YY_MORE_OFFSET
-
-		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
-			{
-			/* We're scanning a new file or input source.  It's
-			 * possible that this happened because the user
-			 * just pointed yyin at a new source and called
-			 * yylex().  If so, then we have to assure
-			 * consistency between YY_CURRENT_BUFFER and our
-			 * globals.  Here is the right place to do so, because
-			 * this is the first action (other than possibly a
-			 * back-up) that will match for the new input source.
-			 */
-			yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
-			}
-
-		/* Note that here we test for yy_c_buf_p "<=" to the position
-		 * of the first EOB in the buffer, since yy_c_buf_p will
-		 * already have been incremented past the NUL character
-		 * (since all states make transitions on EOB to the
-		 * end-of-buffer state).  Contrast this with the test
-		 * in input().
-		 */
-		if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
-			{ /* This was really a NUL. */
-			yy_state_type yy_next_state;
-
-			yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
-
-			yy_current_state = yy_get_previous_state( yyscanner );
-
-			/* Okay, we're now positioned to make the NUL
-			 * transition.  We couldn't have
-			 * yy_get_previous_state() go ahead and do it
-			 * for us because it doesn't know how to deal
-			 * with the possibility of jamming (and we don't
-			 * want to build jamming into it because then it
-			 * will run more slowly).
-			 */
-
-			yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
-
-			yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
-
-			if ( yy_next_state )
-				{
-				/* Consume the NUL. */
-				yy_cp = ++yyg->yy_c_buf_p;
-				yy_current_state = yy_next_state;
-				goto yy_match;
-				}
-
-			else
-				{
-				yy_cp = yyg->yy_last_accepting_cpos;
-				yy_current_state = yyg->yy_last_accepting_state;
-				goto yy_find_action;
-				}
-			}
-
-		else switch ( yy_get_next_buffer( yyscanner ) )
-			{
-			case EOB_ACT_END_OF_FILE:
-				{
-				yyg->yy_did_buffer_switch_on_eof = 0;
-
-				if ( yywrap(yyscanner ) )
-					{
-					/* Note: because we've taken care in
-					 * yy_get_next_buffer() to have set up
-					 * yytext, we can now set up
-					 * yy_c_buf_p so that if some total
-					 * hoser (like flex itself) wants to
-					 * call the scanner after we return the
-					 * YY_NULL, it'll still work - another
-					 * YY_NULL will get returned.
-					 */
-					yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
-
-					yy_act = YY_STATE_EOF(YY_START);
-					goto do_action;
-					}
-
-				else
-					{
-					if ( ! yyg->yy_did_buffer_switch_on_eof )
-						YY_NEW_FILE;
-					}
-				break;
-				}
-
-			case EOB_ACT_CONTINUE_SCAN:
-				yyg->yy_c_buf_p =
-					yyg->yytext_ptr + yy_amount_of_matched_text;
-
-				yy_current_state = yy_get_previous_state( yyscanner );
-
-				yy_cp = yyg->yy_c_buf_p;
-				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
-				goto yy_match;
-
-			case EOB_ACT_LAST_MATCH:
-				yyg->yy_c_buf_p =
-				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
-
-				yy_current_state = yy_get_previous_state( yyscanner );
-
-				yy_cp = yyg->yy_c_buf_p;
-				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
-				goto yy_find_action;
-			}
-		break;
-		}
-
-	default:
-		YY_FATAL_ERROR(
-			"fatal flex scanner internal error--no action found" );
-	} /* end of action switch */
-		} /* end of scanning one token */
-} /* end of yylex */
-
-/* yy_get_next_buffer - try to read in a new buffer
- *
- * Returns a code representing an action:
- *	EOB_ACT_LAST_MATCH -
- *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
- *	EOB_ACT_END_OF_FILE - end of file
- */
-static int yy_get_next_buffer (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
-	register char *source = yyg->yytext_ptr;
-	register int number_to_move, i;
-	int ret_val;
-
-	if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
-		YY_FATAL_ERROR(
-		"fatal flex scanner internal error--end of buffer missed" );
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
-		{ /* Don't try to fill the buffer, so this is an EOF. */
-		if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
-			{
-			/* We matched a single character, the EOB, so
-			 * treat this as a final EOF.
-			 */
-			return EOB_ACT_END_OF_FILE;
-			}
-
-		else
-			{
-			/* We matched some text prior to the EOB, first
-			 * process it.
-			 */
-			return EOB_ACT_LAST_MATCH;
-			}
-		}
-
-	/* Try to read more data. */
-
-	/* First move last chars to start of buffer. */
-	number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
-
-	for ( i = 0; i < number_to_move; ++i )
-		*(dest++) = *(source++);
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
-		/* don't do the read, it's not guaranteed to return an EOF,
-		 * just force an EOF
-		 */
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
-
-	else
-		{
-			yy_size_t num_to_read =
-			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
-
-		while ( num_to_read <= 0 )
-			{ /* Not enough room in the buffer - grow it. */
-
-			/* just a shorter name for the current buffer */
-			YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
-
-			int yy_c_buf_p_offset =
-				(int) (yyg->yy_c_buf_p - b->yy_ch_buf);
-
-			if ( b->yy_is_our_buffer )
-				{
-				yy_size_t new_size = b->yy_buf_size * 2;
-
-				if ( new_size <= 0 )
-					b->yy_buf_size += b->yy_buf_size / 8;
-				else
-					b->yy_buf_size *= 2;
-
-				b->yy_ch_buf = (char *)
-					/* Include room in for 2 EOB chars. */
-					yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
-				}
-			else
-				/* Can't grow it, we don't own it. */
-				b->yy_ch_buf = 0;
-
-			if ( ! b->yy_ch_buf )
-				YY_FATAL_ERROR(
-				"fatal error - scanner input buffer overflow" );
-
-			yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
-
-			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
-						number_to_move - 1;
-
-			}
-
-		if ( num_to_read > YY_READ_BUF_SIZE )
-			num_to_read = YY_READ_BUF_SIZE;
-
-		/* Read in more data. */
-		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
-			yyg->yy_n_chars, num_to_read );
-
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
-		}
-
-	if ( yyg->yy_n_chars == 0 )
-		{
-		if ( number_to_move == YY_MORE_ADJ )
-			{
-			ret_val = EOB_ACT_END_OF_FILE;
-			yyrestart(yyin  ,yyscanner);
-			}
-
-		else
-			{
-			ret_val = EOB_ACT_LAST_MATCH;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
-				YY_BUFFER_EOF_PENDING;
-			}
-		}
-
-	else
-		ret_val = EOB_ACT_CONTINUE_SCAN;
-
-	if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
-		/* Extend the array by 50%, plus the number we really need. */
-		yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
-		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
-		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
-			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
-	}
-
-	yyg->yy_n_chars += number_to_move;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
-
-	yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
-
-	return ret_val;
-}
-
-/* yy_get_previous_state - get the state just before the EOB char was reached */
-
-    static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
-{
-	register yy_state_type yy_current_state;
-	register char *yy_cp;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	yy_current_state = yyg->yy_start;
-
-	for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
-		{
-		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
-		if ( yy_accept[yy_current_state] )
-			{
-			yyg->yy_last_accepting_state = yy_current_state;
-			yyg->yy_last_accepting_cpos = yy_cp;
-			}
-		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-			{
-			yy_current_state = (int) yy_def[yy_current_state];
-			if ( yy_current_state >= 835 )
-				yy_c = yy_meta[(unsigned int) yy_c];
-			}
-		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-		}
-
-	return yy_current_state;
-}
-
-/* yy_try_NUL_trans - try to make a transition on the NUL character
- *
- * synopsis
- *	next_state = yy_try_NUL_trans( current_state );
- */
-    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state , yyscan_t yyscanner)
-{
-	register int yy_is_jam;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
-	register char *yy_cp = yyg->yy_c_buf_p;
-
-	register YY_CHAR yy_c = 1;
-	if ( yy_accept[yy_current_state] )
-		{
-		yyg->yy_last_accepting_state = yy_current_state;
-		yyg->yy_last_accepting_cpos = yy_cp;
-		}
-	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-		{
-		yy_current_state = (int) yy_def[yy_current_state];
-		if ( yy_current_state >= 835 )
-			yy_c = yy_meta[(unsigned int) yy_c];
-		}
-	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-	yy_is_jam = (yy_current_state == 834);
-
-	(void)yyg;
-	return yy_is_jam ? 0 : yy_current_state;
-}
-
-    static void yyunput (int c, register char * yy_bp , yyscan_t yyscanner)
-{
-	register char *yy_cp;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-    yy_cp = yyg->yy_c_buf_p;
-
-	/* undo effects of setting up yytext */
-	*yy_cp = yyg->yy_hold_char;
-
-	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
-		{ /* need to shift things up to make room */
-		/* +2 for EOB chars. */
-		register yy_size_t number_to_move = yyg->yy_n_chars + 2;
-		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
-					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
-		register char *source =
-				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
-
-		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
-			*--dest = *--source;
-
-		yy_cp += (int) (dest - source);
-		yy_bp += (int) (dest - source);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
-			yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
-
-		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
-			YY_FATAL_ERROR( "flex scanner push-back overflow" );
-		}
-
-	*--yy_cp = (char) c;
-
-    if ( c == '\n' ){
-        --yylineno;
-    }
-
-	yyg->yytext_ptr = yy_bp;
-	yyg->yy_hold_char = *yy_cp;
-	yyg->yy_c_buf_p = yy_cp;
-}
-
-#ifndef YY_NO_INPUT
-#ifdef __cplusplus
-    static int yyinput (yyscan_t yyscanner)
-#else
-    static int input  (yyscan_t yyscanner)
-#endif
-
-{
-	int c;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	*yyg->yy_c_buf_p = yyg->yy_hold_char;
-
-	if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
-		{
-		/* yy_c_buf_p now points to the character we want to return.
-		 * If this occurs *before* the EOB characters, then it's a
-		 * valid NUL; if not, then we've hit the end of the buffer.
-		 */
-		if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
-			/* This was really a NUL. */
-			*yyg->yy_c_buf_p = '\0';
-
-		else
-			{ /* need more input */
-			yy_size_t offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
-			++yyg->yy_c_buf_p;
-
-			switch ( yy_get_next_buffer( yyscanner ) )
-				{
-				case EOB_ACT_LAST_MATCH:
-					/* This happens because yy_g_n_b()
-					 * sees that we've accumulated a
-					 * token and flags that we need to
-					 * try matching the token before
-					 * proceeding.  But for input(),
-					 * there's no matching to consider.
-					 * So convert the EOB_ACT_LAST_MATCH
-					 * to EOB_ACT_END_OF_FILE.
-					 */
-
-					/* Reset buffer status. */
-					yyrestart(yyin ,yyscanner);
-
-					/*FALLTHROUGH*/
-
-				case EOB_ACT_END_OF_FILE:
-					{
-					if ( yywrap(yyscanner ) )
-						return EOF;
-
-					if ( ! yyg->yy_did_buffer_switch_on_eof )
-						YY_NEW_FILE;
-#ifdef __cplusplus
-					return yyinput(yyscanner);
-#else
-					return input(yyscanner);
-#endif
-					}
-
-				case EOB_ACT_CONTINUE_SCAN:
-					yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
-					break;
-				}
-			}
-		}
-
-	c = *(unsigned char *) yyg->yy_c_buf_p;	/* cast for 8-bit char's */
-	*yyg->yy_c_buf_p = '\0';	/* preserve yytext */
-	yyg->yy_hold_char = *++yyg->yy_c_buf_p;
-
-	if ( c == '\n' )
-		   
-    do{ yylineno++;
-        yycolumn=0;
-    }while(0)
-;
-
-	return c;
-}
-#endif	/* ifndef YY_NO_INPUT */
-
-/** Immediately switch to a different input stream.
- * @param input_file A readable stream.
- * @param yyscanner The scanner object.
- * @note This function does not reset the start condition to @c INITIAL .
- */
-    void yyrestart  (FILE * input_file , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	if ( ! YY_CURRENT_BUFFER ){
-        yyensure_buffer_stack (yyscanner);
-		YY_CURRENT_BUFFER_LVALUE =
-            yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
-	}
-
-	yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
-	yy_load_buffer_state(yyscanner );
-}
-
-/** Switch to a different input buffer.
- * @param new_buffer The new input buffer.
- * @param yyscanner The scanner object.
- */
-    void yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	/* TODO. We should be able to replace this entire function body
-	 * with
-	 *		yypop_buffer_state();
-	 *		yypush_buffer_state(new_buffer);
-     */
-	yyensure_buffer_stack (yyscanner);
-	if ( YY_CURRENT_BUFFER == new_buffer )
-		return;
-
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*yyg->yy_c_buf_p = yyg->yy_hold_char;
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
-		}
-
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-	yy_load_buffer_state(yyscanner );
-
-	/* We don't actually know whether we did this switch during
-	 * EOF (yywrap()) processing, but the only time this flag
-	 * is looked at is after yywrap() is called, so it's safe
-	 * to go ahead and always set it.
-	 */
-	yyg->yy_did_buffer_switch_on_eof = 1;
-}
-
-static void yy_load_buffer_state  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-	yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
-	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
-	yyg->yy_hold_char = *yyg->yy_c_buf_p;
-}
-
-/** Allocate and initialize an input buffer state.
- * @param file A readable stream.
- * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
- * @param yyscanner The scanner object.
- * @return the allocated buffer state.
- */
-    YY_BUFFER_STATE yy_create_buffer  (FILE * file, int  size , yyscan_t yyscanner)
-{
-	YY_BUFFER_STATE b;
-    
-	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
-
-	b->yy_buf_size = size;
-
-	/* yy_ch_buf has to be 2 characters longer than the size given because
-	 * we need to put in 2 end-of-buffer characters.
-	 */
-	b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ,yyscanner );
-	if ( ! b->yy_ch_buf )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
-
-	b->yy_is_our_buffer = 1;
-
-	yy_init_buffer(b,file ,yyscanner);
-
-	return b;
-}
-
-/** Destroy the buffer.
- * @param b a buffer created with yy_create_buffer()
- * @param yyscanner The scanner object.
- */
-    void yy_delete_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	if ( ! b )
-		return;
-
-	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
-		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
-
-	if ( b->yy_is_our_buffer )
-		yyfree((void *) b->yy_ch_buf ,yyscanner );
-
-	yyfree((void *) b ,yyscanner );
-}
-
-/* Initializes or reinitializes a buffer.
- * This function is sometimes called more than once on the same buffer,
- * such as during a yyrestart() or at EOF.
- */
-    static void yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file , yyscan_t yyscanner)
-
-{
-	int oerrno = errno;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	yy_flush_buffer(b ,yyscanner);
-
-	b->yy_input_file = file;
-	b->yy_fill_buffer = 1;
-
-    /* If b is the current buffer, then yy_init_buffer was _probably_
-     * called from yyrestart() or through yy_get_next_buffer.
-     * In that case, we don't want to reset the lineno or column.
-     */
-    if (b != YY_CURRENT_BUFFER){
-        b->yy_bs_lineno = 1;
-        b->yy_bs_column = 0;
-    }
-
-        b->yy_is_interactive = 0;
-    
-	errno = oerrno;
-}
-
-/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
- * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
- * @param yyscanner The scanner object.
- */
-    void yy_flush_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	if ( ! b )
-		return;
-
-	b->yy_n_chars = 0;
-
-	/* We always need two end-of-buffer characters.  The first causes
-	 * a transition to the end-of-buffer state.  The second causes
-	 * a jam in that state.
-	 */
-	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
-	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
-
-	b->yy_buf_pos = &b->yy_ch_buf[0];
-
-	b->yy_at_bol = 1;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	if ( b == YY_CURRENT_BUFFER )
-		yy_load_buffer_state(yyscanner );
-}
-
-/** Pushes the new state onto the stack. The new state becomes
- *  the current state. This function will allocate the stack
- *  if necessary.
- *  @param new_buffer The new state.
- *  @param yyscanner The scanner object.
- */
-void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	if (new_buffer == NULL)
-		return;
-
-	yyensure_buffer_stack(yyscanner);
-
-	/* This block is copied from yy_switch_to_buffer. */
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*yyg->yy_c_buf_p = yyg->yy_hold_char;
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
-		}
-
-	/* Only push if top exists. Otherwise, replace top. */
-	if (YY_CURRENT_BUFFER)
-		yyg->yy_buffer_stack_top++;
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-
-	/* copied from yy_switch_to_buffer. */
-	yy_load_buffer_state(yyscanner );
-	yyg->yy_did_buffer_switch_on_eof = 1;
-}
-
-/** Removes and deletes the top of the stack, if present.
- *  The next element becomes the new top.
- *  @param yyscanner The scanner object.
- */
-void yypop_buffer_state (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	if (!YY_CURRENT_BUFFER)
-		return;
-
-	yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
-	YY_CURRENT_BUFFER_LVALUE = NULL;
-	if (yyg->yy_buffer_stack_top > 0)
-		--yyg->yy_buffer_stack_top;
-
-	if (YY_CURRENT_BUFFER) {
-		yy_load_buffer_state(yyscanner );
-		yyg->yy_did_buffer_switch_on_eof = 1;
-	}
-}
-
-/* Allocates the stack if it does not exist.
- *  Guarantees space for at least one push.
- */
-static void yyensure_buffer_stack (yyscan_t yyscanner)
-{
-	yy_size_t num_to_alloc;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	if (!yyg->yy_buffer_stack) {
-
-		/* First allocation is just for 2 elements, since we don't know if this
-		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
-		 * immediate realloc on the next call.
-         */
-		num_to_alloc = 1;
-		yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc
-								(num_to_alloc * sizeof(struct yy_buffer_state*)
-								, yyscanner);
-		if ( ! yyg->yy_buffer_stack )
-			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
-								  
-		memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-				
-		yyg->yy_buffer_stack_max = num_to_alloc;
-		yyg->yy_buffer_stack_top = 0;
-		return;
-	}
-
-	if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
-
-		/* Increase the buffer to prepare for a possible push. */
-		int grow_size = 8 /* arbitrary grow size */;
-
-		num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
-		yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc
-								(yyg->yy_buffer_stack,
-								num_to_alloc * sizeof(struct yy_buffer_state*)
-								, yyscanner);
-		if ( ! yyg->yy_buffer_stack )
-			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
-
-		/* zero only the new slots.*/
-		memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
-		yyg->yy_buffer_stack_max = num_to_alloc;
-	}
-}
-
-/** Setup the input buffer state to scan directly from a user-specified character buffer.
- * @param base the character buffer
- * @param size the size in bytes of the character buffer
- * @param yyscanner The scanner object.
- * @return the newly allocated buffer state object. 
- */
-YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size , yyscan_t yyscanner)
-{
-	YY_BUFFER_STATE b;
-    
-	if ( size < 2 ||
-	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
-	     base[size-1] != YY_END_OF_BUFFER_CHAR )
-		/* They forgot to leave room for the EOB's. */
-		return 0;
-
-	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
-
-	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
-	b->yy_buf_pos = b->yy_ch_buf = base;
-	b->yy_is_our_buffer = 0;
-	b->yy_input_file = 0;
-	b->yy_n_chars = b->yy_buf_size;
-	b->yy_is_interactive = 0;
-	b->yy_at_bol = 1;
-	b->yy_fill_buffer = 0;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	yy_switch_to_buffer(b ,yyscanner );
-
-	return b;
-}
-
-/** Setup the input buffer state to scan a string. The next call to yylex() will
- * scan from a @e copy of @a str.
- * @param yystr a NUL-terminated string to scan
- * @param yyscanner The scanner object.
- * @return the newly allocated buffer state object.
- * @note If you want to scan bytes that may contain NUL values, then use
- *       yy_scan_bytes() instead.
- */
-YY_BUFFER_STATE yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
-{
-    
-	return yy_scan_bytes(yystr,strlen(yystr) ,yyscanner);
-}
-
-/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
- * scan from a @e copy of @a bytes.
- * @param yybytes the byte buffer to scan
- * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
- * @param yyscanner The scanner object.
- * @return the newly allocated buffer state object.
- */
-YY_BUFFER_STATE yy_scan_bytes  (yyconst char * yybytes, yy_size_t  _yybytes_len , yyscan_t yyscanner)
-{
-	YY_BUFFER_STATE b;
-	char *buf;
-	yy_size_t n;
-	yy_size_t i;
-    
-	/* Get memory for full buffer, including space for trailing EOB's. */
-	n = _yybytes_len + 2;
-	buf = (char *) yyalloc(n ,yyscanner );
-	if ( ! buf )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
-
-	for ( i = 0; i < _yybytes_len; ++i )
-		buf[i] = yybytes[i];
-
-	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
-
-	b = yy_scan_buffer(buf,n ,yyscanner);
-	if ( ! b )
-		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
-
-	/* It's okay to grow etc. this buffer, and we should throw it
-	 * away when we're done.
-	 */
-	b->yy_is_our_buffer = 1;
-
-	return b;
-}
-
-#ifndef YY_EXIT_FAILURE
-#define YY_EXIT_FAILURE 2
-#endif
-
-static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
-{
-    	(void) fprintf( stderr, "%s\n", msg );
-	exit( YY_EXIT_FAILURE );
-}
-
-/* Redefine yyless() so it works in section 3 code. */
-
-#undef yyless
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up yytext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		yytext[yyleng] = yyg->yy_hold_char; \
-		yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
-		yyg->yy_hold_char = *yyg->yy_c_buf_p; \
-		*yyg->yy_c_buf_p = '\0'; \
-		yyleng = yyless_macro_arg; \
-		} \
-	while ( 0 )
-
-/* Accessor  methods (get/set functions) to struct members. */
-
-/** Get the user-defined data for this scanner.
- * @param yyscanner The scanner object.
- */
-YY_EXTRA_TYPE yyget_extra  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yyextra;
-}
-
-/** Get the current line number.
- * @param yyscanner The scanner object.
- */
-int yyget_lineno  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    
-        if (! YY_CURRENT_BUFFER)
-            return 0;
-    
-    return yylineno;
-}
-
-/** Get the current column number.
- * @param yyscanner The scanner object.
- */
-int yyget_column  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    
-        if (! YY_CURRENT_BUFFER)
-            return 0;
-    
-    return yycolumn;
-}
-
-/** Get the input stream.
- * @param yyscanner The scanner object.
- */
-FILE *yyget_in  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yyin;
-}
-
-/** Get the output stream.
- * @param yyscanner The scanner object.
- */
-FILE *yyget_out  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yyout;
-}
-
-/** Get the length of the current token.
- * @param yyscanner The scanner object.
- */
-yy_size_t yyget_leng  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yyleng;
-}
-
-/** Get the current token.
- * @param yyscanner The scanner object.
- */
-
-char *yyget_text  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yytext;
-}
-
-/** Set the user-defined data. This data is never touched by the scanner.
- * @param user_defined The data to be associated with this scanner.
- * @param yyscanner The scanner object.
- */
-void yyset_extra (YY_EXTRA_TYPE  user_defined , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yyextra = user_defined ;
-}
-
-/** Set the current line number.
- * @param line_number
- * @param yyscanner The scanner object.
- */
-void yyset_lineno (int  line_number , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-        /* lineno is only valid if an input buffer exists. */
-        if (! YY_CURRENT_BUFFER )
-           YY_FATAL_ERROR( "yyset_lineno called with no buffer" );
-    
-    yylineno = line_number;
-}
-
-/** Set the current column.
- * @param line_number
- * @param yyscanner The scanner object.
- */
-void yyset_column (int  column_no , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-        /* column is only valid if an input buffer exists. */
-        if (! YY_CURRENT_BUFFER )
-           YY_FATAL_ERROR( "yyset_column called with no buffer" );
-    
-    yycolumn = column_no;
-}
-
-/** Set the input stream. This does not discard the current
- * input buffer.
- * @param in_str A readable stream.
- * @param yyscanner The scanner object.
- * @see yy_switch_to_buffer
- */
-void yyset_in (FILE *  in_str , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yyin = in_str ;
-}
-
-void yyset_out (FILE *  out_str , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yyout = out_str ;
-}
-
-int yyget_debug  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yy_flex_debug;
-}
-
-void yyset_debug (int  bdebug , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yy_flex_debug = bdebug ;
-}
-
-/* Accessor methods for yylval and yylloc */
-
-YYSTYPE * yyget_lval  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yylval;
-}
-
-void yyset_lval (YYSTYPE *  yylval_param , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yylval = yylval_param;
-}
-
-YYLTYPE *yyget_lloc  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yylloc;
-}
-    
-void yyset_lloc (YYLTYPE *  yylloc_param , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yylloc = yylloc_param;
-}
-    
-/* User-visible API */
-
-/* yylex_init is special because it creates the scanner itself, so it is
- * the ONLY reentrant function that doesn't take the scanner as the last argument.
- * That's why we explicitly handle the declaration, instead of using our macros.
- */
-
-int yylex_init(yyscan_t* ptr_yy_globals)
-
-{
-    if (ptr_yy_globals == NULL){
-        errno = EINVAL;
-        return 1;
-    }
-
-    *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL );
-
-    if (*ptr_yy_globals == NULL){
-        errno = ENOMEM;
-        return 1;
-    }
-
-    /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
-    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
-
-    return yy_init_globals ( *ptr_yy_globals );
-}
-
-/* yylex_init_extra has the same functionality as yylex_init, but follows the
- * convention of taking the scanner as the last argument. Note however, that
- * this is a *pointer* to a scanner, as it will be allocated by this call (and
- * is the reason, too, why this function also must handle its own declaration).
- * The user defined value in the first argument will be available to yyalloc in
- * the yyextra field.
- */
-
-int yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
-
-{
-    struct yyguts_t dummy_yyguts;
-
-    yyset_extra (yy_user_defined, &dummy_yyguts);
-
-    if (ptr_yy_globals == NULL){
-        errno = EINVAL;
-        return 1;
-    }
-	
-    *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
-	
-    if (*ptr_yy_globals == NULL){
-        errno = ENOMEM;
-        return 1;
-    }
-    
-    /* By setting to 0xAA, we expose bugs in
-    yy_init_globals. Leave at 0x00 for releases. */
-    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
-    
-    yyset_extra (yy_user_defined, *ptr_yy_globals);
-    
-    return yy_init_globals ( *ptr_yy_globals );
-}
-
-static int yy_init_globals (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    /* Initialization is the same as for the non-reentrant scanner.
-     * This function is called from yylex_destroy(), so don't allocate here.
-     */
-
-    yyg->yy_buffer_stack = 0;
-    yyg->yy_buffer_stack_top = 0;
-    yyg->yy_buffer_stack_max = 0;
-    yyg->yy_c_buf_p = (char *) 0;
-    yyg->yy_init = 0;
-    yyg->yy_start = 0;
-
-    yyg->yy_start_stack_ptr = 0;
-    yyg->yy_start_stack_depth = 0;
-    yyg->yy_start_stack =  NULL;
-
-/* Defined in main.c */
-#ifdef YY_STDINIT
-    yyin = stdin;
-    yyout = stdout;
-#else
-    yyin = (FILE *) 0;
-    yyout = (FILE *) 0;
-#endif
-
-    /* For future reference: Set errno on error, since we are called by
-     * yylex_init()
-     */
-    return 0;
-}
-
-/* yylex_destroy is for both reentrant and non-reentrant scanners. */
-int yylex_destroy  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-    /* Pop the buffer stack, destroying each element. */
-	while(YY_CURRENT_BUFFER){
-		yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
-		YY_CURRENT_BUFFER_LVALUE = NULL;
-		yypop_buffer_state(yyscanner);
-	}
-
-	/* Destroy the stack itself. */
-	yyfree(yyg->yy_buffer_stack ,yyscanner);
-	yyg->yy_buffer_stack = NULL;
-
-    /* Destroy the start condition stack. */
-        yyfree(yyg->yy_start_stack ,yyscanner );
-        yyg->yy_start_stack = NULL;
-
-    /* Reset the globals. This is important in a non-reentrant scanner so the next time
-     * yylex() is called, initialization will occur. */
-    yy_init_globals( yyscanner);
-
-    /* Destroy the main struct (reentrant only). */
-    yyfree ( yyscanner , yyscanner );
-    yyscanner = NULL;
-    return 0;
-}
-
-/*
- * Internal utility routines.
- */
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
-{
-	register int i;
-	for ( i = 0; i < n; ++i )
-		s1[i] = s2[i];
-}
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
-{
-	register int n;
-	for ( n = 0; s[n]; ++n )
-		;
-
-	return n;
-}
-#endif
-
-void *yyalloc (yy_size_t  size , yyscan_t yyscanner)
-{
-	return (void *) malloc( size );
-}
-
-void *yyrealloc  (void * ptr, yy_size_t  size , yyscan_t yyscanner)
-{
-	/* The cast to (char *) in the following accommodates both
-	 * implementations that use char* generic pointers, and those
-	 * that use void* generic pointers.  It works with the latter
-	 * because both ANSI C and C++ allow castless assignment from
-	 * any pointer type to void*, and deal with argument conversions
-	 * as though doing an assignment.
-	 */
-	return (void *) realloc( (char *) ptr, size );
-}
-
-void yyfree (void * ptr , yyscan_t yyscanner)
-{
-	free( (char *) ptr );	/* see yyrealloc() for (char *) cast */
-}
-
-#define YYTABLES_NAME "yytables"
-
-#line 378 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
-
-
+#line 2 "BsLexerFX.c"
+
+#line 4 "BsLexerFX.c"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 37
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif	/* defined (__STDC__) */
+#endif	/* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For convenience, these vars (plus the bison vars far below)
+   are macros in the reentrant scanner. */
+#define yyin yyg->yyin_r
+#define yyout yyg->yyout_r
+#define yyextra yyg->yyextra_r
+#define yyleng yyg->yyleng_r
+#define yytext yyg->yytext_r
+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
+#define yy_flex_debug yyg->yy_flex_debug_r
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yyg->yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yyg->yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart(yyin ,yyscanner )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+    /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
+     *       access to the local variable yy_act. Since yyless() is a macro, it would break
+     *       existing scanners that call yyless() from OUTSIDE yylex. 
+     *       One obvious solution it to make yy_act a global. I tried that, and saw
+     *       a 5% performance hit in a non-yylineno scanner, because yy_act is
+     *       normally declared as a register variable-- so it is not worth it.
+     */
+    #define  YY_LESS_LINENO(n) \
+            do { \
+                int yyl;\
+                for ( yyl = n; yyl < yyleng; ++yyl )\
+                    if ( yytext[yyl] == '\n' )\
+                        --yylineno;\
+            }while(0)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		*yy_cp = yyg->yy_hold_char; \
+		YY_RESTORE_YY_MORE_OFFSET \
+		yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	yy_size_t yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+	 * shouldn't try reading from the input source any more.  We might
+	 * still have a bunch of tokens to match, though, because of
+	 * possible backing-up.
+	 *
+	 * When we actually see the EOF, we change the status to "new"
+	 * (via yyrestart()), so that the user can continue scanning by
+	 * just pointing yyin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
+                          ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
+                          : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
+
+void yyrestart (FILE *input_file ,yyscan_t yyscanner );
+void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
+void yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+void yypop_buffer_state (yyscan_t yyscanner );
+
+static void yyensure_buffer_stack (yyscan_t yyscanner );
+static void yy_load_buffer_state (yyscan_t yyscanner );
+static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
+
+#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
+
+YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len ,yyscan_t yyscanner );
+
+void *yyalloc (yy_size_t ,yyscan_t yyscanner );
+void *yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
+void yyfree (void * ,yyscan_t yyscanner );
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){ \
+        yyensure_buffer_stack (yyscanner); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){\
+        yyensure_buffer_stack (yyscanner); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define yywrap(yyscanner) 1
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+typedef int yy_state_type;
+
+#define yytext_ptr yytext_r
+
+static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  ,yyscan_t yyscanner);
+static int yy_get_next_buffer (yyscan_t yyscanner );
+static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	yyg->yytext_ptr = yy_bp; \
+	yyleng = (size_t) (yy_cp - yy_bp); \
+	yyg->yy_hold_char = *yy_cp; \
+	*yy_cp = '\0'; \
+	yyg->yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 222
+#define YY_END_OF_BUFFER 223
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+	{
+	flex_int32_t yy_verify;
+	flex_int32_t yy_nxt;
+	};
+static yyconst flex_int16_t yy_accept[835] =
+    {   0,
+        1,    1,  165,  165,  205,  205,  208,  208,    0,    0,
+      218,  218,  169,  169,  173,  173,  177,  177,  181,  181,
+      194,  194,  187,  187,  223,  221,    1,    1,  221,  221,
+      221,  221,    2,    2,  139,  138,  220,  220,  220,  220,
+      137,  220,  220,  220,  220,  220,  220,  220,  220,  220,
+      220,  136,  220,  220,   93,   94,   95,  220,  220,  220,
+      220,  220,  220,  220,  220,  220,  167,  165,  165,  167,
+      206,  205,  205,  204,  209,  208,  208,  207,  212,  212,
+      210,  211,  218,  218,  213,  214,  215,  216,  217,  171,
+      169,  169,  170,  175,  173,  173,  174,  179,  177,  177,
+
+      178,  183,  181,  181,  182,  196,  194,  194,  195,  193,
+      187,  187,  193,    1,    0,    5,    0,    0,    0,    0,
+        2,  219,    0,    2,    0,  220,  220,  220,  220,  220,
+      220,  220,  145,  220,  220,  220,  220,  220,  220,  103,
+      220,  220,  220,  220,  220,  220,  220,  109,  220,  220,
+      220,  220,  144,  143,  112,  220,  220,  220,  220,  220,
+      220,  107,  220,  220,  220,  220,  220,  220,  220,  220,
+      220,   83,  220,  220,  220,  220,  220,  142,  141,  220,
+      140,  220,  220,  220,  220,  220,  220,  220,  220,  220,
+      220,  220,  220,  220,  220,  220,  220,  220,  220,  220,
+
+      220,  220,  220,  220,  220,  220,  220,  220,  220,  220,
+      220,  220,  165,    0,  166,  205,  208,  218,  169,  170,
+      173,  174,  177,  178,  181,  182,  194,  195,  187,    0,
+        0,    0,    0,    0,    0,    0,    0,    2,  219,    4,
+        3,  220,  130,  220,  220,  220,  220,  220,  220,  220,
+      220,  220,  104,  220,  220,  220,  220,  220,  117,  220,
+      220,  220,  220,  220,  220,  220,  220,  220,  149,  111,
+      220,  220,  116,  120,  220,  220,  220,  108,  220,  134,
+      133,  220,  220,  220,  220,  220,  220,  110,  220,  220,
+      121,  220,  220,  220,  220,  220,  220,  148,  220,  147,
+
+      146,  220,  220,  220,  220,  220,  131,  220,  220,  220,
+      220,  220,  220,  220,  220,  220,  220,  220,  220,  220,
+      220,  220,  220,  220,  220,  220,  220,  220,  220,  220,
+        8,  220,  220,  220,  220,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    4,  220,  220,
+      220,  220,  220,  220,  220,  220,  220,  220,  220,  220,
+      220,  220,  220,   56,  220,  126,  220,  220,  220,  220,
+       82,  220,  105,   71,   55,  220,  220,  200,  220,  220,
+      113,  220,  220,  220,  220,  220,  220,  220,  220,  220,
+      220,  220,  220,  220,  106,  220,  220,   53,  220,  220,
+
+      220,  150,  132,  220,  220,  127,  220,  220,  220,  220,
+      220,  220,  220,  220,  220,  220,  220,  220,  220,  220,
+      220,  220,  100,  151,  220,  114,  220,  220,   96,  220,
+      220,  220,    9,   10,   11,  220,  220,  220,  220,    6,
+      220,    0,    0,    0,    0,    0,    0,  185,  184,    0,
+        0,    0,    0,    0,    0,    4,  220,  158,  220,   79,
+      220,  220,   77,   43,  220,  220,  153,   78,  220,  220,
+      220,  220,  220,  128,  220,  220,  220,  220,  220,  220,
+      220,  220,  220,   76,  220,  220,  220,  220,  220,  220,
+      220,  220,  220,  220,  220,  220,  220,  220,  156,  220,
+
+      220,   45,  220,  220,  101,  129,  220,  220,  220,  220,
+      220,  220,  220,  220,  220,  220,  220,  220,  220,  220,
+      220,  220,  220,   72,   97,   16,    7,   12,  220,  220,
+      220,  220,   99,  191,  190,    0,    0,    0,    0,  186,
+      176,    0,    0,  172,   62,  161,  220,  220,  220,  154,
+       50,  220,  220,  203,  220,  220,  220,  220,  220,  122,
+      220,  220,  220,  220,  220,  201,  220,  220,  220,  220,
+      157,  220,  152,  220,  220,  220,  220,   91,   90,  220,
+      220,  220,  102,  220,  159,  220,  220,  220,  220,  220,
+      123,  162,  220,  220,  220,  220,   81,  220,  220,   75,
+
+      220,  220,  220,  220,  197,  220,   13,   14,   15,   17,
+       18,   19,   20,   21,   22,   23,   24,   25,   98,  192,
+      188,    0,  168,  180,    0,  220,  220,  220,  220,  220,
+      220,  202,  220,  119,  124,  163,  220,  220,  220,  220,
+      220,  220,  118,  220,  160,  220,  220,  220,  220,  220,
+      220,  220,  135,  220,  220,  220,  115,  220,  125,  220,
+      220,   60,  220,   66,  220,  220,  220,  220,  220,  220,
+      189,  164,  220,  220,  220,  220,  220,  220,  220,  220,
+      220,  220,  220,  198,  199,  220,   52,  220,   88,  220,
+      220,  220,  220,  155,  220,   46,   51,  220,  220,  220,
+
+      220,  220,  220,  220,  220,  220,  220,  220,  220,  220,
+      220,  220,  220,  220,  220,  220,  220,  220,  220,  220,
+      220,  220,   57,   59,   63,  220,  220,   86,   85,   87,
+      220,  220,  220,   26,   27,   28,  220,  220,   44,  220,
+      220,  220,  220,   48,   31,   32,   33,  220,  220,  220,
+       80,  220,  220,  220,  220,   36,  220,  220,   64,  220,
+       89,  220,   49,  220,  220,  220,  220,  220,  220,   54,
+      220,  220,  220,  220,  220,  220,   84,  220,  220,   92,
+      220,   65,  220,  220,   61,   30,   29,  220,  220,  220,
+      220,  220,  220,   35,   34,   47,  220,  220,   41,   39,
+
+      220,  220,  220,  220,  220,  220,  220,   37,  220,  220,
+       42,  220,  220,   70,  220,  220,  220,  220,   38,  220,
+      220,  220,   69,  220,  220,   40,   73,  220,   58,   67,
+      220,   74,   68,    0
+    } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    1,    2,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    1,    4,    5,    1,    1,    1,    1,    1,
+        1,    1,    6,    1,    7,    8,    9,   10,   11,   12,
+       13,   14,   15,   15,   15,   15,   15,    1,    1,    1,
+       16,    1,    1,    1,   17,   18,   19,   20,   21,   22,
+       23,   24,   25,   26,   27,   28,   29,   30,   31,   32,
+       33,   34,   35,   36,   37,   38,   39,   40,   41,   42,
+        1,    1,    1,    1,   26,    1,   43,   44,   45,   46,
+
+       47,   48,   49,   50,   51,   26,   52,   53,   54,   55,
+       56,   57,   58,   59,   60,   61,   62,   63,   26,   64,
+       65,   26,   66,    1,   67,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst flex_int32_t yy_meta[68] =
+    {   0,
+        1,    1,    2,    1,    1,    1,    1,    1,    1,    3,
+        3,    3,    3,    3,    3,    1,    3,    3,    3,    3,
+        3,    3,    4,    4,    4,    4,    4,    4,    4,    4,
+        4,    4,    4,    4,    4,    4,    4,    4,    4,    4,
+        4,    4,    3,    3,    3,    3,    3,    3,    4,    4,
+        4,    4,    4,    4,    4,    4,    4,    4,    4,    4,
+        4,    4,    4,    4,    4,    1,    1
+    } ;
+
+static yyconst flex_int16_t yy_base[856] =
+    {   0,
+        0,    0,   66,   69,   72,   74,   76,   78,   80,   82,
+       83,   89,  149,  216,  283,  350,  417,  484,  551,  618,
+      685,  752,  102,  106, 1192, 1193,  110,  112, 1187,   70,
+      112, 1181,  126,  159,  216,  182,  149,  154, 1156,  191,
+      162, 1126,   76,    0, 1166,  151,  283,   89,   88,  220,
+     1124,  231,  275,  138,    0, 1138,  242,  107,   36, 1128,
+       90, 1128, 1139, 1131, 1121, 1119, 1193,  180,  189, 1174,
+     1193,  204,  237, 1193, 1193,  241,  253, 1193, 1193, 1193,
+     1193, 1193, 1193,  255, 1193, 1193, 1193, 1193, 1193, 1193,
+      257,  262,    0, 1193,  268,  272,    0, 1193,  278,  300,
+
+        0, 1193,  302,  311,    0, 1193,  313,  321,    0, 1193,
+      325,  327,   36,  330, 1173, 1193, 1129,  131,  145, 1120,
+      327,    0,  357,  365,    0,    0, 1146, 1153, 1147, 1125,
+     1113, 1112,    0, 1134,  221, 1108, 1105, 1126, 1147,    0,
+      293, 1110, 1143, 1125, 1130,  250, 1105,    0, 1133, 1106,
+     1103, 1112,    0, 1137, 1132, 1096, 1098,  234, 1104, 1128,
+     1118, 1126, 1091, 1105,  211,  325,  147, 1091, 1110,  362,
+     1121,    0, 1106, 1115,  284, 1088, 1091,    0, 1120, 1104,
+      365, 1098, 1079, 1105, 1113, 1114, 1112, 1075,  274, 1071,
+     1065,  338, 1067,  341, 1082, 1067, 1064, 1088, 1104, 1069,
+
+     1085, 1075, 1066, 1055, 1062, 1061, 1057, 1051, 1050, 1067,
+     1047, 1065,  385, 1103, 1193,  388,  390,  392,  396,    0,
+      398,    0,  400,    0,  404,    0,  406,    0,  408,  159,
+     1058, 1057,  353, 1058,  388, 1058, 1056,  425,    0,  434,
+        0, 1050,    0, 1065, 1040, 1048, 1050, 1076, 1040, 1049,
+     1047, 1045,    0, 1062, 1034,  358, 1029, 1035, 1048,  425,
+     1069, 1024, 1023, 1040, 1054, 1028, 1027, 1030,    0,    0,
+     1024, 1024, 1037,    0, 1028, 1042, 1052,    0, 1023,    0,
+        0, 1037, 1048, 1052, 1046,  447, 1006,    0,  420, 1041,
+        0, 1030, 1034, 1020, 1002, 1005,  998,    0, 1031,    0,
+
+     1041, 1039, 1010, 1030,  436, 1018,    0,  996,  999,  991,
+     1007,  990,  993,  985,  997,  995,  983,  988,  995,  980,
+     1019, 1007,  977, 1006,  985,  992,  978,  977,  972,  988,
+      450,  453,  971,  982,  979,  417,  981,  425,  975,  977,
+      977,  972,  975,  975,  967,  972,  496, 1193,  963,  986,
+      969,  972,  959,  992,  966,  959,  963,  991,  976,  948,
+      950,  398,  943,    0,  970,    0,  441,  980,  973,  951,
+        0,  949,    0,    0,    0,  945,  951,    0,  963,  415,
+        0,  979,  933,  963,  942,  937,  940,  939,  461,  946,
+      937,  959,  958,  957,    0,  948,  929,    0,  923,  934,
+
+      963,    0,    0,  932,  958,    0,  488,  954,  951,  922,
+      927,  913,  913,  926,  925,  924,  921,  912,  904,  905,
+      918,  916,    0,    0,  915,    0,  908,  900,    0,  900,
+      911,  896,    0,    0,    0,  892,  891,  890,  906,    0,
+      905,  903,  903,  898,  901,  901,  891, 1193, 1193,  897,
+      896,  896,  880,  893,  503,  520,  893,  920,  878,  901,
+      890,  901,    0,  874,  874,  870,    0,    0,  876,  871,
+      868,  874,  910,    0,  903,  907,  899,  502,  868,  875,
+      860,  903,  872,    0,  884,  874,  882,  862,  863,  860,
+      859,  847,  855,  852,  848,  876,  878,  869,  885,  856,
+
+      851,    0,  882,  841,    0,    0,  876,  880,  878,  849,
+      849,  838,  850,  845,  840,  829,  828,  837,  826,  814,
+      847,  753,  787,    0,    0,    0,    0,  511,  514,  525,
+      531,  769,    0, 1193, 1193,  766,  765,  765,  764, 1193,
+     1193,  762,  763, 1193,    0,    0,  748,  751,  788,    0,
+        0,  786,  756,    0,  756,  755,  754,  768,  781,    0,
+      779,  746,  743,  748,  735,    0,  738,  733,  759,  735,
+      770,  739,    0,  726,  726,  724,  723,    0,    0,  765,
+      739,  747,    0,  759,    0,  718,  717,  756,  729,  757,
+        0,    0,  715,  753,  713,  727,    0,  717,  751,    0,
+
+      692,  702,  705,  685,    0,  703,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0, 1193,
+     1193,  697, 1193, 1193,  697,  714,  723,  679,  684,  691,
+      716,    0,  719,    0,    0,    0,  693,  684,  691,  682,
+      671,  666,    0,  684,    0,  682,  681,  671,  679,  678,
+      673,  669,    0,  688,  674,  655,    0,  660,    0,  558,
+      671,    0,  664,  541,  654,  653,  570,  655,  665,  652,
+     1193, 1193,  655,  654,  661,  655,  660,  644,  643,  644,
+      646,  656,  622,    0,    0,  639,    0,  622,    0,  621,
+      620,  635,  620,    0,  617,    0,    0,  655,  654,  653,
+
+      635,  614,  623,  612,  621,  608,  618,  618,  644,  643,
+      642,  624,  613,  611,  606,  611,  593,  607,  598,  594,
+      597,  603,    0,    0,    0,  603,  594,    0,    0,    0,
+      588,  594,  586,    0,  616,    0,  626,  582,    0,  456,
+       87,  591,  593,    0,    0,  611,    0,  621,  583,  590,
+        0,  589,  588,  569,  556,  580,  568,  564,    0,  550,
+        0,  563,    0,  574,  587,  557,  563,  546,  558,    0,
+      542,  555,  566,  579,  538,  539,    0,  538,  537,    0,
+      556,    0,  547,  575,    0,    0,    0,  574,  546,  534,
+      559,  540,  527,    0,    0,    0,  551,  541,    0,    0,
+
+      520,  525,  525,  522,  518,  506,  519,  513,  507,  491,
+        0,  482,  476,    0,   58,  118,  153,  222,    0,  272,
+      266,  275,    0,  344,  354,    0,    0,  406,    0,    0,
+      402,    0,    0, 1193,  819,  823,  827,  831,  835,  839,
+      843,  847,  851,  855,  859,  863,  865,  869,  871,  873,
+      875,  877,  879,  883,  470
+    } ;
+
+static yyconst flex_int16_t yy_def[856] =
+    {   0,
+      834,    1,  835,  835,  836,  836,  837,  837,  838,  838,
+      839,  839,  840,  840,  841,  841,  842,  842,  843,  843,
+      844,  844,  845,  845,  834,  834,  834,  834,  846,  834,
+      834,  834,  834,  834,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  834,  834,  834,  848,
+      834,  834,  834,  834,  834,  834,  834,  834,  834,  834,
+      834,  834,  834,  834,  834,  834,  834,  834,  834,  834,
+      834,  834,  849,  834,  834,  834,  850,  834,  834,  834,
+
+      851,  834,  834,  834,  852,  834,  834,  834,  853,  834,
+      834,  834,  834,  834,  846,  834,  834,  834,  834,  834,
+      834,  854,  834,  834,  855,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  834,  848,  834,  834,  834,  834,  834,  849,
+      834,  850,  834,  851,  834,  852,  834,  853,  834,  834,
+      834,  834,  834,  834,  834,  834,  834,  834,  854,  834,
+      855,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  834,  834,  834,  834,  834,
+      834,  834,  834,  834,  834,  834,  834,  834,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  834,  834,  834,  834,  834,  834,  834,  834,  834,
+      834,  834,  834,  834,  834,  834,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  834,  834,  834,  834,  834,  834,  834,
+      834,  834,  834,  834,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  834,
+      834,  834,  834,  834,  834,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      834,  834,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,    0,  834,  834,  834,  834,  834,  834,
+      834,  834,  834,  834,  834,  834,  834,  834,  834,  834,
+      834,  834,  834,  834,  834
+    } ;
+
+static yyconst flex_int16_t yy_nxt[1261] =
+    {   0,
+       26,   27,   28,   29,   30,   26,   31,   26,   32,   33,
+       34,   34,   34,   34,   34,   26,   35,   36,   37,   38,
+       39,   40,   41,   42,   43,   44,   45,   46,   47,   48,
+       49,   50,   51,   52,   53,   54,   55,   56,   57,   44,
+       44,   58,   59,   44,   60,   44,   44,   61,   44,   44,
+       62,   44,   44,   63,   44,   44,   44,   44,   44,   64,
+       65,   66,   44,   44,   44,   26,   26,   68,   69,   70,
+       68,   69,   70,   72,   73,   72,   73,   76,   77,   76,
+       77,   80,  230,   80,   84,   84,  231,   74,  203,   74,
+       84,   84,   85,   86,   87,   88,   89,  204,   85,   86,
+
+       87,   88,   89,  111,  112,  158,  113,  111,  112,  169,
+      113,  114,  114,  114,  114,  117,  118,  171,  823,  170,
+      119,  121,  121,  121,  121,  121,  121,  201,  202,  769,
+      159,  120,  206,  123,  770,  124,  124,  124,  124,  124,
+      124,   78,  207,   78,  172,   81,   82,   81,   82,   90,
+       91,   92,   90,   90,   90,   90,   90,   90,   90,   90,
+       90,   90,   90,   90,   90,  125,  123,  138,  124,  124,
+      124,  124,  124,  124,  143,  161,  139,  824,  153,  154,
+      193,  213,  213,  233,  194,  234,  162,  140,  144,  125,
+      213,  213,  235,  163,  145,  825,  195,  155,  133,  236,
+
+      146,  285,  196,  286,  141,  216,  216,  149,  156,  147,
+      142,  336,  134,  337,   90,   90,   90,   91,   92,   90,
+       90,   90,   90,   90,   90,   90,   90,   90,   90,   90,
+       90,   90,  127,  150,  135,  128,  173,  136,  216,  216,
+      281,  151,  217,  217,  282,  129,  137,  178,  179,  152,
+      174,  180,  273,  181,  217,  217,  218,  218,  219,  219,
+      826,  130,  175,  219,  219,  182,  198,  249,  131,  221,
+      221,  274,  132,  221,  221,  199,  250,  183,  176,  223,
+      223,   90,   90,   94,   95,   96,   94,   94,   94,   94,
+       94,   94,   94,   94,   94,   94,   94,   94,   94,  164,
+
+      200,  223,  223,  225,  225,  184,  262,  165,  185,  263,
+      186,  187,  225,  225,  227,  227,  309,  188,  827,  189,
+      828,  190,  227,  227,  310,  166,  229,  229,  229,  229,
+      191,  114,  114,  167,  829,  192,  238,  238,  238,  238,
+      238,  238,  294,  295,  168,  255,  256,  257,   94,   94,
+       94,   95,   96,   94,   94,   94,   94,   94,   94,   94,
+       94,   94,   94,   94,   94,   94,  240,  240,  240,  240,
+      240,  240,  123,  283,  124,  124,  124,  124,  124,  124,
+      289,  300,  301,  290,  313,  316,  213,  213,  284,  216,
+      216,  217,  217,  218,  218,  830,  314,  219,  219,  221,
+
+      221,  223,  223,  340,  317,  225,  225,  227,  227,  229,
+      229,  361,  341,  831,  362,   94,   94,   98,   99,  100,
+       98,   98,   98,   98,   98,   98,   98,   98,   98,   98,
+       98,   98,   98,  343,  238,  238,  238,  238,  238,  238,
+      470,  366,  344,  240,  240,  240,  240,  240,  240,  367,
+      392,  832,  406,  833,  347,  348,  393,  474,  368,  471,
+      407,  433,  434,  435,  436,  437,  438,  442,  388,  408,
+      445,  483,  241,  767,  475,  389,  443,  768,  484,  446,
+      347,  348,   98,   98,   98,   99,  100,   98,   98,   98,
+       98,   98,   98,   98,   98,   98,   98,   98,   98,   98,
+
+      390,  455,  455,  492,  506,  456,  456,  456,  456,  456,
+      456,  493,  456,  456,  456,  456,  456,  456,  822,  562,
+      563,  507,  607,  608,  609,  610,  611,  612,  821,  456,
+      456,  456,  456,  456,  456,  564,  613,  614,  615,  820,
+      565,  348,  616,  617,  618,  819,  818,  817,  816,   98,
+       98,  102,  103,  104,  102,  102,  102,  102,  102,  102,
+      102,  102,  102,  102,  102,  102,  102,  348,  698,  699,
+      700,  704,  815,  814,  705,  813,  701,  812,  811,  706,
+      709,  710,  711,  810,  809,  808,  807,  806,  712,  805,
+      804,  803,  802,  801,  800,  799,  798,  797,  796,  795,
+
+      794,  793,  792,  791,  790,  789,  788,  787,  786,  785,
+      784,  783,  782,  781,  780,  779,  102,  102,  102,  103,
+      104,  102,  102,  102,  102,  102,  102,  102,  102,  102,
+      102,  102,  102,  102,  778,  777,  776,  775,  774,  773,
+      772,  771,  766,  765,  764,  763,  762,  761,  760,  759,
+      758,  757,  756,  755,  754,  753,  752,  751,  750,  749,
+      748,  747,  746,  745,  744,  743,  742,  741,  740,  739,
+      738,  737,  736,  735,  734,  733,  732,  731,  730,  729,
+      728,  727,  726,  102,  102,  106,  107,  108,  106,  106,
+      106,  106,  106,  106,  106,  106,  106,  106,  106,  106,
+
+      106,  725,  724,  723,  722,  721,  720,  719,  718,  717,
+      716,  715,  714,  713,  708,  707,  703,  702,  697,  696,
+      695,  694,  693,  692,  691,  690,  689,  688,  687,  686,
+      685,  684,  683,  682,  681,  680,  679,  678,  677,  676,
+      675,  674,  673,  672,  671,  670,  669,  668,  667,  666,
+      106,  106,  106,  107,  108,  106,  106,  106,  106,  106,
+      106,  106,  106,  106,  106,  106,  106,  106,  665,  664,
+      663,  662,  661,  660,  659,  658,  657,  656,  655,  654,
+      653,  652,  651,  650,  649,  648,  647,  646,  645,  644,
+      643,  642,  641,  640,  639,  638,  637,  636,  635,  634,
+
+      633,  632,  631,  630,  629,  628,  627,  626,  625,  624,
+      623,  622,  621,  620,  619,  606,  605,  106,  106,   67,
+       67,   67,   67,   71,   71,   71,   71,   75,   75,   75,
+       75,   79,   79,   79,   79,   83,   83,   83,   83,   93,
+       93,   93,   93,   97,   97,   97,   97,  101,  101,  101,
+      101,  105,  105,  105,  105,  109,  109,  109,  109,  110,
+      110,  110,  110,  115,  604,  115,  115,  126,  126,  214,
+      603,  214,  214,  220,  220,  222,  222,  224,  224,  226,
+      226,  228,  228,  239,  602,  239,  239,  601,  600,  599,
+      598,  597,  596,  595,  594,  593,  592,  591,  590,  589,
+
+      588,  587,  586,  585,  584,  583,  582,  581,  580,  579,
+      578,  577,  576,  575,  574,  573,  572,  571,  570,  569,
+      568,  567,  566,  561,  560,  559,  558,  557,  556,  555,
+      554,  553,  552,  551,  550,  549,  548,  547,  546,  545,
+      544,  543,  542,  541,  540,  539,  538,  537,  536,  535,
+      534,  533,  532,  531,  530,  529,  528,  527,  526,  525,
+      524,  523,  522,  521,  520,  519,  518,  517,  516,  515,
+      514,  513,  512,  511,  510,  509,  508,  505,  504,  503,
+      502,  501,  500,  499,  498,  497,  496,  495,  494,  491,
+      490,  489,  488,  487,  486,  485,  482,  481,  480,  479,
+
+      478,  477,  476,  473,  472,  469,  468,  467,  466,  465,
+      464,  463,  462,  461,  460,  459,  458,  457,  454,  453,
+      452,  451,  450,  449,  448,  447,  444,  441,  440,  439,
+      432,  431,  430,  429,  428,  427,  426,  425,  424,  423,
+      422,  421,  420,  419,  418,  417,  416,  415,  414,  413,
+      412,  411,  410,  409,  405,  404,  403,  402,  401,  400,
+      399,  398,  397,  396,  395,  394,  391,  387,  386,  385,
+      384,  383,  382,  381,  380,  379,  378,  377,  376,  375,
+      374,  373,  372,  371,  370,  369,  365,  364,  363,  360,
+      359,  358,  357,  356,  355,  354,  353,  352,  351,  350,
+
+      349,  346,  345,  342,  339,  338,  215,  335,  334,  333,
+      332,  331,  330,  329,  328,  327,  326,  325,  324,  323,
+      322,  321,  320,  319,  318,  315,  312,  311,  308,  307,
+      306,  305,  304,  303,  302,  299,  298,  297,  296,  293,
+      292,  291,  288,  287,  280,  279,  278,  277,  276,  275,
+      272,  271,  270,  269,  268,  267,  266,  265,  264,  261,
+      260,  259,  258,  254,  253,  252,  251,  248,  247,  246,
+      245,  244,  243,  242,  237,  232,  116,  215,  212,  211,
+      210,  209,  208,  205,  197,  177,  160,  157,  148,  122,
+      116,  834,   25,  834,  834,  834,  834,  834,  834,  834,
+
+      834,  834,  834,  834,  834,  834,  834,  834,  834,  834,
+      834,  834,  834,  834,  834,  834,  834,  834,  834,  834,
+      834,  834,  834,  834,  834,  834,  834,  834,  834,  834,
+      834,  834,  834,  834,  834,  834,  834,  834,  834,  834,
+      834,  834,  834,  834,  834,  834,  834,  834,  834,  834,
+      834,  834,  834,  834,  834,  834,  834,  834,  834,  834
+    } ;
+
+static yyconst flex_int16_t yy_chk[1261] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    3,    3,    3,
+        4,    4,    4,    5,    5,    6,    6,    7,    7,    8,
+        8,    9,  113,   10,   11,   11,  113,    5,   59,    6,
+       12,   12,   11,   11,   11,   11,   11,   59,   12,   12,
+
+       12,   12,   12,   23,   23,   43,   23,   24,   24,   48,
+       24,   27,   27,   28,   28,   30,   30,   49,  815,   48,
+       30,   31,   31,   31,   31,   31,   31,   58,   58,  741,
+       43,   30,   61,   33,  741,   33,   33,   33,   33,   33,
+       33,    7,   61,    8,   49,    9,    9,   10,   10,   13,
+       13,   13,   13,   13,   13,   13,   13,   13,   13,   13,
+       13,   13,   13,   13,   13,   33,   34,   37,   34,   34,
+       34,   34,   34,   34,   38,   46,   37,  816,   41,   41,
+       54,   68,   68,  118,   54,  118,   46,   37,   38,   33,
+       69,   69,  119,   46,   38,  817,   54,   41,   36,  119,
+
+       38,  167,   54,  167,   37,   72,   72,   40,   41,   38,
+       37,  230,   36,  230,   13,   13,   14,   14,   14,   14,
+       14,   14,   14,   14,   14,   14,   14,   14,   14,   14,
+       14,   14,   35,   40,   36,   35,   50,   36,   73,   73,
+      165,   40,   76,   76,  165,   35,   36,   52,   52,   40,
+       50,   52,  158,   52,   77,   77,   84,   84,   91,   91,
+      818,   35,   50,   92,   92,   52,   57,  135,   35,   95,
+       95,  158,   35,   96,   96,   57,  135,   52,   50,   99,
+       99,   14,   14,   15,   15,   15,   15,   15,   15,   15,
+       15,   15,   15,   15,   15,   15,   15,   15,   15,   47,
+
+       57,  100,  100,  103,  103,   53,  146,   47,   53,  146,
+       53,   53,  104,  104,  107,  107,  189,   53,  820,   53,
+      821,   53,  108,  108,  189,   47,  111,  111,  112,  112,
+       53,  114,  114,   47,  822,   53,  121,  121,  121,  121,
+      121,  121,  175,  175,   47,  141,  141,  141,   15,   15,
+       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
+       16,   16,   16,   16,   16,   16,  123,  123,  123,  123,
+      123,  123,  124,  166,  124,  124,  124,  124,  124,  124,
+      170,  181,  181,  170,  192,  194,  213,  213,  166,  216,
+      216,  217,  217,  218,  218,  824,  192,  219,  219,  221,
+
+      221,  223,  223,  233,  194,  225,  225,  227,  227,  229,
+      229,  256,  233,  825,  256,   16,   16,   17,   17,   17,
+       17,   17,   17,   17,   17,   17,   17,   17,   17,   17,
+       17,   17,   17,  235,  238,  238,  238,  238,  238,  238,
+      362,  260,  235,  240,  240,  240,  240,  240,  240,  260,
+      289,  828,  305,  831,  240,  240,  289,  367,  260,  362,
+      305,  331,  331,  331,  332,  332,  332,  336,  286,  305,
+      338,  380,  855,  740,  367,  286,  336,  740,  380,  338,
+      240,  240,   17,   17,   18,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+
+      286,  347,  347,  389,  407,  347,  347,  347,  347,  347,
+      347,  389,  455,  455,  455,  455,  455,  455,  813,  478,
+      478,  407,  528,  528,  528,  529,  529,  529,  812,  456,
+      456,  456,  456,  456,  456,  478,  530,  530,  530,  810,
+      478,  456,  531,  531,  531,  809,  808,  807,  806,   18,
+       18,   19,   19,   19,   19,   19,   19,   19,   19,   19,
+       19,   19,   19,   19,   19,   19,   19,  456,  660,  660,
+      660,  664,  805,  804,  664,  803,  660,  802,  801,  664,
+      667,  667,  667,  798,  797,  793,  792,  791,  667,  790,
+      789,  788,  784,  783,  781,  779,  778,  776,  775,  774,
+
+      773,  772,  771,  769,  768,  767,  766,  765,  764,  762,
+      760,  758,  757,  756,  755,  754,   19,   19,   20,   20,
+       20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
+       20,   20,   20,   20,  753,  752,  750,  749,  748,  746,
+      743,  742,  738,  737,  735,  733,  732,  731,  727,  726,
+      722,  721,  720,  719,  718,  717,  716,  715,  714,  713,
+      712,  711,  710,  709,  708,  707,  706,  705,  704,  703,
+      702,  701,  700,  699,  698,  695,  693,  692,  691,  690,
+      688,  686,  683,   20,   20,   21,   21,   21,   21,   21,
+       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
+
+       21,  682,  681,  680,  679,  678,  677,  676,  675,  674,
+      673,  670,  669,  668,  666,  665,  663,  661,  658,  656,
+      655,  654,  652,  651,  650,  649,  648,  647,  646,  644,
+      642,  641,  640,  639,  638,  637,  633,  631,  630,  629,
+      628,  627,  626,  625,  622,  606,  604,  603,  602,  601,
+       21,   21,   22,   22,   22,   22,   22,   22,   22,   22,
+       22,   22,   22,   22,   22,   22,   22,   22,  599,  598,
+      596,  595,  594,  593,  590,  589,  588,  587,  586,  584,
+      582,  581,  580,  577,  576,  575,  574,  572,  571,  570,
+      569,  568,  567,  565,  564,  563,  562,  561,  559,  558,
+
+      557,  556,  555,  553,  552,  549,  548,  547,  543,  542,
+      539,  538,  537,  536,  532,  523,  522,   22,   22,  835,
+      835,  835,  835,  836,  836,  836,  836,  837,  837,  837,
+      837,  838,  838,  838,  838,  839,  839,  839,  839,  840,
+      840,  840,  840,  841,  841,  841,  841,  842,  842,  842,
+      842,  843,  843,  843,  843,  844,  844,  844,  844,  845,
+      845,  845,  845,  846,  521,  846,  846,  847,  847,  848,
+      520,  848,  848,  849,  849,  850,  850,  851,  851,  852,
+      852,  853,  853,  854,  519,  854,  854,  518,  517,  516,
+      515,  514,  513,  512,  511,  510,  509,  508,  507,  504,
+
+      503,  501,  500,  499,  498,  497,  496,  495,  494,  493,
+      492,  491,  490,  489,  488,  487,  486,  485,  483,  482,
+      481,  480,  479,  477,  476,  475,  473,  472,  471,  470,
+      469,  466,  465,  464,  462,  461,  460,  459,  458,  457,
+      454,  453,  452,  451,  450,  447,  446,  445,  444,  443,
+      442,  441,  439,  438,  437,  436,  432,  431,  430,  428,
+      427,  425,  422,  421,  420,  419,  418,  417,  416,  415,
+      414,  413,  412,  411,  410,  409,  408,  405,  404,  401,
+      400,  399,  397,  396,  394,  393,  392,  391,  390,  388,
+      387,  386,  385,  384,  383,  382,  379,  377,  376,  372,
+
+      370,  369,  368,  365,  363,  361,  360,  359,  358,  357,
+      356,  355,  354,  353,  352,  351,  350,  349,  346,  345,
+      344,  343,  342,  341,  340,  339,  337,  335,  334,  333,
+      330,  329,  328,  327,  326,  325,  324,  323,  322,  321,
+      320,  319,  318,  317,  316,  315,  314,  313,  312,  311,
+      310,  309,  308,  306,  304,  303,  302,  301,  299,  297,
+      296,  295,  294,  293,  292,  290,  287,  285,  284,  283,
+      282,  279,  277,  276,  275,  273,  272,  271,  268,  267,
+      266,  265,  264,  263,  262,  261,  259,  258,  257,  255,
+      254,  252,  251,  250,  249,  248,  247,  246,  245,  244,
+
+      242,  237,  236,  234,  232,  231,  214,  212,  211,  210,
+      209,  208,  207,  206,  205,  204,  203,  202,  201,  200,
+      199,  198,  197,  196,  195,  193,  191,  190,  188,  187,
+      186,  185,  184,  183,  182,  180,  179,  177,  176,  174,
+      173,  171,  169,  168,  164,  163,  162,  161,  160,  159,
+      157,  156,  155,  154,  152,  151,  150,  149,  147,  145,
+      144,  143,  142,  139,  138,  137,  136,  134,  132,  131,
+      130,  129,  128,  127,  120,  117,  115,   70,   66,   65,
+       64,   63,   62,   60,   56,   51,   45,   42,   39,   32,
+       29,   25,  834,  834,  834,  834,  834,  834,  834,  834,
+
+      834,  834,  834,  834,  834,  834,  834,  834,  834,  834,
+      834,  834,  834,  834,  834,  834,  834,  834,  834,  834,
+      834,  834,  834,  834,  834,  834,  834,  834,  834,  834,
+      834,  834,  834,  834,  834,  834,  834,  834,  834,  834,
+      834,  834,  834,  834,  834,  834,  834,  834,  834,  834,
+      834,  834,  834,  834,  834,  834,  834,  834,  834,  834
+    } ;
+
+/* Table of booleans, true if rule could match eol. */
+static yyconst flex_int32_t yy_rule_can_match_eol[223] =
+    {   0,
+1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 
+    0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 
+    0, 0, 0,     };
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+#line 1 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+#line 2 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+#include "BsParserFX.h"
+
+#define YY_USER_ACTION yylloc->first_column = yycolumn + 1; yylloc->first_line = yylineno + 1; yycolumn += (int)yyleng; yylloc->filename = getCurrentFilename(yyextra);
+#define YY_USER_INIT yylineno = 0; yycolumn = 0;
+#define YY_NO_UNISTD_H 1
+/* Start conditions */
+
+
+
+
+
+
+
+
+
+
+
+#line 1037 "BsLexerFX.c"
+
+#define INITIAL 0
+#define INCLUDE 1
+#define CODEBLOCK_HEADER 2
+#define CODEBLOCK_EQUALS 3
+#define CODEBLOCK 4
+#define CODEBLOCK_END 5
+#define DEFINE_COND 6
+#define UNDEF_COND 7
+#define CONDITIONAL_IF 8
+#define CONDITIONAL_IFN 9
+#define CONDITIONAL_ELIF 10
+#define CONDITIONAL_IGNORE 11
+
+/*windows compatibility case*/
+#include <io.h>
+#define isatty _isatty
+#define fileno _fileno
+    
+#define YY_EXTRA_TYPE struct tagParseState *
+
+/* Holds the entire state of the reentrant scanner. */
+struct yyguts_t
+    {
+
+    /* User-defined. Not touched by flex. */
+    YY_EXTRA_TYPE yyextra_r;
+
+    /* The rest are the same as the globals declared in the non-reentrant scanner. */
+    FILE *yyin_r, *yyout_r;
+    size_t yy_buffer_stack_top; /**< index of top of stack. */
+    size_t yy_buffer_stack_max; /**< capacity of stack. */
+    YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
+    char yy_hold_char;
+    yy_size_t yy_n_chars;
+    yy_size_t yyleng_r;
+    char *yy_c_buf_p;
+    int yy_init;
+    int yy_start;
+    int yy_did_buffer_switch_on_eof;
+    int yy_start_stack_ptr;
+    int yy_start_stack_depth;
+    int *yy_start_stack;
+    yy_state_type yy_last_accepting_state;
+    char* yy_last_accepting_cpos;
+
+    int yylineno_r;
+    int yy_flex_debug_r;
+
+    char *yytext_r;
+    int yy_more_flag;
+    int yy_more_len;
+
+    YYSTYPE * yylval_r;
+
+    YYLTYPE * yylloc_r;
+
+    }; /* end struct yyguts_t */
+
+static int yy_init_globals (yyscan_t yyscanner );
+
+    /* This must go here because YYSTYPE and YYLTYPE are included
+     * from bison output in section 1.*/
+    #    define yylval yyg->yylval_r
+    
+    #    define yylloc yyg->yylloc_r
+    
+int yylex_init (yyscan_t* scanner);
+
+int yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int yylex_destroy (yyscan_t yyscanner );
+
+int yyget_debug (yyscan_t yyscanner );
+
+void yyset_debug (int debug_flag ,yyscan_t yyscanner );
+
+YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner );
+
+void yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *yyget_in (yyscan_t yyscanner );
+
+void yyset_in  (FILE * in_str ,yyscan_t yyscanner );
+
+FILE *yyget_out (yyscan_t yyscanner );
+
+void yyset_out  (FILE * out_str ,yyscan_t yyscanner );
+
+yy_size_t yyget_leng (yyscan_t yyscanner );
+
+char *yyget_text (yyscan_t yyscanner );
+
+int yyget_lineno (yyscan_t yyscanner );
+
+void yyset_lineno (int line_number ,yyscan_t yyscanner );
+
+int yyget_column  (yyscan_t yyscanner );
+
+void yyset_column (int column_no ,yyscan_t yyscanner );
+
+YYSTYPE * yyget_lval (yyscan_t yyscanner );
+
+void yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
+
+       YYLTYPE *yyget_lloc (yyscan_t yyscanner );
+    
+        void yyset_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner );
+    
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap (yyscan_t yyscanner );
+#else
+extern int yywrap (yyscan_t yyscanner );
+#endif
+#endif
+
+    static void yyunput (int c,char *buf_ptr  ,yyscan_t yyscanner);
+    
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (yyscan_t yyscanner );
+#else
+static int input (yyscan_t yyscanner );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+		{ \
+		int c = '*'; \
+		size_t n; \
+		for ( n = 0; n < max_size && \
+			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+			buf[n] = (char) c; \
+		if ( c == '\n' ) \
+			buf[n++] = (char) c; \
+		if ( c == EOF && ferror( yyin ) ) \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+		result = n; \
+		} \
+	else \
+		{ \
+		errno=0; \
+		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+			{ \
+			if( errno != EINTR) \
+				{ \
+				YY_FATAL_ERROR( "input in flex scanner failed" ); \
+				break; \
+				} \
+			errno=0; \
+			clearerr(yyin); \
+			} \
+		}\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int yylex \
+               (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner);
+
+#define YY_DECL int yylex \
+               (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+	YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp, *yy_bp;
+	register int yy_act;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+#line 34 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+
+
+#line 1291 "BsLexerFX.c"
+
+    yylval = yylval_param;
+
+    yylloc = yylloc_param;
+
+	if ( !yyg->yy_init )
+		{
+		yyg->yy_init = 1;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! yyg->yy_start )
+			yyg->yy_start = 1;	/* first start state */
+
+		if ( ! yyin )
+			yyin = stdin;
+
+		if ( ! yyout )
+			yyout = stdout;
+
+		if ( ! YY_CURRENT_BUFFER ) {
+			yyensure_buffer_stack (yyscanner);
+			YY_CURRENT_BUFFER_LVALUE =
+				yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+		}
+
+		yy_load_buffer_state(yyscanner );
+		}
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+		yy_cp = yyg->yy_c_buf_p;
+
+		/* Support of yytext. */
+		*yy_cp = yyg->yy_hold_char;
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = yyg->yy_start;
+yy_match:
+		do
+			{
+			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+			if ( yy_accept[yy_current_state] )
+				{
+				yyg->yy_last_accepting_state = yy_current_state;
+				yyg->yy_last_accepting_cpos = yy_cp;
+				}
+			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+				{
+				yy_current_state = (int) yy_def[yy_current_state];
+				if ( yy_current_state >= 835 )
+					yy_c = yy_meta[(unsigned int) yy_c];
+				}
+			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+			++yy_cp;
+			}
+		while ( yy_current_state != 834 );
+		yy_cp = yyg->yy_last_accepting_cpos;
+		yy_current_state = yyg->yy_last_accepting_state;
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+
+		YY_DO_BEFORE_ACTION;
+
+		if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
+			{
+			yy_size_t yyl;
+			for ( yyl = 0; yyl < yyleng; ++yyl )
+				if ( yytext[yyl] == '\n' )
+					   
+    do{ yylineno++;
+        yycolumn=0;
+    }while(0)
+;
+			}
+
+do_action:	/* This label is used only to access EOF actions. */
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+			case 0: /* must back up */
+			/* undo the effects of YY_DO_BEFORE_ACTION */
+			*yy_cp = yyg->yy_hold_char;
+			yy_cp = yyg->yy_last_accepting_cpos;
+			yy_current_state = yyg->yy_last_accepting_state;
+			goto yy_find_action;
+
+case 1:
+/* rule 1 can match eol */
+YY_RULE_SETUP
+#line 36 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ /* Skip blank */ }
+	YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 37 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = atoi(yytext); return TOKEN_INTEGER; }
+	YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 38 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = (int)strtol(yytext, 0, 0); return TOKEN_INTEGER; }
+	YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 39 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->floatValue = (float)atof(yytext); return TOKEN_FLOAT; }
+	YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 40 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->strValue = mmalloc_strdup(yyextra->memContext, yytext); return TOKEN_STRING; }
+	YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 41 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = 1; return TOKEN_BOOLEAN; }
+	YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 42 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = 0; return TOKEN_BOOLEAN; }
+	YY_BREAK
+/* Value types */
+case 8:
+YY_RULE_SETUP
+#line 46 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_Int; return TOKEN_INTTYPE; } 
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 47 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_Int2; return TOKEN_INT2TYPE; } 
+	YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 48 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_Int3; return TOKEN_INT3TYPE; } 
+	YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 49 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_Int4; return TOKEN_INT4TYPE; }
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 51 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_Float; return TOKEN_FLOATTYPE; } 
+	YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 52 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_Float2; return TOKEN_FLOAT2TYPE; } 
+	YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 53 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_Float3; return TOKEN_FLOAT3TYPE; } 
+	YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 54 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_Float4; return TOKEN_FLOAT4TYPE; }
+	YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 55 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_Color; return TOKEN_COLORTYPE; }
+	YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 57 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_Mat2x2; return TOKEN_MAT2x2TYPE; } 
+	YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 58 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_Mat2x3; return TOKEN_MAT2x3TYPE; } 
+	YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 59 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_Mat2x4; return TOKEN_MAT2x4TYPE; }
+	YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 61 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_Mat3x2; return TOKEN_MAT3x2TYPE; } 
+	YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 62 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_Mat3x3; return TOKEN_MAT3x3TYPE; } 
+	YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 63 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_Mat3x4; return TOKEN_MAT3x4TYPE; }
+	YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 65 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_Mat4x2; return TOKEN_MAT4x2TYPE; } 
+	YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 66 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_Mat4x3; return TOKEN_MAT4x3TYPE; } 
+	YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 67 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_Mat4x4; return TOKEN_MAT4x4TYPE; }
+	YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 69 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_Sampler1D; return TOKEN_SAMPLER1D; } 
+	YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 70 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_Sampler2D; return TOKEN_SAMPLER2D; } 
+	YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 71 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_Sampler3D; return TOKEN_SAMPLER3D; } 
+	YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 72 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_SamplerCUBE; return TOKEN_SAMPLERCUBE; } 
+	YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 73 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_Sampler2DMS; return TOKEN_SAMPLER2DMS; }
+	YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 75 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_Texture1D; return TOKEN_TEXTURE1D; } 
+	YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 76 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_Texture2D; return TOKEN_TEXTURE2D; } 
+	YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 77 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_Texture3D; return TOKEN_TEXTURE3D; } 
+	YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 78 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_TextureCUBE; return TOKEN_TEXTURECUBE; } 
+	YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 79 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_Texture2DMS; return TOKEN_TEXTURE2DMS; }
+	YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 81 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_ByteBuffer; return TOKEN_BYTEBUFFER; } 
+	YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 82 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_StructBuffer; return TOKEN_STRUCTBUFFER; } 
+	YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 84 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_TypedBufferRW; return TOKEN_RWTYPEDBUFFER; } 
+	YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 85 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_ByteBufferRW; return TOKEN_RWBYTEBUFFER; }
+	YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 86 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_StructBufferRW; return TOKEN_RWSTRUCTBUFFER; } 
+	YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 87 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_AppendBuffer; return TOKEN_RWAPPENDBUFFER; } 
+	YY_BREAK
+case 42:
+YY_RULE_SETUP
+#line 88 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = PT_ConsumeBuffer; return TOKEN_RWCONSUMEBUFFER; }
+	YY_BREAK
+case 43:
+YY_RULE_SETUP
+#line 90 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_PARAMSBLOCK; }
+	YY_BREAK
+/* Shader keywords */
+case 44:
+YY_RULE_SETUP
+#line 93 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_SEPARABLE; }
+	YY_BREAK
+case 45:
+YY_RULE_SETUP
+#line 94 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_QUEUE; }
+	YY_BREAK
+case 46:
+YY_RULE_SETUP
+#line 95 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_PRIORITY; }
+	YY_BREAK
+case 47:
+YY_RULE_SETUP
+#line 96 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_TRANSPARENT; }
+	YY_BREAK
+case 48:
+YY_RULE_SETUP
+#line 97 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_TECHNIQUE; }
+	YY_BREAK
+case 49:
+YY_RULE_SETUP
+#line 98 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_PARAMETERS; }
+	YY_BREAK
+case 50:
+YY_RULE_SETUP
+#line 99 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_BLOCKS; }
+	YY_BREAK
+/* Technique keywords */
+case 51:
+YY_RULE_SETUP
+#line 102 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_RENDERER; }
+	YY_BREAK
+case 52:
+YY_RULE_SETUP
+#line 103 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_LANGUAGE; }
+	YY_BREAK
+case 53:
+YY_RULE_SETUP
+#line 104 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_PASS; }
+	YY_BREAK
+/* Pass keywords */
+case 54:
+YY_RULE_SETUP
+#line 107 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_STENCILREF; }
+	YY_BREAK
+/* Rasterizer state keywords */
+case 55:
+YY_RULE_SETUP
+#line 110 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_FILLMODE; }
+	YY_BREAK
+case 56:
+YY_RULE_SETUP
+#line 111 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_CULLMODE; }
+	YY_BREAK
+case 57:
+YY_RULE_SETUP
+#line 112 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_DEPTHBIAS; }
+	YY_BREAK
+case 58:
+YY_RULE_SETUP
+#line 113 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_SDEPTHBIAS; }
+	YY_BREAK
+case 59:
+YY_RULE_SETUP
+#line 114 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_DEPTHCLIP; }
+	YY_BREAK
+case 60:
+YY_RULE_SETUP
+#line 115 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_SCISSOR; }
+	YY_BREAK
+case 61:
+YY_RULE_SETUP
+#line 116 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_MULTISAMPLE; }
+	YY_BREAK
+case 62:
+YY_RULE_SETUP
+#line 117 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_AALINE; }
+	YY_BREAK
+/* Depth-stencil state keywords */
+case 63:
+YY_RULE_SETUP
+#line 120 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_DEPTHREAD; }
+	YY_BREAK
+case 64:
+YY_RULE_SETUP
+#line 121 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_DEPTHWRITE; }
+	YY_BREAK
+case 65:
+YY_RULE_SETUP
+#line 122 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_COMPAREFUNC; }
+	YY_BREAK
+case 66:
+YY_RULE_SETUP
+#line 123 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_STENCIL; }
+	YY_BREAK
+case 67:
+YY_RULE_SETUP
+#line 124 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_STENCILREADMASK; }
+	YY_BREAK
+case 68:
+YY_RULE_SETUP
+#line 125 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_STENCILWRITEMASK; }
+	YY_BREAK
+case 69:
+YY_RULE_SETUP
+#line 126 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_STENCILOPFRONT; }
+	YY_BREAK
+case 70:
+YY_RULE_SETUP
+#line 127 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_STENCILOPBACK; }
+	YY_BREAK
+case 71:
+YY_RULE_SETUP
+#line 128 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_FAIL; }
+	YY_BREAK
+case 72:
+YY_RULE_SETUP
+#line 129 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_ZFAIL; }
+	YY_BREAK
+/* Blend state keywords */
+case 73:
+YY_RULE_SETUP
+#line 132 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_ALPHATOCOVERAGE; }
+	YY_BREAK
+case 74:
+YY_RULE_SETUP
+#line 133 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_INDEPENDANTBLEND; }
+	YY_BREAK
+case 75:
+YY_RULE_SETUP
+#line 134 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_TARGET; }
+	YY_BREAK
+case 76:
+YY_RULE_SETUP
+#line 135 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_INDEX; }
+	YY_BREAK
+case 77:
+YY_RULE_SETUP
+#line 136 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_BLEND; }
+	YY_BREAK
+case 78:
+YY_RULE_SETUP
+#line 137 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_COLOR; }
+	YY_BREAK
+case 79:
+YY_RULE_SETUP
+#line 138 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_ALPHA; }
+	YY_BREAK
+case 80:
+YY_RULE_SETUP
+#line 139 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_WRITEMASK; }
+	YY_BREAK
+case 81:
+YY_RULE_SETUP
+#line 140 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_SOURCE; }
+	YY_BREAK
+case 82:
+YY_RULE_SETUP
+#line 141 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_DEST; }
+	YY_BREAK
+case 83:
+YY_RULE_SETUP
+#line 142 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_OP; }
+	YY_BREAK
+/* Sampler state keywords */
+case 84:
+YY_RULE_SETUP
+#line 145 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_ADDRMODE; }
+	YY_BREAK
+case 85:
+YY_RULE_SETUP
+#line 146 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_MINFILTER; }
+	YY_BREAK
+case 86:
+YY_RULE_SETUP
+#line 147 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_MAGFILTER; }
+	YY_BREAK
+case 87:
+YY_RULE_SETUP
+#line 148 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_MIPFILTER; }
+	YY_BREAK
+case 88:
+YY_RULE_SETUP
+#line 149 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_MAXANISO; }
+	YY_BREAK
+case 89:
+YY_RULE_SETUP
+#line 150 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_MIPBIAS; }
+	YY_BREAK
+case 90:
+YY_RULE_SETUP
+#line 151 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_MIPMIN; }
+	YY_BREAK
+case 91:
+YY_RULE_SETUP
+#line 152 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_MIPMAX; }
+	YY_BREAK
+case 92:
+YY_RULE_SETUP
+#line 153 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_BORDERCOLOR; }
+	YY_BREAK
+case 93:
+YY_RULE_SETUP
+#line 154 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_U; }
+	YY_BREAK
+case 94:
+YY_RULE_SETUP
+#line 155 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_V; }
+	YY_BREAK
+case 95:
+YY_RULE_SETUP
+#line 156 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_W; }
+	YY_BREAK
+/* Qualifiers */
+case 96:
+YY_RULE_SETUP
+#line 159 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_AUTO; }
+	YY_BREAK
+case 97:
+YY_RULE_SETUP
+#line 160 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_ALIAS; }
+	YY_BREAK
+case 98:
+YY_RULE_SETUP
+#line 161 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_SHARED; }
+	YY_BREAK
+case 99:
+YY_RULE_SETUP
+#line 162 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return TOKEN_USAGE; }
+	YY_BREAK
+/* State values */
+case 100:
+YY_RULE_SETUP
+#line 165 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = FMV_Wire; return TOKEN_FILLMODEVALUE; }
+	YY_BREAK
+case 101:
+YY_RULE_SETUP
+#line 166 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = FMV_Solid; return TOKEN_FILLMODEVALUE; }
+	YY_BREAK
+case 102:
+YY_RULE_SETUP
+#line 168 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = CMV_None; return TOKEN_CULLMODEVALUE; }
+	YY_BREAK
+case 103:
+YY_RULE_SETUP
+#line 169 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = CMV_CW; return TOKEN_CULLMODEVALUE; }
+	YY_BREAK
+case 104:
+YY_RULE_SETUP
+#line 170 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = CMV_CCW; return TOKEN_CULLMODEVALUE; }
+	YY_BREAK
+case 105:
+YY_RULE_SETUP
+#line 172 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = CFV_Fail; return TOKEN_COMPFUNCVALUE; }
+	YY_BREAK
+case 106:
+YY_RULE_SETUP
+#line 173 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = CFV_Pass; return TOKEN_COMPFUNCVALUE; }
+	YY_BREAK
+case 107:
+YY_RULE_SETUP
+#line 174 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = CFV_LT; return TOKEN_COMPFUNCVALUE; }
+	YY_BREAK
+case 108:
+YY_RULE_SETUP
+#line 175 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = CFV_LTE; return TOKEN_COMPFUNCVALUE; }
+	YY_BREAK
+case 109:
+YY_RULE_SETUP
+#line 176 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = CFV_EQ; return TOKEN_COMPFUNCVALUE; }
+	YY_BREAK
+case 110:
+YY_RULE_SETUP
+#line 177 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = CFV_NEQ; return TOKEN_COMPFUNCVALUE; }
+	YY_BREAK
+case 111:
+YY_RULE_SETUP
+#line 178 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = CFV_GTE; return TOKEN_COMPFUNCVALUE; }
+	YY_BREAK
+case 112:
+YY_RULE_SETUP
+#line 179 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = CFV_GT; return TOKEN_COMPFUNCVALUE; }
+	YY_BREAK
+case 113:
+YY_RULE_SETUP
+#line 181 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = OV_Keep; return TOKEN_OPVALUE; }
+	YY_BREAK
+case 114:
+YY_RULE_SETUP
+#line 182 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = OV_Zero; return TOKEN_OPVALUE; }
+	YY_BREAK
+case 115:
+YY_RULE_SETUP
+#line 183 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = OV_Replace; return TOKEN_OPVALUE; }
+	YY_BREAK
+case 116:
+YY_RULE_SETUP
+#line 184 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = OV_Incr; return TOKEN_OPVALUE; }
+	YY_BREAK
+case 117:
+YY_RULE_SETUP
+#line 185 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = OV_Decr; return TOKEN_OPVALUE; }
+	YY_BREAK
+case 118:
+YY_RULE_SETUP
+#line 186 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = OV_IncrWrap; return TOKEN_OPVALUE; }
+	YY_BREAK
+case 119:
+YY_RULE_SETUP
+#line 187 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = OV_DecrWrap; return TOKEN_OPVALUE; }
+	YY_BREAK
+case 120:
+YY_RULE_SETUP
+#line 188 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = OV_Invert; return TOKEN_OPVALUE; }
+	YY_BREAK
+case 121:
+YY_RULE_SETUP
+#line 189 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = OV_One; return TOKEN_OPVALUE; }
+	YY_BREAK
+case 122:
+YY_RULE_SETUP
+#line 190 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = OV_DestColor; return TOKEN_OPVALUE; }
+	YY_BREAK
+case 123:
+YY_RULE_SETUP
+#line 191 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = OV_SrcColor; return TOKEN_OPVALUE; }
+	YY_BREAK
+case 124:
+YY_RULE_SETUP
+#line 192 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = OV_InvDestColor; return TOKEN_OPVALUE; }
+	YY_BREAK
+case 125:
+YY_RULE_SETUP
+#line 193 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = OV_InvSrcColor; return TOKEN_OPVALUE; }
+	YY_BREAK
+case 126:
+YY_RULE_SETUP
+#line 194 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = OV_DestAlpha; return TOKEN_OPVALUE; }
+	YY_BREAK
+case 127:
+YY_RULE_SETUP
+#line 195 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = OV_SrcAlpha; return TOKEN_OPVALUE; }
+	YY_BREAK
+case 128:
+YY_RULE_SETUP
+#line 196 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = OV_InvDestAlpha; return TOKEN_OPVALUE; }
+	YY_BREAK
+case 129:
+YY_RULE_SETUP
+#line 197 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = OV_InvSrcAlpha; return TOKEN_OPVALUE; }
+	YY_BREAK
+case 130:
+YY_RULE_SETUP
+#line 199 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = BOV_Add; return TOKEN_BLENDOPVALUE; }
+	YY_BREAK
+case 131:
+YY_RULE_SETUP
+#line 200 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = BOV_Subtract; return TOKEN_BLENDOPVALUE; }
+	YY_BREAK
+case 132:
+YY_RULE_SETUP
+#line 201 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = BOV_RevSubtract; return TOKEN_BLENDOPVALUE; }
+	YY_BREAK
+case 133:
+YY_RULE_SETUP
+#line 202 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = BOV_Min; return TOKEN_BLENDOPVALUE; }
+	YY_BREAK
+case 134:
+YY_RULE_SETUP
+#line 203 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = BOV_Max; return TOKEN_BLENDOPVALUE; }
+	YY_BREAK
+case 135:
+YY_RULE_SETUP
+#line 205 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = 0x0; return TOKEN_COLORMASK; }
+	YY_BREAK
+case 136:
+YY_RULE_SETUP
+#line 206 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = 0x1; return TOKEN_COLORMASK; }
+	YY_BREAK
+case 137:
+YY_RULE_SETUP
+#line 207 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = 0x2; return TOKEN_COLORMASK; }
+	YY_BREAK
+case 138:
+YY_RULE_SETUP
+#line 208 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = 0x4; return TOKEN_COLORMASK; }
+	YY_BREAK
+case 139:
+YY_RULE_SETUP
+#line 209 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = 0x8; return TOKEN_COLORMASK; }
+	YY_BREAK
+case 140:
+YY_RULE_SETUP
+#line 210 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = 0x3; return TOKEN_COLORMASK; }
+	YY_BREAK
+case 141:
+YY_RULE_SETUP
+#line 211 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = 0x5; return TOKEN_COLORMASK; }
+	YY_BREAK
+case 142:
+YY_RULE_SETUP
+#line 212 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = 0x9; return TOKEN_COLORMASK; }
+	YY_BREAK
+case 143:
+YY_RULE_SETUP
+#line 213 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = 0x6; return TOKEN_COLORMASK; }
+	YY_BREAK
+case 144:
+YY_RULE_SETUP
+#line 214 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = 0xA; return TOKEN_COLORMASK; }
+	YY_BREAK
+case 145:
+YY_RULE_SETUP
+#line 215 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = 0xC; return TOKEN_COLORMASK; }
+	YY_BREAK
+case 146:
+YY_RULE_SETUP
+#line 216 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = 0x7; return TOKEN_COLORMASK; }
+	YY_BREAK
+case 147:
+YY_RULE_SETUP
+#line 217 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = 0xB; return TOKEN_COLORMASK; }
+	YY_BREAK
+case 148:
+YY_RULE_SETUP
+#line 218 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = 0xD; return TOKEN_COLORMASK; }
+	YY_BREAK
+case 149:
+YY_RULE_SETUP
+#line 219 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = 0xE; return TOKEN_COLORMASK; }
+	YY_BREAK
+case 150:
+YY_RULE_SETUP
+#line 220 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = 0xF; return TOKEN_COLORMASK; }
+	YY_BREAK
+case 151:
+YY_RULE_SETUP
+#line 222 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = AMV_Wrap; return TOKEN_ADDRMODEVALUE; }
+	YY_BREAK
+case 152:
+YY_RULE_SETUP
+#line 223 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = AMV_Mirror; return TOKEN_ADDRMODEVALUE; }
+	YY_BREAK
+case 153:
+YY_RULE_SETUP
+#line 224 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = AMV_Clamp; return TOKEN_ADDRMODEVALUE; }
+	YY_BREAK
+case 154:
+YY_RULE_SETUP
+#line 225 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = AMV_Border; return TOKEN_ADDRMODEVALUE; }
+	YY_BREAK
+case 155:
+YY_RULE_SETUP
+#line 227 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = FV_None; return TOKEN_FILTERVALUE; }
+	YY_BREAK
+case 156:
+YY_RULE_SETUP
+#line 228 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = FV_Point; return TOKEN_FILTERVALUE; }
+	YY_BREAK
+case 157:
+YY_RULE_SETUP
+#line 229 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = FV_Linear; return TOKEN_FILTERVALUE; }
+	YY_BREAK
+case 158:
+YY_RULE_SETUP
+#line 230 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = FV_Anisotropic; return TOKEN_FILTERVALUE; }
+	YY_BREAK
+case 159:
+YY_RULE_SETUP
+#line 231 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = FV_PointCmp; return TOKEN_FILTERVALUE; }
+	YY_BREAK
+case 160:
+YY_RULE_SETUP
+#line 232 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = FV_LinearCmp; return TOKEN_FILTERVALUE; }
+	YY_BREAK
+case 161:
+YY_RULE_SETUP
+#line 233 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = FV_AnisotropicCmp; return TOKEN_FILTERVALUE; }
+	YY_BREAK
+case 162:
+YY_RULE_SETUP
+#line 235 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = BUV_Static; return TOKEN_BUFFERUSAGE; }
+	YY_BREAK
+case 163:
+YY_RULE_SETUP
+#line 236 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = BUV_Dynamic; return TOKEN_BUFFERUSAGE; }
+	YY_BREAK
+/* Preprocessor */
+case 164:
+YY_RULE_SETUP
+#line 239 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ BEGIN(INCLUDE); }
+	YY_BREAK
+case 165:
+/* rule 165 can match eol */
+YY_RULE_SETUP
+#line 241 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ /* Skip blank */ }
+	YY_BREAK
+case 166:
+YY_RULE_SETUP
+#line 242 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{
+	int size = 0;
+	char* includeBuffer = includePush(yyextra, yytext, yylineno, yycolumn, &size);
+	if(!includeBuffer)
+		yyterminate();
+
+	YY_BUFFER_STATE currentBuffer = YY_CURRENT_BUFFER;
+	YY_BUFFER_STATE newBuffer = yy_scan_buffer(includeBuffer,size,yyscanner);
+
+	yy_switch_to_buffer(currentBuffer,yyscanner);
+	yypush_buffer_state(newBuffer,yyscanner);
+
+	yylineno = 0; 
+	yycolumn = 0;
+
+	BEGIN(INITIAL);
+	}
+	YY_BREAK
+case 167:
+YY_RULE_SETUP
+#line 259 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return yytext[0]; }
+	YY_BREAK
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(INCLUDE):
+case YY_STATE_EOF(CODEBLOCK_HEADER):
+case YY_STATE_EOF(CODEBLOCK_EQUALS):
+case YY_STATE_EOF(CODEBLOCK):
+case YY_STATE_EOF(CODEBLOCK_END):
+case YY_STATE_EOF(DEFINE_COND):
+case YY_STATE_EOF(UNDEF_COND):
+case YY_STATE_EOF(CONDITIONAL_IF):
+case YY_STATE_EOF(CONDITIONAL_IFN):
+case YY_STATE_EOF(CONDITIONAL_ELIF):
+case YY_STATE_EOF(CONDITIONAL_IGNORE):
+#line 261 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{
+	if(!yyextra->includeStack)
+		yyterminate();
+
+	yypop_buffer_state(yyscanner);
+	includePop(yyextra);
+}
+	YY_BREAK
+case 168:
+YY_RULE_SETUP
+#line 269 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ BEGIN(DEFINE_COND); }
+	YY_BREAK
+case 169:
+/* rule 169 can match eol */
+YY_RULE_SETUP
+#line 270 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ /* Skip blank */ }
+	YY_BREAK
+case 170:
+YY_RULE_SETUP
+#line 271 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ addDefine(yyextra, yytext); BEGIN(INITIAL); }
+	YY_BREAK
+case 171:
+YY_RULE_SETUP
+#line 272 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return yytext[0]; }
+	YY_BREAK
+case 172:
+YY_RULE_SETUP
+#line 274 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ BEGIN(UNDEF_COND); }
+	YY_BREAK
+case 173:
+/* rule 173 can match eol */
+YY_RULE_SETUP
+#line 275 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ /* Skip blank */ }
+	YY_BREAK
+case 174:
+YY_RULE_SETUP
+#line 276 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ removeDefine(yyextra, yytext); BEGIN(INITIAL); }
+	YY_BREAK
+case 175:
+YY_RULE_SETUP
+#line 277 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return yytext[0]; }
+	YY_BREAK
+case 176:
+YY_RULE_SETUP
+#line 279 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ BEGIN(CONDITIONAL_IF); }
+	YY_BREAK
+case 177:
+/* rule 177 can match eol */
+YY_RULE_SETUP
+#line 280 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ /* Skip blank */ }
+	YY_BREAK
+case 178:
+YY_RULE_SETUP
+#line 281 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ 
+	int isEnabled = pushConditional(yyextra, hasDefine(yyextra, yytext));
+	if(!isEnabled)
+		BEGIN(CONDITIONAL_IGNORE);
+	else
+		BEGIN(INITIAL);
+}
+	YY_BREAK
+case 179:
+YY_RULE_SETUP
+#line 288 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return yytext[0]; }
+	YY_BREAK
+case 180:
+YY_RULE_SETUP
+#line 290 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ BEGIN(CONDITIONAL_IFN); }
+	YY_BREAK
+case 181:
+/* rule 181 can match eol */
+YY_RULE_SETUP
+#line 291 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ /* Skip blank */ }
+	YY_BREAK
+case 182:
+YY_RULE_SETUP
+#line 292 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ 
+	int isEnabled = pushConditional(yyextra, !hasDefine(yyextra, yytext));
+	if(!isEnabled)
+		BEGIN(CONDITIONAL_IGNORE);
+	else
+		BEGIN(INITIAL);
+}
+	YY_BREAK
+case 183:
+YY_RULE_SETUP
+#line 299 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return yytext[0]; }
+	YY_BREAK
+case 184:
+YY_RULE_SETUP
+#line 301 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ BEGIN(CONDITIONAL_IGNORE); }
+	YY_BREAK
+case 185:
+YY_RULE_SETUP
+#line 302 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ BEGIN(CONDITIONAL_IGNORE); }
+	YY_BREAK
+case 186:
+YY_RULE_SETUP
+#line 304 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ popConditional(yyextra); }
+	YY_BREAK
+case 187:
+/* rule 187 can match eol */
+YY_RULE_SETUP
+#line 306 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ /* Skip */ }
+	YY_BREAK
+case 188:
+YY_RULE_SETUP
+#line 307 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ pushConditional(yyextra, 0); }
+	YY_BREAK
+case 189:
+YY_RULE_SETUP
+#line 308 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ pushConditional(yyextra, 0); }
+	YY_BREAK
+case 190:
+YY_RULE_SETUP
+#line 309 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ 
+	if(switchConditional(yyextra))
+		BEGIN(INITIAL);
+}
+	YY_BREAK
+case 191:
+YY_RULE_SETUP
+#line 313 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ BEGIN(CONDITIONAL_ELIF); }
+	YY_BREAK
+case 192:
+YY_RULE_SETUP
+#line 314 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ 
+	if(popConditional(yyextra))
+		BEGIN(INITIAL);
+}
+	YY_BREAK
+case 193:
+YY_RULE_SETUP
+#line 318 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ /* Skip */ }
+	YY_BREAK
+case 194:
+/* rule 194 can match eol */
+YY_RULE_SETUP
+#line 320 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ /* Skip blank */ }
+	YY_BREAK
+case 195:
+YY_RULE_SETUP
+#line 321 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ 
+	int isEnabled = setConditional(yyextra, hasDefine(yyextra, yytext));
+	if(!isEnabled)
+		BEGIN(CONDITIONAL_IGNORE);
+	else
+		BEGIN(INITIAL);
+}
+	YY_BREAK
+case 196:
+YY_RULE_SETUP
+#line 328 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return yytext[0]; }
+	YY_BREAK
+/* Code blocks */
+case 197:
+YY_RULE_SETUP
+#line 331 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ BEGIN(CODEBLOCK_HEADER); return TOKEN_VERTEX; }
+	YY_BREAK
+case 198:
+YY_RULE_SETUP
+#line 332 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ BEGIN(CODEBLOCK_HEADER); return TOKEN_FRAGMENT; }
+	YY_BREAK
+case 199:
+YY_RULE_SETUP
+#line 333 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ BEGIN(CODEBLOCK_HEADER); return TOKEN_GEOMETRY; }
+	YY_BREAK
+case 200:
+YY_RULE_SETUP
+#line 334 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ BEGIN(CODEBLOCK_HEADER); return TOKEN_HULL; }
+	YY_BREAK
+case 201:
+YY_RULE_SETUP
+#line 335 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ BEGIN(CODEBLOCK_HEADER); return TOKEN_DOMAIN; }
+	YY_BREAK
+case 202:
+YY_RULE_SETUP
+#line 336 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ BEGIN(CODEBLOCK_HEADER); return TOKEN_COMPUTE; }
+	YY_BREAK
+case 203:
+YY_RULE_SETUP
+#line 337 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ BEGIN(CODEBLOCK_HEADER); return TOKEN_COMMON; }
+	YY_BREAK
+/* Track when the code block begins, insert all code block characters into our own buffer, record a sequential index */
+/* of all code blocks in the text, and track bracket open/closed state so we know when we're done with the code block. */
+/* And finally output a sequential code block index to the parser (it shouldn't be aware of anything else in the block). */
+case 204:
+YY_RULE_SETUP
+#line 342 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ BEGIN(CODEBLOCK_EQUALS); return yytext[0]; }
+	YY_BREAK
+case 205:
+/* rule 205 can match eol */
+YY_RULE_SETUP
+#line 343 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ /* Skip blank */ }
+	YY_BREAK
+case 206:
+YY_RULE_SETUP
+#line 344 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return yytext[0]; }
+	YY_BREAK
+case 207:
+YY_RULE_SETUP
+#line 346 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ BEGIN(CODEBLOCK); beginCodeBlock(yyextra); yyextra->numOpenBrackets = 1; return yytext[0]; }
+	YY_BREAK
+case 208:
+/* rule 208 can match eol */
+YY_RULE_SETUP
+#line 347 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ /* Skip blank */ }
+	YY_BREAK
+case 209:
+YY_RULE_SETUP
+#line 348 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return yytext[0]; }
+	YY_BREAK
+case 210:
+YY_RULE_SETUP
+#line 350 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yyextra->numOpenBrackets++; appendCodeBlock(yyextra, yytext, 1); }
+	YY_BREAK
+case 211:
+YY_RULE_SETUP
+#line 351 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ 
+	yyextra->numOpenBrackets--; 
+
+	if(yyextra->numOpenBrackets == 0)
+	{
+		BEGIN(CODEBLOCK_END);
+		unput('0');
+	}
+	else
+		appendCodeBlock(yyextra, yytext, 1);
+}
+	YY_BREAK
+case 212:
+/* rule 212 can match eol */
+YY_RULE_SETUP
+#line 362 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ appendCodeBlock(yyextra, yytext, 1); }
+	YY_BREAK
+/* Logic for manually inserting "Index = codeBlockIndex;". We insert arbitrary numbers which allows us to sequentially */
+/* output all the tokens we need. We use only single-character values so we don't override anything in the text buffer */
+/* (since the starting value was also a single character "{"). */
+case 213:
+YY_RULE_SETUP
+#line 367 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ unput('1'); return TOKEN_INDEX; }
+	YY_BREAK
+case 214:
+YY_RULE_SETUP
+#line 368 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ unput('2'); return '='; }
+	YY_BREAK
+case 215:
+YY_RULE_SETUP
+#line 369 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->intValue = getCodeBlockIndex(yyextra); unput('3'); return TOKEN_INTEGER; }
+	YY_BREAK
+case 216:
+YY_RULE_SETUP
+#line 370 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ unput('4'); return ';'; }
+	YY_BREAK
+case 217:
+YY_RULE_SETUP
+#line 371 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ BEGIN(INITIAL); return '}'; }
+	YY_BREAK
+case 218:
+/* rule 218 can match eol */
+YY_RULE_SETUP
+#line 372 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ /* Never reached */ }
+	YY_BREAK
+/* Catch all rules */
+case 219:
+YY_RULE_SETUP
+#line 375 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ }
+	YY_BREAK
+case 220:
+YY_RULE_SETUP
+#line 376 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ yylval->strValue = mmalloc_strdup(yyextra->memContext, yytext); return TOKEN_IDENTIFIER; }
+	YY_BREAK
+case 221:
+YY_RULE_SETUP
+#line 377 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+{ return yytext[0]; }
+	YY_BREAK
+case 222:
+YY_RULE_SETUP
+#line 379 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+YY_FATAL_ERROR( "flex scanner jammed" );
+	YY_BREAK
+#line 2598 "BsLexerFX.c"
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = yyg->yy_hold_char;
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed yyin at a new source and called
+			 * yylex().  If so, then we have to assure
+			 * consistency between YY_CURRENT_BUFFER and our
+			 * globals.  Here is the right place to do so, because
+			 * this is the first action (other than possibly a
+			 * back-up) that will match for the new input source.
+			 */
+			yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_c_buf_p will
+		 * already have been incremented past the NUL character
+		 * (since all states make transitions on EOB to the
+		 * end-of-buffer state).  Contrast this with the test
+		 * in input().
+		 */
+		if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state( yyscanner );
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_get_previous_state() go ahead and do it
+			 * for us because it doesn't know how to deal
+			 * with the possibility of jamming (and we don't
+			 * want to build jamming into it because then it
+			 * will run more slowly).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
+
+			yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++yyg->yy_c_buf_p;
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = yyg->yy_last_accepting_cpos;
+				yy_current_state = yyg->yy_last_accepting_state;
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer( yyscanner ) )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				yyg->yy_did_buffer_switch_on_eof = 0;
+
+				if ( yywrap(yyscanner ) )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * yytext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! yyg->yy_did_buffer_switch_on_eof )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				yyg->yy_c_buf_p =
+					yyg->yytext_ptr + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state( yyscanner );
+
+				yy_cp = yyg->yy_c_buf_p;
+				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				yyg->yy_c_buf_p =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
+
+				yy_current_state = yy_get_previous_state( yyscanner );
+
+				yy_cp = yyg->yy_c_buf_p;
+				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+} /* end of yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *	EOB_ACT_LAST_MATCH -
+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *	EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+	register char *source = yyg->yytext_ptr;
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
+			{
+			/* We matched a single character, the EOB, so
+			 * treat this as a final EOF.
+			 */
+			return EOB_ACT_END_OF_FILE;
+			}
+
+		else
+			{
+			/* We matched some text prior to the EOB, first
+			 * process it.
+			 */
+			return EOB_ACT_LAST_MATCH;
+			}
+		}
+
+	/* Try to read more data. */
+
+	/* First move last chars to start of buffer. */
+	number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
+
+	else
+		{
+			yy_size_t num_to_read =
+			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+		while ( num_to_read <= 0 )
+			{ /* Not enough room in the buffer - grow it. */
+
+			/* just a shorter name for the current buffer */
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
+
+			int yy_c_buf_p_offset =
+				(int) (yyg->yy_c_buf_p - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				yy_size_t new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+						number_to_move - 1;
+
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+			yyg->yy_n_chars, num_to_read );
+
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+		}
+
+	if ( yyg->yy_n_chars == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			yyrestart(yyin  ,yyscanner);
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+		/* Extend the array by 50%, plus the number we really need. */
+		yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+	}
+
+	yyg->yy_n_chars += number_to_move;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+	yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+	return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	yy_current_state = yyg->yy_start;
+
+	for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
+		{
+		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+		if ( yy_accept[yy_current_state] )
+			{
+			yyg->yy_last_accepting_state = yy_current_state;
+			yyg->yy_last_accepting_cpos = yy_cp;
+			}
+		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+			{
+			yy_current_state = (int) yy_def[yy_current_state];
+			if ( yy_current_state >= 835 )
+				yy_c = yy_meta[(unsigned int) yy_c];
+			}
+		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+		}
+
+	return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state , yyscan_t yyscanner)
+{
+	register int yy_is_jam;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
+	register char *yy_cp = yyg->yy_c_buf_p;
+
+	register YY_CHAR yy_c = 1;
+	if ( yy_accept[yy_current_state] )
+		{
+		yyg->yy_last_accepting_state = yy_current_state;
+		yyg->yy_last_accepting_cpos = yy_cp;
+		}
+	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+		{
+		yy_current_state = (int) yy_def[yy_current_state];
+		if ( yy_current_state >= 835 )
+			yy_c = yy_meta[(unsigned int) yy_c];
+		}
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+	yy_is_jam = (yy_current_state == 834);
+
+	(void)yyg;
+	return yy_is_jam ? 0 : yy_current_state;
+}
+
+    static void yyunput (int c, register char * yy_bp , yyscan_t yyscanner)
+{
+	register char *yy_cp;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+    yy_cp = yyg->yy_c_buf_p;
+
+	/* undo effects of setting up yytext */
+	*yy_cp = yyg->yy_hold_char;
+
+	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+		{ /* need to shift things up to make room */
+		/* +2 for EOB chars. */
+		register yy_size_t number_to_move = yyg->yy_n_chars + 2;
+		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+		register char *source =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			*--dest = *--source;
+
+		yy_cp += (int) (dest - source);
+		yy_bp += (int) (dest - source);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+			yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+			YY_FATAL_ERROR( "flex scanner push-back overflow" );
+		}
+
+	*--yy_cp = (char) c;
+
+    if ( c == '\n' ){
+        --yylineno;
+    }
+
+	yyg->yytext_ptr = yy_bp;
+	yyg->yy_hold_char = *yy_cp;
+	yyg->yy_c_buf_p = yy_cp;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (yyscan_t yyscanner)
+#else
+    static int input  (yyscan_t yyscanner)
+#endif
+
+{
+	int c;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	*yyg->yy_c_buf_p = yyg->yy_hold_char;
+
+	if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_c_buf_p now points to the character we want to return.
+		 * If this occurs *before* the EOB characters, then it's a
+		 * valid NUL; if not, then we've hit the end of the buffer.
+		 */
+		if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+			/* This was really a NUL. */
+			*yyg->yy_c_buf_p = '\0';
+
+		else
+			{ /* need more input */
+			yy_size_t offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+			++yyg->yy_c_buf_p;
+
+			switch ( yy_get_next_buffer( yyscanner ) )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_g_n_b()
+					 * sees that we've accumulated a
+					 * token and flags that we need to
+					 * try matching the token before
+					 * proceeding.  But for input(),
+					 * there's no matching to consider.
+					 * So convert the EOB_ACT_LAST_MATCH
+					 * to EOB_ACT_END_OF_FILE.
+					 */
+
+					/* Reset buffer status. */
+					yyrestart(yyin ,yyscanner);
+
+					/*FALLTHROUGH*/
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( yywrap(yyscanner ) )
+						return EOF;
+
+					if ( ! yyg->yy_did_buffer_switch_on_eof )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput(yyscanner);
+#else
+					return input(yyscanner);
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) yyg->yy_c_buf_p;	/* cast for 8-bit char's */
+	*yyg->yy_c_buf_p = '\0';	/* preserve yytext */
+	yyg->yy_hold_char = *++yyg->yy_c_buf_p;
+
+	if ( c == '\n' )
+		   
+    do{ yylineno++;
+        yycolumn=0;
+    }while(0)
+;
+
+	return c;
+}
+#endif	/* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * @param yyscanner The scanner object.
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+    void yyrestart  (FILE * input_file , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	if ( ! YY_CURRENT_BUFFER ){
+        yyensure_buffer_stack (yyscanner);
+		YY_CURRENT_BUFFER_LVALUE =
+            yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+	}
+
+	yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
+	yy_load_buffer_state(yyscanner );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * @param yyscanner The scanner object.
+ */
+    void yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	/* TODO. We should be able to replace this entire function body
+	 * with
+	 *		yypop_buffer_state();
+	 *		yypush_buffer_state(new_buffer);
+     */
+	yyensure_buffer_stack (yyscanner);
+	if ( YY_CURRENT_BUFFER == new_buffer )
+		return;
+
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*yyg->yy_c_buf_p = yyg->yy_hold_char;
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+		}
+
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+	yy_load_buffer_state(yyscanner );
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (yywrap()) processing, but the only time this flag
+	 * is looked at is after yywrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+static void yy_load_buffer_state  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+	yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+	yyg->yy_hold_char = *yyg->yy_c_buf_p;
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * @param yyscanner The scanner object.
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE yy_create_buffer  (FILE * file, int  size , yyscan_t yyscanner)
+{
+	YY_BUFFER_STATE b;
+    
+	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ,yyscanner );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	yy_init_buffer(b,file ,yyscanner);
+
+	return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with yy_create_buffer()
+ * @param yyscanner The scanner object.
+ */
+    void yy_delete_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	if ( ! b )
+		return;
+
+	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		yyfree((void *) b->yy_ch_buf ,yyscanner );
+
+	yyfree((void *) b ,yyscanner );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a yyrestart() or at EOF.
+ */
+    static void yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file , yyscan_t yyscanner)
+
+{
+	int oerrno = errno;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	yy_flush_buffer(b ,yyscanner);
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then yy_init_buffer was _probably_
+     * called from yyrestart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+        b->yy_is_interactive = 0;
+    
+	errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * @param yyscanner The scanner object.
+ */
+    void yy_flush_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if ( ! b )
+		return;
+
+	b->yy_n_chars = 0;
+
+	/* We always need two end-of-buffer characters.  The first causes
+	 * a transition to the end-of-buffer state.  The second causes
+	 * a jam in that state.
+	 */
+	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == YY_CURRENT_BUFFER )
+		yy_load_buffer_state(yyscanner );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ *  the current state. This function will allocate the stack
+ *  if necessary.
+ *  @param new_buffer The new state.
+ *  @param yyscanner The scanner object.
+ */
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if (new_buffer == NULL)
+		return;
+
+	yyensure_buffer_stack(yyscanner);
+
+	/* This block is copied from yy_switch_to_buffer. */
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*yyg->yy_c_buf_p = yyg->yy_hold_char;
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+		}
+
+	/* Only push if top exists. Otherwise, replace top. */
+	if (YY_CURRENT_BUFFER)
+		yyg->yy_buffer_stack_top++;
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+	/* copied from yy_switch_to_buffer. */
+	yy_load_buffer_state(yyscanner );
+	yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  @param yyscanner The scanner object.
+ */
+void yypop_buffer_state (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if (!YY_CURRENT_BUFFER)
+		return;
+
+	yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
+	YY_CURRENT_BUFFER_LVALUE = NULL;
+	if (yyg->yy_buffer_stack_top > 0)
+		--yyg->yy_buffer_stack_top;
+
+	if (YY_CURRENT_BUFFER) {
+		yy_load_buffer_state(yyscanner );
+		yyg->yy_did_buffer_switch_on_eof = 1;
+	}
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+static void yyensure_buffer_stack (yyscan_t yyscanner)
+{
+	yy_size_t num_to_alloc;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	if (!yyg->yy_buffer_stack) {
+
+		/* First allocation is just for 2 elements, since we don't know if this
+		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
+		 * immediate realloc on the next call.
+         */
+		num_to_alloc = 1;
+		yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc
+								(num_to_alloc * sizeof(struct yy_buffer_state*)
+								, yyscanner);
+		if ( ! yyg->yy_buffer_stack )
+			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+								  
+		memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+				
+		yyg->yy_buffer_stack_max = num_to_alloc;
+		yyg->yy_buffer_stack_top = 0;
+		return;
+	}
+
+	if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
+
+		/* Increase the buffer to prepare for a possible push. */
+		int grow_size = 8 /* arbitrary grow size */;
+
+		num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
+		yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc
+								(yyg->yy_buffer_stack,
+								num_to_alloc * sizeof(struct yy_buffer_state*)
+								, yyscanner);
+		if ( ! yyg->yy_buffer_stack )
+			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+		/* zero only the new slots.*/
+		memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
+		yyg->yy_buffer_stack_max = num_to_alloc;
+	}
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object. 
+ */
+YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size , yyscan_t yyscanner)
+{
+	YY_BUFFER_STATE b;
+    
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return 0;
+
+	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = 0;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	yy_switch_to_buffer(b ,yyscanner );
+
+	return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to yylex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ *       yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
+{
+    
+	return yy_scan_bytes(yystr,strlen(yystr) ,yyscanner);
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_bytes  (yyconst char * yybytes, yy_size_t  _yybytes_len , yyscan_t yyscanner)
+{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	yy_size_t i;
+    
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = _yybytes_len + 2;
+	buf = (char *) yyalloc(n ,yyscanner );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+	for ( i = 0; i < _yybytes_len; ++i )
+		buf[i] = yybytes[i];
+
+	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = yy_scan_buffer(buf,n ,yyscanner);
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
+{
+    	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		yytext[yyleng] = yyg->yy_hold_char; \
+		yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
+		yyg->yy_hold_char = *yyg->yy_c_buf_p; \
+		*yyg->yy_c_buf_p = '\0'; \
+		yyleng = yyless_macro_arg; \
+		} \
+	while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/** Get the user-defined data for this scanner.
+ * @param yyscanner The scanner object.
+ */
+YY_EXTRA_TYPE yyget_extra  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyextra;
+}
+
+/** Get the current line number.
+ * @param yyscanner The scanner object.
+ */
+int yyget_lineno  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    
+        if (! YY_CURRENT_BUFFER)
+            return 0;
+    
+    return yylineno;
+}
+
+/** Get the current column number.
+ * @param yyscanner The scanner object.
+ */
+int yyget_column  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    
+        if (! YY_CURRENT_BUFFER)
+            return 0;
+    
+    return yycolumn;
+}
+
+/** Get the input stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *yyget_in  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyin;
+}
+
+/** Get the output stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *yyget_out  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyout;
+}
+
+/** Get the length of the current token.
+ * @param yyscanner The scanner object.
+ */
+yy_size_t yyget_leng  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyleng;
+}
+
+/** Get the current token.
+ * @param yyscanner The scanner object.
+ */
+
+char *yyget_text  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yytext;
+}
+
+/** Set the user-defined data. This data is never touched by the scanner.
+ * @param user_defined The data to be associated with this scanner.
+ * @param yyscanner The scanner object.
+ */
+void yyset_extra (YY_EXTRA_TYPE  user_defined , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyextra = user_defined ;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void yyset_lineno (int  line_number , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+        /* lineno is only valid if an input buffer exists. */
+        if (! YY_CURRENT_BUFFER )
+           YY_FATAL_ERROR( "yyset_lineno called with no buffer" );
+    
+    yylineno = line_number;
+}
+
+/** Set the current column.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void yyset_column (int  column_no , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+        /* column is only valid if an input buffer exists. */
+        if (! YY_CURRENT_BUFFER )
+           YY_FATAL_ERROR( "yyset_column called with no buffer" );
+    
+    yycolumn = column_no;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * @param yyscanner The scanner object.
+ * @see yy_switch_to_buffer
+ */
+void yyset_in (FILE *  in_str , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyin = in_str ;
+}
+
+void yyset_out (FILE *  out_str , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyout = out_str ;
+}
+
+int yyget_debug  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yy_flex_debug;
+}
+
+void yyset_debug (int  bdebug , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yy_flex_debug = bdebug ;
+}
+
+/* Accessor methods for yylval and yylloc */
+
+YYSTYPE * yyget_lval  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yylval;
+}
+
+void yyset_lval (YYSTYPE *  yylval_param , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yylval = yylval_param;
+}
+
+YYLTYPE *yyget_lloc  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yylloc;
+}
+    
+void yyset_lloc (YYLTYPE *  yylloc_param , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yylloc = yylloc_param;
+}
+    
+/* User-visible API */
+
+/* yylex_init is special because it creates the scanner itself, so it is
+ * the ONLY reentrant function that doesn't take the scanner as the last argument.
+ * That's why we explicitly handle the declaration, instead of using our macros.
+ */
+
+int yylex_init(yyscan_t* ptr_yy_globals)
+
+{
+    if (ptr_yy_globals == NULL){
+        errno = EINVAL;
+        return 1;
+    }
+
+    *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL );
+
+    if (*ptr_yy_globals == NULL){
+        errno = ENOMEM;
+        return 1;
+    }
+
+    /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
+    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+    return yy_init_globals ( *ptr_yy_globals );
+}
+
+/* yylex_init_extra has the same functionality as yylex_init, but follows the
+ * convention of taking the scanner as the last argument. Note however, that
+ * this is a *pointer* to a scanner, as it will be allocated by this call (and
+ * is the reason, too, why this function also must handle its own declaration).
+ * The user defined value in the first argument will be available to yyalloc in
+ * the yyextra field.
+ */
+
+int yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
+
+{
+    struct yyguts_t dummy_yyguts;
+
+    yyset_extra (yy_user_defined, &dummy_yyguts);
+
+    if (ptr_yy_globals == NULL){
+        errno = EINVAL;
+        return 1;
+    }
+	
+    *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
+	
+    if (*ptr_yy_globals == NULL){
+        errno = ENOMEM;
+        return 1;
+    }
+    
+    /* By setting to 0xAA, we expose bugs in
+    yy_init_globals. Leave at 0x00 for releases. */
+    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+    
+    yyset_extra (yy_user_defined, *ptr_yy_globals);
+    
+    return yy_init_globals ( *ptr_yy_globals );
+}
+
+static int yy_init_globals (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from yylex_destroy(), so don't allocate here.
+     */
+
+    yyg->yy_buffer_stack = 0;
+    yyg->yy_buffer_stack_top = 0;
+    yyg->yy_buffer_stack_max = 0;
+    yyg->yy_c_buf_p = (char *) 0;
+    yyg->yy_init = 0;
+    yyg->yy_start = 0;
+
+    yyg->yy_start_stack_ptr = 0;
+    yyg->yy_start_stack_depth = 0;
+    yyg->yy_start_stack =  NULL;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    yyin = stdin;
+    yyout = stdout;
+#else
+    yyin = (FILE *) 0;
+    yyout = (FILE *) 0;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * yylex_init()
+     */
+    return 0;
+}
+
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+    /* Pop the buffer stack, destroying each element. */
+	while(YY_CURRENT_BUFFER){
+		yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
+		YY_CURRENT_BUFFER_LVALUE = NULL;
+		yypop_buffer_state(yyscanner);
+	}
+
+	/* Destroy the stack itself. */
+	yyfree(yyg->yy_buffer_stack ,yyscanner);
+	yyg->yy_buffer_stack = NULL;
+
+    /* Destroy the start condition stack. */
+        yyfree(yyg->yy_start_stack ,yyscanner );
+        yyg->yy_start_stack = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * yylex() is called, initialization will occur. */
+    yy_init_globals( yyscanner);
+
+    /* Destroy the main struct (reentrant only). */
+    yyfree ( yyscanner , yyscanner );
+    yyscanner = NULL;
+    return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
+{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
+{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+}
+#endif
+
+void *yyalloc (yy_size_t  size , yyscan_t yyscanner)
+{
+	return (void *) malloc( size );
+}
+
+void *yyrealloc  (void * ptr, yy_size_t  size , yyscan_t yyscanner)
+{
+	/* The cast to (char *) in the following accommodates both
+	 * implementations that use char* generic pointers, and those
+	 * that use void* generic pointers.  It works with the latter
+	 * because both ANSI C and C++ allow castless assignment from
+	 * any pointer type to void*, and deal with argument conversions
+	 * as though doing an assignment.
+	 */
+	return (void *) realloc( (char *) ptr, size );
+}
+
+void yyfree (void * ptr , yyscan_t yyscanner)
+{
+	free( (char *) ptr );	/* see yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 378 "..\\..\\Source\\BansheeSL\\BsLexerFX.l"
+
+

+ 4709 - 4709
Source/BansheeSL/Source/BsParserFX.c

@@ -1,4710 +1,4710 @@
-/* A Bison parser, made by GNU Bison 2.7.  */
-
-/* Skeleton implementation for Bison GLR parsers in C
-   
-      Copyright (C) 2002-2012 Free Software Foundation, Inc.
-   
-   This program is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-   
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-   
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-   
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-/* C GLR parser skeleton written by Paul Hilfinger.  */
-
-/* Identify Bison output.  */
-#define YYBISON 1
-
-/* Bison version.  */
-#define YYBISON_VERSION "2.7"
-
-/* Skeleton name.  */
-#define YYSKELETON_NAME "glr.c"
-
-/* Pure parsers.  */
-#define YYPURE 1
-
-
-
-
-
-
-/* Copy the first part of user declarations.  */
-/* Line 207 of glr.c  */
-#line 1 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-
-#include "BsParserFX.h"
-#include "BsLexerFX.h"
-#define inline
-
-void yyerror(YYLTYPE *locp, ParseState* parse_state, yyscan_t scanner, const char *msg);
-
-/* Line 207 of glr.c  */
-#line 64 "BsParserFX.c"
-
-# ifndef YY_NULL
-#  if defined __cplusplus && 201103L <= __cplusplus
-#   define YY_NULL nullptr
-#  else
-#   define YY_NULL 0
-#  endif
-# endif
-
-#include "BsParserFX.h"
-
-/* Enabling verbose error messages.  */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
-
-/* Default (constant) value used for initialization for null
-   right-hand sides.  Unlike the standard yacc.c template, here we set
-   the default value of $$ to a zeroed-out value.  Since the default
-   value is undefined, this behavior is technically correct.  */
-static YYSTYPE yyval_default;
-static YYLTYPE yyloc_default
-# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
-  = { 1, 1, 1, 1 }
-# endif
-;
-
-/* Copy the second part of user declarations.  */
-
-/* Line 230 of glr.c  */
-#line 98 "BsParserFX.c"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifndef YY_
-# if defined YYENABLE_NLS && YYENABLE_NLS
-#  if ENABLE_NLS
-#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
-#  endif
-# endif
-# ifndef YY_
-#  define YY_(Msgid) Msgid
-# endif
-#endif
-
-/* Suppress unused-variable warnings by "using" E.  */
-#if ! defined lint || defined __GNUC__
-# define YYUSE(E) ((void) (E))
-#else
-# define YYUSE(E) /* empty */
-#endif
-
-/* Identity function, used to suppress warnings about constant conditions.  */
-#ifndef lint
-# define YYID(N) (N)
-#else
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int i)
-#else
-static int
-YYID (i)
-    int i;
-#endif
-{
-  return i;
-}
-#endif
-
-#ifndef YYFREE
-# define YYFREE free
-#endif
-#ifndef YYMALLOC
-# define YYMALLOC malloc
-#endif
-#ifndef YYREALLOC
-# define YYREALLOC realloc
-#endif
-
-#define YYSIZEMAX ((size_t) -1)
-
-#ifdef __cplusplus
-   typedef bool yybool;
-#else
-   typedef unsigned char yybool;
-#endif
-#define yytrue 1
-#define yyfalse 0
-
-#ifndef YYSETJMP
-# include <setjmp.h>
-# define YYJMP_BUF jmp_buf
-# define YYSETJMP(Env) setjmp (Env)
-/* Pacify clang.  */
-# define YYLONGJMP(Env, Val) (longjmp (Env, Val), YYASSERT (0))
-#endif
-
-/*-----------------.
-| GCC extensions.  |
-`-----------------*/
-
-#ifndef __attribute__
-/* This feature is available in gcc versions 2.5 and later.  */
-# if (! defined __GNUC__ || __GNUC__ < 2 \
-      || (__GNUC__ == 2 && __GNUC_MINOR__ < 5))
-#  define __attribute__(Spec) /* empty */
-# endif
-#endif
-
-#ifndef YYASSERT
-# define YYASSERT(Condition) ((void) ((Condition) || (abort (), 0)))
-#endif
-
-/* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  24
-/* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   668
-
-/* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  124
-/* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  97
-/* YYNRULES -- Number of rules.  */
-#define YYNRULES  222
-/* YYNRULES -- Number of states.  */
-#define YYNSTATES  703
-/* YYMAXRHS -- Maximum number of symbols on right-hand side of rule.  */
-#define YYMAXRHS 33
-/* YYMAXLEFT -- Maximum number of symbols to the left of a handle
-   accessed by $0, $-1, etc., in any rule.  */
-#define YYMAXLEFT 0
-
-/* YYTRANSLATE(X) -- Bison symbol number corresponding to X.  */
-#define YYUNDEFTOK  2
-#define YYMAXUTOK   370
-
-#define YYTRANSLATE(YYX)                                                \
-  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
-static const unsigned char yytranslate[] =
-{
-       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     122,   123,     2,     2,   120,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,   121,   117,
-       2,   116,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,   118,     2,   119,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
-       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
-      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
-      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
-      55,    56,    57,    58,    59,    60,    61,    62,    63,    64,
-      65,    66,    67,    68,    69,    70,    71,    72,    73,    74,
-      75,    76,    77,    78,    79,    80,    81,    82,    83,    84,
-      85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
-      95,    96,    97,    98,    99,   100,   101,   102,   103,   104,
-     105,   106,   107,   108,   109,   110,   111,   112,   113,   114,
-     115
-};
-
-#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
-   YYRHS.  */
-static const unsigned short int yyprhs[] =
-{
-       0,     0,     3,     4,     7,     9,    11,    13,    15,    20,
-      25,    30,    35,    41,    44,    45,    48,    50,    52,    54,
-      56,    61,    66,    72,    75,    76,    79,    81,    83,    88,
-      93,    98,   103,   108,   113,   118,   123,   128,   133,   138,
-     143,   148,   153,   158,   164,   170,   176,   182,   187,   192,
-     194,   199,   208,   211,   214,   217,   220,   223,   226,   229,
-     232,   235,   243,   244,   247,   252,   257,   262,   267,   273,
-     276,   277,   280,   282,   287,   292,   298,   304,   310,   316,
-     321,   324,   327,   328,   331,   337,   342,   347,   352,   353,
-     356,   358,   363,   368,   373,   378,   383,   388,   393,   398,
-     403,   409,   415,   418,   424,   425,   428,   433,   438,   443,
-     449,   457,   467,   473,   481,   491,   505,   523,   543,   569,
-     603,   609,   612,   613,   616,   621,   626,   631,   636,   641,
-     646,   651,   656,   661,   666,   671,   676,   681,   686,   691,
-     696,   701,   706,   711,   715,   719,   722,   725,   728,   731,
-     734,   737,   740,   743,   746,   749,   752,   755,   758,   761,
-     764,   767,   770,   773,   776,   779,   782,   785,   788,   791,
-     794,   797,   800,   803,   806,   809,   812,   815,   818,   821,
-     824,   827,   828,   831,   832,   835,   836,   839,   840,   843,
-     844,   847,   848,   851,   852,   855,   856,   859,   860,   863,
-     864,   867,   868,   871,   872,   875,   876,   879,   880,   885,
-     886,   889,   895,   898,   899,   902,   906,   909,   910,   913,
-     919,   925,   931
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
-static const short int yyrhs[] =
-{
-     125,     0,    -1,    -1,   126,   125,    -1,   127,    -1,   128,
-      -1,   173,    -1,   214,    -1,    57,   116,     5,   117,    -1,
-      58,   116,     3,   117,    -1,    59,   116,     3,   117,    -1,
-      60,   116,     5,   117,    -1,   129,   118,   130,   119,   117,
-      -1,    63,   116,    -1,    -1,   131,   130,    -1,   132,    -1,
-     133,    -1,   137,    -1,   138,    -1,    64,   116,     6,   117,
-      -1,    65,   116,     6,   117,    -1,   134,   118,   135,   119,
-     117,    -1,    66,   116,    -1,    -1,   136,   135,    -1,   137,
-      -1,   138,    -1,    96,   116,     3,   117,    -1,    75,   116,
-       8,   117,    -1,    76,   116,     9,   117,    -1,    77,   116,
-       4,   117,    -1,    78,   116,     4,   117,    -1,    79,   116,
-       5,   117,    -1,    80,   116,     5,   117,    -1,    81,   116,
-       5,   117,    -1,    82,   116,     5,   117,    -1,    83,   116,
-       5,   117,    -1,    84,   116,     5,   117,    -1,    85,   116,
-      10,   117,    -1,    86,   116,     5,   117,    -1,    87,   116,
-       3,   117,    -1,    88,   116,     3,   117,    -1,   140,   118,
-     143,   119,   117,    -1,   141,   118,   143,   119,   117,    -1,
-     140,   118,   142,   119,   117,    -1,   141,   118,   142,   119,
-     117,    -1,    93,   116,     5,   117,    -1,    94,   116,     5,
-     117,    -1,   145,    -1,    74,   116,     3,   117,    -1,   139,
-     118,    96,   116,     3,   117,   119,   117,    -1,    67,   116,
-      -1,    68,   116,    -1,    69,   116,    -1,    70,   116,    -1,
-      71,   116,    -1,    72,   116,    -1,    73,   116,    -1,    89,
-     116,    -1,    90,   116,    -1,    11,   120,    11,   120,    11,
-     120,    10,    -1,    -1,   144,   143,    -1,    91,   116,    11,
-     117,    -1,    92,   116,    11,   117,    -1,    66,   116,    11,
-     117,    -1,    85,   116,    10,   117,    -1,   146,   118,   147,
-     119,   117,    -1,    95,   116,    -1,    -1,   148,   147,    -1,
-     149,    -1,    96,   116,     3,   117,    -1,    97,   116,     5,
-     117,    -1,   150,   118,   152,   119,   117,    -1,   151,   118,
-     152,   119,   117,    -1,   150,   118,   153,   119,   117,    -1,
-     151,   118,   153,   119,   117,    -1,   100,   116,    12,   117,
-      -1,    98,   116,    -1,    99,   116,    -1,    -1,   154,   152,
-      -1,    11,   120,    11,   120,    15,    -1,   101,   116,    11,
-     117,    -1,   102,   116,    11,   117,    -1,   103,   116,    15,
-     117,    -1,    -1,   156,   155,    -1,   157,    -1,   105,   116,
-      14,   117,    -1,   106,   116,    14,   117,    -1,   107,   116,
-      14,   117,    -1,   108,   116,     3,   117,    -1,   109,   116,
-       4,   117,    -1,   110,   116,     4,   117,    -1,   111,   116,
-       4,   117,    -1,   112,   116,   164,   117,    -1,    85,   116,
-      10,   117,    -1,   158,   118,   160,   119,   117,    -1,   158,
-     118,   159,   119,   117,    -1,   104,   116,    -1,    13,   120,
-      13,   120,    13,    -1,    -1,   161,   160,    -1,   113,   116,
-      13,   117,    -1,   114,   116,    13,   117,    -1,   115,   116,
-      13,   117,    -1,   118,     4,   120,     4,   119,    -1,   118,
-       4,   120,     4,   120,     4,   119,    -1,   118,     4,   120,
-       4,   120,     4,   120,     4,   119,    -1,   118,     3,   120,
-       3,   119,    -1,   118,     3,   120,     3,   120,     3,   119,
-      -1,   118,     3,   120,     3,   120,     3,   120,     3,   119,
-      -1,   118,     4,   120,     4,   120,     4,   120,     4,   120,
-       4,   120,     4,   119,    -1,   118,     4,   120,     4,   120,
-       4,   120,     4,   120,     4,   120,     4,   120,     4,   120,
-       4,   119,    -1,   118,     4,   120,     4,   120,     4,   120,
-       4,   120,     4,   120,     4,   120,     4,   120,     4,   120,
-       4,   119,    -1,   118,     4,   120,     4,   120,     4,   120,
-       4,   120,     4,   120,     4,   120,     4,   120,     4,   120,
-       4,   120,     4,   120,     4,   120,     4,   119,    -1,   118,
-       4,   120,     4,   120,     4,   120,     4,   120,     4,   120,
-       4,   120,     4,   120,     4,   120,     4,   120,     4,   120,
-       4,   120,     4,   120,     4,   120,     4,   120,     4,   120,
-       4,   119,    -1,   174,   118,   175,   119,   117,    -1,    61,
-     116,    -1,    -1,   176,   175,    -1,   177,   219,   199,   117,
-      -1,   178,   219,   200,   117,    -1,   179,   219,   201,   117,
-      -1,   180,   219,   202,   117,    -1,   181,   219,   203,   117,
-      -1,   182,   219,   204,   117,    -1,   183,   219,   205,   117,
-      -1,   184,   219,   206,   117,    -1,   185,   219,   202,   117,
-      -1,   186,   219,   202,   117,    -1,   187,   219,   207,   117,
-      -1,   188,   219,   208,   117,    -1,   189,   219,   207,   117,
-      -1,   190,   219,   209,   117,    -1,   191,   219,   210,   117,
-      -1,   192,   219,   208,   117,    -1,   193,   219,   210,   117,
-      -1,   194,   219,   211,   117,    -1,   196,   219,   213,   117,
-      -1,   197,   219,   117,    -1,   198,   212,   117,    -1,    17,
-       7,    -1,    18,     7,    -1,    19,     7,    -1,    20,     7,
-      -1,    21,     7,    -1,    22,     7,    -1,    23,     7,    -1,
-      24,     7,    -1,    25,     7,    -1,    26,     7,    -1,    27,
-       7,    -1,    28,     7,    -1,    29,     7,    -1,    30,     7,
-      -1,    31,     7,    -1,    32,     7,    -1,    33,     7,    -1,
-      34,     7,    -1,    35,     7,    -1,    36,     7,    -1,    37,
-       7,    -1,    38,     7,    -1,    39,     7,    -1,    40,     7,
-      -1,    41,     7,    -1,    42,     7,    -1,    43,     7,    -1,
-      44,     7,    -1,    45,     7,    -1,    46,     7,    -1,    47,
-       7,    -1,    48,     7,    -1,    49,     7,    -1,    50,     7,
-      -1,    51,     7,    -1,   195,   219,    -1,    -1,   116,     4,
-      -1,    -1,   116,   162,    -1,    -1,   116,   163,    -1,    -1,
-     116,   164,    -1,    -1,   116,     3,    -1,    -1,   116,   165,
-      -1,    -1,   116,   166,    -1,    -1,   116,   167,    -1,    -1,
-     116,   168,    -1,    -1,   116,   169,    -1,    -1,   116,   170,
-      -1,    -1,   116,   171,    -1,    -1,   116,   172,    -1,    -1,
-     116,   118,   155,   119,    -1,    -1,   116,     6,    -1,   215,
-     118,   216,   119,   117,    -1,    62,   116,    -1,    -1,   217,
-     216,    -1,   218,   219,   117,    -1,    52,     7,    -1,    -1,
-     220,   219,    -1,   121,    54,   122,     6,   123,    -1,   121,
-      53,   122,     6,   123,    -1,   121,    55,   122,     5,   123,
-      -1,   121,    56,   122,    16,   123,    -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
-static const unsigned short int yyrline[] =
-{
-       0,   277,   277,   278,   282,   283,   284,   285,   289,   290,
-     291,   292,   298,   302,   309,   311,   315,   316,   317,   318,
-     322,   323,   329,   333,   340,   342,   346,   347,   351,   352,
-     353,   354,   355,   356,   357,   358,   359,   360,   361,   362,
-     363,   364,   365,   366,   367,   368,   369,   370,   371,   372,
-     373,   379,   393,   398,   403,   408,   413,   418,   423,   433,
-     441,   449,   463,   465,   469,   470,   471,   472,   477,   481,
-     488,   490,   494,   498,   499,   500,   501,   502,   503,   504,
-     509,   517,   524,   526,   530,   543,   544,   545,   550,   552,
-     556,   557,   558,   559,   560,   561,   562,   563,   564,   565,
-     570,   571,   575,   583,   595,   597,   601,   602,   603,   608,
-     612,   616,   620,   624,   628,   632,   641,   652,   663,   674,
-     688,   692,   699,   701,   705,   706,   707,   708,   709,   710,
-     711,   712,   713,   714,   715,   716,   717,   718,   719,   720,
-     721,   722,   723,   724,   725,   741,   745,   749,   753,   757,
-     761,   765,   769,   773,   777,   781,   785,   789,   793,   797,
-     801,   805,   809,   813,   814,   815,   816,   817,   821,   822,
-     823,   824,   825,   829,   830,   831,   832,   833,   834,   835,
-     839,   847,   848,   852,   853,   857,   858,   862,   863,   867,
-     868,   872,   873,   877,   878,   882,   883,   887,   888,   892,
-     893,   897,   898,   902,   903,   907,   908,   912,   913,   917,
-     918,   923,   927,   934,   936,   940,   944,   958,   960,   964,
-     965,   966,   967
-};
-#endif
-
-#if YYDEBUG || YYERROR_VERBOSE || 0
-/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
-   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
-static const char *const yytname[] =
-{
-  "$end", "error", "$undefined", "TOKEN_INTEGER", "TOKEN_FLOAT",
-  "TOKEN_BOOLEAN", "TOKEN_STRING", "TOKEN_IDENTIFIER",
-  "TOKEN_FILLMODEVALUE", "TOKEN_CULLMODEVALUE", "TOKEN_COMPFUNCVALUE",
-  "TOKEN_OPVALUE", "TOKEN_COLORMASK", "TOKEN_ADDRMODEVALUE",
-  "TOKEN_FILTERVALUE", "TOKEN_BLENDOPVALUE", "TOKEN_BUFFERUSAGE",
-  "TOKEN_FLOATTYPE", "TOKEN_FLOAT2TYPE", "TOKEN_FLOAT3TYPE",
-  "TOKEN_FLOAT4TYPE", "TOKEN_INTTYPE", "TOKEN_INT2TYPE", "TOKEN_INT3TYPE",
-  "TOKEN_INT4TYPE", "TOKEN_COLORTYPE", "TOKEN_MAT2x2TYPE",
-  "TOKEN_MAT2x3TYPE", "TOKEN_MAT2x4TYPE", "TOKEN_MAT3x2TYPE",
-  "TOKEN_MAT3x3TYPE", "TOKEN_MAT3x4TYPE", "TOKEN_MAT4x2TYPE",
-  "TOKEN_MAT4x3TYPE", "TOKEN_MAT4x4TYPE", "TOKEN_SAMPLER1D",
-  "TOKEN_SAMPLER2D", "TOKEN_SAMPLER3D", "TOKEN_SAMPLERCUBE",
-  "TOKEN_SAMPLER2DMS", "TOKEN_TEXTURE1D", "TOKEN_TEXTURE2D",
-  "TOKEN_TEXTURE3D", "TOKEN_TEXTURECUBE", "TOKEN_TEXTURE2DMS",
-  "TOKEN_BYTEBUFFER", "TOKEN_STRUCTBUFFER", "TOKEN_RWTYPEDBUFFER",
-  "TOKEN_RWBYTEBUFFER", "TOKEN_RWSTRUCTBUFFER", "TOKEN_RWAPPENDBUFFER",
-  "TOKEN_RWCONSUMEBUFFER", "TOKEN_PARAMSBLOCK", "TOKEN_AUTO",
-  "TOKEN_ALIAS", "TOKEN_SHARED", "TOKEN_USAGE", "TOKEN_SEPARABLE",
-  "TOKEN_QUEUE", "TOKEN_PRIORITY", "TOKEN_TRANSPARENT", "TOKEN_PARAMETERS",
-  "TOKEN_BLOCKS", "TOKEN_TECHNIQUE", "TOKEN_RENDERER", "TOKEN_LANGUAGE",
-  "TOKEN_PASS", "TOKEN_VERTEX", "TOKEN_FRAGMENT", "TOKEN_GEOMETRY",
-  "TOKEN_HULL", "TOKEN_DOMAIN", "TOKEN_COMPUTE", "TOKEN_COMMON",
-  "TOKEN_STENCILREF", "TOKEN_FILLMODE", "TOKEN_CULLMODE",
-  "TOKEN_DEPTHBIAS", "TOKEN_SDEPTHBIAS", "TOKEN_DEPTHCLIP",
-  "TOKEN_SCISSOR", "TOKEN_MULTISAMPLE", "TOKEN_AALINE", "TOKEN_DEPTHREAD",
-  "TOKEN_DEPTHWRITE", "TOKEN_COMPAREFUNC", "TOKEN_STENCIL",
-  "TOKEN_STENCILREADMASK", "TOKEN_STENCILWRITEMASK",
-  "TOKEN_STENCILOPFRONT", "TOKEN_STENCILOPBACK", "TOKEN_FAIL",
-  "TOKEN_ZFAIL", "TOKEN_ALPHATOCOVERAGE", "TOKEN_INDEPENDANTBLEND",
-  "TOKEN_TARGET", "TOKEN_INDEX", "TOKEN_BLEND", "TOKEN_COLOR",
-  "TOKEN_ALPHA", "TOKEN_WRITEMASK", "TOKEN_SOURCE", "TOKEN_DEST",
-  "TOKEN_OP", "TOKEN_ADDRMODE", "TOKEN_MINFILTER", "TOKEN_MAGFILTER",
-  "TOKEN_MIPFILTER", "TOKEN_MAXANISO", "TOKEN_MIPBIAS", "TOKEN_MIPMIN",
-  "TOKEN_MIPMAX", "TOKEN_BORDERCOLOR", "TOKEN_U", "TOKEN_V", "TOKEN_W",
-  "'='", "';'", "'{'", "'}'", "','", "':'", "'('", "')'", "$accept",
-  "shader", "shader_statement", "shader_option", "technique",
-  "technique_header", "technique_body", "technique_statement",
-  "technique_option", "pass", "pass_header", "pass_body", "pass_statement",
-  "pass_option", "code", "code_header", "stencil_op_front_header",
-  "stencil_op_back_header", "stencil_op_body_init", "stencil_op_body",
-  "stencil_op_option", "target", "target_header", "target_body",
-  "target_statement", "target_option", "blend_color_header",
-  "blend_alpha_header", "blenddef_body", "blenddef_body_init",
-  "blenddef_option", "sampler_state_body", "sampler_state_option",
-  "addr_mode", "addr_mode_header", "addr_mode_body_init", "addr_mode_body",
-  "addr_mode_option", "float2", "float3", "float4", "int2", "int3", "int4",
-  "mat6", "mat8", "mat9", "mat12", "mat16", "parameters",
-  "parameters_header", "parameters_body", "parameter",
-  "param_header_float", "param_header_float2", "param_header_float3",
-  "param_header_float4", "param_header_int", "param_header_int2",
-  "param_header_int3", "param_header_int4", "param_header_color",
-  "param_header_mat2x2", "param_header_mat2x3", "param_header_mat2x4",
-  "param_header_mat3x2", "param_header_mat3x3", "param_header_mat3x4",
-  "param_header_mat4x2", "param_header_mat4x3", "param_header_mat4x4",
-  "param_header_sampler", "param_header_texture", "param_header_buffer",
-  "param_header_qualified_sampler", "param_body_float",
-  "param_body_float2", "param_body_float3", "param_body_float4",
-  "param_body_int", "param_body_int2", "param_body_int3",
-  "param_body_int4", "param_body_mat6", "param_body_mat8",
-  "param_body_mat9", "param_body_mat12", "param_body_mat16",
-  "param_body_sampler", "param_body_tex", "blocks", "blocks_header",
-  "blocks_body", "block", "block_header", "qualifier_list", "qualifier", YY_NULL
-};
-#endif
-
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
-static const unsigned char yyr1[] =
-{
-       0,   124,   125,   125,   126,   126,   126,   126,   127,   127,
-     127,   127,   128,   129,   130,   130,   131,   131,   131,   131,
-     132,   132,   133,   134,   135,   135,   136,   136,   137,   137,
-     137,   137,   137,   137,   137,   137,   137,   137,   137,   137,
-     137,   137,   137,   137,   137,   137,   137,   137,   137,   137,
-     137,   138,   139,   139,   139,   139,   139,   139,   139,   140,
-     141,   142,   143,   143,   144,   144,   144,   144,   145,   146,
-     147,   147,   148,   149,   149,   149,   149,   149,   149,   149,
-     150,   151,   152,   152,   153,   154,   154,   154,   155,   155,
-     156,   156,   156,   156,   156,   156,   156,   156,   156,   156,
-     157,   157,   158,   159,   160,   160,   161,   161,   161,   162,
-     163,   164,   165,   166,   167,   168,   169,   170,   171,   172,
-     173,   174,   175,   175,   176,   176,   176,   176,   176,   176,
-     176,   176,   176,   176,   176,   176,   176,   176,   176,   176,
-     176,   176,   176,   176,   176,   177,   178,   179,   180,   181,
-     182,   183,   184,   185,   186,   187,   188,   189,   190,   191,
-     192,   193,   194,   195,   195,   195,   195,   195,   196,   196,
-     196,   196,   196,   197,   197,   197,   197,   197,   197,   197,
-     198,   199,   199,   200,   200,   201,   201,   202,   202,   203,
-     203,   204,   204,   205,   205,   206,   206,   207,   207,   208,
-     208,   209,   209,   210,   210,   211,   211,   212,   212,   213,
-     213,   214,   215,   216,   216,   217,   218,   219,   219,   220,
-     220,   220,   220
-};
-
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
-static const unsigned char yyr2[] =
-{
-       0,     2,     0,     2,     1,     1,     1,     1,     4,     4,
-       4,     4,     5,     2,     0,     2,     1,     1,     1,     1,
-       4,     4,     5,     2,     0,     2,     1,     1,     4,     4,
-       4,     4,     4,     4,     4,     4,     4,     4,     4,     4,
-       4,     4,     4,     5,     5,     5,     5,     4,     4,     1,
-       4,     8,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     7,     0,     2,     4,     4,     4,     4,     5,     2,
-       0,     2,     1,     4,     4,     5,     5,     5,     5,     4,
-       2,     2,     0,     2,     5,     4,     4,     4,     0,     2,
-       1,     4,     4,     4,     4,     4,     4,     4,     4,     4,
-       5,     5,     2,     5,     0,     2,     4,     4,     4,     5,
-       7,     9,     5,     7,     9,    13,    17,    19,    25,    33,
-       5,     2,     0,     2,     4,     4,     4,     4,     4,     4,
-       4,     4,     4,     4,     4,     4,     4,     4,     4,     4,
-       4,     4,     4,     3,     3,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     0,     2,     0,     2,     0,     2,     0,     2,     0,
-       2,     0,     2,     0,     2,     0,     2,     0,     2,     0,
-       2,     0,     2,     0,     2,     0,     2,     0,     4,     0,
-       2,     5,     2,     0,     2,     3,     2,     0,     2,     5,
-       5,     5,     5
-};
-
-/* YYDPREC[RULE-NUM] -- Dynamic precedence of rule #RULE-NUM (0 if none).  */
-static const unsigned char yydprec[] =
-{
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0
-};
-
-/* YYMERGER[RULE-NUM] -- Index of merging function for rule #RULE-NUM.  */
-static const unsigned char yymerger[] =
-{
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0
-};
-
-/* YYDEFACT[S] -- default reduction number in state S.  Performed when
-   YYTABLE doesn't specify something else to do.  Zero means the default
-   is an error.  */
-static const unsigned char yydefact[] =
-{
-       2,     0,     0,     0,     0,     0,     0,     0,     0,     2,
-       4,     5,     0,     6,     0,     7,     0,     0,     0,     0,
-       0,   121,   212,    13,     1,     3,    14,   122,   213,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,    14,    16,    17,     0,    18,
-      19,     0,     0,     0,    49,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,   122,   217,   217,   217,   217,   217,   217,   217,
-     217,   217,   217,   217,   217,   217,   217,   217,   217,   217,
-     217,   217,   217,   217,   207,     0,     0,   213,   217,     8,
-       9,    10,    11,     0,     0,    23,    52,    53,    54,    55,
-      56,    57,    58,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,    59,    60,
-       0,     0,    69,     0,     0,    15,    24,     0,    62,    62,
-      70,   145,   146,   147,   148,   149,   150,   151,   152,   153,
-     154,   155,   156,   157,   158,   159,   160,   161,   162,   163,
-     164,   165,   166,   167,   168,   169,   170,   171,   172,   173,
-     174,   175,   176,   177,   178,   179,     0,   123,     0,   181,
-     217,   183,   185,   187,   189,   191,   193,   195,   187,   187,
-     197,   199,   197,   201,   203,   199,   203,   205,   180,   209,
-       0,     0,     0,   216,     0,   214,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,    12,     0,    24,
-      26,    27,     0,     0,     0,     0,     0,     0,     0,     0,
-      62,     0,     0,     0,     0,     0,     0,     0,     0,    70,
-      72,     0,     0,   120,     0,     0,     0,     0,     0,     0,
-     218,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,   143,    88,   144,   211,   215,    20,    21,    50,
-      29,    30,    31,    32,    33,    34,    35,    36,    37,    38,
-      39,    40,    41,    42,    47,    48,    28,     0,    25,     0,
-       0,     0,     0,     0,     0,     0,     0,    63,     0,     0,
-       0,     0,    80,    81,     0,     0,    71,    82,    82,     0,
-       0,     0,     0,   182,   124,     0,   184,   125,     0,   186,
-     126,     0,   188,   127,   190,   128,     0,   192,   129,     0,
-     194,   130,     0,   196,   131,   132,   133,     0,   198,   134,
-       0,   200,   135,   136,     0,   202,   137,     0,   204,   138,
-     139,   140,     0,   206,   141,   210,   142,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,    88,    90,
-       0,    22,     0,     0,     0,     0,     0,     0,    45,    43,
-      46,    44,     0,     0,     0,    68,     0,     0,     0,     0,
-       0,     0,    82,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,   102,     0,     0,     0,     0,     0,     0,     0,     0,
-     208,    89,   104,     0,     0,    66,    67,    64,    65,    73,
-      74,    79,     0,     0,     0,     0,     0,     0,    83,     0,
-       0,   220,   219,   221,   222,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,   104,     0,     0,     0,     0,     0,     0,    75,    77,
-      76,    78,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,    99,    91,    92,    93,    94,    95,    96,
-      97,    98,     0,     0,     0,     0,     0,     0,   105,    51,
-       0,     0,    85,    86,    87,   109,     0,     0,   112,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-     101,   100,    61,    84,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,   106,   107,   108,   110,     0,   113,
-       0,     0,     0,     0,     0,     0,   103,     0,     0,     0,
-       0,     0,     0,     0,   111,   114,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,   115,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,   116,     0,     0,     0,     0,     0,     0,
-     117,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,   118,     0,     0,     0,     0,     0,     0,
-       0,     0,   119
-};
-
-/* YYPDEFGOTO[NTERM-NUM].  */
-static const short int yydefgoto[] =
-{
-      -1,     8,     9,    10,    11,    12,    64,    65,    66,    67,
-      68,   268,   269,    69,    70,    71,    72,    73,   278,   279,
-     280,    74,    75,   288,   289,   290,   291,   292,   460,   461,
-     462,   437,   438,   439,   440,   539,   540,   541,   386,   389,
-     392,   397,   400,   403,   408,   411,   415,   418,   423,    13,
-      14,   111,   112,   113,   114,   115,   116,   117,   118,   119,
-     120,   121,   122,   123,   124,   125,   126,   127,   128,   129,
-     130,   131,   132,   133,   134,   299,   302,   304,   306,   308,
-     310,   312,   314,   318,   320,   323,   325,   329,   242,   331,
-      15,    16,   136,   137,   138,   219,   220
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
-   STATE-NUM.  */
-#define YYPACT_NINF -354
-static const short int yypact[] =
-{
-      11,   -90,   -50,   -41,   -16,   -13,   -11,    -9,   108,    11,
-    -354,  -354,    -6,  -354,    -5,  -354,    -3,   146,   149,   178,
-     177,  -354,  -354,  -354,  -354,  -354,    60,    14,   138,    74,
-      75,    76,    77,    79,    80,    81,    82,    83,    84,    85,
-      87,    88,    89,    91,    92,    93,    94,    95,    96,    97,
-      98,    99,   100,   101,   102,   103,   104,   105,   106,   107,
-     109,   110,   111,   112,   113,    60,  -354,  -354,   115,  -354,
-    -354,   116,   117,   118,  -354,   119,   195,   199,   217,   222,
-     223,   224,   231,   232,   233,   234,   235,   236,   237,   238,
-     239,   240,   241,   242,   243,   244,   245,   246,   247,   248,
-     249,   250,   251,   252,   253,   254,   255,   256,   257,   258,
-     259,   148,    14,   147,   147,   147,   147,   147,   147,   147,
-     147,   147,   147,   147,   147,   147,   147,   147,   147,   147,
-     147,   147,   147,   147,   153,   263,   152,   138,   147,  -354,
-    -354,  -354,  -354,   266,   267,  -354,  -354,  -354,  -354,  -354,
-    -354,  -354,  -354,   271,   268,   269,   273,   275,   270,   276,
-     277,   278,   279,   280,   281,   282,   283,   285,  -354,  -354,
-     284,   287,  -354,   290,   163,  -354,    90,   194,    19,    19,
-     -19,  -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,
-    -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,
-    -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,
-    -354,  -354,  -354,  -354,  -354,  -354,   179,  -354,    43,   181,
-     147,   182,   183,   184,   185,   186,   187,   188,   184,   184,
-     189,   190,   189,   191,   192,   190,   192,   193,  -354,   196,
-     197,   176,   198,  -354,   200,  -354,   201,   202,   203,   204,
-     205,   206,   207,   208,   209,   210,   211,   212,   213,   214,
-     215,   216,   218,   219,   220,   221,   225,  -354,   226,    90,
-    -354,  -354,   227,   175,   228,   230,   260,   261,   229,   262,
-      10,   264,   265,   272,   274,   286,   288,   289,   291,   -19,
-    -354,   293,   294,  -354,   292,   295,   296,   297,   306,   298,
-    -354,   302,   299,   303,   305,   307,   309,   308,   310,   311,
-     313,   314,   316,   317,   319,   320,   321,   322,   324,   325,
-     327,   328,   329,   331,   332,   334,   335,   336,   337,   339,
-     333,   340,  -354,   -18,  -354,  -354,  -354,  -354,  -354,  -354,
-    -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,
-    -354,  -354,  -354,  -354,  -354,  -354,  -354,   341,  -354,   338,
-     323,   342,   330,   343,   344,   345,   346,  -354,   347,   348,
-     349,   351,  -354,  -354,   301,   350,  -354,    16,    16,   352,
-     353,   355,   300,  -354,  -354,   357,  -354,  -354,   358,  -354,
-    -354,   359,  -354,  -354,  -354,  -354,   354,  -354,  -354,   361,
-    -354,  -354,   362,  -354,  -354,  -354,  -354,   363,  -354,  -354,
-     364,  -354,  -354,  -354,   365,  -354,  -354,   366,  -354,  -354,
-    -354,  -354,   367,  -354,  -354,  -354,  -354,   312,   315,   318,
-     326,   356,   360,   368,   369,   370,   371,   304,   -18,  -354,
-     372,  -354,   374,   373,   375,   377,   378,   379,  -354,  -354,
-    -354,  -354,   380,   381,   382,  -354,   383,   384,   385,   386,
-     387,   388,    86,   389,   390,   391,   392,   393,   394,   398,
-     399,   400,   401,   402,   403,   404,   405,   406,   407,   408,
-     376,  -354,   395,   410,   425,   396,   397,   409,   442,   307,
-    -354,  -354,     7,   411,   438,  -354,  -354,  -354,  -354,  -354,
-    -354,  -354,   443,   448,   449,   446,   412,   414,  -354,   415,
-     416,  -354,  -354,  -354,  -354,   462,   464,   465,   467,   468,
-     470,   471,   473,   474,   475,   476,   417,   418,   419,   420,
-     421,   422,   423,   424,   426,   427,   428,   429,   430,   431,
-     432,   -31,   435,   433,   434,   439,   440,   441,  -354,  -354,
-    -354,  -354,   436,   444,   445,   447,   450,   451,   452,   453,
-     454,   455,   456,  -354,  -354,  -354,  -354,  -354,  -354,  -354,
-    -354,  -354,   461,   469,   491,   492,   460,   463,  -354,  -354,
-     478,   466,  -354,  -354,  -354,  -354,   479,   485,  -354,   507,
-     508,   509,   538,   544,   545,   555,   458,   472,   477,   480,
-    -354,  -354,  -354,  -354,   481,   459,   482,   483,   484,   486,
-     487,   488,   489,   499,  -354,  -354,  -354,  -354,   556,  -354,
-     558,   559,   563,   564,   565,   577,  -354,   493,   494,   490,
-     495,   496,   497,   498,  -354,  -354,   578,   579,   580,   581,
-     582,   500,   501,   502,   503,   504,   583,   584,   586,   587,
-     588,   506,   510,   511,   512,   513,  -354,   589,   591,   592,
-     594,   514,   515,   516,   517,   595,   598,   601,   607,   519,
-     520,   521,   522,  -354,   610,   615,   622,   524,   525,   526,
-    -354,   623,   624,   527,   528,   625,   635,   529,   530,   640,
-     647,   533,   534,  -354,   649,   535,   652,   537,   654,   539,
-     656,   542,  -354
-};
-
-/* YYPGOTO[NTERM-NUM].  */
-static const short int yypgoto[] =
-{
-    -354,   553,  -354,  -354,  -354,  -354,   597,  -354,  -354,  -354,
-    -354,    78,  -354,  -155,  -153,  -354,  -354,  -354,   170,  -157,
-    -354,  -354,  -354,    61,  -354,  -354,  -354,  -354,  -353,   -27,
-    -354,   -72,  -354,  -354,  -354,  -354,  -169,  -354,  -354,  -354,
-    -116,  -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,
-    -354,   551,  -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,
-    -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,
-    -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,  -200,  -354,
-    -354,  -354,  -354,   142,   140,  -354,   143,  -354,  -354,  -354,
-    -354,  -354,   531,  -354,  -354,  -114,  -354
-};
-
-/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
-   positive, shift that token.  If negative, reduce the rule which
-   number is the opposite.  If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -1
-static const unsigned short int yytable[] =
-{
-     221,   222,   223,   224,   225,   226,   227,   228,   229,   230,
-     231,   232,   233,   234,   235,   236,   237,   238,   239,   240,
-     535,   270,   282,   271,   246,   463,    17,   456,   315,   316,
-     273,    76,    77,    78,    79,    80,    81,    82,    83,    84,
-      85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
-      95,    96,    97,    98,    99,   100,   101,   102,   103,   104,
-     105,   106,   107,   108,   109,   110,    18,   427,     1,     2,
-       3,     4,     5,     6,     7,    19,   274,   283,   284,   285,
-     286,   287,   536,   537,   538,   274,   428,   429,   430,   431,
-     432,   433,   434,   435,   436,   275,   294,   295,   296,   297,
-      20,   276,   277,    21,   275,    22,   300,    23,    24,   508,
-     276,   277,    26,    27,   270,    28,   271,   457,   458,   459,
-     536,   537,   538,   367,    33,    34,    35,    36,    37,    38,
-      39,    40,    41,    42,    43,    44,    45,    46,    47,    48,
-      49,    50,    51,    52,    53,    54,    55,    56,    57,    58,
-      59,    29,    30,    60,    61,    62,    63,    36,    37,    38,
-      39,    40,    41,    42,    43,    44,    45,    46,    47,    48,
-      49,    50,    51,    52,    53,    54,    55,    56,    57,    58,
-      59,    31,    32,    60,    61,    62,    63,   457,   458,   459,
-     135,   139,   140,   141,   142,   143,   144,   145,   146,   147,
-     148,   149,   181,   150,   151,   152,   182,   153,   154,   155,
-     156,   157,   158,   159,   160,   161,   162,   163,   164,   165,
-     166,   167,   168,   169,   183,   170,   171,   172,   173,   184,
-     185,   186,   174,   176,   177,   178,   179,   180,   187,   188,
-     189,   190,   191,   192,   193,   194,   195,   196,   197,   198,
-     199,   200,   201,   202,   203,   204,   205,   206,   207,   208,
-     209,   210,   211,   212,   213,   214,   215,   216,   218,   241,
-     243,   244,   247,   248,   249,   254,   250,   252,   251,   253,
-     267,   255,   256,   257,   258,   259,   262,   261,   263,   264,
-     272,   260,   265,   266,   333,   360,   293,   298,   301,   303,
-     305,   307,   309,   311,   313,   317,   319,   322,   324,   328,
-     383,   394,   330,   454,   332,   334,   468,   335,   336,   337,
-     338,   339,   340,   341,   342,   343,   344,   345,   346,   347,
-     348,   349,   350,   351,   443,   352,   353,   354,   355,   425,
-     445,   442,   356,   359,   361,   357,   362,   358,   365,   281,
-     376,   464,   452,   444,   446,   447,   453,   472,   465,   466,
-     467,   469,   470,   471,   473,   474,   491,   475,   476,   477,
-     478,   479,   578,   534,   321,   326,   363,   364,     0,   327,
-       0,   366,     0,   368,   369,     0,   526,     0,   370,     0,
-     371,     0,     0,     0,     0,     0,     0,     0,     0,   530,
-       0,   531,   372,     0,   373,   374,     0,     0,     0,   527,
-     375,   377,   378,   532,   379,   384,   387,   380,   381,   382,
-     385,   388,   390,   490,   528,   391,   393,   395,   480,   396,
-     398,   481,   399,   401,   482,   402,   404,   405,   406,   529,
-     407,   409,   483,   410,   412,   413,   533,   414,   416,   543,
-     417,   419,   420,   421,   544,   422,   424,   426,   441,   545,
-     546,   547,   448,   449,   450,   451,   552,   455,   553,   554,
-     555,   556,   484,   557,   596,   558,   485,   559,   560,   561,
-     562,   603,   597,   604,   486,   487,   488,   489,   602,   605,
-     492,   493,   495,   494,   496,   497,   498,   499,   500,   501,
-     503,   504,   505,   502,   598,   599,   506,   507,   509,   510,
-     606,   607,   626,   608,   511,   512,   513,   514,   515,   516,
-     517,   518,   519,   520,   521,   522,   523,   524,   525,   548,
-     542,   549,   550,   551,   563,   564,   565,   566,   567,   568,
-     569,   570,   609,   571,   573,   574,   575,   572,   610,   611,
-     576,   577,   579,   580,   581,   585,   582,   583,   584,   612,
-     627,   628,    25,   629,   586,   587,   588,   630,   631,   632,
-     589,   590,   591,   592,   593,   594,   595,   600,   613,   618,
-     601,   633,   641,   642,   643,   644,   645,   651,   652,   614,
-     653,   654,   655,   661,   615,   662,   663,   616,   664,   669,
-     617,   619,   670,   620,   621,   671,   622,   623,   624,   625,
-     636,   672,   634,   635,   677,   637,   638,   639,   640,   678,
-     646,   647,   648,   649,   650,   656,   679,   683,   684,   687,
-     657,   658,   659,   660,   665,   666,   667,   668,   673,   688,
-     674,   675,   676,   680,   691,   681,   682,   685,   686,   689,
-     690,   692,   693,   695,   694,   696,   697,   698,   699,   700,
-     701,   702,   175,   217,     0,     0,     0,     0,   245
-};
-
-/* YYCONFLP[YYPACT[STATE-NUM]] -- Pointer into YYCONFL of start of
-   list of conflicting reductions corresponding to action entry for
-   state STATE-NUM in yytable.  0 means no conflicts.  The list in
-   yyconfl is terminated by a rule number of 0.  */
-static const unsigned char yyconflp[] =
-{
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0
-};
-
-/* YYCONFL[I] -- lists of conflicting rule numbers, each terminated by
-   0, pointed into by YYCONFLP.  */
-static const short int yyconfl[] =
-{
-       0
-};
-
-static const short int yycheck[] =
-{
-     114,   115,   116,   117,   118,   119,   120,   121,   122,   123,
-     124,   125,   126,   127,   128,   129,   130,   131,   132,   133,
-      13,   176,   179,   176,   138,   378,   116,    11,   228,   229,
-      11,    17,    18,    19,    20,    21,    22,    23,    24,    25,
-      26,    27,    28,    29,    30,    31,    32,    33,    34,    35,
-      36,    37,    38,    39,    40,    41,    42,    43,    44,    45,
-      46,    47,    48,    49,    50,    51,   116,    85,    57,    58,
-      59,    60,    61,    62,    63,   116,    66,    96,    97,    98,
-      99,   100,   113,   114,   115,    66,   104,   105,   106,   107,
-     108,   109,   110,   111,   112,    85,    53,    54,    55,    56,
-     116,    91,    92,   116,    85,   116,   220,   116,     0,   462,
-      91,    92,   118,   118,   269,   118,   269,   101,   102,   103,
-     113,   114,   115,   280,    64,    65,    66,    67,    68,    69,
-      70,    71,    72,    73,    74,    75,    76,    77,    78,    79,
-      80,    81,    82,    83,    84,    85,    86,    87,    88,    89,
-      90,     5,     3,    93,    94,    95,    96,    67,    68,    69,
-      70,    71,    72,    73,    74,    75,    76,    77,    78,    79,
-      80,    81,    82,    83,    84,    85,    86,    87,    88,    89,
-      90,     3,     5,    93,    94,    95,    96,   101,   102,   103,
-      52,   117,   117,   117,   117,   116,   116,   116,   116,   116,
-     116,   116,     7,   116,   116,   116,     7,   116,   116,   116,
-     116,   116,   116,   116,   116,   116,   116,   116,   116,   116,
-     116,   116,   116,   116,     7,   116,   116,   116,   116,     7,
-       7,     7,   119,   118,   118,   118,   118,   118,     7,     7,
-       7,     7,     7,     7,     7,     7,     7,     7,     7,     7,
-       7,     7,     7,     7,     7,     7,     7,     7,     7,     7,
-       7,     7,     7,     7,     7,     7,     7,   119,   121,   116,
-       7,   119,     6,     6,     3,     5,     8,     4,     9,     4,
-     117,     5,     5,     5,     5,     5,     3,     5,     3,     5,
-      96,    10,     5,     3,   118,   120,   117,   116,   116,   116,
-     116,   116,   116,   116,   116,   116,   116,   116,   116,   116,
-       4,     3,   116,    12,   117,   117,    16,   117,   117,   117,
-     117,   117,   117,   117,   117,   117,   117,   117,   117,   117,
-     117,   117,   117,   117,    11,   117,   117,   117,   117,     6,
-      10,     3,   117,   116,   116,   119,   116,   269,   119,   179,
-     289,   378,     3,    11,    11,    11,     5,     3,     6,     6,
-       5,     4,     4,     4,     3,     3,   438,     4,     4,     4,
-       4,     4,   541,   489,   232,   235,   116,   116,    -1,   236,
-      -1,   119,    -1,   119,   119,    -1,    10,    -1,   116,    -1,
-     116,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,     3,
-      -1,     4,   116,    -1,   116,   116,    -1,    -1,    -1,    14,
-     119,   118,   118,     4,   122,   117,   117,   122,   122,   122,
-     118,   118,   117,   119,    14,   118,   117,   117,   116,   118,
-     117,   116,   118,   117,   116,   118,   117,   117,   117,    14,
-     118,   117,   116,   118,   117,   117,     4,   118,   117,    11,
-     118,   117,   117,   117,    11,   118,   117,   117,   117,    11,
-      11,    15,   117,   117,   117,   117,     4,   117,     4,     4,
-       3,     3,   116,     3,    13,     4,   116,     4,     4,     4,
-       4,    15,    13,     4,   116,   116,   116,   116,    10,     4,
-     118,   117,   117,   120,   117,   117,   117,   117,   117,   117,
-     116,   116,   116,   120,    13,    13,   119,   119,   119,   119,
-       3,     3,    13,     4,   123,   123,   123,   123,   120,   120,
-     120,   120,   120,   120,   120,   120,   120,   120,   120,   117,
-     119,   117,   117,   117,   117,   117,   117,   117,   117,   117,
-     117,   117,     4,   117,   116,   116,   116,   120,     4,     4,
-     119,   119,   117,   120,   120,   119,   117,   117,   117,     4,
-       4,     3,     9,     4,   120,   120,   119,     4,     4,     4,
-     120,   120,   120,   120,   120,   120,   120,   117,   120,   120,
-     117,     4,     4,     4,     4,     4,     4,     4,     4,   117,
-       4,     4,     4,     4,   117,     4,     4,   117,     4,     4,
-     119,   119,     4,   120,   120,     4,   120,   120,   120,   120,
-     120,     4,   119,   119,     4,   120,   120,   120,   120,     4,
-     120,   120,   120,   120,   120,   119,     4,     4,     4,     4,
-     120,   120,   120,   120,   120,   120,   120,   120,   119,     4,
-     120,   120,   120,   119,     4,   120,   120,   120,   120,   120,
-     120,     4,   119,     4,   120,   120,     4,   120,     4,   120,
-       4,   119,    65,   112,    -1,    -1,    -1,    -1,   137
-};
-
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
-   symbol of state STATE-NUM.  */
-static const unsigned char yystos[] =
-{
-       0,    57,    58,    59,    60,    61,    62,    63,   125,   126,
-     127,   128,   129,   173,   174,   214,   215,   116,   116,   116,
-     116,   116,   116,   116,     0,   125,   118,   118,   118,     5,
-       3,     3,     5,    64,    65,    66,    67,    68,    69,    70,
-      71,    72,    73,    74,    75,    76,    77,    78,    79,    80,
-      81,    82,    83,    84,    85,    86,    87,    88,    89,    90,
-      93,    94,    95,    96,   130,   131,   132,   133,   134,   137,
-     138,   139,   140,   141,   145,   146,    17,    18,    19,    20,
-      21,    22,    23,    24,    25,    26,    27,    28,    29,    30,
-      31,    32,    33,    34,    35,    36,    37,    38,    39,    40,
-      41,    42,    43,    44,    45,    46,    47,    48,    49,    50,
-      51,   175,   176,   177,   178,   179,   180,   181,   182,   183,
-     184,   185,   186,   187,   188,   189,   190,   191,   192,   193,
-     194,   195,   196,   197,   198,    52,   216,   217,   218,   117,
-     117,   117,   117,   116,   116,   116,   116,   116,   116,   116,
-     116,   116,   116,   116,   116,   116,   116,   116,   116,   116,
-     116,   116,   116,   116,   116,   116,   116,   116,   116,   116,
-     116,   116,   116,   116,   119,   130,   118,   118,   118,   118,
-     118,     7,     7,     7,     7,     7,     7,     7,     7,     7,
-       7,     7,     7,     7,     7,     7,     7,     7,     7,     7,
-       7,     7,     7,     7,     7,     7,     7,     7,     7,     7,
-       7,     7,     7,     7,     7,     7,   119,   175,   121,   219,
-     220,   219,   219,   219,   219,   219,   219,   219,   219,   219,
-     219,   219,   219,   219,   219,   219,   219,   219,   219,   219,
-     219,   116,   212,     7,   119,   216,   219,     6,     6,     3,
-       8,     9,     4,     4,     5,     5,     5,     5,     5,     5,
-      10,     5,     3,     3,     5,     5,     3,   117,   135,   136,
-     137,   138,    96,    11,    66,    85,    91,    92,   142,   143,
-     144,   142,   143,    96,    97,    98,    99,   100,   147,   148,
-     149,   150,   151,   117,    53,    54,    55,    56,   116,   199,
-     219,   116,   200,   116,   201,   116,   202,   116,   203,   116,
-     204,   116,   205,   116,   206,   202,   202,   116,   207,   116,
-     208,   207,   116,   209,   116,   210,   208,   210,   116,   211,
-     116,   213,   117,   118,   117,   117,   117,   117,   117,   117,
-     117,   117,   117,   117,   117,   117,   117,   117,   117,   117,
-     117,   117,   117,   117,   117,   117,   117,   119,   135,   116,
-     120,   116,   116,   116,   116,   119,   119,   143,   119,   119,
-     116,   116,   116,   116,   116,   119,   147,   118,   118,   122,
-     122,   122,   122,     4,   117,   118,   162,   117,   118,   163,
-     117,   118,   164,   117,     3,   117,   118,   165,   117,   118,
-     166,   117,   118,   167,   117,   117,   117,   118,   168,   117,
-     118,   169,   117,   117,   118,   170,   117,   118,   171,   117,
-     117,   117,   118,   172,   117,     6,   117,    85,   104,   105,
-     106,   107,   108,   109,   110,   111,   112,   155,   156,   157,
-     158,   117,     3,    11,    11,    10,    11,    11,   117,   117,
-     117,   117,     3,     5,    12,   117,    11,   101,   102,   103,
-     152,   153,   154,   152,   153,     6,     6,     5,    16,     4,
-       4,     4,     3,     3,     3,     4,     4,     4,     4,     4,
-     116,   116,   116,   116,   116,   116,   116,   116,   116,   116,
-     119,   155,   118,   117,   120,   117,   117,   117,   117,   117,
-     117,   117,   120,   116,   116,   116,   119,   119,   152,   119,
-     119,   123,   123,   123,   123,   120,   120,   120,   120,   120,
-     120,   120,   120,   120,   120,   120,    10,    14,    14,    14,
-       3,     4,     4,     4,   164,    13,   113,   114,   115,   159,
-     160,   161,   119,    11,    11,    11,    11,    15,   117,   117,
-     117,   117,     4,     4,     4,     3,     3,     3,     4,     4,
-       4,     4,     4,   117,   117,   117,   117,   117,   117,   117,
-     117,   117,   120,   116,   116,   116,   119,   119,   160,   117,
-     120,   120,   117,   117,   117,   119,   120,   120,   119,   120,
-     120,   120,   120,   120,   120,   120,    13,    13,    13,    13,
-     117,   117,    10,    15,     4,     4,     3,     3,     4,     4,
-       4,     4,     4,   120,   117,   117,   117,   119,   120,   119,
-     120,   120,   120,   120,   120,   120,    13,     4,     3,     4,
-       4,     4,     4,     4,   119,   119,   120,   120,   120,   120,
-     120,     4,     4,     4,     4,     4,   120,   120,   120,   120,
-     120,     4,     4,     4,     4,     4,   119,   120,   120,   120,
-     120,     4,     4,     4,     4,   120,   120,   120,   120,     4,
-       4,     4,     4,   119,   120,   120,   120,     4,     4,     4,
-     119,   120,   120,     4,     4,   120,   120,     4,     4,   120,
-     120,     4,     4,   119,   120,     4,   120,     4,   120,     4,
-     120,     4,   119
-};
-
-/* Error token number */
-#define YYTERROR 1
-
-
-/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
-   If N is 0, then set CURRENT to the empty location which ends
-   the previous symbol: RHS[0] (always defined).  */
-
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N)                                \
-    do                                                                  \
-      if (YYID (N))                                                     \
-        {                                                               \
-          (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;        \
-          (Current).first_column = YYRHSLOC (Rhs, 1).first_column;      \
-          (Current).last_line    = YYRHSLOC (Rhs, N).last_line;         \
-          (Current).last_column  = YYRHSLOC (Rhs, N).last_column;       \
-        }                                                               \
-      else                                                              \
-        {                                                               \
-          (Current).first_line   = (Current).last_line   =              \
-            YYRHSLOC (Rhs, 0).last_line;                                \
-          (Current).first_column = (Current).last_column =              \
-            YYRHSLOC (Rhs, 0).last_column;                              \
-        }                                                               \
-    while (YYID (0))
-#endif
-
-# define YYRHSLOC(Rhs, K) ((Rhs)[K].yystate.yyloc)
-
-
-/* YY_LOCATION_PRINT -- Print the location on the stream.
-   This macro was not mandated originally: define only if we know
-   we won't break user code: when these are the locations we know.  */
-
-#ifndef __attribute__
-/* This feature is available in gcc versions 2.5 and later.  */
-# if (! defined __GNUC__ || __GNUC__ < 2 \
-      || (__GNUC__ == 2 && __GNUC_MINOR__ < 5))
-#  define __attribute__(Spec) /* empty */
-# endif
-#endif
-
-#ifndef YY_LOCATION_PRINT
-# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
-
-/* Print *YYLOCP on YYO.  Private, do not rely on its existence. */
-
-__attribute__((__unused__))
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static unsigned
-yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp)
-#else
-static unsigned
-yy_location_print_ (yyo, yylocp)
-    FILE *yyo;
-    YYLTYPE const * const yylocp;
-#endif
-{
-  unsigned res = 0;
-  int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0;
-  if (0 <= yylocp->first_line)
-    {
-      res += fprintf (yyo, "%d", yylocp->first_line);
-      if (0 <= yylocp->first_column)
-        res += fprintf (yyo, ".%d", yylocp->first_column);
-    }
-  if (0 <= yylocp->last_line)
-    {
-      if (yylocp->first_line < yylocp->last_line)
-        {
-          res += fprintf (yyo, "-%d", yylocp->last_line);
-          if (0 <= end_col)
-            res += fprintf (yyo, ".%d", end_col);
-        }
-      else if (0 <= end_col && yylocp->first_column < end_col)
-        res += fprintf (yyo, "-%d", end_col);
-    }
-  return res;
- }
-
-#  define YY_LOCATION_PRINT(File, Loc)          \
-  yy_location_print_ (File, &(Loc))
-
-# else
-#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-# endif
-#endif
-
-
-/* YYLEX -- calling `yylex' with the right arguments.  */
-#define YYLEX yylex (&yylval, &yylloc, scanner)
-
-
-#undef yynerrs
-#define yynerrs (yystackp->yyerrcnt)
-#undef yychar
-#define yychar (yystackp->yyrawchar)
-#undef yylval
-#define yylval (yystackp->yyval)
-#undef yylloc
-#define yylloc (yystackp->yyloc)
-
-
-static const int YYEOF = 0;
-static const int YYEMPTY = -2;
-
-typedef enum { yyok, yyaccept, yyabort, yyerr } YYRESULTTAG;
-
-#define YYCHK(YYE)                                                           \
-   do { YYRESULTTAG yyflag = YYE; if (yyflag != yyok) return yyflag; }       \
-   while (YYID (0))
-
-#if YYDEBUG
-
-# ifndef YYFPRINTF
-#  define YYFPRINTF fprintf
-# endif
-
-# define YYDPRINTF(Args)                        \
-do {                                            \
-  if (yydebug)                                  \
-    YYFPRINTF Args;                             \
-} while (YYID (0))
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-/*ARGSUSED*/
-static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, ParseState* parse_state, yyscan_t scanner)
-{
-  FILE *yyo = yyoutput;
-  YYUSE (yyo);
-  if (!yyvaluep)
-    return;
-  YYUSE (yylocationp);
-  YYUSE (parse_state);
-  YYUSE (scanner);
-# ifdef YYPRINT
-  if (yytype < YYNTOKENS)
-    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
-  YYUSE (yyoutput);
-# endif
-  switch (yytype)
-    {
-      default:
-        break;
-    }
-}
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, ParseState* parse_state, yyscan_t scanner)
-{
-  if (yytype < YYNTOKENS)
-    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-  else
-    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
-
-  YY_LOCATION_PRINT (yyoutput, *yylocationp);
-  YYFPRINTF (yyoutput, ": ");
-  yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, parse_state, scanner);
-  YYFPRINTF (yyoutput, ")");
-}
-
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)          \
-do {                                                            \
-  if (yydebug)                                                  \
-    {                                                           \
-      YYFPRINTF (stderr, "%s ", Title);                         \
-      yy_symbol_print (stderr, Type, Value, Location, parse_state, scanner);        \
-      YYFPRINTF (stderr, "\n");                                 \
-    }                                                           \
-} while (YYID (0))
-
-/* Nonzero means print parse trace.  It is left uninitialized so that
-   multiple parsers can coexist.  */
-int yydebug;
-
-#else /* !YYDEBUG */
-
-# define YYDPRINTF(Args)
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
-
-#endif /* !YYDEBUG */
-
-/* YYINITDEPTH -- initial size of the parser's stacks.  */
-#ifndef YYINITDEPTH
-# define YYINITDEPTH 200
-#endif
-
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
-   if the built-in stack extension method is used).
-
-   Do not make this value too large; the results are undefined if
-   SIZE_MAX < YYMAXDEPTH * sizeof (GLRStackItem)
-   evaluated with infinite-precision integer arithmetic.  */
-
-#ifndef YYMAXDEPTH
-# define YYMAXDEPTH 10000
-#endif
-
-/* Minimum number of free items on the stack allowed after an
-   allocation.  This is to allow allocation and initialization
-   to be completed by functions that call yyexpandGLRStack before the
-   stack is expanded, thus insuring that all necessary pointers get
-   properly redirected to new data.  */
-#define YYHEADROOM 2
-
-#ifndef YYSTACKEXPANDABLE
-# if (! defined __cplusplus \
-      || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \
-          && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))
-#  define YYSTACKEXPANDABLE 1
-# else
-#  define YYSTACKEXPANDABLE 0
-# endif
-#endif
-
-#if YYSTACKEXPANDABLE
-# define YY_RESERVE_GLRSTACK(Yystack)                   \
-  do {                                                  \
-    if (Yystack->yyspaceLeft < YYHEADROOM)              \
-      yyexpandGLRStack (Yystack);                       \
-  } while (YYID (0))
-#else
-# define YY_RESERVE_GLRSTACK(Yystack)                   \
-  do {                                                  \
-    if (Yystack->yyspaceLeft < YYHEADROOM)              \
-      yyMemoryExhausted (Yystack);                      \
-  } while (YYID (0))
-#endif
-
-
-#if YYERROR_VERBOSE
-
-# ifndef yystpcpy
-#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
-#   define yystpcpy stpcpy
-#  else
-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
-   YYDEST.  */
-static char *
-yystpcpy (char *yydest, const char *yysrc)
-{
-  char *yyd = yydest;
-  const char *yys = yysrc;
-
-  while ((*yyd++ = *yys++) != '\0')
-    continue;
-
-  return yyd - 1;
-}
-#  endif
-# endif
-
-# ifndef yytnamerr
-/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
-   quotes and backslashes, so that it's suitable for yyerror.  The
-   heuristic is that double-quoting is unnecessary unless the string
-   contains an apostrophe, a comma, or backslash (other than
-   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
-   null, do not copy; instead, return the length of what the result
-   would have been.  */
-static size_t
-yytnamerr (char *yyres, const char *yystr)
-{
-  if (*yystr == '"')
-    {
-      size_t yyn = 0;
-      char const *yyp = yystr;
-
-      for (;;)
-        switch (*++yyp)
-          {
-          case '\'':
-          case ',':
-            goto do_not_strip_quotes;
-
-          case '\\':
-            if (*++yyp != '\\')
-              goto do_not_strip_quotes;
-            /* Fall through.  */
-          default:
-            if (yyres)
-              yyres[yyn] = *yyp;
-            yyn++;
-            break;
-
-          case '"':
-            if (yyres)
-              yyres[yyn] = '\0';
-            return yyn;
-          }
-    do_not_strip_quotes: ;
-    }
-
-  if (! yyres)
-    return strlen (yystr);
-
-  return yystpcpy (yyres, yystr) - yyres;
-}
-# endif
-
-#endif /* !YYERROR_VERBOSE */
-
-/** State numbers, as in LALR(1) machine */
-typedef int yyStateNum;
-
-/** Rule numbers, as in LALR(1) machine */
-typedef int yyRuleNum;
-
-/** Grammar symbol */
-typedef short int yySymbol;
-
-/** Item references, as in LALR(1) machine */
-typedef short int yyItemNum;
-
-typedef struct yyGLRState yyGLRState;
-typedef struct yyGLRStateSet yyGLRStateSet;
-typedef struct yySemanticOption yySemanticOption;
-typedef union yyGLRStackItem yyGLRStackItem;
-typedef struct yyGLRStack yyGLRStack;
-
-struct yyGLRState {
-  /** Type tag: always true.  */
-  yybool yyisState;
-  /** Type tag for yysemantics.  If true, yysval applies, otherwise
-   *  yyfirstVal applies.  */
-  yybool yyresolved;
-  /** Number of corresponding LALR(1) machine state.  */
-  yyStateNum yylrState;
-  /** Preceding state in this stack */
-  yyGLRState* yypred;
-  /** Source position of the first token produced by my symbol */
-  size_t yyposn;
-  union {
-    /** First in a chain of alternative reductions producing the
-     *  non-terminal corresponding to this state, threaded through
-     *  yynext.  */
-    yySemanticOption* yyfirstVal;
-    /** Semantic value for this state.  */
-    YYSTYPE yysval;
-  } yysemantics;
-  /** Source location for this state.  */
-  YYLTYPE yyloc;
-};
-
-struct yyGLRStateSet {
-  yyGLRState** yystates;
-  /** During nondeterministic operation, yylookaheadNeeds tracks which
-   *  stacks have actually needed the current lookahead.  During deterministic
-   *  operation, yylookaheadNeeds[0] is not maintained since it would merely
-   *  duplicate yychar != YYEMPTY.  */
-  yybool* yylookaheadNeeds;
-  size_t yysize, yycapacity;
-};
-
-struct yySemanticOption {
-  /** Type tag: always false.  */
-  yybool yyisState;
-  /** Rule number for this reduction */
-  yyRuleNum yyrule;
-  /** The last RHS state in the list of states to be reduced.  */
-  yyGLRState* yystate;
-  /** The lookahead for this reduction.  */
-  int yyrawchar;
-  YYSTYPE yyval;
-  YYLTYPE yyloc;
-  /** Next sibling in chain of options.  To facilitate merging,
-   *  options are chained in decreasing order by address.  */
-  yySemanticOption* yynext;
-};
-
-/** Type of the items in the GLR stack.  The yyisState field
- *  indicates which item of the union is valid.  */
-union yyGLRStackItem {
-  yyGLRState yystate;
-  yySemanticOption yyoption;
-};
-
-struct yyGLRStack {
-  int yyerrState;
-  /* To compute the location of the error token.  */
-  yyGLRStackItem yyerror_range[3];
-
-  int yyerrcnt;
-  int yyrawchar;
-  YYSTYPE yyval;
-  YYLTYPE yyloc;
-
-  YYJMP_BUF yyexception_buffer;
-  yyGLRStackItem* yyitems;
-  yyGLRStackItem* yynextFree;
-  size_t yyspaceLeft;
-  yyGLRState* yysplitPoint;
-  yyGLRState* yylastDeleted;
-  yyGLRStateSet yytops;
-};
-
-#if YYSTACKEXPANDABLE
-static void yyexpandGLRStack (yyGLRStack* yystackp);
-#endif
-
-static void yyFail (yyGLRStack* yystackp, YYLTYPE *yylocp, ParseState* parse_state, yyscan_t scanner, const char* yymsg)
-  __attribute__ ((__noreturn__));
-static void
-yyFail (yyGLRStack* yystackp, YYLTYPE *yylocp, ParseState* parse_state, yyscan_t scanner, const char* yymsg)
-{
-  if (yymsg != YY_NULL)
-    yyerror (yylocp, parse_state, scanner, yymsg);
-  YYLONGJMP (yystackp->yyexception_buffer, 1);
-}
-
-static void yyMemoryExhausted (yyGLRStack* yystackp)
-  __attribute__ ((__noreturn__));
-static void
-yyMemoryExhausted (yyGLRStack* yystackp)
-{
-  YYLONGJMP (yystackp->yyexception_buffer, 2);
-}
-
-#if YYDEBUG || YYERROR_VERBOSE
-/** A printable representation of TOKEN.  */
-static inline const char*
-yytokenName (yySymbol yytoken)
-{
-  if (yytoken == YYEMPTY)
-    return "";
-
-  return yytname[yytoken];
-}
-#endif
-
-/** Fill in YYVSP[YYLOW1 .. YYLOW0-1] from the chain of states starting
- *  at YYVSP[YYLOW0].yystate.yypred.  Leaves YYVSP[YYLOW1].yystate.yypred
- *  containing the pointer to the next state in the chain.  */
-static void yyfillin (yyGLRStackItem *, int, int) __attribute__ ((__unused__));
-static void
-yyfillin (yyGLRStackItem *yyvsp, int yylow0, int yylow1)
-{
-  int i;
-  yyGLRState *s = yyvsp[yylow0].yystate.yypred;
-  for (i = yylow0-1; i >= yylow1; i -= 1)
-    {
-      YYASSERT (s->yyresolved);
-      yyvsp[i].yystate.yyresolved = yytrue;
-      yyvsp[i].yystate.yysemantics.yysval = s->yysemantics.yysval;
-      yyvsp[i].yystate.yyloc = s->yyloc;
-      s = yyvsp[i].yystate.yypred = s->yypred;
-    }
-}
-
-/* Do nothing if YYNORMAL or if *YYLOW <= YYLOW1.  Otherwise, fill in
- * YYVSP[YYLOW1 .. *YYLOW-1] as in yyfillin and set *YYLOW = YYLOW1.
- * For convenience, always return YYLOW1.  */
-static inline int yyfill (yyGLRStackItem *, int *, int, yybool)
-     __attribute__ ((__unused__));
-static inline int
-yyfill (yyGLRStackItem *yyvsp, int *yylow, int yylow1, yybool yynormal)
-{
-  if (!yynormal && yylow1 < *yylow)
-    {
-      yyfillin (yyvsp, *yylow, yylow1);
-      *yylow = yylow1;
-    }
-  return yylow1;
-}
-
-/** Perform user action for rule number YYN, with RHS length YYRHSLEN,
- *  and top stack item YYVSP.  YYLVALP points to place to put semantic
- *  value ($$), and yylocp points to place for location information
- *  (@$).  Returns yyok for normal return, yyaccept for YYACCEPT,
- *  yyerr for YYERROR, yyabort for YYABORT.  */
-/*ARGSUSED*/ static YYRESULTTAG
-yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp,
-              yyGLRStack* yystackp,
-              YYSTYPE* yyvalp, YYLTYPE *yylocp, ParseState* parse_state, yyscan_t scanner)
-{
-  yybool yynormal __attribute__ ((__unused__)) =
-    (yystackp->yysplitPoint == YY_NULL);
-  int yylow;
-  YYUSE (parse_state);
-  YYUSE (scanner);
-# undef yyerrok
-# define yyerrok (yystackp->yyerrState = 0)
-# undef YYACCEPT
-# define YYACCEPT return yyaccept
-# undef YYABORT
-# define YYABORT return yyabort
-# undef YYERROR
-# define YYERROR return yyerrok, yyerr
-# undef YYRECOVERING
-# define YYRECOVERING() (yystackp->yyerrState != 0)
-# undef yyclearin
-# define yyclearin (yychar = YYEMPTY)
-# undef YYFILL
-# define YYFILL(N) yyfill (yyvsp, &yylow, N, yynormal)
-# undef YYBACKUP
-# define YYBACKUP(Token, Value)                                              \
-  return yyerror (yylocp, parse_state, scanner, YY_("syntax error: cannot back up")),     \
-         yyerrok, yyerr
-
-  yylow = 1;
-  if (yyrhslen == 0)
-    *yyvalp = yyval_default;
-  else
-    *yyvalp = yyvsp[YYFILL (1-yyrhslen)].yystate.yysemantics.yysval;
-  YYLLOC_DEFAULT ((*yylocp), (yyvsp - yyrhslen), yyrhslen);
-  yystackp->yyerror_range[1].yystate.yyloc = *yylocp;
-
-  switch (yyn)
-    {
-        case 2:
-/* Line 868 of glr.c  */
-#line 277 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { }
-    break;
-
-  case 3:
-/* Line 868 of glr.c  */
-#line 278 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.nodeOption)); }
-    break;
-
-  case 5:
-/* Line 868 of glr.c  */
-#line 283 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_Technique; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (1))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 6:
-/* Line 868 of glr.c  */
-#line 284 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_Parameters; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (1))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 7:
-/* Line 868 of glr.c  */
-#line 285 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_Blocks; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (1))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 8:
-/* Line 868 of glr.c  */
-#line 289 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_Separable; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 9:
-/* Line 868 of glr.c  */
-#line 290 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_Queue; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 10:
-/* Line 868 of glr.c  */
-#line 291 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_Priority; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 11:
-/* Line 868 of glr.c  */
-#line 292 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_Transparent; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 12:
-/* Line 868 of glr.c  */
-#line 298 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodePop(parse_state); ((*yyvalp).nodePtr) = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 13:
-/* Line 868 of glr.c  */
-#line 303 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { 
-			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_Technique); 
-			nodePush(parse_state, ((*yyvalp).nodePtr));
-		}
-    break;
-
-  case 15:
-/* Line 868 of glr.c  */
-#line 311 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.nodeOption)); }
-    break;
-
-  case 17:
-/* Line 868 of glr.c  */
-#line 316 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_Pass; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (1))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 19:
-/* Line 868 of glr.c  */
-#line 318 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_Code; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (1))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 20:
-/* Line 868 of glr.c  */
-#line 322 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_Renderer; ((*yyvalp).nodeOption).value.strValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.strValue); }
-    break;
-
-  case 21:
-/* Line 868 of glr.c  */
-#line 323 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_Language; ((*yyvalp).nodeOption).value.strValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.strValue); }
-    break;
-
-  case 22:
-/* Line 868 of glr.c  */
-#line 329 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodePop(parse_state); ((*yyvalp).nodePtr) = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 23:
-/* Line 868 of glr.c  */
-#line 334 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { 
-			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_Pass); 
-			nodePush(parse_state, ((*yyvalp).nodePtr));
-		}
-    break;
-
-  case 25:
-/* Line 868 of glr.c  */
-#line 342 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.nodeOption)); }
-    break;
-
-  case 27:
-/* Line 868 of glr.c  */
-#line 347 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_Code; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (1))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 28:
-/* Line 868 of glr.c  */
-#line 351 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_Index; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 29:
-/* Line 868 of glr.c  */
-#line 352 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_FillMode; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 30:
-/* Line 868 of glr.c  */
-#line 353 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_CullMode; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 31:
-/* Line 868 of glr.c  */
-#line 354 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_DepthBias; ((*yyvalp).nodeOption).value.floatValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.floatValue); }
-    break;
-
-  case 32:
-/* Line 868 of glr.c  */
-#line 355 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_SDepthBias; ((*yyvalp).nodeOption).value.floatValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.floatValue); }
-    break;
-
-  case 33:
-/* Line 868 of glr.c  */
-#line 356 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_DepthClip; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 34:
-/* Line 868 of glr.c  */
-#line 357 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_Scissor; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 35:
-/* Line 868 of glr.c  */
-#line 358 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_Multisample; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 36:
-/* Line 868 of glr.c  */
-#line 359 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_AALine; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 37:
-/* Line 868 of glr.c  */
-#line 360 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_DepthRead; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 38:
-/* Line 868 of glr.c  */
-#line 361 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_DepthWrite; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 39:
-/* Line 868 of glr.c  */
-#line 362 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_CompareFunc; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 40:
-/* Line 868 of glr.c  */
-#line 363 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_Stencil; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 41:
-/* Line 868 of glr.c  */
-#line 364 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_StencilReadMask; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 42:
-/* Line 868 of glr.c  */
-#line 365 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_StencilWriteMask; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 43:
-/* Line 868 of glr.c  */
-#line 366 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_StencilOpFront; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 44:
-/* Line 868 of glr.c  */
-#line 367 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_StencilOpBack; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 45:
-/* Line 868 of glr.c  */
-#line 368 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_StencilOpFront; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 46:
-/* Line 868 of glr.c  */
-#line 369 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_StencilOpBack; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 47:
-/* Line 868 of glr.c  */
-#line 370 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_AlphaToCoverage; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 48:
-/* Line 868 of glr.c  */
-#line 371 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_IndependantBlend; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 49:
-/* Line 868 of glr.c  */
-#line 372 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_Target; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (1))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 50:
-/* Line 868 of glr.c  */
-#line 373 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_StencilRef; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 51:
-/* Line 868 of glr.c  */
-#line 380 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    {
-		NodeOption index;
-		index.type = OT_Index; 
-		index.value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((5) - (8))].yystate.yysemantics.yysval.intValue);
-
-		nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &index);
-
-		nodePop(parse_state); 
-		((*yyvalp).nodePtr) = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (8))].yystate.yysemantics.yysval.nodePtr);
-	}
-    break;
-
-  case 52:
-/* Line 868 of glr.c  */
-#line 394 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { 
-			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_CodeVertex); 
-			nodePush(parse_state, ((*yyvalp).nodePtr));
-		}
-    break;
-
-  case 53:
-/* Line 868 of glr.c  */
-#line 399 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { 
-			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_CodeFragment); 
-			nodePush(parse_state, ((*yyvalp).nodePtr));
-		}
-    break;
-
-  case 54:
-/* Line 868 of glr.c  */
-#line 404 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { 
-			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_CodeGeometry); 
-			nodePush(parse_state, ((*yyvalp).nodePtr));
-		}
-    break;
-
-  case 55:
-/* Line 868 of glr.c  */
-#line 409 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { 
-			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_CodeHull); 
-			nodePush(parse_state, ((*yyvalp).nodePtr));
-		}
-    break;
-
-  case 56:
-/* Line 868 of glr.c  */
-#line 414 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { 
-			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_CodeDomain); 
-			nodePush(parse_state, ((*yyvalp).nodePtr));
-		}
-    break;
-
-  case 57:
-/* Line 868 of glr.c  */
-#line 419 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { 
-			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_CodeCompute); 
-			nodePush(parse_state, ((*yyvalp).nodePtr));
-		}
-    break;
-
-  case 58:
-/* Line 868 of glr.c  */
-#line 424 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { 
-			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_CodeCommon); 
-			nodePush(parse_state, ((*yyvalp).nodePtr));
-		}
-    break;
-
-  case 59:
-/* Line 868 of glr.c  */
-#line 434 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { 
-			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_StencilOp); 
-			nodePush(parse_state, ((*yyvalp).nodePtr));
-		}
-    break;
-
-  case 60:
-/* Line 868 of glr.c  */
-#line 442 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { 
-			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_StencilOp); 
-			nodePush(parse_state, ((*yyvalp).nodePtr));
-		}
-    break;
-
-  case 61:
-/* Line 868 of glr.c  */
-#line 450 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    {
-			NodeOption fail; fail.type = OT_Fail; fail.value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (7))].yystate.yysemantics.yysval.intValue);
-			NodeOption zfail; zfail.type = OT_ZFail; zfail.value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (7))].yystate.yysemantics.yysval.intValue);
-			NodeOption pass; pass.type = OT_PassOp; pass.value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((5) - (7))].yystate.yysemantics.yysval.intValue);
-			NodeOption cmp; cmp.type = OT_CompareFunc; cmp.value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((7) - (7))].yystate.yysemantics.yysval.intValue);
-
-			nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &fail);
-			nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &zfail);
-			nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &pass);
-			nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &cmp);
-		}
-    break;
-
-  case 63:
-/* Line 868 of glr.c  */
-#line 465 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.nodeOption)); }
-    break;
-
-  case 64:
-/* Line 868 of glr.c  */
-#line 469 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_Fail; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 65:
-/* Line 868 of glr.c  */
-#line 470 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_ZFail; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 66:
-/* Line 868 of glr.c  */
-#line 471 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_PassOp; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 67:
-/* Line 868 of glr.c  */
-#line 472 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_CompareFunc; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 68:
-/* Line 868 of glr.c  */
-#line 477 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodePop(parse_state); ((*yyvalp).nodePtr) = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 69:
-/* Line 868 of glr.c  */
-#line 482 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { 
-			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_Target); 
-			nodePush(parse_state, ((*yyvalp).nodePtr));
-		}
-    break;
-
-  case 71:
-/* Line 868 of glr.c  */
-#line 490 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.nodeOption)); }
-    break;
-
-  case 73:
-/* Line 868 of glr.c  */
-#line 498 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_Index; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 74:
-/* Line 868 of glr.c  */
-#line 499 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_Blend; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 75:
-/* Line 868 of glr.c  */
-#line 500 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Color; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 76:
-/* Line 868 of glr.c  */
-#line 501 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Alpha; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 77:
-/* Line 868 of glr.c  */
-#line 502 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Color; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 78:
-/* Line 868 of glr.c  */
-#line 503 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Alpha; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 79:
-/* Line 868 of glr.c  */
-#line 504 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_WriteMask; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 80:
-/* Line 868 of glr.c  */
-#line 510 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { 
-			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_BlendDef); 
-			nodePush(parse_state, ((*yyvalp).nodePtr));
-		}
-    break;
-
-  case 81:
-/* Line 868 of glr.c  */
-#line 518 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { 
-			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_BlendDef); 
-			nodePush(parse_state, ((*yyvalp).nodePtr));
-		}
-    break;
-
-  case 83:
-/* Line 868 of glr.c  */
-#line 526 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.nodeOption)); }
-    break;
-
-  case 84:
-/* Line 868 of glr.c  */
-#line 531 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    {
-			NodeOption src; src.type = OT_Source; src.value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.intValue);
-			NodeOption dst; dst.type = OT_Dest; dst.value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (5))].yystate.yysemantics.yysval.intValue);
-			NodeOption op; op.type = OT_Op; op.value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((5) - (5))].yystate.yysemantics.yysval.intValue);
-
-			nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &src);
-			nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &dst);
-			nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &op);
-		}
-    break;
-
-  case 85:
-/* Line 868 of glr.c  */
-#line 543 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_Source; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 86:
-/* Line 868 of glr.c  */
-#line 544 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_Dest; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 87:
-/* Line 868 of glr.c  */
-#line 545 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_Op; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 89:
-/* Line 868 of glr.c  */
-#line 552 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.nodeOption)); }
-    break;
-
-  case 90:
-/* Line 868 of glr.c  */
-#line 556 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_AddrMode; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (1))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 91:
-/* Line 868 of glr.c  */
-#line 557 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_MinFilter; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 92:
-/* Line 868 of glr.c  */
-#line 558 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_MagFilter; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 93:
-/* Line 868 of glr.c  */
-#line 559 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_MipFilter; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 94:
-/* Line 868 of glr.c  */
-#line 560 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_MaxAniso; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 95:
-/* Line 868 of glr.c  */
-#line 561 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_MipBias; ((*yyvalp).nodeOption).value.floatValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.floatValue); }
-    break;
-
-  case 96:
-/* Line 868 of glr.c  */
-#line 562 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_MipMin; ((*yyvalp).nodeOption).value.floatValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.floatValue); }
-    break;
-
-  case 97:
-/* Line 868 of glr.c  */
-#line 563 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_MipMax; ((*yyvalp).nodeOption).value.floatValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.floatValue); }
-    break;
-
-  case 98:
-/* Line 868 of glr.c  */
-#line 564 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_BorderColor; memcpy(((*yyvalp).nodeOption).value.matrixValue, (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.matrixValue), sizeof((((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.matrixValue))); }
-    break;
-
-  case 99:
-/* Line 868 of glr.c  */
-#line 565 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_CompareFunc; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 100:
-/* Line 868 of glr.c  */
-#line 570 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodePop(parse_state); ((*yyvalp).nodePtr) = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 101:
-/* Line 868 of glr.c  */
-#line 571 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodePop(parse_state); ((*yyvalp).nodePtr) = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 102:
-/* Line 868 of glr.c  */
-#line 576 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { 
-			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_AddrMode); 
-			nodePush(parse_state, ((*yyvalp).nodePtr));
-		}
-    break;
-
-  case 103:
-/* Line 868 of glr.c  */
-#line 584 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    {
-			NodeOption u; u.type = OT_U; u.value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.intValue);
-			NodeOption v; v.type = OT_V; v.value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (5))].yystate.yysemantics.yysval.intValue);
-			NodeOption w; w.type = OT_W; w.value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((5) - (5))].yystate.yysemantics.yysval.intValue);
-
-			nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &u);
-			nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &v);
-			nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &w);
-		}
-    break;
-
-  case 105:
-/* Line 868 of glr.c  */
-#line 597 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.nodeOption)); }
-    break;
-
-  case 106:
-/* Line 868 of glr.c  */
-#line 601 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_U; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 107:
-/* Line 868 of glr.c  */
-#line 602 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_V; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 108:
-/* Line 868 of glr.c  */
-#line 603 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_W; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 109:
-/* Line 868 of glr.c  */
-#line 608 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).matrixValue)[0] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (5))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[1] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((4) - (5))].yystate.yysemantics.yysval.floatValue); }
-    break;
-
-  case 110:
-/* Line 868 of glr.c  */
-#line 612 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).matrixValue)[0] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (7))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[1] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((4) - (7))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[2] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((6) - (7))].yystate.yysemantics.yysval.floatValue); }
-    break;
-
-  case 111:
-/* Line 868 of glr.c  */
-#line 616 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).matrixValue)[0] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (9))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[1] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((4) - (9))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[2] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((6) - (9))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[3] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((8) - (9))].yystate.yysemantics.yysval.floatValue);}
-    break;
-
-  case 112:
-/* Line 868 of glr.c  */
-#line 620 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).intVectorValue)[0] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (5))].yystate.yysemantics.yysval.intValue); ((*yyvalp).intVectorValue)[1] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((4) - (5))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 113:
-/* Line 868 of glr.c  */
-#line 624 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).intVectorValue)[0] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (7))].yystate.yysemantics.yysval.intValue); ((*yyvalp).intVectorValue)[1] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((4) - (7))].yystate.yysemantics.yysval.intValue); ((*yyvalp).intVectorValue)[2] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((6) - (7))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 114:
-/* Line 868 of glr.c  */
-#line 628 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).intVectorValue)[0] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (9))].yystate.yysemantics.yysval.intValue); ((*yyvalp).intVectorValue)[1] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((4) - (9))].yystate.yysemantics.yysval.intValue); ((*yyvalp).intVectorValue)[2] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((6) - (9))].yystate.yysemantics.yysval.intValue); ((*yyvalp).intVectorValue)[3] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((8) - (9))].yystate.yysemantics.yysval.intValue);}
-    break;
-
-  case 115:
-/* Line 868 of glr.c  */
-#line 634 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { 
-			((*yyvalp).matrixValue)[0] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (13))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[1] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((4) - (13))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[2] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((6) - (13))].yystate.yysemantics.yysval.floatValue); 
-			((*yyvalp).matrixValue)[3] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((8) - (13))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[4] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((10) - (13))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[5] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((12) - (13))].yystate.yysemantics.yysval.floatValue);
-		}
-    break;
-
-  case 116:
-/* Line 868 of glr.c  */
-#line 644 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { 
-			((*yyvalp).matrixValue)[0] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (17))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[1] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((4) - (17))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[2] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((6) - (17))].yystate.yysemantics.yysval.floatValue); 
-			((*yyvalp).matrixValue)[3] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((8) - (17))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[4] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((10) - (17))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[5] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((12) - (17))].yystate.yysemantics.yysval.floatValue);
-			((*yyvalp).matrixValue)[6] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((14) - (17))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[7] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((16) - (17))].yystate.yysemantics.yysval.floatValue);
-		}
-    break;
-
-  case 117:
-/* Line 868 of glr.c  */
-#line 655 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { 
-			((*yyvalp).matrixValue)[0] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (19))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[1] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((4) - (19))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[2] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((6) - (19))].yystate.yysemantics.yysval.floatValue); 
-			((*yyvalp).matrixValue)[3] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((8) - (19))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[4] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((10) - (19))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[5] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((12) - (19))].yystate.yysemantics.yysval.floatValue);
-			((*yyvalp).matrixValue)[6] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((14) - (19))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[7] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((16) - (19))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[8] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((18) - (19))].yystate.yysemantics.yysval.floatValue);
-		}
-    break;
-
-  case 118:
-/* Line 868 of glr.c  */
-#line 666 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { 
-			((*yyvalp).matrixValue)[0] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (25))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[1] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((4) - (25))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[2] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((6) - (25))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[3] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((8) - (25))].yystate.yysemantics.yysval.floatValue); 
-			((*yyvalp).matrixValue)[4] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((10) - (25))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[5] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((12) - (25))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[6] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((14) - (25))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[7] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((16) - (25))].yystate.yysemantics.yysval.floatValue); 
-			((*yyvalp).matrixValue)[8] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((18) - (25))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[9] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((20) - (25))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[10] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((22) - (25))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[11] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((24) - (25))].yystate.yysemantics.yysval.floatValue);
-		}
-    break;
-
-  case 119:
-/* Line 868 of glr.c  */
-#line 678 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { 
-			((*yyvalp).matrixValue)[0] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (33))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[1] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((4) - (33))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[2] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((6) - (33))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[3] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((8) - (33))].yystate.yysemantics.yysval.floatValue); 
-			((*yyvalp).matrixValue)[4] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((10) - (33))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[5] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((12) - (33))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[6] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((14) - (33))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[7] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((16) - (33))].yystate.yysemantics.yysval.floatValue); 
-			((*yyvalp).matrixValue)[8] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((18) - (33))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[9] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((20) - (33))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[10] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((22) - (33))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[11] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((24) - (33))].yystate.yysemantics.yysval.floatValue);
-			((*yyvalp).matrixValue)[12] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((26) - (33))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[13] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((28) - (33))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[14] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((30) - (33))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[15] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((32) - (33))].yystate.yysemantics.yysval.floatValue);
-		}
-    break;
-
-  case 120:
-/* Line 868 of glr.c  */
-#line 688 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodePop(parse_state); ((*yyvalp).nodePtr) = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 121:
-/* Line 868 of glr.c  */
-#line 693 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { 
-			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_Parameters); 
-			nodePush(parse_state, ((*yyvalp).nodePtr));
-		}
-    break;
-
-  case 123:
-/* Line 868 of glr.c  */
-#line 701 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.nodeOption)); }
-    break;
-
-  case 124:
-/* Line 868 of glr.c  */
-#line 705 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 125:
-/* Line 868 of glr.c  */
-#line 706 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 126:
-/* Line 868 of glr.c  */
-#line 707 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 127:
-/* Line 868 of glr.c  */
-#line 708 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 128:
-/* Line 868 of glr.c  */
-#line 709 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 129:
-/* Line 868 of glr.c  */
-#line 710 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 130:
-/* Line 868 of glr.c  */
-#line 711 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 131:
-/* Line 868 of glr.c  */
-#line 712 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 132:
-/* Line 868 of glr.c  */
-#line 713 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 133:
-/* Line 868 of glr.c  */
-#line 714 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 134:
-/* Line 868 of glr.c  */
-#line 715 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 135:
-/* Line 868 of glr.c  */
-#line 716 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 136:
-/* Line 868 of glr.c  */
-#line 717 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 137:
-/* Line 868 of glr.c  */
-#line 718 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 138:
-/* Line 868 of glr.c  */
-#line 719 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 139:
-/* Line 868 of glr.c  */
-#line 720 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 140:
-/* Line 868 of glr.c  */
-#line 721 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 141:
-/* Line 868 of glr.c  */
-#line 722 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 142:
-/* Line 868 of glr.c  */
-#line 723 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 143:
-/* Line 868 of glr.c  */
-#line 724 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (3))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 144:
-/* Line 868 of glr.c  */
-#line 726 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { 
-			nodePop(parse_state);
-
-			NodeOption samplerState;
-			samplerState.type = OT_SamplerState;
-			samplerState.value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (3))].yystate.yysemantics.yysval.nodePtr);
-
-			nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &samplerState); 
-
-			((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = parse_state->topNode; 
-			nodePop(parse_state); 
-		}
-    break;
-
-  case 145:
-/* Line 868 of glr.c  */
-#line 741 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 146:
-/* Line 868 of glr.c  */
-#line 745 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 147:
-/* Line 868 of glr.c  */
-#line 749 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 148:
-/* Line 868 of glr.c  */
-#line 753 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 149:
-/* Line 868 of glr.c  */
-#line 757 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 150:
-/* Line 868 of glr.c  */
-#line 761 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 151:
-/* Line 868 of glr.c  */
-#line 765 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 152:
-/* Line 868 of glr.c  */
-#line 769 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 153:
-/* Line 868 of glr.c  */
-#line 773 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 154:
-/* Line 868 of glr.c  */
-#line 777 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 155:
-/* Line 868 of glr.c  */
-#line 781 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 156:
-/* Line 868 of glr.c  */
-#line 785 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 157:
-/* Line 868 of glr.c  */
-#line 789 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 158:
-/* Line 868 of glr.c  */
-#line 793 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 159:
-/* Line 868 of glr.c  */
-#line 797 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 160:
-/* Line 868 of glr.c  */
-#line 801 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 161:
-/* Line 868 of glr.c  */
-#line 805 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 162:
-/* Line 868 of glr.c  */
-#line 809 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 163:
-/* Line 868 of glr.c  */
-#line 813 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 164:
-/* Line 868 of glr.c  */
-#line 814 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 165:
-/* Line 868 of glr.c  */
-#line 815 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 166:
-/* Line 868 of glr.c  */
-#line 816 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 167:
-/* Line 868 of glr.c  */
-#line 817 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 168:
-/* Line 868 of glr.c  */
-#line 821 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 169:
-/* Line 868 of glr.c  */
-#line 822 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 170:
-/* Line 868 of glr.c  */
-#line 823 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 171:
-/* Line 868 of glr.c  */
-#line 824 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 172:
-/* Line 868 of glr.c  */
-#line 825 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 173:
-/* Line 868 of glr.c  */
-#line 829 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 174:
-/* Line 868 of glr.c  */
-#line 830 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 175:
-/* Line 868 of glr.c  */
-#line 831 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 176:
-/* Line 868 of glr.c  */
-#line 832 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 177:
-/* Line 868 of glr.c  */
-#line 833 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 178:
-/* Line 868 of glr.c  */
-#line 834 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 179:
-/* Line 868 of glr.c  */
-#line 835 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
-    break;
-
-  case 180:
-/* Line 868 of glr.c  */
-#line 840 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { 
-			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_SamplerState); 
-			nodePush(parse_state, ((*yyvalp).nodePtr));
-		}
-    break;
-
-  case 181:
-/* Line 868 of glr.c  */
-#line 847 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_None; }
-    break;
-
-  case 182:
-/* Line 868 of glr.c  */
-#line 848 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_ParamValue; ((*yyvalp).nodeOption).value.floatValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.floatValue); }
-    break;
-
-  case 183:
-/* Line 868 of glr.c  */
-#line 852 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_None; }
-    break;
-
-  case 184:
-/* Line 868 of glr.c  */
-#line 853 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_ParamValue; memcpy(((*yyvalp).nodeOption).value.matrixValue, (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue), sizeof((((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue))); }
-    break;
-
-  case 185:
-/* Line 868 of glr.c  */
-#line 857 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_None; }
-    break;
-
-  case 186:
-/* Line 868 of glr.c  */
-#line 858 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_ParamValue; memcpy(((*yyvalp).nodeOption).value.matrixValue, (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue), sizeof((((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue))); }
-    break;
-
-  case 187:
-/* Line 868 of glr.c  */
-#line 862 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_None; }
-    break;
-
-  case 188:
-/* Line 868 of glr.c  */
-#line 863 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_ParamValue; memcpy(((*yyvalp).nodeOption).value.matrixValue, (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue), sizeof((((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue))); }
-    break;
-
-  case 189:
-/* Line 868 of glr.c  */
-#line 867 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_None; }
-    break;
-
-  case 190:
-/* Line 868 of glr.c  */
-#line 868 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_ParamValue; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 191:
-/* Line 868 of glr.c  */
-#line 872 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_None; }
-    break;
-
-  case 192:
-/* Line 868 of glr.c  */
-#line 873 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_ParamValue; memcpy(((*yyvalp).nodeOption).value.intVectorValue, (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.intVectorValue), sizeof((((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.intVectorValue))); }
-    break;
-
-  case 193:
-/* Line 868 of glr.c  */
-#line 877 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_None; }
-    break;
-
-  case 194:
-/* Line 868 of glr.c  */
-#line 878 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_ParamValue; memcpy(((*yyvalp).nodeOption).value.intVectorValue, (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.intVectorValue), sizeof((((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.intVectorValue))); }
-    break;
-
-  case 195:
-/* Line 868 of glr.c  */
-#line 882 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_None; }
-    break;
-
-  case 196:
-/* Line 868 of glr.c  */
-#line 883 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_ParamValue; memcpy(((*yyvalp).nodeOption).value.intVectorValue, (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.intVectorValue), sizeof((((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.intVectorValue))); }
-    break;
-
-  case 197:
-/* Line 868 of glr.c  */
-#line 887 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_None; }
-    break;
-
-  case 198:
-/* Line 868 of glr.c  */
-#line 888 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_ParamValue; memcpy(((*yyvalp).nodeOption).value.matrixValue, (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue), sizeof((((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue))); }
-    break;
-
-  case 199:
-/* Line 868 of glr.c  */
-#line 892 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_None; }
-    break;
-
-  case 200:
-/* Line 868 of glr.c  */
-#line 893 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_ParamValue; memcpy(((*yyvalp).nodeOption).value.matrixValue, (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue), sizeof((((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue))); }
-    break;
-
-  case 201:
-/* Line 868 of glr.c  */
-#line 897 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_None; }
-    break;
-
-  case 202:
-/* Line 868 of glr.c  */
-#line 898 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_ParamValue; memcpy(((*yyvalp).nodeOption).value.matrixValue, (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue), sizeof((((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue))); }
-    break;
-
-  case 203:
-/* Line 868 of glr.c  */
-#line 902 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_None; }
-    break;
-
-  case 204:
-/* Line 868 of glr.c  */
-#line 903 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_ParamValue; memcpy(((*yyvalp).nodeOption).value.matrixValue, (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue), sizeof((((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue))); }
-    break;
-
-  case 205:
-/* Line 868 of glr.c  */
-#line 907 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_None; }
-    break;
-
-  case 206:
-/* Line 868 of glr.c  */
-#line 908 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_ParamValue; memcpy(((*yyvalp).nodeOption).value.matrixValue, (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue), sizeof((((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue))); }
-    break;
-
-  case 207:
-/* Line 868 of glr.c  */
-#line 912 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_None; }
-    break;
-
-  case 208:
-/* Line 868 of glr.c  */
-#line 913 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { }
-    break;
-
-  case 209:
-/* Line 868 of glr.c  */
-#line 917 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_None; }
-    break;
-
-  case 210:
-/* Line 868 of glr.c  */
-#line 918 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_ParamStrValue; ((*yyvalp).nodeOption).value.strValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue); }
-    break;
-
-  case 211:
-/* Line 868 of glr.c  */
-#line 923 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodePop(parse_state); ((*yyvalp).nodePtr) = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 212:
-/* Line 868 of glr.c  */
-#line 928 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { 
-			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_Blocks); 
-			nodePush(parse_state, ((*yyvalp).nodePtr));
-		}
-    break;
-
-  case 214:
-/* Line 868 of glr.c  */
-#line 936 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.nodeOption)); }
-    break;
-
-  case 215:
-/* Line 868 of glr.c  */
-#line 940 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Block; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (3))].yystate.yysemantics.yysval.nodePtr); }
-    break;
-
-  case 216:
-/* Line 868 of glr.c  */
-#line 945 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    {
-			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_Block);
-			nodePush(parse_state, ((*yyvalp).nodePtr));
-
-			NodeOption blockName;
-			blockName.type = OT_Identifier;
-			blockName.value.strValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue);
-
-			nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &blockName);
-		}
-    break;
-
-  case 218:
-/* Line 868 of glr.c  */
-#line 960 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.nodeOption)); }
-    break;
-
-  case 219:
-/* Line 868 of glr.c  */
-#line 964 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_Alias; ((*yyvalp).nodeOption).value.strValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((4) - (5))].yystate.yysemantics.yysval.strValue); }
-    break;
-
-  case 220:
-/* Line 868 of glr.c  */
-#line 965 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_Auto; ((*yyvalp).nodeOption).value.strValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((4) - (5))].yystate.yysemantics.yysval.strValue); }
-    break;
-
-  case 221:
-/* Line 868 of glr.c  */
-#line 966 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_Shared; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((4) - (5))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-  case 222:
-/* Line 868 of glr.c  */
-#line 967 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_Usage; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((4) - (5))].yystate.yysemantics.yysval.intValue); }
-    break;
-
-
-/* Line 868 of glr.c  */
-#line 2974 "BsParserFX.c"
-      default: break;
-    }
-
-  return yyok;
-# undef yyerrok
-# undef YYABORT
-# undef YYACCEPT
-# undef YYERROR
-# undef YYBACKUP
-# undef yyclearin
-# undef YYRECOVERING
-}
-
-
-/*ARGSUSED*/ static void
-yyuserMerge (int yyn, YYSTYPE* yy0, YYSTYPE* yy1)
-{
-  YYUSE (yy0);
-  YYUSE (yy1);
-
-  switch (yyn)
-    {
-      
-      default: break;
-    }
-}
-
-                              /* Bison grammar-table manipulation.  */
-
-/*-----------------------------------------------.
-| Release the memory associated to this symbol.  |
-`-----------------------------------------------*/
-
-/*ARGSUSED*/
-static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, ParseState* parse_state, yyscan_t scanner)
-{
-  YYUSE (yyvaluep);
-  YYUSE (yylocationp);
-  YYUSE (parse_state);
-  YYUSE (scanner);
-
-  if (!yymsg)
-    yymsg = "Deleting";
-  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
-
-  switch (yytype)
-    {
-
-      default:
-        break;
-    }
-}
-
-/** Number of symbols composing the right hand side of rule #RULE.  */
-static inline int
-yyrhsLength (yyRuleNum yyrule)
-{
-  return yyr2[yyrule];
-}
-
-static void
-yydestroyGLRState (char const *yymsg, yyGLRState *yys, ParseState* parse_state, yyscan_t scanner)
-{
-  if (yys->yyresolved)
-    yydestruct (yymsg, yystos[yys->yylrState],
-                &yys->yysemantics.yysval, &yys->yyloc, parse_state, scanner);
-  else
-    {
-#if YYDEBUG
-      if (yydebug)
-        {
-          if (yys->yysemantics.yyfirstVal)
-            YYFPRINTF (stderr, "%s unresolved ", yymsg);
-          else
-            YYFPRINTF (stderr, "%s incomplete ", yymsg);
-          yy_symbol_print (stderr, yystos[yys->yylrState],
-                           YY_NULL, &yys->yyloc, parse_state, scanner);
-          YYFPRINTF (stderr, "\n");
-        }
-#endif
-
-      if (yys->yysemantics.yyfirstVal)
-        {
-          yySemanticOption *yyoption = yys->yysemantics.yyfirstVal;
-          yyGLRState *yyrh;
-          int yyn;
-          for (yyrh = yyoption->yystate, yyn = yyrhsLength (yyoption->yyrule);
-               yyn > 0;
-               yyrh = yyrh->yypred, yyn -= 1)
-            yydestroyGLRState (yymsg, yyrh, parse_state, scanner);
-        }
-    }
-}
-
-/** Left-hand-side symbol for rule #RULE.  */
-static inline yySymbol
-yylhsNonterm (yyRuleNum yyrule)
-{
-  return yyr1[yyrule];
-}
-
-#define yypact_value_is_default(Yystate) \
-  (!!((Yystate) == (-354)))
-
-/** True iff LR state STATE has only a default reduction (regardless
- *  of token).  */
-static inline yybool
-yyisDefaultedState (yyStateNum yystate)
-{
-  return yypact_value_is_default (yypact[yystate]);
-}
-
-/** The default reduction for STATE, assuming it has one.  */
-static inline yyRuleNum
-yydefaultAction (yyStateNum yystate)
-{
-  return yydefact[yystate];
-}
-
-#define yytable_value_is_error(Yytable_value) \
-  YYID (0)
-
-/** Set *YYACTION to the action to take in YYSTATE on seeing YYTOKEN.
- *  Result R means
- *    R < 0:  Reduce on rule -R.
- *    R = 0:  Error.
- *    R > 0:  Shift to state R.
- *  Set *CONFLICTS to a pointer into yyconfl to 0-terminated list of
- *  conflicting reductions.
- */
-static inline void
-yygetLRActions (yyStateNum yystate, int yytoken,
-                int* yyaction, const short int** yyconflicts)
-{
-  int yyindex = yypact[yystate] + yytoken;
-  if (yypact_value_is_default (yypact[yystate])
-      || yyindex < 0 || YYLAST < yyindex || yycheck[yyindex] != yytoken)
-    {
-      *yyaction = -yydefact[yystate];
-      *yyconflicts = yyconfl;
-    }
-  else if (! yytable_value_is_error (yytable[yyindex]))
-    {
-      *yyaction = yytable[yyindex];
-      *yyconflicts = yyconfl + yyconflp[yyindex];
-    }
-  else
-    {
-      *yyaction = 0;
-      *yyconflicts = yyconfl + yyconflp[yyindex];
-    }
-}
-
-static inline yyStateNum
-yyLRgotoState (yyStateNum yystate, yySymbol yylhs)
-{
-  int yyr;
-  yyr = yypgoto[yylhs - YYNTOKENS] + yystate;
-  if (0 <= yyr && yyr <= YYLAST && yycheck[yyr] == yystate)
-    return yytable[yyr];
-  else
-    return yydefgoto[yylhs - YYNTOKENS];
-}
-
-static inline yybool
-yyisShiftAction (int yyaction)
-{
-  return 0 < yyaction;
-}
-
-static inline yybool
-yyisErrorAction (int yyaction)
-{
-  return yyaction == 0;
-}
-
-                                /* GLRStates */
-
-/** Return a fresh GLRStackItem.  Callers should call
- * YY_RESERVE_GLRSTACK afterwards to make sure there is sufficient
- * headroom.  */
-
-static inline yyGLRStackItem*
-yynewGLRStackItem (yyGLRStack* yystackp, yybool yyisState)
-{
-  yyGLRStackItem* yynewItem = yystackp->yynextFree;
-  yystackp->yyspaceLeft -= 1;
-  yystackp->yynextFree += 1;
-  yynewItem->yystate.yyisState = yyisState;
-  return yynewItem;
-}
-
-/** Add a new semantic action that will execute the action for rule
- *  RULENUM on the semantic values in RHS to the list of
- *  alternative actions for STATE.  Assumes that RHS comes from
- *  stack #K of *STACKP. */
-static void
-yyaddDeferredAction (yyGLRStack* yystackp, size_t yyk, yyGLRState* yystate,
-                     yyGLRState* rhs, yyRuleNum yyrule)
-{
-  yySemanticOption* yynewOption =
-    &yynewGLRStackItem (yystackp, yyfalse)->yyoption;
-  yynewOption->yystate = rhs;
-  yynewOption->yyrule = yyrule;
-  if (yystackp->yytops.yylookaheadNeeds[yyk])
-    {
-      yynewOption->yyrawchar = yychar;
-      yynewOption->yyval = yylval;
-      yynewOption->yyloc = yylloc;
-    }
-  else
-    yynewOption->yyrawchar = YYEMPTY;
-  yynewOption->yynext = yystate->yysemantics.yyfirstVal;
-  yystate->yysemantics.yyfirstVal = yynewOption;
-
-  YY_RESERVE_GLRSTACK (yystackp);
-}
-
-                                /* GLRStacks */
-
-/** Initialize SET to a singleton set containing an empty stack.  */
-static yybool
-yyinitStateSet (yyGLRStateSet* yyset)
-{
-  yyset->yysize = 1;
-  yyset->yycapacity = 16;
-  yyset->yystates = (yyGLRState**) YYMALLOC (16 * sizeof yyset->yystates[0]);
-  if (! yyset->yystates)
-    return yyfalse;
-  yyset->yystates[0] = YY_NULL;
-  yyset->yylookaheadNeeds =
-    (yybool*) YYMALLOC (16 * sizeof yyset->yylookaheadNeeds[0]);
-  if (! yyset->yylookaheadNeeds)
-    {
-      YYFREE (yyset->yystates);
-      return yyfalse;
-    }
-  return yytrue;
-}
-
-static void yyfreeStateSet (yyGLRStateSet* yyset)
-{
-  YYFREE (yyset->yystates);
-  YYFREE (yyset->yylookaheadNeeds);
-}
-
-/** Initialize STACK to a single empty stack, with total maximum
- *  capacity for all stacks of SIZE.  */
-static yybool
-yyinitGLRStack (yyGLRStack* yystackp, size_t yysize)
-{
-  yystackp->yyerrState = 0;
-  yynerrs = 0;
-  yystackp->yyspaceLeft = yysize;
-  yystackp->yyitems =
-    (yyGLRStackItem*) YYMALLOC (yysize * sizeof yystackp->yynextFree[0]);
-  if (!yystackp->yyitems)
-    return yyfalse;
-  yystackp->yynextFree = yystackp->yyitems;
-  yystackp->yysplitPoint = YY_NULL;
-  yystackp->yylastDeleted = YY_NULL;
-  return yyinitStateSet (&yystackp->yytops);
-}
-
-
-#if YYSTACKEXPANDABLE
-# define YYRELOC(YYFROMITEMS,YYTOITEMS,YYX,YYTYPE) \
-  &((YYTOITEMS) - ((YYFROMITEMS) - (yyGLRStackItem*) (YYX)))->YYTYPE
-
-/** If STACK is expandable, extend it.  WARNING: Pointers into the
-    stack from outside should be considered invalid after this call.
-    We always expand when there are 1 or fewer items left AFTER an
-    allocation, so that we can avoid having external pointers exist
-    across an allocation.  */
-static void
-yyexpandGLRStack (yyGLRStack* yystackp)
-{
-  yyGLRStackItem* yynewItems;
-  yyGLRStackItem* yyp0, *yyp1;
-  size_t yynewSize;
-  size_t yyn;
-  size_t yysize = yystackp->yynextFree - yystackp->yyitems;
-  if (YYMAXDEPTH - YYHEADROOM < yysize)
-    yyMemoryExhausted (yystackp);
-  yynewSize = 2*yysize;
-  if (YYMAXDEPTH < yynewSize)
-    yynewSize = YYMAXDEPTH;
-  yynewItems = (yyGLRStackItem*) YYMALLOC (yynewSize * sizeof yynewItems[0]);
-  if (! yynewItems)
-    yyMemoryExhausted (yystackp);
-  for (yyp0 = yystackp->yyitems, yyp1 = yynewItems, yyn = yysize;
-       0 < yyn;
-       yyn -= 1, yyp0 += 1, yyp1 += 1)
-    {
-      *yyp1 = *yyp0;
-      if (*(yybool *) yyp0)
-        {
-          yyGLRState* yys0 = &yyp0->yystate;
-          yyGLRState* yys1 = &yyp1->yystate;
-          if (yys0->yypred != YY_NULL)
-            yys1->yypred =
-              YYRELOC (yyp0, yyp1, yys0->yypred, yystate);
-          if (! yys0->yyresolved && yys0->yysemantics.yyfirstVal != YY_NULL)
-            yys1->yysemantics.yyfirstVal =
-              YYRELOC (yyp0, yyp1, yys0->yysemantics.yyfirstVal, yyoption);
-        }
-      else
-        {
-          yySemanticOption* yyv0 = &yyp0->yyoption;
-          yySemanticOption* yyv1 = &yyp1->yyoption;
-          if (yyv0->yystate != YY_NULL)
-            yyv1->yystate = YYRELOC (yyp0, yyp1, yyv0->yystate, yystate);
-          if (yyv0->yynext != YY_NULL)
-            yyv1->yynext = YYRELOC (yyp0, yyp1, yyv0->yynext, yyoption);
-        }
-    }
-  if (yystackp->yysplitPoint != YY_NULL)
-    yystackp->yysplitPoint = YYRELOC (yystackp->yyitems, yynewItems,
-                                 yystackp->yysplitPoint, yystate);
-
-  for (yyn = 0; yyn < yystackp->yytops.yysize; yyn += 1)
-    if (yystackp->yytops.yystates[yyn] != YY_NULL)
-      yystackp->yytops.yystates[yyn] =
-        YYRELOC (yystackp->yyitems, yynewItems,
-                 yystackp->yytops.yystates[yyn], yystate);
-  YYFREE (yystackp->yyitems);
-  yystackp->yyitems = yynewItems;
-  yystackp->yynextFree = yynewItems + yysize;
-  yystackp->yyspaceLeft = yynewSize - yysize;
-}
-#endif
-
-static void
-yyfreeGLRStack (yyGLRStack* yystackp)
-{
-  YYFREE (yystackp->yyitems);
-  yyfreeStateSet (&yystackp->yytops);
-}
-
-/** Assuming that S is a GLRState somewhere on STACK, update the
- *  splitpoint of STACK, if needed, so that it is at least as deep as
- *  S.  */
-static inline void
-yyupdateSplit (yyGLRStack* yystackp, yyGLRState* yys)
-{
-  if (yystackp->yysplitPoint != YY_NULL && yystackp->yysplitPoint > yys)
-    yystackp->yysplitPoint = yys;
-}
-
-/** Invalidate stack #K in STACK.  */
-static inline void
-yymarkStackDeleted (yyGLRStack* yystackp, size_t yyk)
-{
-  if (yystackp->yytops.yystates[yyk] != YY_NULL)
-    yystackp->yylastDeleted = yystackp->yytops.yystates[yyk];
-  yystackp->yytops.yystates[yyk] = YY_NULL;
-}
-
-/** Undelete the last stack that was marked as deleted.  Can only be
-    done once after a deletion, and only when all other stacks have
-    been deleted.  */
-static void
-yyundeleteLastStack (yyGLRStack* yystackp)
-{
-  if (yystackp->yylastDeleted == YY_NULL || yystackp->yytops.yysize != 0)
-    return;
-  yystackp->yytops.yystates[0] = yystackp->yylastDeleted;
-  yystackp->yytops.yysize = 1;
-  YYDPRINTF ((stderr, "Restoring last deleted stack as stack #0.\n"));
-  yystackp->yylastDeleted = YY_NULL;
-}
-
-static inline void
-yyremoveDeletes (yyGLRStack* yystackp)
-{
-  size_t yyi, yyj;
-  yyi = yyj = 0;
-  while (yyj < yystackp->yytops.yysize)
-    {
-      if (yystackp->yytops.yystates[yyi] == YY_NULL)
-        {
-          if (yyi == yyj)
-            {
-              YYDPRINTF ((stderr, "Removing dead stacks.\n"));
-            }
-          yystackp->yytops.yysize -= 1;
-        }
-      else
-        {
-          yystackp->yytops.yystates[yyj] = yystackp->yytops.yystates[yyi];
-          /* In the current implementation, it's unnecessary to copy
-             yystackp->yytops.yylookaheadNeeds[yyi] since, after
-             yyremoveDeletes returns, the parser immediately either enters
-             deterministic operation or shifts a token.  However, it doesn't
-             hurt, and the code might evolve to need it.  */
-          yystackp->yytops.yylookaheadNeeds[yyj] =
-            yystackp->yytops.yylookaheadNeeds[yyi];
-          if (yyj != yyi)
-            {
-              YYDPRINTF ((stderr, "Rename stack %lu -> %lu.\n",
-                          (unsigned long int) yyi, (unsigned long int) yyj));
-            }
-          yyj += 1;
-        }
-      yyi += 1;
-    }
-}
-
-/** Shift to a new state on stack #K of STACK, corresponding to LR state
- * LRSTATE, at input position POSN, with (resolved) semantic value SVAL.  */
-static inline void
-yyglrShift (yyGLRStack* yystackp, size_t yyk, yyStateNum yylrState,
-            size_t yyposn,
-            YYSTYPE* yyvalp, YYLTYPE* yylocp)
-{
-  yyGLRState* yynewState = &yynewGLRStackItem (yystackp, yytrue)->yystate;
-
-  yynewState->yylrState = yylrState;
-  yynewState->yyposn = yyposn;
-  yynewState->yyresolved = yytrue;
-  yynewState->yypred = yystackp->yytops.yystates[yyk];
-  yynewState->yysemantics.yysval = *yyvalp;
-  yynewState->yyloc = *yylocp;
-  yystackp->yytops.yystates[yyk] = yynewState;
-
-  YY_RESERVE_GLRSTACK (yystackp);
-}
-
-/** Shift stack #K of YYSTACK, to a new state corresponding to LR
- *  state YYLRSTATE, at input position YYPOSN, with the (unresolved)
- *  semantic value of YYRHS under the action for YYRULE.  */
-static inline void
-yyglrShiftDefer (yyGLRStack* yystackp, size_t yyk, yyStateNum yylrState,
-                 size_t yyposn, yyGLRState* rhs, yyRuleNum yyrule)
-{
-  yyGLRState* yynewState = &yynewGLRStackItem (yystackp, yytrue)->yystate;
-
-  yynewState->yylrState = yylrState;
-  yynewState->yyposn = yyposn;
-  yynewState->yyresolved = yyfalse;
-  yynewState->yypred = yystackp->yytops.yystates[yyk];
-  yynewState->yysemantics.yyfirstVal = YY_NULL;
-  yystackp->yytops.yystates[yyk] = yynewState;
-
-  /* Invokes YY_RESERVE_GLRSTACK.  */
-  yyaddDeferredAction (yystackp, yyk, yynewState, rhs, yyrule);
-}
-
-/** Pop the symbols consumed by reduction #RULE from the top of stack
- *  #K of STACK, and perform the appropriate semantic action on their
- *  semantic values.  Assumes that all ambiguities in semantic values
- *  have been previously resolved.  Set *VALP to the resulting value,
- *  and *LOCP to the computed location (if any).  Return value is as
- *  for userAction.  */
-static inline YYRESULTTAG
-yydoAction (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
-            YYSTYPE* yyvalp, YYLTYPE *yylocp, ParseState* parse_state, yyscan_t scanner)
-{
-  int yynrhs = yyrhsLength (yyrule);
-
-  if (yystackp->yysplitPoint == YY_NULL)
-    {
-      /* Standard special case: single stack.  */
-      yyGLRStackItem* rhs = (yyGLRStackItem*) yystackp->yytops.yystates[yyk];
-      YYASSERT (yyk == 0);
-      yystackp->yynextFree -= yynrhs;
-      yystackp->yyspaceLeft += yynrhs;
-      yystackp->yytops.yystates[0] = & yystackp->yynextFree[-1].yystate;
-      return yyuserAction (yyrule, yynrhs, rhs, yystackp,
-                           yyvalp, yylocp, parse_state, scanner);
-    }
-  else
-    {
-      /* At present, doAction is never called in nondeterministic
-       * mode, so this branch is never taken.  It is here in
-       * anticipation of a future feature that will allow immediate
-       * evaluation of selected actions in nondeterministic mode.  */
-      int yyi;
-      yyGLRState* yys;
-      yyGLRStackItem yyrhsVals[YYMAXRHS + YYMAXLEFT + 1];
-      yys = yyrhsVals[YYMAXRHS + YYMAXLEFT].yystate.yypred
-        = yystackp->yytops.yystates[yyk];
-      if (yynrhs == 0)
-        /* Set default location.  */
-        yyrhsVals[YYMAXRHS + YYMAXLEFT - 1].yystate.yyloc = yys->yyloc;
-      for (yyi = 0; yyi < yynrhs; yyi += 1)
-        {
-          yys = yys->yypred;
-          YYASSERT (yys);
-        }
-      yyupdateSplit (yystackp, yys);
-      yystackp->yytops.yystates[yyk] = yys;
-      return yyuserAction (yyrule, yynrhs, yyrhsVals + YYMAXRHS + YYMAXLEFT - 1,
-                           yystackp, yyvalp, yylocp, parse_state, scanner);
-    }
-}
-
-#if !YYDEBUG
-# define YY_REDUCE_PRINT(Args)
-#else
-# define YY_REDUCE_PRINT(Args)          \
-do {                                    \
-  if (yydebug)                          \
-    yy_reduce_print Args;               \
-} while (YYID (0))
-
-/*----------------------------------------------------------.
-| Report that the RULE is going to be reduced on stack #K.  |
-`----------------------------------------------------------*/
-
-/*ARGSUSED*/ static inline void
-yy_reduce_print (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
-                 YYSTYPE* yyvalp, YYLTYPE *yylocp, ParseState* parse_state, yyscan_t scanner)
-{
-  int yynrhs = yyrhsLength (yyrule);
-  yybool yynormal __attribute__ ((__unused__)) =
-    (yystackp->yysplitPoint == YY_NULL);
-  yyGLRStackItem* yyvsp = (yyGLRStackItem*) yystackp->yytops.yystates[yyk];
-  int yylow = 1;
-  int yyi;
-  YYUSE (yyvalp);
-  YYUSE (yylocp);
-  YYUSE (parse_state);
-  YYUSE (scanner);
-  YYFPRINTF (stderr, "Reducing stack %lu by rule %d (line %lu):\n",
-             (unsigned long int) yyk, yyrule - 1,
-             (unsigned long int) yyrline[yyrule]);
-  /* The symbols being reduced.  */
-  for (yyi = 0; yyi < yynrhs; yyi++)
-    {
-      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
-      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
-                       &(((yyGLRStackItem const *)yyvsp)[YYFILL ((yyi + 1) - (yynrhs))].yystate.yysemantics.yysval)
-                       , &(((yyGLRStackItem const *)yyvsp)[YYFILL ((yyi + 1) - (yynrhs))].yystate.yyloc)                       , parse_state, scanner);
-      YYFPRINTF (stderr, "\n");
-    }
-}
-#endif
-
-/** Pop items off stack #K of STACK according to grammar rule RULE,
- *  and push back on the resulting nonterminal symbol.  Perform the
- *  semantic action associated with RULE and store its value with the
- *  newly pushed state, if FORCEEVAL or if STACK is currently
- *  unambiguous.  Otherwise, store the deferred semantic action with
- *  the new state.  If the new state would have an identical input
- *  position, LR state, and predecessor to an existing state on the stack,
- *  it is identified with that existing state, eliminating stack #K from
- *  the STACK.  In this case, the (necessarily deferred) semantic value is
- *  added to the options for the existing state's semantic value.
- */
-static inline YYRESULTTAG
-yyglrReduce (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
-             yybool yyforceEval, ParseState* parse_state, yyscan_t scanner)
-{
-  size_t yyposn = yystackp->yytops.yystates[yyk]->yyposn;
-
-  if (yyforceEval || yystackp->yysplitPoint == YY_NULL)
-    {
-      YYSTYPE yysval;
-      YYLTYPE yyloc;
-
-      YY_REDUCE_PRINT ((yystackp, yyk, yyrule, &yysval, &yyloc, parse_state, scanner));
-      YYCHK (yydoAction (yystackp, yyk, yyrule, &yysval, &yyloc, parse_state, scanner));
-      YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyrule], &yysval, &yyloc);
-      yyglrShift (yystackp, yyk,
-                  yyLRgotoState (yystackp->yytops.yystates[yyk]->yylrState,
-                                 yylhsNonterm (yyrule)),
-                  yyposn, &yysval, &yyloc);
-    }
-  else
-    {
-      size_t yyi;
-      int yyn;
-      yyGLRState* yys, *yys0 = yystackp->yytops.yystates[yyk];
-      yyStateNum yynewLRState;
-
-      for (yys = yystackp->yytops.yystates[yyk], yyn = yyrhsLength (yyrule);
-           0 < yyn; yyn -= 1)
-        {
-          yys = yys->yypred;
-          YYASSERT (yys);
-        }
-      yyupdateSplit (yystackp, yys);
-      yynewLRState = yyLRgotoState (yys->yylrState, yylhsNonterm (yyrule));
-      YYDPRINTF ((stderr,
-                  "Reduced stack %lu by rule #%d; action deferred.  Now in state %d.\n",
-                  (unsigned long int) yyk, yyrule - 1, yynewLRState));
-      for (yyi = 0; yyi < yystackp->yytops.yysize; yyi += 1)
-        if (yyi != yyk && yystackp->yytops.yystates[yyi] != YY_NULL)
-          {
-            yyGLRState *yysplit = yystackp->yysplitPoint;
-            yyGLRState *yyp = yystackp->yytops.yystates[yyi];
-            while (yyp != yys && yyp != yysplit && yyp->yyposn >= yyposn)
-              {
-                if (yyp->yylrState == yynewLRState && yyp->yypred == yys)
-                  {
-                    yyaddDeferredAction (yystackp, yyk, yyp, yys0, yyrule);
-                    yymarkStackDeleted (yystackp, yyk);
-                    YYDPRINTF ((stderr, "Merging stack %lu into stack %lu.\n",
-                                (unsigned long int) yyk,
-                                (unsigned long int) yyi));
-                    return yyok;
-                  }
-                yyp = yyp->yypred;
-              }
-          }
-      yystackp->yytops.yystates[yyk] = yys;
-      yyglrShiftDefer (yystackp, yyk, yynewLRState, yyposn, yys0, yyrule);
-    }
-  return yyok;
-}
-
-static size_t
-yysplitStack (yyGLRStack* yystackp, size_t yyk)
-{
-  if (yystackp->yysplitPoint == YY_NULL)
-    {
-      YYASSERT (yyk == 0);
-      yystackp->yysplitPoint = yystackp->yytops.yystates[yyk];
-    }
-  if (yystackp->yytops.yysize >= yystackp->yytops.yycapacity)
-    {
-      yyGLRState** yynewStates;
-      yybool* yynewLookaheadNeeds;
-
-      yynewStates = YY_NULL;
-
-      if (yystackp->yytops.yycapacity
-          > (YYSIZEMAX / (2 * sizeof yynewStates[0])))
-        yyMemoryExhausted (yystackp);
-      yystackp->yytops.yycapacity *= 2;
-
-      yynewStates =
-        (yyGLRState**) YYREALLOC (yystackp->yytops.yystates,
-                                  (yystackp->yytops.yycapacity
-                                   * sizeof yynewStates[0]));
-      if (yynewStates == YY_NULL)
-        yyMemoryExhausted (yystackp);
-      yystackp->yytops.yystates = yynewStates;
-
-      yynewLookaheadNeeds =
-        (yybool*) YYREALLOC (yystackp->yytops.yylookaheadNeeds,
-                             (yystackp->yytops.yycapacity
-                              * sizeof yynewLookaheadNeeds[0]));
-      if (yynewLookaheadNeeds == YY_NULL)
-        yyMemoryExhausted (yystackp);
-      yystackp->yytops.yylookaheadNeeds = yynewLookaheadNeeds;
-    }
-  yystackp->yytops.yystates[yystackp->yytops.yysize]
-    = yystackp->yytops.yystates[yyk];
-  yystackp->yytops.yylookaheadNeeds[yystackp->yytops.yysize]
-    = yystackp->yytops.yylookaheadNeeds[yyk];
-  yystackp->yytops.yysize += 1;
-  return yystackp->yytops.yysize-1;
-}
-
-/** True iff Y0 and Y1 represent identical options at the top level.
- *  That is, they represent the same rule applied to RHS symbols
- *  that produce the same terminal symbols.  */
-static yybool
-yyidenticalOptions (yySemanticOption* yyy0, yySemanticOption* yyy1)
-{
-  if (yyy0->yyrule == yyy1->yyrule)
-    {
-      yyGLRState *yys0, *yys1;
-      int yyn;
-      for (yys0 = yyy0->yystate, yys1 = yyy1->yystate,
-           yyn = yyrhsLength (yyy0->yyrule);
-           yyn > 0;
-           yys0 = yys0->yypred, yys1 = yys1->yypred, yyn -= 1)
-        if (yys0->yyposn != yys1->yyposn)
-          return yyfalse;
-      return yytrue;
-    }
-  else
-    return yyfalse;
-}
-
-/** Assuming identicalOptions (Y0,Y1), destructively merge the
- *  alternative semantic values for the RHS-symbols of Y1 and Y0.  */
-static void
-yymergeOptionSets (yySemanticOption* yyy0, yySemanticOption* yyy1)
-{
-  yyGLRState *yys0, *yys1;
-  int yyn;
-  for (yys0 = yyy0->yystate, yys1 = yyy1->yystate,
-       yyn = yyrhsLength (yyy0->yyrule);
-       yyn > 0;
-       yys0 = yys0->yypred, yys1 = yys1->yypred, yyn -= 1)
-    {
-      if (yys0 == yys1)
-        break;
-      else if (yys0->yyresolved)
-        {
-          yys1->yyresolved = yytrue;
-          yys1->yysemantics.yysval = yys0->yysemantics.yysval;
-        }
-      else if (yys1->yyresolved)
-        {
-          yys0->yyresolved = yytrue;
-          yys0->yysemantics.yysval = yys1->yysemantics.yysval;
-        }
-      else
-        {
-          yySemanticOption** yyz0p = &yys0->yysemantics.yyfirstVal;
-          yySemanticOption* yyz1 = yys1->yysemantics.yyfirstVal;
-          while (YYID (yytrue))
-            {
-              if (yyz1 == *yyz0p || yyz1 == YY_NULL)
-                break;
-              else if (*yyz0p == YY_NULL)
-                {
-                  *yyz0p = yyz1;
-                  break;
-                }
-              else if (*yyz0p < yyz1)
-                {
-                  yySemanticOption* yyz = *yyz0p;
-                  *yyz0p = yyz1;
-                  yyz1 = yyz1->yynext;
-                  (*yyz0p)->yynext = yyz;
-                }
-              yyz0p = &(*yyz0p)->yynext;
-            }
-          yys1->yysemantics.yyfirstVal = yys0->yysemantics.yyfirstVal;
-        }
-    }
-}
-
-/** Y0 and Y1 represent two possible actions to take in a given
- *  parsing state; return 0 if no combination is possible,
- *  1 if user-mergeable, 2 if Y0 is preferred, 3 if Y1 is preferred.  */
-static int
-yypreference (yySemanticOption* y0, yySemanticOption* y1)
-{
-  yyRuleNum r0 = y0->yyrule, r1 = y1->yyrule;
-  int p0 = yydprec[r0], p1 = yydprec[r1];
-
-  if (p0 == p1)
-    {
-      if (yymerger[r0] == 0 || yymerger[r0] != yymerger[r1])
-        return 0;
-      else
-        return 1;
-    }
-  if (p0 == 0 || p1 == 0)
-    return 0;
-  if (p0 < p1)
-    return 3;
-  if (p1 < p0)
-    return 2;
-  return 0;
-}
-
-static YYRESULTTAG yyresolveValue (yyGLRState* yys,
-                                   yyGLRStack* yystackp, ParseState* parse_state, yyscan_t scanner);
-
-
-/** Resolve the previous N states starting at and including state S.  If result
- *  != yyok, some states may have been left unresolved possibly with empty
- *  semantic option chains.  Regardless of whether result = yyok, each state
- *  has been left with consistent data so that yydestroyGLRState can be invoked
- *  if necessary.  */
-static YYRESULTTAG
-yyresolveStates (yyGLRState* yys, int yyn,
-                 yyGLRStack* yystackp, ParseState* parse_state, yyscan_t scanner)
-{
-  if (0 < yyn)
-    {
-      YYASSERT (yys->yypred);
-      YYCHK (yyresolveStates (yys->yypred, yyn-1, yystackp, parse_state, scanner));
-      if (! yys->yyresolved)
-        YYCHK (yyresolveValue (yys, yystackp, parse_state, scanner));
-    }
-  return yyok;
-}
-
-/** Resolve the states for the RHS of OPT, perform its user action, and return
- *  the semantic value and location.  Regardless of whether result = yyok, all
- *  RHS states have been destroyed (assuming the user action destroys all RHS
- *  semantic values if invoked).  */
-static YYRESULTTAG
-yyresolveAction (yySemanticOption* yyopt, yyGLRStack* yystackp,
-                 YYSTYPE* yyvalp, YYLTYPE *yylocp, ParseState* parse_state, yyscan_t scanner)
-{
-  yyGLRStackItem yyrhsVals[YYMAXRHS + YYMAXLEFT + 1];
-  int yynrhs = yyrhsLength (yyopt->yyrule);
-  YYRESULTTAG yyflag =
-    yyresolveStates (yyopt->yystate, yynrhs, yystackp, parse_state, scanner);
-  if (yyflag != yyok)
-    {
-      yyGLRState *yys;
-      for (yys = yyopt->yystate; yynrhs > 0; yys = yys->yypred, yynrhs -= 1)
-        yydestroyGLRState ("Cleanup: popping", yys, parse_state, scanner);
-      return yyflag;
-    }
-
-  yyrhsVals[YYMAXRHS + YYMAXLEFT].yystate.yypred = yyopt->yystate;
-  if (yynrhs == 0)
-    /* Set default location.  */
-    yyrhsVals[YYMAXRHS + YYMAXLEFT - 1].yystate.yyloc = yyopt->yystate->yyloc;
-  {
-    int yychar_current = yychar;
-    YYSTYPE yylval_current = yylval;
-    YYLTYPE yylloc_current = yylloc;
-    yychar = yyopt->yyrawchar;
-    yylval = yyopt->yyval;
-    yylloc = yyopt->yyloc;
-    yyflag = yyuserAction (yyopt->yyrule, yynrhs,
-                           yyrhsVals + YYMAXRHS + YYMAXLEFT - 1,
-                           yystackp, yyvalp, yylocp, parse_state, scanner);
-    yychar = yychar_current;
-    yylval = yylval_current;
-    yylloc = yylloc_current;
-  }
-  return yyflag;
-}
-
-#if YYDEBUG
-static void
-yyreportTree (yySemanticOption* yyx, int yyindent)
-{
-  int yynrhs = yyrhsLength (yyx->yyrule);
-  int yyi;
-  yyGLRState* yys;
-  yyGLRState* yystates[1 + YYMAXRHS];
-  yyGLRState yyleftmost_state;
-
-  for (yyi = yynrhs, yys = yyx->yystate; 0 < yyi; yyi -= 1, yys = yys->yypred)
-    yystates[yyi] = yys;
-  if (yys == YY_NULL)
-    {
-      yyleftmost_state.yyposn = 0;
-      yystates[0] = &yyleftmost_state;
-    }
-  else
-    yystates[0] = yys;
-
-  if (yyx->yystate->yyposn < yys->yyposn + 1)
-    YYFPRINTF (stderr, "%*s%s -> <Rule %d, empty>\n",
-               yyindent, "", yytokenName (yylhsNonterm (yyx->yyrule)),
-               yyx->yyrule - 1);
-  else
-    YYFPRINTF (stderr, "%*s%s -> <Rule %d, tokens %lu .. %lu>\n",
-               yyindent, "", yytokenName (yylhsNonterm (yyx->yyrule)),
-               yyx->yyrule - 1, (unsigned long int) (yys->yyposn + 1),
-               (unsigned long int) yyx->yystate->yyposn);
-  for (yyi = 1; yyi <= yynrhs; yyi += 1)
-    {
-      if (yystates[yyi]->yyresolved)
-        {
-          if (yystates[yyi-1]->yyposn+1 > yystates[yyi]->yyposn)
-            YYFPRINTF (stderr, "%*s%s <empty>\n", yyindent+2, "",
-                       yytokenName (yyrhs[yyprhs[yyx->yyrule]+yyi-1]));
-          else
-            YYFPRINTF (stderr, "%*s%s <tokens %lu .. %lu>\n", yyindent+2, "",
-                       yytokenName (yyrhs[yyprhs[yyx->yyrule]+yyi-1]),
-                       (unsigned long int) (yystates[yyi - 1]->yyposn + 1),
-                       (unsigned long int) yystates[yyi]->yyposn);
-        }
-      else
-        yyreportTree (yystates[yyi]->yysemantics.yyfirstVal, yyindent+2);
-    }
-}
-#endif
-
-/*ARGSUSED*/ static YYRESULTTAG
-yyreportAmbiguity (yySemanticOption* yyx0,
-                   yySemanticOption* yyx1, YYLTYPE *yylocp, ParseState* parse_state, yyscan_t scanner)
-{
-  YYUSE (yyx0);
-  YYUSE (yyx1);
-
-#if YYDEBUG
-  YYFPRINTF (stderr, "Ambiguity detected.\n");
-  YYFPRINTF (stderr, "Option 1,\n");
-  yyreportTree (yyx0, 2);
-  YYFPRINTF (stderr, "\nOption 2,\n");
-  yyreportTree (yyx1, 2);
-  YYFPRINTF (stderr, "\n");
-#endif
-
-  yyerror (yylocp, parse_state, scanner, YY_("syntax is ambiguous"));
-  return yyabort;
-}
-
-/** Starting at and including state S1, resolve the location for each of the
- *  previous N1 states that is unresolved.  The first semantic option of a state
- *  is always chosen.  */
-static void
-yyresolveLocations (yyGLRState* yys1, int yyn1,
-                    yyGLRStack *yystackp, ParseState* parse_state, yyscan_t scanner)
-{
-  if (0 < yyn1)
-    {
-      yyresolveLocations (yys1->yypred, yyn1 - 1, yystackp, parse_state, scanner);
-      if (!yys1->yyresolved)
-        {
-          yyGLRStackItem yyrhsloc[1 + YYMAXRHS];
-          int yynrhs;
-          yySemanticOption *yyoption = yys1->yysemantics.yyfirstVal;
-          YYASSERT (yyoption != YY_NULL);
-          yynrhs = yyrhsLength (yyoption->yyrule);
-          if (yynrhs > 0)
-            {
-              yyGLRState *yys;
-              int yyn;
-              yyresolveLocations (yyoption->yystate, yynrhs,
-                                  yystackp, parse_state, scanner);
-              for (yys = yyoption->yystate, yyn = yynrhs;
-                   yyn > 0;
-                   yys = yys->yypred, yyn -= 1)
-                yyrhsloc[yyn].yystate.yyloc = yys->yyloc;
-            }
-          else
-            {
-              /* Both yyresolveAction and yyresolveLocations traverse the GSS
-                 in reverse rightmost order.  It is only necessary to invoke
-                 yyresolveLocations on a subforest for which yyresolveAction
-                 would have been invoked next had an ambiguity not been
-                 detected.  Thus the location of the previous state (but not
-                 necessarily the previous state itself) is guaranteed to be
-                 resolved already.  */
-              yyGLRState *yyprevious = yyoption->yystate;
-              yyrhsloc[0].yystate.yyloc = yyprevious->yyloc;
-            }
-          {
-            int yychar_current = yychar;
-            YYSTYPE yylval_current = yylval;
-            YYLTYPE yylloc_current = yylloc;
-            yychar = yyoption->yyrawchar;
-            yylval = yyoption->yyval;
-            yylloc = yyoption->yyloc;
-            YYLLOC_DEFAULT ((yys1->yyloc), yyrhsloc, yynrhs);
-            yychar = yychar_current;
-            yylval = yylval_current;
-            yylloc = yylloc_current;
-          }
-        }
-    }
-}
-
-/** Resolve the ambiguity represented in state S, perform the indicated
- *  actions, and set the semantic value of S.  If result != yyok, the chain of
- *  semantic options in S has been cleared instead or it has been left
- *  unmodified except that redundant options may have been removed.  Regardless
- *  of whether result = yyok, S has been left with consistent data so that
- *  yydestroyGLRState can be invoked if necessary.  */
-static YYRESULTTAG
-yyresolveValue (yyGLRState* yys, yyGLRStack* yystackp, ParseState* parse_state, yyscan_t scanner)
-{
-  yySemanticOption* yyoptionList = yys->yysemantics.yyfirstVal;
-  yySemanticOption* yybest = yyoptionList;
-  yySemanticOption** yypp;
-  yybool yymerge = yyfalse;
-  YYSTYPE yysval;
-  YYRESULTTAG yyflag;
-  YYLTYPE *yylocp = &yys->yyloc;
-
-  for (yypp = &yyoptionList->yynext; *yypp != YY_NULL; )
-    {
-      yySemanticOption* yyp = *yypp;
-
-      if (yyidenticalOptions (yybest, yyp))
-        {
-          yymergeOptionSets (yybest, yyp);
-          *yypp = yyp->yynext;
-        }
-      else
-        {
-          switch (yypreference (yybest, yyp))
-            {
-            case 0:
-              yyresolveLocations (yys, 1, yystackp, parse_state, scanner);
-              return yyreportAmbiguity (yybest, yyp, yylocp, parse_state, scanner);
-              break;
-            case 1:
-              yymerge = yytrue;
-              break;
-            case 2:
-              break;
-            case 3:
-              yybest = yyp;
-              yymerge = yyfalse;
-              break;
-            default:
-              /* This cannot happen so it is not worth a YYASSERT (yyfalse),
-                 but some compilers complain if the default case is
-                 omitted.  */
-              break;
-            }
-          yypp = &yyp->yynext;
-        }
-    }
-
-  if (yymerge)
-    {
-      yySemanticOption* yyp;
-      int yyprec = yydprec[yybest->yyrule];
-      yyflag = yyresolveAction (yybest, yystackp, &yysval, yylocp, parse_state, scanner);
-      if (yyflag == yyok)
-        for (yyp = yybest->yynext; yyp != YY_NULL; yyp = yyp->yynext)
-          {
-            if (yyprec == yydprec[yyp->yyrule])
-              {
-                YYSTYPE yysval_other;
-                YYLTYPE yydummy;
-                yyflag = yyresolveAction (yyp, yystackp, &yysval_other, &yydummy, parse_state, scanner);
-                if (yyflag != yyok)
-                  {
-                    yydestruct ("Cleanup: discarding incompletely merged value for",
-                                yystos[yys->yylrState],
-                                &yysval, yylocp, parse_state, scanner);
-                    break;
-                  }
-                yyuserMerge (yymerger[yyp->yyrule], &yysval, &yysval_other);
-              }
-          }
-    }
-  else
-    yyflag = yyresolveAction (yybest, yystackp, &yysval, yylocp, parse_state, scanner);
-
-  if (yyflag == yyok)
-    {
-      yys->yyresolved = yytrue;
-      yys->yysemantics.yysval = yysval;
-    }
-  else
-    yys->yysemantics.yyfirstVal = YY_NULL;
-  return yyflag;
-}
-
-static YYRESULTTAG
-yyresolveStack (yyGLRStack* yystackp, ParseState* parse_state, yyscan_t scanner)
-{
-  if (yystackp->yysplitPoint != YY_NULL)
-    {
-      yyGLRState* yys;
-      int yyn;
-
-      for (yyn = 0, yys = yystackp->yytops.yystates[0];
-           yys != yystackp->yysplitPoint;
-           yys = yys->yypred, yyn += 1)
-        continue;
-      YYCHK (yyresolveStates (yystackp->yytops.yystates[0], yyn, yystackp
-                             , parse_state, scanner));
-    }
-  return yyok;
-}
-
-static void
-yycompressStack (yyGLRStack* yystackp)
-{
-  yyGLRState* yyp, *yyq, *yyr;
-
-  if (yystackp->yytops.yysize != 1 || yystackp->yysplitPoint == YY_NULL)
-    return;
-
-  for (yyp = yystackp->yytops.yystates[0], yyq = yyp->yypred, yyr = YY_NULL;
-       yyp != yystackp->yysplitPoint;
-       yyr = yyp, yyp = yyq, yyq = yyp->yypred)
-    yyp->yypred = yyr;
-
-  yystackp->yyspaceLeft += yystackp->yynextFree - yystackp->yyitems;
-  yystackp->yynextFree = ((yyGLRStackItem*) yystackp->yysplitPoint) + 1;
-  yystackp->yyspaceLeft -= yystackp->yynextFree - yystackp->yyitems;
-  yystackp->yysplitPoint = YY_NULL;
-  yystackp->yylastDeleted = YY_NULL;
-
-  while (yyr != YY_NULL)
-    {
-      yystackp->yynextFree->yystate = *yyr;
-      yyr = yyr->yypred;
-      yystackp->yynextFree->yystate.yypred = &yystackp->yynextFree[-1].yystate;
-      yystackp->yytops.yystates[0] = &yystackp->yynextFree->yystate;
-      yystackp->yynextFree += 1;
-      yystackp->yyspaceLeft -= 1;
-    }
-}
-
-static YYRESULTTAG
-yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
-                   size_t yyposn, YYLTYPE *yylocp, ParseState* parse_state, yyscan_t scanner)
-{
-  int yyaction;
-  const short int* yyconflicts;
-  yyRuleNum yyrule;
-
-  while (yystackp->yytops.yystates[yyk] != YY_NULL)
-    {
-      yyStateNum yystate = yystackp->yytops.yystates[yyk]->yylrState;
-      YYDPRINTF ((stderr, "Stack %lu Entering state %d\n",
-                  (unsigned long int) yyk, yystate));
-
-      YYASSERT (yystate != YYFINAL);
-
-      if (yyisDefaultedState (yystate))
-        {
-          yyrule = yydefaultAction (yystate);
-          if (yyrule == 0)
-            {
-              YYDPRINTF ((stderr, "Stack %lu dies.\n",
-                          (unsigned long int) yyk));
-              yymarkStackDeleted (yystackp, yyk);
-              return yyok;
-            }
-          YYCHK (yyglrReduce (yystackp, yyk, yyrule, yyfalse, parse_state, scanner));
-        }
-      else
-        {
-          yySymbol yytoken;
-          yystackp->yytops.yylookaheadNeeds[yyk] = yytrue;
-          if (yychar == YYEMPTY)
-            {
-              YYDPRINTF ((stderr, "Reading a token: "));
-              yychar = YYLEX;
-            }
-
-          if (yychar <= YYEOF)
-            {
-              yychar = yytoken = YYEOF;
-              YYDPRINTF ((stderr, "Now at end of input.\n"));
-            }
-          else
-            {
-              yytoken = YYTRANSLATE (yychar);
-              YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
-            }
-
-          yygetLRActions (yystate, yytoken, &yyaction, &yyconflicts);
-
-          while (*yyconflicts != 0)
-            {
-              size_t yynewStack = yysplitStack (yystackp, yyk);
-              YYDPRINTF ((stderr, "Splitting off stack %lu from %lu.\n",
-                          (unsigned long int) yynewStack,
-                          (unsigned long int) yyk));
-              YYCHK (yyglrReduce (yystackp, yynewStack,
-                                  *yyconflicts, yyfalse, parse_state, scanner));
-              YYCHK (yyprocessOneStack (yystackp, yynewStack,
-                                        yyposn, yylocp, parse_state, scanner));
-              yyconflicts += 1;
-            }
-
-          if (yyisShiftAction (yyaction))
-            break;
-          else if (yyisErrorAction (yyaction))
-            {
-              YYDPRINTF ((stderr, "Stack %lu dies.\n",
-                          (unsigned long int) yyk));
-              yymarkStackDeleted (yystackp, yyk);
-              break;
-            }
-          else
-            YYCHK (yyglrReduce (yystackp, yyk, -yyaction,
-                                yyfalse, parse_state, scanner));
-        }
-    }
-  return yyok;
-}
-
-/*ARGSUSED*/ static void
-yyreportSyntaxError (yyGLRStack* yystackp, ParseState* parse_state, yyscan_t scanner)
-{
-  if (yystackp->yyerrState != 0)
-    return;
-#if ! YYERROR_VERBOSE
-  yyerror (&yylloc, parse_state, scanner, YY_("syntax error"));
-#else
-  {
-  yySymbol yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
-  size_t yysize0 = yytnamerr (YY_NULL, yytokenName (yytoken));
-  size_t yysize = yysize0;
-  yybool yysize_overflow = yyfalse;
-  char* yymsg = YY_NULL;
-  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
-  /* Internationalized format string. */
-  const char *yyformat = YY_NULL;
-  /* Arguments of yyformat. */
-  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
-  /* Number of reported tokens (one for the "unexpected", one per
-     "expected").  */
-  int yycount = 0;
-
-  /* There are many possibilities here to consider:
-     - If this state is a consistent state with a default action, then
-       the only way this function was invoked is if the default action
-       is an error action.  In that case, don't check for expected
-       tokens because there are none.
-     - The only way there can be no lookahead present (in yychar) is if
-       this state is a consistent state with a default action.  Thus,
-       detecting the absence of a lookahead is sufficient to determine
-       that there is no unexpected or expected token to report.  In that
-       case, just report a simple "syntax error".
-     - Don't assume there isn't a lookahead just because this state is a
-       consistent state with a default action.  There might have been a
-       previous inconsistent state, consistent state with a non-default
-       action, or user semantic action that manipulated yychar.
-     - Of course, the expected token list depends on states to have
-       correct lookahead information, and it depends on the parser not
-       to perform extra reductions after fetching a lookahead from the
-       scanner and before detecting a syntax error.  Thus, state merging
-       (from LALR or IELR) and default reductions corrupt the expected
-       token list.  However, the list is correct for canonical LR with
-       one exception: it will still contain any token that will not be
-       accepted due to an error action in a later state.
-  */
-  if (yytoken != YYEMPTY)
-    {
-      int yyn = yypact[yystackp->yytops.yystates[0]->yylrState];
-      yyarg[yycount++] = yytokenName (yytoken);
-      if (!yypact_value_is_default (yyn))
-        {
-          /* Start YYX at -YYN if negative to avoid negative indexes in
-             YYCHECK.  In other words, skip the first -YYN actions for this
-             state because they are default actions.  */
-          int yyxbegin = yyn < 0 ? -yyn : 0;
-          /* Stay within bounds of both yycheck and yytname.  */
-          int yychecklim = YYLAST - yyn + 1;
-          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
-          int yyx;
-          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
-                && !yytable_value_is_error (yytable[yyx + yyn]))
-              {
-                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
-                  {
-                    yycount = 1;
-                    yysize = yysize0;
-                    break;
-                  }
-                yyarg[yycount++] = yytokenName (yyx);
-                {
-                  size_t yysz = yysize + yytnamerr (YY_NULL, yytokenName (yyx));
-                  yysize_overflow |= yysz < yysize;
-                  yysize = yysz;
-                }
-              }
-        }
-    }
-
-  switch (yycount)
-    {
-#define YYCASE_(N, S)                   \
-      case N:                           \
-        yyformat = S;                   \
-      break
-      YYCASE_(0, YY_("syntax error"));
-      YYCASE_(1, YY_("syntax error, unexpected %s"));
-      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
-      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
-      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
-      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
-#undef YYCASE_
-    }
-
-  {
-    size_t yysz = yysize + strlen (yyformat);
-    yysize_overflow |= yysz < yysize;
-    yysize = yysz;
-  }
-
-  if (!yysize_overflow)
-    yymsg = (char *) YYMALLOC (yysize);
-
-  if (yymsg)
-    {
-      char *yyp = yymsg;
-      int yyi = 0;
-      while ((*yyp = *yyformat))
-        {
-          if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
-            {
-              yyp += yytnamerr (yyp, yyarg[yyi++]);
-              yyformat += 2;
-            }
-          else
-            {
-              yyp++;
-              yyformat++;
-            }
-        }
-      yyerror (&yylloc, parse_state, scanner, yymsg);
-      YYFREE (yymsg);
-    }
-  else
-    {
-      yyerror (&yylloc, parse_state, scanner, YY_("syntax error"));
-      yyMemoryExhausted (yystackp);
-    }
-  }
-#endif /* YYERROR_VERBOSE */
-  yynerrs += 1;
-}
-
-/* Recover from a syntax error on *YYSTACKP, assuming that *YYSTACKP->YYTOKENP,
-   yylval, and yylloc are the syntactic category, semantic value, and location
-   of the lookahead.  */
-/*ARGSUSED*/ static void
-yyrecoverSyntaxError (yyGLRStack* yystackp, ParseState* parse_state, yyscan_t scanner)
-{
-  size_t yyk;
-  int yyj;
-
-  if (yystackp->yyerrState == 3)
-    /* We just shifted the error token and (perhaps) took some
-       reductions.  Skip tokens until we can proceed.  */
-    while (YYID (yytrue))
-      {
-        yySymbol yytoken;
-        if (yychar == YYEOF)
-          yyFail (yystackp, &yylloc, parse_state, scanner, YY_NULL);
-        if (yychar != YYEMPTY)
-          {
-            /* We throw away the lookahead, but the error range
-               of the shifted error token must take it into account.  */
-            yyGLRState *yys = yystackp->yytops.yystates[0];
-            yyGLRStackItem yyerror_range[3];
-            yyerror_range[1].yystate.yyloc = yys->yyloc;
-            yyerror_range[2].yystate.yyloc = yylloc;
-            YYLLOC_DEFAULT ((yys->yyloc), yyerror_range, 2);
-            yytoken = YYTRANSLATE (yychar);
-            yydestruct ("Error: discarding",
-                        yytoken, &yylval, &yylloc, parse_state, scanner);
-          }
-        YYDPRINTF ((stderr, "Reading a token: "));
-        yychar = YYLEX;
-        if (yychar <= YYEOF)
-          {
-            yychar = yytoken = YYEOF;
-            YYDPRINTF ((stderr, "Now at end of input.\n"));
-          }
-        else
-          {
-            yytoken = YYTRANSLATE (yychar);
-            YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
-          }
-        yyj = yypact[yystackp->yytops.yystates[0]->yylrState];
-        if (yypact_value_is_default (yyj))
-          return;
-        yyj += yytoken;
-        if (yyj < 0 || YYLAST < yyj || yycheck[yyj] != yytoken)
-          {
-            if (yydefact[yystackp->yytops.yystates[0]->yylrState] != 0)
-              return;
-          }
-        else if (! yytable_value_is_error (yytable[yyj]))
-          return;
-      }
-
-  /* Reduce to one stack.  */
-  for (yyk = 0; yyk < yystackp->yytops.yysize; yyk += 1)
-    if (yystackp->yytops.yystates[yyk] != YY_NULL)
-      break;
-  if (yyk >= yystackp->yytops.yysize)
-    yyFail (yystackp, &yylloc, parse_state, scanner, YY_NULL);
-  for (yyk += 1; yyk < yystackp->yytops.yysize; yyk += 1)
-    yymarkStackDeleted (yystackp, yyk);
-  yyremoveDeletes (yystackp);
-  yycompressStack (yystackp);
-
-  /* Now pop stack until we find a state that shifts the error token.  */
-  yystackp->yyerrState = 3;
-  while (yystackp->yytops.yystates[0] != YY_NULL)
-    {
-      yyGLRState *yys = yystackp->yytops.yystates[0];
-      yyj = yypact[yys->yylrState];
-      if (! yypact_value_is_default (yyj))
-        {
-          yyj += YYTERROR;
-          if (0 <= yyj && yyj <= YYLAST && yycheck[yyj] == YYTERROR
-              && yyisShiftAction (yytable[yyj]))
-            {
-              /* Shift the error token.  */
-              /* First adjust its location.*/
-              YYLTYPE yyerrloc;
-              yystackp->yyerror_range[2].yystate.yyloc = yylloc;
-              YYLLOC_DEFAULT (yyerrloc, (yystackp->yyerror_range), 2);
-              YY_SYMBOL_PRINT ("Shifting", yystos[yytable[yyj]],
-                               &yylval, &yyerrloc);
-              yyglrShift (yystackp, 0, yytable[yyj],
-                          yys->yyposn, &yylval, &yyerrloc);
-              yys = yystackp->yytops.yystates[0];
-              break;
-            }
-        }
-      yystackp->yyerror_range[1].yystate.yyloc = yys->yyloc;
-      if (yys->yypred != YY_NULL)
-        yydestroyGLRState ("Error: popping", yys, parse_state, scanner);
-      yystackp->yytops.yystates[0] = yys->yypred;
-      yystackp->yynextFree -= 1;
-      yystackp->yyspaceLeft += 1;
-    }
-  if (yystackp->yytops.yystates[0] == YY_NULL)
-    yyFail (yystackp, &yylloc, parse_state, scanner, YY_NULL);
-}
-
-#define YYCHK1(YYE)                                                          \
-  do {                                                                       \
-    switch (YYE) {                                                           \
-    case yyok:                                                               \
-      break;                                                                 \
-    case yyabort:                                                            \
-      goto yyabortlab;                                                       \
-    case yyaccept:                                                           \
-      goto yyacceptlab;                                                      \
-    case yyerr:                                                              \
-      goto yyuser_error;                                                     \
-    default:                                                                 \
-      goto yybuglab;                                                         \
-    }                                                                        \
-  } while (YYID (0))
-
-
-/*----------.
-| yyparse.  |
-`----------*/
-
-int
-yyparse (ParseState* parse_state, yyscan_t scanner)
-{
-  int yyresult;
-  yyGLRStack yystack;
-  yyGLRStack* const yystackp = &yystack;
-  size_t yyposn;
-
-  YYDPRINTF ((stderr, "Starting parse\n"));
-
-  yychar = YYEMPTY;
-  yylval = yyval_default;
-  yylloc = yyloc_default;
-
-  if (! yyinitGLRStack (yystackp, YYINITDEPTH))
-    goto yyexhaustedlab;
-  switch (YYSETJMP (yystack.yyexception_buffer))
-    {
-    case 0: break;
-    case 1: goto yyabortlab;
-    case 2: goto yyexhaustedlab;
-    default: goto yybuglab;
-    }
-  yyglrShift (&yystack, 0, 0, 0, &yylval, &yylloc);
-  yyposn = 0;
-
-  while (YYID (yytrue))
-    {
-      /* For efficiency, we have two loops, the first of which is
-         specialized to deterministic operation (single stack, no
-         potential ambiguity).  */
-      /* Standard mode */
-      while (YYID (yytrue))
-        {
-          yyRuleNum yyrule;
-          int yyaction;
-          const short int* yyconflicts;
-
-          yyStateNum yystate = yystack.yytops.yystates[0]->yylrState;
-          YYDPRINTF ((stderr, "Entering state %d\n", yystate));
-          if (yystate == YYFINAL)
-            goto yyacceptlab;
-          if (yyisDefaultedState (yystate))
-            {
-              yyrule = yydefaultAction (yystate);
-              if (yyrule == 0)
-                {
-               yystack.yyerror_range[1].yystate.yyloc = yylloc;
-                  yyreportSyntaxError (&yystack, parse_state, scanner);
-                  goto yyuser_error;
-                }
-              YYCHK1 (yyglrReduce (&yystack, 0, yyrule, yytrue, parse_state, scanner));
-            }
-          else
-            {
-              yySymbol yytoken;
-              if (yychar == YYEMPTY)
-                {
-                  YYDPRINTF ((stderr, "Reading a token: "));
-                  yychar = YYLEX;
-                }
-
-              if (yychar <= YYEOF)
-                {
-                  yychar = yytoken = YYEOF;
-                  YYDPRINTF ((stderr, "Now at end of input.\n"));
-                }
-              else
-                {
-                  yytoken = YYTRANSLATE (yychar);
-                  YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
-                }
-
-              yygetLRActions (yystate, yytoken, &yyaction, &yyconflicts);
-              if (*yyconflicts != 0)
-                break;
-              if (yyisShiftAction (yyaction))
-                {
-                  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
-                  yychar = YYEMPTY;
-                  yyposn += 1;
-                  yyglrShift (&yystack, 0, yyaction, yyposn, &yylval, &yylloc);
-                  if (0 < yystack.yyerrState)
-                    yystack.yyerrState -= 1;
-                }
-              else if (yyisErrorAction (yyaction))
-                {
-               yystack.yyerror_range[1].yystate.yyloc = yylloc;
-                  yyreportSyntaxError (&yystack, parse_state, scanner);
-                  goto yyuser_error;
-                }
-              else
-                YYCHK1 (yyglrReduce (&yystack, 0, -yyaction, yytrue, parse_state, scanner));
-            }
-        }
-
-      while (YYID (yytrue))
-        {
-          yySymbol yytoken_to_shift;
-          size_t yys;
-
-          for (yys = 0; yys < yystack.yytops.yysize; yys += 1)
-            yystackp->yytops.yylookaheadNeeds[yys] = yychar != YYEMPTY;
-
-          /* yyprocessOneStack returns one of three things:
-
-              - An error flag.  If the caller is yyprocessOneStack, it
-                immediately returns as well.  When the caller is finally
-                yyparse, it jumps to an error label via YYCHK1.
-
-              - yyok, but yyprocessOneStack has invoked yymarkStackDeleted
-                (&yystack, yys), which sets the top state of yys to NULL.  Thus,
-                yyparse's following invocation of yyremoveDeletes will remove
-                the stack.
-
-              - yyok, when ready to shift a token.
-
-             Except in the first case, yyparse will invoke yyremoveDeletes and
-             then shift the next token onto all remaining stacks.  This
-             synchronization of the shift (that is, after all preceding
-             reductions on all stacks) helps prevent double destructor calls
-             on yylval in the event of memory exhaustion.  */
-
-          for (yys = 0; yys < yystack.yytops.yysize; yys += 1)
-            YYCHK1 (yyprocessOneStack (&yystack, yys, yyposn, &yylloc, parse_state, scanner));
-          yyremoveDeletes (&yystack);
-          if (yystack.yytops.yysize == 0)
-            {
-              yyundeleteLastStack (&yystack);
-              if (yystack.yytops.yysize == 0)
-                yyFail (&yystack, &yylloc, parse_state, scanner, YY_("syntax error"));
-              YYCHK1 (yyresolveStack (&yystack, parse_state, scanner));
-              YYDPRINTF ((stderr, "Returning to deterministic operation.\n"));
-           yystack.yyerror_range[1].yystate.yyloc = yylloc;
-              yyreportSyntaxError (&yystack, parse_state, scanner);
-              goto yyuser_error;
-            }
-
-          /* If any yyglrShift call fails, it will fail after shifting.  Thus,
-             a copy of yylval will already be on stack 0 in the event of a
-             failure in the following loop.  Thus, yychar is set to YYEMPTY
-             before the loop to make sure the user destructor for yylval isn't
-             called twice.  */
-          yytoken_to_shift = YYTRANSLATE (yychar);
-          yychar = YYEMPTY;
-          yyposn += 1;
-          for (yys = 0; yys < yystack.yytops.yysize; yys += 1)
-            {
-              int yyaction;
-              const short int* yyconflicts;
-              yyStateNum yystate = yystack.yytops.yystates[yys]->yylrState;
-              yygetLRActions (yystate, yytoken_to_shift, &yyaction,
-                              &yyconflicts);
-              /* Note that yyconflicts were handled by yyprocessOneStack.  */
-              YYDPRINTF ((stderr, "On stack %lu, ", (unsigned long int) yys));
-              YY_SYMBOL_PRINT ("shifting", yytoken_to_shift, &yylval, &yylloc);
-              yyglrShift (&yystack, yys, yyaction, yyposn,
-                          &yylval, &yylloc);
-              YYDPRINTF ((stderr, "Stack %lu now in state #%d\n",
-                          (unsigned long int) yys,
-                          yystack.yytops.yystates[yys]->yylrState));
-            }
-
-          if (yystack.yytops.yysize == 1)
-            {
-              YYCHK1 (yyresolveStack (&yystack, parse_state, scanner));
-              YYDPRINTF ((stderr, "Returning to deterministic operation.\n"));
-              yycompressStack (&yystack);
-              break;
-            }
-        }
-      continue;
-    yyuser_error:
-      yyrecoverSyntaxError (&yystack, parse_state, scanner);
-      yyposn = yystack.yytops.yystates[0]->yyposn;
-    }
-
- yyacceptlab:
-  yyresult = 0;
-  goto yyreturn;
-
- yybuglab:
-  YYASSERT (yyfalse);
-  goto yyabortlab;
-
- yyabortlab:
-  yyresult = 1;
-  goto yyreturn;
-
- yyexhaustedlab:
-  yyerror (&yylloc, parse_state, scanner, YY_("memory exhausted"));
-  yyresult = 2;
-  goto yyreturn;
-
- yyreturn:
-  if (yychar != YYEMPTY)
-    yydestruct ("Cleanup: discarding lookahead",
-                YYTRANSLATE (yychar), &yylval, &yylloc, parse_state, scanner);
-
-  /* If the stack is well-formed, pop the stack until it is empty,
-     destroying its entries as we go.  But free the stack regardless
-     of whether it is well-formed.  */
-  if (yystack.yyitems)
-    {
-      yyGLRState** yystates = yystack.yytops.yystates;
-      if (yystates)
-        {
-          size_t yysize = yystack.yytops.yysize;
-          size_t yyk;
-          for (yyk = 0; yyk < yysize; yyk += 1)
-            if (yystates[yyk])
-              {
-                while (yystates[yyk])
-                  {
-                    yyGLRState *yys = yystates[yyk];
-                 yystack.yyerror_range[1].yystate.yyloc = yys->yyloc;
-                  if (yys->yypred != YY_NULL)
-                      yydestroyGLRState ("Cleanup: popping", yys, parse_state, scanner);
-                    yystates[yyk] = yys->yypred;
-                    yystack.yynextFree -= 1;
-                    yystack.yyspaceLeft += 1;
-                  }
-                break;
-              }
-        }
-      yyfreeGLRStack (&yystack);
-    }
-
-  /* Make sure YYID is used.  */
-  return YYID (yyresult);
-}
-
-/* DEBUGGING ONLY */
-#if YYDEBUG
-static void yypstack (yyGLRStack* yystackp, size_t yyk)
-  __attribute__ ((__unused__));
-static void yypdumpstack (yyGLRStack* yystackp) __attribute__ ((__unused__));
-
-static void
-yy_yypstack (yyGLRState* yys)
-{
-  if (yys->yypred)
-    {
-      yy_yypstack (yys->yypred);
-      YYFPRINTF (stderr, " -> ");
-    }
-  YYFPRINTF (stderr, "%d@%lu", yys->yylrState,
-             (unsigned long int) yys->yyposn);
-}
-
-static void
-yypstates (yyGLRState* yyst)
-{
-  if (yyst == YY_NULL)
-    YYFPRINTF (stderr, "<null>");
-  else
-    yy_yypstack (yyst);
-  YYFPRINTF (stderr, "\n");
-}
-
-static void
-yypstack (yyGLRStack* yystackp, size_t yyk)
-{
-  yypstates (yystackp->yytops.yystates[yyk]);
-}
-
-#define YYINDEX(YYX)                                                         \
-    ((YYX) == YY_NULL ? -1 : (yyGLRStackItem*) (YYX) - yystackp->yyitems)
-
-
-static void
-yypdumpstack (yyGLRStack* yystackp)
-{
-  yyGLRStackItem* yyp;
-  size_t yyi;
-  for (yyp = yystackp->yyitems; yyp < yystackp->yynextFree; yyp += 1)
-    {
-      YYFPRINTF (stderr, "%3lu. ",
-                 (unsigned long int) (yyp - yystackp->yyitems));
-      if (*(yybool *) yyp)
-        {
-          YYFPRINTF (stderr, "Res: %d, LR State: %d, posn: %lu, pred: %ld",
-                     yyp->yystate.yyresolved, yyp->yystate.yylrState,
-                     (unsigned long int) yyp->yystate.yyposn,
-                     (long int) YYINDEX (yyp->yystate.yypred));
-          if (! yyp->yystate.yyresolved)
-            YYFPRINTF (stderr, ", firstVal: %ld",
-                       (long int) YYINDEX (yyp->yystate
-                                             .yysemantics.yyfirstVal));
-        }
-      else
-        {
-          YYFPRINTF (stderr, "Option. rule: %d, state: %ld, next: %ld",
-                     yyp->yyoption.yyrule - 1,
-                     (long int) YYINDEX (yyp->yyoption.yystate),
-                     (long int) YYINDEX (yyp->yyoption.yynext));
-        }
-      YYFPRINTF (stderr, "\n");
-    }
-  YYFPRINTF (stderr, "Tops:");
-  for (yyi = 0; yyi < yystackp->yytops.yysize; yyi += 1)
-    YYFPRINTF (stderr, "%lu: %ld; ", (unsigned long int) yyi,
-               (long int) YYINDEX (yystackp->yytops.yystates[yyi]));
-  YYFPRINTF (stderr, "\n");
-}
-#endif
-/* Line 2575 of glr.c  */
-#line 969 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
-
-
-void yyerror(YYLTYPE *locp, ParseState* parse_state, yyscan_t scanner, const char *msg) 
-{ 
-	parse_state->hasError = 1;
-	parse_state->errorLine = locp->first_line;
-	parse_state->errorColumn = locp->first_column;
-	parse_state->errorMessage = mmalloc_strdup(parse_state->memContext, msg);
-	parse_state->errorFile = locp->filename;
+/* A Bison parser, made by GNU Bison 2.7.  */
+
+/* Skeleton implementation for Bison GLR parsers in C
+   
+      Copyright (C) 2002-2012 Free Software Foundation, Inc.
+   
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+   
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* C GLR parser skeleton written by Paul Hilfinger.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Bison version.  */
+#define YYBISON_VERSION "2.7"
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "glr.c"
+
+/* Pure parsers.  */
+#define YYPURE 1
+
+
+
+
+
+
+/* Copy the first part of user declarations.  */
+/* Line 207 of glr.c  */
+#line 1 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+
+#include "BsParserFX.h"
+#include "BsLexerFX.h"
+#define inline
+
+void yyerror(YYLTYPE *locp, ParseState* parse_state, yyscan_t scanner, const char *msg);
+
+/* Line 207 of glr.c  */
+#line 64 "BsParserFX.c"
+
+# ifndef YY_NULL
+#  if defined __cplusplus && 201103L <= __cplusplus
+#   define YY_NULL nullptr
+#  else
+#   define YY_NULL 0
+#  endif
+# endif
+
+#include "BsParserFX.h"
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Default (constant) value used for initialization for null
+   right-hand sides.  Unlike the standard yacc.c template, here we set
+   the default value of $$ to a zeroed-out value.  Since the default
+   value is undefined, this behavior is technically correct.  */
+static YYSTYPE yyval_default;
+static YYLTYPE yyloc_default
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+  = { 1, 1, 1, 1 }
+# endif
+;
+
+/* Copy the second part of user declarations.  */
+
+/* Line 230 of glr.c  */
+#line 98 "BsParserFX.c"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(Msgid) Msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E.  */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(E) ((void) (E))
+#else
+# define YYUSE(E) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions.  */
+#ifndef lint
+# define YYID(N) (N)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int i)
+#else
+static int
+YYID (i)
+    int i;
+#endif
+{
+  return i;
+}
+#endif
+
+#ifndef YYFREE
+# define YYFREE free
+#endif
+#ifndef YYMALLOC
+# define YYMALLOC malloc
+#endif
+#ifndef YYREALLOC
+# define YYREALLOC realloc
+#endif
+
+#define YYSIZEMAX ((size_t) -1)
+
+#ifdef __cplusplus
+   typedef bool yybool;
+#else
+   typedef unsigned char yybool;
+#endif
+#define yytrue 1
+#define yyfalse 0
+
+#ifndef YYSETJMP
+# include <setjmp.h>
+# define YYJMP_BUF jmp_buf
+# define YYSETJMP(Env) setjmp (Env)
+/* Pacify clang.  */
+# define YYLONGJMP(Env, Val) (longjmp (Env, Val), YYASSERT (0))
+#endif
+
+/*-----------------.
+| GCC extensions.  |
+`-----------------*/
+
+#ifndef __attribute__
+/* This feature is available in gcc versions 2.5 and later.  */
+# if (! defined __GNUC__ || __GNUC__ < 2 \
+      || (__GNUC__ == 2 && __GNUC_MINOR__ < 5))
+#  define __attribute__(Spec) /* empty */
+# endif
+#endif
+
+#ifndef YYASSERT
+# define YYASSERT(Condition) ((void) ((Condition) || (abort (), 0)))
+#endif
+
+/* YYFINAL -- State number of the termination state.  */
+#define YYFINAL  24
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   668
+
+/* YYNTOKENS -- Number of terminals.  */
+#define YYNTOKENS  124
+/* YYNNTS -- Number of nonterminals.  */
+#define YYNNTS  97
+/* YYNRULES -- Number of rules.  */
+#define YYNRULES  222
+/* YYNRULES -- Number of states.  */
+#define YYNSTATES  703
+/* YYMAXRHS -- Maximum number of symbols on right-hand side of rule.  */
+#define YYMAXRHS 33
+/* YYMAXLEFT -- Maximum number of symbols to the left of a handle
+   accessed by $0, $-1, etc., in any rule.  */
+#define YYMAXLEFT 0
+
+/* YYTRANSLATE(X) -- Bison symbol number corresponding to X.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   370
+
+#define YYTRANSLATE(YYX)                                                \
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
+static const unsigned char yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     122,   123,     2,     2,   120,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,   121,   117,
+       2,   116,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,   118,     2,   119,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
+      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
+      55,    56,    57,    58,    59,    60,    61,    62,    63,    64,
+      65,    66,    67,    68,    69,    70,    71,    72,    73,    74,
+      75,    76,    77,    78,    79,    80,    81,    82,    83,    84,
+      85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
+      95,    96,    97,    98,    99,   100,   101,   102,   103,   104,
+     105,   106,   107,   108,   109,   110,   111,   112,   113,   114,
+     115
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+   YYRHS.  */
+static const unsigned short int yyprhs[] =
+{
+       0,     0,     3,     4,     7,     9,    11,    13,    15,    20,
+      25,    30,    35,    41,    44,    45,    48,    50,    52,    54,
+      56,    61,    66,    72,    75,    76,    79,    81,    83,    88,
+      93,    98,   103,   108,   113,   118,   123,   128,   133,   138,
+     143,   148,   153,   158,   164,   170,   176,   182,   187,   192,
+     194,   199,   208,   211,   214,   217,   220,   223,   226,   229,
+     232,   235,   243,   244,   247,   252,   257,   262,   267,   273,
+     276,   277,   280,   282,   287,   292,   298,   304,   310,   316,
+     321,   324,   327,   328,   331,   337,   342,   347,   352,   353,
+     356,   358,   363,   368,   373,   378,   383,   388,   393,   398,
+     403,   409,   415,   418,   424,   425,   428,   433,   438,   443,
+     449,   457,   467,   473,   481,   491,   505,   523,   543,   569,
+     603,   609,   612,   613,   616,   621,   626,   631,   636,   641,
+     646,   651,   656,   661,   666,   671,   676,   681,   686,   691,
+     696,   701,   706,   711,   715,   719,   722,   725,   728,   731,
+     734,   737,   740,   743,   746,   749,   752,   755,   758,   761,
+     764,   767,   770,   773,   776,   779,   782,   785,   788,   791,
+     794,   797,   800,   803,   806,   809,   812,   815,   818,   821,
+     824,   827,   828,   831,   832,   835,   836,   839,   840,   843,
+     844,   847,   848,   851,   852,   855,   856,   859,   860,   863,
+     864,   867,   868,   871,   872,   875,   876,   879,   880,   885,
+     886,   889,   895,   898,   899,   902,   906,   909,   910,   913,
+     919,   925,   931
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
+static const short int yyrhs[] =
+{
+     125,     0,    -1,    -1,   126,   125,    -1,   127,    -1,   128,
+      -1,   173,    -1,   214,    -1,    57,   116,     5,   117,    -1,
+      58,   116,     3,   117,    -1,    59,   116,     3,   117,    -1,
+      60,   116,     5,   117,    -1,   129,   118,   130,   119,   117,
+      -1,    63,   116,    -1,    -1,   131,   130,    -1,   132,    -1,
+     133,    -1,   137,    -1,   138,    -1,    64,   116,     6,   117,
+      -1,    65,   116,     6,   117,    -1,   134,   118,   135,   119,
+     117,    -1,    66,   116,    -1,    -1,   136,   135,    -1,   137,
+      -1,   138,    -1,    96,   116,     3,   117,    -1,    75,   116,
+       8,   117,    -1,    76,   116,     9,   117,    -1,    77,   116,
+       4,   117,    -1,    78,   116,     4,   117,    -1,    79,   116,
+       5,   117,    -1,    80,   116,     5,   117,    -1,    81,   116,
+       5,   117,    -1,    82,   116,     5,   117,    -1,    83,   116,
+       5,   117,    -1,    84,   116,     5,   117,    -1,    85,   116,
+      10,   117,    -1,    86,   116,     5,   117,    -1,    87,   116,
+       3,   117,    -1,    88,   116,     3,   117,    -1,   140,   118,
+     143,   119,   117,    -1,   141,   118,   143,   119,   117,    -1,
+     140,   118,   142,   119,   117,    -1,   141,   118,   142,   119,
+     117,    -1,    93,   116,     5,   117,    -1,    94,   116,     5,
+     117,    -1,   145,    -1,    74,   116,     3,   117,    -1,   139,
+     118,    96,   116,     3,   117,   119,   117,    -1,    67,   116,
+      -1,    68,   116,    -1,    69,   116,    -1,    70,   116,    -1,
+      71,   116,    -1,    72,   116,    -1,    73,   116,    -1,    89,
+     116,    -1,    90,   116,    -1,    11,   120,    11,   120,    11,
+     120,    10,    -1,    -1,   144,   143,    -1,    91,   116,    11,
+     117,    -1,    92,   116,    11,   117,    -1,    66,   116,    11,
+     117,    -1,    85,   116,    10,   117,    -1,   146,   118,   147,
+     119,   117,    -1,    95,   116,    -1,    -1,   148,   147,    -1,
+     149,    -1,    96,   116,     3,   117,    -1,    97,   116,     5,
+     117,    -1,   150,   118,   152,   119,   117,    -1,   151,   118,
+     152,   119,   117,    -1,   150,   118,   153,   119,   117,    -1,
+     151,   118,   153,   119,   117,    -1,   100,   116,    12,   117,
+      -1,    98,   116,    -1,    99,   116,    -1,    -1,   154,   152,
+      -1,    11,   120,    11,   120,    15,    -1,   101,   116,    11,
+     117,    -1,   102,   116,    11,   117,    -1,   103,   116,    15,
+     117,    -1,    -1,   156,   155,    -1,   157,    -1,   105,   116,
+      14,   117,    -1,   106,   116,    14,   117,    -1,   107,   116,
+      14,   117,    -1,   108,   116,     3,   117,    -1,   109,   116,
+       4,   117,    -1,   110,   116,     4,   117,    -1,   111,   116,
+       4,   117,    -1,   112,   116,   164,   117,    -1,    85,   116,
+      10,   117,    -1,   158,   118,   160,   119,   117,    -1,   158,
+     118,   159,   119,   117,    -1,   104,   116,    -1,    13,   120,
+      13,   120,    13,    -1,    -1,   161,   160,    -1,   113,   116,
+      13,   117,    -1,   114,   116,    13,   117,    -1,   115,   116,
+      13,   117,    -1,   118,     4,   120,     4,   119,    -1,   118,
+       4,   120,     4,   120,     4,   119,    -1,   118,     4,   120,
+       4,   120,     4,   120,     4,   119,    -1,   118,     3,   120,
+       3,   119,    -1,   118,     3,   120,     3,   120,     3,   119,
+      -1,   118,     3,   120,     3,   120,     3,   120,     3,   119,
+      -1,   118,     4,   120,     4,   120,     4,   120,     4,   120,
+       4,   120,     4,   119,    -1,   118,     4,   120,     4,   120,
+       4,   120,     4,   120,     4,   120,     4,   120,     4,   120,
+       4,   119,    -1,   118,     4,   120,     4,   120,     4,   120,
+       4,   120,     4,   120,     4,   120,     4,   120,     4,   120,
+       4,   119,    -1,   118,     4,   120,     4,   120,     4,   120,
+       4,   120,     4,   120,     4,   120,     4,   120,     4,   120,
+       4,   120,     4,   120,     4,   120,     4,   119,    -1,   118,
+       4,   120,     4,   120,     4,   120,     4,   120,     4,   120,
+       4,   120,     4,   120,     4,   120,     4,   120,     4,   120,
+       4,   120,     4,   120,     4,   120,     4,   120,     4,   120,
+       4,   119,    -1,   174,   118,   175,   119,   117,    -1,    61,
+     116,    -1,    -1,   176,   175,    -1,   177,   219,   199,   117,
+      -1,   178,   219,   200,   117,    -1,   179,   219,   201,   117,
+      -1,   180,   219,   202,   117,    -1,   181,   219,   203,   117,
+      -1,   182,   219,   204,   117,    -1,   183,   219,   205,   117,
+      -1,   184,   219,   206,   117,    -1,   185,   219,   202,   117,
+      -1,   186,   219,   202,   117,    -1,   187,   219,   207,   117,
+      -1,   188,   219,   208,   117,    -1,   189,   219,   207,   117,
+      -1,   190,   219,   209,   117,    -1,   191,   219,   210,   117,
+      -1,   192,   219,   208,   117,    -1,   193,   219,   210,   117,
+      -1,   194,   219,   211,   117,    -1,   196,   219,   213,   117,
+      -1,   197,   219,   117,    -1,   198,   212,   117,    -1,    17,
+       7,    -1,    18,     7,    -1,    19,     7,    -1,    20,     7,
+      -1,    21,     7,    -1,    22,     7,    -1,    23,     7,    -1,
+      24,     7,    -1,    25,     7,    -1,    26,     7,    -1,    27,
+       7,    -1,    28,     7,    -1,    29,     7,    -1,    30,     7,
+      -1,    31,     7,    -1,    32,     7,    -1,    33,     7,    -1,
+      34,     7,    -1,    35,     7,    -1,    36,     7,    -1,    37,
+       7,    -1,    38,     7,    -1,    39,     7,    -1,    40,     7,
+      -1,    41,     7,    -1,    42,     7,    -1,    43,     7,    -1,
+      44,     7,    -1,    45,     7,    -1,    46,     7,    -1,    47,
+       7,    -1,    48,     7,    -1,    49,     7,    -1,    50,     7,
+      -1,    51,     7,    -1,   195,   219,    -1,    -1,   116,     4,
+      -1,    -1,   116,   162,    -1,    -1,   116,   163,    -1,    -1,
+     116,   164,    -1,    -1,   116,     3,    -1,    -1,   116,   165,
+      -1,    -1,   116,   166,    -1,    -1,   116,   167,    -1,    -1,
+     116,   168,    -1,    -1,   116,   169,    -1,    -1,   116,   170,
+      -1,    -1,   116,   171,    -1,    -1,   116,   172,    -1,    -1,
+     116,   118,   155,   119,    -1,    -1,   116,     6,    -1,   215,
+     118,   216,   119,   117,    -1,    62,   116,    -1,    -1,   217,
+     216,    -1,   218,   219,   117,    -1,    52,     7,    -1,    -1,
+     220,   219,    -1,   121,    54,   122,     6,   123,    -1,   121,
+      53,   122,     6,   123,    -1,   121,    55,   122,     5,   123,
+      -1,   121,    56,   122,    16,   123,    -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
+static const unsigned short int yyrline[] =
+{
+       0,   277,   277,   278,   282,   283,   284,   285,   289,   290,
+     291,   292,   298,   302,   309,   311,   315,   316,   317,   318,
+     322,   323,   329,   333,   340,   342,   346,   347,   351,   352,
+     353,   354,   355,   356,   357,   358,   359,   360,   361,   362,
+     363,   364,   365,   366,   367,   368,   369,   370,   371,   372,
+     373,   379,   393,   398,   403,   408,   413,   418,   423,   433,
+     441,   449,   463,   465,   469,   470,   471,   472,   477,   481,
+     488,   490,   494,   498,   499,   500,   501,   502,   503,   504,
+     509,   517,   524,   526,   530,   543,   544,   545,   550,   552,
+     556,   557,   558,   559,   560,   561,   562,   563,   564,   565,
+     570,   571,   575,   583,   595,   597,   601,   602,   603,   608,
+     612,   616,   620,   624,   628,   632,   641,   652,   663,   674,
+     688,   692,   699,   701,   705,   706,   707,   708,   709,   710,
+     711,   712,   713,   714,   715,   716,   717,   718,   719,   720,
+     721,   722,   723,   724,   725,   741,   745,   749,   753,   757,
+     761,   765,   769,   773,   777,   781,   785,   789,   793,   797,
+     801,   805,   809,   813,   814,   815,   816,   817,   821,   822,
+     823,   824,   825,   829,   830,   831,   832,   833,   834,   835,
+     839,   847,   848,   852,   853,   857,   858,   862,   863,   867,
+     868,   872,   873,   877,   878,   882,   883,   887,   888,   892,
+     893,   897,   898,   902,   903,   907,   908,   912,   913,   917,
+     918,   923,   927,   934,   936,   940,   944,   958,   960,   964,
+     965,   966,   967
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || 0
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "TOKEN_INTEGER", "TOKEN_FLOAT",
+  "TOKEN_BOOLEAN", "TOKEN_STRING", "TOKEN_IDENTIFIER",
+  "TOKEN_FILLMODEVALUE", "TOKEN_CULLMODEVALUE", "TOKEN_COMPFUNCVALUE",
+  "TOKEN_OPVALUE", "TOKEN_COLORMASK", "TOKEN_ADDRMODEVALUE",
+  "TOKEN_FILTERVALUE", "TOKEN_BLENDOPVALUE", "TOKEN_BUFFERUSAGE",
+  "TOKEN_FLOATTYPE", "TOKEN_FLOAT2TYPE", "TOKEN_FLOAT3TYPE",
+  "TOKEN_FLOAT4TYPE", "TOKEN_INTTYPE", "TOKEN_INT2TYPE", "TOKEN_INT3TYPE",
+  "TOKEN_INT4TYPE", "TOKEN_COLORTYPE", "TOKEN_MAT2x2TYPE",
+  "TOKEN_MAT2x3TYPE", "TOKEN_MAT2x4TYPE", "TOKEN_MAT3x2TYPE",
+  "TOKEN_MAT3x3TYPE", "TOKEN_MAT3x4TYPE", "TOKEN_MAT4x2TYPE",
+  "TOKEN_MAT4x3TYPE", "TOKEN_MAT4x4TYPE", "TOKEN_SAMPLER1D",
+  "TOKEN_SAMPLER2D", "TOKEN_SAMPLER3D", "TOKEN_SAMPLERCUBE",
+  "TOKEN_SAMPLER2DMS", "TOKEN_TEXTURE1D", "TOKEN_TEXTURE2D",
+  "TOKEN_TEXTURE3D", "TOKEN_TEXTURECUBE", "TOKEN_TEXTURE2DMS",
+  "TOKEN_BYTEBUFFER", "TOKEN_STRUCTBUFFER", "TOKEN_RWTYPEDBUFFER",
+  "TOKEN_RWBYTEBUFFER", "TOKEN_RWSTRUCTBUFFER", "TOKEN_RWAPPENDBUFFER",
+  "TOKEN_RWCONSUMEBUFFER", "TOKEN_PARAMSBLOCK", "TOKEN_AUTO",
+  "TOKEN_ALIAS", "TOKEN_SHARED", "TOKEN_USAGE", "TOKEN_SEPARABLE",
+  "TOKEN_QUEUE", "TOKEN_PRIORITY", "TOKEN_TRANSPARENT", "TOKEN_PARAMETERS",
+  "TOKEN_BLOCKS", "TOKEN_TECHNIQUE", "TOKEN_RENDERER", "TOKEN_LANGUAGE",
+  "TOKEN_PASS", "TOKEN_VERTEX", "TOKEN_FRAGMENT", "TOKEN_GEOMETRY",
+  "TOKEN_HULL", "TOKEN_DOMAIN", "TOKEN_COMPUTE", "TOKEN_COMMON",
+  "TOKEN_STENCILREF", "TOKEN_FILLMODE", "TOKEN_CULLMODE",
+  "TOKEN_DEPTHBIAS", "TOKEN_SDEPTHBIAS", "TOKEN_DEPTHCLIP",
+  "TOKEN_SCISSOR", "TOKEN_MULTISAMPLE", "TOKEN_AALINE", "TOKEN_DEPTHREAD",
+  "TOKEN_DEPTHWRITE", "TOKEN_COMPAREFUNC", "TOKEN_STENCIL",
+  "TOKEN_STENCILREADMASK", "TOKEN_STENCILWRITEMASK",
+  "TOKEN_STENCILOPFRONT", "TOKEN_STENCILOPBACK", "TOKEN_FAIL",
+  "TOKEN_ZFAIL", "TOKEN_ALPHATOCOVERAGE", "TOKEN_INDEPENDANTBLEND",
+  "TOKEN_TARGET", "TOKEN_INDEX", "TOKEN_BLEND", "TOKEN_COLOR",
+  "TOKEN_ALPHA", "TOKEN_WRITEMASK", "TOKEN_SOURCE", "TOKEN_DEST",
+  "TOKEN_OP", "TOKEN_ADDRMODE", "TOKEN_MINFILTER", "TOKEN_MAGFILTER",
+  "TOKEN_MIPFILTER", "TOKEN_MAXANISO", "TOKEN_MIPBIAS", "TOKEN_MIPMIN",
+  "TOKEN_MIPMAX", "TOKEN_BORDERCOLOR", "TOKEN_U", "TOKEN_V", "TOKEN_W",
+  "'='", "';'", "'{'", "'}'", "','", "':'", "'('", "')'", "$accept",
+  "shader", "shader_statement", "shader_option", "technique",
+  "technique_header", "technique_body", "technique_statement",
+  "technique_option", "pass", "pass_header", "pass_body", "pass_statement",
+  "pass_option", "code", "code_header", "stencil_op_front_header",
+  "stencil_op_back_header", "stencil_op_body_init", "stencil_op_body",
+  "stencil_op_option", "target", "target_header", "target_body",
+  "target_statement", "target_option", "blend_color_header",
+  "blend_alpha_header", "blenddef_body", "blenddef_body_init",
+  "blenddef_option", "sampler_state_body", "sampler_state_option",
+  "addr_mode", "addr_mode_header", "addr_mode_body_init", "addr_mode_body",
+  "addr_mode_option", "float2", "float3", "float4", "int2", "int3", "int4",
+  "mat6", "mat8", "mat9", "mat12", "mat16", "parameters",
+  "parameters_header", "parameters_body", "parameter",
+  "param_header_float", "param_header_float2", "param_header_float3",
+  "param_header_float4", "param_header_int", "param_header_int2",
+  "param_header_int3", "param_header_int4", "param_header_color",
+  "param_header_mat2x2", "param_header_mat2x3", "param_header_mat2x4",
+  "param_header_mat3x2", "param_header_mat3x3", "param_header_mat3x4",
+  "param_header_mat4x2", "param_header_mat4x3", "param_header_mat4x4",
+  "param_header_sampler", "param_header_texture", "param_header_buffer",
+  "param_header_qualified_sampler", "param_body_float",
+  "param_body_float2", "param_body_float3", "param_body_float4",
+  "param_body_int", "param_body_int2", "param_body_int3",
+  "param_body_int4", "param_body_mat6", "param_body_mat8",
+  "param_body_mat9", "param_body_mat12", "param_body_mat16",
+  "param_body_sampler", "param_body_tex", "blocks", "blocks_header",
+  "blocks_body", "block", "block_header", "qualifier_list", "qualifier", YY_NULL
+};
+#endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const unsigned char yyr1[] =
+{
+       0,   124,   125,   125,   126,   126,   126,   126,   127,   127,
+     127,   127,   128,   129,   130,   130,   131,   131,   131,   131,
+     132,   132,   133,   134,   135,   135,   136,   136,   137,   137,
+     137,   137,   137,   137,   137,   137,   137,   137,   137,   137,
+     137,   137,   137,   137,   137,   137,   137,   137,   137,   137,
+     137,   138,   139,   139,   139,   139,   139,   139,   139,   140,
+     141,   142,   143,   143,   144,   144,   144,   144,   145,   146,
+     147,   147,   148,   149,   149,   149,   149,   149,   149,   149,
+     150,   151,   152,   152,   153,   154,   154,   154,   155,   155,
+     156,   156,   156,   156,   156,   156,   156,   156,   156,   156,
+     157,   157,   158,   159,   160,   160,   161,   161,   161,   162,
+     163,   164,   165,   166,   167,   168,   169,   170,   171,   172,
+     173,   174,   175,   175,   176,   176,   176,   176,   176,   176,
+     176,   176,   176,   176,   176,   176,   176,   176,   176,   176,
+     176,   176,   176,   176,   176,   177,   178,   179,   180,   181,
+     182,   183,   184,   185,   186,   187,   188,   189,   190,   191,
+     192,   193,   194,   195,   195,   195,   195,   195,   196,   196,
+     196,   196,   196,   197,   197,   197,   197,   197,   197,   197,
+     198,   199,   199,   200,   200,   201,   201,   202,   202,   203,
+     203,   204,   204,   205,   205,   206,   206,   207,   207,   208,
+     208,   209,   209,   210,   210,   211,   211,   212,   212,   213,
+     213,   214,   215,   216,   216,   217,   218,   219,   219,   220,
+     220,   220,   220
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
+static const unsigned char yyr2[] =
+{
+       0,     2,     0,     2,     1,     1,     1,     1,     4,     4,
+       4,     4,     5,     2,     0,     2,     1,     1,     1,     1,
+       4,     4,     5,     2,     0,     2,     1,     1,     4,     4,
+       4,     4,     4,     4,     4,     4,     4,     4,     4,     4,
+       4,     4,     4,     5,     5,     5,     5,     4,     4,     1,
+       4,     8,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     7,     0,     2,     4,     4,     4,     4,     5,     2,
+       0,     2,     1,     4,     4,     5,     5,     5,     5,     4,
+       2,     2,     0,     2,     5,     4,     4,     4,     0,     2,
+       1,     4,     4,     4,     4,     4,     4,     4,     4,     4,
+       5,     5,     2,     5,     0,     2,     4,     4,     4,     5,
+       7,     9,     5,     7,     9,    13,    17,    19,    25,    33,
+       5,     2,     0,     2,     4,     4,     4,     4,     4,     4,
+       4,     4,     4,     4,     4,     4,     4,     4,     4,     4,
+       4,     4,     4,     3,     3,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     0,     2,     0,     2,     0,     2,     0,     2,     0,
+       2,     0,     2,     0,     2,     0,     2,     0,     2,     0,
+       2,     0,     2,     0,     2,     0,     2,     0,     4,     0,
+       2,     5,     2,     0,     2,     3,     2,     0,     2,     5,
+       5,     5,     5
+};
+
+/* YYDPREC[RULE-NUM] -- Dynamic precedence of rule #RULE-NUM (0 if none).  */
+static const unsigned char yydprec[] =
+{
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0
+};
+
+/* YYMERGER[RULE-NUM] -- Index of merging function for rule #RULE-NUM.  */
+static const unsigned char yymerger[] =
+{
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0
+};
+
+/* YYDEFACT[S] -- default reduction number in state S.  Performed when
+   YYTABLE doesn't specify something else to do.  Zero means the default
+   is an error.  */
+static const unsigned char yydefact[] =
+{
+       2,     0,     0,     0,     0,     0,     0,     0,     0,     2,
+       4,     5,     0,     6,     0,     7,     0,     0,     0,     0,
+       0,   121,   212,    13,     1,     3,    14,   122,   213,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,    14,    16,    17,     0,    18,
+      19,     0,     0,     0,    49,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,   122,   217,   217,   217,   217,   217,   217,   217,
+     217,   217,   217,   217,   217,   217,   217,   217,   217,   217,
+     217,   217,   217,   217,   207,     0,     0,   213,   217,     8,
+       9,    10,    11,     0,     0,    23,    52,    53,    54,    55,
+      56,    57,    58,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,    59,    60,
+       0,     0,    69,     0,     0,    15,    24,     0,    62,    62,
+      70,   145,   146,   147,   148,   149,   150,   151,   152,   153,
+     154,   155,   156,   157,   158,   159,   160,   161,   162,   163,
+     164,   165,   166,   167,   168,   169,   170,   171,   172,   173,
+     174,   175,   176,   177,   178,   179,     0,   123,     0,   181,
+     217,   183,   185,   187,   189,   191,   193,   195,   187,   187,
+     197,   199,   197,   201,   203,   199,   203,   205,   180,   209,
+       0,     0,     0,   216,     0,   214,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,    12,     0,    24,
+      26,    27,     0,     0,     0,     0,     0,     0,     0,     0,
+      62,     0,     0,     0,     0,     0,     0,     0,     0,    70,
+      72,     0,     0,   120,     0,     0,     0,     0,     0,     0,
+     218,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,   143,    88,   144,   211,   215,    20,    21,    50,
+      29,    30,    31,    32,    33,    34,    35,    36,    37,    38,
+      39,    40,    41,    42,    47,    48,    28,     0,    25,     0,
+       0,     0,     0,     0,     0,     0,     0,    63,     0,     0,
+       0,     0,    80,    81,     0,     0,    71,    82,    82,     0,
+       0,     0,     0,   182,   124,     0,   184,   125,     0,   186,
+     126,     0,   188,   127,   190,   128,     0,   192,   129,     0,
+     194,   130,     0,   196,   131,   132,   133,     0,   198,   134,
+       0,   200,   135,   136,     0,   202,   137,     0,   204,   138,
+     139,   140,     0,   206,   141,   210,   142,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,    88,    90,
+       0,    22,     0,     0,     0,     0,     0,     0,    45,    43,
+      46,    44,     0,     0,     0,    68,     0,     0,     0,     0,
+       0,     0,    82,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,   102,     0,     0,     0,     0,     0,     0,     0,     0,
+     208,    89,   104,     0,     0,    66,    67,    64,    65,    73,
+      74,    79,     0,     0,     0,     0,     0,     0,    83,     0,
+       0,   220,   219,   221,   222,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,   104,     0,     0,     0,     0,     0,     0,    75,    77,
+      76,    78,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,    99,    91,    92,    93,    94,    95,    96,
+      97,    98,     0,     0,     0,     0,     0,     0,   105,    51,
+       0,     0,    85,    86,    87,   109,     0,     0,   112,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+     101,   100,    61,    84,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,   106,   107,   108,   110,     0,   113,
+       0,     0,     0,     0,     0,     0,   103,     0,     0,     0,
+       0,     0,     0,     0,   111,   114,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,   115,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,   116,     0,     0,     0,     0,     0,     0,
+     117,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,   118,     0,     0,     0,     0,     0,     0,
+       0,     0,   119
+};
+
+/* YYPDEFGOTO[NTERM-NUM].  */
+static const short int yydefgoto[] =
+{
+      -1,     8,     9,    10,    11,    12,    64,    65,    66,    67,
+      68,   268,   269,    69,    70,    71,    72,    73,   278,   279,
+     280,    74,    75,   288,   289,   290,   291,   292,   460,   461,
+     462,   437,   438,   439,   440,   539,   540,   541,   386,   389,
+     392,   397,   400,   403,   408,   411,   415,   418,   423,    13,
+      14,   111,   112,   113,   114,   115,   116,   117,   118,   119,
+     120,   121,   122,   123,   124,   125,   126,   127,   128,   129,
+     130,   131,   132,   133,   134,   299,   302,   304,   306,   308,
+     310,   312,   314,   318,   320,   323,   325,   329,   242,   331,
+      15,    16,   136,   137,   138,   219,   220
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+   STATE-NUM.  */
+#define YYPACT_NINF -354
+static const short int yypact[] =
+{
+      11,   -90,   -50,   -41,   -16,   -13,   -11,    -9,   108,    11,
+    -354,  -354,    -6,  -354,    -5,  -354,    -3,   146,   149,   178,
+     177,  -354,  -354,  -354,  -354,  -354,    60,    14,   138,    74,
+      75,    76,    77,    79,    80,    81,    82,    83,    84,    85,
+      87,    88,    89,    91,    92,    93,    94,    95,    96,    97,
+      98,    99,   100,   101,   102,   103,   104,   105,   106,   107,
+     109,   110,   111,   112,   113,    60,  -354,  -354,   115,  -354,
+    -354,   116,   117,   118,  -354,   119,   195,   199,   217,   222,
+     223,   224,   231,   232,   233,   234,   235,   236,   237,   238,
+     239,   240,   241,   242,   243,   244,   245,   246,   247,   248,
+     249,   250,   251,   252,   253,   254,   255,   256,   257,   258,
+     259,   148,    14,   147,   147,   147,   147,   147,   147,   147,
+     147,   147,   147,   147,   147,   147,   147,   147,   147,   147,
+     147,   147,   147,   147,   153,   263,   152,   138,   147,  -354,
+    -354,  -354,  -354,   266,   267,  -354,  -354,  -354,  -354,  -354,
+    -354,  -354,  -354,   271,   268,   269,   273,   275,   270,   276,
+     277,   278,   279,   280,   281,   282,   283,   285,  -354,  -354,
+     284,   287,  -354,   290,   163,  -354,    90,   194,    19,    19,
+     -19,  -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,
+    -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,
+    -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,
+    -354,  -354,  -354,  -354,  -354,  -354,   179,  -354,    43,   181,
+     147,   182,   183,   184,   185,   186,   187,   188,   184,   184,
+     189,   190,   189,   191,   192,   190,   192,   193,  -354,   196,
+     197,   176,   198,  -354,   200,  -354,   201,   202,   203,   204,
+     205,   206,   207,   208,   209,   210,   211,   212,   213,   214,
+     215,   216,   218,   219,   220,   221,   225,  -354,   226,    90,
+    -354,  -354,   227,   175,   228,   230,   260,   261,   229,   262,
+      10,   264,   265,   272,   274,   286,   288,   289,   291,   -19,
+    -354,   293,   294,  -354,   292,   295,   296,   297,   306,   298,
+    -354,   302,   299,   303,   305,   307,   309,   308,   310,   311,
+     313,   314,   316,   317,   319,   320,   321,   322,   324,   325,
+     327,   328,   329,   331,   332,   334,   335,   336,   337,   339,
+     333,   340,  -354,   -18,  -354,  -354,  -354,  -354,  -354,  -354,
+    -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,
+    -354,  -354,  -354,  -354,  -354,  -354,  -354,   341,  -354,   338,
+     323,   342,   330,   343,   344,   345,   346,  -354,   347,   348,
+     349,   351,  -354,  -354,   301,   350,  -354,    16,    16,   352,
+     353,   355,   300,  -354,  -354,   357,  -354,  -354,   358,  -354,
+    -354,   359,  -354,  -354,  -354,  -354,   354,  -354,  -354,   361,
+    -354,  -354,   362,  -354,  -354,  -354,  -354,   363,  -354,  -354,
+     364,  -354,  -354,  -354,   365,  -354,  -354,   366,  -354,  -354,
+    -354,  -354,   367,  -354,  -354,  -354,  -354,   312,   315,   318,
+     326,   356,   360,   368,   369,   370,   371,   304,   -18,  -354,
+     372,  -354,   374,   373,   375,   377,   378,   379,  -354,  -354,
+    -354,  -354,   380,   381,   382,  -354,   383,   384,   385,   386,
+     387,   388,    86,   389,   390,   391,   392,   393,   394,   398,
+     399,   400,   401,   402,   403,   404,   405,   406,   407,   408,
+     376,  -354,   395,   410,   425,   396,   397,   409,   442,   307,
+    -354,  -354,     7,   411,   438,  -354,  -354,  -354,  -354,  -354,
+    -354,  -354,   443,   448,   449,   446,   412,   414,  -354,   415,
+     416,  -354,  -354,  -354,  -354,   462,   464,   465,   467,   468,
+     470,   471,   473,   474,   475,   476,   417,   418,   419,   420,
+     421,   422,   423,   424,   426,   427,   428,   429,   430,   431,
+     432,   -31,   435,   433,   434,   439,   440,   441,  -354,  -354,
+    -354,  -354,   436,   444,   445,   447,   450,   451,   452,   453,
+     454,   455,   456,  -354,  -354,  -354,  -354,  -354,  -354,  -354,
+    -354,  -354,   461,   469,   491,   492,   460,   463,  -354,  -354,
+     478,   466,  -354,  -354,  -354,  -354,   479,   485,  -354,   507,
+     508,   509,   538,   544,   545,   555,   458,   472,   477,   480,
+    -354,  -354,  -354,  -354,   481,   459,   482,   483,   484,   486,
+     487,   488,   489,   499,  -354,  -354,  -354,  -354,   556,  -354,
+     558,   559,   563,   564,   565,   577,  -354,   493,   494,   490,
+     495,   496,   497,   498,  -354,  -354,   578,   579,   580,   581,
+     582,   500,   501,   502,   503,   504,   583,   584,   586,   587,
+     588,   506,   510,   511,   512,   513,  -354,   589,   591,   592,
+     594,   514,   515,   516,   517,   595,   598,   601,   607,   519,
+     520,   521,   522,  -354,   610,   615,   622,   524,   525,   526,
+    -354,   623,   624,   527,   528,   625,   635,   529,   530,   640,
+     647,   533,   534,  -354,   649,   535,   652,   537,   654,   539,
+     656,   542,  -354
+};
+
+/* YYPGOTO[NTERM-NUM].  */
+static const short int yypgoto[] =
+{
+    -354,   553,  -354,  -354,  -354,  -354,   597,  -354,  -354,  -354,
+    -354,    78,  -354,  -155,  -153,  -354,  -354,  -354,   170,  -157,
+    -354,  -354,  -354,    61,  -354,  -354,  -354,  -354,  -353,   -27,
+    -354,   -72,  -354,  -354,  -354,  -354,  -169,  -354,  -354,  -354,
+    -116,  -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,
+    -354,   551,  -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,
+    -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,
+    -354,  -354,  -354,  -354,  -354,  -354,  -354,  -354,  -200,  -354,
+    -354,  -354,  -354,   142,   140,  -354,   143,  -354,  -354,  -354,
+    -354,  -354,   531,  -354,  -354,  -114,  -354
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
+   positive, shift that token.  If negative, reduce the rule which
+   number is the opposite.  If YYTABLE_NINF, syntax error.  */
+#define YYTABLE_NINF -1
+static const unsigned short int yytable[] =
+{
+     221,   222,   223,   224,   225,   226,   227,   228,   229,   230,
+     231,   232,   233,   234,   235,   236,   237,   238,   239,   240,
+     535,   270,   282,   271,   246,   463,    17,   456,   315,   316,
+     273,    76,    77,    78,    79,    80,    81,    82,    83,    84,
+      85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
+      95,    96,    97,    98,    99,   100,   101,   102,   103,   104,
+     105,   106,   107,   108,   109,   110,    18,   427,     1,     2,
+       3,     4,     5,     6,     7,    19,   274,   283,   284,   285,
+     286,   287,   536,   537,   538,   274,   428,   429,   430,   431,
+     432,   433,   434,   435,   436,   275,   294,   295,   296,   297,
+      20,   276,   277,    21,   275,    22,   300,    23,    24,   508,
+     276,   277,    26,    27,   270,    28,   271,   457,   458,   459,
+     536,   537,   538,   367,    33,    34,    35,    36,    37,    38,
+      39,    40,    41,    42,    43,    44,    45,    46,    47,    48,
+      49,    50,    51,    52,    53,    54,    55,    56,    57,    58,
+      59,    29,    30,    60,    61,    62,    63,    36,    37,    38,
+      39,    40,    41,    42,    43,    44,    45,    46,    47,    48,
+      49,    50,    51,    52,    53,    54,    55,    56,    57,    58,
+      59,    31,    32,    60,    61,    62,    63,   457,   458,   459,
+     135,   139,   140,   141,   142,   143,   144,   145,   146,   147,
+     148,   149,   181,   150,   151,   152,   182,   153,   154,   155,
+     156,   157,   158,   159,   160,   161,   162,   163,   164,   165,
+     166,   167,   168,   169,   183,   170,   171,   172,   173,   184,
+     185,   186,   174,   176,   177,   178,   179,   180,   187,   188,
+     189,   190,   191,   192,   193,   194,   195,   196,   197,   198,
+     199,   200,   201,   202,   203,   204,   205,   206,   207,   208,
+     209,   210,   211,   212,   213,   214,   215,   216,   218,   241,
+     243,   244,   247,   248,   249,   254,   250,   252,   251,   253,
+     267,   255,   256,   257,   258,   259,   262,   261,   263,   264,
+     272,   260,   265,   266,   333,   360,   293,   298,   301,   303,
+     305,   307,   309,   311,   313,   317,   319,   322,   324,   328,
+     383,   394,   330,   454,   332,   334,   468,   335,   336,   337,
+     338,   339,   340,   341,   342,   343,   344,   345,   346,   347,
+     348,   349,   350,   351,   443,   352,   353,   354,   355,   425,
+     445,   442,   356,   359,   361,   357,   362,   358,   365,   281,
+     376,   464,   452,   444,   446,   447,   453,   472,   465,   466,
+     467,   469,   470,   471,   473,   474,   491,   475,   476,   477,
+     478,   479,   578,   534,   321,   326,   363,   364,     0,   327,
+       0,   366,     0,   368,   369,     0,   526,     0,   370,     0,
+     371,     0,     0,     0,     0,     0,     0,     0,     0,   530,
+       0,   531,   372,     0,   373,   374,     0,     0,     0,   527,
+     375,   377,   378,   532,   379,   384,   387,   380,   381,   382,
+     385,   388,   390,   490,   528,   391,   393,   395,   480,   396,
+     398,   481,   399,   401,   482,   402,   404,   405,   406,   529,
+     407,   409,   483,   410,   412,   413,   533,   414,   416,   543,
+     417,   419,   420,   421,   544,   422,   424,   426,   441,   545,
+     546,   547,   448,   449,   450,   451,   552,   455,   553,   554,
+     555,   556,   484,   557,   596,   558,   485,   559,   560,   561,
+     562,   603,   597,   604,   486,   487,   488,   489,   602,   605,
+     492,   493,   495,   494,   496,   497,   498,   499,   500,   501,
+     503,   504,   505,   502,   598,   599,   506,   507,   509,   510,
+     606,   607,   626,   608,   511,   512,   513,   514,   515,   516,
+     517,   518,   519,   520,   521,   522,   523,   524,   525,   548,
+     542,   549,   550,   551,   563,   564,   565,   566,   567,   568,
+     569,   570,   609,   571,   573,   574,   575,   572,   610,   611,
+     576,   577,   579,   580,   581,   585,   582,   583,   584,   612,
+     627,   628,    25,   629,   586,   587,   588,   630,   631,   632,
+     589,   590,   591,   592,   593,   594,   595,   600,   613,   618,
+     601,   633,   641,   642,   643,   644,   645,   651,   652,   614,
+     653,   654,   655,   661,   615,   662,   663,   616,   664,   669,
+     617,   619,   670,   620,   621,   671,   622,   623,   624,   625,
+     636,   672,   634,   635,   677,   637,   638,   639,   640,   678,
+     646,   647,   648,   649,   650,   656,   679,   683,   684,   687,
+     657,   658,   659,   660,   665,   666,   667,   668,   673,   688,
+     674,   675,   676,   680,   691,   681,   682,   685,   686,   689,
+     690,   692,   693,   695,   694,   696,   697,   698,   699,   700,
+     701,   702,   175,   217,     0,     0,     0,     0,   245
+};
+
+/* YYCONFLP[YYPACT[STATE-NUM]] -- Pointer into YYCONFL of start of
+   list of conflicting reductions corresponding to action entry for
+   state STATE-NUM in yytable.  0 means no conflicts.  The list in
+   yyconfl is terminated by a rule number of 0.  */
+static const unsigned char yyconflp[] =
+{
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0
+};
+
+/* YYCONFL[I] -- lists of conflicting rule numbers, each terminated by
+   0, pointed into by YYCONFLP.  */
+static const short int yyconfl[] =
+{
+       0
+};
+
+static const short int yycheck[] =
+{
+     114,   115,   116,   117,   118,   119,   120,   121,   122,   123,
+     124,   125,   126,   127,   128,   129,   130,   131,   132,   133,
+      13,   176,   179,   176,   138,   378,   116,    11,   228,   229,
+      11,    17,    18,    19,    20,    21,    22,    23,    24,    25,
+      26,    27,    28,    29,    30,    31,    32,    33,    34,    35,
+      36,    37,    38,    39,    40,    41,    42,    43,    44,    45,
+      46,    47,    48,    49,    50,    51,   116,    85,    57,    58,
+      59,    60,    61,    62,    63,   116,    66,    96,    97,    98,
+      99,   100,   113,   114,   115,    66,   104,   105,   106,   107,
+     108,   109,   110,   111,   112,    85,    53,    54,    55,    56,
+     116,    91,    92,   116,    85,   116,   220,   116,     0,   462,
+      91,    92,   118,   118,   269,   118,   269,   101,   102,   103,
+     113,   114,   115,   280,    64,    65,    66,    67,    68,    69,
+      70,    71,    72,    73,    74,    75,    76,    77,    78,    79,
+      80,    81,    82,    83,    84,    85,    86,    87,    88,    89,
+      90,     5,     3,    93,    94,    95,    96,    67,    68,    69,
+      70,    71,    72,    73,    74,    75,    76,    77,    78,    79,
+      80,    81,    82,    83,    84,    85,    86,    87,    88,    89,
+      90,     3,     5,    93,    94,    95,    96,   101,   102,   103,
+      52,   117,   117,   117,   117,   116,   116,   116,   116,   116,
+     116,   116,     7,   116,   116,   116,     7,   116,   116,   116,
+     116,   116,   116,   116,   116,   116,   116,   116,   116,   116,
+     116,   116,   116,   116,     7,   116,   116,   116,   116,     7,
+       7,     7,   119,   118,   118,   118,   118,   118,     7,     7,
+       7,     7,     7,     7,     7,     7,     7,     7,     7,     7,
+       7,     7,     7,     7,     7,     7,     7,     7,     7,     7,
+       7,     7,     7,     7,     7,     7,     7,   119,   121,   116,
+       7,   119,     6,     6,     3,     5,     8,     4,     9,     4,
+     117,     5,     5,     5,     5,     5,     3,     5,     3,     5,
+      96,    10,     5,     3,   118,   120,   117,   116,   116,   116,
+     116,   116,   116,   116,   116,   116,   116,   116,   116,   116,
+       4,     3,   116,    12,   117,   117,    16,   117,   117,   117,
+     117,   117,   117,   117,   117,   117,   117,   117,   117,   117,
+     117,   117,   117,   117,    11,   117,   117,   117,   117,     6,
+      10,     3,   117,   116,   116,   119,   116,   269,   119,   179,
+     289,   378,     3,    11,    11,    11,     5,     3,     6,     6,
+       5,     4,     4,     4,     3,     3,   438,     4,     4,     4,
+       4,     4,   541,   489,   232,   235,   116,   116,    -1,   236,
+      -1,   119,    -1,   119,   119,    -1,    10,    -1,   116,    -1,
+     116,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,     3,
+      -1,     4,   116,    -1,   116,   116,    -1,    -1,    -1,    14,
+     119,   118,   118,     4,   122,   117,   117,   122,   122,   122,
+     118,   118,   117,   119,    14,   118,   117,   117,   116,   118,
+     117,   116,   118,   117,   116,   118,   117,   117,   117,    14,
+     118,   117,   116,   118,   117,   117,     4,   118,   117,    11,
+     118,   117,   117,   117,    11,   118,   117,   117,   117,    11,
+      11,    15,   117,   117,   117,   117,     4,   117,     4,     4,
+       3,     3,   116,     3,    13,     4,   116,     4,     4,     4,
+       4,    15,    13,     4,   116,   116,   116,   116,    10,     4,
+     118,   117,   117,   120,   117,   117,   117,   117,   117,   117,
+     116,   116,   116,   120,    13,    13,   119,   119,   119,   119,
+       3,     3,    13,     4,   123,   123,   123,   123,   120,   120,
+     120,   120,   120,   120,   120,   120,   120,   120,   120,   117,
+     119,   117,   117,   117,   117,   117,   117,   117,   117,   117,
+     117,   117,     4,   117,   116,   116,   116,   120,     4,     4,
+     119,   119,   117,   120,   120,   119,   117,   117,   117,     4,
+       4,     3,     9,     4,   120,   120,   119,     4,     4,     4,
+     120,   120,   120,   120,   120,   120,   120,   117,   120,   120,
+     117,     4,     4,     4,     4,     4,     4,     4,     4,   117,
+       4,     4,     4,     4,   117,     4,     4,   117,     4,     4,
+     119,   119,     4,   120,   120,     4,   120,   120,   120,   120,
+     120,     4,   119,   119,     4,   120,   120,   120,   120,     4,
+     120,   120,   120,   120,   120,   119,     4,     4,     4,     4,
+     120,   120,   120,   120,   120,   120,   120,   120,   119,     4,
+     120,   120,   120,   119,     4,   120,   120,   120,   120,   120,
+     120,     4,   119,     4,   120,   120,     4,   120,     4,   120,
+       4,   119,    65,   112,    -1,    -1,    -1,    -1,   137
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+   symbol of state STATE-NUM.  */
+static const unsigned char yystos[] =
+{
+       0,    57,    58,    59,    60,    61,    62,    63,   125,   126,
+     127,   128,   129,   173,   174,   214,   215,   116,   116,   116,
+     116,   116,   116,   116,     0,   125,   118,   118,   118,     5,
+       3,     3,     5,    64,    65,    66,    67,    68,    69,    70,
+      71,    72,    73,    74,    75,    76,    77,    78,    79,    80,
+      81,    82,    83,    84,    85,    86,    87,    88,    89,    90,
+      93,    94,    95,    96,   130,   131,   132,   133,   134,   137,
+     138,   139,   140,   141,   145,   146,    17,    18,    19,    20,
+      21,    22,    23,    24,    25,    26,    27,    28,    29,    30,
+      31,    32,    33,    34,    35,    36,    37,    38,    39,    40,
+      41,    42,    43,    44,    45,    46,    47,    48,    49,    50,
+      51,   175,   176,   177,   178,   179,   180,   181,   182,   183,
+     184,   185,   186,   187,   188,   189,   190,   191,   192,   193,
+     194,   195,   196,   197,   198,    52,   216,   217,   218,   117,
+     117,   117,   117,   116,   116,   116,   116,   116,   116,   116,
+     116,   116,   116,   116,   116,   116,   116,   116,   116,   116,
+     116,   116,   116,   116,   116,   116,   116,   116,   116,   116,
+     116,   116,   116,   116,   119,   130,   118,   118,   118,   118,
+     118,     7,     7,     7,     7,     7,     7,     7,     7,     7,
+       7,     7,     7,     7,     7,     7,     7,     7,     7,     7,
+       7,     7,     7,     7,     7,     7,     7,     7,     7,     7,
+       7,     7,     7,     7,     7,     7,   119,   175,   121,   219,
+     220,   219,   219,   219,   219,   219,   219,   219,   219,   219,
+     219,   219,   219,   219,   219,   219,   219,   219,   219,   219,
+     219,   116,   212,     7,   119,   216,   219,     6,     6,     3,
+       8,     9,     4,     4,     5,     5,     5,     5,     5,     5,
+      10,     5,     3,     3,     5,     5,     3,   117,   135,   136,
+     137,   138,    96,    11,    66,    85,    91,    92,   142,   143,
+     144,   142,   143,    96,    97,    98,    99,   100,   147,   148,
+     149,   150,   151,   117,    53,    54,    55,    56,   116,   199,
+     219,   116,   200,   116,   201,   116,   202,   116,   203,   116,
+     204,   116,   205,   116,   206,   202,   202,   116,   207,   116,
+     208,   207,   116,   209,   116,   210,   208,   210,   116,   211,
+     116,   213,   117,   118,   117,   117,   117,   117,   117,   117,
+     117,   117,   117,   117,   117,   117,   117,   117,   117,   117,
+     117,   117,   117,   117,   117,   117,   117,   119,   135,   116,
+     120,   116,   116,   116,   116,   119,   119,   143,   119,   119,
+     116,   116,   116,   116,   116,   119,   147,   118,   118,   122,
+     122,   122,   122,     4,   117,   118,   162,   117,   118,   163,
+     117,   118,   164,   117,     3,   117,   118,   165,   117,   118,
+     166,   117,   118,   167,   117,   117,   117,   118,   168,   117,
+     118,   169,   117,   117,   118,   170,   117,   118,   171,   117,
+     117,   117,   118,   172,   117,     6,   117,    85,   104,   105,
+     106,   107,   108,   109,   110,   111,   112,   155,   156,   157,
+     158,   117,     3,    11,    11,    10,    11,    11,   117,   117,
+     117,   117,     3,     5,    12,   117,    11,   101,   102,   103,
+     152,   153,   154,   152,   153,     6,     6,     5,    16,     4,
+       4,     4,     3,     3,     3,     4,     4,     4,     4,     4,
+     116,   116,   116,   116,   116,   116,   116,   116,   116,   116,
+     119,   155,   118,   117,   120,   117,   117,   117,   117,   117,
+     117,   117,   120,   116,   116,   116,   119,   119,   152,   119,
+     119,   123,   123,   123,   123,   120,   120,   120,   120,   120,
+     120,   120,   120,   120,   120,   120,    10,    14,    14,    14,
+       3,     4,     4,     4,   164,    13,   113,   114,   115,   159,
+     160,   161,   119,    11,    11,    11,    11,    15,   117,   117,
+     117,   117,     4,     4,     4,     3,     3,     3,     4,     4,
+       4,     4,     4,   117,   117,   117,   117,   117,   117,   117,
+     117,   117,   120,   116,   116,   116,   119,   119,   160,   117,
+     120,   120,   117,   117,   117,   119,   120,   120,   119,   120,
+     120,   120,   120,   120,   120,   120,    13,    13,    13,    13,
+     117,   117,    10,    15,     4,     4,     3,     3,     4,     4,
+       4,     4,     4,   120,   117,   117,   117,   119,   120,   119,
+     120,   120,   120,   120,   120,   120,    13,     4,     3,     4,
+       4,     4,     4,     4,   119,   119,   120,   120,   120,   120,
+     120,     4,     4,     4,     4,     4,   120,   120,   120,   120,
+     120,     4,     4,     4,     4,     4,   119,   120,   120,   120,
+     120,     4,     4,     4,     4,   120,   120,   120,   120,     4,
+       4,     4,     4,   119,   120,   120,   120,     4,     4,     4,
+     119,   120,   120,     4,     4,   120,   120,     4,     4,   120,
+     120,     4,     4,   119,   120,     4,   120,     4,   120,     4,
+     120,     4,   119
+};
+
+/* Error token number */
+#define YYTERROR 1
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+   If N is 0, then set CURRENT to the empty location which ends
+   the previous symbol: RHS[0] (always defined).  */
+
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)                                \
+    do                                                                  \
+      if (YYID (N))                                                     \
+        {                                                               \
+          (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;        \
+          (Current).first_column = YYRHSLOC (Rhs, 1).first_column;      \
+          (Current).last_line    = YYRHSLOC (Rhs, N).last_line;         \
+          (Current).last_column  = YYRHSLOC (Rhs, N).last_column;       \
+        }                                                               \
+      else                                                              \
+        {                                                               \
+          (Current).first_line   = (Current).last_line   =              \
+            YYRHSLOC (Rhs, 0).last_line;                                \
+          (Current).first_column = (Current).last_column =              \
+            YYRHSLOC (Rhs, 0).last_column;                              \
+        }                                                               \
+    while (YYID (0))
+#endif
+
+# define YYRHSLOC(Rhs, K) ((Rhs)[K].yystate.yyloc)
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+   This macro was not mandated originally: define only if we know
+   we won't break user code: when these are the locations we know.  */
+
+#ifndef __attribute__
+/* This feature is available in gcc versions 2.5 and later.  */
+# if (! defined __GNUC__ || __GNUC__ < 2 \
+      || (__GNUC__ == 2 && __GNUC_MINOR__ < 5))
+#  define __attribute__(Spec) /* empty */
+# endif
+#endif
+
+#ifndef YY_LOCATION_PRINT
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+
+/* Print *YYLOCP on YYO.  Private, do not rely on its existence. */
+
+__attribute__((__unused__))
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static unsigned
+yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp)
+#else
+static unsigned
+yy_location_print_ (yyo, yylocp)
+    FILE *yyo;
+    YYLTYPE const * const yylocp;
+#endif
+{
+  unsigned res = 0;
+  int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0;
+  if (0 <= yylocp->first_line)
+    {
+      res += fprintf (yyo, "%d", yylocp->first_line);
+      if (0 <= yylocp->first_column)
+        res += fprintf (yyo, ".%d", yylocp->first_column);
+    }
+  if (0 <= yylocp->last_line)
+    {
+      if (yylocp->first_line < yylocp->last_line)
+        {
+          res += fprintf (yyo, "-%d", yylocp->last_line);
+          if (0 <= end_col)
+            res += fprintf (yyo, ".%d", end_col);
+        }
+      else if (0 <= end_col && yylocp->first_column < end_col)
+        res += fprintf (yyo, "-%d", end_col);
+    }
+  return res;
+ }
+
+#  define YY_LOCATION_PRINT(File, Loc)          \
+  yy_location_print_ (File, &(Loc))
+
+# else
+#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments.  */
+#define YYLEX yylex (&yylval, &yylloc, scanner)
+
+
+#undef yynerrs
+#define yynerrs (yystackp->yyerrcnt)
+#undef yychar
+#define yychar (yystackp->yyrawchar)
+#undef yylval
+#define yylval (yystackp->yyval)
+#undef yylloc
+#define yylloc (yystackp->yyloc)
+
+
+static const int YYEOF = 0;
+static const int YYEMPTY = -2;
+
+typedef enum { yyok, yyaccept, yyabort, yyerr } YYRESULTTAG;
+
+#define YYCHK(YYE)                                                           \
+   do { YYRESULTTAG yyflag = YYE; if (yyflag != yyok) return yyflag; }       \
+   while (YYID (0))
+
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)                        \
+do {                                            \
+  if (yydebug)                                  \
+    YYFPRINTF Args;                             \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+/*ARGSUSED*/
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, ParseState* parse_state, yyscan_t scanner)
+{
+  FILE *yyo = yyoutput;
+  YYUSE (yyo);
+  if (!yyvaluep)
+    return;
+  YYUSE (yylocationp);
+  YYUSE (parse_state);
+  YYUSE (scanner);
+# ifdef YYPRINT
+  if (yytype < YYNTOKENS)
+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+  YYUSE (yyoutput);
+# endif
+  switch (yytype)
+    {
+      default:
+        break;
+    }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, ParseState* parse_state, yyscan_t scanner)
+{
+  if (yytype < YYNTOKENS)
+    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+  else
+    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+  YY_LOCATION_PRINT (yyoutput, *yylocationp);
+  YYFPRINTF (yyoutput, ": ");
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, parse_state, scanner);
+  YYFPRINTF (yyoutput, ")");
+}
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)          \
+do {                                                            \
+  if (yydebug)                                                  \
+    {                                                           \
+      YYFPRINTF (stderr, "%s ", Title);                         \
+      yy_symbol_print (stderr, Type, Value, Location, parse_state, scanner);        \
+      YYFPRINTF (stderr, "\n");                                 \
+    }                                                           \
+} while (YYID (0))
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+
+#else /* !YYDEBUG */
+
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+
+#endif /* !YYDEBUG */
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   SIZE_MAX < YYMAXDEPTH * sizeof (GLRStackItem)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+/* Minimum number of free items on the stack allowed after an
+   allocation.  This is to allow allocation and initialization
+   to be completed by functions that call yyexpandGLRStack before the
+   stack is expanded, thus insuring that all necessary pointers get
+   properly redirected to new data.  */
+#define YYHEADROOM 2
+
+#ifndef YYSTACKEXPANDABLE
+# if (! defined __cplusplus \
+      || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \
+          && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))
+#  define YYSTACKEXPANDABLE 1
+# else
+#  define YYSTACKEXPANDABLE 0
+# endif
+#endif
+
+#if YYSTACKEXPANDABLE
+# define YY_RESERVE_GLRSTACK(Yystack)                   \
+  do {                                                  \
+    if (Yystack->yyspaceLeft < YYHEADROOM)              \
+      yyexpandGLRStack (Yystack);                       \
+  } while (YYID (0))
+#else
+# define YY_RESERVE_GLRSTACK(Yystack)                   \
+  do {                                                  \
+    if (Yystack->yyspaceLeft < YYHEADROOM)              \
+      yyMemoryExhausted (Yystack);                      \
+  } while (YYID (0))
+#endif
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystpcpy
+#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+{
+  char *yyd = yydest;
+  const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+   quotes and backslashes, so that it's suitable for yyerror.  The
+   heuristic is that double-quoting is unnecessary unless the string
+   contains an apostrophe, a comma, or backslash (other than
+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
+   null, do not copy; instead, return the length of what the result
+   would have been.  */
+static size_t
+yytnamerr (char *yyres, const char *yystr)
+{
+  if (*yystr == '"')
+    {
+      size_t yyn = 0;
+      char const *yyp = yystr;
+
+      for (;;)
+        switch (*++yyp)
+          {
+          case '\'':
+          case ',':
+            goto do_not_strip_quotes;
+
+          case '\\':
+            if (*++yyp != '\\')
+              goto do_not_strip_quotes;
+            /* Fall through.  */
+          default:
+            if (yyres)
+              yyres[yyn] = *yyp;
+            yyn++;
+            break;
+
+          case '"':
+            if (yyres)
+              yyres[yyn] = '\0';
+            return yyn;
+          }
+    do_not_strip_quotes: ;
+    }
+
+  if (! yyres)
+    return strlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+#endif /* !YYERROR_VERBOSE */
+
+/** State numbers, as in LALR(1) machine */
+typedef int yyStateNum;
+
+/** Rule numbers, as in LALR(1) machine */
+typedef int yyRuleNum;
+
+/** Grammar symbol */
+typedef short int yySymbol;
+
+/** Item references, as in LALR(1) machine */
+typedef short int yyItemNum;
+
+typedef struct yyGLRState yyGLRState;
+typedef struct yyGLRStateSet yyGLRStateSet;
+typedef struct yySemanticOption yySemanticOption;
+typedef union yyGLRStackItem yyGLRStackItem;
+typedef struct yyGLRStack yyGLRStack;
+
+struct yyGLRState {
+  /** Type tag: always true.  */
+  yybool yyisState;
+  /** Type tag for yysemantics.  If true, yysval applies, otherwise
+   *  yyfirstVal applies.  */
+  yybool yyresolved;
+  /** Number of corresponding LALR(1) machine state.  */
+  yyStateNum yylrState;
+  /** Preceding state in this stack */
+  yyGLRState* yypred;
+  /** Source position of the first token produced by my symbol */
+  size_t yyposn;
+  union {
+    /** First in a chain of alternative reductions producing the
+     *  non-terminal corresponding to this state, threaded through
+     *  yynext.  */
+    yySemanticOption* yyfirstVal;
+    /** Semantic value for this state.  */
+    YYSTYPE yysval;
+  } yysemantics;
+  /** Source location for this state.  */
+  YYLTYPE yyloc;
+};
+
+struct yyGLRStateSet {
+  yyGLRState** yystates;
+  /** During nondeterministic operation, yylookaheadNeeds tracks which
+   *  stacks have actually needed the current lookahead.  During deterministic
+   *  operation, yylookaheadNeeds[0] is not maintained since it would merely
+   *  duplicate yychar != YYEMPTY.  */
+  yybool* yylookaheadNeeds;
+  size_t yysize, yycapacity;
+};
+
+struct yySemanticOption {
+  /** Type tag: always false.  */
+  yybool yyisState;
+  /** Rule number for this reduction */
+  yyRuleNum yyrule;
+  /** The last RHS state in the list of states to be reduced.  */
+  yyGLRState* yystate;
+  /** The lookahead for this reduction.  */
+  int yyrawchar;
+  YYSTYPE yyval;
+  YYLTYPE yyloc;
+  /** Next sibling in chain of options.  To facilitate merging,
+   *  options are chained in decreasing order by address.  */
+  yySemanticOption* yynext;
+};
+
+/** Type of the items in the GLR stack.  The yyisState field
+ *  indicates which item of the union is valid.  */
+union yyGLRStackItem {
+  yyGLRState yystate;
+  yySemanticOption yyoption;
+};
+
+struct yyGLRStack {
+  int yyerrState;
+  /* To compute the location of the error token.  */
+  yyGLRStackItem yyerror_range[3];
+
+  int yyerrcnt;
+  int yyrawchar;
+  YYSTYPE yyval;
+  YYLTYPE yyloc;
+
+  YYJMP_BUF yyexception_buffer;
+  yyGLRStackItem* yyitems;
+  yyGLRStackItem* yynextFree;
+  size_t yyspaceLeft;
+  yyGLRState* yysplitPoint;
+  yyGLRState* yylastDeleted;
+  yyGLRStateSet yytops;
+};
+
+#if YYSTACKEXPANDABLE
+static void yyexpandGLRStack (yyGLRStack* yystackp);
+#endif
+
+static void yyFail (yyGLRStack* yystackp, YYLTYPE *yylocp, ParseState* parse_state, yyscan_t scanner, const char* yymsg)
+  __attribute__ ((__noreturn__));
+static void
+yyFail (yyGLRStack* yystackp, YYLTYPE *yylocp, ParseState* parse_state, yyscan_t scanner, const char* yymsg)
+{
+  if (yymsg != YY_NULL)
+    yyerror (yylocp, parse_state, scanner, yymsg);
+  YYLONGJMP (yystackp->yyexception_buffer, 1);
+}
+
+static void yyMemoryExhausted (yyGLRStack* yystackp)
+  __attribute__ ((__noreturn__));
+static void
+yyMemoryExhausted (yyGLRStack* yystackp)
+{
+  YYLONGJMP (yystackp->yyexception_buffer, 2);
+}
+
+#if YYDEBUG || YYERROR_VERBOSE
+/** A printable representation of TOKEN.  */
+static inline const char*
+yytokenName (yySymbol yytoken)
+{
+  if (yytoken == YYEMPTY)
+    return "";
+
+  return yytname[yytoken];
+}
+#endif
+
+/** Fill in YYVSP[YYLOW1 .. YYLOW0-1] from the chain of states starting
+ *  at YYVSP[YYLOW0].yystate.yypred.  Leaves YYVSP[YYLOW1].yystate.yypred
+ *  containing the pointer to the next state in the chain.  */
+static void yyfillin (yyGLRStackItem *, int, int) __attribute__ ((__unused__));
+static void
+yyfillin (yyGLRStackItem *yyvsp, int yylow0, int yylow1)
+{
+  int i;
+  yyGLRState *s = yyvsp[yylow0].yystate.yypred;
+  for (i = yylow0-1; i >= yylow1; i -= 1)
+    {
+      YYASSERT (s->yyresolved);
+      yyvsp[i].yystate.yyresolved = yytrue;
+      yyvsp[i].yystate.yysemantics.yysval = s->yysemantics.yysval;
+      yyvsp[i].yystate.yyloc = s->yyloc;
+      s = yyvsp[i].yystate.yypred = s->yypred;
+    }
+}
+
+/* Do nothing if YYNORMAL or if *YYLOW <= YYLOW1.  Otherwise, fill in
+ * YYVSP[YYLOW1 .. *YYLOW-1] as in yyfillin and set *YYLOW = YYLOW1.
+ * For convenience, always return YYLOW1.  */
+static inline int yyfill (yyGLRStackItem *, int *, int, yybool)
+     __attribute__ ((__unused__));
+static inline int
+yyfill (yyGLRStackItem *yyvsp, int *yylow, int yylow1, yybool yynormal)
+{
+  if (!yynormal && yylow1 < *yylow)
+    {
+      yyfillin (yyvsp, *yylow, yylow1);
+      *yylow = yylow1;
+    }
+  return yylow1;
+}
+
+/** Perform user action for rule number YYN, with RHS length YYRHSLEN,
+ *  and top stack item YYVSP.  YYLVALP points to place to put semantic
+ *  value ($$), and yylocp points to place for location information
+ *  (@$).  Returns yyok for normal return, yyaccept for YYACCEPT,
+ *  yyerr for YYERROR, yyabort for YYABORT.  */
+/*ARGSUSED*/ static YYRESULTTAG
+yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp,
+              yyGLRStack* yystackp,
+              YYSTYPE* yyvalp, YYLTYPE *yylocp, ParseState* parse_state, yyscan_t scanner)
+{
+  yybool yynormal __attribute__ ((__unused__)) =
+    (yystackp->yysplitPoint == YY_NULL);
+  int yylow;
+  YYUSE (parse_state);
+  YYUSE (scanner);
+# undef yyerrok
+# define yyerrok (yystackp->yyerrState = 0)
+# undef YYACCEPT
+# define YYACCEPT return yyaccept
+# undef YYABORT
+# define YYABORT return yyabort
+# undef YYERROR
+# define YYERROR return yyerrok, yyerr
+# undef YYRECOVERING
+# define YYRECOVERING() (yystackp->yyerrState != 0)
+# undef yyclearin
+# define yyclearin (yychar = YYEMPTY)
+# undef YYFILL
+# define YYFILL(N) yyfill (yyvsp, &yylow, N, yynormal)
+# undef YYBACKUP
+# define YYBACKUP(Token, Value)                                              \
+  return yyerror (yylocp, parse_state, scanner, YY_("syntax error: cannot back up")),     \
+         yyerrok, yyerr
+
+  yylow = 1;
+  if (yyrhslen == 0)
+    *yyvalp = yyval_default;
+  else
+    *yyvalp = yyvsp[YYFILL (1-yyrhslen)].yystate.yysemantics.yysval;
+  YYLLOC_DEFAULT ((*yylocp), (yyvsp - yyrhslen), yyrhslen);
+  yystackp->yyerror_range[1].yystate.yyloc = *yylocp;
+
+  switch (yyn)
+    {
+        case 2:
+/* Line 868 of glr.c  */
+#line 277 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { }
+    break;
+
+  case 3:
+/* Line 868 of glr.c  */
+#line 278 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.nodeOption)); }
+    break;
+
+  case 5:
+/* Line 868 of glr.c  */
+#line 283 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_Technique; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (1))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 6:
+/* Line 868 of glr.c  */
+#line 284 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_Parameters; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (1))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 7:
+/* Line 868 of glr.c  */
+#line 285 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_Blocks; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (1))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 8:
+/* Line 868 of glr.c  */
+#line 289 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_Separable; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 9:
+/* Line 868 of glr.c  */
+#line 290 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_Queue; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 10:
+/* Line 868 of glr.c  */
+#line 291 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_Priority; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 11:
+/* Line 868 of glr.c  */
+#line 292 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_Transparent; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 12:
+/* Line 868 of glr.c  */
+#line 298 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodePop(parse_state); ((*yyvalp).nodePtr) = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 13:
+/* Line 868 of glr.c  */
+#line 303 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { 
+			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_Technique); 
+			nodePush(parse_state, ((*yyvalp).nodePtr));
+		}
+    break;
+
+  case 15:
+/* Line 868 of glr.c  */
+#line 311 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.nodeOption)); }
+    break;
+
+  case 17:
+/* Line 868 of glr.c  */
+#line 316 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_Pass; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (1))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 19:
+/* Line 868 of glr.c  */
+#line 318 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_Code; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (1))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 20:
+/* Line 868 of glr.c  */
+#line 322 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_Renderer; ((*yyvalp).nodeOption).value.strValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.strValue); }
+    break;
+
+  case 21:
+/* Line 868 of glr.c  */
+#line 323 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_Language; ((*yyvalp).nodeOption).value.strValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.strValue); }
+    break;
+
+  case 22:
+/* Line 868 of glr.c  */
+#line 329 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodePop(parse_state); ((*yyvalp).nodePtr) = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 23:
+/* Line 868 of glr.c  */
+#line 334 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { 
+			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_Pass); 
+			nodePush(parse_state, ((*yyvalp).nodePtr));
+		}
+    break;
+
+  case 25:
+/* Line 868 of glr.c  */
+#line 342 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.nodeOption)); }
+    break;
+
+  case 27:
+/* Line 868 of glr.c  */
+#line 347 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_Code; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (1))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 28:
+/* Line 868 of glr.c  */
+#line 351 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_Index; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 29:
+/* Line 868 of glr.c  */
+#line 352 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_FillMode; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 30:
+/* Line 868 of glr.c  */
+#line 353 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_CullMode; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 31:
+/* Line 868 of glr.c  */
+#line 354 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_DepthBias; ((*yyvalp).nodeOption).value.floatValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.floatValue); }
+    break;
+
+  case 32:
+/* Line 868 of glr.c  */
+#line 355 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_SDepthBias; ((*yyvalp).nodeOption).value.floatValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.floatValue); }
+    break;
+
+  case 33:
+/* Line 868 of glr.c  */
+#line 356 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_DepthClip; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 34:
+/* Line 868 of glr.c  */
+#line 357 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_Scissor; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 35:
+/* Line 868 of glr.c  */
+#line 358 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_Multisample; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 36:
+/* Line 868 of glr.c  */
+#line 359 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_AALine; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 37:
+/* Line 868 of glr.c  */
+#line 360 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_DepthRead; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 38:
+/* Line 868 of glr.c  */
+#line 361 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_DepthWrite; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 39:
+/* Line 868 of glr.c  */
+#line 362 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_CompareFunc; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 40:
+/* Line 868 of glr.c  */
+#line 363 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_Stencil; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 41:
+/* Line 868 of glr.c  */
+#line 364 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_StencilReadMask; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 42:
+/* Line 868 of glr.c  */
+#line 365 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_StencilWriteMask; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 43:
+/* Line 868 of glr.c  */
+#line 366 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_StencilOpFront; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 44:
+/* Line 868 of glr.c  */
+#line 367 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_StencilOpBack; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 45:
+/* Line 868 of glr.c  */
+#line 368 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_StencilOpFront; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 46:
+/* Line 868 of glr.c  */
+#line 369 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_StencilOpBack; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 47:
+/* Line 868 of glr.c  */
+#line 370 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_AlphaToCoverage; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 48:
+/* Line 868 of glr.c  */
+#line 371 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_IndependantBlend; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 49:
+/* Line 868 of glr.c  */
+#line 372 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_Target; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (1))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 50:
+/* Line 868 of glr.c  */
+#line 373 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_StencilRef; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 51:
+/* Line 868 of glr.c  */
+#line 380 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    {
+		NodeOption index;
+		index.type = OT_Index; 
+		index.value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((5) - (8))].yystate.yysemantics.yysval.intValue);
+
+		nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &index);
+
+		nodePop(parse_state); 
+		((*yyvalp).nodePtr) = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (8))].yystate.yysemantics.yysval.nodePtr);
+	}
+    break;
+
+  case 52:
+/* Line 868 of glr.c  */
+#line 394 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { 
+			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_CodeVertex); 
+			nodePush(parse_state, ((*yyvalp).nodePtr));
+		}
+    break;
+
+  case 53:
+/* Line 868 of glr.c  */
+#line 399 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { 
+			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_CodeFragment); 
+			nodePush(parse_state, ((*yyvalp).nodePtr));
+		}
+    break;
+
+  case 54:
+/* Line 868 of glr.c  */
+#line 404 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { 
+			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_CodeGeometry); 
+			nodePush(parse_state, ((*yyvalp).nodePtr));
+		}
+    break;
+
+  case 55:
+/* Line 868 of glr.c  */
+#line 409 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { 
+			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_CodeHull); 
+			nodePush(parse_state, ((*yyvalp).nodePtr));
+		}
+    break;
+
+  case 56:
+/* Line 868 of glr.c  */
+#line 414 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { 
+			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_CodeDomain); 
+			nodePush(parse_state, ((*yyvalp).nodePtr));
+		}
+    break;
+
+  case 57:
+/* Line 868 of glr.c  */
+#line 419 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { 
+			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_CodeCompute); 
+			nodePush(parse_state, ((*yyvalp).nodePtr));
+		}
+    break;
+
+  case 58:
+/* Line 868 of glr.c  */
+#line 424 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { 
+			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_CodeCommon); 
+			nodePush(parse_state, ((*yyvalp).nodePtr));
+		}
+    break;
+
+  case 59:
+/* Line 868 of glr.c  */
+#line 434 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { 
+			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_StencilOp); 
+			nodePush(parse_state, ((*yyvalp).nodePtr));
+		}
+    break;
+
+  case 60:
+/* Line 868 of glr.c  */
+#line 442 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { 
+			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_StencilOp); 
+			nodePush(parse_state, ((*yyvalp).nodePtr));
+		}
+    break;
+
+  case 61:
+/* Line 868 of glr.c  */
+#line 450 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    {
+			NodeOption fail; fail.type = OT_Fail; fail.value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (7))].yystate.yysemantics.yysval.intValue);
+			NodeOption zfail; zfail.type = OT_ZFail; zfail.value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (7))].yystate.yysemantics.yysval.intValue);
+			NodeOption pass; pass.type = OT_PassOp; pass.value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((5) - (7))].yystate.yysemantics.yysval.intValue);
+			NodeOption cmp; cmp.type = OT_CompareFunc; cmp.value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((7) - (7))].yystate.yysemantics.yysval.intValue);
+
+			nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &fail);
+			nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &zfail);
+			nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &pass);
+			nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &cmp);
+		}
+    break;
+
+  case 63:
+/* Line 868 of glr.c  */
+#line 465 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.nodeOption)); }
+    break;
+
+  case 64:
+/* Line 868 of glr.c  */
+#line 469 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_Fail; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 65:
+/* Line 868 of glr.c  */
+#line 470 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_ZFail; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 66:
+/* Line 868 of glr.c  */
+#line 471 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_PassOp; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 67:
+/* Line 868 of glr.c  */
+#line 472 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_CompareFunc; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 68:
+/* Line 868 of glr.c  */
+#line 477 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodePop(parse_state); ((*yyvalp).nodePtr) = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 69:
+/* Line 868 of glr.c  */
+#line 482 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { 
+			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_Target); 
+			nodePush(parse_state, ((*yyvalp).nodePtr));
+		}
+    break;
+
+  case 71:
+/* Line 868 of glr.c  */
+#line 490 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.nodeOption)); }
+    break;
+
+  case 73:
+/* Line 868 of glr.c  */
+#line 498 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_Index; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 74:
+/* Line 868 of glr.c  */
+#line 499 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_Blend; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 75:
+/* Line 868 of glr.c  */
+#line 500 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Color; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 76:
+/* Line 868 of glr.c  */
+#line 501 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Alpha; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 77:
+/* Line 868 of glr.c  */
+#line 502 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Color; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 78:
+/* Line 868 of glr.c  */
+#line 503 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Alpha; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 79:
+/* Line 868 of glr.c  */
+#line 504 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_WriteMask; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 80:
+/* Line 868 of glr.c  */
+#line 510 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { 
+			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_BlendDef); 
+			nodePush(parse_state, ((*yyvalp).nodePtr));
+		}
+    break;
+
+  case 81:
+/* Line 868 of glr.c  */
+#line 518 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { 
+			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_BlendDef); 
+			nodePush(parse_state, ((*yyvalp).nodePtr));
+		}
+    break;
+
+  case 83:
+/* Line 868 of glr.c  */
+#line 526 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.nodeOption)); }
+    break;
+
+  case 84:
+/* Line 868 of glr.c  */
+#line 531 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    {
+			NodeOption src; src.type = OT_Source; src.value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.intValue);
+			NodeOption dst; dst.type = OT_Dest; dst.value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (5))].yystate.yysemantics.yysval.intValue);
+			NodeOption op; op.type = OT_Op; op.value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((5) - (5))].yystate.yysemantics.yysval.intValue);
+
+			nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &src);
+			nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &dst);
+			nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &op);
+		}
+    break;
+
+  case 85:
+/* Line 868 of glr.c  */
+#line 543 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_Source; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 86:
+/* Line 868 of glr.c  */
+#line 544 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_Dest; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 87:
+/* Line 868 of glr.c  */
+#line 545 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_Op; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 89:
+/* Line 868 of glr.c  */
+#line 552 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.nodeOption)); }
+    break;
+
+  case 90:
+/* Line 868 of glr.c  */
+#line 556 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_AddrMode; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (1))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 91:
+/* Line 868 of glr.c  */
+#line 557 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_MinFilter; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 92:
+/* Line 868 of glr.c  */
+#line 558 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_MagFilter; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 93:
+/* Line 868 of glr.c  */
+#line 559 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_MipFilter; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 94:
+/* Line 868 of glr.c  */
+#line 560 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_MaxAniso; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 95:
+/* Line 868 of glr.c  */
+#line 561 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_MipBias; ((*yyvalp).nodeOption).value.floatValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.floatValue); }
+    break;
+
+  case 96:
+/* Line 868 of glr.c  */
+#line 562 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_MipMin; ((*yyvalp).nodeOption).value.floatValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.floatValue); }
+    break;
+
+  case 97:
+/* Line 868 of glr.c  */
+#line 563 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_MipMax; ((*yyvalp).nodeOption).value.floatValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.floatValue); }
+    break;
+
+  case 98:
+/* Line 868 of glr.c  */
+#line 564 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_BorderColor; memcpy(((*yyvalp).nodeOption).value.matrixValue, (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.matrixValue), sizeof((((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.matrixValue))); }
+    break;
+
+  case 99:
+/* Line 868 of glr.c  */
+#line 565 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_CompareFunc; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 100:
+/* Line 868 of glr.c  */
+#line 570 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodePop(parse_state); ((*yyvalp).nodePtr) = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 101:
+/* Line 868 of glr.c  */
+#line 571 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodePop(parse_state); ((*yyvalp).nodePtr) = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 102:
+/* Line 868 of glr.c  */
+#line 576 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { 
+			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_AddrMode); 
+			nodePush(parse_state, ((*yyvalp).nodePtr));
+		}
+    break;
+
+  case 103:
+/* Line 868 of glr.c  */
+#line 584 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    {
+			NodeOption u; u.type = OT_U; u.value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.intValue);
+			NodeOption v; v.type = OT_V; v.value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (5))].yystate.yysemantics.yysval.intValue);
+			NodeOption w; w.type = OT_W; w.value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((5) - (5))].yystate.yysemantics.yysval.intValue);
+
+			nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &u);
+			nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &v);
+			nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &w);
+		}
+    break;
+
+  case 105:
+/* Line 868 of glr.c  */
+#line 597 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.nodeOption)); }
+    break;
+
+  case 106:
+/* Line 868 of glr.c  */
+#line 601 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_U; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 107:
+/* Line 868 of glr.c  */
+#line 602 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_V; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 108:
+/* Line 868 of glr.c  */
+#line 603 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_W; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 109:
+/* Line 868 of glr.c  */
+#line 608 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).matrixValue)[0] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (5))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[1] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((4) - (5))].yystate.yysemantics.yysval.floatValue); }
+    break;
+
+  case 110:
+/* Line 868 of glr.c  */
+#line 612 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).matrixValue)[0] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (7))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[1] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((4) - (7))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[2] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((6) - (7))].yystate.yysemantics.yysval.floatValue); }
+    break;
+
+  case 111:
+/* Line 868 of glr.c  */
+#line 616 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).matrixValue)[0] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (9))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[1] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((4) - (9))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[2] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((6) - (9))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[3] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((8) - (9))].yystate.yysemantics.yysval.floatValue);}
+    break;
+
+  case 112:
+/* Line 868 of glr.c  */
+#line 620 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).intVectorValue)[0] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (5))].yystate.yysemantics.yysval.intValue); ((*yyvalp).intVectorValue)[1] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((4) - (5))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 113:
+/* Line 868 of glr.c  */
+#line 624 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).intVectorValue)[0] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (7))].yystate.yysemantics.yysval.intValue); ((*yyvalp).intVectorValue)[1] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((4) - (7))].yystate.yysemantics.yysval.intValue); ((*yyvalp).intVectorValue)[2] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((6) - (7))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 114:
+/* Line 868 of glr.c  */
+#line 628 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).intVectorValue)[0] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (9))].yystate.yysemantics.yysval.intValue); ((*yyvalp).intVectorValue)[1] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((4) - (9))].yystate.yysemantics.yysval.intValue); ((*yyvalp).intVectorValue)[2] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((6) - (9))].yystate.yysemantics.yysval.intValue); ((*yyvalp).intVectorValue)[3] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((8) - (9))].yystate.yysemantics.yysval.intValue);}
+    break;
+
+  case 115:
+/* Line 868 of glr.c  */
+#line 634 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { 
+			((*yyvalp).matrixValue)[0] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (13))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[1] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((4) - (13))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[2] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((6) - (13))].yystate.yysemantics.yysval.floatValue); 
+			((*yyvalp).matrixValue)[3] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((8) - (13))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[4] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((10) - (13))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[5] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((12) - (13))].yystate.yysemantics.yysval.floatValue);
+		}
+    break;
+
+  case 116:
+/* Line 868 of glr.c  */
+#line 644 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { 
+			((*yyvalp).matrixValue)[0] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (17))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[1] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((4) - (17))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[2] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((6) - (17))].yystate.yysemantics.yysval.floatValue); 
+			((*yyvalp).matrixValue)[3] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((8) - (17))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[4] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((10) - (17))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[5] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((12) - (17))].yystate.yysemantics.yysval.floatValue);
+			((*yyvalp).matrixValue)[6] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((14) - (17))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[7] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((16) - (17))].yystate.yysemantics.yysval.floatValue);
+		}
+    break;
+
+  case 117:
+/* Line 868 of glr.c  */
+#line 655 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { 
+			((*yyvalp).matrixValue)[0] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (19))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[1] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((4) - (19))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[2] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((6) - (19))].yystate.yysemantics.yysval.floatValue); 
+			((*yyvalp).matrixValue)[3] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((8) - (19))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[4] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((10) - (19))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[5] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((12) - (19))].yystate.yysemantics.yysval.floatValue);
+			((*yyvalp).matrixValue)[6] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((14) - (19))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[7] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((16) - (19))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[8] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((18) - (19))].yystate.yysemantics.yysval.floatValue);
+		}
+    break;
+
+  case 118:
+/* Line 868 of glr.c  */
+#line 666 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { 
+			((*yyvalp).matrixValue)[0] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (25))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[1] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((4) - (25))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[2] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((6) - (25))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[3] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((8) - (25))].yystate.yysemantics.yysval.floatValue); 
+			((*yyvalp).matrixValue)[4] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((10) - (25))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[5] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((12) - (25))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[6] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((14) - (25))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[7] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((16) - (25))].yystate.yysemantics.yysval.floatValue); 
+			((*yyvalp).matrixValue)[8] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((18) - (25))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[9] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((20) - (25))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[10] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((22) - (25))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[11] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((24) - (25))].yystate.yysemantics.yysval.floatValue);
+		}
+    break;
+
+  case 119:
+/* Line 868 of glr.c  */
+#line 678 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { 
+			((*yyvalp).matrixValue)[0] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (33))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[1] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((4) - (33))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[2] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((6) - (33))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[3] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((8) - (33))].yystate.yysemantics.yysval.floatValue); 
+			((*yyvalp).matrixValue)[4] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((10) - (33))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[5] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((12) - (33))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[6] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((14) - (33))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[7] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((16) - (33))].yystate.yysemantics.yysval.floatValue); 
+			((*yyvalp).matrixValue)[8] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((18) - (33))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[9] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((20) - (33))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[10] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((22) - (33))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[11] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((24) - (33))].yystate.yysemantics.yysval.floatValue);
+			((*yyvalp).matrixValue)[12] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((26) - (33))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[13] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((28) - (33))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[14] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((30) - (33))].yystate.yysemantics.yysval.floatValue); ((*yyvalp).matrixValue)[15] = (((yyGLRStackItem const *)yyvsp)[YYFILL ((32) - (33))].yystate.yysemantics.yysval.floatValue);
+		}
+    break;
+
+  case 120:
+/* Line 868 of glr.c  */
+#line 688 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodePop(parse_state); ((*yyvalp).nodePtr) = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 121:
+/* Line 868 of glr.c  */
+#line 693 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { 
+			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_Parameters); 
+			nodePush(parse_state, ((*yyvalp).nodePtr));
+		}
+    break;
+
+  case 123:
+/* Line 868 of glr.c  */
+#line 701 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.nodeOption)); }
+    break;
+
+  case 124:
+/* Line 868 of glr.c  */
+#line 705 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 125:
+/* Line 868 of glr.c  */
+#line 706 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 126:
+/* Line 868 of glr.c  */
+#line 707 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 127:
+/* Line 868 of glr.c  */
+#line 708 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 128:
+/* Line 868 of glr.c  */
+#line 709 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 129:
+/* Line 868 of glr.c  */
+#line 710 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 130:
+/* Line 868 of glr.c  */
+#line 711 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 131:
+/* Line 868 of glr.c  */
+#line 712 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 132:
+/* Line 868 of glr.c  */
+#line 713 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 133:
+/* Line 868 of glr.c  */
+#line 714 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 134:
+/* Line 868 of glr.c  */
+#line 715 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 135:
+/* Line 868 of glr.c  */
+#line 716 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 136:
+/* Line 868 of glr.c  */
+#line 717 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 137:
+/* Line 868 of glr.c  */
+#line 718 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 138:
+/* Line 868 of glr.c  */
+#line 719 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 139:
+/* Line 868 of glr.c  */
+#line 720 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 140:
+/* Line 868 of glr.c  */
+#line 721 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 141:
+/* Line 868 of glr.c  */
+#line 722 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 142:
+/* Line 868 of glr.c  */
+#line 723 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.nodeOption)); nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (4))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 143:
+/* Line 868 of glr.c  */
+#line 724 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (3))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 144:
+/* Line 868 of glr.c  */
+#line 726 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { 
+			nodePop(parse_state);
+
+			NodeOption samplerState;
+			samplerState.type = OT_SamplerState;
+			samplerState.value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (3))].yystate.yysemantics.yysval.nodePtr);
+
+			nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &samplerState); 
+
+			((*yyvalp).nodeOption).type = OT_Parameter; ((*yyvalp).nodeOption).value.nodePtr = parse_state->topNode; 
+			nodePop(parse_state); 
+		}
+    break;
+
+  case 145:
+/* Line 868 of glr.c  */
+#line 741 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 146:
+/* Line 868 of glr.c  */
+#line 745 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 147:
+/* Line 868 of glr.c  */
+#line 749 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 148:
+/* Line 868 of glr.c  */
+#line 753 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 149:
+/* Line 868 of glr.c  */
+#line 757 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 150:
+/* Line 868 of glr.c  */
+#line 761 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 151:
+/* Line 868 of glr.c  */
+#line 765 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 152:
+/* Line 868 of glr.c  */
+#line 769 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 153:
+/* Line 868 of glr.c  */
+#line 773 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 154:
+/* Line 868 of glr.c  */
+#line 777 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 155:
+/* Line 868 of glr.c  */
+#line 781 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 156:
+/* Line 868 of glr.c  */
+#line 785 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 157:
+/* Line 868 of glr.c  */
+#line 789 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 158:
+/* Line 868 of glr.c  */
+#line 793 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 159:
+/* Line 868 of glr.c  */
+#line 797 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 160:
+/* Line 868 of glr.c  */
+#line 801 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 161:
+/* Line 868 of glr.c  */
+#line 805 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 162:
+/* Line 868 of glr.c  */
+#line 809 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 163:
+/* Line 868 of glr.c  */
+#line 813 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 164:
+/* Line 868 of glr.c  */
+#line 814 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 165:
+/* Line 868 of glr.c  */
+#line 815 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 166:
+/* Line 868 of glr.c  */
+#line 816 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 167:
+/* Line 868 of glr.c  */
+#line 817 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 168:
+/* Line 868 of glr.c  */
+#line 821 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 169:
+/* Line 868 of glr.c  */
+#line 822 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 170:
+/* Line 868 of glr.c  */
+#line 823 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 171:
+/* Line 868 of glr.c  */
+#line 824 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 172:
+/* Line 868 of glr.c  */
+#line 825 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 173:
+/* Line 868 of glr.c  */
+#line 829 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 174:
+/* Line 868 of glr.c  */
+#line 830 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 175:
+/* Line 868 of glr.c  */
+#line 831 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 176:
+/* Line 868 of glr.c  */
+#line 832 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 177:
+/* Line 868 of glr.c  */
+#line 833 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 178:
+/* Line 868 of glr.c  */
+#line 834 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 179:
+/* Line 868 of glr.c  */
+#line 835 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ADD_PARAMETER(((*yyvalp).nodePtr), (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.intValue), (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue)); }
+    break;
+
+  case 180:
+/* Line 868 of glr.c  */
+#line 840 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { 
+			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_SamplerState); 
+			nodePush(parse_state, ((*yyvalp).nodePtr));
+		}
+    break;
+
+  case 181:
+/* Line 868 of glr.c  */
+#line 847 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_None; }
+    break;
+
+  case 182:
+/* Line 868 of glr.c  */
+#line 848 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_ParamValue; ((*yyvalp).nodeOption).value.floatValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.floatValue); }
+    break;
+
+  case 183:
+/* Line 868 of glr.c  */
+#line 852 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_None; }
+    break;
+
+  case 184:
+/* Line 868 of glr.c  */
+#line 853 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_ParamValue; memcpy(((*yyvalp).nodeOption).value.matrixValue, (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue), sizeof((((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue))); }
+    break;
+
+  case 185:
+/* Line 868 of glr.c  */
+#line 857 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_None; }
+    break;
+
+  case 186:
+/* Line 868 of glr.c  */
+#line 858 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_ParamValue; memcpy(((*yyvalp).nodeOption).value.matrixValue, (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue), sizeof((((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue))); }
+    break;
+
+  case 187:
+/* Line 868 of glr.c  */
+#line 862 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_None; }
+    break;
+
+  case 188:
+/* Line 868 of glr.c  */
+#line 863 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_ParamValue; memcpy(((*yyvalp).nodeOption).value.matrixValue, (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue), sizeof((((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue))); }
+    break;
+
+  case 189:
+/* Line 868 of glr.c  */
+#line 867 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_None; }
+    break;
+
+  case 190:
+/* Line 868 of glr.c  */
+#line 868 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_ParamValue; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 191:
+/* Line 868 of glr.c  */
+#line 872 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_None; }
+    break;
+
+  case 192:
+/* Line 868 of glr.c  */
+#line 873 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_ParamValue; memcpy(((*yyvalp).nodeOption).value.intVectorValue, (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.intVectorValue), sizeof((((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.intVectorValue))); }
+    break;
+
+  case 193:
+/* Line 868 of glr.c  */
+#line 877 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_None; }
+    break;
+
+  case 194:
+/* Line 868 of glr.c  */
+#line 878 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_ParamValue; memcpy(((*yyvalp).nodeOption).value.intVectorValue, (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.intVectorValue), sizeof((((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.intVectorValue))); }
+    break;
+
+  case 195:
+/* Line 868 of glr.c  */
+#line 882 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_None; }
+    break;
+
+  case 196:
+/* Line 868 of glr.c  */
+#line 883 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_ParamValue; memcpy(((*yyvalp).nodeOption).value.intVectorValue, (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.intVectorValue), sizeof((((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.intVectorValue))); }
+    break;
+
+  case 197:
+/* Line 868 of glr.c  */
+#line 887 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_None; }
+    break;
+
+  case 198:
+/* Line 868 of glr.c  */
+#line 888 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_ParamValue; memcpy(((*yyvalp).nodeOption).value.matrixValue, (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue), sizeof((((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue))); }
+    break;
+
+  case 199:
+/* Line 868 of glr.c  */
+#line 892 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_None; }
+    break;
+
+  case 200:
+/* Line 868 of glr.c  */
+#line 893 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_ParamValue; memcpy(((*yyvalp).nodeOption).value.matrixValue, (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue), sizeof((((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue))); }
+    break;
+
+  case 201:
+/* Line 868 of glr.c  */
+#line 897 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_None; }
+    break;
+
+  case 202:
+/* Line 868 of glr.c  */
+#line 898 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_ParamValue; memcpy(((*yyvalp).nodeOption).value.matrixValue, (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue), sizeof((((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue))); }
+    break;
+
+  case 203:
+/* Line 868 of glr.c  */
+#line 902 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_None; }
+    break;
+
+  case 204:
+/* Line 868 of glr.c  */
+#line 903 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_ParamValue; memcpy(((*yyvalp).nodeOption).value.matrixValue, (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue), sizeof((((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue))); }
+    break;
+
+  case 205:
+/* Line 868 of glr.c  */
+#line 907 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_None; }
+    break;
+
+  case 206:
+/* Line 868 of glr.c  */
+#line 908 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_ParamValue; memcpy(((*yyvalp).nodeOption).value.matrixValue, (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue), sizeof((((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.matrixValue))); }
+    break;
+
+  case 207:
+/* Line 868 of glr.c  */
+#line 912 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_None; }
+    break;
+
+  case 208:
+/* Line 868 of glr.c  */
+#line 913 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { }
+    break;
+
+  case 209:
+/* Line 868 of glr.c  */
+#line 917 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_None; }
+    break;
+
+  case 210:
+/* Line 868 of glr.c  */
+#line 918 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_ParamStrValue; ((*yyvalp).nodeOption).value.strValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue); }
+    break;
+
+  case 211:
+/* Line 868 of glr.c  */
+#line 923 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodePop(parse_state); ((*yyvalp).nodePtr) = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (5))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 212:
+/* Line 868 of glr.c  */
+#line 928 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { 
+			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_Blocks); 
+			nodePush(parse_state, ((*yyvalp).nodePtr));
+		}
+    break;
+
+  case 214:
+/* Line 868 of glr.c  */
+#line 936 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.nodeOption)); }
+    break;
+
+  case 215:
+/* Line 868 of glr.c  */
+#line 940 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodePop(parse_state); ((*yyvalp).nodeOption).type = OT_Block; ((*yyvalp).nodeOption).value.nodePtr = (((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (3))].yystate.yysemantics.yysval.nodePtr); }
+    break;
+
+  case 216:
+/* Line 868 of glr.c  */
+#line 945 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    {
+			((*yyvalp).nodePtr) = nodeCreate(parse_state->memContext, NT_Block);
+			nodePush(parse_state, ((*yyvalp).nodePtr));
+
+			NodeOption blockName;
+			blockName.type = OT_Identifier;
+			blockName.value.strValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((2) - (2))].yystate.yysemantics.yysval.strValue);
+
+			nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &blockName);
+		}
+    break;
+
+  case 218:
+/* Line 868 of glr.c  */
+#line 960 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.nodeOption)); }
+    break;
+
+  case 219:
+/* Line 868 of glr.c  */
+#line 964 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_Alias; ((*yyvalp).nodeOption).value.strValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((4) - (5))].yystate.yysemantics.yysval.strValue); }
+    break;
+
+  case 220:
+/* Line 868 of glr.c  */
+#line 965 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_Auto; ((*yyvalp).nodeOption).value.strValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((4) - (5))].yystate.yysemantics.yysval.strValue); }
+    break;
+
+  case 221:
+/* Line 868 of glr.c  */
+#line 966 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_Shared; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((4) - (5))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+  case 222:
+/* Line 868 of glr.c  */
+#line 967 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+    { ((*yyvalp).nodeOption).type = OT_Usage; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((4) - (5))].yystate.yysemantics.yysval.intValue); }
+    break;
+
+
+/* Line 868 of glr.c  */
+#line 2974 "BsParserFX.c"
+      default: break;
+    }
+
+  return yyok;
+# undef yyerrok
+# undef YYABORT
+# undef YYACCEPT
+# undef YYERROR
+# undef YYBACKUP
+# undef yyclearin
+# undef YYRECOVERING
+}
+
+
+/*ARGSUSED*/ static void
+yyuserMerge (int yyn, YYSTYPE* yy0, YYSTYPE* yy1)
+{
+  YYUSE (yy0);
+  YYUSE (yy1);
+
+  switch (yyn)
+    {
+      
+      default: break;
+    }
+}
+
+                              /* Bison grammar-table manipulation.  */
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, ParseState* parse_state, yyscan_t scanner)
+{
+  YYUSE (yyvaluep);
+  YYUSE (yylocationp);
+  YYUSE (parse_state);
+  YYUSE (scanner);
+
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+  switch (yytype)
+    {
+
+      default:
+        break;
+    }
+}
+
+/** Number of symbols composing the right hand side of rule #RULE.  */
+static inline int
+yyrhsLength (yyRuleNum yyrule)
+{
+  return yyr2[yyrule];
+}
+
+static void
+yydestroyGLRState (char const *yymsg, yyGLRState *yys, ParseState* parse_state, yyscan_t scanner)
+{
+  if (yys->yyresolved)
+    yydestruct (yymsg, yystos[yys->yylrState],
+                &yys->yysemantics.yysval, &yys->yyloc, parse_state, scanner);
+  else
+    {
+#if YYDEBUG
+      if (yydebug)
+        {
+          if (yys->yysemantics.yyfirstVal)
+            YYFPRINTF (stderr, "%s unresolved ", yymsg);
+          else
+            YYFPRINTF (stderr, "%s incomplete ", yymsg);
+          yy_symbol_print (stderr, yystos[yys->yylrState],
+                           YY_NULL, &yys->yyloc, parse_state, scanner);
+          YYFPRINTF (stderr, "\n");
+        }
+#endif
+
+      if (yys->yysemantics.yyfirstVal)
+        {
+          yySemanticOption *yyoption = yys->yysemantics.yyfirstVal;
+          yyGLRState *yyrh;
+          int yyn;
+          for (yyrh = yyoption->yystate, yyn = yyrhsLength (yyoption->yyrule);
+               yyn > 0;
+               yyrh = yyrh->yypred, yyn -= 1)
+            yydestroyGLRState (yymsg, yyrh, parse_state, scanner);
+        }
+    }
+}
+
+/** Left-hand-side symbol for rule #RULE.  */
+static inline yySymbol
+yylhsNonterm (yyRuleNum yyrule)
+{
+  return yyr1[yyrule];
+}
+
+#define yypact_value_is_default(Yystate) \
+  (!!((Yystate) == (-354)))
+
+/** True iff LR state STATE has only a default reduction (regardless
+ *  of token).  */
+static inline yybool
+yyisDefaultedState (yyStateNum yystate)
+{
+  return yypact_value_is_default (yypact[yystate]);
+}
+
+/** The default reduction for STATE, assuming it has one.  */
+static inline yyRuleNum
+yydefaultAction (yyStateNum yystate)
+{
+  return yydefact[yystate];
+}
+
+#define yytable_value_is_error(Yytable_value) \
+  YYID (0)
+
+/** Set *YYACTION to the action to take in YYSTATE on seeing YYTOKEN.
+ *  Result R means
+ *    R < 0:  Reduce on rule -R.
+ *    R = 0:  Error.
+ *    R > 0:  Shift to state R.
+ *  Set *CONFLICTS to a pointer into yyconfl to 0-terminated list of
+ *  conflicting reductions.
+ */
+static inline void
+yygetLRActions (yyStateNum yystate, int yytoken,
+                int* yyaction, const short int** yyconflicts)
+{
+  int yyindex = yypact[yystate] + yytoken;
+  if (yypact_value_is_default (yypact[yystate])
+      || yyindex < 0 || YYLAST < yyindex || yycheck[yyindex] != yytoken)
+    {
+      *yyaction = -yydefact[yystate];
+      *yyconflicts = yyconfl;
+    }
+  else if (! yytable_value_is_error (yytable[yyindex]))
+    {
+      *yyaction = yytable[yyindex];
+      *yyconflicts = yyconfl + yyconflp[yyindex];
+    }
+  else
+    {
+      *yyaction = 0;
+      *yyconflicts = yyconfl + yyconflp[yyindex];
+    }
+}
+
+static inline yyStateNum
+yyLRgotoState (yyStateNum yystate, yySymbol yylhs)
+{
+  int yyr;
+  yyr = yypgoto[yylhs - YYNTOKENS] + yystate;
+  if (0 <= yyr && yyr <= YYLAST && yycheck[yyr] == yystate)
+    return yytable[yyr];
+  else
+    return yydefgoto[yylhs - YYNTOKENS];
+}
+
+static inline yybool
+yyisShiftAction (int yyaction)
+{
+  return 0 < yyaction;
+}
+
+static inline yybool
+yyisErrorAction (int yyaction)
+{
+  return yyaction == 0;
+}
+
+                                /* GLRStates */
+
+/** Return a fresh GLRStackItem.  Callers should call
+ * YY_RESERVE_GLRSTACK afterwards to make sure there is sufficient
+ * headroom.  */
+
+static inline yyGLRStackItem*
+yynewGLRStackItem (yyGLRStack* yystackp, yybool yyisState)
+{
+  yyGLRStackItem* yynewItem = yystackp->yynextFree;
+  yystackp->yyspaceLeft -= 1;
+  yystackp->yynextFree += 1;
+  yynewItem->yystate.yyisState = yyisState;
+  return yynewItem;
+}
+
+/** Add a new semantic action that will execute the action for rule
+ *  RULENUM on the semantic values in RHS to the list of
+ *  alternative actions for STATE.  Assumes that RHS comes from
+ *  stack #K of *STACKP. */
+static void
+yyaddDeferredAction (yyGLRStack* yystackp, size_t yyk, yyGLRState* yystate,
+                     yyGLRState* rhs, yyRuleNum yyrule)
+{
+  yySemanticOption* yynewOption =
+    &yynewGLRStackItem (yystackp, yyfalse)->yyoption;
+  yynewOption->yystate = rhs;
+  yynewOption->yyrule = yyrule;
+  if (yystackp->yytops.yylookaheadNeeds[yyk])
+    {
+      yynewOption->yyrawchar = yychar;
+      yynewOption->yyval = yylval;
+      yynewOption->yyloc = yylloc;
+    }
+  else
+    yynewOption->yyrawchar = YYEMPTY;
+  yynewOption->yynext = yystate->yysemantics.yyfirstVal;
+  yystate->yysemantics.yyfirstVal = yynewOption;
+
+  YY_RESERVE_GLRSTACK (yystackp);
+}
+
+                                /* GLRStacks */
+
+/** Initialize SET to a singleton set containing an empty stack.  */
+static yybool
+yyinitStateSet (yyGLRStateSet* yyset)
+{
+  yyset->yysize = 1;
+  yyset->yycapacity = 16;
+  yyset->yystates = (yyGLRState**) YYMALLOC (16 * sizeof yyset->yystates[0]);
+  if (! yyset->yystates)
+    return yyfalse;
+  yyset->yystates[0] = YY_NULL;
+  yyset->yylookaheadNeeds =
+    (yybool*) YYMALLOC (16 * sizeof yyset->yylookaheadNeeds[0]);
+  if (! yyset->yylookaheadNeeds)
+    {
+      YYFREE (yyset->yystates);
+      return yyfalse;
+    }
+  return yytrue;
+}
+
+static void yyfreeStateSet (yyGLRStateSet* yyset)
+{
+  YYFREE (yyset->yystates);
+  YYFREE (yyset->yylookaheadNeeds);
+}
+
+/** Initialize STACK to a single empty stack, with total maximum
+ *  capacity for all stacks of SIZE.  */
+static yybool
+yyinitGLRStack (yyGLRStack* yystackp, size_t yysize)
+{
+  yystackp->yyerrState = 0;
+  yynerrs = 0;
+  yystackp->yyspaceLeft = yysize;
+  yystackp->yyitems =
+    (yyGLRStackItem*) YYMALLOC (yysize * sizeof yystackp->yynextFree[0]);
+  if (!yystackp->yyitems)
+    return yyfalse;
+  yystackp->yynextFree = yystackp->yyitems;
+  yystackp->yysplitPoint = YY_NULL;
+  yystackp->yylastDeleted = YY_NULL;
+  return yyinitStateSet (&yystackp->yytops);
+}
+
+
+#if YYSTACKEXPANDABLE
+# define YYRELOC(YYFROMITEMS,YYTOITEMS,YYX,YYTYPE) \
+  &((YYTOITEMS) - ((YYFROMITEMS) - (yyGLRStackItem*) (YYX)))->YYTYPE
+
+/** If STACK is expandable, extend it.  WARNING: Pointers into the
+    stack from outside should be considered invalid after this call.
+    We always expand when there are 1 or fewer items left AFTER an
+    allocation, so that we can avoid having external pointers exist
+    across an allocation.  */
+static void
+yyexpandGLRStack (yyGLRStack* yystackp)
+{
+  yyGLRStackItem* yynewItems;
+  yyGLRStackItem* yyp0, *yyp1;
+  size_t yynewSize;
+  size_t yyn;
+  size_t yysize = yystackp->yynextFree - yystackp->yyitems;
+  if (YYMAXDEPTH - YYHEADROOM < yysize)
+    yyMemoryExhausted (yystackp);
+  yynewSize = 2*yysize;
+  if (YYMAXDEPTH < yynewSize)
+    yynewSize = YYMAXDEPTH;
+  yynewItems = (yyGLRStackItem*) YYMALLOC (yynewSize * sizeof yynewItems[0]);
+  if (! yynewItems)
+    yyMemoryExhausted (yystackp);
+  for (yyp0 = yystackp->yyitems, yyp1 = yynewItems, yyn = yysize;
+       0 < yyn;
+       yyn -= 1, yyp0 += 1, yyp1 += 1)
+    {
+      *yyp1 = *yyp0;
+      if (*(yybool *) yyp0)
+        {
+          yyGLRState* yys0 = &yyp0->yystate;
+          yyGLRState* yys1 = &yyp1->yystate;
+          if (yys0->yypred != YY_NULL)
+            yys1->yypred =
+              YYRELOC (yyp0, yyp1, yys0->yypred, yystate);
+          if (! yys0->yyresolved && yys0->yysemantics.yyfirstVal != YY_NULL)
+            yys1->yysemantics.yyfirstVal =
+              YYRELOC (yyp0, yyp1, yys0->yysemantics.yyfirstVal, yyoption);
+        }
+      else
+        {
+          yySemanticOption* yyv0 = &yyp0->yyoption;
+          yySemanticOption* yyv1 = &yyp1->yyoption;
+          if (yyv0->yystate != YY_NULL)
+            yyv1->yystate = YYRELOC (yyp0, yyp1, yyv0->yystate, yystate);
+          if (yyv0->yynext != YY_NULL)
+            yyv1->yynext = YYRELOC (yyp0, yyp1, yyv0->yynext, yyoption);
+        }
+    }
+  if (yystackp->yysplitPoint != YY_NULL)
+    yystackp->yysplitPoint = YYRELOC (yystackp->yyitems, yynewItems,
+                                 yystackp->yysplitPoint, yystate);
+
+  for (yyn = 0; yyn < yystackp->yytops.yysize; yyn += 1)
+    if (yystackp->yytops.yystates[yyn] != YY_NULL)
+      yystackp->yytops.yystates[yyn] =
+        YYRELOC (yystackp->yyitems, yynewItems,
+                 yystackp->yytops.yystates[yyn], yystate);
+  YYFREE (yystackp->yyitems);
+  yystackp->yyitems = yynewItems;
+  yystackp->yynextFree = yynewItems + yysize;
+  yystackp->yyspaceLeft = yynewSize - yysize;
+}
+#endif
+
+static void
+yyfreeGLRStack (yyGLRStack* yystackp)
+{
+  YYFREE (yystackp->yyitems);
+  yyfreeStateSet (&yystackp->yytops);
+}
+
+/** Assuming that S is a GLRState somewhere on STACK, update the
+ *  splitpoint of STACK, if needed, so that it is at least as deep as
+ *  S.  */
+static inline void
+yyupdateSplit (yyGLRStack* yystackp, yyGLRState* yys)
+{
+  if (yystackp->yysplitPoint != YY_NULL && yystackp->yysplitPoint > yys)
+    yystackp->yysplitPoint = yys;
+}
+
+/** Invalidate stack #K in STACK.  */
+static inline void
+yymarkStackDeleted (yyGLRStack* yystackp, size_t yyk)
+{
+  if (yystackp->yytops.yystates[yyk] != YY_NULL)
+    yystackp->yylastDeleted = yystackp->yytops.yystates[yyk];
+  yystackp->yytops.yystates[yyk] = YY_NULL;
+}
+
+/** Undelete the last stack that was marked as deleted.  Can only be
+    done once after a deletion, and only when all other stacks have
+    been deleted.  */
+static void
+yyundeleteLastStack (yyGLRStack* yystackp)
+{
+  if (yystackp->yylastDeleted == YY_NULL || yystackp->yytops.yysize != 0)
+    return;
+  yystackp->yytops.yystates[0] = yystackp->yylastDeleted;
+  yystackp->yytops.yysize = 1;
+  YYDPRINTF ((stderr, "Restoring last deleted stack as stack #0.\n"));
+  yystackp->yylastDeleted = YY_NULL;
+}
+
+static inline void
+yyremoveDeletes (yyGLRStack* yystackp)
+{
+  size_t yyi, yyj;
+  yyi = yyj = 0;
+  while (yyj < yystackp->yytops.yysize)
+    {
+      if (yystackp->yytops.yystates[yyi] == YY_NULL)
+        {
+          if (yyi == yyj)
+            {
+              YYDPRINTF ((stderr, "Removing dead stacks.\n"));
+            }
+          yystackp->yytops.yysize -= 1;
+        }
+      else
+        {
+          yystackp->yytops.yystates[yyj] = yystackp->yytops.yystates[yyi];
+          /* In the current implementation, it's unnecessary to copy
+             yystackp->yytops.yylookaheadNeeds[yyi] since, after
+             yyremoveDeletes returns, the parser immediately either enters
+             deterministic operation or shifts a token.  However, it doesn't
+             hurt, and the code might evolve to need it.  */
+          yystackp->yytops.yylookaheadNeeds[yyj] =
+            yystackp->yytops.yylookaheadNeeds[yyi];
+          if (yyj != yyi)
+            {
+              YYDPRINTF ((stderr, "Rename stack %lu -> %lu.\n",
+                          (unsigned long int) yyi, (unsigned long int) yyj));
+            }
+          yyj += 1;
+        }
+      yyi += 1;
+    }
+}
+
+/** Shift to a new state on stack #K of STACK, corresponding to LR state
+ * LRSTATE, at input position POSN, with (resolved) semantic value SVAL.  */
+static inline void
+yyglrShift (yyGLRStack* yystackp, size_t yyk, yyStateNum yylrState,
+            size_t yyposn,
+            YYSTYPE* yyvalp, YYLTYPE* yylocp)
+{
+  yyGLRState* yynewState = &yynewGLRStackItem (yystackp, yytrue)->yystate;
+
+  yynewState->yylrState = yylrState;
+  yynewState->yyposn = yyposn;
+  yynewState->yyresolved = yytrue;
+  yynewState->yypred = yystackp->yytops.yystates[yyk];
+  yynewState->yysemantics.yysval = *yyvalp;
+  yynewState->yyloc = *yylocp;
+  yystackp->yytops.yystates[yyk] = yynewState;
+
+  YY_RESERVE_GLRSTACK (yystackp);
+}
+
+/** Shift stack #K of YYSTACK, to a new state corresponding to LR
+ *  state YYLRSTATE, at input position YYPOSN, with the (unresolved)
+ *  semantic value of YYRHS under the action for YYRULE.  */
+static inline void
+yyglrShiftDefer (yyGLRStack* yystackp, size_t yyk, yyStateNum yylrState,
+                 size_t yyposn, yyGLRState* rhs, yyRuleNum yyrule)
+{
+  yyGLRState* yynewState = &yynewGLRStackItem (yystackp, yytrue)->yystate;
+
+  yynewState->yylrState = yylrState;
+  yynewState->yyposn = yyposn;
+  yynewState->yyresolved = yyfalse;
+  yynewState->yypred = yystackp->yytops.yystates[yyk];
+  yynewState->yysemantics.yyfirstVal = YY_NULL;
+  yystackp->yytops.yystates[yyk] = yynewState;
+
+  /* Invokes YY_RESERVE_GLRSTACK.  */
+  yyaddDeferredAction (yystackp, yyk, yynewState, rhs, yyrule);
+}
+
+/** Pop the symbols consumed by reduction #RULE from the top of stack
+ *  #K of STACK, and perform the appropriate semantic action on their
+ *  semantic values.  Assumes that all ambiguities in semantic values
+ *  have been previously resolved.  Set *VALP to the resulting value,
+ *  and *LOCP to the computed location (if any).  Return value is as
+ *  for userAction.  */
+static inline YYRESULTTAG
+yydoAction (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
+            YYSTYPE* yyvalp, YYLTYPE *yylocp, ParseState* parse_state, yyscan_t scanner)
+{
+  int yynrhs = yyrhsLength (yyrule);
+
+  if (yystackp->yysplitPoint == YY_NULL)
+    {
+      /* Standard special case: single stack.  */
+      yyGLRStackItem* rhs = (yyGLRStackItem*) yystackp->yytops.yystates[yyk];
+      YYASSERT (yyk == 0);
+      yystackp->yynextFree -= yynrhs;
+      yystackp->yyspaceLeft += yynrhs;
+      yystackp->yytops.yystates[0] = & yystackp->yynextFree[-1].yystate;
+      return yyuserAction (yyrule, yynrhs, rhs, yystackp,
+                           yyvalp, yylocp, parse_state, scanner);
+    }
+  else
+    {
+      /* At present, doAction is never called in nondeterministic
+       * mode, so this branch is never taken.  It is here in
+       * anticipation of a future feature that will allow immediate
+       * evaluation of selected actions in nondeterministic mode.  */
+      int yyi;
+      yyGLRState* yys;
+      yyGLRStackItem yyrhsVals[YYMAXRHS + YYMAXLEFT + 1];
+      yys = yyrhsVals[YYMAXRHS + YYMAXLEFT].yystate.yypred
+        = yystackp->yytops.yystates[yyk];
+      if (yynrhs == 0)
+        /* Set default location.  */
+        yyrhsVals[YYMAXRHS + YYMAXLEFT - 1].yystate.yyloc = yys->yyloc;
+      for (yyi = 0; yyi < yynrhs; yyi += 1)
+        {
+          yys = yys->yypred;
+          YYASSERT (yys);
+        }
+      yyupdateSplit (yystackp, yys);
+      yystackp->yytops.yystates[yyk] = yys;
+      return yyuserAction (yyrule, yynrhs, yyrhsVals + YYMAXRHS + YYMAXLEFT - 1,
+                           yystackp, yyvalp, yylocp, parse_state, scanner);
+    }
+}
+
+#if !YYDEBUG
+# define YY_REDUCE_PRINT(Args)
+#else
+# define YY_REDUCE_PRINT(Args)          \
+do {                                    \
+  if (yydebug)                          \
+    yy_reduce_print Args;               \
+} while (YYID (0))
+
+/*----------------------------------------------------------.
+| Report that the RULE is going to be reduced on stack #K.  |
+`----------------------------------------------------------*/
+
+/*ARGSUSED*/ static inline void
+yy_reduce_print (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
+                 YYSTYPE* yyvalp, YYLTYPE *yylocp, ParseState* parse_state, yyscan_t scanner)
+{
+  int yynrhs = yyrhsLength (yyrule);
+  yybool yynormal __attribute__ ((__unused__)) =
+    (yystackp->yysplitPoint == YY_NULL);
+  yyGLRStackItem* yyvsp = (yyGLRStackItem*) yystackp->yytops.yystates[yyk];
+  int yylow = 1;
+  int yyi;
+  YYUSE (yyvalp);
+  YYUSE (yylocp);
+  YYUSE (parse_state);
+  YYUSE (scanner);
+  YYFPRINTF (stderr, "Reducing stack %lu by rule %d (line %lu):\n",
+             (unsigned long int) yyk, yyrule - 1,
+             (unsigned long int) yyrline[yyrule]);
+  /* The symbols being reduced.  */
+  for (yyi = 0; yyi < yynrhs; yyi++)
+    {
+      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
+      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+                       &(((yyGLRStackItem const *)yyvsp)[YYFILL ((yyi + 1) - (yynrhs))].yystate.yysemantics.yysval)
+                       , &(((yyGLRStackItem const *)yyvsp)[YYFILL ((yyi + 1) - (yynrhs))].yystate.yyloc)                       , parse_state, scanner);
+      YYFPRINTF (stderr, "\n");
+    }
+}
+#endif
+
+/** Pop items off stack #K of STACK according to grammar rule RULE,
+ *  and push back on the resulting nonterminal symbol.  Perform the
+ *  semantic action associated with RULE and store its value with the
+ *  newly pushed state, if FORCEEVAL or if STACK is currently
+ *  unambiguous.  Otherwise, store the deferred semantic action with
+ *  the new state.  If the new state would have an identical input
+ *  position, LR state, and predecessor to an existing state on the stack,
+ *  it is identified with that existing state, eliminating stack #K from
+ *  the STACK.  In this case, the (necessarily deferred) semantic value is
+ *  added to the options for the existing state's semantic value.
+ */
+static inline YYRESULTTAG
+yyglrReduce (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
+             yybool yyforceEval, ParseState* parse_state, yyscan_t scanner)
+{
+  size_t yyposn = yystackp->yytops.yystates[yyk]->yyposn;
+
+  if (yyforceEval || yystackp->yysplitPoint == YY_NULL)
+    {
+      YYSTYPE yysval;
+      YYLTYPE yyloc;
+
+      YY_REDUCE_PRINT ((yystackp, yyk, yyrule, &yysval, &yyloc, parse_state, scanner));
+      YYCHK (yydoAction (yystackp, yyk, yyrule, &yysval, &yyloc, parse_state, scanner));
+      YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyrule], &yysval, &yyloc);
+      yyglrShift (yystackp, yyk,
+                  yyLRgotoState (yystackp->yytops.yystates[yyk]->yylrState,
+                                 yylhsNonterm (yyrule)),
+                  yyposn, &yysval, &yyloc);
+    }
+  else
+    {
+      size_t yyi;
+      int yyn;
+      yyGLRState* yys, *yys0 = yystackp->yytops.yystates[yyk];
+      yyStateNum yynewLRState;
+
+      for (yys = yystackp->yytops.yystates[yyk], yyn = yyrhsLength (yyrule);
+           0 < yyn; yyn -= 1)
+        {
+          yys = yys->yypred;
+          YYASSERT (yys);
+        }
+      yyupdateSplit (yystackp, yys);
+      yynewLRState = yyLRgotoState (yys->yylrState, yylhsNonterm (yyrule));
+      YYDPRINTF ((stderr,
+                  "Reduced stack %lu by rule #%d; action deferred.  Now in state %d.\n",
+                  (unsigned long int) yyk, yyrule - 1, yynewLRState));
+      for (yyi = 0; yyi < yystackp->yytops.yysize; yyi += 1)
+        if (yyi != yyk && yystackp->yytops.yystates[yyi] != YY_NULL)
+          {
+            yyGLRState *yysplit = yystackp->yysplitPoint;
+            yyGLRState *yyp = yystackp->yytops.yystates[yyi];
+            while (yyp != yys && yyp != yysplit && yyp->yyposn >= yyposn)
+              {
+                if (yyp->yylrState == yynewLRState && yyp->yypred == yys)
+                  {
+                    yyaddDeferredAction (yystackp, yyk, yyp, yys0, yyrule);
+                    yymarkStackDeleted (yystackp, yyk);
+                    YYDPRINTF ((stderr, "Merging stack %lu into stack %lu.\n",
+                                (unsigned long int) yyk,
+                                (unsigned long int) yyi));
+                    return yyok;
+                  }
+                yyp = yyp->yypred;
+              }
+          }
+      yystackp->yytops.yystates[yyk] = yys;
+      yyglrShiftDefer (yystackp, yyk, yynewLRState, yyposn, yys0, yyrule);
+    }
+  return yyok;
+}
+
+static size_t
+yysplitStack (yyGLRStack* yystackp, size_t yyk)
+{
+  if (yystackp->yysplitPoint == YY_NULL)
+    {
+      YYASSERT (yyk == 0);
+      yystackp->yysplitPoint = yystackp->yytops.yystates[yyk];
+    }
+  if (yystackp->yytops.yysize >= yystackp->yytops.yycapacity)
+    {
+      yyGLRState** yynewStates;
+      yybool* yynewLookaheadNeeds;
+
+      yynewStates = YY_NULL;
+
+      if (yystackp->yytops.yycapacity
+          > (YYSIZEMAX / (2 * sizeof yynewStates[0])))
+        yyMemoryExhausted (yystackp);
+      yystackp->yytops.yycapacity *= 2;
+
+      yynewStates =
+        (yyGLRState**) YYREALLOC (yystackp->yytops.yystates,
+                                  (yystackp->yytops.yycapacity
+                                   * sizeof yynewStates[0]));
+      if (yynewStates == YY_NULL)
+        yyMemoryExhausted (yystackp);
+      yystackp->yytops.yystates = yynewStates;
+
+      yynewLookaheadNeeds =
+        (yybool*) YYREALLOC (yystackp->yytops.yylookaheadNeeds,
+                             (yystackp->yytops.yycapacity
+                              * sizeof yynewLookaheadNeeds[0]));
+      if (yynewLookaheadNeeds == YY_NULL)
+        yyMemoryExhausted (yystackp);
+      yystackp->yytops.yylookaheadNeeds = yynewLookaheadNeeds;
+    }
+  yystackp->yytops.yystates[yystackp->yytops.yysize]
+    = yystackp->yytops.yystates[yyk];
+  yystackp->yytops.yylookaheadNeeds[yystackp->yytops.yysize]
+    = yystackp->yytops.yylookaheadNeeds[yyk];
+  yystackp->yytops.yysize += 1;
+  return yystackp->yytops.yysize-1;
+}
+
+/** True iff Y0 and Y1 represent identical options at the top level.
+ *  That is, they represent the same rule applied to RHS symbols
+ *  that produce the same terminal symbols.  */
+static yybool
+yyidenticalOptions (yySemanticOption* yyy0, yySemanticOption* yyy1)
+{
+  if (yyy0->yyrule == yyy1->yyrule)
+    {
+      yyGLRState *yys0, *yys1;
+      int yyn;
+      for (yys0 = yyy0->yystate, yys1 = yyy1->yystate,
+           yyn = yyrhsLength (yyy0->yyrule);
+           yyn > 0;
+           yys0 = yys0->yypred, yys1 = yys1->yypred, yyn -= 1)
+        if (yys0->yyposn != yys1->yyposn)
+          return yyfalse;
+      return yytrue;
+    }
+  else
+    return yyfalse;
+}
+
+/** Assuming identicalOptions (Y0,Y1), destructively merge the
+ *  alternative semantic values for the RHS-symbols of Y1 and Y0.  */
+static void
+yymergeOptionSets (yySemanticOption* yyy0, yySemanticOption* yyy1)
+{
+  yyGLRState *yys0, *yys1;
+  int yyn;
+  for (yys0 = yyy0->yystate, yys1 = yyy1->yystate,
+       yyn = yyrhsLength (yyy0->yyrule);
+       yyn > 0;
+       yys0 = yys0->yypred, yys1 = yys1->yypred, yyn -= 1)
+    {
+      if (yys0 == yys1)
+        break;
+      else if (yys0->yyresolved)
+        {
+          yys1->yyresolved = yytrue;
+          yys1->yysemantics.yysval = yys0->yysemantics.yysval;
+        }
+      else if (yys1->yyresolved)
+        {
+          yys0->yyresolved = yytrue;
+          yys0->yysemantics.yysval = yys1->yysemantics.yysval;
+        }
+      else
+        {
+          yySemanticOption** yyz0p = &yys0->yysemantics.yyfirstVal;
+          yySemanticOption* yyz1 = yys1->yysemantics.yyfirstVal;
+          while (YYID (yytrue))
+            {
+              if (yyz1 == *yyz0p || yyz1 == YY_NULL)
+                break;
+              else if (*yyz0p == YY_NULL)
+                {
+                  *yyz0p = yyz1;
+                  break;
+                }
+              else if (*yyz0p < yyz1)
+                {
+                  yySemanticOption* yyz = *yyz0p;
+                  *yyz0p = yyz1;
+                  yyz1 = yyz1->yynext;
+                  (*yyz0p)->yynext = yyz;
+                }
+              yyz0p = &(*yyz0p)->yynext;
+            }
+          yys1->yysemantics.yyfirstVal = yys0->yysemantics.yyfirstVal;
+        }
+    }
+}
+
+/** Y0 and Y1 represent two possible actions to take in a given
+ *  parsing state; return 0 if no combination is possible,
+ *  1 if user-mergeable, 2 if Y0 is preferred, 3 if Y1 is preferred.  */
+static int
+yypreference (yySemanticOption* y0, yySemanticOption* y1)
+{
+  yyRuleNum r0 = y0->yyrule, r1 = y1->yyrule;
+  int p0 = yydprec[r0], p1 = yydprec[r1];
+
+  if (p0 == p1)
+    {
+      if (yymerger[r0] == 0 || yymerger[r0] != yymerger[r1])
+        return 0;
+      else
+        return 1;
+    }
+  if (p0 == 0 || p1 == 0)
+    return 0;
+  if (p0 < p1)
+    return 3;
+  if (p1 < p0)
+    return 2;
+  return 0;
+}
+
+static YYRESULTTAG yyresolveValue (yyGLRState* yys,
+                                   yyGLRStack* yystackp, ParseState* parse_state, yyscan_t scanner);
+
+
+/** Resolve the previous N states starting at and including state S.  If result
+ *  != yyok, some states may have been left unresolved possibly with empty
+ *  semantic option chains.  Regardless of whether result = yyok, each state
+ *  has been left with consistent data so that yydestroyGLRState can be invoked
+ *  if necessary.  */
+static YYRESULTTAG
+yyresolveStates (yyGLRState* yys, int yyn,
+                 yyGLRStack* yystackp, ParseState* parse_state, yyscan_t scanner)
+{
+  if (0 < yyn)
+    {
+      YYASSERT (yys->yypred);
+      YYCHK (yyresolveStates (yys->yypred, yyn-1, yystackp, parse_state, scanner));
+      if (! yys->yyresolved)
+        YYCHK (yyresolveValue (yys, yystackp, parse_state, scanner));
+    }
+  return yyok;
+}
+
+/** Resolve the states for the RHS of OPT, perform its user action, and return
+ *  the semantic value and location.  Regardless of whether result = yyok, all
+ *  RHS states have been destroyed (assuming the user action destroys all RHS
+ *  semantic values if invoked).  */
+static YYRESULTTAG
+yyresolveAction (yySemanticOption* yyopt, yyGLRStack* yystackp,
+                 YYSTYPE* yyvalp, YYLTYPE *yylocp, ParseState* parse_state, yyscan_t scanner)
+{
+  yyGLRStackItem yyrhsVals[YYMAXRHS + YYMAXLEFT + 1];
+  int yynrhs = yyrhsLength (yyopt->yyrule);
+  YYRESULTTAG yyflag =
+    yyresolveStates (yyopt->yystate, yynrhs, yystackp, parse_state, scanner);
+  if (yyflag != yyok)
+    {
+      yyGLRState *yys;
+      for (yys = yyopt->yystate; yynrhs > 0; yys = yys->yypred, yynrhs -= 1)
+        yydestroyGLRState ("Cleanup: popping", yys, parse_state, scanner);
+      return yyflag;
+    }
+
+  yyrhsVals[YYMAXRHS + YYMAXLEFT].yystate.yypred = yyopt->yystate;
+  if (yynrhs == 0)
+    /* Set default location.  */
+    yyrhsVals[YYMAXRHS + YYMAXLEFT - 1].yystate.yyloc = yyopt->yystate->yyloc;
+  {
+    int yychar_current = yychar;
+    YYSTYPE yylval_current = yylval;
+    YYLTYPE yylloc_current = yylloc;
+    yychar = yyopt->yyrawchar;
+    yylval = yyopt->yyval;
+    yylloc = yyopt->yyloc;
+    yyflag = yyuserAction (yyopt->yyrule, yynrhs,
+                           yyrhsVals + YYMAXRHS + YYMAXLEFT - 1,
+                           yystackp, yyvalp, yylocp, parse_state, scanner);
+    yychar = yychar_current;
+    yylval = yylval_current;
+    yylloc = yylloc_current;
+  }
+  return yyflag;
+}
+
+#if YYDEBUG
+static void
+yyreportTree (yySemanticOption* yyx, int yyindent)
+{
+  int yynrhs = yyrhsLength (yyx->yyrule);
+  int yyi;
+  yyGLRState* yys;
+  yyGLRState* yystates[1 + YYMAXRHS];
+  yyGLRState yyleftmost_state;
+
+  for (yyi = yynrhs, yys = yyx->yystate; 0 < yyi; yyi -= 1, yys = yys->yypred)
+    yystates[yyi] = yys;
+  if (yys == YY_NULL)
+    {
+      yyleftmost_state.yyposn = 0;
+      yystates[0] = &yyleftmost_state;
+    }
+  else
+    yystates[0] = yys;
+
+  if (yyx->yystate->yyposn < yys->yyposn + 1)
+    YYFPRINTF (stderr, "%*s%s -> <Rule %d, empty>\n",
+               yyindent, "", yytokenName (yylhsNonterm (yyx->yyrule)),
+               yyx->yyrule - 1);
+  else
+    YYFPRINTF (stderr, "%*s%s -> <Rule %d, tokens %lu .. %lu>\n",
+               yyindent, "", yytokenName (yylhsNonterm (yyx->yyrule)),
+               yyx->yyrule - 1, (unsigned long int) (yys->yyposn + 1),
+               (unsigned long int) yyx->yystate->yyposn);
+  for (yyi = 1; yyi <= yynrhs; yyi += 1)
+    {
+      if (yystates[yyi]->yyresolved)
+        {
+          if (yystates[yyi-1]->yyposn+1 > yystates[yyi]->yyposn)
+            YYFPRINTF (stderr, "%*s%s <empty>\n", yyindent+2, "",
+                       yytokenName (yyrhs[yyprhs[yyx->yyrule]+yyi-1]));
+          else
+            YYFPRINTF (stderr, "%*s%s <tokens %lu .. %lu>\n", yyindent+2, "",
+                       yytokenName (yyrhs[yyprhs[yyx->yyrule]+yyi-1]),
+                       (unsigned long int) (yystates[yyi - 1]->yyposn + 1),
+                       (unsigned long int) yystates[yyi]->yyposn);
+        }
+      else
+        yyreportTree (yystates[yyi]->yysemantics.yyfirstVal, yyindent+2);
+    }
+}
+#endif
+
+/*ARGSUSED*/ static YYRESULTTAG
+yyreportAmbiguity (yySemanticOption* yyx0,
+                   yySemanticOption* yyx1, YYLTYPE *yylocp, ParseState* parse_state, yyscan_t scanner)
+{
+  YYUSE (yyx0);
+  YYUSE (yyx1);
+
+#if YYDEBUG
+  YYFPRINTF (stderr, "Ambiguity detected.\n");
+  YYFPRINTF (stderr, "Option 1,\n");
+  yyreportTree (yyx0, 2);
+  YYFPRINTF (stderr, "\nOption 2,\n");
+  yyreportTree (yyx1, 2);
+  YYFPRINTF (stderr, "\n");
+#endif
+
+  yyerror (yylocp, parse_state, scanner, YY_("syntax is ambiguous"));
+  return yyabort;
+}
+
+/** Starting at and including state S1, resolve the location for each of the
+ *  previous N1 states that is unresolved.  The first semantic option of a state
+ *  is always chosen.  */
+static void
+yyresolveLocations (yyGLRState* yys1, int yyn1,
+                    yyGLRStack *yystackp, ParseState* parse_state, yyscan_t scanner)
+{
+  if (0 < yyn1)
+    {
+      yyresolveLocations (yys1->yypred, yyn1 - 1, yystackp, parse_state, scanner);
+      if (!yys1->yyresolved)
+        {
+          yyGLRStackItem yyrhsloc[1 + YYMAXRHS];
+          int yynrhs;
+          yySemanticOption *yyoption = yys1->yysemantics.yyfirstVal;
+          YYASSERT (yyoption != YY_NULL);
+          yynrhs = yyrhsLength (yyoption->yyrule);
+          if (yynrhs > 0)
+            {
+              yyGLRState *yys;
+              int yyn;
+              yyresolveLocations (yyoption->yystate, yynrhs,
+                                  yystackp, parse_state, scanner);
+              for (yys = yyoption->yystate, yyn = yynrhs;
+                   yyn > 0;
+                   yys = yys->yypred, yyn -= 1)
+                yyrhsloc[yyn].yystate.yyloc = yys->yyloc;
+            }
+          else
+            {
+              /* Both yyresolveAction and yyresolveLocations traverse the GSS
+                 in reverse rightmost order.  It is only necessary to invoke
+                 yyresolveLocations on a subforest for which yyresolveAction
+                 would have been invoked next had an ambiguity not been
+                 detected.  Thus the location of the previous state (but not
+                 necessarily the previous state itself) is guaranteed to be
+                 resolved already.  */
+              yyGLRState *yyprevious = yyoption->yystate;
+              yyrhsloc[0].yystate.yyloc = yyprevious->yyloc;
+            }
+          {
+            int yychar_current = yychar;
+            YYSTYPE yylval_current = yylval;
+            YYLTYPE yylloc_current = yylloc;
+            yychar = yyoption->yyrawchar;
+            yylval = yyoption->yyval;
+            yylloc = yyoption->yyloc;
+            YYLLOC_DEFAULT ((yys1->yyloc), yyrhsloc, yynrhs);
+            yychar = yychar_current;
+            yylval = yylval_current;
+            yylloc = yylloc_current;
+          }
+        }
+    }
+}
+
+/** Resolve the ambiguity represented in state S, perform the indicated
+ *  actions, and set the semantic value of S.  If result != yyok, the chain of
+ *  semantic options in S has been cleared instead or it has been left
+ *  unmodified except that redundant options may have been removed.  Regardless
+ *  of whether result = yyok, S has been left with consistent data so that
+ *  yydestroyGLRState can be invoked if necessary.  */
+static YYRESULTTAG
+yyresolveValue (yyGLRState* yys, yyGLRStack* yystackp, ParseState* parse_state, yyscan_t scanner)
+{
+  yySemanticOption* yyoptionList = yys->yysemantics.yyfirstVal;
+  yySemanticOption* yybest = yyoptionList;
+  yySemanticOption** yypp;
+  yybool yymerge = yyfalse;
+  YYSTYPE yysval;
+  YYRESULTTAG yyflag;
+  YYLTYPE *yylocp = &yys->yyloc;
+
+  for (yypp = &yyoptionList->yynext; *yypp != YY_NULL; )
+    {
+      yySemanticOption* yyp = *yypp;
+
+      if (yyidenticalOptions (yybest, yyp))
+        {
+          yymergeOptionSets (yybest, yyp);
+          *yypp = yyp->yynext;
+        }
+      else
+        {
+          switch (yypreference (yybest, yyp))
+            {
+            case 0:
+              yyresolveLocations (yys, 1, yystackp, parse_state, scanner);
+              return yyreportAmbiguity (yybest, yyp, yylocp, parse_state, scanner);
+              break;
+            case 1:
+              yymerge = yytrue;
+              break;
+            case 2:
+              break;
+            case 3:
+              yybest = yyp;
+              yymerge = yyfalse;
+              break;
+            default:
+              /* This cannot happen so it is not worth a YYASSERT (yyfalse),
+                 but some compilers complain if the default case is
+                 omitted.  */
+              break;
+            }
+          yypp = &yyp->yynext;
+        }
+    }
+
+  if (yymerge)
+    {
+      yySemanticOption* yyp;
+      int yyprec = yydprec[yybest->yyrule];
+      yyflag = yyresolveAction (yybest, yystackp, &yysval, yylocp, parse_state, scanner);
+      if (yyflag == yyok)
+        for (yyp = yybest->yynext; yyp != YY_NULL; yyp = yyp->yynext)
+          {
+            if (yyprec == yydprec[yyp->yyrule])
+              {
+                YYSTYPE yysval_other;
+                YYLTYPE yydummy;
+                yyflag = yyresolveAction (yyp, yystackp, &yysval_other, &yydummy, parse_state, scanner);
+                if (yyflag != yyok)
+                  {
+                    yydestruct ("Cleanup: discarding incompletely merged value for",
+                                yystos[yys->yylrState],
+                                &yysval, yylocp, parse_state, scanner);
+                    break;
+                  }
+                yyuserMerge (yymerger[yyp->yyrule], &yysval, &yysval_other);
+              }
+          }
+    }
+  else
+    yyflag = yyresolveAction (yybest, yystackp, &yysval, yylocp, parse_state, scanner);
+
+  if (yyflag == yyok)
+    {
+      yys->yyresolved = yytrue;
+      yys->yysemantics.yysval = yysval;
+    }
+  else
+    yys->yysemantics.yyfirstVal = YY_NULL;
+  return yyflag;
+}
+
+static YYRESULTTAG
+yyresolveStack (yyGLRStack* yystackp, ParseState* parse_state, yyscan_t scanner)
+{
+  if (yystackp->yysplitPoint != YY_NULL)
+    {
+      yyGLRState* yys;
+      int yyn;
+
+      for (yyn = 0, yys = yystackp->yytops.yystates[0];
+           yys != yystackp->yysplitPoint;
+           yys = yys->yypred, yyn += 1)
+        continue;
+      YYCHK (yyresolveStates (yystackp->yytops.yystates[0], yyn, yystackp
+                             , parse_state, scanner));
+    }
+  return yyok;
+}
+
+static void
+yycompressStack (yyGLRStack* yystackp)
+{
+  yyGLRState* yyp, *yyq, *yyr;
+
+  if (yystackp->yytops.yysize != 1 || yystackp->yysplitPoint == YY_NULL)
+    return;
+
+  for (yyp = yystackp->yytops.yystates[0], yyq = yyp->yypred, yyr = YY_NULL;
+       yyp != yystackp->yysplitPoint;
+       yyr = yyp, yyp = yyq, yyq = yyp->yypred)
+    yyp->yypred = yyr;
+
+  yystackp->yyspaceLeft += yystackp->yynextFree - yystackp->yyitems;
+  yystackp->yynextFree = ((yyGLRStackItem*) yystackp->yysplitPoint) + 1;
+  yystackp->yyspaceLeft -= yystackp->yynextFree - yystackp->yyitems;
+  yystackp->yysplitPoint = YY_NULL;
+  yystackp->yylastDeleted = YY_NULL;
+
+  while (yyr != YY_NULL)
+    {
+      yystackp->yynextFree->yystate = *yyr;
+      yyr = yyr->yypred;
+      yystackp->yynextFree->yystate.yypred = &yystackp->yynextFree[-1].yystate;
+      yystackp->yytops.yystates[0] = &yystackp->yynextFree->yystate;
+      yystackp->yynextFree += 1;
+      yystackp->yyspaceLeft -= 1;
+    }
+}
+
+static YYRESULTTAG
+yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
+                   size_t yyposn, YYLTYPE *yylocp, ParseState* parse_state, yyscan_t scanner)
+{
+  int yyaction;
+  const short int* yyconflicts;
+  yyRuleNum yyrule;
+
+  while (yystackp->yytops.yystates[yyk] != YY_NULL)
+    {
+      yyStateNum yystate = yystackp->yytops.yystates[yyk]->yylrState;
+      YYDPRINTF ((stderr, "Stack %lu Entering state %d\n",
+                  (unsigned long int) yyk, yystate));
+
+      YYASSERT (yystate != YYFINAL);
+
+      if (yyisDefaultedState (yystate))
+        {
+          yyrule = yydefaultAction (yystate);
+          if (yyrule == 0)
+            {
+              YYDPRINTF ((stderr, "Stack %lu dies.\n",
+                          (unsigned long int) yyk));
+              yymarkStackDeleted (yystackp, yyk);
+              return yyok;
+            }
+          YYCHK (yyglrReduce (yystackp, yyk, yyrule, yyfalse, parse_state, scanner));
+        }
+      else
+        {
+          yySymbol yytoken;
+          yystackp->yytops.yylookaheadNeeds[yyk] = yytrue;
+          if (yychar == YYEMPTY)
+            {
+              YYDPRINTF ((stderr, "Reading a token: "));
+              yychar = YYLEX;
+            }
+
+          if (yychar <= YYEOF)
+            {
+              yychar = yytoken = YYEOF;
+              YYDPRINTF ((stderr, "Now at end of input.\n"));
+            }
+          else
+            {
+              yytoken = YYTRANSLATE (yychar);
+              YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+            }
+
+          yygetLRActions (yystate, yytoken, &yyaction, &yyconflicts);
+
+          while (*yyconflicts != 0)
+            {
+              size_t yynewStack = yysplitStack (yystackp, yyk);
+              YYDPRINTF ((stderr, "Splitting off stack %lu from %lu.\n",
+                          (unsigned long int) yynewStack,
+                          (unsigned long int) yyk));
+              YYCHK (yyglrReduce (yystackp, yynewStack,
+                                  *yyconflicts, yyfalse, parse_state, scanner));
+              YYCHK (yyprocessOneStack (yystackp, yynewStack,
+                                        yyposn, yylocp, parse_state, scanner));
+              yyconflicts += 1;
+            }
+
+          if (yyisShiftAction (yyaction))
+            break;
+          else if (yyisErrorAction (yyaction))
+            {
+              YYDPRINTF ((stderr, "Stack %lu dies.\n",
+                          (unsigned long int) yyk));
+              yymarkStackDeleted (yystackp, yyk);
+              break;
+            }
+          else
+            YYCHK (yyglrReduce (yystackp, yyk, -yyaction,
+                                yyfalse, parse_state, scanner));
+        }
+    }
+  return yyok;
+}
+
+/*ARGSUSED*/ static void
+yyreportSyntaxError (yyGLRStack* yystackp, ParseState* parse_state, yyscan_t scanner)
+{
+  if (yystackp->yyerrState != 0)
+    return;
+#if ! YYERROR_VERBOSE
+  yyerror (&yylloc, parse_state, scanner, YY_("syntax error"));
+#else
+  {
+  yySymbol yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
+  size_t yysize0 = yytnamerr (YY_NULL, yytokenName (yytoken));
+  size_t yysize = yysize0;
+  yybool yysize_overflow = yyfalse;
+  char* yymsg = YY_NULL;
+  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+  /* Internationalized format string. */
+  const char *yyformat = YY_NULL;
+  /* Arguments of yyformat. */
+  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+  /* Number of reported tokens (one for the "unexpected", one per
+     "expected").  */
+  int yycount = 0;
+
+  /* There are many possibilities here to consider:
+     - If this state is a consistent state with a default action, then
+       the only way this function was invoked is if the default action
+       is an error action.  In that case, don't check for expected
+       tokens because there are none.
+     - The only way there can be no lookahead present (in yychar) is if
+       this state is a consistent state with a default action.  Thus,
+       detecting the absence of a lookahead is sufficient to determine
+       that there is no unexpected or expected token to report.  In that
+       case, just report a simple "syntax error".
+     - Don't assume there isn't a lookahead just because this state is a
+       consistent state with a default action.  There might have been a
+       previous inconsistent state, consistent state with a non-default
+       action, or user semantic action that manipulated yychar.
+     - Of course, the expected token list depends on states to have
+       correct lookahead information, and it depends on the parser not
+       to perform extra reductions after fetching a lookahead from the
+       scanner and before detecting a syntax error.  Thus, state merging
+       (from LALR or IELR) and default reductions corrupt the expected
+       token list.  However, the list is correct for canonical LR with
+       one exception: it will still contain any token that will not be
+       accepted due to an error action in a later state.
+  */
+  if (yytoken != YYEMPTY)
+    {
+      int yyn = yypact[yystackp->yytops.yystates[0]->yylrState];
+      yyarg[yycount++] = yytokenName (yytoken);
+      if (!yypact_value_is_default (yyn))
+        {
+          /* Start YYX at -YYN if negative to avoid negative indexes in
+             YYCHECK.  In other words, skip the first -YYN actions for this
+             state because they are default actions.  */
+          int yyxbegin = yyn < 0 ? -yyn : 0;
+          /* Stay within bounds of both yycheck and yytname.  */
+          int yychecklim = YYLAST - yyn + 1;
+          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+          int yyx;
+          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
+                && !yytable_value_is_error (yytable[yyx + yyn]))
+              {
+                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+                  {
+                    yycount = 1;
+                    yysize = yysize0;
+                    break;
+                  }
+                yyarg[yycount++] = yytokenName (yyx);
+                {
+                  size_t yysz = yysize + yytnamerr (YY_NULL, yytokenName (yyx));
+                  yysize_overflow |= yysz < yysize;
+                  yysize = yysz;
+                }
+              }
+        }
+    }
+
+  switch (yycount)
+    {
+#define YYCASE_(N, S)                   \
+      case N:                           \
+        yyformat = S;                   \
+      break
+      YYCASE_(0, YY_("syntax error"));
+      YYCASE_(1, YY_("syntax error, unexpected %s"));
+      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
+      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
+      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
+      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
+#undef YYCASE_
+    }
+
+  {
+    size_t yysz = yysize + strlen (yyformat);
+    yysize_overflow |= yysz < yysize;
+    yysize = yysz;
+  }
+
+  if (!yysize_overflow)
+    yymsg = (char *) YYMALLOC (yysize);
+
+  if (yymsg)
+    {
+      char *yyp = yymsg;
+      int yyi = 0;
+      while ((*yyp = *yyformat))
+        {
+          if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
+            {
+              yyp += yytnamerr (yyp, yyarg[yyi++]);
+              yyformat += 2;
+            }
+          else
+            {
+              yyp++;
+              yyformat++;
+            }
+        }
+      yyerror (&yylloc, parse_state, scanner, yymsg);
+      YYFREE (yymsg);
+    }
+  else
+    {
+      yyerror (&yylloc, parse_state, scanner, YY_("syntax error"));
+      yyMemoryExhausted (yystackp);
+    }
+  }
+#endif /* YYERROR_VERBOSE */
+  yynerrs += 1;
+}
+
+/* Recover from a syntax error on *YYSTACKP, assuming that *YYSTACKP->YYTOKENP,
+   yylval, and yylloc are the syntactic category, semantic value, and location
+   of the lookahead.  */
+/*ARGSUSED*/ static void
+yyrecoverSyntaxError (yyGLRStack* yystackp, ParseState* parse_state, yyscan_t scanner)
+{
+  size_t yyk;
+  int yyj;
+
+  if (yystackp->yyerrState == 3)
+    /* We just shifted the error token and (perhaps) took some
+       reductions.  Skip tokens until we can proceed.  */
+    while (YYID (yytrue))
+      {
+        yySymbol yytoken;
+        if (yychar == YYEOF)
+          yyFail (yystackp, &yylloc, parse_state, scanner, YY_NULL);
+        if (yychar != YYEMPTY)
+          {
+            /* We throw away the lookahead, but the error range
+               of the shifted error token must take it into account.  */
+            yyGLRState *yys = yystackp->yytops.yystates[0];
+            yyGLRStackItem yyerror_range[3];
+            yyerror_range[1].yystate.yyloc = yys->yyloc;
+            yyerror_range[2].yystate.yyloc = yylloc;
+            YYLLOC_DEFAULT ((yys->yyloc), yyerror_range, 2);
+            yytoken = YYTRANSLATE (yychar);
+            yydestruct ("Error: discarding",
+                        yytoken, &yylval, &yylloc, parse_state, scanner);
+          }
+        YYDPRINTF ((stderr, "Reading a token: "));
+        yychar = YYLEX;
+        if (yychar <= YYEOF)
+          {
+            yychar = yytoken = YYEOF;
+            YYDPRINTF ((stderr, "Now at end of input.\n"));
+          }
+        else
+          {
+            yytoken = YYTRANSLATE (yychar);
+            YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+          }
+        yyj = yypact[yystackp->yytops.yystates[0]->yylrState];
+        if (yypact_value_is_default (yyj))
+          return;
+        yyj += yytoken;
+        if (yyj < 0 || YYLAST < yyj || yycheck[yyj] != yytoken)
+          {
+            if (yydefact[yystackp->yytops.yystates[0]->yylrState] != 0)
+              return;
+          }
+        else if (! yytable_value_is_error (yytable[yyj]))
+          return;
+      }
+
+  /* Reduce to one stack.  */
+  for (yyk = 0; yyk < yystackp->yytops.yysize; yyk += 1)
+    if (yystackp->yytops.yystates[yyk] != YY_NULL)
+      break;
+  if (yyk >= yystackp->yytops.yysize)
+    yyFail (yystackp, &yylloc, parse_state, scanner, YY_NULL);
+  for (yyk += 1; yyk < yystackp->yytops.yysize; yyk += 1)
+    yymarkStackDeleted (yystackp, yyk);
+  yyremoveDeletes (yystackp);
+  yycompressStack (yystackp);
+
+  /* Now pop stack until we find a state that shifts the error token.  */
+  yystackp->yyerrState = 3;
+  while (yystackp->yytops.yystates[0] != YY_NULL)
+    {
+      yyGLRState *yys = yystackp->yytops.yystates[0];
+      yyj = yypact[yys->yylrState];
+      if (! yypact_value_is_default (yyj))
+        {
+          yyj += YYTERROR;
+          if (0 <= yyj && yyj <= YYLAST && yycheck[yyj] == YYTERROR
+              && yyisShiftAction (yytable[yyj]))
+            {
+              /* Shift the error token.  */
+              /* First adjust its location.*/
+              YYLTYPE yyerrloc;
+              yystackp->yyerror_range[2].yystate.yyloc = yylloc;
+              YYLLOC_DEFAULT (yyerrloc, (yystackp->yyerror_range), 2);
+              YY_SYMBOL_PRINT ("Shifting", yystos[yytable[yyj]],
+                               &yylval, &yyerrloc);
+              yyglrShift (yystackp, 0, yytable[yyj],
+                          yys->yyposn, &yylval, &yyerrloc);
+              yys = yystackp->yytops.yystates[0];
+              break;
+            }
+        }
+      yystackp->yyerror_range[1].yystate.yyloc = yys->yyloc;
+      if (yys->yypred != YY_NULL)
+        yydestroyGLRState ("Error: popping", yys, parse_state, scanner);
+      yystackp->yytops.yystates[0] = yys->yypred;
+      yystackp->yynextFree -= 1;
+      yystackp->yyspaceLeft += 1;
+    }
+  if (yystackp->yytops.yystates[0] == YY_NULL)
+    yyFail (yystackp, &yylloc, parse_state, scanner, YY_NULL);
+}
+
+#define YYCHK1(YYE)                                                          \
+  do {                                                                       \
+    switch (YYE) {                                                           \
+    case yyok:                                                               \
+      break;                                                                 \
+    case yyabort:                                                            \
+      goto yyabortlab;                                                       \
+    case yyaccept:                                                           \
+      goto yyacceptlab;                                                      \
+    case yyerr:                                                              \
+      goto yyuser_error;                                                     \
+    default:                                                                 \
+      goto yybuglab;                                                         \
+    }                                                                        \
+  } while (YYID (0))
+
+
+/*----------.
+| yyparse.  |
+`----------*/
+
+int
+yyparse (ParseState* parse_state, yyscan_t scanner)
+{
+  int yyresult;
+  yyGLRStack yystack;
+  yyGLRStack* const yystackp = &yystack;
+  size_t yyposn;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yychar = YYEMPTY;
+  yylval = yyval_default;
+  yylloc = yyloc_default;
+
+  if (! yyinitGLRStack (yystackp, YYINITDEPTH))
+    goto yyexhaustedlab;
+  switch (YYSETJMP (yystack.yyexception_buffer))
+    {
+    case 0: break;
+    case 1: goto yyabortlab;
+    case 2: goto yyexhaustedlab;
+    default: goto yybuglab;
+    }
+  yyglrShift (&yystack, 0, 0, 0, &yylval, &yylloc);
+  yyposn = 0;
+
+  while (YYID (yytrue))
+    {
+      /* For efficiency, we have two loops, the first of which is
+         specialized to deterministic operation (single stack, no
+         potential ambiguity).  */
+      /* Standard mode */
+      while (YYID (yytrue))
+        {
+          yyRuleNum yyrule;
+          int yyaction;
+          const short int* yyconflicts;
+
+          yyStateNum yystate = yystack.yytops.yystates[0]->yylrState;
+          YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+          if (yystate == YYFINAL)
+            goto yyacceptlab;
+          if (yyisDefaultedState (yystate))
+            {
+              yyrule = yydefaultAction (yystate);
+              if (yyrule == 0)
+                {
+               yystack.yyerror_range[1].yystate.yyloc = yylloc;
+                  yyreportSyntaxError (&yystack, parse_state, scanner);
+                  goto yyuser_error;
+                }
+              YYCHK1 (yyglrReduce (&yystack, 0, yyrule, yytrue, parse_state, scanner));
+            }
+          else
+            {
+              yySymbol yytoken;
+              if (yychar == YYEMPTY)
+                {
+                  YYDPRINTF ((stderr, "Reading a token: "));
+                  yychar = YYLEX;
+                }
+
+              if (yychar <= YYEOF)
+                {
+                  yychar = yytoken = YYEOF;
+                  YYDPRINTF ((stderr, "Now at end of input.\n"));
+                }
+              else
+                {
+                  yytoken = YYTRANSLATE (yychar);
+                  YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+                }
+
+              yygetLRActions (yystate, yytoken, &yyaction, &yyconflicts);
+              if (*yyconflicts != 0)
+                break;
+              if (yyisShiftAction (yyaction))
+                {
+                  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+                  yychar = YYEMPTY;
+                  yyposn += 1;
+                  yyglrShift (&yystack, 0, yyaction, yyposn, &yylval, &yylloc);
+                  if (0 < yystack.yyerrState)
+                    yystack.yyerrState -= 1;
+                }
+              else if (yyisErrorAction (yyaction))
+                {
+               yystack.yyerror_range[1].yystate.yyloc = yylloc;
+                  yyreportSyntaxError (&yystack, parse_state, scanner);
+                  goto yyuser_error;
+                }
+              else
+                YYCHK1 (yyglrReduce (&yystack, 0, -yyaction, yytrue, parse_state, scanner));
+            }
+        }
+
+      while (YYID (yytrue))
+        {
+          yySymbol yytoken_to_shift;
+          size_t yys;
+
+          for (yys = 0; yys < yystack.yytops.yysize; yys += 1)
+            yystackp->yytops.yylookaheadNeeds[yys] = yychar != YYEMPTY;
+
+          /* yyprocessOneStack returns one of three things:
+
+              - An error flag.  If the caller is yyprocessOneStack, it
+                immediately returns as well.  When the caller is finally
+                yyparse, it jumps to an error label via YYCHK1.
+
+              - yyok, but yyprocessOneStack has invoked yymarkStackDeleted
+                (&yystack, yys), which sets the top state of yys to NULL.  Thus,
+                yyparse's following invocation of yyremoveDeletes will remove
+                the stack.
+
+              - yyok, when ready to shift a token.
+
+             Except in the first case, yyparse will invoke yyremoveDeletes and
+             then shift the next token onto all remaining stacks.  This
+             synchronization of the shift (that is, after all preceding
+             reductions on all stacks) helps prevent double destructor calls
+             on yylval in the event of memory exhaustion.  */
+
+          for (yys = 0; yys < yystack.yytops.yysize; yys += 1)
+            YYCHK1 (yyprocessOneStack (&yystack, yys, yyposn, &yylloc, parse_state, scanner));
+          yyremoveDeletes (&yystack);
+          if (yystack.yytops.yysize == 0)
+            {
+              yyundeleteLastStack (&yystack);
+              if (yystack.yytops.yysize == 0)
+                yyFail (&yystack, &yylloc, parse_state, scanner, YY_("syntax error"));
+              YYCHK1 (yyresolveStack (&yystack, parse_state, scanner));
+              YYDPRINTF ((stderr, "Returning to deterministic operation.\n"));
+           yystack.yyerror_range[1].yystate.yyloc = yylloc;
+              yyreportSyntaxError (&yystack, parse_state, scanner);
+              goto yyuser_error;
+            }
+
+          /* If any yyglrShift call fails, it will fail after shifting.  Thus,
+             a copy of yylval will already be on stack 0 in the event of a
+             failure in the following loop.  Thus, yychar is set to YYEMPTY
+             before the loop to make sure the user destructor for yylval isn't
+             called twice.  */
+          yytoken_to_shift = YYTRANSLATE (yychar);
+          yychar = YYEMPTY;
+          yyposn += 1;
+          for (yys = 0; yys < yystack.yytops.yysize; yys += 1)
+            {
+              int yyaction;
+              const short int* yyconflicts;
+              yyStateNum yystate = yystack.yytops.yystates[yys]->yylrState;
+              yygetLRActions (yystate, yytoken_to_shift, &yyaction,
+                              &yyconflicts);
+              /* Note that yyconflicts were handled by yyprocessOneStack.  */
+              YYDPRINTF ((stderr, "On stack %lu, ", (unsigned long int) yys));
+              YY_SYMBOL_PRINT ("shifting", yytoken_to_shift, &yylval, &yylloc);
+              yyglrShift (&yystack, yys, yyaction, yyposn,
+                          &yylval, &yylloc);
+              YYDPRINTF ((stderr, "Stack %lu now in state #%d\n",
+                          (unsigned long int) yys,
+                          yystack.yytops.yystates[yys]->yylrState));
+            }
+
+          if (yystack.yytops.yysize == 1)
+            {
+              YYCHK1 (yyresolveStack (&yystack, parse_state, scanner));
+              YYDPRINTF ((stderr, "Returning to deterministic operation.\n"));
+              yycompressStack (&yystack);
+              break;
+            }
+        }
+      continue;
+    yyuser_error:
+      yyrecoverSyntaxError (&yystack, parse_state, scanner);
+      yyposn = yystack.yytops.yystates[0]->yyposn;
+    }
+
+ yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+ yybuglab:
+  YYASSERT (yyfalse);
+  goto yyabortlab;
+
+ yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+ yyexhaustedlab:
+  yyerror (&yylloc, parse_state, scanner, YY_("memory exhausted"));
+  yyresult = 2;
+  goto yyreturn;
+
+ yyreturn:
+  if (yychar != YYEMPTY)
+    yydestruct ("Cleanup: discarding lookahead",
+                YYTRANSLATE (yychar), &yylval, &yylloc, parse_state, scanner);
+
+  /* If the stack is well-formed, pop the stack until it is empty,
+     destroying its entries as we go.  But free the stack regardless
+     of whether it is well-formed.  */
+  if (yystack.yyitems)
+    {
+      yyGLRState** yystates = yystack.yytops.yystates;
+      if (yystates)
+        {
+          size_t yysize = yystack.yytops.yysize;
+          size_t yyk;
+          for (yyk = 0; yyk < yysize; yyk += 1)
+            if (yystates[yyk])
+              {
+                while (yystates[yyk])
+                  {
+                    yyGLRState *yys = yystates[yyk];
+                 yystack.yyerror_range[1].yystate.yyloc = yys->yyloc;
+                  if (yys->yypred != YY_NULL)
+                      yydestroyGLRState ("Cleanup: popping", yys, parse_state, scanner);
+                    yystates[yyk] = yys->yypred;
+                    yystack.yynextFree -= 1;
+                    yystack.yyspaceLeft += 1;
+                  }
+                break;
+              }
+        }
+      yyfreeGLRStack (&yystack);
+    }
+
+  /* Make sure YYID is used.  */
+  return YYID (yyresult);
+}
+
+/* DEBUGGING ONLY */
+#if YYDEBUG
+static void yypstack (yyGLRStack* yystackp, size_t yyk)
+  __attribute__ ((__unused__));
+static void yypdumpstack (yyGLRStack* yystackp) __attribute__ ((__unused__));
+
+static void
+yy_yypstack (yyGLRState* yys)
+{
+  if (yys->yypred)
+    {
+      yy_yypstack (yys->yypred);
+      YYFPRINTF (stderr, " -> ");
+    }
+  YYFPRINTF (stderr, "%d@%lu", yys->yylrState,
+             (unsigned long int) yys->yyposn);
+}
+
+static void
+yypstates (yyGLRState* yyst)
+{
+  if (yyst == YY_NULL)
+    YYFPRINTF (stderr, "<null>");
+  else
+    yy_yypstack (yyst);
+  YYFPRINTF (stderr, "\n");
+}
+
+static void
+yypstack (yyGLRStack* yystackp, size_t yyk)
+{
+  yypstates (yystackp->yytops.yystates[yyk]);
+}
+
+#define YYINDEX(YYX)                                                         \
+    ((YYX) == YY_NULL ? -1 : (yyGLRStackItem*) (YYX) - yystackp->yyitems)
+
+
+static void
+yypdumpstack (yyGLRStack* yystackp)
+{
+  yyGLRStackItem* yyp;
+  size_t yyi;
+  for (yyp = yystackp->yyitems; yyp < yystackp->yynextFree; yyp += 1)
+    {
+      YYFPRINTF (stderr, "%3lu. ",
+                 (unsigned long int) (yyp - yystackp->yyitems));
+      if (*(yybool *) yyp)
+        {
+          YYFPRINTF (stderr, "Res: %d, LR State: %d, posn: %lu, pred: %ld",
+                     yyp->yystate.yyresolved, yyp->yystate.yylrState,
+                     (unsigned long int) yyp->yystate.yyposn,
+                     (long int) YYINDEX (yyp->yystate.yypred));
+          if (! yyp->yystate.yyresolved)
+            YYFPRINTF (stderr, ", firstVal: %ld",
+                       (long int) YYINDEX (yyp->yystate
+                                             .yysemantics.yyfirstVal));
+        }
+      else
+        {
+          YYFPRINTF (stderr, "Option. rule: %d, state: %ld, next: %ld",
+                     yyp->yyoption.yyrule - 1,
+                     (long int) YYINDEX (yyp->yyoption.yystate),
+                     (long int) YYINDEX (yyp->yyoption.yynext));
+        }
+      YYFPRINTF (stderr, "\n");
+    }
+  YYFPRINTF (stderr, "Tops:");
+  for (yyi = 0; yyi < yystackp->yytops.yysize; yyi += 1)
+    YYFPRINTF (stderr, "%lu: %ld; ", (unsigned long int) yyi,
+               (long int) YYINDEX (yystackp->yytops.yystates[yyi]));
+  YYFPRINTF (stderr, "\n");
+}
+#endif
+/* Line 2575 of glr.c  */
+#line 969 "..\\..\\Source\\BansheeSL\\BsParserFX.y"
+
+
+void yyerror(YYLTYPE *locp, ParseState* parse_state, yyscan_t scanner, const char *msg) 
+{ 
+	parse_state->hasError = 1;
+	parse_state->errorLine = locp->first_line;
+	parse_state->errorColumn = locp->first_column;
+	parse_state->errorMessage = mmalloc_strdup(parse_state->memContext, msg);
+	parse_state->errorFile = locp->filename;
 }

+ 1 - 7
Source/MBansheeEditor/Scene/Gizmos/JointGizmos.cs

@@ -1,10 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace BansheeEditor.Scene.Gizmos
+namespace BansheeEditor
 {
     class JointGizmos
     {

+ 1064 - 1059
Source/RenderBeast/Source/BsRenderBeast.cpp

@@ -1,1060 +1,1065 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsRenderBeast.h"
-#include "BsCCamera.h"
-#include "BsCRenderable.h"
-#include "BsMaterial.h"
-#include "BsMesh.h"
-#include "BsPass.h"
-#include "BsBlendState.h"
-#include "BsRasterizerState.h"
-#include "BsDepthStencilState.h"
-#include "BsSamplerState.h"
-#include "BsCoreApplication.h"
-#include "BsViewport.h"
-#include "BsRenderTarget.h"
-#include "BsRenderQueue.h"
-#include "BsCoreThread.h"
-#include "BsGpuParams.h"
-#include "BsProfilerCPU.h"
-#include "BsShader.h"
-#include "BsGpuParamBlockBuffer.h"
-#include "BsStaticRenderableHandler.h"
-#include "BsTime.h"
-#include "BsRenderableElement.h"
-#include "BsCoreObjectManager.h"
-#include "BsRenderBeastOptions.h"
-#include "BsSamplerOverrides.h"
-#include "BsLight.h"
-#include "BsRenderTexturePool.h"
-#include "BsRenderTargets.h"
-#include "BsRendererUtility.h"
-#include "BsRenderStateManager.h"
-
-using namespace std::placeholders;
-
-namespace BansheeEngine
-{
-	RenderBeast::RenderBeast()
-		:mOptions(bs_shared_ptr_new<RenderBeastOptions>()), mOptionsDirty(true), mStaticHandler(nullptr),
-		mDefaultMaterial(nullptr), mPointLightInMat(nullptr), mPointLightOutMat(nullptr), mDirLightMat(nullptr)
-	{
-
-	}
-
-	const StringID& RenderBeast::getName() const
-	{
-		static StringID name = "RenderBeast";
-		return name;
-	}
-
-	void RenderBeast::initialize()
-	{
-		CoreRenderer::initialize();
-
-		CoreThread::instance().queueCommand(std::bind(&RenderBeast::initializeCore, this));
-	}
-
-	void RenderBeast::destroy()
-	{
-		CoreRenderer::destroy();
-
-		gCoreAccessor().queueCommand(std::bind(&RenderBeast::destroyCore, this));
-		gCoreAccessor().submitToCoreThread(true);
-	}
-
-	void RenderBeast::initializeCore()
-	{
-		RendererUtility::startUp();
-
-		mCoreOptions = bs_shared_ptr_new<RenderBeastOptions>();
-		mStaticHandler = bs_new<StaticRenderableHandler>();
-
-		mDefaultMaterial = bs_new<DefaultMaterial>();
-		mPointLightInMat = bs_new<PointLightInMat>();
-		mPointLightOutMat = bs_new<PointLightOutMat>();
-		mDirLightMat = bs_new<DirectionalLightMat>();
-
-		RenderTexturePool::startUp();
-	}
-
-	void RenderBeast::destroyCore()
-	{
-		if (mStaticHandler != nullptr)
-			bs_delete(mStaticHandler);
-
-		mRenderTargets.clear();
-		mCameraData.clear();
-		mRenderables.clear();
-
-		RenderTexturePool::shutDown();
-
-		bs_delete(mDefaultMaterial);
-		bs_delete(mPointLightInMat);
-		bs_delete(mPointLightOutMat);
-		bs_delete(mDirLightMat);
-
-		RendererUtility::shutDown();
-
-		assert(mSamplerOverrides.empty());
-	}
-
-	void RenderBeast::_notifyRenderableAdded(RenderableCore* renderable)
-	{
-		UINT32 renderableId = (UINT32)mRenderables.size();
-
-		renderable->setRendererId(renderableId);
-
-		mRenderables.push_back(RenderableData());
-		mRenderableShaderData.push_back(RenderableShaderData());
-		mWorldBounds.push_back(renderable->getBounds());
-
-		RenderableData& renderableData = mRenderables.back();
-		renderableData.renderable = renderable;
-
-		RenderableShaderData& shaderData = mRenderableShaderData.back();
-		shaderData.worldTransform = renderable->getTransform();
-		shaderData.invWorldTransform = shaderData.worldTransform.inverseAffine();
-		shaderData.worldNoScaleTransform = renderable->getTransformNoScale();
-		shaderData.invWorldNoScaleTransform = shaderData.worldNoScaleTransform.inverseAffine();
-		shaderData.worldDeterminantSign = shaderData.worldTransform.determinant3x3() >= 0.0f ? 1.0f : -1.0f;
-
-		if (renderable->getRenderableType() == RenType_LitTextured)
-			renderableData.controller = mStaticHandler;
-		else
-			renderableData.controller = nullptr;
-
-		SPtr<MeshCore> mesh = renderable->getMesh();
-		if (mesh != nullptr)
-		{
-			const MeshProperties& meshProps = mesh->getProperties();
-			SPtr<VertexDeclarationCore> vertexDecl = mesh->getVertexData()->vertexDeclaration;
-
-			for (UINT32 i = 0; i < meshProps.getNumSubMeshes(); i++)
-			{
-				renderableData.elements.push_back(BeastRenderableElement());
-				BeastRenderableElement& renElement = renderableData.elements.back();
-
-				renElement.mesh = mesh;
-				renElement.subMesh = meshProps.getSubMesh(i);
-				renElement.renderableId = renderableId;
-
-				renElement.material = renderable->getMaterial(i);
-				if (renElement.material == nullptr)
-					renElement.material = renderable->getMaterial(0);
-
-				if (renElement.material != nullptr && renElement.material->getShader() == nullptr)
-					renElement.material = nullptr;
-
-				// Validate mesh <-> shader vertex bindings
-				if (renElement.material != nullptr)
-				{
-					UINT32 numPasses = renElement.material->getNumPasses();
-					for (UINT32 j = 0; j < numPasses; j++)
-					{
-						SPtr<PassCore> pass = renElement.material->getPass(j);
-
-						SPtr<VertexDeclarationCore> shaderDecl = pass->getVertexProgram()->getInputDeclaration();
-						if (!vertexDecl->isCompatible(shaderDecl))
-						{
-							Vector<VertexElement> missingElements = vertexDecl->getMissingElements(shaderDecl);
-
-							StringStream wrnStream;
-							wrnStream << "Provided mesh is missing required vertex attributes to render with the provided shader. Missing elements: " << std::endl;
-
-							for (auto& entry : missingElements)
-								wrnStream << "\t" << toString(entry.getSemantic()) << entry.getSemanticIdx() << std::endl;
-
-							LOGWRN(wrnStream.str());
-							break;
-						}
-					}
-				}
-
-				// If no material use the default material
-				if (renElement.material == nullptr)
-					renElement.material = mDefaultMaterial->getMaterial();
-
-				auto iterFind = mSamplerOverrides.find(renElement.material);
-				if (iterFind != mSamplerOverrides.end())
-				{
-					renElement.samplerOverrides = iterFind->second;
-					iterFind->second->refCount++;
-				}
-				else
-				{
-					MaterialSamplerOverrides* samplerOverrides = SamplerOverrideUtility::generateSamplerOverrides(renElement.material, mCoreOptions);
-					mSamplerOverrides[renElement.material] = samplerOverrides;
-
-					renElement.samplerOverrides = samplerOverrides;
-					samplerOverrides->refCount++;
-				}
-
-				if (renderableData.controller != nullptr)
-					renderableData.controller->initializeRenderElem(renElement);
-			}
-		}
-	}
-
-	void RenderBeast::_notifyRenderableRemoved(RenderableCore* renderable)
-	{
-		UINT32 renderableId = renderable->getRendererId();
-		RenderableCore* lastRenerable = mRenderables.back().renderable;
-		UINT32 lastRenderableId = lastRenerable->getRendererId();
-
-		Vector<BeastRenderableElement>& elements = mRenderables[renderableId].elements;
-		for (auto& element : elements)
-		{
-			auto iterFind = mSamplerOverrides.find(element.material);
-			assert(iterFind != mSamplerOverrides.end());
-
-			MaterialSamplerOverrides* samplerOverrides = iterFind->second;
-			samplerOverrides->refCount--;
-			if (samplerOverrides->refCount == 0)
-			{
-				SamplerOverrideUtility::destroySamplerOverrides(samplerOverrides);
-				mSamplerOverrides.erase(iterFind);
-			}
-
-			element.samplerOverrides = nullptr;
-		}
-
-		if (renderableId != lastRenderableId)
-		{
-			// Swap current last element with the one we want to erase
-			std::swap(mRenderables[renderableId], mRenderables[lastRenderableId]);
-			std::swap(mWorldBounds[renderableId], mWorldBounds[lastRenderableId]);
-			std::swap(mRenderableShaderData[renderableId], mRenderableShaderData[lastRenderableId]);
-
-			lastRenerable->setRendererId(renderableId);
-
-			Vector<BeastRenderableElement>& lastRenderableElements = mRenderables[renderableId].elements;
-			for (auto& element : elements)
-				element.renderableId = renderableId;
-		}
-
-		// Last element is the one we want to erase
-		mRenderables.erase(mRenderables.end() - 1);
-		mWorldBounds.erase(mWorldBounds.end() - 1);
-		mRenderableShaderData.erase(mRenderableShaderData.end() - 1);
-	}
-
-	void RenderBeast::_notifyRenderableUpdated(RenderableCore* renderable)
-	{
-		UINT32 renderableId = renderable->getRendererId();
-
-		RenderableShaderData& shaderData = mRenderableShaderData[renderableId];
-		shaderData.worldTransform = renderable->getTransform();
-		shaderData.invWorldTransform = shaderData.worldTransform.inverseAffine();
-		shaderData.worldNoScaleTransform = renderable->getTransformNoScale();
-		shaderData.invWorldNoScaleTransform = shaderData.worldNoScaleTransform.inverseAffine();
-		shaderData.worldDeterminantSign = shaderData.worldTransform.determinant3x3() >= 0.0f ? 1.0f : -1.0f;
-
-		mWorldBounds[renderableId] = renderable->getBounds();
-	}
-
-	void RenderBeast::_notifyLightAdded(LightCore* light)
-	{
-		if (light->getType() == LightType::Directional)
-		{
-			UINT32 lightId = (UINT32)mDirectionalLights.size();
-			light->setRendererId(lightId);
-
-			mDirectionalLights.push_back(LightData());
-
-			LightData& lightData = mDirectionalLights.back();
-			lightData.internal = light;
-		}
-		else
-		{
-			UINT32 lightId = (UINT32)mPointLights.size();
-
-			light->setRendererId(lightId);
-
-			mPointLights.push_back(LightData());
-			mLightWorldBounds.push_back(light->getBounds());
-
-			LightData& lightData = mPointLights.back();
-			lightData.internal = light;
-		}
-	}
-
-	void RenderBeast::_notifyLightUpdated(LightCore* light)
-	{
-		UINT32 lightId = light->getRendererId();
-
-		if (light->getType() != LightType::Directional)
-			mLightWorldBounds[lightId] = light->getBounds();
-	}
-
-	void RenderBeast::_notifyLightRemoved(LightCore* light)
-	{
-		UINT32 lightId = light->getRendererId();
-		if (light->getType() == LightType::Directional)
-		{
-			LightCore* lastLight = mDirectionalLights.back().internal;
-			UINT32 lastLightId = lastLight->getRendererId();
-
-			if (lightId != lastLightId)
-			{
-				// Swap current last element with the one we want to erase
-				std::swap(mDirectionalLights[lightId], mDirectionalLights[lastLightId]);
-				lastLight->setRendererId(lightId);
-			}
-
-			// Last element is the one we want to erase
-			mDirectionalLights.erase(mDirectionalLights.end() - 1);
-		}
-		else
-		{
-			LightCore* lastLight = mPointLights.back().internal;
-			UINT32 lastLightId = lastLight->getRendererId();
-
-			if (lightId != lastLightId)
-			{
-				// Swap current last element with the one we want to erase
-				std::swap(mPointLights[lightId], mPointLights[lastLightId]);
-				std::swap(mLightWorldBounds[lightId], mLightWorldBounds[lastLightId]);
-
-				lastLight->setRendererId(lightId);
-			}
-
-			// Last element is the one we want to erase
-			mPointLights.erase(mPointLights.end() - 1);
-			mLightWorldBounds.erase(mLightWorldBounds.end() - 1);
-		}
-	}
-
-	void RenderBeast::_notifyCameraAdded(const CameraCore* camera)
-	{
-		SPtr<RenderTargetCore> renderTarget = camera->getViewport()->getTarget();
-		if (renderTarget == nullptr)
-			return;
-
-		CameraData& camData = mCameraData[camera];
-		camData.opaqueQueue = bs_shared_ptr_new<RenderQueue>(mCoreOptions->stateReductionMode);
-
-		StateReduction transparentStateReduction = mCoreOptions->stateReductionMode;
-		if (transparentStateReduction == StateReduction::Material)
-			transparentStateReduction = StateReduction::Distance; // Transparent object MUST be sorted by distance
-
-		camData.transparentQueue = bs_shared_ptr_new<RenderQueue>(transparentStateReduction);
-
-		// Register in render target list
-		auto findIter = std::find_if(mRenderTargets.begin(), mRenderTargets.end(), 
-			[&](const RenderTargetData& x) { return x.target == renderTarget; });
-
-		if (findIter != mRenderTargets.end())
-		{
-			findIter->cameras.push_back(camera);
-		}
-		else
-		{
-			mRenderTargets.push_back(RenderTargetData());
-			RenderTargetData& renderTargetData = mRenderTargets.back();
-
-			renderTargetData.target = renderTarget;
-			renderTargetData.cameras.push_back(camera);
-		}
-
-		// Sort render targets based on priority
-		auto cameraComparer = [&](const CameraCore* a, const CameraCore* b) { return a->getPriority() > b->getPriority(); };
-		auto renderTargetInfoComparer = [&](const RenderTargetData& a, const RenderTargetData& b)
-		{ return a.target->getProperties().getPriority() > b.target->getProperties().getPriority(); };
-		std::sort(begin(mRenderTargets), end(mRenderTargets), renderTargetInfoComparer);
-
-		for (auto& camerasPerTarget : mRenderTargets)
-		{
-			Vector<const CameraCore*>& cameras = camerasPerTarget.cameras;
-
-			std::sort(begin(cameras), end(cameras), cameraComparer);
-		}
-	}
-
-	void RenderBeast::_notifyCameraRemoved(const CameraCore* camera)
-	{
-		mCameraData.erase(camera);
-
-		// Remove from render target list
-		for (auto iterTarget = mRenderTargets.begin(); iterTarget != mRenderTargets.end(); ++iterTarget)
-		{
-			RenderTargetData& target = *iterTarget;
-			for (auto iterCam = target.cameras.begin(); iterCam != target.cameras.end(); ++iterCam)
-			{
-				if (camera == *iterCam)
-				{
-					target.cameras.erase(iterCam);
-					break;
-				}
-			}
-
-			if (target.cameras.empty())
-			{
-				mRenderTargets.erase(iterTarget);
-				break;
-			}
-		}
-	}
-
-	void RenderBeast::setOptions(const SPtr<CoreRendererOptions>& options)
-	{
-		mOptions = std::static_pointer_cast<RenderBeastOptions>(options);
-		mOptionsDirty = true;
-	}
-
-	SPtr<CoreRendererOptions> RenderBeast::getOptions() const
-	{
-		return mOptions;
-	}
-
-	void RenderBeast::renderAll() 
-	{
-		// Sync all dirty sim thread CoreObject data to core thread
-		CoreObjectManager::instance().syncToCore(gCoreAccessor());
-
-		if (mOptionsDirty)
-		{
-			gCoreAccessor().queueCommand(std::bind(&RenderBeast::syncRenderOptions, this, *mOptions));
-			mOptionsDirty = false;
-		}
-
-		gCoreAccessor().queueCommand(std::bind(&RenderBeast::renderAllCore, this, gTime().getTime()));
-	}
-
-	void RenderBeast::syncRenderOptions(const RenderBeastOptions& options)
-	{
-		bool filteringChanged = mCoreOptions->filtering != options.filtering;
-		if (options.filtering == RenderBeastFiltering::Anisotropic)
-			filteringChanged |= mCoreOptions->anisotropyMax != options.anisotropyMax;
-
-		if (filteringChanged)
-			refreshSamplerOverrides(true);
-
-		*mCoreOptions = options;
-
-		for (auto& cameraData : mCameraData)
-		{
-			cameraData.second.opaqueQueue->setStateReduction(mCoreOptions->stateReductionMode);
-
-			StateReduction transparentStateReduction = mCoreOptions->stateReductionMode;
-			if (transparentStateReduction == StateReduction::Material)
-				transparentStateReduction = StateReduction::Distance; // Transparent object MUST be sorted by distance
-
-			cameraData.second.transparentQueue->setStateReduction(transparentStateReduction);
-		}
-	}
-
-	void RenderBeast::renderAllCore(float time)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		gProfilerCPU().beginSample("renderAllCore");
-
-		// Note: I'm iterating over all sampler states every frame. If this ends up being a performance
-		// issue consider handling this internally in MaterialCore which can only do it when sampler states
-		// are actually modified after sync
-		refreshSamplerOverrides();
-
-		// Update global per-frame hardware buffers
-		mStaticHandler->updatePerFrameBuffers(time);
-
-		// Generate render queues per camera
-		for (auto& cameraData : mCameraData)
-		{
-			const CameraCore* camera = cameraData.first;
-			determineVisible(*camera);
-		}
-
-		// Render everything, target by target
-		for (auto& renderTargetData : mRenderTargets)
-		{
-			SPtr<RenderTargetCore> target = renderTargetData.target;
-			Vector<const CameraCore*>& cameras = renderTargetData.cameras;
-
-			RenderAPICore::instance().beginFrame();
-
-			UINT32 numCameras = (UINT32)cameras.size();
-			for (UINT32 i = 0; i < numCameras; i++)
-				render(renderTargetData, i);
-
-			RenderAPICore::instance().endFrame();
-			RenderAPICore::instance().swapBuffers(target);
-		}
-
-		gProfilerCPU().endSample("renderAllCore");
-	}
-
-	void RenderBeast::render(RenderTargetData& rtData, UINT32 camIdx)
-	{
-		gProfilerCPU().beginSample("Render");
-
-		const CameraCore* camera = rtData.cameras[camIdx];
-		CameraData& camData = mCameraData[camera];
-
-		SPtr<ViewportCore> viewport = camera->getViewport();
-		CameraShaderData cameraShaderData = getCameraShaderData(*camera);
-
-		mStaticHandler->updatePerCameraBuffers(cameraShaderData);
-
-		// Render scene objects to g-buffer
-		bool hasGBuffer = ((UINT32)camera->getFlags() & (UINT32)CameraFlags::Overlay) == 0;
-
-		if (hasGBuffer)
-		{
-			bool createGBuffer = camData.target == nullptr ||
-				camData.target->getHDR() != mCoreOptions->hdr ||
-				camData.target->getNumSamples() != mCoreOptions->msaa;
-
-			if (createGBuffer)
-				camData.target = RenderTargets::create(viewport, mCoreOptions->hdr, mCoreOptions->msaa);
-
-			camData.target->allocate();
-			camData.target->bindGBuffer();
-		}
-		else
-			camData.target = nullptr;
-
-		// Trigger pre-scene callbacks
-		auto iterCameraCallbacks = mRenderCallbacks.find(camera);
-		if (iterCameraCallbacks != mRenderCallbacks.end())
-		{
-			for (auto& callbackPair : iterCameraCallbacks->second)
-			{
-				const RenderCallbackData& callbackData = callbackPair.second;
-
-				if (callbackData.overlay)
-					continue;
-
-				if (callbackPair.first >= 0)
-					break;
-
-				callbackData.callback();
-			}
-		}
-		
-		if (hasGBuffer)
-		{
-			// Render base pass
-			const Vector<RenderQueueElement>& opaqueElements = camData.opaqueQueue->getSortedElements();
-			for (auto iter = opaqueElements.begin(); iter != opaqueElements.end(); ++iter)
-			{
-				BeastRenderableElement* renderElem = static_cast<BeastRenderableElement*>(iter->renderElem);
-				SPtr<MaterialCore> material = renderElem->material;
-
-				UINT32 rendererId = renderElem->renderableId;
-				Matrix4 worldViewProjMatrix = cameraShaderData.viewProj * mRenderableShaderData[rendererId].worldTransform;
-
-				mStaticHandler->updatePerObjectBuffers(*renderElem, mRenderableShaderData[rendererId], worldViewProjMatrix);
-				mStaticHandler->bindGlobalBuffers(*renderElem); // Note: If I can keep global buffer slot indexes the same between shaders I could only bind these once
-				mStaticHandler->bindPerObjectBuffers(*renderElem);
-
-				if (iter->applyPass)
-				{
-					SPtr<PassCore> pass = material->getPass(iter->passIdx);
-					setPass(pass);
-				}
-
-				SPtr<PassParametersCore> passParams = material->getPassParameters(iter->passIdx);
-
-				if (renderElem->samplerOverrides != nullptr)
-					setPassParams(passParams, &renderElem->samplerOverrides->passes[iter->passIdx]);
-				else
-					setPassParams(passParams, nullptr);
-
-				gRendererUtility().draw(iter->renderElem->mesh, iter->renderElem->subMesh);
-			}
-
-			camData.target->bindSceneColor(true);
-
-			// Render light pass
-			SPtr<GpuParamBlockBufferCore> perCameraBuffer = mStaticHandler->getPerCameraParams().getBuffer();
-
-			SPtr<MaterialCore> dirMaterial = mDirLightMat->getMaterial();
-			SPtr<PassCore> dirPass = dirMaterial->getPass(0);
-
-			setPass(dirPass);
-			mDirLightMat->setStaticParameters(camData.target, perCameraBuffer);
-
-			for (auto& light : mDirectionalLights)
-			{
-				if (!light.internal->getIsActive())
-					continue;
-
-				mDirLightMat->setParameters(light.internal);
-
-				// TODO - Bind parameters to the pipeline manually as I don't need to re-bind gbuffer textures for every light
-				//  - I can't think of a good way to do this automatically. Probably best to do it in setParameters()
-				setPassParams(dirMaterial->getPassParameters(0), nullptr);
-				gRendererUtility().drawScreenQuad();
-			}
-
-			// Draw point lights which our camera is within
-			SPtr<MaterialCore> pointInsideMaterial = mPointLightInMat->getMaterial();
-			SPtr<PassCore> pointInsidePass = pointInsideMaterial->getPass(0);
-
-			// TODO - Possibly use instanced drawing here as only two meshes are drawn with various properties
-			setPass(pointInsidePass);
-			mPointLightInMat->setStaticParameters(camData.target, perCameraBuffer);
-
-			// TODO - Cull lights based on visibility, right now I just iterate over all of them. 
-			for (auto& light : mPointLights)
-			{
-				if (!light.internal->getIsActive())
-					continue;
-
-				float distToLight = (light.internal->getBounds().getCenter() - camera->getPosition()).squaredLength();
-				float boundRadius = light.internal->getBounds().getRadius() * 1.05f + camera->getNearClipDistance() * 2.0f;
-
-				bool cameraInLightGeometry = distToLight < boundRadius * boundRadius;
-				if (!cameraInLightGeometry)
-					continue;
-
-				mPointLightInMat->setParameters(light.internal);
-
-				// TODO - Bind parameters to the pipeline manually as I don't need to re-bind gbuffer textures for every light
-				//  - I can't think of a good way to do this automatically. Probably best to do it in setParameters()
-				setPassParams(pointInsideMaterial->getPassParameters(0), nullptr);
-				SPtr<MeshCore> mesh = light.internal->getMesh();
-				gRendererUtility().draw(mesh, mesh->getProperties().getSubMesh(0));
-			}
-
-			// Draw other point lights
-			SPtr<MaterialCore> pointOutsideMaterial = mPointLightOutMat->getMaterial();
-			SPtr<PassCore> pointOutsidePass = pointOutsideMaterial->getPass(0);
-
-			setPass(pointOutsidePass);
-			mPointLightOutMat->setStaticParameters(camData.target, perCameraBuffer);
-
-			for (auto& light : mPointLights)
-			{
-				if (!light.internal->getIsActive())
-					continue;
-
-				float distToLight = (light.internal->getBounds().getCenter() - camera->getPosition()).squaredLength();
-				float boundRadius = light.internal->getBounds().getRadius() * 1.05f + camera->getNearClipDistance() * 2.0f;
-
-				bool cameraInLightGeometry = distToLight < boundRadius * boundRadius;
-				if (cameraInLightGeometry)
-					continue;
-
-				mPointLightOutMat->setParameters(light.internal);
-
-				// TODO - Bind parameters to the pipeline manually as I don't need to re-bind gbuffer textures for every light
-				setPassParams(pointOutsideMaterial->getPassParameters(0), nullptr);
-				SPtr<MeshCore> mesh = light.internal->getMesh();
-				gRendererUtility().draw(mesh, mesh->getProperties().getSubMesh(0));
-			}
-
-			camData.target->bindSceneColor(false);
-		}
-		else
-		{
-			// Prepare final render target
-			SPtr<RenderTargetCore> target = rtData.target;
-
-			RenderAPICore::instance().setRenderTarget(target);
-			RenderAPICore::instance().setViewport(viewport->getNormArea());
-
-			// If first camera in render target, prepare the render target
-			if (camIdx == 0)
-			{
-				UINT32 clearBuffers = 0;
-				if (viewport->getRequiresColorClear())
-					clearBuffers |= FBT_COLOR;
-
-				if (viewport->getRequiresDepthClear())
-					clearBuffers |= FBT_DEPTH;
-
-				if (viewport->getRequiresStencilClear())
-					clearBuffers |= FBT_STENCIL;
-
-				if (clearBuffers != 0)
-				{
-					RenderAPICore::instance().clearViewport(clearBuffers, viewport->getClearColor(),
-						viewport->getClearDepthValue(), viewport->getClearStencilValue());
-				}
-			}
-		}
-
-		// Render transparent objects (TODO - No lighting yet)
-		const Vector<RenderQueueElement>& transparentElements = camData.transparentQueue->getSortedElements();
-		for (auto iter = transparentElements.begin(); iter != transparentElements.end(); ++iter)
-		{
-			BeastRenderableElement* renderElem = static_cast<BeastRenderableElement*>(iter->renderElem);
-			SPtr<MaterialCore> material = renderElem->material;
-
-			UINT32 rendererId = renderElem->renderableId;
-			Matrix4 worldViewProjMatrix = cameraShaderData.viewProj * mRenderableShaderData[rendererId].worldTransform;
-
-			mStaticHandler->updatePerObjectBuffers(*renderElem, mRenderableShaderData[rendererId], worldViewProjMatrix);
-			mStaticHandler->bindGlobalBuffers(*renderElem); // Note: If I can keep global buffer slot indexes the same between shaders I could only bind these once
-			mStaticHandler->bindPerObjectBuffers(*renderElem);
-
-			if (iter->applyPass)
-			{
-				SPtr<PassCore> pass = material->getPass(iter->passIdx);
-				setPass(pass);
-			}
-
-			SPtr<PassParametersCore> passParams = material->getPassParameters(iter->passIdx);
-
-			if (renderElem->samplerOverrides != nullptr)
-				setPassParams(passParams, &renderElem->samplerOverrides->passes[iter->passIdx]);
-			else
-				setPassParams(passParams, nullptr);
-
-			gRendererUtility().draw(iter->renderElem->mesh, iter->renderElem->subMesh);
-		}
-
-		camData.opaqueQueue->clear();
-		camData.transparentQueue->clear();
-
-		// Render non-overlay post-scene callbacks
-		if (iterCameraCallbacks != mRenderCallbacks.end())
-		{
-			for (auto& callbackPair : iterCameraCallbacks->second)
-			{
-				const RenderCallbackData& callbackData = callbackPair.second;
-
-				if (callbackData.overlay || callbackPair.first < 0)
-					continue;
-
-				callbackData.callback();
-			}
-		}
-
-		if (hasGBuffer)
-		{
-			// TODO - Instead of doing a separate resolve here I could potentially perform a resolve directly in some
-			// post-processing pass (e.g. tone mapping). Right now it is just an unnecessary blit.
-			camData.target->resolve();
-		}
-
-		// Render overlay post-scene callbacks
-		if (iterCameraCallbacks != mRenderCallbacks.end())
-		{
-			for (auto& callbackPair : iterCameraCallbacks->second)
-			{
-				const RenderCallbackData& callbackData = callbackPair.second;
-
-				if (!callbackData.overlay)
-					continue;
-
-				callbackData.callback();
-			}
-		}
-
-		if (hasGBuffer)
-			camData.target->release();
-
-		gProfilerCPU().endSample("Render");
-	}
-	
-	void RenderBeast::determineVisible(const CameraCore& camera)
-	{
-		CameraData& cameraData = mCameraData[&camera];
-
-		UINT64 cameraLayers = camera.getLayers();
-		ConvexVolume worldFrustum = camera.getWorldFrustum();
-
-		// Update per-object param buffers and queue render elements
-		for (auto& renderableData : mRenderables)
-		{
-			RenderableCore* renderable = renderableData.renderable;
-			RenderableHandler* controller = renderableData.controller;
-			UINT32 renderableType = renderable->getRenderableType();
-			UINT32 rendererId = renderable->getRendererId();
-
-			if ((renderable->getLayer() & cameraLayers) == 0)
-				continue;
-
-			// Do frustum culling
-			// TODO - This is bound to be a bottleneck at some point. When it is ensure that intersect
-			// methods use vector operations, as it is trivial to update them.
-			const Sphere& boundingSphere = mWorldBounds[rendererId].getSphere();
-			if (worldFrustum.intersects(boundingSphere))
-			{
-				// More precise with the box
-				const AABox& boundingBox = mWorldBounds[rendererId].getBox();
-
-				if (worldFrustum.intersects(boundingBox))
-				{
-					float distanceToCamera = (camera.getPosition() - boundingBox.getCenter()).length();
-
-					for (auto& renderElem : renderableData.elements)
-					{
-						bool isTransparent = (renderElem.material->getShader()->getFlags() & (UINT32)ShaderFlags::Transparent) != 0;
-
-						if (isTransparent)
-							cameraData.transparentQueue->add(&renderElem, distanceToCamera);
-						else
-							cameraData.opaqueQueue->add(&renderElem, distanceToCamera);
-					}
-
-				}
-			}
-		}
-
-		cameraData.opaqueQueue->sort();
-		cameraData.transparentQueue->sort();
-	}
-
-	Vector2 RenderBeast::getDeviceZTransform(const Matrix4& projMatrix)
-	{
-		// Returns a set of values that will transform depth buffer values (e.g. [0, 1] in DX, [-1, 1] in GL) to a distance
-		// in world space. This involes applying the inverse projection transform to the depth value. When you multiply
-		// a vector with the projection matrix you get [clipX, clipY, Az + B, C * z], where we don't care about clipX/clipY.
-		// A is [2, 2], B is [2, 3] and C is [3, 2] elements of the projection matrix (only ones that matter for our depth 
-		// value). The hardware will also automatically divide the z value with w to get the depth, therefore the final 
-		// formula is:
-		// depth = (Az + B) / (C * z)
-
-		// To get the z coordinate back we simply do the opposite: 
-		// z = B / (depth * C - A)
-
-		// However some APIs will also do a transformation on the depth values before storing them to the texture 
-		// (e.g. OpenGL will transform from [-1, 1] to [0, 1]). And we need to reverse that as well. Therefore the final 
-		// formula is:
-		// z = B / ((depth * (maxDepth - minDepth) + minDepth) * C - A)
-
-		// Are we reorganize it because it needs to fit the "(1.0f / (depth + y)) * x" format used in the shader:
-		// z = 1.0f / (depth + minDepth/(maxDepth - minDepth) - A/((maxDepth - minDepth) * C)) * B/((maxDepth - minDepth) * C)
-
-		RenderAPICore& rapi = RenderAPICore::instance();
-
-		float depthRange = rapi.getMaximumDepthInputValue() - rapi.getMinimumDepthInputValue();
-		float minDepth = rapi.getMinimumDepthInputValue();
-
-		float a = projMatrix[2][2];
-		float b = projMatrix[2][3];
-		float c = projMatrix[3][2];
-
-		Vector2 output;
-		output.x = b / (depthRange * c);
-		output.y = minDepth / depthRange - a / (depthRange * c);
-
-		return output;
-	}
-
-	CameraShaderData RenderBeast::getCameraShaderData(const CameraCore& camera)
-	{
-		CameraShaderData data;
-		data.proj = camera.getProjectionMatrixRS();
-		data.view = camera.getViewMatrix();
-		data.viewProj = data.proj * data.view;
-		data.invProj = data.proj.inverse();
-		data.invViewProj = data.viewProj.inverse(); // Note: Calculate inverses separately (better precision possibly)
-
-		// Construct a special inverse view-projection matrix that had projection entries that affect z and w eliminated.
-		// Used to transform a vector(clip_x, clip_y, view_z, view_w), where clip_x/clip_y are in clip space, and 
-		// view_z/view_w in view space, into world space.
-
-		// Only projects z/w coordinates
-		Matrix4 projZ = Matrix4::IDENTITY;
-		projZ[2][2] = data.proj[2][2];
-		projZ[2][3] = data.proj[2][3];
-		projZ[3][2] = data.proj[3][2];
-		projZ[3][3] = 0.0f;
-
-		data.screenToWorld = data.invViewProj * projZ;
-		data.viewDir = camera.getForward();
-		data.viewOrigin = camera.getPosition();
-		data.deviceZToWorldZ = getDeviceZTransform(data.proj);
-
-		SPtr<ViewportCore> viewport = camera.getViewport();
-		SPtr<RenderTargetCore> rt = viewport->getTarget();
-
-		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 / rtWidth;
-		data.clipToUVScaleOffset.y = halfHeight / rtHeight; // TODO - Negate for DX11
-		data.clipToUVScaleOffset.z = viewport->getX() / rtWidth + (halfWidth + rapi.getHorizontalTexelOffset()) / rtWidth;
-		data.clipToUVScaleOffset.w = viewport->getY() / rtHeight + (halfHeight + rapi.getVerticalTexelOffset()) / rtHeight;
-
-		return data;
-	}
-
-	void RenderBeast::refreshSamplerOverrides(bool force)
-	{
-		for (auto& entry : mSamplerOverrides)
-		{
-			SPtr<MaterialCore> material = entry.first;
-
-			if (force)
-			{
-				SamplerOverrideUtility::destroySamplerOverrides(entry.second);
-				entry.second = SamplerOverrideUtility::generateSamplerOverrides(material, mCoreOptions);
-			}
-			else
-			{
-				MaterialSamplerOverrides* materialOverrides = entry.second;
-				UINT32 numPasses = material->getNumPasses();
-
-				assert(numPasses == materialOverrides->numPasses);
-				for (UINT32 i = 0; i < numPasses; i++)
-				{
-					SPtr<PassParametersCore> passParams = material->getPassParameters(i);
-					PassSamplerOverrides& passOverrides = materialOverrides->passes[i];
-
-					for (UINT32 j = 0; j < PassParametersCore::NUM_PARAMS; j++)
-					{
-						StageSamplerOverrides& stageOverrides = passOverrides.stages[j];
-
-						SPtr<GpuParamsCore> params = passParams->getParamByIdx(j);
-						if (params == nullptr)
-							continue;
-
-						const GpuParamDesc& paramDesc = params->getParamDesc();
-
-						for (auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
-						{
-							UINT32 slot = iter->second.slot;
-							SPtr<SamplerStateCore> samplerState = params->getSamplerState(slot);
-
-							assert(stageOverrides.numStates > slot);
-
-							if (samplerState != stageOverrides.stateOverrides[slot])
-							{
-								if (samplerState != nullptr)
-									stageOverrides.stateOverrides[slot] = SamplerOverrideUtility::generateSamplerOverride(samplerState, mCoreOptions);
-								else
-									stageOverrides.stateOverrides[slot] = SamplerOverrideUtility::generateSamplerOverride(SamplerStateCore::getDefault(), mCoreOptions);;
-							}	
-						}
-					}
-				}
-			}
-		}
-	}
-
-	void RenderBeast::setPass(const SPtr<PassCore>& pass)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		RenderAPICore& rs = RenderAPICore::instance();
-
-		struct StageData
-		{
-			GpuProgramType type;
-			bool enable;
-			SPtr<GpuProgramCore> program;
-		};
-
-		const UINT32 numStages = 6;
-		StageData stages[numStages] =
-		{
-			{ GPT_VERTEX_PROGRAM, pass->hasVertexProgram(), pass->getVertexProgram() },
-			{ GPT_FRAGMENT_PROGRAM, pass->hasFragmentProgram(), pass->getFragmentProgram() },
-			{ GPT_GEOMETRY_PROGRAM, pass->hasGeometryProgram(), pass->getGeometryProgram() },
-			{ GPT_HULL_PROGRAM, pass->hasHullProgram(), pass->getHullProgram() },
-			{ GPT_DOMAIN_PROGRAM, pass->hasDomainProgram(), pass->getDomainProgram() },
-			{ GPT_COMPUTE_PROGRAM, pass->hasComputeProgram(), pass->getComputeProgram() }
-		};
-
-		for (UINT32 i = 0; i < numStages; i++)
-		{
-			const StageData& stage = stages[i];
-
-			if (stage.enable)
-				rs.bindGpuProgram(stage.program);
-			else
-				rs.unbindGpuProgram(stage.type);
-		}
-
-		// Set up non-texture related pass settings
-		if (pass->getBlendState() != nullptr)
-			rs.setBlendState(pass->getBlendState());
-		else
-			rs.setBlendState(BlendStateCore::getDefault());
-
-		if (pass->getDepthStencilState() != nullptr)
-			rs.setDepthStencilState(pass->getDepthStencilState(), pass->getStencilRefValue());
-		else
-			rs.setDepthStencilState(DepthStencilStateCore::getDefault(), pass->getStencilRefValue());
-
-		if (pass->getRasterizerState() != nullptr)
-			rs.setRasterizerState(pass->getRasterizerState());
-		else
-			rs.setRasterizerState(RasterizerStateCore::getDefault());
-	}
-
-	void RenderBeast::setPassParams(const SPtr<PassParametersCore>& passParams, const PassSamplerOverrides* samplerOverrides)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		RenderAPICore& rs = RenderAPICore::instance();
-
-		struct StageData
-		{
-			GpuProgramType type;
-			SPtr<GpuParamsCore> params;
-		};
-
-		const UINT32 numStages = 6;
-		StageData stages[numStages] =
-		{
-			{ GPT_VERTEX_PROGRAM, passParams->mVertParams },
-			{ GPT_FRAGMENT_PROGRAM, passParams->mFragParams },
-			{ GPT_GEOMETRY_PROGRAM, passParams->mGeomParams },
-			{ GPT_HULL_PROGRAM, passParams->mHullParams },
-			{ GPT_DOMAIN_PROGRAM, passParams->mDomainParams },
-			{ GPT_COMPUTE_PROGRAM, passParams->mComputeParams }
-		};
-
-		for (UINT32 i = 0; i < numStages; i++)
-		{
-			const StageData& stage = stages[i];
-
-			SPtr<GpuParamsCore> params = stage.params;
-			if (params == nullptr)
-				continue;
-
-			const GpuParamDesc& paramDesc = params->getParamDesc();
-
-			for (auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
-			{
-				SPtr<SamplerStateCore> samplerState;
-
-				if (samplerOverrides != nullptr)
-					samplerState = samplerOverrides->stages[i].stateOverrides[iter->second.slot];
-				else
-					samplerState = params->getSamplerState(iter->second.slot);
-
-				if (samplerState == nullptr)
-					rs.setSamplerState(stage.type, iter->second.slot, SamplerStateCore::getDefault());
-				else
-					rs.setSamplerState(stage.type, iter->second.slot, samplerState);
-			}
-
-			for (auto iter = paramDesc.textures.begin(); iter != paramDesc.textures.end(); ++iter)
-			{
-				SPtr<TextureCore> texture = params->getTexture(iter->second.slot);
-
-				if (!params->isLoadStoreTexture(iter->second.slot))
-				{
-					if (texture == nullptr)
-						rs.setTexture(stage.type, iter->second.slot, false, nullptr);
-					else
-						rs.setTexture(stage.type, iter->second.slot, true, texture);
-				}
-				else
-				{
-					const TextureSurface& surface = params->getLoadStoreSurface(iter->second.slot);
-
-					if (texture == nullptr)
-						rs.setLoadStoreTexture(stage.type, iter->second.slot, false, nullptr, surface);
-					else
-						rs.setLoadStoreTexture(stage.type, iter->second.slot, true, texture, surface);
-				}
-			}
-
-			rs.setConstantBuffers(stage.type, params);
-		}
-	}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsRenderBeast.h"
+#include "BsCCamera.h"
+#include "BsCRenderable.h"
+#include "BsMaterial.h"
+#include "BsMesh.h"
+#include "BsPass.h"
+#include "BsBlendState.h"
+#include "BsRasterizerState.h"
+#include "BsDepthStencilState.h"
+#include "BsSamplerState.h"
+#include "BsCoreApplication.h"
+#include "BsViewport.h"
+#include "BsRenderTarget.h"
+#include "BsRenderQueue.h"
+#include "BsCoreThread.h"
+#include "BsGpuParams.h"
+#include "BsProfilerCPU.h"
+#include "BsShader.h"
+#include "BsGpuParamBlockBuffer.h"
+#include "BsStaticRenderableHandler.h"
+#include "BsTime.h"
+#include "BsRenderableElement.h"
+#include "BsCoreObjectManager.h"
+#include "BsRenderBeastOptions.h"
+#include "BsSamplerOverrides.h"
+#include "BsLight.h"
+#include "BsRenderTexturePool.h"
+#include "BsRenderTargets.h"
+#include "BsRendererUtility.h"
+#include "BsRenderStateManager.h"
+
+using namespace std::placeholders;
+
+namespace BansheeEngine
+{
+	RenderBeast::RenderBeast()
+		:mOptions(bs_shared_ptr_new<RenderBeastOptions>()), mOptionsDirty(true), mStaticHandler(nullptr),
+		mDefaultMaterial(nullptr), mPointLightInMat(nullptr), mPointLightOutMat(nullptr), mDirLightMat(nullptr)
+	{
+
+	}
+
+	const StringID& RenderBeast::getName() const
+	{
+		static StringID name = "RenderBeast";
+		return name;
+	}
+
+	void RenderBeast::initialize()
+	{
+		CoreRenderer::initialize();
+
+		CoreThread::instance().queueCommand(std::bind(&RenderBeast::initializeCore, this));
+	}
+
+	void RenderBeast::destroy()
+	{
+		CoreRenderer::destroy();
+
+		gCoreAccessor().queueCommand(std::bind(&RenderBeast::destroyCore, this));
+		gCoreAccessor().submitToCoreThread(true);
+	}
+
+	void RenderBeast::initializeCore()
+	{
+		RendererUtility::startUp();
+
+		mCoreOptions = bs_shared_ptr_new<RenderBeastOptions>();
+		mStaticHandler = bs_new<StaticRenderableHandler>();
+
+		mDefaultMaterial = bs_new<DefaultMaterial>();
+		mPointLightInMat = bs_new<PointLightInMat>();
+		mPointLightOutMat = bs_new<PointLightOutMat>();
+		mDirLightMat = bs_new<DirectionalLightMat>();
+
+		RenderTexturePool::startUp();
+	}
+
+	void RenderBeast::destroyCore()
+	{
+		if (mStaticHandler != nullptr)
+			bs_delete(mStaticHandler);
+
+		mRenderTargets.clear();
+		mCameraData.clear();
+		mRenderables.clear();
+
+		RenderTexturePool::shutDown();
+
+		bs_delete(mDefaultMaterial);
+		bs_delete(mPointLightInMat);
+		bs_delete(mPointLightOutMat);
+		bs_delete(mDirLightMat);
+
+		RendererUtility::shutDown();
+
+		assert(mSamplerOverrides.empty());
+	}
+
+	void RenderBeast::_notifyRenderableAdded(RenderableCore* renderable)
+	{
+		UINT32 renderableId = (UINT32)mRenderables.size();
+
+		renderable->setRendererId(renderableId);
+
+		mRenderables.push_back(RenderableData());
+		mRenderableShaderData.push_back(RenderableShaderData());
+		mWorldBounds.push_back(renderable->getBounds());
+
+		RenderableData& renderableData = mRenderables.back();
+		renderableData.renderable = renderable;
+
+		RenderableShaderData& shaderData = mRenderableShaderData.back();
+		shaderData.worldTransform = renderable->getTransform();
+		shaderData.invWorldTransform = shaderData.worldTransform.inverseAffine();
+		shaderData.worldNoScaleTransform = renderable->getTransformNoScale();
+		shaderData.invWorldNoScaleTransform = shaderData.worldNoScaleTransform.inverseAffine();
+		shaderData.worldDeterminantSign = shaderData.worldTransform.determinant3x3() >= 0.0f ? 1.0f : -1.0f;
+
+		if (renderable->getRenderableType() == RenType_LitTextured)
+			renderableData.controller = mStaticHandler;
+		else
+			renderableData.controller = nullptr;
+
+		SPtr<MeshCore> mesh = renderable->getMesh();
+		if (mesh != nullptr)
+		{
+			const MeshProperties& meshProps = mesh->getProperties();
+			SPtr<VertexDeclarationCore> vertexDecl = mesh->getVertexData()->vertexDeclaration;
+
+			for (UINT32 i = 0; i < meshProps.getNumSubMeshes(); i++)
+			{
+				renderableData.elements.push_back(BeastRenderableElement());
+				BeastRenderableElement& renElement = renderableData.elements.back();
+
+				renElement.mesh = mesh;
+				renElement.subMesh = meshProps.getSubMesh(i);
+				renElement.renderableId = renderableId;
+
+				renElement.material = renderable->getMaterial(i);
+				if (renElement.material == nullptr)
+					renElement.material = renderable->getMaterial(0);
+
+				if (renElement.material != nullptr && renElement.material->getShader() == nullptr)
+					renElement.material = nullptr;
+
+				// Validate mesh <-> shader vertex bindings
+				if (renElement.material != nullptr)
+				{
+					UINT32 numPasses = renElement.material->getNumPasses();
+					for (UINT32 j = 0; j < numPasses; j++)
+					{
+						SPtr<PassCore> pass = renElement.material->getPass(j);
+
+						SPtr<VertexDeclarationCore> shaderDecl = pass->getVertexProgram()->getInputDeclaration();
+						if (!vertexDecl->isCompatible(shaderDecl))
+						{
+							Vector<VertexElement> missingElements = vertexDecl->getMissingElements(shaderDecl);
+
+							StringStream wrnStream;
+							wrnStream << "Provided mesh is missing required vertex attributes to render with the provided shader. Missing elements: " << std::endl;
+
+							for (auto& entry : missingElements)
+								wrnStream << "\t" << toString(entry.getSemantic()) << entry.getSemanticIdx() << std::endl;
+
+							LOGWRN(wrnStream.str());
+							break;
+						}
+					}
+				}
+
+				// If no material use the default material
+				if (renElement.material == nullptr)
+					renElement.material = mDefaultMaterial->getMaterial();
+
+				auto iterFind = mSamplerOverrides.find(renElement.material);
+				if (iterFind != mSamplerOverrides.end())
+				{
+					renElement.samplerOverrides = iterFind->second;
+					iterFind->second->refCount++;
+				}
+				else
+				{
+					MaterialSamplerOverrides* samplerOverrides = SamplerOverrideUtility::generateSamplerOverrides(renElement.material, mCoreOptions);
+					mSamplerOverrides[renElement.material] = samplerOverrides;
+
+					renElement.samplerOverrides = samplerOverrides;
+					samplerOverrides->refCount++;
+				}
+
+				if (renderableData.controller != nullptr)
+					renderableData.controller->initializeRenderElem(renElement);
+			}
+		}
+	}
+
+	void RenderBeast::_notifyRenderableRemoved(RenderableCore* renderable)
+	{
+		UINT32 renderableId = renderable->getRendererId();
+		RenderableCore* lastRenerable = mRenderables.back().renderable;
+		UINT32 lastRenderableId = lastRenerable->getRendererId();
+
+		Vector<BeastRenderableElement>& elements = mRenderables[renderableId].elements;
+		for (auto& element : elements)
+		{
+			auto iterFind = mSamplerOverrides.find(element.material);
+			assert(iterFind != mSamplerOverrides.end());
+
+			MaterialSamplerOverrides* samplerOverrides = iterFind->second;
+			samplerOverrides->refCount--;
+			if (samplerOverrides->refCount == 0)
+			{
+				SamplerOverrideUtility::destroySamplerOverrides(samplerOverrides);
+				mSamplerOverrides.erase(iterFind);
+			}
+
+			element.samplerOverrides = nullptr;
+		}
+
+		if (renderableId != lastRenderableId)
+		{
+			// Swap current last element with the one we want to erase
+			std::swap(mRenderables[renderableId], mRenderables[lastRenderableId]);
+			std::swap(mWorldBounds[renderableId], mWorldBounds[lastRenderableId]);
+			std::swap(mRenderableShaderData[renderableId], mRenderableShaderData[lastRenderableId]);
+
+			lastRenerable->setRendererId(renderableId);
+
+			Vector<BeastRenderableElement>& lastRenderableElements = mRenderables[renderableId].elements;
+			for (auto& element : elements)
+				element.renderableId = renderableId;
+		}
+
+		// Last element is the one we want to erase
+		mRenderables.erase(mRenderables.end() - 1);
+		mWorldBounds.erase(mWorldBounds.end() - 1);
+		mRenderableShaderData.erase(mRenderableShaderData.end() - 1);
+	}
+
+	void RenderBeast::_notifyRenderableUpdated(RenderableCore* renderable)
+	{
+		UINT32 renderableId = renderable->getRendererId();
+
+		RenderableShaderData& shaderData = mRenderableShaderData[renderableId];
+		shaderData.worldTransform = renderable->getTransform();
+		shaderData.invWorldTransform = shaderData.worldTransform.inverseAffine();
+		shaderData.worldNoScaleTransform = renderable->getTransformNoScale();
+		shaderData.invWorldNoScaleTransform = shaderData.worldNoScaleTransform.inverseAffine();
+		shaderData.worldDeterminantSign = shaderData.worldTransform.determinant3x3() >= 0.0f ? 1.0f : -1.0f;
+
+		mWorldBounds[renderableId] = renderable->getBounds();
+	}
+
+	void RenderBeast::_notifyLightAdded(LightCore* light)
+	{
+		if (light->getType() == LightType::Directional)
+		{
+			UINT32 lightId = (UINT32)mDirectionalLights.size();
+			light->setRendererId(lightId);
+
+			mDirectionalLights.push_back(LightData());
+
+			LightData& lightData = mDirectionalLights.back();
+			lightData.internal = light;
+		}
+		else
+		{
+			UINT32 lightId = (UINT32)mPointLights.size();
+
+			light->setRendererId(lightId);
+
+			mPointLights.push_back(LightData());
+			mLightWorldBounds.push_back(light->getBounds());
+
+			LightData& lightData = mPointLights.back();
+			lightData.internal = light;
+		}
+	}
+
+	void RenderBeast::_notifyLightUpdated(LightCore* light)
+	{
+		UINT32 lightId = light->getRendererId();
+
+		if (light->getType() != LightType::Directional)
+			mLightWorldBounds[lightId] = light->getBounds();
+	}
+
+	void RenderBeast::_notifyLightRemoved(LightCore* light)
+	{
+		UINT32 lightId = light->getRendererId();
+		if (light->getType() == LightType::Directional)
+		{
+			LightCore* lastLight = mDirectionalLights.back().internal;
+			UINT32 lastLightId = lastLight->getRendererId();
+
+			if (lightId != lastLightId)
+			{
+				// Swap current last element with the one we want to erase
+				std::swap(mDirectionalLights[lightId], mDirectionalLights[lastLightId]);
+				lastLight->setRendererId(lightId);
+			}
+
+			// Last element is the one we want to erase
+			mDirectionalLights.erase(mDirectionalLights.end() - 1);
+		}
+		else
+		{
+			LightCore* lastLight = mPointLights.back().internal;
+			UINT32 lastLightId = lastLight->getRendererId();
+
+			if (lightId != lastLightId)
+			{
+				// Swap current last element with the one we want to erase
+				std::swap(mPointLights[lightId], mPointLights[lastLightId]);
+				std::swap(mLightWorldBounds[lightId], mLightWorldBounds[lastLightId]);
+
+				lastLight->setRendererId(lightId);
+			}
+
+			// Last element is the one we want to erase
+			mPointLights.erase(mPointLights.end() - 1);
+			mLightWorldBounds.erase(mLightWorldBounds.end() - 1);
+		}
+	}
+
+	void RenderBeast::_notifyCameraAdded(const CameraCore* camera)
+	{
+		SPtr<RenderTargetCore> renderTarget = camera->getViewport()->getTarget();
+		if (renderTarget == nullptr)
+			return;
+
+		CameraData& camData = mCameraData[camera];
+		camData.opaqueQueue = bs_shared_ptr_new<RenderQueue>(mCoreOptions->stateReductionMode);
+
+		StateReduction transparentStateReduction = mCoreOptions->stateReductionMode;
+		if (transparentStateReduction == StateReduction::Material)
+			transparentStateReduction = StateReduction::Distance; // Transparent object MUST be sorted by distance
+
+		camData.transparentQueue = bs_shared_ptr_new<RenderQueue>(transparentStateReduction);
+
+		// Register in render target list
+		auto findIter = std::find_if(mRenderTargets.begin(), mRenderTargets.end(), 
+			[&](const RenderTargetData& x) { return x.target == renderTarget; });
+
+		if (findIter != mRenderTargets.end())
+		{
+			findIter->cameras.push_back(camera);
+		}
+		else
+		{
+			mRenderTargets.push_back(RenderTargetData());
+			RenderTargetData& renderTargetData = mRenderTargets.back();
+
+			renderTargetData.target = renderTarget;
+			renderTargetData.cameras.push_back(camera);
+		}
+
+		// Sort render targets based on priority
+		auto cameraComparer = [&](const CameraCore* a, const CameraCore* b) { return a->getPriority() > b->getPriority(); };
+		auto renderTargetInfoComparer = [&](const RenderTargetData& a, const RenderTargetData& b)
+		{ return a.target->getProperties().getPriority() > b.target->getProperties().getPriority(); };
+		std::sort(begin(mRenderTargets), end(mRenderTargets), renderTargetInfoComparer);
+
+		for (auto& camerasPerTarget : mRenderTargets)
+		{
+			Vector<const CameraCore*>& cameras = camerasPerTarget.cameras;
+
+			std::sort(begin(cameras), end(cameras), cameraComparer);
+		}
+	}
+
+	void RenderBeast::_notifyCameraRemoved(const CameraCore* camera)
+	{
+		mCameraData.erase(camera);
+
+		// Remove from render target list
+		for (auto iterTarget = mRenderTargets.begin(); iterTarget != mRenderTargets.end(); ++iterTarget)
+		{
+			RenderTargetData& target = *iterTarget;
+			for (auto iterCam = target.cameras.begin(); iterCam != target.cameras.end(); ++iterCam)
+			{
+				if (camera == *iterCam)
+				{
+					target.cameras.erase(iterCam);
+					break;
+				}
+			}
+
+			if (target.cameras.empty())
+			{
+				mRenderTargets.erase(iterTarget);
+				break;
+			}
+		}
+	}
+
+	void RenderBeast::setOptions(const SPtr<CoreRendererOptions>& options)
+	{
+		mOptions = std::static_pointer_cast<RenderBeastOptions>(options);
+		mOptionsDirty = true;
+	}
+
+	SPtr<CoreRendererOptions> RenderBeast::getOptions() const
+	{
+		return mOptions;
+	}
+
+	void RenderBeast::renderAll() 
+	{
+		// Sync all dirty sim thread CoreObject data to core thread
+		CoreObjectManager::instance().syncToCore(gCoreAccessor());
+
+		if (mOptionsDirty)
+		{
+			gCoreAccessor().queueCommand(std::bind(&RenderBeast::syncRenderOptions, this, *mOptions));
+			mOptionsDirty = false;
+		}
+
+		gCoreAccessor().queueCommand(std::bind(&RenderBeast::renderAllCore, this, gTime().getTime()));
+	}
+
+	void RenderBeast::syncRenderOptions(const RenderBeastOptions& options)
+	{
+		bool filteringChanged = mCoreOptions->filtering != options.filtering;
+		if (options.filtering == RenderBeastFiltering::Anisotropic)
+			filteringChanged |= mCoreOptions->anisotropyMax != options.anisotropyMax;
+
+		if (filteringChanged)
+			refreshSamplerOverrides(true);
+
+		*mCoreOptions = options;
+
+		for (auto& cameraData : mCameraData)
+		{
+			cameraData.second.opaqueQueue->setStateReduction(mCoreOptions->stateReductionMode);
+
+			StateReduction transparentStateReduction = mCoreOptions->stateReductionMode;
+			if (transparentStateReduction == StateReduction::Material)
+				transparentStateReduction = StateReduction::Distance; // Transparent object MUST be sorted by distance
+
+			cameraData.second.transparentQueue->setStateReduction(transparentStateReduction);
+		}
+	}
+
+	void RenderBeast::renderAllCore(float time)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		gProfilerCPU().beginSample("renderAllCore");
+
+		// Note: I'm iterating over all sampler states every frame. If this ends up being a performance
+		// issue consider handling this internally in MaterialCore which can only do it when sampler states
+		// are actually modified after sync
+		refreshSamplerOverrides();
+
+		// Update global per-frame hardware buffers
+		mStaticHandler->updatePerFrameBuffers(time);
+
+		// Generate render queues per camera
+		for (auto& cameraData : mCameraData)
+		{
+			const CameraCore* camera = cameraData.first;
+			determineVisible(*camera);
+		}
+
+		// Render everything, target by target
+		for (auto& renderTargetData : mRenderTargets)
+		{
+			SPtr<RenderTargetCore> target = renderTargetData.target;
+			Vector<const CameraCore*>& cameras = renderTargetData.cameras;
+
+			RenderAPICore::instance().beginFrame();
+
+			UINT32 numCameras = (UINT32)cameras.size();
+			for (UINT32 i = 0; i < numCameras; i++)
+				render(renderTargetData, i);
+
+			RenderAPICore::instance().endFrame();
+			RenderAPICore::instance().swapBuffers(target);
+		}
+
+		gProfilerCPU().endSample("renderAllCore");
+	}
+
+	void RenderBeast::render(RenderTargetData& rtData, UINT32 camIdx)
+	{
+		gProfilerCPU().beginSample("Render");
+
+		const CameraCore* camera = rtData.cameras[camIdx];
+		CameraData& camData = mCameraData[camera];
+
+		SPtr<ViewportCore> viewport = camera->getViewport();
+		CameraShaderData cameraShaderData = getCameraShaderData(*camera);
+
+		mStaticHandler->updatePerCameraBuffers(cameraShaderData);
+
+		// Render scene objects to g-buffer
+		bool hasGBuffer = ((UINT32)camera->getFlags() & (UINT32)CameraFlags::Overlay) == 0;
+
+		if (hasGBuffer)
+		{
+			bool createGBuffer = camData.target == nullptr ||
+				camData.target->getHDR() != mCoreOptions->hdr ||
+				camData.target->getNumSamples() != mCoreOptions->msaa;
+
+			if (createGBuffer)
+				camData.target = RenderTargets::create(viewport, mCoreOptions->hdr, mCoreOptions->msaa);
+
+			camData.target->allocate();
+			camData.target->bindGBuffer();
+		}
+		else
+			camData.target = nullptr;
+
+		// Trigger pre-scene callbacks
+		auto iterCameraCallbacks = mRenderCallbacks.find(camera);
+		if (iterCameraCallbacks != mRenderCallbacks.end())
+		{
+			for (auto& callbackPair : iterCameraCallbacks->second)
+			{
+				const RenderCallbackData& callbackData = callbackPair.second;
+
+				if (callbackData.overlay)
+					continue;
+
+				if (callbackPair.first >= 0)
+					break;
+
+				callbackData.callback();
+			}
+		}
+		
+		if (hasGBuffer)
+		{
+			// Render base pass
+			const Vector<RenderQueueElement>& opaqueElements = camData.opaqueQueue->getSortedElements();
+			for (auto iter = opaqueElements.begin(); iter != opaqueElements.end(); ++iter)
+			{
+				BeastRenderableElement* renderElem = static_cast<BeastRenderableElement*>(iter->renderElem);
+				SPtr<MaterialCore> material = renderElem->material;
+
+				UINT32 rendererId = renderElem->renderableId;
+				Matrix4 worldViewProjMatrix = cameraShaderData.viewProj * mRenderableShaderData[rendererId].worldTransform;
+
+				mStaticHandler->updatePerObjectBuffers(*renderElem, mRenderableShaderData[rendererId], worldViewProjMatrix);
+				mStaticHandler->bindGlobalBuffers(*renderElem); // Note: If I can keep global buffer slot indexes the same between shaders I could only bind these once
+				mStaticHandler->bindPerObjectBuffers(*renderElem);
+
+				if (iter->applyPass)
+				{
+					SPtr<PassCore> pass = material->getPass(iter->passIdx);
+					setPass(pass);
+				}
+
+				SPtr<PassParametersCore> passParams = material->getPassParameters(iter->passIdx);
+
+				if (renderElem->samplerOverrides != nullptr)
+					setPassParams(passParams, &renderElem->samplerOverrides->passes[iter->passIdx]);
+				else
+					setPassParams(passParams, nullptr);
+
+				gRendererUtility().draw(iter->renderElem->mesh, iter->renderElem->subMesh);
+			}
+
+			camData.target->bindSceneColor(true);
+
+			// Render light pass
+			SPtr<GpuParamBlockBufferCore> perCameraBuffer = mStaticHandler->getPerCameraParams().getBuffer();
+
+			SPtr<MaterialCore> dirMaterial = mDirLightMat->getMaterial();
+			SPtr<PassCore> dirPass = dirMaterial->getPass(0);
+
+			setPass(dirPass);
+			mDirLightMat->setStaticParameters(camData.target, perCameraBuffer);
+
+			for (auto& light : mDirectionalLights)
+			{
+				if (!light.internal->getIsActive())
+					continue;
+
+				mDirLightMat->setParameters(light.internal);
+
+				// TODO - Bind parameters to the pipeline manually as I don't need to re-bind gbuffer textures for every light
+				//  - I can't think of a good way to do this automatically. Probably best to do it in setParameters()
+				setPassParams(dirMaterial->getPassParameters(0), nullptr);
+				gRendererUtility().drawScreenQuad();
+			}
+
+			// Draw point lights which our camera is within
+			SPtr<MaterialCore> pointInsideMaterial = mPointLightInMat->getMaterial();
+			SPtr<PassCore> pointInsidePass = pointInsideMaterial->getPass(0);
+
+			// TODO - Possibly use instanced drawing here as only two meshes are drawn with various properties
+			setPass(pointInsidePass);
+			mPointLightInMat->setStaticParameters(camData.target, perCameraBuffer);
+
+			// TODO - Cull lights based on visibility, right now I just iterate over all of them. 
+			for (auto& light : mPointLights)
+			{
+				if (!light.internal->getIsActive())
+					continue;
+
+				float distToLight = (light.internal->getBounds().getCenter() - camera->getPosition()).squaredLength();
+				float boundRadius = light.internal->getBounds().getRadius() * 1.05f + camera->getNearClipDistance() * 2.0f;
+
+				bool cameraInLightGeometry = distToLight < boundRadius * boundRadius;
+				if (!cameraInLightGeometry)
+					continue;
+
+				mPointLightInMat->setParameters(light.internal);
+
+				// TODO - Bind parameters to the pipeline manually as I don't need to re-bind gbuffer textures for every light
+				//  - I can't think of a good way to do this automatically. Probably best to do it in setParameters()
+				setPassParams(pointInsideMaterial->getPassParameters(0), nullptr);
+				SPtr<MeshCore> mesh = light.internal->getMesh();
+				gRendererUtility().draw(mesh, mesh->getProperties().getSubMesh(0));
+			}
+
+			// Draw other point lights
+			SPtr<MaterialCore> pointOutsideMaterial = mPointLightOutMat->getMaterial();
+			SPtr<PassCore> pointOutsidePass = pointOutsideMaterial->getPass(0);
+
+			setPass(pointOutsidePass);
+			mPointLightOutMat->setStaticParameters(camData.target, perCameraBuffer);
+
+			for (auto& light : mPointLights)
+			{
+				if (!light.internal->getIsActive())
+					continue;
+
+				float distToLight = (light.internal->getBounds().getCenter() - camera->getPosition()).squaredLength();
+				float boundRadius = light.internal->getBounds().getRadius() * 1.05f + camera->getNearClipDistance() * 2.0f;
+
+				bool cameraInLightGeometry = distToLight < boundRadius * boundRadius;
+				if (cameraInLightGeometry)
+					continue;
+
+				mPointLightOutMat->setParameters(light.internal);
+
+				// TODO - Bind parameters to the pipeline manually as I don't need to re-bind gbuffer textures for every light
+				setPassParams(pointOutsideMaterial->getPassParameters(0), nullptr);
+				SPtr<MeshCore> mesh = light.internal->getMesh();
+				gRendererUtility().draw(mesh, mesh->getProperties().getSubMesh(0));
+			}
+
+			camData.target->bindSceneColor(false);
+		}
+		else
+		{
+			// Prepare final render target
+			SPtr<RenderTargetCore> target = rtData.target;
+
+			RenderAPICore::instance().setRenderTarget(target);
+			RenderAPICore::instance().setViewport(viewport->getNormArea());
+
+			// If first camera in render target, prepare the render target
+			if (camIdx == 0)
+			{
+				UINT32 clearBuffers = 0;
+				if (viewport->getRequiresColorClear())
+					clearBuffers |= FBT_COLOR;
+
+				if (viewport->getRequiresDepthClear())
+					clearBuffers |= FBT_DEPTH;
+
+				if (viewport->getRequiresStencilClear())
+					clearBuffers |= FBT_STENCIL;
+
+				if (clearBuffers != 0)
+				{
+					RenderAPICore::instance().clearViewport(clearBuffers, viewport->getClearColor(),
+						viewport->getClearDepthValue(), viewport->getClearStencilValue());
+				}
+			}
+		}
+
+		// Render transparent objects (TODO - No lighting yet)
+		const Vector<RenderQueueElement>& transparentElements = camData.transparentQueue->getSortedElements();
+		for (auto iter = transparentElements.begin(); iter != transparentElements.end(); ++iter)
+		{
+			BeastRenderableElement* renderElem = static_cast<BeastRenderableElement*>(iter->renderElem);
+			SPtr<MaterialCore> material = renderElem->material;
+
+			UINT32 rendererId = renderElem->renderableId;
+			Matrix4 worldViewProjMatrix = cameraShaderData.viewProj * mRenderableShaderData[rendererId].worldTransform;
+
+			mStaticHandler->updatePerObjectBuffers(*renderElem, mRenderableShaderData[rendererId], worldViewProjMatrix);
+			mStaticHandler->bindGlobalBuffers(*renderElem); // Note: If I can keep global buffer slot indexes the same between shaders I could only bind these once
+			mStaticHandler->bindPerObjectBuffers(*renderElem);
+
+			if (iter->applyPass)
+			{
+				SPtr<PassCore> pass = material->getPass(iter->passIdx);
+				setPass(pass);
+			}
+
+			SPtr<PassParametersCore> passParams = material->getPassParameters(iter->passIdx);
+
+			if (renderElem->samplerOverrides != nullptr)
+				setPassParams(passParams, &renderElem->samplerOverrides->passes[iter->passIdx]);
+			else
+				setPassParams(passParams, nullptr);
+
+			gRendererUtility().draw(iter->renderElem->mesh, iter->renderElem->subMesh);
+		}
+
+		camData.opaqueQueue->clear();
+		camData.transparentQueue->clear();
+
+		// Render non-overlay post-scene callbacks
+		if (iterCameraCallbacks != mRenderCallbacks.end())
+		{
+			for (auto& callbackPair : iterCameraCallbacks->second)
+			{
+				const RenderCallbackData& callbackData = callbackPair.second;
+
+				if (callbackData.overlay || callbackPair.first < 0)
+					continue;
+
+				callbackData.callback();
+			}
+		}
+
+		if (hasGBuffer)
+		{
+			// TODO - Instead of doing a separate resolve here I could potentially perform a resolve directly in some
+			// post-processing pass (e.g. tone mapping). Right now it is just an unnecessary blit.
+			camData.target->resolve();
+		}
+
+		// Render overlay post-scene callbacks
+		if (iterCameraCallbacks != mRenderCallbacks.end())
+		{
+			for (auto& callbackPair : iterCameraCallbacks->second)
+			{
+				const RenderCallbackData& callbackData = callbackPair.second;
+
+				if (!callbackData.overlay)
+					continue;
+
+				callbackData.callback();
+			}
+		}
+
+		if (hasGBuffer)
+			camData.target->release();
+
+		gProfilerCPU().endSample("Render");
+	}
+	
+	void RenderBeast::determineVisible(const CameraCore& camera)
+	{
+		CameraData& cameraData = mCameraData[&camera];
+
+		UINT64 cameraLayers = camera.getLayers();
+		ConvexVolume worldFrustum = camera.getWorldFrustum();
+
+		// Update per-object param buffers and queue render elements
+		for (auto& renderableData : mRenderables)
+		{
+			RenderableCore* renderable = renderableData.renderable;
+			RenderableHandler* controller = renderableData.controller;
+			UINT32 renderableType = renderable->getRenderableType();
+			UINT32 rendererId = renderable->getRendererId();
+
+			if ((renderable->getLayer() & cameraLayers) == 0)
+				continue;
+
+			// Do frustum culling
+			// TODO - This is bound to be a bottleneck at some point. When it is ensure that intersect
+			// methods use vector operations, as it is trivial to update them.
+			const Sphere& boundingSphere = mWorldBounds[rendererId].getSphere();
+			if (worldFrustum.intersects(boundingSphere))
+			{
+				// More precise with the box
+				const AABox& boundingBox = mWorldBounds[rendererId].getBox();
+
+				if (worldFrustum.intersects(boundingBox))
+				{
+					float distanceToCamera = (camera.getPosition() - boundingBox.getCenter()).length();
+
+					for (auto& renderElem : renderableData.elements)
+					{
+						bool isTransparent = (renderElem.material->getShader()->getFlags() & (UINT32)ShaderFlags::Transparent) != 0;
+
+						if (isTransparent)
+							cameraData.transparentQueue->add(&renderElem, distanceToCamera);
+						else
+							cameraData.opaqueQueue->add(&renderElem, distanceToCamera);
+					}
+
+				}
+			}
+		}
+
+		cameraData.opaqueQueue->sort();
+		cameraData.transparentQueue->sort();
+	}
+
+	Vector2 RenderBeast::getDeviceZTransform(const Matrix4& projMatrix)
+	{
+		// Returns a set of values that will transform depth buffer values (e.g. [0, 1] in DX, [-1, 1] in GL) to a distance
+		// in world space. This involes applying the inverse projection transform to the depth value. When you multiply
+		// a vector with the projection matrix you get [clipX, clipY, Az + B, C * z], where we don't care about clipX/clipY.
+		// A is [2, 2], B is [2, 3] and C is [3, 2] elements of the projection matrix (only ones that matter for our depth 
+		// value). The hardware will also automatically divide the z value with w to get the depth, therefore the final 
+		// formula is:
+		// depth = (Az + B) / (C * z)
+
+		// To get the z coordinate back we simply do the opposite: 
+		// z = B / (depth * C - A)
+
+		// However some APIs will also do a transformation on the depth values before storing them to the texture 
+		// (e.g. OpenGL will transform from [-1, 1] to [0, 1]). And we need to reverse that as well. Therefore the final 
+		// formula is:
+		// z = B / ((depth * (maxDepth - minDepth) + minDepth) * C - A)
+
+		// Are we reorganize it because it needs to fit the "(1.0f / (depth + y)) * x" format used in the shader:
+		// z = 1.0f / (depth + minDepth/(maxDepth - minDepth) - A/((maxDepth - minDepth) * C)) * B/((maxDepth - minDepth) * C)
+
+		RenderAPICore& rapi = RenderAPICore::instance();
+		const RenderAPIInfo& rapiInfo = rapi.getAPIInfo();
+
+		float depthRange = rapiInfo.getMaximumDepthInputValue() - rapiInfo.getMinimumDepthInputValue();
+		float minDepth = rapiInfo.getMinimumDepthInputValue();
+
+		float a = projMatrix[2][2];
+		float b = projMatrix[2][3];
+		float c = projMatrix[3][2];
+
+		Vector2 output;
+		output.x = b / (depthRange * c);
+		output.y = minDepth / depthRange - a / (depthRange * c);
+
+		return output;
+	}
+
+	CameraShaderData RenderBeast::getCameraShaderData(const CameraCore& camera)
+	{
+		CameraShaderData data;
+		data.proj = camera.getProjectionMatrixRS();
+		data.view = camera.getViewMatrix();
+		data.viewProj = data.proj * data.view;
+		data.invProj = data.proj.inverse();
+		data.invViewProj = data.viewProj.inverse(); // Note: Calculate inverses separately (better precision possibly)
+
+		// Construct a special inverse view-projection matrix that had projection entries that affect z and w eliminated.
+		// Used to transform a vector(clip_x, clip_y, view_z, view_w), where clip_x/clip_y are in clip space, and 
+		// view_z/view_w in view space, into world space.
+
+		// Only projects z/w coordinates
+		Matrix4 projZ = Matrix4::IDENTITY;
+		projZ[2][2] = data.proj[2][2];
+		projZ[2][3] = data.proj[2][3];
+		projZ[3][2] = data.proj[3][2];
+		projZ[3][3] = 0.0f;
+
+		data.screenToWorld = data.invViewProj * projZ;
+		data.viewDir = camera.getForward();
+		data.viewOrigin = camera.getPosition();
+		data.deviceZToWorldZ = getDeviceZTransform(data.proj);
+
+		SPtr<ViewportCore> viewport = camera.getViewport();
+		SPtr<RenderTargetCore> rt = viewport->getTarget();
+
+		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();
+		const RenderAPIInfo& rapiInfo = rapi.getAPIInfo();
+
+		data.clipToUVScaleOffset.x = halfWidth / rtWidth;
+		data.clipToUVScaleOffset.y = -halfHeight / rtHeight;
+		data.clipToUVScaleOffset.z = viewport->getX() / rtWidth + (halfWidth + rapiInfo.getHorizontalTexelOffset()) / rtWidth;
+		data.clipToUVScaleOffset.w = viewport->getY() / rtHeight + (halfHeight + rapiInfo.getVerticalTexelOffset()) / rtHeight;
+
+		if (!rapiInfo.getNDCYAxisDown())
+			data.clipToUVScaleOffset.y = -data.clipToUVScaleOffset.y;
+
+		return data;
+	}
+
+	void RenderBeast::refreshSamplerOverrides(bool force)
+	{
+		for (auto& entry : mSamplerOverrides)
+		{
+			SPtr<MaterialCore> material = entry.first;
+
+			if (force)
+			{
+				SamplerOverrideUtility::destroySamplerOverrides(entry.second);
+				entry.second = SamplerOverrideUtility::generateSamplerOverrides(material, mCoreOptions);
+			}
+			else
+			{
+				MaterialSamplerOverrides* materialOverrides = entry.second;
+				UINT32 numPasses = material->getNumPasses();
+
+				assert(numPasses == materialOverrides->numPasses);
+				for (UINT32 i = 0; i < numPasses; i++)
+				{
+					SPtr<PassParametersCore> passParams = material->getPassParameters(i);
+					PassSamplerOverrides& passOverrides = materialOverrides->passes[i];
+
+					for (UINT32 j = 0; j < PassParametersCore::NUM_PARAMS; j++)
+					{
+						StageSamplerOverrides& stageOverrides = passOverrides.stages[j];
+
+						SPtr<GpuParamsCore> params = passParams->getParamByIdx(j);
+						if (params == nullptr)
+							continue;
+
+						const GpuParamDesc& paramDesc = params->getParamDesc();
+
+						for (auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
+						{
+							UINT32 slot = iter->second.slot;
+							SPtr<SamplerStateCore> samplerState = params->getSamplerState(slot);
+
+							assert(stageOverrides.numStates > slot);
+
+							if (samplerState != stageOverrides.stateOverrides[slot])
+							{
+								if (samplerState != nullptr)
+									stageOverrides.stateOverrides[slot] = SamplerOverrideUtility::generateSamplerOverride(samplerState, mCoreOptions);
+								else
+									stageOverrides.stateOverrides[slot] = SamplerOverrideUtility::generateSamplerOverride(SamplerStateCore::getDefault(), mCoreOptions);;
+							}	
+						}
+					}
+				}
+			}
+		}
+	}
+
+	void RenderBeast::setPass(const SPtr<PassCore>& pass)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		RenderAPICore& rs = RenderAPICore::instance();
+
+		struct StageData
+		{
+			GpuProgramType type;
+			bool enable;
+			SPtr<GpuProgramCore> program;
+		};
+
+		const UINT32 numStages = 6;
+		StageData stages[numStages] =
+		{
+			{ GPT_VERTEX_PROGRAM, pass->hasVertexProgram(), pass->getVertexProgram() },
+			{ GPT_FRAGMENT_PROGRAM, pass->hasFragmentProgram(), pass->getFragmentProgram() },
+			{ GPT_GEOMETRY_PROGRAM, pass->hasGeometryProgram(), pass->getGeometryProgram() },
+			{ GPT_HULL_PROGRAM, pass->hasHullProgram(), pass->getHullProgram() },
+			{ GPT_DOMAIN_PROGRAM, pass->hasDomainProgram(), pass->getDomainProgram() },
+			{ GPT_COMPUTE_PROGRAM, pass->hasComputeProgram(), pass->getComputeProgram() }
+		};
+
+		for (UINT32 i = 0; i < numStages; i++)
+		{
+			const StageData& stage = stages[i];
+
+			if (stage.enable)
+				rs.bindGpuProgram(stage.program);
+			else
+				rs.unbindGpuProgram(stage.type);
+		}
+
+		// Set up non-texture related pass settings
+		if (pass->getBlendState() != nullptr)
+			rs.setBlendState(pass->getBlendState());
+		else
+			rs.setBlendState(BlendStateCore::getDefault());
+
+		if (pass->getDepthStencilState() != nullptr)
+			rs.setDepthStencilState(pass->getDepthStencilState(), pass->getStencilRefValue());
+		else
+			rs.setDepthStencilState(DepthStencilStateCore::getDefault(), pass->getStencilRefValue());
+
+		if (pass->getRasterizerState() != nullptr)
+			rs.setRasterizerState(pass->getRasterizerState());
+		else
+			rs.setRasterizerState(RasterizerStateCore::getDefault());
+	}
+
+	void RenderBeast::setPassParams(const SPtr<PassParametersCore>& passParams, const PassSamplerOverrides* samplerOverrides)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		RenderAPICore& rs = RenderAPICore::instance();
+
+		struct StageData
+		{
+			GpuProgramType type;
+			SPtr<GpuParamsCore> params;
+		};
+
+		const UINT32 numStages = 6;
+		StageData stages[numStages] =
+		{
+			{ GPT_VERTEX_PROGRAM, passParams->mVertParams },
+			{ GPT_FRAGMENT_PROGRAM, passParams->mFragParams },
+			{ GPT_GEOMETRY_PROGRAM, passParams->mGeomParams },
+			{ GPT_HULL_PROGRAM, passParams->mHullParams },
+			{ GPT_DOMAIN_PROGRAM, passParams->mDomainParams },
+			{ GPT_COMPUTE_PROGRAM, passParams->mComputeParams }
+		};
+
+		for (UINT32 i = 0; i < numStages; i++)
+		{
+			const StageData& stage = stages[i];
+
+			SPtr<GpuParamsCore> params = stage.params;
+			if (params == nullptr)
+				continue;
+
+			const GpuParamDesc& paramDesc = params->getParamDesc();
+
+			for (auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
+			{
+				SPtr<SamplerStateCore> samplerState;
+
+				if (samplerOverrides != nullptr)
+					samplerState = samplerOverrides->stages[i].stateOverrides[iter->second.slot];
+				else
+					samplerState = params->getSamplerState(iter->second.slot);
+
+				if (samplerState == nullptr)
+					rs.setSamplerState(stage.type, iter->second.slot, SamplerStateCore::getDefault());
+				else
+					rs.setSamplerState(stage.type, iter->second.slot, samplerState);
+			}
+
+			for (auto iter = paramDesc.textures.begin(); iter != paramDesc.textures.end(); ++iter)
+			{
+				SPtr<TextureCore> texture = params->getTexture(iter->second.slot);
+
+				if (!params->isLoadStoreTexture(iter->second.slot))
+				{
+					if (texture == nullptr)
+						rs.setTexture(stage.type, iter->second.slot, false, nullptr);
+					else
+						rs.setTexture(stage.type, iter->second.slot, true, texture);
+				}
+				else
+				{
+					const TextureSurface& surface = params->getLoadStoreSurface(iter->second.slot);
+
+					if (texture == nullptr)
+						rs.setLoadStoreTexture(stage.type, iter->second.slot, false, nullptr, surface);
+					else
+						rs.setLoadStoreTexture(stage.type, iter->second.slot, true, texture, surface);
+				}
+			}
+
+			rs.setConstantBuffers(stage.type, params);
+		}
+	}
 }