Parcourir la source

Added an separate object that encapsulates entire pipeline states to Render API, to more easily match up with Vulkan internals

BearishSun il y a 9 ans
Parent
commit
50b2daaa81

+ 28 - 16
Source/BansheeCore/CMakeSources.cmake

@@ -128,20 +128,14 @@ set(BS_BANSHEECORE_INC_RENDERAPI
 	"Include/BsTextureView.h"
 	"Include/BsSubMesh.h"
 	"Include/BsSamplerState.h"
-	"Include/BsRenderWindowManager.h"
 	"Include/BsRenderWindow.h"
 	"Include/BsRenderTexture.h"
 	"Include/BsRenderTarget.h"
-	"Include/BsRenderStateManager.h"
 	"Include/BsRasterizerState.h"
-	"Include/BsQueryManager.h"
 	"Include/BsOcclusionQuery.h"
 	"Include/BsMultiRenderTexture.h"
-	"Include/BsMeshManager.h"
 	"Include/BsIndexBuffer.h"
-	"Include/BsHardwareBufferManager.h"
 	"Include/BsHardwareBuffer.h"
-	"Include/BsGpuProgramManager.h"
 	"Include/BsGpuProgram.h"
 	"Include/BsGpuParams.h"
 	"Include/BsGpuParamDesc.h"
@@ -154,12 +148,22 @@ set(BS_BANSHEECORE_INC_RENDERAPI
 	"Include/BsDepthStencilState.h"
 	"Include/BsBlendState.h"
 	"Include/BsRenderAPI.h"
-	"Include/BsRenderAPIManager.h"
-	"Include/BsRenderAPIFactory.h"
 	"Include/BsRenderAPICapabilities.h"
 	"Include/BsViewport.h"
-	"Include/BsCommandBufferManager.h"
 	"Include/BsCommandBuffer.h"
+	"Include/BsGpuPipelineState.h"
+)
+
+set(BS_BANSHEECORE_INC_RENDERAPI_FACTORIES
+	"Include/BsRenderWindowManager.h"
+	"Include/BsRenderStateManager.h"
+	"Include/BsQueryManager.h"
+	"Include/BsMeshManager.h"
+	"Include/BsHardwareBufferManager.h"
+	"Include/BsGpuProgramManager.h"
+	"Include/BsRenderAPIManager.h"
+	"Include/BsRenderAPIFactory.h"
+	"Include/BsCommandBufferManager.h"
 )
 
 set(BS_BANSHEECORE_SRC_CORETHREAD
@@ -423,19 +427,13 @@ set(BS_BANSHEECORE_SRC_RENDERAPI
 	"Source/BsGpuParamBlockBuffer.cpp"
 	"Source/BsGpuParams.cpp"
 	"Source/BsGpuProgram.cpp"
-	"Source/BsGpuProgramManager.cpp"
-	"Source/BsHardwareBufferManager.cpp"
 	"Source/BsIndexBuffer.cpp"
-	"Source/BsMeshManager.cpp"
 	"Source/BsMultiRenderTexture.cpp"
 	"Source/BsOcclusionQuery.cpp"
-	"Source/BsQueryManager.cpp"
 	"Source/BsRasterizerState.cpp"
-	"Source/BsRenderStateManager.cpp"
 	"Source/BsRenderTarget.cpp"
 	"Source/BsRenderTexture.cpp"
 	"Source/BsRenderWindow.cpp"
-	"Source/BsRenderWindowManager.cpp"
 	"Source/BsSamplerState.cpp"
 	"Source/BsTextureView.cpp"
 	"Source/BsTimerQuery.cpp"
@@ -444,10 +442,20 @@ set(BS_BANSHEECORE_SRC_RENDERAPI
 	"Source/BsVertexDeclaration.cpp"
 	"Source/BsVideoModeInfo.cpp"
 	"Source/BsRenderAPI.cpp"
-	"Source/BsRenderAPIManager.cpp"
 	"Source/BsRenderAPICapabilities.cpp"
 	"Source/BsViewport.cpp"
 	"Source/BsCommandBuffer.cpp"
+	"Source/BsGpuPipelineState.cpp"
+)
+
+set(BS_BANSHEECORE_SRC_RENDERAPI_FACTORIES
+	"Source/BsGpuProgramManager.cpp"
+	"Source/BsHardwareBufferManager.cpp"
+	"Source/BsMeshManager.cpp"
+	"Source/BsQueryManager.cpp"
+	"Source/BsRenderStateManager.cpp"
+	"Source/BsRenderWindowManager.cpp"
+	"Source/BsRenderAPIManager.cpp"
 )
 
 set(BS_BANSHEECORE_SRC_NOFILTER
@@ -545,6 +553,7 @@ source_group("Source Files\\Localization" FILES ${BS_BANSHEECORE_SRC_LOCALIZATIO
 source_group("Source Files\\RTTI" FILES ${BS_BANSHEECORE_SRC_RTTI})
 source_group("Header Files\\Profiling" FILES ${BS_BANSHEECORE_INC_PROFILING})
 source_group("Header Files\\RenderAPI" FILES ${BS_BANSHEECORE_INC_RENDERAPI})
+source_group("Header Files\\RenderAPI\\Factories" FILES ${BS_BANSHEECORE_INC_RENDERAPI_FACTORIES})
 source_group("Source Files\\CoreThread" FILES ${BS_BANSHEECORE_SRC_CORETHREAD})
 source_group("Header Files" FILES ${BS_BANSHEECORE_INC_NOFILTER})
 source_group("Header Files\\Material" FILES ${BS_BANSHEECORE_INC_MATERIAL})
@@ -564,6 +573,7 @@ source_group("Source Files\\Input" FILES ${BS_BANSHEECORE_SRC_INPUT})
 source_group("Header Files\\Localization" FILES ${BS_BANSHEECORE_INC_LOCALIZATION})
 source_group("Source Files\\Text" FILES ${BS_BANSHEECORE_SRC_TEXT})
 source_group("Source Files\\RenderAPI" FILES ${BS_BANSHEECORE_SRC_RENDERAPI})
+source_group("Source Files\\RenderAPI\\Factories" FILES ${BS_BANSHEECORE_SRC_RENDERAPI_FACTORIES})
 source_group("Source Files" FILES ${BS_BANSHEECORE_SRC_NOFILTER})
 source_group("Source Files\\Physics" FILES ${BS_BANSHEECORE_SRC_PHYSICS})
 source_group("Source Files\\Scene" FILES ${BS_BANSHEECORE_SRC_SCENE})
@@ -611,4 +621,6 @@ set(BS_BANSHEECORE_SRC
 	${BS_BANSHEECORE_SRC_AUDIO}
 	${BS_BANSHEECORE_INC_ANIMATION}
 	${BS_BANSHEECORE_SRC_ANIMATION}
+	${BS_BANSHEECORE_INC_RENDERAPI_FACTORIES}
+	${BS_BANSHEECORE_SRC_RENDERAPI_FACTORIES}
 )

+ 0 - 1
Source/BansheeCore/Include/BsCommandBuffer.h

@@ -3,7 +3,6 @@
 #pragma once
 
 #include "BsCorePrerequisites.h"
-#include "BsModule.h"
 
 namespace BansheeEngine
 {

+ 2 - 0
Source/BansheeCore/Include/BsCorePrerequisites.h

@@ -379,6 +379,8 @@ namespace BansheeEngine
 	class MorphShape;
 	class MorphChannel;
 	class CommandBuffer;
+	class GpuPipelineState;
+	class GpuPipelineStateCore;
 	// Asset import
 	class SpecificImporter;
 	class Importer;

+ 0 - 1
Source/BansheeCore/Include/BsGpuParamsSet.h

@@ -140,7 +140,6 @@ namespace BansheeEngine
 		 */
 		GpuParamsType getGpuParams(GpuProgramType type, UINT32 passIdx = 0);
 
-
 		/**
 		 * Assign a parameter block buffer with the specified name to all the relevant child GpuParams.
 		 *

+ 173 - 0
Source/BansheeCore/Include/BsGpuPipelineState.h

@@ -0,0 +1,173 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsCoreObject.h"
+
+namespace BansheeEngine 
+{
+	/** @addtogroup RenderAPI
+	 *  @{
+	 */
+
+	/** Descriptor structure used for initializing a GPU pipeline state. */
+	struct PIPELINE_STATE_DESC
+	{
+		SPtr<BlendState> blendState;
+		SPtr<RasterizerState> rasterizerState;
+		SPtr<DepthStencilState> depthStencilState;
+		UINT32 stencilRefValue;
+
+		SPtr<GpuProgram> vertexProgram;
+		SPtr<GpuProgram> fragmentProgram;
+		SPtr<GpuProgram> geometryProgram;
+		SPtr<GpuProgram> hullProgram;
+		SPtr<GpuProgram> domainProgram;
+		SPtr<GpuProgram> computeProgram;
+	};
+
+	/** @} */
+
+	/** @addtogroup RenderAPI-Internal
+	 *  @{
+	 */
+
+	/** Descriptor structure used for initializing a GPU pipeline state. */
+	struct PIPELINE_STATE_CORE_DESC
+	{
+		SPtr<BlendStateCore> blendState;
+		SPtr<RasterizerStateCore> rasterizerState;
+		SPtr<DepthStencilStateCore> depthStencilState;
+
+		SPtr<GpuProgramCore> vertexProgram;
+		SPtr<GpuProgramCore> fragmentProgram;
+		SPtr<GpuProgramCore> geometryProgram;
+		SPtr<GpuProgramCore> hullProgram;
+		SPtr<GpuProgramCore> domainProgram;
+	};
+
+	/** @} */
+
+	/** @addtogroup Implementation
+	 *  @{
+	 */
+
+	/** Contains all data used by a GPU pipeline state, templated so it may contain both core and sim thread data. */
+	template<bool Core>
+	struct TGpuPipelineStateTypes
+	{ };
+
+	template<>
+	struct TGpuPipelineStateTypes < false >
+	{
+		typedef SPtr<BlendState> BlendStateType;
+		typedef SPtr<RasterizerState> RasterizerStateType;
+		typedef SPtr<DepthStencilState> DepthStencilStateType;
+		typedef SPtr<GpuProgram> GpuProgramType;
+		typedef PIPELINE_STATE_DESC StateDescType;
+	};
+
+	template<>
+	struct TGpuPipelineStateTypes < true >
+	{
+		typedef SPtr<BlendStateCore> BlendStateType;
+		typedef SPtr<RasterizerStateCore> RasterizerStateType;
+		typedef SPtr<DepthStencilStateCore> DepthStencilStateType;
+		typedef SPtr<GpuProgramCore> GpuProgramType;
+		typedef PIPELINE_STATE_CORE_DESC StateDescType;
+	};
+
+	/** 
+	 * Templated version of GpuPipelineState so it can be used for both core and non-core versions of the pipeline state. 
+	 */
+	template<bool Core>
+	class BS_CORE_EXPORT TGpuPipelineState
+    {
+    public:
+		typedef typename TGpuPipelineStateTypes<Core>::BlendStateType BlendStateType;
+		typedef typename TGpuPipelineStateTypes<Core>::RasterizerStateType RasterizerStateType;
+		typedef typename TGpuPipelineStateTypes<Core>::DepthStencilStateType DepthStencilStateType;
+		typedef typename TGpuPipelineStateTypes<Core>::GpuProgramType GpuProgramType;
+		typedef typename TGpuPipelineStateTypes<Core>::StateDescType StateDescType;
+
+		virtual ~TGpuPipelineState() { }
+
+        bool hasVertexProgram() const { return mData.vertexProgram != nullptr; }
+		bool hasFragmentProgram() const { return mData.fragmentProgram != nullptr; }
+		bool hasGeometryProgram() const { return mData.geometryProgram != nullptr; }
+		bool hasHullProgram() const { return mData.hullProgram != nullptr; }
+		bool hasDomainProgram() const { return mData.domainProgram != nullptr; }
+
+		BlendStateType getBlendState() const { return mData.blendState; }
+		RasterizerStateType getRasterizerState() const { return mData.rasterizerState; }
+		DepthStencilStateType getDepthStencilState() const { return mData.depthStencilState; }
+
+		const GpuProgramType& getVertexProgram() const { return mData.vertexProgram; }
+		const GpuProgramType& getFragmentProgram() const { return mData.fragmentProgram; }
+		const GpuProgramType& getGeometryProgram() const { return mData.geometryProgram; }
+		const GpuProgramType& getHullProgram() const { return mData.hullProgram; }
+		const GpuProgramType& getDomainProgram() const { return mData.domainProgram; }
+
+	protected:
+		TGpuPipelineState();
+		TGpuPipelineState(const StateDescType& desc);
+
+		StateDescType mData;
+    };
+
+	/** @} */
+
+	/** @addtogroup RenderAPI
+	 *  @{
+	 */
+
+	class GpuPipelineStateCore;
+
+	/**
+	 * Describes the state of the GPU pipeline that determines how are primitives rendered. It consists of programmable
+	 * states (vertex, fragment, geometry, etc. GPU programs), as well as a set of fixed states (blend, rasterizer, 
+	 * depth-stencil). Once created the state is immutable, and can be bound to RenderAPI for rendering.
+	 */
+    class BS_CORE_EXPORT GpuPipelineState : public CoreObject, public TGpuPipelineState<false>
+    {
+	public:
+		virtual ~GpuPipelineState() { }
+
+		/**
+		 * Retrieves a core implementation of the pipeline object usable only from the core thread.
+		 *
+		 * @note	Core thread only.
+		 */
+		SPtr<GpuPipelineStateCore> getCore() const;
+
+		/** @copydoc RenderStateManager::createPipelineState */
+		static SPtr<GpuPipelineState> create(const PIPELINE_STATE_DESC& desc);
+	protected:
+		friend class RenderStateManager;
+
+		GpuPipelineState(const PIPELINE_STATE_DESC& desc);
+
+		/** @copydoc CoreObject::createCore */
+		virtual SPtr<CoreObjectCore> createCore() const;
+    };
+
+	/** @} */
+
+	/** @addtogroup RenderAPI-Internal
+	 *  @{
+	 */
+
+	/** Core thread version of a GpuPipelineState. */
+	class BS_CORE_EXPORT GpuPipelineStateCore : public CoreObjectCore, public TGpuPipelineState<true>
+	{
+	public:
+		GpuPipelineStateCore(const PIPELINE_STATE_CORE_DESC& desc);
+		virtual ~GpuPipelineStateCore() { }
+
+		/** @copydoc RenderStateManager::createPipelineState */
+		static SPtr<GpuPipelineStateCore> create(const PIPELINE_STATE_CORE_DESC& desc);
+	};
+
+	/** @} */
+}

+ 4 - 4
Source/BansheeCore/Include/BsPass.h

@@ -122,9 +122,9 @@ namespace BansheeEngine
 		const GpuProgramType& getVertexProgram() const { return mData.vertexProgram; }
 		const GpuProgramType& getFragmentProgram() const { return mData.fragmentProgram; }
 		const GpuProgramType& getGeometryProgram() const { return mData.geometryProgram; }
-		const GpuProgramType& getHullProgram(void) const { return mData.hullProgram; }
-		const GpuProgramType& getDomainProgram(void) const { return mData.domainProgram; }
-		const GpuProgramType& getComputeProgram(void) const { return mData.computeProgram; }
+		const GpuProgramType& getHullProgram() const { return mData.hullProgram; }
+		const GpuProgramType& getDomainProgram() const { return mData.domainProgram; }
+		const GpuProgramType& getComputeProgram() const { return mData.computeProgram; }
 
 	protected:
 		TPass();
@@ -208,7 +208,7 @@ namespace BansheeEngine
 	public:
 		friend class PassRTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;
+		RTTITypeBase* getRTTI() const override;
     };
 
 	/** @} */

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

@@ -37,80 +37,80 @@ namespace BansheeEngine
 		/** @see RenderAPICore::setTexture() */
 		static void setTexture(CoreAccessor& accessor, GpuProgramType gptype, UINT16 texUnit, const SPtr<Texture>& texture);
 
-		/** @see RenderAPICore::setLoadStoreTexture() */
+		/** @see RenderAPICore::setLoadStoreTexture() */
 		static void setLoadStoreTexture(CoreAccessor& accessor, GpuProgramType gptype, UINT16 texUnit,
 			const SPtr<Texture>& texture, const TextureSurface& surface);
 
-		/** @see RenderAPICore::setBuffer() */
+		/** @see RenderAPICore::setBuffer() */
 		static void setBuffer(CoreAccessor& accessor, GpuProgramType gptype, UINT16 unit, const SPtr<GpuBuffer>& buffer,
 			bool loadStore = false);
 
-		/** @see RenderAPICore::setSamplerState() */
+		/** @see RenderAPICore::setSamplerState() */
 		static void setSamplerState(CoreAccessor& accessor, GpuProgramType gptype, UINT16 texUnit, 
 			const SPtr<SamplerState>& samplerState);
 
-		/** @see RenderAPICore::setBlendState() */
+		/** @see RenderAPICore::setBlendState() */
 		static void setBlendState(CoreAccessor& accessor, const SPtr<BlendState>& blendState);
 
-		/** @see RenderAPICore::setRasterizerState() */
+		/** @see RenderAPICore::setRasterizerState() */
 		static void setRasterizerState(CoreAccessor& accessor, const SPtr<RasterizerState>& rasterizerState);
 
-		/** @see RenderAPICore::setDepthStencilState() */
+		/** @see RenderAPICore::setDepthStencilState() */
 		static void setDepthStencilState(CoreAccessor& accessor, const SPtr<DepthStencilState>& depthStencilState, 
 			UINT32 stencilRefValue);
 
 		/** @see RenderAPICore::setVertexBuffers() */
 		static void setVertexBuffers(CoreAccessor& accessor, UINT32 index, const Vector<SPtr<VertexBuffer>>& buffers);
-
-		/** @see RenderAPICore::setIndexBuffer() */
+
+		/** @see RenderAPICore::setIndexBuffer() */
 		static void setIndexBuffer(CoreAccessor& accessor, const SPtr<IndexBuffer>& buffer);
 
-		/** @see RenderAPICore::setVertexDeclaration() */
+		/** @see RenderAPICore::setVertexDeclaration() */
 		static void setVertexDeclaration(CoreAccessor& accessor, const SPtr<VertexDeclaration>& vertexDeclaration);
 
-		/** @see RenderAPICore::setViewport() */
+		/** @see RenderAPICore::setViewport() */
 		static void setViewport(CoreAccessor& accessor, const Rect2& area);
 
-		/** @see RenderAPICore::setDrawOperation()  */
+		/** @see RenderAPICore::setDrawOperation()  */
 		static void setDrawOperation(CoreAccessor& accessor, DrawOperationType op);
 
-		/** @see RenderAPICore::setScissorRect()  */
+		/** @see RenderAPICore::setScissorRect()  */
 		static void setScissorRect(CoreAccessor& accessor, UINT32 left = 0, UINT32 top = 0, UINT32 right = 800, UINT32 bottom = 600);
 
-		/** @see RenderAPICore::setRenderTarget() */
+		/** @see RenderAPICore::setRenderTarget() */
 		static void setRenderTarget(CoreAccessor& accessor, const SPtr<RenderTarget>& target, bool readOnlyDepthStencil = false);
 
-		/** @see RenderAPICore::bindGpuProgram() */
+		/** @see RenderAPICore::bindGpuProgram() */
 		static void bindGpuProgram(CoreAccessor& accessor, const SPtr<GpuProgram>& prg);
 
-		/** @see RenderAPICore::unbindGpuProgram() */
+		/** @see RenderAPICore::unbindGpuProgram() */
 		static void unbindGpuProgram(CoreAccessor& accessor, GpuProgramType gptype);
 
-		/** @see RenderAPICore::beginFrame() */
+		/** @see RenderAPICore::beginFrame() */
 		static void beginRender(CoreAccessor& accessor);
 
-		/** @see RenderAPICore::endFrame() */
+		/** @see RenderAPICore::endFrame() */
 		static void endRender(CoreAccessor& accessor);
 
-		/** @see RenderAPICore::clearRenderTarget()  */
+		/** @see RenderAPICore::clearRenderTarget()  */
 		static void clearRenderTarget(CoreAccessor& accessor, UINT32 buffers, 
 			const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0, UINT8 targetMask = 0xFF);
 
-		/** @see RenderAPICore::clearViewport() */
+		/** @see RenderAPICore::clearViewport() */
 		static void clearViewport(CoreAccessor& accessor, UINT32 buffers, const Color& color = Color::Black, 
 			float depth = 1.0f, UINT16 stencil = 0, UINT8 targetMask = 0xFF);
 
-		/** @see RenderAPICore::swapBuffers() */
+		/** @see RenderAPICore::swapBuffers() */
 		static void swapBuffers(CoreAccessor& accessor, const SPtr<RenderTarget>& target);
 
-		/** @see RenderAPICore::draw() */
+		/** @see RenderAPICore::draw() */
 		static void draw(CoreAccessor& accessor, UINT32 vertexOffset, UINT32 vertexCount, UINT32 instanceCount = 0);
 
-		/** @see RenderAPICore::drawIndexed() */
+		/** @see RenderAPICore::drawIndexed() */
 		static void drawIndexed(CoreAccessor& accessor, UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, 
 			UINT32 vertexCount, UINT32 instanceCount = 0);
 
-		/** @see RenderAPICore::dispatchCompute() */
+		/** @see RenderAPICore::dispatchCompute() */
 		static void dispatchCompute(CoreAccessor& accessor, UINT32 numGroupsX, UINT32 numGroupsY = 1, UINT32 numGroupsZ = 1);
 
 		/** @copydoc RenderAPICore::getVideoModeInfo */

+ 14 - 1
Source/BansheeCore/Include/BsRenderStateManager.h

@@ -8,6 +8,7 @@
 #include "BsRasterizerState.h"
 #include "BsDepthStencilState.h"
 #include "BsSamplerState.h"
+#include "BsGpuPipelineState.h"
 
 namespace BansheeEngine
 {
@@ -31,6 +32,9 @@ namespace BansheeEngine
 		/**	Creates and initializes a new BlendState. */
 		SPtr<BlendState> createBlendState(const BLEND_STATE_DESC& desc) const;
 
+		/**	Creates and initializes a new GpuPipelineState. */
+		SPtr<GpuPipelineState> createPipelineState(const PIPELINE_STATE_DESC& desc) const;
+
 		/** Creates an uninitialized sampler state. Requires manual initialization after creation. */
 		SPtr<SamplerState> _createSamplerStatePtr(const SAMPLER_STATE_DESC& desc) const;
 
@@ -40,9 +44,12 @@ namespace BansheeEngine
 		/** Creates an uninitialized rasterizer state. Requires manual initialization after creation. */
 		SPtr<RasterizerState> _createRasterizerStatePtr(const RASTERIZER_STATE_DESC& desc) const;
 
-		/** Creates an uninitialized blend state. Requires manual initialization	after creation. */
+		/** Creates an uninitialized blend state. Requires manual initialization after creation. */
 		SPtr<BlendState> _createBlendStatePtr(const BLEND_STATE_DESC& desc) const;
 
+		/**	Creates an uninitialized GpuPipelineState. Requires manual initialization after creation. */
+		virtual SPtr<GpuPipelineState> _createPipelineState(const PIPELINE_STATE_DESC& desc) const;
+
 		/** Gets a sampler state initialized with default options. */
 		const SPtr<SamplerState>& getDefaultSamplerState() const;
 
@@ -131,6 +138,9 @@ namespace BansheeEngine
 		/** @copydoc RenderStateManager::createBlendState */
 		SPtr<BlendStateCore> createBlendState(const BLEND_STATE_DESC& desc) const;
 
+		/** @copydoc RenderStateManager::createPipelineState */
+		SPtr<GpuPipelineStateCore> createPipelineState(const PIPELINE_STATE_CORE_DESC& desc) const;
+
 		/** Creates an uninitialized sampler state. Requires manual initialization after creation. */
 		SPtr<SamplerStateCore> _createSamplerState(const SAMPLER_STATE_DESC& desc) const;
 
@@ -143,6 +153,9 @@ namespace BansheeEngine
 		/** Creates an uninitialized blend state. Requires manual initialization after creation. */
 		SPtr<BlendStateCore> _createBlendState(const BLEND_STATE_DESC& desc) const;
 
+		/**	Creates an uninitialized GpuPipelineState. Requires manual initialization after creation. */
+		SPtr<GpuPipelineStateCore> _createPipelineState(const PIPELINE_STATE_CORE_DESC& desc) const;
+
 		/** Gets a sampler state initialized with default options. */
 		const SPtr<SamplerStateCore>& getDefaultSamplerState() const;
 

+ 67 - 0
Source/BansheeCore/Source/BsGpuPipelineState.cpp

@@ -0,0 +1,67 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsGpuPipelineState.h"
+#include "BsRasterizerState.h"
+#include "BsBlendState.h"
+#include "BsDepthStencilState.h"
+#include "BsGpuProgram.h"
+#include "BsRenderStateManager.h"
+
+namespace BansheeEngine
+{
+	/** Converts a sim thread pipeline state descriptor to a core thread one. */
+	void convertPassDesc(const PIPELINE_STATE_DESC& input, PIPELINE_STATE_CORE_DESC& output)
+	{
+		output.blendState = input.blendState != nullptr ? input.blendState->getCore() : nullptr;
+		output.rasterizerState = input.rasterizerState != nullptr ? input.rasterizerState->getCore() : nullptr;
+		output.depthStencilState = input.depthStencilState != nullptr ? input.depthStencilState->getCore() : nullptr;
+		output.vertexProgram = input.vertexProgram != nullptr ? input.vertexProgram->getCore() : nullptr;
+		output.fragmentProgram = input.fragmentProgram != nullptr ? input.fragmentProgram->getCore() : nullptr;
+		output.geometryProgram = input.geometryProgram != nullptr ? input.geometryProgram->getCore() : nullptr;
+		output.hullProgram = input.hullProgram != nullptr ? input.hullProgram->getCore() : nullptr;
+		output.domainProgram = input.domainProgram != nullptr ? input.domainProgram->getCore() : nullptr;
+	}
+
+	template<bool Core>
+	TGpuPipelineState<Core>::TGpuPipelineState()
+	{ }
+
+	template<bool Core>
+	TGpuPipelineState<Core>::TGpuPipelineState(const StateDescType& data)
+		:mData(data)
+	{ }
+
+	template class TGpuPipelineState < false > ;
+	template class TGpuPipelineState < true >;
+
+	GpuPipelineStateCore::GpuPipelineStateCore(const PIPELINE_STATE_CORE_DESC& desc)
+		:TGpuPipelineState(desc)
+	{ }
+
+	SPtr<GpuPipelineStateCore> GpuPipelineStateCore::create(const PIPELINE_STATE_CORE_DESC& desc)
+	{
+		return RenderStateCoreManager::instance().createPipelineState(desc);
+	}
+
+	GpuPipelineState::GpuPipelineState(const PIPELINE_STATE_DESC& desc)
+		:TGpuPipelineState(desc)
+	{ }
+
+	SPtr<GpuPipelineStateCore> GpuPipelineState::getCore() const
+	{
+		return std::static_pointer_cast<GpuPipelineStateCore>(mCoreSpecific);
+	}
+
+	SPtr<CoreObjectCore> GpuPipelineState::createCore() const
+	{
+		PIPELINE_STATE_CORE_DESC desc;
+		convertPassDesc(mData, desc);
+
+		return RenderStateCoreManager::instance()._createPipelineState(desc);
+	}
+
+	SPtr<GpuPipelineState> GpuPipelineState::create(const PIPELINE_STATE_DESC& desc)
+	{
+		return RenderStateManager::instance().createPipelineState(desc);
+	}
+}

+ 0 - 1
Source/BansheeCore/Source/BsPass.cpp

@@ -25,7 +25,6 @@ namespace BansheeEngine
 		output.geometryProgram = input.geometryProgram != nullptr ? input.geometryProgram->getCore() : nullptr;
 		output.hullProgram = input.hullProgram != nullptr ? input.hullProgram->getCore() : nullptr;
 		output.domainProgram = input.domainProgram != nullptr ? input.domainProgram->getCore() : nullptr;
-		output.hullProgram = input.hullProgram != nullptr ? input.hullProgram->getCore() : nullptr;
 		output.computeProgram = input.computeProgram != nullptr ? input.computeProgram->getCore() : nullptr;
 	}
 

+ 34 - 0
Source/BansheeCore/Source/BsRenderStateManager.cpp

@@ -40,6 +40,14 @@ namespace BansheeEngine
 		return state;
 	}
 
+	SPtr<GpuPipelineState> RenderStateManager::createPipelineState(const PIPELINE_STATE_DESC& desc) const
+	{
+		SPtr<GpuPipelineState> state = _createPipelineState(desc);
+		state->initialize();
+
+		return state;
+	}
+
 	SPtr<SamplerState> RenderStateManager::_createSamplerStatePtr(const SAMPLER_STATE_DESC& desc) const
 	{
 		SPtr<SamplerState> samplerState = bs_core_ptr<SamplerState>(new (bs_alloc<SamplerState>()) SamplerState(desc));
@@ -72,6 +80,15 @@ namespace BansheeEngine
 		return blendState;
 	}
 
+	SPtr<GpuPipelineState> RenderStateManager::_createPipelineState(const PIPELINE_STATE_DESC& desc) const
+	{
+		SPtr<GpuPipelineState> pipelineState = 
+			bs_core_ptr<GpuPipelineState>(new (bs_alloc<GpuPipelineState>()) GpuPipelineState(desc));
+		pipelineState->_setThisPtr(pipelineState);
+
+		return pipelineState;
+	}
+
 	const SPtr<SamplerState>& RenderStateManager::getDefaultSamplerState() const 
 	{ 
 		if(mDefaultSamplerState == nullptr)
@@ -178,6 +195,14 @@ namespace BansheeEngine
 		return state;
 	}
 
+	SPtr<GpuPipelineStateCore> RenderStateCoreManager::createPipelineState(const PIPELINE_STATE_CORE_DESC& desc) const
+	{
+		SPtr<GpuPipelineStateCore> state = _createPipelineState(desc);
+		state->initialize();
+
+		return state;
+	}
+
 	SPtr<SamplerStateCore> RenderStateCoreManager::_createSamplerState(const SAMPLER_STATE_DESC& desc) const
 	{
 		SPtr<SamplerStateCore> state = findCachedState(desc);
@@ -242,6 +267,15 @@ namespace BansheeEngine
 		return state;
 	}
 
+	SPtr<GpuPipelineStateCore> RenderStateCoreManager::_createPipelineState(const PIPELINE_STATE_CORE_DESC& desc) const
+	{
+		SPtr<GpuPipelineStateCore> pipelineState =
+			bs_shared_ptr<GpuPipelineStateCore>(new (bs_alloc<GpuPipelineStateCore>()) GpuPipelineStateCore(desc));
+		pipelineState->_setThisPtr(pipelineState);
+
+		return pipelineState;
+	}
+
 	void RenderStateCoreManager::onShutDown()
 	{
 		mDefaultBlendState = nullptr;

+ 2 - 1
Source/BansheeD3D11RenderAPI/Source/BsD3D11CommandBuffer.cpp

@@ -7,7 +7,8 @@ namespace BansheeEngine
 	D3D11CommandBuffer::D3D11CommandBuffer(CommandBufferType type, UINT32 deviceIdx, UINT32 syncMask, bool secondary)
 		: CommandBuffer(type, syncMask, secondary), mDeviceIdx(deviceIdx), mActiveDrawOp(DOT_TRIANGLE_LIST)
 	{
-
+		if (deviceIdx != 0)
+			BS_EXCEPT(InvalidParametersException, "Only a single device supported on DX11.");
 	}
 
 	void D3D11CommandBuffer::queueCommand(const std::function<void()> command)

+ 2 - 1
Source/BansheeGLRenderAPI/Source/BsGLCommandBuffer.cpp

@@ -7,7 +7,8 @@ namespace BansheeEngine
 	GLCommandBuffer::GLCommandBuffer(CommandBufferType type, UINT32 deviceIdx, UINT32 syncMask, bool secondary)
 		: CommandBuffer(type, syncMask, secondary), mDeviceIdx(deviceIdx), mCurrentDrawOperation(DOT_TRIANGLE_LIST)
 	{
-
+		if (deviceIdx != 0)
+			BS_EXCEPT(InvalidParametersException, "Only a single device supported on DX11.");
 	}
 
 	void GLCommandBuffer::queueCommand(const std::function<void()> command)