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

Getting rid of the old way of setting GPU parameters and moving towards the new single-object approach (WIP - DX11 only for now)
Updated sampler state overrides so they work with the new GPU parameter design

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

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

@@ -29,11 +29,9 @@ namespace BansheeEngine
 
 		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 numGpuParamBinds; /**< How many times were GPU parameters 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 numResourceWrites; /**< How many times were GPU resources written to. */
 		UINT32 numResourceReads; /**< How many times were GPU resources read from. */

+ 6 - 85
Source/BansheeCore/Include/BsRenderAPI.h

@@ -34,20 +34,8 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT RenderAPI
 	{
 	public:
-		/** @see RenderAPICore::setTexture() */
-		static void setTexture(CoreAccessor& accessor, GpuProgramType gptype, UINT16 texUnit, const SPtr<Texture>& texture);
-
-		/** @see RenderAPICore::setLoadStoreTexture() */
-		static void setLoadStoreTexture(CoreAccessor& accessor, GpuProgramType gptype, UINT16 texUnit,
-			const SPtr<Texture>& texture, const TextureSurface& surface);
-
-		/** @see RenderAPICore::setBuffer() */
-		static void setBuffer(CoreAccessor& accessor, GpuProgramType gptype, UINT16 unit, const SPtr<GpuBuffer>& buffer,
-			bool loadStore = false);
-
-		/** @see RenderAPICore::setSamplerState() */
-		static void setSamplerState(CoreAccessor& accessor, GpuProgramType gptype, UINT16 texUnit, 
-			const SPtr<SamplerState>& samplerState);
+		/** @see RenderAPICore::setGpuParams() */
+		static void setGpuParams(CoreAccessor& accessor, const SPtr<GpuParams>& gpuParams);
 
 		/** @see RenderAPICore::setGraphicsPipeline() */
 		static void setGraphicsPipeline(CoreAccessor& accessor, const SPtr<GpuPipelineState>& pipelineState);
@@ -215,19 +203,11 @@ namespace BansheeEngine
 		virtual const String& getShadingLanguageName() const = 0;
 
 		/**
-		 * Sets a sampler state for the specified texture unit. Make sure to assign the sampler state after the texture
-		 * has been assigned, as certain APIs will reset sampler state on texture bind.
-		 *
-		 * @param[in]	gptype			Determines to which GPU program slot to bind the sampler state.
-		 * @param[in]	texUnit			Texture unit index to bind the state to.
-		 * @param[in]	samplerState	Sampler 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 or compute operations.
-		 *
-		 * @see		SamplerState
+		 * Applies a set of parameters that control execution of all currently bound GPU programs. These are the uniforms
+		 * like textures, samplers, or uniform buffers. Caller is expected to ensure the provided parameters actually
+		 * match the currently bound programs.
 		 */
-		virtual void setSamplerState(GpuProgramType gptype, UINT16 texUnit, const SPtr<SamplerStateCore>& samplerState, 
+		virtual void setGpuParams(const SPtr<GpuParamsCore>& gpuParams, 
 			const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
 		/**
@@ -254,49 +234,6 @@ namespace BansheeEngine
 		virtual void setComputePipeline(const SPtr<GpuProgramCore>& computeProgram,
 			const SPtr<CommandBuffer>& commandBuffer = nullptr) = 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.
-		 *
-		 * @param[in]	gptype			Determines to which GPU program slot to bind the texture.
-		 * @param[in]	texUnit			Texture unit index to bind the texture to.
-		 * @param[in]	texture			Texture to bind.
-		 * @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.
-		 */
-		virtual void setTexture(GpuProgramType gptype, UINT16 texUnit, const SPtr<TextureCore>& texture,
-			const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
-
-		/**	
-		 * Binds a texture that can be used for random load/store operations from a GPU program. 
-		 *
-		 * @param[in]	gptype			Determines to which GPU program slot to bind the texture.
-		 * @param[in]	texUnit			Texture unit index to bind the texture to.
-		 * @param[in]	texture			Texture to bind.
-		 * @param[in]	surface			Determines which surface of the texture to bind.
-		 * @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.
-		 */
-		virtual void setLoadStoreTexture(GpuProgramType gptype, UINT16 texUnit, const SPtr<TextureCore>& texture, 
-			const TextureSurface& surface, const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
-
-		/**
-		 * Binds a buffer that can be used for read or write operations on the GPU.
-		 *
-		 * @param[in]	gptype			Determines to which GPU program slot to bind the buffer.
-		 * @param[in]	unit			GPU program unit index to bind the buffer to.
-		 * @param[in]	buffer			Buffer to bind.
-		 * @param[in]	loadStore		If true the buffer will be bound with support for unordered reads and writes, 
-		 *								otherwise it will only be bound for reads.
-		 * @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.
-		 */
-		virtual void setBuffer(GpuProgramType gptype, UINT16 unit, const SPtr<GpuBufferCore>& buffer, 
-			bool loadStore = false, const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
-
 		/**
 		 * Signals that rendering for a specific viewport has started. Any draw calls need to be called between beginFrame()
 		 * and endFrame(). 
@@ -377,22 +314,6 @@ namespace BansheeEngine
 		virtual void setIndexBuffer(const SPtr<IndexBufferCore>& buffer, 
 			const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
-		/**
-		 * Assigns a parameter buffer containing constants (uniforms) for use in a GPU program.
-		 *
-		 * @param[in]	gptype			Type of GPU program to bind the buffer to.
-		 * @param[in]	slot			Slot to bind the buffer to. The slot is dependant on the GPU program the buffer will
-		 *								be used with.
-		 * @param[in]	buffer			Buffer containing constants (uniforms) for use by the shader.
-		 * @param[in]	paramDesc		Description of all parameters in the buffer. Required mostly for backwards 
-		 *								compatibility.
-		 * @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.
-		 */
-		virtual void setParamBuffer(GpuProgramType gptype, UINT32 slot, const SPtr<GpuParamBlockBufferCore>& buffer, 
-			const SPtr<GpuParamDesc>& paramDesc, const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
-
 		/**
 		 * Sets the vertex declaration to use when drawing. Vertex declaration is used to decode contents of a single 
 		 * vertex in a vertex buffer.

+ 5 - 16
Source/BansheeCore/Include/BsRenderStats.h

@@ -28,8 +28,8 @@ namespace BansheeEngine
 	{
 		RenderStatsData()
 		: 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)
+		, numVertices(0), numPrimitives(0), numPipelineStateChanges(0), numGpuParamBinds(0), numVertexBufferBinds(0)
+		, numIndexBufferBinds(0)
 		{ }
 
 		UINT64 numDrawCalls;
@@ -43,11 +43,9 @@ namespace BansheeEngine
 
 		UINT64 numPipelineStateChanges;
 
-		UINT64 numTextureBinds; 
-		UINT64 numSamplerBinds; 
+		UINT64 numGpuParamBinds; 
 		UINT64 numVertexBufferBinds; 
 		UINT64 numIndexBufferBinds;
-		UINT64 numGpuParamBufferBinds;
 
 		UINT64 numResourceWrites;
 		UINT64 numResourceReads;
@@ -91,11 +89,8 @@ namespace BansheeEngine
 		/** 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++; }
-
-		/** Increments sampler state change counter indicating how many times was a sampler state bound to the pipeline. */
-		void incNumSamplerBinds() { mData.numSamplerBinds++; }
+		/** Increments GPU parameter change counter indicating how many times were GPU parameters bound to the pipeline. */
+		void incNumGpuParamBinds() { mData.numGpuParamBinds++; }
 
 		/** Increments vertex buffer change counter indicating how many times was a vertex buffer bound to the pipeline. */
 		void incNumVertexBufferBinds() { mData.numVertexBufferBinds++; }
@@ -103,12 +98,6 @@ namespace BansheeEngine
 		/** Increments index buffer change counter indicating how many times was a index buffer bound to the pipeline. */
 		void incNumIndexBufferBinds() { mData.numIndexBufferBinds++; }
 
-		/** 
-		 * Increments GPU parameter buffer change counter indicating how many times was a GPU parameter buffer bound to the 
-		 * pipeline.
-		 */
-		void incNumGpuParamBufferBinds() { mData.numGpuParamBufferBinds++; }
-
 		/**
 		 * Increments created GPU resource counter. 
 		 *

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

@@ -148,11 +148,9 @@ namespace BansheeEngine
 		
 		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.numGpuParamBinds = (UINT32)(sample.endStats.numGpuParamBinds - sample.startStats.numGpuParamBinds);
 		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.numResourceWrites = (UINT32)(sample.endStats.numResourceWrites - sample.startStats.numResourceWrites);
 		reportSample.numResourceReads = (UINT32)(sample.endStats.numResourceReads - sample.startStats.numResourceReads);

+ 3 - 24
Source/BansheeCore/Source/BsRenderAPI.cpp

@@ -17,31 +17,10 @@ using namespace std::placeholders;
 
 namespace BansheeEngine 
 {
-	void RenderAPI::setTexture(CoreAccessor& accessor, GpuProgramType gptype, UINT16 unit, const SPtr<Texture> &texPtr)
+	void RenderAPI::setGpuParams(CoreAccessor& accessor, const SPtr<GpuParams>& gpuParams)
 	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setTexture, RenderAPICore::instancePtr(), gptype, unit, 
-			texPtr->getCore(), nullptr));
-	}
-
-	void RenderAPI::setLoadStoreTexture(CoreAccessor& accessor, GpuProgramType gptype, UINT16 unit, 
-		const SPtr<Texture>& texPtr, const TextureSurface& surface)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setLoadStoreTexture, RenderAPICore::instancePtr(), gptype, unit, 
-			texPtr->getCore(), surface, nullptr));
-	}
-
-	void RenderAPI::setBuffer(CoreAccessor& accessor, GpuProgramType gptype, UINT16 unit, const SPtr<GpuBuffer>& buffer,
-		bool loadStore)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setBuffer, RenderAPICore::instancePtr(), gptype, unit, 
-			buffer->getCore(), loadStore, nullptr));
-	}
-
-	void RenderAPI::setSamplerState(CoreAccessor& accessor, GpuProgramType gptype, UINT16 texUnit, 
-		const SPtr<SamplerState>& samplerState)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setSamplerState, RenderAPICore::instancePtr(), gptype, texUnit, 
-			samplerState->getCore(), nullptr));
+		accessor.queueCommand(std::bind(&RenderAPICore::setGpuParams, RenderAPICore::instancePtr(), gpuParams->getCore(), 
+			nullptr));
 	}
 
 	void RenderAPI::setGraphicsPipeline(CoreAccessor& accessor, const SPtr<GpuPipelineState>& pipelineState)

+ 46 - 18
Source/BansheeD3D11RenderAPI/Include/BsD3D11RenderAPI.h

@@ -32,20 +32,8 @@ namespace BansheeEngine
 		void setComputePipeline(const SPtr<GpuProgramCore>& computeProgram,
 			const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
-		/** @copydoc RenderAPICore::setSamplerState */
-		void setSamplerState(GpuProgramType gptype, UINT16 texUnit, const SPtr<SamplerStateCore>& samplerState,
-			const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
-
-		/** @copydoc RenderAPICore::setTexture */
-		void setTexture(GpuProgramType gptype, UINT16 texUnit, const SPtr<TextureCore>& texture,
-			const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
-
-		/** @copydoc RenderAPICore::setLoadStoreTexture */
-		void setLoadStoreTexture(GpuProgramType gptype, UINT16 texUnit, const SPtr<TextureCore>& texture,
-			const TextureSurface& surface, const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
-
-		/** @copydoc RenderAPICore::setBuffer */
-		void setBuffer(GpuProgramType gptype, UINT16 unit, const SPtr<GpuBufferCore>& buffer, bool loadStore = false,
+		/** @copydoc RenderAPICore::setGpuParams */
+		void setGpuParams(const SPtr<GpuParamsCore>& gpuParams, 
 			const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPICore::beginFrame */
@@ -108,10 +96,6 @@ namespace BansheeEngine
 		void swapBuffers(const SPtr<RenderTargetCore>& target,
 			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;
-
 		/** @copydoc RenderAPICore::addCommands() */
 		void addCommands(const SPtr<CommandBuffer>& commandBuffer, const SPtr<CommandBuffer>& secondary) override;
 
@@ -161,6 +145,50 @@ namespace BansheeEngine
 		/** @copydoc RenderAPICore::destroyCore */
 		void destroyCore() override;
 
+		/**
+		 * Sets a sampler state for the specified texture unit. 
+		 *
+		 * @param[in]	gptype			Determines to which GPU program slot to bind the sampler state.
+		 * @param[in]	texUnit			Texture unit index to bind the state to.
+		 * @param[in]	samplerState	Sampler state to bind, or null to unbind.
+		 *
+		 * @see		SamplerState
+		 */
+		void setSamplerState(GpuProgramType gptype, UINT16 texUnit, const SPtr<SamplerStateCore>& samplerState);
+
+		/**
+		 * 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.
+		 *
+		 * @param[in]	gptype			Determines to which GPU program slot to bind the texture.
+		 * @param[in]	texUnit			Texture unit index to bind the texture to.
+		 * @param[in]	texture			Texture to bind.
+		 */
+		void setTexture(GpuProgramType gptype, UINT16 texUnit, const SPtr<TextureCore>& texture);
+
+		/**	
+		 * Binds a texture that can be used for random load/store operations from a GPU program. 
+		 *
+		 * @param[in]	gptype			Determines to which GPU program slot to bind the texture.
+		 * @param[in]	texUnit			Texture unit index to bind the texture to.
+		 * @param[in]	texture			Texture to bind.
+		 * @param[in]	surface			Determines which surface of the texture to bind.
+		 */
+		void setLoadStoreTexture(GpuProgramType gptype, UINT16 texUnit, const SPtr<TextureCore>& texture, 
+			const TextureSurface& surface);
+
+		/**
+		 * Binds a buffer that can be used for read or write operations on the GPU.
+		 *
+		 * @param[in]	gptype			Determines to which GPU program slot to bind the buffer.
+		 * @param[in]	unit			GPU program unit index to bind the buffer to.
+		 * @param[in]	buffer			Buffer to bind.
+		 * @param[in]	loadStore		If true the buffer will be bound with support for unordered reads and writes, 
+		 *								otherwise it will only be bound for reads.
+		 */
+		void setBuffer(GpuProgramType gptype, UINT16 unit, const SPtr<GpuBufferCore>& buffer, 
+			bool loadStore = false);
+
 		/**
 		 * Creates or retrieves a proper input layout depending on the currently set vertex shader and vertex buffer.
 		 *

+ 222 - 262
Source/BansheeD3D11RenderAPI/Source/BsD3D11RenderAPI.cpp

@@ -215,56 +215,6 @@ namespace BansheeEngine
 		RenderAPICore::destroyCore();
 	}
 
-	void D3D11RenderAPI::setSamplerState(GpuProgramType gptype, UINT16 texUnit, const SPtr<SamplerStateCore>& samplerState,
-		const SPtr<CommandBuffer>& commandBuffer)
-	{
-		auto executeRef = [&](GpuProgramType gptype, UINT16 texUnit, const SPtr<SamplerStateCore>& samplerState)
-		{
-			THROW_IF_NOT_CORE_THREAD;
-
-			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));
-			}
-
-		};
-
-		if (commandBuffer == nullptr)
-			executeRef(gptype, texUnit, samplerState);
-		else
-		{
-			auto execute = [=]() { executeRef(gptype, texUnit, samplerState); };
-
-			SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
-			cb->queueCommand(execute);
-		}
-
-		BS_INC_RENDER_STAT(NumSamplerBinds);
-	}
-
 	void D3D11RenderAPI::setGraphicsPipeline(const SPtr<GpuPipelineStateCore>& pipelineState,
 		const SPtr<CommandBuffer>& commandBuffer)
 	{
@@ -391,197 +341,265 @@ namespace BansheeEngine
 		BS_INC_RENDER_STAT(NumPipelineStateChanges);
 	}
 
-	void D3D11RenderAPI::setTexture(GpuProgramType gptype, UINT16 unit, const SPtr<TextureCore>& texPtr, 
-		const SPtr<CommandBuffer>& commandBuffer)
+	void D3D11RenderAPI::setGpuParams(const SPtr<GpuParamsCore>& gpuParams, const SPtr<CommandBuffer>& commandBuffer)
 	{
-		auto executeRef = [&](GpuProgramType gptype, UINT16 unit, const SPtr<TextureCore>& texPtr)
+		auto executeRef = [&](const SPtr<GpuParamsCore>& gpuParams)
 		{
 			THROW_IF_NOT_CORE_THREAD;
 
-			ID3D11ShaderResourceView* viewArray[1];
-			if (texPtr != nullptr)
+			bs_frame_mark();
 			{
-				D3D11TextureCore* d3d11Texture = static_cast<D3D11TextureCore*>(texPtr.get());
-				viewArray[0] = d3d11Texture->getSRV();
-			}
-			else
-				viewArray[0] = nullptr;
+				FrameVector<ID3D11ShaderResourceView*> srvs(8);
+				FrameVector<ID3D11UnorderedAccessView*> uavs(8);
+				FrameVector<ID3D11Buffer*> constBuffers(8);
+				FrameVector<ID3D11SamplerState*> samplers(8);
 
-			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));
-			}
-		};
+				auto populateViews = [&](GpuProgramType type)
+				{
+					srvs.clear();
+					uavs.clear();
+					constBuffers.clear();
+					samplers.clear();
 
-		if (commandBuffer == nullptr)
-			executeRef(gptype, unit, texPtr);
-		else
-		{
-			auto execute = [=]() { executeRef(gptype, unit, texPtr); };
+					SPtr<GpuParamDesc> paramDesc = gpuParams->getParamDesc(type);
+					if (paramDesc == nullptr)
+						return;
 
-			SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
-			cb->queueCommand(execute);
-		}
+					for (auto iter = paramDesc->textures.begin(); iter != paramDesc->textures.end(); ++iter)
+					{
+						UINT32 slot = iter->second.slot;
+						SPtr<TextureCore> texture = gpuParams->getTexture(iter->second.set, slot);
 
-		BS_INC_RENDER_STAT(NumTextureBinds);
-	}
+						while (slot >= (UINT32)srvs.size())
+							srvs.push_back(nullptr);
 
-	void D3D11RenderAPI::setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, const SPtr<TextureCore>& texPtr,
-		const TextureSurface& surface, const SPtr<CommandBuffer>& commandBuffer)
-	{
-		auto executeRef = [&](GpuProgramType gptype, UINT16 unit, const SPtr<TextureCore>& texPtr,
-			const TextureSurface& surface)
-		{
-			THROW_IF_NOT_CORE_THREAD;
+						if (texture != nullptr)
+						{
+							D3D11TextureCore* d3d11Texture = static_cast<D3D11TextureCore*>(texture.get());
+							srvs[slot] = d3d11Texture->getSRV();
+						}
+					}
 
-			ID3D11UnorderedAccessView* viewArray[1];
-			if (texPtr != nullptr)
-			{
-				D3D11TextureCore* d3d11Texture = static_cast<D3D11TextureCore*>(texPtr.get());
-				SPtr<TextureView> texView = TextureCore::requestView(texPtr, surface.mipLevel, 1,
-					surface.arraySlice, surface.numArraySlices, GVU_RANDOMWRITE);
+					for (auto iter = paramDesc->buffers.begin(); iter != paramDesc->buffers.end(); ++iter)
+					{
+						UINT32 slot = iter->second.slot;
+						SPtr<GpuBufferCore> buffer = gpuParams->getBuffer(iter->second.set, slot);
+
+						bool isLoadStore = iter->second.type != GPOT_BYTE_BUFFER &&
+							iter->second.type != GPOT_STRUCTURED_BUFFER;
+
+						if (!isLoadStore)
+						{
+							while (slot >= (UINT32)srvs.size())
+								srvs.push_back(nullptr);
+
+							if (buffer != nullptr)
+							{
+								D3D11GpuBufferCore* d3d11buffer = static_cast<D3D11GpuBufferCore*>(buffer.get());
+								srvs[slot] = d3d11buffer->getSRV();
+							}
+						}
+						else
+						{
+							while (slot >= (UINT32)uavs.size())
+								uavs.push_back(nullptr);
+
+							if (buffer != nullptr)
+							{
+								D3D11GpuBufferCore* d3d11buffer = static_cast<D3D11GpuBufferCore*>(buffer.get());
+								uavs[slot] = d3d11buffer->getUAV();
+							}
+						}
+					}
 
-				D3D11TextureView* d3d11texView = static_cast<D3D11TextureView*>(texView.get());
-				viewArray[0] = d3d11texView->getUAV();
+					for (auto iter = paramDesc->loadStoreTextures.begin(); iter != paramDesc->loadStoreTextures.end(); ++iter)
+					{
+						UINT32 slot = iter->second.slot;
 
-				if (mBoundUAVs[unit].second != nullptr)
-					mBoundUAVs[unit].first->releaseView(mBoundUAVs[unit].second);
+						SPtr<TextureCore> texture = gpuParams->getLoadStoreTexture(iter->second.set, slot);
+						const TextureSurface& surface = gpuParams->getLoadStoreSurface(iter->second.set, slot);
 
-				mBoundUAVs[unit] = std::make_pair(texPtr, texView);
-			}
-			else
-			{
-				viewArray[0] = nullptr;
+						while (slot >= (UINT32)uavs.size())
+							uavs.push_back(nullptr);
 
-				if (mBoundUAVs[unit].second != nullptr)
-					mBoundUAVs[unit].first->releaseView(mBoundUAVs[unit].second);
+						if (texture != nullptr)
+						{
+							SPtr<TextureView> texView = TextureCore::requestView(texture, surface.mipLevel, 1,
+								surface.arraySlice, surface.numArraySlices, GVU_RANDOMWRITE);
 
-				mBoundUAVs[unit] = std::pair<SPtr<TextureCore>, SPtr<TextureView>>();
-			}
+							D3D11TextureView* d3d11texView = static_cast<D3D11TextureView*>(texView.get());
+							uavs[slot] = d3d11texView->getUAV();
 
-			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
-				LOGERR("Unsupported gpu program type: " + toString(gptype));
-		};
+							if (mBoundUAVs[slot].second != nullptr)
+								mBoundUAVs[slot].first->releaseView(mBoundUAVs[slot].second);
 
-		if (commandBuffer == nullptr)
-			executeRef(gptype, unit, texPtr, surface);
-		else
-		{
-			auto execute = [=]() { executeRef(gptype, unit, texPtr, surface); };
+							mBoundUAVs[slot] = std::make_pair(texture, texView);
+						}
+						else
+						{
+							uavs[slot] = nullptr;
 
-			SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
-			cb->queueCommand(execute);
-		}
+							if (mBoundUAVs[slot].second != nullptr)
+								mBoundUAVs[slot].first->releaseView(mBoundUAVs[slot].second);
 
-		BS_INC_RENDER_STAT(NumTextureBinds);
-	}
+							mBoundUAVs[slot] = std::pair<SPtr<TextureCore>, SPtr<TextureView>>();
+						}
+					}
 
-	void D3D11RenderAPI::setBuffer(GpuProgramType gptype, UINT16 unit, const SPtr<GpuBufferCore>& buffer, bool loadStore, 
-		const SPtr<CommandBuffer>& commandBuffer)
-	{
-		auto executeRef = [&](GpuProgramType gptype, UINT16 unit, const SPtr<GpuBufferCore>& buffer, bool loadStore)
-		{
-			THROW_IF_NOT_CORE_THREAD;
+					for (auto iter = paramDesc->samplers.begin(); iter != paramDesc->samplers.end(); ++iter)
+					{
+						UINT32 slot = iter->second.slot;
+						SPtr<SamplerStateCore> samplerState = gpuParams->getSamplerState(iter->second.set, slot);
 
-			if (!loadStore)
-			{
-				ID3D11ShaderResourceView* viewArray[1];
-				if (buffer != nullptr)
-				{
-					D3D11GpuBufferCore* d3d11buffer = static_cast<D3D11GpuBufferCore*>(buffer.get());
-					viewArray[0] = d3d11buffer->getSRV();
-				}
-				else
-					viewArray[0] = nullptr;
+						while (slot >= (UINT32)samplers.size())
+							samplers.push_back(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));
-				}
-			}
-			else
-			{
-				ID3D11UnorderedAccessView* viewArray[1];
-				if (buffer != nullptr)
-				{
-					D3D11GpuBufferCore* d3d11buffer = static_cast<D3D11GpuBufferCore*>(buffer.get());
-					viewArray[0] = d3d11buffer->getUAV();
-				}
-				else
-					viewArray[0] = nullptr;
+						if (samplerState == nullptr)
+							samplerState = SamplerStateCore::getDefault();
 
-				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)
+						D3D11SamplerStateCore* d3d11SamplerState = 
+							static_cast<D3D11SamplerStateCore*>(const_cast<SamplerStateCore*>(samplerState.get()));
+						samplers[slot] = d3d11SamplerState->getInternal();
+					}
+
+					for (auto iter = paramDesc->paramBlocks.begin(); iter != paramDesc->paramBlocks.end(); ++iter)
+					{
+						UINT32 slot = iter->second.slot;
+						SPtr<GpuParamBlockBufferCore> buffer = gpuParams->getParamBlockBuffer(iter->second.set, slot);
+						buffer->flushToGPU();
+
+						while (slot >= (UINT32)constBuffers.size())
+							constBuffers.push_back(nullptr);
+
+						if (buffer != nullptr)
+						{
+							const D3D11GpuParamBlockBufferCore* d3d11paramBlockBuffer =
+								static_cast<const D3D11GpuParamBlockBufferCore*>(buffer.get());
+							constBuffers[slot] = d3d11paramBlockBuffer->getD3D11Buffer();
+						}
+					}
+				};
+
+				ID3D11DeviceContext* context = mDevice->getImmediateContext();
+
+				UINT32 numSRVs = 0;
+				UINT32 numUAVs = 0;
+				UINT32 numConstBuffers = 0;
+				UINT32 numSamplers = 0;
+
+				populateViews(GPT_VERTEX_PROGRAM);
+				numSRVs = (UINT32)srvs.size();
+				numUAVs = (UINT32)uavs.size();
+				numConstBuffers = (UINT32)constBuffers.size();
+				numSamplers = (UINT32)samplers.size();
+
+				if(numSRVs > 0)
+					context->VSSetShaderResources(0, numSRVs, srvs.data());
+
+				if(numUAVs > 0)
 				{
-					mDevice->getImmediateContext()->CSSetUnorderedAccessViews(unit, 1, viewArray, nullptr);
+					context->OMSetRenderTargetsAndUnorderedAccessViews(D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr,
+						nullptr, 0, numUAVs, uavs.data(), nullptr);
 				}
-				else
-					BS_EXCEPT(InvalidParametersException, "Unsupported gpu program type: " + toString(gptype));
+
+				if (numConstBuffers > 0)
+					context->VSSetConstantBuffers(0, numConstBuffers, constBuffers.data());
+
+				if (numSamplers > 0)
+					context->VSSetSamplers(0, numSamplers, samplers.data());
+
+				populateViews(GPT_FRAGMENT_PROGRAM);
+				numSRVs = (UINT32)srvs.size();
+				numConstBuffers = (UINT32)constBuffers.size();
+				numSamplers = (UINT32)samplers.size();
+
+				if (numSRVs > 0)
+					context->PSSetShaderResources(0, numSRVs, srvs.data());
+
+				if (numConstBuffers > 0)
+					context->PSSetConstantBuffers(0, numConstBuffers, constBuffers.data());
+
+				if (numSamplers > 0)
+					context->PSSetSamplers(0, numSamplers, samplers.data());
+
+				populateViews(GPT_GEOMETRY_PROGRAM);
+				numSRVs = (UINT32)srvs.size();
+				numConstBuffers = (UINT32)constBuffers.size();
+				numSamplers = (UINT32)samplers.size();
+
+				if (numSRVs > 0)
+					context->GSSetShaderResources(0, numSRVs, srvs.data());
+
+				if (numConstBuffers > 0)
+					context->GSSetConstantBuffers(0, numConstBuffers, constBuffers.data());
+
+				if (numSamplers > 0)
+					context->GSSetSamplers(0, numSamplers, samplers.data());
+
+				populateViews(GPT_HULL_PROGRAM);
+				numSRVs = (UINT32)srvs.size();
+				numConstBuffers = (UINT32)constBuffers.size();
+				numSamplers = (UINT32)samplers.size();
+
+				if (numSRVs > 0)
+					context->HSSetShaderResources(0, numSRVs, srvs.data());
+
+				if (numConstBuffers > 0)
+					context->HSSetConstantBuffers(0, numConstBuffers, constBuffers.data());
+
+				if (numSamplers > 0)
+					context->HSSetSamplers(0, numSamplers, samplers.data());
+
+				populateViews(GPT_DOMAIN_PROGRAM);
+				numSRVs = (UINT32)srvs.size();
+				numConstBuffers = (UINT32)constBuffers.size();
+				numSamplers = (UINT32)samplers.size();
+
+				if (numSRVs > 0)
+					context->DSSetShaderResources(0, numSRVs, srvs.data());
+
+				if (numConstBuffers > 0)
+					context->DSSetConstantBuffers(0, numConstBuffers, constBuffers.data());
+
+				if (numSamplers > 0)
+					context->DSSetSamplers(0, numSamplers, samplers.data());
+
+				populateViews(GPT_COMPUTE_PROGRAM);
+				numSRVs = (UINT32)srvs.size();
+				numUAVs = (UINT32)uavs.size();
+				numConstBuffers = (UINT32)constBuffers.size();
+				numSamplers = (UINT32)samplers.size();
+
+				if (numSRVs > 0)
+					context->CSSetShaderResources(0, numSRVs, srvs.data());
+
+				if(numUAVs > 0)
+					context->CSSetUnorderedAccessViews(0, numUAVs, uavs.data(), nullptr);
+
+				if (numConstBuffers > 0)
+					context->CSSetConstantBuffers(0, numConstBuffers, constBuffers.data());
+
+				if (numSamplers > 0)
+					context->CSSetSamplers(0, numSamplers, samplers.data());
+
 			}
+			bs_frame_clear();
+
+			if (mDevice->hasError())
+				BS_EXCEPT(RenderingAPIException, "Failed to set GPU parameters: " + mDevice->getErrorDescription());
 		};
 
 		if (commandBuffer == nullptr)
-			executeRef(gptype, unit, buffer, loadStore);
+			executeRef(gpuParams);
 		else
 		{
-			auto execute = [=]() { executeRef(gptype, unit, buffer, loadStore); };
+			auto execute = [=]() { executeRef(gpuParams); };
 
 			SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
 			cb->queueCommand(execute);
 		}
 
-		BS_INC_RENDER_STAT(NumTextureBinds);
+		BS_INC_RENDER_STAT(NumGpuParamBinds);
 	}
 
 	void D3D11RenderAPI::beginFrame(const SPtr<CommandBuffer>& commandBuffer)
@@ -736,64 +754,6 @@ namespace BansheeEngine
 		}
 	}
 
-	void D3D11RenderAPI::setParamBuffer(GpuProgramType gptype, UINT32 slot, const SPtr<GpuParamBlockBufferCore>& buffer, 
-		const SPtr<GpuParamDesc>& paramDesc, const SPtr<CommandBuffer>& commandBuffer)
-	{
-		auto executeRef = [&](GpuProgramType gptype, UINT32 slot, const SPtr<GpuParamBlockBufferCore>& buffer,
-			const SPtr<GpuParamDesc>& paramDesc)
-		{
-			THROW_IF_NOT_CORE_THREAD;
-
-			ID3D11Buffer* bufferArray[1];
-
-			if (buffer != nullptr)
-			{
-				const D3D11GpuParamBlockBufferCore* d3d11paramBlockBuffer =
-					static_cast<const D3D11GpuParamBlockBufferCore*>(buffer.get());
-				bufferArray[0] = d3d11paramBlockBuffer->getD3D11Buffer();
-			}
-			else
-				bufferArray[0] = nullptr;
-
-			switch (gptype)
-			{
-			case GPT_VERTEX_PROGRAM:
-				mDevice->getImmediateContext()->VSSetConstantBuffers(slot, 1, bufferArray);
-				break;
-			case GPT_FRAGMENT_PROGRAM:
-				mDevice->getImmediateContext()->PSSetConstantBuffers(slot, 1, bufferArray);
-				break;
-			case GPT_GEOMETRY_PROGRAM:
-				mDevice->getImmediateContext()->GSSetConstantBuffers(slot, 1, bufferArray);
-				break;
-			case GPT_HULL_PROGRAM:
-				mDevice->getImmediateContext()->HSSetConstantBuffers(slot, 1, bufferArray);
-				break;
-			case GPT_DOMAIN_PROGRAM:
-				mDevice->getImmediateContext()->DSSetConstantBuffers(slot, 1, bufferArray);
-				break;
-			case GPT_COMPUTE_PROGRAM:
-				mDevice->getImmediateContext()->CSSetConstantBuffers(slot, 1, bufferArray);
-				break;
-			}
-
-			if (mDevice->hasError())
-				BS_EXCEPT(RenderingAPIException, "Failed to setParamBuffer: " + mDevice->getErrorDescription());
-		};
-
-		if (commandBuffer == nullptr)
-			executeRef(gptype, slot,buffer, paramDesc);
-		else
-		{
-			auto execute = [=]() { executeRef(gptype, slot, buffer, paramDesc); };
-
-			SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
-			cb->queueCommand(execute);
-		}
-
-		BS_INC_RENDER_STAT(NumGpuParamBufferBinds);
-	}
-
 	void D3D11RenderAPI::draw(UINT32 vertexOffset, UINT32 vertexCount, UINT32 instanceCount, 
 		const SPtr<CommandBuffer>& commandBuffer)
 	{

+ 2 - 2
Source/BansheeEditor/Source/BsGizmoManager.cpp

@@ -1181,7 +1181,7 @@ namespace BansheeEngine
 					mIconMaterial.texture[passIdx].set(curRenderData.texture);
 
 					SPtr<GpuParamsCore> params = mIconMaterial.params->getGpuParams(passIdx);
-					gRendererUtility().setGpuParams(GPT_FRAGMENT_PROGRAM, params);
+					rapi.setGpuParams(params);
 
 					rapi.drawIndexed(curIndexOffset, curRenderData.count * 6, mesh->getVertexOffset(), curRenderData.count * 4);
 					curIndexOffset += curRenderData.count * 6;
@@ -1201,7 +1201,7 @@ namespace BansheeEngine
 				mAlphaPickingMaterial.texture.set(curRenderData.texture);
 
 				SPtr<GpuParamsCore> params = mAlphaPickingMaterial.params->getGpuParams();
-				gRendererUtility().setGpuParams(GPT_FRAGMENT_PROGRAM, params);
+				rapi.setGpuParams(params);
 
 				rapi.drawIndexed(curIndexOffset, curRenderData.count * 6, mesh->getVertexOffset(), curRenderData.count * 4);
 				curIndexOffset += curRenderData.count * 6;

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

@@ -231,11 +231,9 @@ namespace BansheeEngine
 		GUILabel* mGPUObjectsDestroyedLbl;
 		GUILabel* mGPUResourceWritesLbl;
 		GUILabel* mGPUResourceReadsLbl;
-		GUILabel* mGPUTextureBindsLbl;
-		GUILabel* mGPUSamplerBindsLbl;
+		GUILabel* mGPUParamBindsLbl;
 		GUILabel* mGPUVertexBufferBindsLbl;
 		GUILabel* mGPUIndexBufferBindsLbl;
-		GUILabel* mGPUGPUProgramBufferBindsLbl;
 
 		HString mGPUFrameNumStr;
 		HString mGPUTimeStr;
@@ -252,11 +250,9 @@ namespace BansheeEngine
 		HString mGPUObjectsDestroyedStr;
 		HString mGPUResourceWritesStr;
 		HString mGPUResourceReadsStr;
-		HString mGPUTextureBindsStr;
-		HString mGPUSamplerBindsStr;
+		HString mGPUParamBindsStr;
 		HString mGPUVertexBufferBindsStr;
 		HString mGPUIndexBufferBindsStr;
-		HString mGPUGPUProgramBufferBindsStr;
 
 		Vector<BasicRow> mBasicRows;
 		Vector<PreciseRow> mPreciseRows;

+ 0 - 8
Source/BansheeEngine/Include/BsRendererUtility.h

@@ -60,14 +60,6 @@ namespace BansheeEngine
 		 */
 		void setPassParams(const SPtr<GpuParamsSetCore>& params, UINT32 passIdx = 0);
 
-		/**
-		 * Sets parameters (textures, samplers, buffers) for the provided GPU program type.
-		 *
-		 * @param[in]	type		Type of the GPU program to assign the parameters to.
-		 * @param[in]	params		Parameters to assign.
-		 */
-		void setGpuParams(GpuProgramType type, const SPtr<GpuParamsCore>& params);
-
 		/**
 		 * Draws the specified mesh.
 		 *

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

@@ -463,11 +463,9 @@ namespace BansheeEngine
 		mGPUObjectsDestroyedStr = HEString(L"__ProfOvObjsDestroyed", L"Objects destroyed: {0}");
 		mGPUResourceWritesStr = HEString(L"__ProfOvResWrites", L"Resource writes: {0}");
 		mGPUResourceReadsStr = HEString(L"__ProfOvResReads", L"Resource reads: {0}");
-		mGPUTextureBindsStr = HEString(L"__ProfOvTexBinds", L"Texture binds: {0}");
-		mGPUSamplerBindsStr = HEString(L"__ProfOvSampBinds", L"Sampler binds: {0}");
+		mGPUParamBindsStr = HEString(L"__ProfOvGpuParamBinds", L"GPU parameter binds: {0}");
 		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}");
 
 		mGPUFrameNumLbl = GUILabel::create(mGPUFrameNumStr, GUIOptions(GUIOption::fixedWidth(200)));
 		mGPUTimeLbl = GUILabel::create(mGPUTimeStr, GUIOptions(GUIOption::fixedWidth(200)));
@@ -484,11 +482,9 @@ namespace BansheeEngine
 		mGPUObjectsDestroyedLbl = GUILabel::create(mGPUObjectsDestroyedStr, GUIOptions(GUIOption::fixedWidth(200)));
 		mGPUResourceWritesLbl = GUILabel::create(mGPUResourceWritesStr, GUIOptions(GUIOption::fixedWidth(200)));
 		mGPUResourceReadsLbl = GUILabel::create(mGPUResourceReadsStr, GUIOptions(GUIOption::fixedWidth(200)));
-		mGPUTextureBindsLbl = GUILabel::create(mGPUTextureBindsStr, GUIOptions(GUIOption::fixedWidth(200)));
-		mGPUSamplerBindsLbl = GUILabel::create(mGPUSamplerBindsStr, GUIOptions(GUIOption::fixedWidth(200)));
+		mGPUParamBindsLbl = GUILabel::create(mGPUParamBindsStr, GUIOptions(GUIOption::fixedWidth(200)));
 		mGPUVertexBufferBindsLbl = GUILabel::create(mGPUVertexBufferBindsStr, GUIOptions(GUIOption::fixedWidth(200)));
 		mGPUIndexBufferBindsLbl = GUILabel::create(mGPUIndexBufferBindsStr, GUIOptions(GUIOption::fixedWidth(200)));
-		mGPUGPUProgramBufferBindsLbl = GUILabel::create(mGPUGPUProgramBufferBindsStr, GUIOptions(GUIOption::fixedWidth(200)));
 
 		mGPULayoutFrameContentsLeft->addElement(mGPUFrameNumLbl);
 		mGPULayoutFrameContentsLeft->addElement(mGPUTimeLbl);
@@ -506,11 +502,9 @@ namespace BansheeEngine
 		mGPULayoutFrameContentsRight->addElement(mGPUObjectsDestroyedLbl);
 		mGPULayoutFrameContentsRight->addElement(mGPUResourceWritesLbl);
 		mGPULayoutFrameContentsRight->addElement(mGPUResourceReadsLbl);
-		mGPULayoutFrameContentsRight->addElement(mGPUTextureBindsLbl);
-		mGPULayoutFrameContentsRight->addElement(mGPUSamplerBindsLbl);
+		mGPULayoutFrameContentsRight->addElement(mGPUParamBindsLbl);
 		mGPULayoutFrameContentsRight->addElement(mGPUVertexBufferBindsLbl);
 		mGPULayoutFrameContentsRight->addElement(mGPUIndexBufferBindsLbl);
-		mGPULayoutFrameContentsRight->addElement(mGPUGPUProgramBufferBindsLbl);
 		mGPULayoutFrameContentsRight->addNewElement<GUIFlexibleSpace>();
 
 		updateCPUSampleAreaSizes();
@@ -741,11 +735,9 @@ namespace BansheeEngine
 		mGPUObjectsDestroyedStr.setParameter(0, toWString(gpuReport.frameSample.numObjectsDestroyed));
 		mGPUResourceWritesStr.setParameter(0, toWString(gpuReport.frameSample.numResourceWrites));
 		mGPUResourceReadsStr.setParameter(0, toWString(gpuReport.frameSample.numResourceReads));
-		mGPUTextureBindsStr.setParameter(0, toWString(gpuReport.frameSample.numTextureBinds));
-		mGPUSamplerBindsStr.setParameter(0, toWString(gpuReport.frameSample.numSamplerBinds));
+		mGPUParamBindsStr.setParameter(0, toWString(gpuReport.frameSample.numGpuParamBinds));
 		mGPUVertexBufferBindsStr.setParameter(0, toWString(gpuReport.frameSample.numVertexBufferBinds));
 		mGPUIndexBufferBindsStr.setParameter(0, toWString(gpuReport.frameSample.numIndexBufferBinds));
-		mGPUGPUProgramBufferBindsStr.setParameter(0, toWString(gpuReport.frameSample.numGpuParamBufferBinds));
 
 		mGPUFrameNumLbl->setContent(mGPUFrameNumStr);
 		mGPUTimeLbl->setContent(mGPUTimeStr);
@@ -762,11 +754,9 @@ namespace BansheeEngine
 		mGPUObjectsDestroyedLbl->setContent(mGPUObjectsDestroyedStr);
 		mGPUResourceWritesLbl->setContent(mGPUResourceWritesStr);
 		mGPUResourceReadsLbl->setContent(mGPUResourceReadsStr);
-		mGPUTextureBindsLbl->setContent(mGPUTextureBindsStr);
-		mGPUSamplerBindsLbl->setContent(mGPUSamplerBindsStr);
+		mGPUParamBindsLbl->setContent(mGPUParamBindsStr);
 		mGPUVertexBufferBindsLbl->setContent(mGPUVertexBufferBindsStr);
 		mGPUIndexBufferBindsLbl->setContent(mGPUIndexBufferBindsStr);
-		mGPUGPUProgramBufferBindsLbl->setContent(mGPUGPUProgramBufferBindsStr);
 
 		GPUSampleRowFiller sampleRowFiller(mGPUSampleRows, *mGPULayoutSampleContents, *mWidget->_getInternal());
 		for (auto& sample : gpuReport.samples)

+ 1 - 57
Source/BansheeEngine/Source/BsRendererUtility.cpp

@@ -140,64 +140,8 @@ namespace BansheeEngine
 		if (gpuParams == nullptr)
 			return;
 
-		const UINT32 numStages = 6;
-
-		for (UINT32 i = 0; i < numStages; i++)
-			setGpuParams((GpuProgramType)i, gpuParams);
-	}
-
-	void RendererUtility::setGpuParams(GpuProgramType type, const SPtr<GpuParamsCore>& params)
-	{
-		SPtr<GpuParamDesc> paramDesc = params->getParamDesc(type);
-		if (paramDesc == nullptr)
-			return;
-
 		RenderAPICore& rapi = RenderAPICore::instance();
-		for (auto iter = paramDesc->textures.begin(); iter != paramDesc->textures.end(); ++iter)
-		{
-			SPtr<TextureCore> texture = params->getTexture(iter->second.set, iter->second.slot);
-
-			rapi.setTexture(type, iter->second.slot, texture);
-		}
-
-		for (auto iter = paramDesc->loadStoreTextures.begin(); iter != paramDesc->loadStoreTextures.end(); ++iter)
-		{
-			SPtr<TextureCore> texture = params->getLoadStoreTexture(iter->second.set, iter->second.slot);
-			const TextureSurface& surface = params->getLoadStoreSurface(iter->second.set, iter->second.slot);
-
-			if (texture == nullptr)
-				rapi.setLoadStoreTexture(type, iter->second.slot, nullptr, surface);
-			else
-				rapi.setLoadStoreTexture(type, iter->second.slot, texture, surface);
-		}
-
-		for (auto iter = paramDesc->buffers.begin(); iter != paramDesc->buffers.end(); ++iter)
-		{
-			SPtr<GpuBufferCore> buffer = params->getBuffer(iter->second.set, iter->second.slot);
-
-			bool isLoadStore = iter->second.type != GPOT_BYTE_BUFFER &&
-				iter->second.type != GPOT_STRUCTURED_BUFFER;
-
-			rapi.setBuffer(type, iter->second.slot, buffer, isLoadStore);
-		}
-
-		for (auto iter = paramDesc->samplers.begin(); iter != paramDesc->samplers.end(); ++iter)
-		{
-			SPtr<SamplerStateCore> samplerState = params->getSamplerState(iter->second.set, iter->second.slot);
-
-			if (samplerState == nullptr)
-				rapi.setSamplerState(type, iter->second.slot, SamplerStateCore::getDefault());
-			else
-				rapi.setSamplerState(type, iter->second.slot, samplerState);
-		}
-
-		for (auto iter = paramDesc->paramBlocks.begin(); iter != paramDesc->paramBlocks.end(); ++iter)
-		{
-			SPtr<GpuParamBlockBufferCore> blockBuffer = params->getParamBlockBuffer(iter->second.set, iter->second.slot);
-			blockBuffer->flushToGPU();
-
-			rapi.setParamBuffer(type, iter->second.slot, blockBuffer, paramDesc);
-		}
+		rapi.setGpuParams(gpuParams);
 	}
 
 	void RendererUtility::draw(const SPtr<MeshCoreBase>& mesh, const SubMesh& subMesh, UINT32 numInstances)

+ 0 - 13
Source/RenderBeast/Include/BsRenderBeast.h

@@ -192,19 +192,6 @@ namespace BansheeEngine
 		 */
 		void refreshSamplerOverrides(bool force = false);
 
-		/**
-		 * Sets parameters (textures, samplers, buffers) for the currently active pass.
-		 *
-		 * @param[in]	paramsSet			Structure containing parameters for a material.
-		 * @param[in]	samplerOverrides	Optional samplers to use instead of the those in the pass parameters. Number of
-		 *									samplers must match number in pass parameters.
-		 * @param[in]	passIdx				Index of the pass whose parameters to bind.
-		 *
-		 * @note	Core thread.
-		 */
-		static void setPassParams(const SPtr<GpuParamsSetCore>& paramsSet, const MaterialSamplerOverrides* samplerOverrides, 
-			UINT32 passIdx);
-
 		// Core thread only fields
 		Vector<RendererRenderTarget> mRenderTargets;
 		UnorderedMap<const CameraCore*, RendererCamera> mCameras;

+ 1 - 0
Source/RenderBeast/Include/BsSamplerOverrides.h

@@ -33,6 +33,7 @@ namespace BansheeEngine
 		UINT32 numPasses;
 		UINT32 numOverrides;
 		UINT32 refCount;
+		bool isDirty;
 	};
 
 	/** Key used for uniquely identifying a sampler override entry. */

+ 0 - 4
Source/RenderBeast/Source/BsPostProcessing.cpp

@@ -109,10 +109,6 @@ namespace BansheeEngine
 		gRendererUtility().setPassParams(mParamsSet);
 		rapi.dispatchCompute(threadGroupCount.x, threadGroupCount.y);
 
-		// Note: This is ugly, add a better way to clear load/store textures?
-		TextureSurface blankSurface;
-		rapi.setLoadStoreTexture(GPT_COMPUTE_PROGRAM, 0, nullptr, blankSurface);
-
 		mOutput = ppInfo.histogramTex->renderTexture;
 	}
 

+ 45 - 75
Source/RenderBeast/Source/BsRenderBeast.cpp

@@ -831,12 +831,9 @@ namespace BansheeEngine
 		material->updateParamsSet(element.params, element.techniqueIdx);
 
 		if (bindPass)
-			RendererUtility::instance().setPass(material, passIdx, element.techniqueIdx);
+			gRendererUtility().setPass(material, passIdx, element.techniqueIdx);
 
-		if (element.samplerOverrides != nullptr)
-			setPassParams(element.params, element.samplerOverrides, passIdx);
-		else
-			setPassParams(element.params, nullptr, passIdx);
+		gRendererUtility().setPassParams(element.params, passIdx);
 
 		if(element.morphVertexDeclaration == nullptr)
 			gRendererUtility().draw(element.mesh, element.subMesh);
@@ -847,6 +844,7 @@ namespace BansheeEngine
 
 	void RenderBeast::refreshSamplerOverrides(bool force)
 	{
+		bool anyDirty = false;
 		for (auto& entry : mSamplerOverrides)
 		{
 			SPtr<MaterialParamsCore> materialParams = entry.first.material->_getInternalParams();
@@ -869,90 +867,62 @@ namespace BansheeEngine
 					if (samplerState != nullptr)
 						override.state = SamplerOverrideUtility::generateSamplerOverride(samplerState, mCoreOptions);
 					else
-						override.state = SamplerOverrideUtility::generateSamplerOverride(SamplerStateCore::getDefault(), mCoreOptions);;
+						override.state = SamplerOverrideUtility::generateSamplerOverride(SamplerStateCore::getDefault(), mCoreOptions);
+
+					override.originalStateHash = override.state->getProperties().getHash();
+					materialOverrides->isDirty = true;
 				}
+
+				// Dirty flag can also be set externally, so check here even though we assign it above
+				if (materialOverrides->isDirty)
+					anyDirty = true;
 			}
 		}
-	}
 
-	void RenderBeast::setPassParams(const SPtr<GpuParamsSetCore>& paramsSet, const MaterialSamplerOverrides* samplerOverrides,
-		UINT32 passIdx)
-	{
-		THROW_IF_NOT_CORE_THREAD;
+		// Early exit if possible
+		if (!anyDirty)
+			return;
 
-		RenderAPICore& rapi = RenderAPICore::instance();
-
-		struct StageData
-		{
-			GpuProgramType type;
-			SPtr<GpuParamsCore> params;
-		};
-
-		const UINT32 numStages = 6;
-
-		SPtr<GpuParamsCore> params = paramsSet->getGpuParams(passIdx);
-		for (UINT32 i = 0; i < numStages; i++)
+		UINT32 numRenderables = (UINT32)mRenderables.size();
+		for (UINT32 i = 0; i < numRenderables; i++)
 		{
-			GpuProgramType type = (GpuProgramType)i;
-
-			SPtr<GpuParamDesc> paramDesc = params->getParamDesc(type);
-			if (paramDesc == nullptr)
-				continue;
-
-			for (auto iter = paramDesc->textures.begin(); iter != paramDesc->textures.end(); ++iter)
-			{
-				SPtr<TextureCore> texture = params->getTexture(iter->second.set, iter->second.slot);
-				rapi.setTexture(type, iter->second.slot, texture);
-			}
-
-			for (auto iter = paramDesc->loadStoreTextures.begin(); iter != paramDesc->loadStoreTextures.end(); ++iter)
-			{
-				SPtr<TextureCore> texture = params->getLoadStoreTexture(iter->second.set, iter->second.slot);
-				const TextureSurface& surface = params->getLoadStoreSurface(iter->second.set, iter->second.slot);
-
-				if (texture == nullptr)
-					rapi.setLoadStoreTexture(type, iter->second.slot, nullptr, surface);
-				else
-					rapi.setLoadStoreTexture(type, iter->second.slot, texture, surface);
-			}
-
-			for (auto iter = paramDesc->buffers.begin(); iter != paramDesc->buffers.end(); ++iter)
+			for(auto& element : mRenderables[i].elements)
 			{
-				SPtr<GpuBufferCore> buffer = params->getBuffer(iter->second.set, iter->second.slot);
+				MaterialSamplerOverrides* overrides = element.samplerOverrides;
+				if(overrides != nullptr && overrides->isDirty)
+				{
+					UINT32 numPasses = element.material->getNumPasses();
+					for(UINT32 j = 0; j < numPasses; j++)
+					{
+						SPtr<GpuParamsCore> params = element.params->getGpuParams(j);
 
-				bool isLoadStore = iter->second.type != GPOT_BYTE_BUFFER &&
-					iter->second.type != GPOT_STRUCTURED_BUFFER;
+						const UINT32 numStages = 6;
+						for (UINT32 k = 0; k < numStages; k++)
+						{
+							GpuProgramType type = (GpuProgramType)k;
 
-				rapi.setBuffer(type, iter->second.slot, buffer, isLoadStore);
-			}
+							SPtr<GpuParamDesc> paramDesc = params->getParamDesc(type);
+							if (paramDesc == nullptr)
+								continue;
 
-			for (auto iter = paramDesc->paramBlocks.begin(); iter != paramDesc->paramBlocks.end(); ++iter)
-			{
-				SPtr<GpuParamBlockBufferCore> blockBuffer = params->getParamBlockBuffer(iter->second.set, iter->second.slot);
-				blockBuffer->flushToGPU();
+							for (auto& samplerDesc : paramDesc->samplers)
+							{
+								UINT32 set = samplerDesc.second.set;
+								UINT32 slot = samplerDesc.second.slot;
 
-				rapi.setParamBuffer(type, iter->second.slot, blockBuffer, paramDesc);
-			}
+								UINT32 overrideIndex = overrides->passes[j].stateOverrides[set][slot];
+								if (overrideIndex == (UINT32)-1)
+									continue;
 
-			for (auto iter = paramDesc->samplers.begin(); iter != paramDesc->samplers.end(); ++iter)
-			{
-				SPtr<SamplerStateCore> samplerState;
-
-				if (samplerOverrides != nullptr)
-				{
-					UINT32 overrideIndex = samplerOverrides->passes[passIdx].stateOverrides[iter->second.set][iter->second.slot];
-					if (overrideIndex != (UINT32)-1)
-						samplerState = samplerOverrides->overrides[overrideIndex].state;
+								params->setSamplerState(set, slot, overrides->overrides[overrideIndex].state);
+							}
+						}
+					}
 				}
-
-				if (samplerState == nullptr)
-					samplerState = params->getSamplerState(iter->second.set, iter->second.slot);
-
-				if (samplerState == nullptr)
-					rapi.setSamplerState(type, iter->second.slot, SamplerStateCore::getDefault());
-				else
-					rapi.setSamplerState(type, iter->second.slot, samplerState);
 			}
 		}
+
+		for (auto& entry : mSamplerOverrides)
+			entry.second->isDirty = false;
 	}
 }

+ 4 - 2
Source/RenderBeast/Source/BsSamplerOverrides.cpp

@@ -49,13 +49,14 @@ namespace BansheeEngine
 					samplerState = SamplerStateCore::getDefault();
 
 				override.paramIdx = paramIdx;
-				override.originalStateHash = samplerState->getProperties().getHash();
-
+				
 				if (checkNeedsOverride(samplerState, options))
 					override.state = generateSamplerOverride(samplerState, options);
 				else
 					override.state = samplerState;
 
+				override.originalStateHash = override.state->getProperties().getHash();
+
 				overrideLookup[samplerParam.first] = overrideIdx;
 			}
 
@@ -131,6 +132,7 @@ namespace BansheeEngine
 			output->refCount = 0;
 			output->numPasses = numPasses;
 			output->passes = (PassSamplerOverrides*)outputData;
+			output->isDirty = true;
 			outputData += sizeof(PassSamplerOverrides) * numPasses;
 
 			slotsPerSetIter = slotsPerSet;