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

DirectX 11 now uses combined pipeline states instead of individually setting per-stage states and programs. This way the system more closely matches modern API's like Vulkan.

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

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

@@ -17,14 +17,12 @@ namespace BansheeEngine
 		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;
 	};
 
 	/** @} */

+ 13 - 0
Source/BansheeCore/Include/BsPass.h

@@ -69,6 +69,7 @@ namespace BansheeEngine
 		typedef SPtr<RasterizerState> RasterizerStateType;
 		typedef SPtr<DepthStencilState> DepthStencilStateType;
 		typedef SPtr<GpuProgram> GpuProgramType;
+		typedef SPtr<GpuPipelineState> GpuPipelineStateType;
 		typedef PASS_DESC PassDescType;
 	};
 
@@ -79,6 +80,7 @@ namespace BansheeEngine
 		typedef SPtr<RasterizerStateCore> RasterizerStateType;
 		typedef SPtr<DepthStencilStateCore> DepthStencilStateType;
 		typedef SPtr<GpuProgramCore> GpuProgramType;
+		typedef SPtr<GpuPipelineStateCore> GpuPipelineStateType;
 		typedef PASS_DESC_CORE PassDescType;
 	};
 
@@ -99,6 +101,7 @@ namespace BansheeEngine
 		typedef typename TPassTypes<Core>::DepthStencilStateType DepthStencilStateType;
 		typedef typename TPassTypes<Core>::GpuProgramType GpuProgramType;
 		typedef typename TPassTypes<Core>::PassDescType PassDescType;
+		typedef typename TPassTypes<Core>::GpuPipelineStateType GpuPipelineStateType;
 
 		virtual ~TPass() { }
 
@@ -126,11 +129,14 @@ namespace BansheeEngine
 		const GpuProgramType& getDomainProgram() const { return mData.domainProgram; }
 		const GpuProgramType& getComputeProgram() const { return mData.computeProgram; }
 
+		const GpuPipelineStateType& getPipelineState() const { return mPipelineState; }
+
 	protected:
 		TPass();
 		TPass(const PassDescType& desc);
 
 		PassDescType mData;
+		GpuPipelineStateType mPipelineState;
     };
 
 	/** @} */
@@ -156,8 +162,12 @@ namespace BansheeEngine
 		friend class Pass;
 		friend class TechniqueCore;
 
+		/** @copydoc CoreObjectCore::initialize */
+		void initialize() override;
+
 		PassCore() { }
 		PassCore(const PASS_DESC_CORE& desc);
+		PassCore(const PASS_DESC_CORE& desc, const SPtr<GpuPipelineStateCore>& pipelineState);
 
 		/** @copydoc CoreObjectCore::syncToCore */
 		void syncToCore(const CoreSyncData& data) override;
@@ -190,6 +200,9 @@ namespace BansheeEngine
 		Pass() { }
 		Pass(const PASS_DESC& desc);
 
+		/** @copydoc CoreObject::initialize */
+		void initialize() override;
+
 		/** @copydoc CoreObject::syncToCore */
 		CoreSyncData syncToCore(FrameAlloc* allocator) override;
 

+ 1 - 4
Source/BansheeCore/Include/BsProfilerGPU.h

@@ -27,16 +27,13 @@ namespace BansheeEngine
 		UINT32 numPrimitives; /**< Total number of primitives sent to the GPU. */
 		UINT32 numDrawnSamples; /**< Number of samples drawn by the GPU. */
 
-		UINT32 numBlendStateChanges; /**< How many times did the blend state change. */
-		UINT32 numRasterizerStateChanges; /**< How many times did the rasterizer state change. */
-		UINT32 numDepthStencilStateChanges; /**< How many times did the depth stencil state change. */
+		UINT32 numPipelineStateChanges; /**< How many times did the pipeline state change. */
 
 		UINT32 numTextureBinds; /**< How many times was a texture bound. */
 		UINT32 numSamplerBinds; /**< How many times was a sampler bound. */
 		UINT32 numVertexBufferBinds; /**< How many times was a vertex buffer bound. */
 		UINT32 numIndexBufferBinds; /**< How many times was an index buffer bound. */
 		UINT32 numGpuParamBufferBinds; /**< How many times was an GPU parameter buffer bound. */
-		UINT32 numGpuProgramBinds; /**< How many times was a GPU program bound. */
 
 		UINT32 numResourceWrites; /**< How many times were GPU resources written to. */
 		UINT32 numResourceReads; /**< How many times were GPU resources read from. */

+ 24 - 61
Source/BansheeCore/Include/BsRenderAPI.h

@@ -49,15 +49,11 @@ namespace BansheeEngine
 		static void setSamplerState(CoreAccessor& accessor, GpuProgramType gptype, UINT16 texUnit, 
 			const SPtr<SamplerState>& samplerState);
 
-		/** @see RenderAPICore::setBlendState() */
-		static void setBlendState(CoreAccessor& accessor, const SPtr<BlendState>& blendState);
+		/** @see RenderAPICore::setGraphicsPipeline() */
+		static void setGraphicsPipeline(CoreAccessor& accessor, const SPtr<GpuPipelineState>& pipelineState);
 
-		/** @see RenderAPICore::setRasterizerState() */
-		static void setRasterizerState(CoreAccessor& accessor, const SPtr<RasterizerState>& rasterizerState);
-
-		/** @see RenderAPICore::setDepthStencilState() */
-		static void setDepthStencilState(CoreAccessor& accessor, const SPtr<DepthStencilState>& depthStencilState, 
-			UINT32 stencilRefValue);
+		/** @see RenderAPICore::setComputePipeline() */
+		static void setComputePipeline(CoreAccessor& accessor, const SPtr<GpuProgram>& computeProgram);
 
 		/** @see RenderAPICore::setVertexBuffers() */
 		static void setVertexBuffers(CoreAccessor& accessor, UINT32 index, const Vector<SPtr<VertexBuffer>>& buffers);
@@ -71,6 +67,9 @@ namespace BansheeEngine
 		/** @see RenderAPICore::setViewport() */
 		static void setViewport(CoreAccessor& accessor, const Rect2& area);
 
+		/** @see RenderAPICore::setViewport() */
+		static void setStencilRef(CoreAccessor& accessor, UINT32 value);
+
 		/** @see RenderAPICore::setDrawOperation()  */
 		static void setDrawOperation(CoreAccessor& accessor, DrawOperationType op);
 
@@ -80,12 +79,6 @@ namespace BansheeEngine
 		/** @see RenderAPICore::setRenderTarget() */
 		static void setRenderTarget(CoreAccessor& accessor, const SPtr<RenderTarget>& target, bool readOnlyDepthStencil = false);
 
-		/** @see RenderAPICore::bindGpuProgram() */
-		static void bindGpuProgram(CoreAccessor& accessor, const SPtr<GpuProgram>& prg);
-
-		/** @see RenderAPICore::unbindGpuProgram() */
-		static void unbindGpuProgram(CoreAccessor& accessor, GpuProgramType gptype);
-
 		/** @see RenderAPICore::beginFrame() */
 		static void beginRender(CoreAccessor& accessor);
 
@@ -238,43 +231,27 @@ namespace BansheeEngine
 			const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
 		/**
-		 * Sets a blend state used for all active render targets.
+		 * Sets a pipeline state that controls how will subsequent draw commands render primitives.
 		 *
-		 * @param[in]	blendState		Blend state to bind, or null to unbind.
-		 * @param[in]	commandBuffer	Optional command buffer to queue the operation on. If not provided operation
-		 *								is executed immediately. Otherwise it is executed when executeCommands() is called.
-		 *								Buffer must support graphics operations.
-		 *
-		 * @see		BlendState
-		 */
-		virtual void setBlendState(const SPtr<BlendStateCore>& blendState, 
-			const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
-
-		/**
-		 * Sets a state that controls various rasterizer options. 
-		 *
-		 * @param[in]	rasterizerState		Rasterizer state to bind, or null to unbind.
+		 * @param[in]	pipelineState		Pipeline state to bind, or null to unbind.
 		 * @param[in]	commandBuffer		Optional command buffer to queue the operation on. If not provided operation
 		 *									is executed immediately. Otherwise it is executed when executeCommands() is 
 		 *									called. Buffer must support graphics operations.
 		 *
-		 * @see		RasterizerState
+		 * @see		GpuPipelineState
 		 */
-		virtual void setRasterizerState(const SPtr<RasterizerStateCore>& rasterizerState, 
+		virtual void setGraphicsPipeline(const SPtr<GpuPipelineStateCore>& pipelineState,
 			const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
 		/**
-		 * Sets a state that controls depth & stencil buffer options.
+		 * Sets a pipeline state that controls how will subsequent dispatch commands execute.
 		 *
-		 * @param[in]	depthStencilState	Depth-stencil state to bind, or null to unbind.
-		 * @param[in]	stencilRefValue		Stencil reference value to be used for stencil comparisons, if enabled.
+		 * @param[in]	computeProgram		Compute program to bind to the pipeline.
 		 * @param[in]	commandBuffer		Optional command buffer to queue the operation on. If not provided operation
 		 *									is executed immediately. Otherwise it is executed when executeCommands() is 
 		 *									called. Buffer must support graphics operations.
-		 *
-		 * @see		DepthStencilState
 		 */
-		virtual void setDepthStencilState(const SPtr<DepthStencilStateCore>& depthStencilState, UINT32 stencilRefValue,
+		virtual void setComputePipeline(const SPtr<GpuProgramCore>& computeProgram,
 			const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
 		/**
@@ -364,6 +341,16 @@ namespace BansheeEngine
 		virtual void setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom, 
 			const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
+		/**
+		 * Sets a reference value that will be used for stencil compare operations.
+		 *
+		 * @param[in]	value			Reference value to set.
+		 * @param[in]	commandBuffer	Optional command buffer to queue the operation on. If not provided operation
+		 *								is executed immediately. Otherwise it is executed when executeCommands() is called.
+		 *								Buffer must support graphics operations.
+		 */
+		virtual void setStencilRef(UINT32 value, const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
+
 		/**
 		 * Sets the provided vertex buffers starting at the specified source index.	Set buffer to nullptr to clear the 
 		 * buffer at the specified index.
@@ -484,30 +471,6 @@ namespace BansheeEngine
 		virtual void swapBuffers(const SPtr<RenderTargetCore>& target, 
 			const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
-		/**
-		 * Binds the provided GPU program to the pipeline. Any following draw operations will use this program. 
-		 *
-		 * @param[in]	prg				GPU program to bind. Slot it is bound to is determined by the program type.
-		 * @param[in]	commandBuffer	Optional command buffer to queue the operation on. If not provided operation
-		 *								is executed immediately. Otherwise it is executed when executeCommands() is called.
-		 *								Buffer must support graphics or compute operations (depending on program type).
-		 *
-		 * @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, 
-			const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
-
-		/**	
-		 * Unbinds a program of a given type. 
-		 *
-		 * @param[in]	gptype			GPU program slot to unbind the program from.
-		 * @param[in]	commandBuffer	Optional command buffer to queue the operation on. If not provided operation
-		 *								is executed immediately. Otherwise it is executed when executeCommands() is called.
-		 *								Buffer must support graphics or compute operations (depending on program type).
-		 */
-		virtual void unbindGpuProgram(GpuProgramType gptype,
-			const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
-
 		/**
 		 * Change the render target into which we want to draw.
 		 *

+ 6 - 25
Source/BansheeCore/Include/BsRenderStats.h

@@ -27,10 +27,9 @@ namespace BansheeEngine
 	struct BS_CORE_EXPORT RenderStatsData
 	{
 		RenderStatsData()
-		: numDrawCalls(0), numComputeCalls(0), numRenderTargetChanges(0), numPresents(0), numClears(0),
-		  numVertices(0), numPrimitives(0), numBlendStateChanges(0), numRasterizerStateChanges(0), 
-		  numDepthStencilStateChanges(0), numTextureBinds(0), numSamplerBinds(0), numVertexBufferBinds(0), 
-		  numIndexBufferBinds(0), numGpuParamBufferBinds(0), numGpuProgramBinds(0)
+		: numDrawCalls(0), numComputeCalls(0), numRenderTargetChanges(0), numPresents(0), numClears(0)
+		, numVertices(0), numPrimitives(0), numPipelineStateChanges(0), numTextureBinds(0), numSamplerBinds(0)
+		, numVertexBufferBinds(0), numIndexBufferBinds(0), numGpuParamBufferBinds(0)
 		{ }
 
 		UINT64 numDrawCalls;
@@ -42,16 +41,13 @@ namespace BansheeEngine
 		UINT64 numVertices;
 		UINT64 numPrimitives;
 
-		UINT64 numBlendStateChanges; 
-		UINT64 numRasterizerStateChanges; 
-		UINT64 numDepthStencilStateChanges;
+		UINT64 numPipelineStateChanges;
 
 		UINT64 numTextureBinds; 
 		UINT64 numSamplerBinds; 
 		UINT64 numVertexBufferBinds; 
 		UINT64 numIndexBufferBinds;
 		UINT64 numGpuParamBufferBinds;
-		UINT64 numGpuProgramBinds; 
 
 		UINT64 numResourceWrites;
 		UINT64 numResourceReads;
@@ -92,20 +88,8 @@ namespace BansheeEngine
 		/** Increments primitive draw counter indicating how many primitives were sent to the pipeline. */
 		void addNumPrimitives(UINT32 count) { mData.numPrimitives += count; }
 
-		/** Increments blend state change counter indicating how many times was a blend state bound to the pipeline. */
-		void incNumBlendStateChanges() { mData.numBlendStateChanges++; }
-
-		/** 
-		 * Increments rasterizer state change counter indicating how many times was a rasterizer state bound to the 
-		 * pipeline.
-		 */
-		void incNumRasterizerStateChanges() { mData.numRasterizerStateChanges++; }
-
-		/** 
-		 * Increments depth/stencil state change counter indicating how many times was a depth/stencil state bound to the 
-		 * pipeline. 
-		 */
-		void incNumDepthStencilStateChanges() { mData.numDepthStencilStateChanges++; }
+		/** Increments pipeline state change counter indicating how many times was a pipeline state bound. */
+		void incNumPipelineStateChanges() { mData.numPipelineStateChanges++; }
 
 		/** Increments texture change counter indicating how many times was a texture bound to the pipeline. */
 		void incNumTextureBinds() { mData.numTextureBinds++; }
@@ -125,9 +109,6 @@ namespace BansheeEngine
 		 */
 		void incNumGpuParamBufferBinds() { mData.numGpuParamBufferBinds++; }
 
-		/** Increments GPU program change counter indicating how many times was a GPU program bound to the pipeline. */
-		void incNumGpuProgramBinds() { mData.numGpuProgramBinds++; }
-
 		/**
 		 * Increments created GPU resource counter. 
 		 *

+ 66 - 2
Source/BansheeCore/Source/BsPass.cpp

@@ -9,7 +9,7 @@
 #include "BsGpuParams.h"
 #include "BsFrameAlloc.h"
 #include "BsGpuProgram.h"
-#include "BsException.h"
+#include "BsGpuPipelineState.h"
 
 namespace BansheeEngine
 {
@@ -28,6 +28,32 @@ namespace BansheeEngine
 		output.computeProgram = input.computeProgram != nullptr ? input.computeProgram->getCore() : nullptr;
 	}
 
+	/** Converts a sim thread pass descriptor to a pipeline state descriptor. */
+	void convertPassDesc(const PASS_DESC& input, PIPELINE_STATE_DESC& output)
+	{
+		output.blendState = input.blendState ;
+		output.rasterizerState = input.rasterizerState;
+		output.depthStencilState = input.depthStencilState;
+		output.vertexProgram = input.vertexProgram;
+		output.fragmentProgram = input.fragmentProgram;
+		output.geometryProgram = input.geometryProgram;
+		output.hullProgram = input.hullProgram;
+		output.domainProgram = input.domainProgram;
+	}
+
+	/** Converts a sim thread pass descriptor to a core thread pipeline state descriptor. */
+	void convertPassDesc(const PASS_DESC_CORE& input, PIPELINE_STATE_CORE_DESC& output)
+	{
+		output.blendState = input.blendState;
+		output.rasterizerState = input.rasterizerState;
+		output.depthStencilState = input.depthStencilState;
+		output.vertexProgram = input.vertexProgram;
+		output.fragmentProgram = input.fragmentProgram;
+		output.geometryProgram = input.geometryProgram;
+		output.hullProgram = input.hullProgram;
+		output.domainProgram = input.domainProgram;
+	}
+
 	template<bool Core>
 	TPass<Core>::TPass()
 	{
@@ -73,6 +99,26 @@ namespace BansheeEngine
 		:TPass(desc)
 	{ }
 
+	PassCore::PassCore(const PASS_DESC_CORE& desc, const SPtr<GpuPipelineStateCore>& pipelineState)
+		:TPass(desc)
+	{
+		mPipelineState = pipelineState;
+	}
+
+	void PassCore::initialize()
+	{
+		// Create pipeline state unless it's already provided, or unless it's a compute pass
+		if (mPipelineState == nullptr && !hasComputeProgram())
+		{
+			PIPELINE_STATE_CORE_DESC desc;
+			convertPassDesc(mData, desc);
+
+			mPipelineState = GpuPipelineStateCore::create(desc);
+		}
+
+		CoreObjectCore::initialize();
+	}
+
 	void PassCore::syncToCore(const CoreSyncData& data)
 	{
 		UINT8* dataPtr = data.getBuffer();
@@ -106,13 +152,31 @@ namespace BansheeEngine
 		PASS_DESC_CORE desc;
 		convertPassDesc(mData, desc);
 
-		PassCore* pass = new (bs_alloc<PassCore>()) PassCore(desc);
+		SPtr<GpuPipelineStateCore> corePipeline;
+		if (mPipelineState != nullptr)
+			corePipeline = mPipelineState->getCore();
+
+		PassCore* pass = new (bs_alloc<PassCore>()) PassCore(desc, corePipeline);
 		SPtr<PassCore> passPtr = bs_shared_ptr<PassCore>(pass);
 		passPtr->_setThisPtr(passPtr);
 
 		return passPtr;
 	}
 
+	void Pass::initialize()
+	{
+		// Create pipeline state unless it's a compute pass
+		if (!hasComputeProgram())
+		{
+			PIPELINE_STATE_DESC desc;
+			convertPassDesc(mData, desc);
+
+			mPipelineState = GpuPipelineState::create(desc);
+		}
+
+		CoreObject::initialize();
+	}
+
 	CoreSyncData Pass::syncToCore(FrameAlloc* allocator)
 	{
 		UINT32 size = sizeof(PASS_DESC_CORE);

+ 1 - 4
Source/BansheeCore/Source/BsProfilerGPU.cpp

@@ -146,16 +146,13 @@ namespace BansheeEngine
 		reportSample.numVertices = (UINT32)(sample.endStats.numVertices - sample.startStats.numVertices);
 		reportSample.numPrimitives = (UINT32)(sample.endStats.numPrimitives - sample.startStats.numPrimitives);
 		
-		reportSample.numBlendStateChanges = (UINT32)(sample.endStats.numBlendStateChanges - sample.startStats.numBlendStateChanges);
-		reportSample.numRasterizerStateChanges = (UINT32)(sample.endStats.numRasterizerStateChanges - sample.startStats.numRasterizerStateChanges);
-		reportSample.numDepthStencilStateChanges = (UINT32)(sample.endStats.numDepthStencilStateChanges - sample.startStats.numDepthStencilStateChanges);
+		reportSample.numPipelineStateChanges = (UINT32)(sample.endStats.numPipelineStateChanges - sample.startStats.numPipelineStateChanges);
 
 		reportSample.numTextureBinds = (UINT32)(sample.endStats.numTextureBinds - sample.startStats.numTextureBinds);
 		reportSample.numSamplerBinds = (UINT32)(sample.endStats.numSamplerBinds - sample.startStats.numSamplerBinds);
 		reportSample.numVertexBufferBinds = (UINT32)(sample.endStats.numVertexBufferBinds - sample.startStats.numVertexBufferBinds);
 		reportSample.numIndexBufferBinds = (UINT32)(sample.endStats.numIndexBufferBinds - sample.startStats.numIndexBufferBinds);
 		reportSample.numGpuParamBufferBinds = (UINT32)(sample.endStats.numGpuParamBufferBinds - sample.startStats.numGpuParamBufferBinds);
-		reportSample.numGpuProgramBinds = (UINT32)(sample.endStats.numGpuProgramBinds - sample.startStats.numGpuProgramBinds);
 
 		reportSample.numResourceWrites = (UINT32)(sample.endStats.numResourceWrites - sample.startStats.numResourceWrites);
 		reportSample.numResourceReads = (UINT32)(sample.endStats.numResourceReads - sample.startStats.numResourceReads);

+ 12 - 31
Source/BansheeCore/Source/BsRenderAPI.cpp

@@ -6,17 +6,12 @@
 #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"
 #include "BsGpuBuffer.h"
-#include "BsGpuParamBlockBuffer.h"
-#include "BsCommandBuffer.h"
+#include "BsGpuPipelineState.h"
 
 using namespace std::placeholders;
 
@@ -49,22 +44,16 @@ namespace BansheeEngine
 			samplerState->getCore(), nullptr));
 	}
 
-	void RenderAPI::setBlendState(CoreAccessor& accessor, const SPtr<BlendState>& blendState)
+	void RenderAPI::setGraphicsPipeline(CoreAccessor& accessor, const SPtr<GpuPipelineState>& pipelineState)
 	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setBlendState, RenderAPICore::instancePtr(), blendState->getCore(), 
-			nullptr));
-	}
-
-	void RenderAPI::setRasterizerState(CoreAccessor& accessor, const SPtr<RasterizerState>& rasterizerState)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setRasterizerState, RenderAPICore::instancePtr(), 
-			rasterizerState->getCore(), nullptr));
+		accessor.queueCommand(std::bind(&RenderAPICore::setGraphicsPipeline, RenderAPICore::instancePtr(),
+			pipelineState->getCore(), nullptr));
 	}
 
-	void RenderAPI::setDepthStencilState(CoreAccessor& accessor, const SPtr<DepthStencilState>& depthStencilState, UINT32 stencilRefValue)
+	void RenderAPI::setComputePipeline(CoreAccessor& accessor, const SPtr<GpuProgram>& computeProgram)
 	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setDepthStencilState, RenderAPICore::instancePtr(), 
-			depthStencilState->getCore(), stencilRefValue, nullptr));
+		accessor.queueCommand(std::bind(&RenderAPICore::setComputePipeline, RenderAPICore::instancePtr(),
+			computeProgram->getCore(), nullptr));
 	}
 
 	void RenderAPI::setVertexBuffers(CoreAccessor& accessor, UINT32 index, const Vector<SPtr<VertexBuffer>>& buffers)
@@ -99,6 +88,11 @@ namespace BansheeEngine
 		accessor.queueCommand(std::bind(&RenderAPICore::setViewport, RenderAPICore::instancePtr(), vp, nullptr));
 	}
 
+	void RenderAPI::setStencilRef(CoreAccessor& accessor, UINT32 value)
+	{
+		accessor.queueCommand(std::bind(&RenderAPICore::setStencilRef, RenderAPICore::instancePtr(), value, nullptr));
+	}
+
 	void RenderAPI::setDrawOperation(CoreAccessor& accessor, DrawOperationType op)
 	{
 		accessor.queueCommand(std::bind(&RenderAPICore::setDrawOperation, RenderAPICore::instancePtr(), op, 
@@ -117,19 +111,6 @@ namespace BansheeEngine
 			RenderAPICore::instancePtr(), target->getCore(), readOnlyDepthStencil, nullptr));
 	}
 
-	void RenderAPI::bindGpuProgram(CoreAccessor& accessor, const SPtr<GpuProgram>& prg)
-	{
-		prg->syncToCore(accessor);
-		accessor.queueCommand(std::bind(&RenderAPICore::bindGpuProgram, RenderAPICore::instancePtr(), prg->getCore(), 
-			nullptr));
-	}
-
-	void RenderAPI::unbindGpuProgram(CoreAccessor& accessor, GpuProgramType gptype)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::unbindGpuProgram, RenderAPICore::instancePtr(), gptype, 
-			nullptr));
-	}
-
 	void RenderAPI::beginRender(CoreAccessor& accessor)
 	{
 		accessor.queueCommand(std::bind(&RenderAPICore::beginFrame, RenderAPICore::instancePtr(), nullptr));

+ 1 - 4
Source/BansheeD3D11RenderAPI/Include/BsD3D11Prerequisites.h

@@ -53,10 +53,7 @@ namespace BansheeEngine
 	class D3D11GpuGeometryProgram;
 	class D3D11GpuHullProgram;
 	class D3D11GpuDomainProgram;
-	class D3D11BlendState;
-	class D3D11RasterizerState;
-	class D3D11SamplerState;
-	class D3D11DepthStencilState;
+	class D3D11DepthStencilStateCore;
 	class D3D11InputLayoutManager;
 	class D3D11GpuBufferCore;
 	class D3D11RenderUtility;

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

@@ -24,16 +24,12 @@ namespace BansheeEngine
 		/** @copydoc RenderAPICore::getShadingLanguageName */
 		const String& getShadingLanguageName() const override;
 
-		/** @copydoc RenderAPICore::setBlendState */
-		void setBlendState(const SPtr<BlendStateCore>& blendState, 
+		/** @copydoc RenderAPICore::setGraphicsPipeline */
+		void setGraphicsPipeline(const SPtr<GpuPipelineStateCore>& pipelineState, 
 			const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
-		/** @copydoc RenderAPICore::setRasterizerState */
-		void setRasterizerState(const SPtr<RasterizerStateCore>& rasterizerState,
-			const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
-
-		/** @copydoc RenderAPICore::setDepthStencilState */
-		void setDepthStencilState(const SPtr<DepthStencilStateCore>& depthStencilState, UINT32 stencilRefValue,
+		/** @copydoc RenderAPICore::setComputePipeline */
+		void setComputePipeline(const SPtr<GpuProgramCore>& computeProgram,
 			const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPICore::setSamplerState */
@@ -77,6 +73,9 @@ namespace BansheeEngine
 		void setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom, 
 			const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
+		/** @copydoc RenderAPICore::setStencilRef */
+		void setStencilRef(UINT32 value, const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
+
 		/** @copydoc RenderAPICore::setVertexBuffers */
 		void setVertexBuffers(UINT32 index, SPtr<VertexBufferCore>* buffers, UINT32 numBuffers,
 			const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
@@ -109,12 +108,6 @@ namespace BansheeEngine
 		void swapBuffers(const SPtr<RenderTargetCore>& target,
 			const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
-		/** @copydoc RenderAPICore::bindGpuProgram */
-		void bindGpuProgram(const SPtr<GpuProgramCore>& prg, const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
-
-		/** @copydoc RenderAPICore::unbindGpuProgram */
-		void unbindGpuProgram(GpuProgramType gptype, const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
-
 		/** @copydoc RenderAPICore::setParamBuffer */
 		void setParamBuffer(GpuProgramType gptype, UINT32 slot, const SPtr<GpuParamBlockBufferCore>& buffer, 
 			const SPtr<GpuParamDesc>& paramDesc, const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
@@ -205,6 +198,7 @@ namespace BansheeEngine
 
 		SPtr<VertexDeclarationCore> mActiveVertexDeclaration;
 		SPtr<D3D11GpuProgramCore> mActiveVertexShader;
+		SPtr<D3D11DepthStencilStateCore> mActiveDepthStencilState;
 
 		DrawOperationType mActiveDrawOp;
 	};

+ 115 - 152
Source/BansheeD3D11RenderAPI/Source/BsD3D11RenderAPI.cpp

@@ -35,11 +35,9 @@
 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)
+		: 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)
 	{ }
 
 	D3D11RenderAPI::~D3D11RenderAPI()
@@ -188,6 +186,7 @@ namespace BansheeEngine
 		mActiveVertexDeclaration = nullptr;
 		mActiveVertexShader = nullptr;
 		mActiveRenderTarget = nullptr;
+		mActiveDepthStencilState = nullptr;
 
 		RenderStateCoreManager::shutDown();
 		RenderWindowCoreManager::shutDown();
@@ -266,80 +265,130 @@ namespace BansheeEngine
 		BS_INC_RENDER_STAT(NumSamplerBinds);
 	}
 
-	void D3D11RenderAPI::setBlendState(const SPtr<BlendStateCore>& blendState, const SPtr<CommandBuffer>& commandBuffer)
+	void D3D11RenderAPI::setGraphicsPipeline(const SPtr<GpuPipelineStateCore>& pipelineState,
+		const SPtr<CommandBuffer>& commandBuffer)
 	{
-		auto executeRef = [&](const SPtr<BlendStateCore>& blendState)
+		auto executeRef = [&](const SPtr<GpuPipelineStateCore>& pipelineState)
 		{
 			THROW_IF_NOT_CORE_THREAD;
 
-			D3D11BlendStateCore* d3d11BlendState = 
-				static_cast<D3D11BlendStateCore*>(const_cast<BlendStateCore*>(blendState.get()));
-			mDevice->getImmediateContext()->OMSetBlendState(d3d11BlendState->getInternal(), nullptr, 0xFFFFFFFF);
-		};
+			D3D11BlendStateCore* d3d11BlendState;
+			D3D11RasterizerStateCore* d3d11RasterizerState;
 
-		if (commandBuffer == nullptr)
-			executeRef(blendState);
-		else
-		{
-			auto execute = [=]() { executeRef(blendState); };
+			D3D11GpuFragmentProgramCore* d3d11FragmentProgram;
+			D3D11GpuGeometryProgramCore* d3d11GeometryProgram;
+			D3D11GpuDomainProgramCore* d3d11DomainProgram;
+			D3D11GpuHullProgramCore* d3d11HullProgram;
 
-			SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
-			cb->queueCommand(execute);
-		}
+			if(pipelineState != nullptr)
+			{
+				d3d11BlendState = static_cast<D3D11BlendStateCore*>(pipelineState->getBlendState().get());
+				d3d11RasterizerState = static_cast<D3D11RasterizerStateCore*>(pipelineState->getRasterizerState().get());
+				mActiveDepthStencilState = std::static_pointer_cast<D3D11DepthStencilStateCore>(pipelineState->getDepthStencilState());
 
-		BS_INC_RENDER_STAT(NumBlendStateChanges);
-	}
+				mActiveVertexShader = std::static_pointer_cast<D3D11GpuVertexProgramCore>(pipelineState->getVertexProgram());
+				d3d11FragmentProgram = static_cast<D3D11GpuFragmentProgramCore*>(pipelineState->getFragmentProgram().get());
+				d3d11GeometryProgram = static_cast<D3D11GpuGeometryProgramCore*>(pipelineState->getGeometryProgram().get());
+				d3d11DomainProgram = static_cast<D3D11GpuDomainProgramCore*>(pipelineState->getDomainProgram().get());
+				d3d11HullProgram = static_cast<D3D11GpuHullProgramCore*>(pipelineState->getHullProgram().get());
 
-	void D3D11RenderAPI::setRasterizerState(const SPtr<RasterizerStateCore>& rasterizerState, 
-		const SPtr<CommandBuffer>& commandBuffer)
-	{
-		auto executeRef = [&](const SPtr<RasterizerStateCore>& rasterizerState)
-		{
-			THROW_IF_NOT_CORE_THREAD;
+				if (d3d11BlendState == nullptr)
+					d3d11BlendState = static_cast<D3D11BlendStateCore*>(BlendStateCore::getDefault().get());
+
+				if (d3d11RasterizerState == nullptr)
+					d3d11RasterizerState = static_cast<D3D11RasterizerStateCore*>(RasterizerStateCore::getDefault().get());
+
+				if (mActiveDepthStencilState == nullptr)
+					mActiveDepthStencilState = std::static_pointer_cast<D3D11DepthStencilStateCore>(DepthStencilStateCore::getDefault());
+			}
+			else
+			{
+				d3d11BlendState = static_cast<D3D11BlendStateCore*>(BlendStateCore::getDefault().get());
+				d3d11RasterizerState = static_cast<D3D11RasterizerStateCore*>(RasterizerStateCore::getDefault().get());
+				mActiveDepthStencilState = std::static_pointer_cast<D3D11DepthStencilStateCore>(DepthStencilStateCore::getDefault());
 
-			D3D11RasterizerStateCore* d3d11RasterizerState = 
-				static_cast<D3D11RasterizerStateCore*>(const_cast<RasterizerStateCore*>(rasterizerState.get()));
-			mDevice->getImmediateContext()->RSSetState(d3d11RasterizerState->getInternal());
+				mActiveVertexShader = nullptr;
+				d3d11FragmentProgram = nullptr;
+				d3d11GeometryProgram = nullptr;
+				d3d11DomainProgram = nullptr;
+				d3d11HullProgram = nullptr;
+			}
 
+			ID3D11DeviceContext* d3d11Context = mDevice->getImmediateContext();
+			d3d11Context->OMSetBlendState(d3d11BlendState->getInternal(), nullptr, 0xFFFFFFFF);
+			d3d11Context->RSSetState(d3d11RasterizerState->getInternal());
+			d3d11Context->OMSetDepthStencilState(mActiveDepthStencilState->getInternal(), mStencilRef);
 
+			if (mActiveVertexShader != nullptr)
+			{
+				D3D11GpuVertexProgramCore* vertexProgram = static_cast<D3D11GpuVertexProgramCore*>(mActiveVertexShader.get());
+				d3d11Context->VSSetShader(vertexProgram->getVertexShader(), nullptr, 0);
+			}
+			else
+				d3d11Context->VSSetShader(nullptr, nullptr, 0);
+
+			if(d3d11FragmentProgram != nullptr)
+				d3d11Context->PSSetShader(d3d11FragmentProgram->getPixelShader(), nullptr, 0);
+			else
+				d3d11Context->PSSetShader(nullptr, nullptr, 0);
+
+			if (d3d11GeometryProgram != nullptr)
+				d3d11Context->GSSetShader(d3d11GeometryProgram->getGeometryShader(), nullptr, 0);
+			else
+				d3d11Context->GSSetShader(nullptr, nullptr, 0);
+
+			if (d3d11DomainProgram != nullptr)
+				d3d11Context->DSSetShader(d3d11DomainProgram->getDomainShader(), nullptr, 0);
+			else
+				d3d11Context->DSSetShader(nullptr, nullptr, 0);
+
+			if (d3d11HullProgram != nullptr)
+				d3d11Context->HSSetShader(d3d11HullProgram->getHullShader(), nullptr, 0);
+			else
+				d3d11Context->HSSetShader(nullptr, nullptr, 0);
+			
 		};
 
 		if (commandBuffer == nullptr)
-			executeRef(rasterizerState);
+			executeRef(pipelineState);
 		else
 		{
-			auto execute = [=]() { executeRef(rasterizerState); };
+			auto execute = [=]() { executeRef(pipelineState); };
 
 			SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
 			cb->queueCommand(execute);
 		}
 
-		BS_INC_RENDER_STAT(NumRasterizerStateChanges);
+		BS_INC_RENDER_STAT(NumPipelineStateChanges);
 	}
 
-	void D3D11RenderAPI::setDepthStencilState(const SPtr<DepthStencilStateCore>& depthStencilState, UINT32 stencilRefValue, 
+	void D3D11RenderAPI::setComputePipeline(const SPtr<GpuProgramCore>& computeProgram,
 		const SPtr<CommandBuffer>& commandBuffer)
 	{
-		auto executeRef = [&](const SPtr<DepthStencilStateCore>& depthStencilState, UINT32 stencilRefValue)
+		auto executeRef = [&](const SPtr<GpuProgramCore>& computeProgram)
 		{
 			THROW_IF_NOT_CORE_THREAD;
 
-			D3D11DepthStencilStateCore* d3d11RasterizerState = 
-				static_cast<D3D11DepthStencilStateCore*>(const_cast<DepthStencilStateCore*>(depthStencilState.get()));
-			mDevice->getImmediateContext()->OMSetDepthStencilState(d3d11RasterizerState->getInternal(), stencilRefValue);
+			if (computeProgram != nullptr)
+			{
+				D3D11GpuComputeProgramCore *d3d11ComputeProgram = static_cast<D3D11GpuComputeProgramCore*>(computeProgram.get());
+				mDevice->getImmediateContext()->CSSetShader(d3d11ComputeProgram->getComputeShader(), nullptr, 0);
+			}
+			else
+				mDevice->getImmediateContext()->CSSetShader(nullptr, nullptr, 0);
 		};
 
 		if (commandBuffer == nullptr)
-			executeRef(depthStencilState, stencilRefValue);
+			executeRef(computeProgram);
 		else
 		{
-			auto execute = [=]() { executeRef(depthStencilState, stencilRefValue); };
+			auto execute = [=]() { executeRef(computeProgram); };
 
 			SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
 			cb->queueCommand(execute);
 		}
 
-		BS_INC_RENDER_STAT(NumDepthStencilStateChanges);
+		BS_INC_RENDER_STAT(NumPipelineStateChanges);
 	}
 
 	void D3D11RenderAPI::setTexture(GpuProgramType gptype, UINT16 unit, const SPtr<TextureCore>& texPtr, 
@@ -687,117 +736,6 @@ namespace BansheeEngine
 		}
 	}
 
-	void D3D11RenderAPI::bindGpuProgram(const SPtr<GpuProgramCore>& prg, const SPtr<CommandBuffer>& commandBuffer)
-	{
-		auto executeRef = [&](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());
-		};
-
-		if (commandBuffer == nullptr)
-			executeRef(prg);
-		else
-		{
-			auto execute = [=]() { executeRef(prg); };
-
-			SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
-			cb->queueCommand(execute);
-		}
-
-		BS_INC_RENDER_STAT(NumGpuProgramBinds);
-	}
-
-	void D3D11RenderAPI::unbindGpuProgram(GpuProgramType gptype, const SPtr<CommandBuffer>& commandBuffer)
-	{
-		auto executeRef = [&](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));
-			}
-		};
-
-		if (commandBuffer == nullptr)
-			executeRef(gptype);
-		else
-		{
-			auto execute = [=]() { executeRef(gptype); };
-
-			SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
-			cb->queueCommand(execute);
-		}
-
-		BS_INC_RENDER_STAT(NumGpuProgramBinds);
-	}
-
 	void D3D11RenderAPI::setParamBuffer(GpuProgramType gptype, UINT32 slot, const SPtr<GpuParamBlockBufferCore>& buffer, 
 		const SPtr<GpuParamDesc>& paramDesc, const SPtr<CommandBuffer>& commandBuffer)
 	{
@@ -993,6 +931,31 @@ namespace BansheeEngine
 		}
 	}
 
+	void D3D11RenderAPI::setStencilRef(UINT32 value, const SPtr<CommandBuffer>& commandBuffer)
+	{
+		auto executeRef = [&](UINT32 value)
+		{
+			THROW_IF_NOT_CORE_THREAD;
+
+			mStencilRef = value;
+
+			if(mActiveDepthStencilState != nullptr)
+				mDevice->getImmediateContext()->OMSetDepthStencilState(mActiveDepthStencilState->getInternal(), mStencilRef);
+			else
+				mDevice->getImmediateContext()->OMSetDepthStencilState(nullptr, mStencilRef);
+		};
+
+		if (commandBuffer == nullptr)
+			executeRef(value);
+		else
+		{
+			auto execute = [=]() { executeRef(value); };
+
+			SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
+			cb->queueCommand(execute);
+		}
+	}
+
 	void D3D11RenderAPI::clearViewport(UINT32 buffers, const Color& color, float depth, UINT16 stencil, UINT8 targetMask, 
 		const SPtr<CommandBuffer>& commandBuffer)
 	{

+ 2 - 8
Source/BansheeEngine/Include/BsProfilerOverlay.h

@@ -225,9 +225,7 @@ namespace BansheeEngine
 		GUILabel* mGPUVerticesLbl;
 		GUILabel* mGPUPrimitivesLbl;
 		GUILabel* mGPUSamplesLbl;
-		GUILabel* mGPUBlendStateChangesLbl;
-		GUILabel* mGPURasterStateChangesLbl;
-		GUILabel* mGPUDepthStencilStateChangesLbl;
+		GUILabel* mGPUPipelineStateChangesLbl;
 
 		GUILabel* mGPUObjectsCreatedLbl;
 		GUILabel* mGPUObjectsDestroyedLbl;
@@ -238,7 +236,6 @@ namespace BansheeEngine
 		GUILabel* mGPUVertexBufferBindsLbl;
 		GUILabel* mGPUIndexBufferBindsLbl;
 		GUILabel* mGPUGPUProgramBufferBindsLbl;
-		GUILabel* mGPUGPUProgramBindsLbl;
 
 		HString mGPUFrameNumStr;
 		HString mGPUTimeStr;
@@ -249,9 +246,7 @@ namespace BansheeEngine
 		HString mGPUVerticesStr;
 		HString mGPUPrimitivesStr;
 		HString mGPUSamplesStr;
-		HString mGPUBlendStateChangesStr;
-		HString mGPURasterStateChangesStr;
-		HString mGPUDepthStencilStateChangesStr;
+		HString mGPUPipelineStateChangesStr;
 
 		HString mGPUObjectsCreatedStr;
 		HString mGPUObjectsDestroyedStr;
@@ -262,7 +257,6 @@ namespace BansheeEngine
 		HString mGPUVertexBufferBindsStr;
 		HString mGPUIndexBufferBindsStr;
 		HString mGPUGPUProgramBufferBindsStr;
-		HString mGPUGPUProgramBindsStr;
 
 		Vector<BasicRow> mBasicRows;
 		Vector<PreciseRow> mPreciseRows;

+ 5 - 20
Source/BansheeEngine/Source/BsProfilerOverlay.cpp

@@ -457,9 +457,7 @@ namespace BansheeEngine
 		mGPUVerticesStr = HEString(L"__ProfOvVertices", L"Num. vertices: {0}");
 		mGPUPrimitivesStr = HEString(L"__ProfOvPrimitives", L"Num. primitives: {0}");
 		mGPUSamplesStr = HEString(L"__ProfOvSamples", L"Samples drawn: {0}");
-		mGPUBlendStateChangesStr = HEString(L"__ProfOvBSChanges", L"Blend state changes: {0}");
-		mGPURasterStateChangesStr = HEString(L"__ProfOvRSChanges", L"Rasterizer state changes: {0}");
-		mGPUDepthStencilStateChangesStr = HEString(L"__ProfOvDSSChanges", L"Depth/stencil state changes: {0}");
+		mGPUPipelineStateChangesStr = HEString(L"__ProfOvPSChanges", L"Pipeline state changes: {0}");
 
 		mGPUObjectsCreatedStr = HEString(L"__ProfOvObjsCreated", L"Objects created: {0}");
 		mGPUObjectsDestroyedStr = HEString(L"__ProfOvObjsDestroyed", L"Objects destroyed: {0}");
@@ -470,7 +468,6 @@ namespace BansheeEngine
 		mGPUVertexBufferBindsStr = HEString(L"__ProfOvVBBinds", L"VB binds: {0}");
 		mGPUIndexBufferBindsStr = HEString(L"__ProfOvIBBinds", L"IB binds: {0}");
 		mGPUGPUProgramBufferBindsStr = HEString(L"__ProfOvProgBuffBinds", L"GPU program buffer binds: {0}");
-		mGPUGPUProgramBindsStr = HEString(L"__ProfOvProgBinds", L"GPU program binds: {0}");
 
 		mGPUFrameNumLbl = GUILabel::create(mGPUFrameNumStr, GUIOptions(GUIOption::fixedWidth(200)));
 		mGPUTimeLbl = GUILabel::create(mGPUTimeStr, GUIOptions(GUIOption::fixedWidth(200)));
@@ -481,9 +478,7 @@ namespace BansheeEngine
 		mGPUVerticesLbl = GUILabel::create(mGPUVerticesStr, GUIOptions(GUIOption::fixedWidth(200)));
 		mGPUPrimitivesLbl = GUILabel::create(mGPUPrimitivesStr, GUIOptions(GUIOption::fixedWidth(200)));
 		mGPUSamplesLbl = GUILabel::create(mGPUSamplesStr, GUIOptions(GUIOption::fixedWidth(200)));
-		mGPUBlendStateChangesLbl = GUILabel::create(mGPUBlendStateChangesStr, GUIOptions(GUIOption::fixedWidth(200)));
-		mGPURasterStateChangesLbl = GUILabel::create(mGPURasterStateChangesStr, GUIOptions(GUIOption::fixedWidth(200)));
-		mGPUDepthStencilStateChangesLbl = GUILabel::create(mGPUDepthStencilStateChangesStr, GUIOptions(GUIOption::fixedWidth(200)));
+		mGPUPipelineStateChangesLbl = GUILabel::create(mGPUPipelineStateChangesStr, GUIOptions(GUIOption::fixedWidth(200)));
 
 		mGPUObjectsCreatedLbl = GUILabel::create(mGPUObjectsCreatedStr, GUIOptions(GUIOption::fixedWidth(200)));
 		mGPUObjectsDestroyedLbl = GUILabel::create(mGPUObjectsDestroyedStr, GUIOptions(GUIOption::fixedWidth(200)));
@@ -494,7 +489,6 @@ namespace BansheeEngine
 		mGPUVertexBufferBindsLbl = GUILabel::create(mGPUVertexBufferBindsStr, GUIOptions(GUIOption::fixedWidth(200)));
 		mGPUIndexBufferBindsLbl = GUILabel::create(mGPUIndexBufferBindsStr, GUIOptions(GUIOption::fixedWidth(200)));
 		mGPUGPUProgramBufferBindsLbl = GUILabel::create(mGPUGPUProgramBufferBindsStr, GUIOptions(GUIOption::fixedWidth(200)));
-		mGPUGPUProgramBindsLbl = GUILabel::create(mGPUGPUProgramBindsStr, GUIOptions(GUIOption::fixedWidth(200)));
 
 		mGPULayoutFrameContentsLeft->addElement(mGPUFrameNumLbl);
 		mGPULayoutFrameContentsLeft->addElement(mGPUTimeLbl);
@@ -505,9 +499,7 @@ namespace BansheeEngine
 		mGPULayoutFrameContentsLeft->addElement(mGPUVerticesLbl);
 		mGPULayoutFrameContentsLeft->addElement(mGPUPrimitivesLbl);
 		mGPULayoutFrameContentsLeft->addElement(mGPUSamplesLbl);
-		mGPULayoutFrameContentsLeft->addElement(mGPUBlendStateChangesLbl);
-		mGPULayoutFrameContentsLeft->addElement(mGPURasterStateChangesLbl);
-		mGPULayoutFrameContentsLeft->addElement(mGPUDepthStencilStateChangesLbl);
+		mGPULayoutFrameContentsLeft->addElement(mGPUPipelineStateChangesLbl);
 		mGPULayoutFrameContentsLeft->addNewElement<GUIFlexibleSpace>();
 
 		mGPULayoutFrameContentsRight->addElement(mGPUObjectsCreatedLbl);
@@ -519,7 +511,6 @@ namespace BansheeEngine
 		mGPULayoutFrameContentsRight->addElement(mGPUVertexBufferBindsLbl);
 		mGPULayoutFrameContentsRight->addElement(mGPUIndexBufferBindsLbl);
 		mGPULayoutFrameContentsRight->addElement(mGPUGPUProgramBufferBindsLbl);
-		mGPULayoutFrameContentsRight->addElement(mGPUGPUProgramBindsLbl);
 		mGPULayoutFrameContentsRight->addNewElement<GUIFlexibleSpace>();
 
 		updateCPUSampleAreaSizes();
@@ -744,9 +735,7 @@ namespace BansheeEngine
 		mGPUVerticesStr.setParameter(0, toWString(gpuReport.frameSample.numVertices));
 		mGPUPrimitivesStr.setParameter(0, toWString(gpuReport.frameSample.numPrimitives));
 		mGPUSamplesStr.setParameter(0, toWString(gpuReport.frameSample.numDrawnSamples));
-		mGPUBlendStateChangesStr.setParameter(0, toWString(gpuReport.frameSample.numBlendStateChanges));
-		mGPURasterStateChangesStr.setParameter(0, toWString(gpuReport.frameSample.numRasterizerStateChanges));
-		mGPUDepthStencilStateChangesStr.setParameter(0, toWString(gpuReport.frameSample.numDepthStencilStateChanges));
+		mGPUPipelineStateChangesStr.setParameter(0, toWString(gpuReport.frameSample.numPipelineStateChanges));
 
 		mGPUObjectsCreatedStr.setParameter(0, toWString(gpuReport.frameSample.numObjectsCreated));
 		mGPUObjectsDestroyedStr.setParameter(0, toWString(gpuReport.frameSample.numObjectsDestroyed));
@@ -757,7 +746,6 @@ namespace BansheeEngine
 		mGPUVertexBufferBindsStr.setParameter(0, toWString(gpuReport.frameSample.numVertexBufferBinds));
 		mGPUIndexBufferBindsStr.setParameter(0, toWString(gpuReport.frameSample.numIndexBufferBinds));
 		mGPUGPUProgramBufferBindsStr.setParameter(0, toWString(gpuReport.frameSample.numGpuParamBufferBinds));
-		mGPUGPUProgramBindsStr.setParameter(0, toWString(gpuReport.frameSample.numGpuProgramBinds));
 
 		mGPUFrameNumLbl->setContent(mGPUFrameNumStr);
 		mGPUTimeLbl->setContent(mGPUTimeStr);
@@ -768,9 +756,7 @@ namespace BansheeEngine
 		mGPUVerticesLbl->setContent(mGPUVerticesStr);
 		mGPUPrimitivesLbl->setContent(mGPUPrimitivesStr);
 		mGPUSamplesLbl->setContent(mGPUSamplesStr);
-		mGPUBlendStateChangesLbl->setContent(mGPUBlendStateChangesStr);
-		mGPURasterStateChangesLbl->setContent(mGPURasterStateChangesStr);
-		mGPUDepthStencilStateChangesLbl->setContent(mGPUDepthStencilStateChangesStr);
+		mGPUPipelineStateChangesLbl->setContent(mGPUPipelineStateChangesStr);
 
 		mGPUObjectsCreatedLbl->setContent(mGPUObjectsCreatedStr);
 		mGPUObjectsDestroyedLbl->setContent(mGPUObjectsDestroyedStr);
@@ -781,7 +767,6 @@ namespace BansheeEngine
 		mGPUVertexBufferBindsLbl->setContent(mGPUVertexBufferBindsStr);
 		mGPUIndexBufferBindsLbl->setContent(mGPUIndexBufferBindsStr);
 		mGPUGPUProgramBufferBindsLbl->setContent(mGPUGPUProgramBufferBindsStr);
-		mGPUGPUProgramBindsLbl->setContent(mGPUGPUProgramBindsStr);
 
 		GPUSampleRowFiller sampleRowFiller(mGPUSampleRows, *mGPULayoutSampleContents, *mWidget->_getInternal());
 		for (auto& sample : gpuReport.samples)

+ 4 - 48
Source/BansheeEngine/Source/BsRendererUtility.cpp

@@ -122,60 +122,16 @@ namespace BansheeEngine
 		RenderAPICore& rapi = RenderAPICore::instance();
 
 		SPtr<PassCore> pass = material->getPass(passIdx, techniqueIdx);
-
-		struct StageData
-		{
-			GpuProgramType type;
-			bool enable;
-			SPtr<GpuProgramCore> program;
-		};
-
-		const UINT32 numStages = 5;
-		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() }
-		};
-
-		for (UINT32 i = 0; i < numStages; i++)
-		{
-			const StageData& stage = stages[i];
-
-			if (stage.enable)
-				rapi.bindGpuProgram(stage.program);
-			else
-				rapi.unbindGpuProgram(stage.type);
-		}
-
-		// Set up non-texture related pass settings
-		if (pass->getBlendState() != nullptr)
-			rapi.setBlendState(pass->getBlendState());
-		else
-			rapi.setBlendState(BlendStateCore::getDefault());
-
-		if (pass->getDepthStencilState() != nullptr)
-			rapi.setDepthStencilState(pass->getDepthStencilState(), pass->getStencilRefValue());
-		else
-			rapi.setDepthStencilState(DepthStencilStateCore::getDefault(), pass->getStencilRefValue());
-
-		if (pass->getRasterizerState() != nullptr)
-			rapi.setRasterizerState(pass->getRasterizerState());
-		else
-			rapi.setRasterizerState(RasterizerStateCore::getDefault());
+		rapi.setGraphicsPipeline(pass->getPipelineState());
+		rapi.setStencilRef(pass->getStencilRefValue());
 	}
 
 	void RendererUtility::setComputePass(const SPtr<MaterialCore>& material, UINT32 passIdx)
 	{
 		RenderAPICore& rapi = RenderAPICore::instance();
-		SPtr<PassCore> pass = material->getPass(passIdx);
 
-		if(pass->hasComputeProgram())
-			rapi.bindGpuProgram(pass->getComputeProgram());
-		else
-			rapi.unbindGpuProgram(GPT_COMPUTE_PROGRAM);
+		SPtr<PassCore> pass = material->getPass(passIdx);
+		rapi.setComputePipeline(pass->getComputeProgram());
 	}
 
 	void RendererUtility::setPassParams(const SPtr<GpuParamsSetCore>& params, UINT32 passIdx)