Kaynağa Gözat

Refactoring how GPU program parameters are assigned, in order to make it more intuitive on the core thread

BearishSun 9 yıl önce
ebeveyn
işleme
b48081c63c
43 değiştirilmiş dosya ile 462 ekleme ve 462 silme
  1. BIN
      Data/Engine/GUISkin.asset
  2. BIN
      Data/Engine/ResourceManifest.asset
  3. BIN
      Data/Engine/Shaders/PPDownsample.bsl.asset
  4. BIN
      Data/Engine/Shaders/PPEyeAdaptHistogram.bsl.asset
  5. BIN
      Data/Engine/Shaders/PPEyeAdaptHistogramReduce.bsl.asset
  6. BIN
      Data/Engine/Shaders/PPEyeAdaptation.bsl.asset
  7. BIN
      Data/Engine/Shaders/PPTonemapping.bsl.asset
  8. BIN
      Data/Engine/Shaders/PPTonemapping_1.bsl.asset
  9. BIN
      Data/Engine/Shaders/PPTonemapping_2.bsl.asset
  10. BIN
      Data/Engine/Shaders/PPTonemapping_3.bsl.asset
  11. BIN
      Data/Engine/Timestamp.asset
  12. BIN
      Data/Engine/arial.ttf.asset
  13. 5 0
      Data/Raw/Engine/Shaders/PPDownsample.bsl
  14. 5 0
      Data/Raw/Engine/Shaders/PPEyeAdaptHistogram.bsl
  15. 5 0
      Data/Raw/Engine/Shaders/PPEyeAdaptHistogramReduce.bsl
  16. 5 0
      Data/Raw/Engine/Shaders/PPEyeAdaptation.bsl
  17. 5 0
      Data/Raw/Engine/Shaders/PPTonemapping.bsl
  18. 11 0
      Source/BansheeCore/Include/BsCommonTypes.h
  19. 18 0
      Source/BansheeCore/Include/BsGpuParam.h
  20. 3 3
      Source/BansheeCore/Include/BsGpuParams.h
  21. 0 11
      Source/BansheeCore/Include/BsGpuProgram.h
  22. 10 0
      Source/BansheeCore/Include/BsMaterial.h
  23. 1 0
      Source/BansheeCore/Include/BsParamBlocks.h
  24. 8 27
      Source/BansheeCore/Include/BsRenderAPI.h
  25. 9 11
      Source/BansheeCore/Source/BsGpuParams.cpp
  26. 25 0
      Source/BansheeCore/Source/BsMaterial.cpp
  27. 2 56
      Source/BansheeCore/Source/BsRenderAPI.cpp
  28. 4 3
      Source/BansheeD3D11RenderAPI/Include/BsD3D11RenderAPI.h
  29. 33 42
      Source/BansheeD3D11RenderAPI/Source/BsD3D11RenderAPI.cpp
  30. 3 2
      Source/BansheeD3D9RenderAPI/Include/BsD3D9RenderAPI.h
  31. 27 44
      Source/BansheeD3D9RenderAPI/Source/BsD3D9RenderAPI.cpp
  32. 2 2
      Source/BansheeEditor/Source/BsGizmoManager.cpp
  33. 4 4
      Source/BansheeEditor/Source/BsScenePicking.cpp
  34. 8 0
      Source/BansheeEngine/Include/BsRendererUtility.h
  35. 46 36
      Source/BansheeEngine/Source/BsRendererUtility.cpp
  36. 1 1
      Source/BansheeGLRenderAPI/Include/BsGLGpuParamBlockBuffer.h
  37. 3 2
      Source/BansheeGLRenderAPI/Include/BsGLRenderAPI.h
  38. 100 112
      Source/BansheeGLRenderAPI/Source/BsGLRenderAPI.cpp
  39. 27 17
      Source/RenderBeast/Include/BsLightRendering.h
  40. 1 1
      Source/RenderBeast/Include/BsRenderBeast.h
  41. 62 55
      Source/RenderBeast/Source/BsLightRendering.cpp
  42. 27 33
      Source/RenderBeast/Source/BsRenderBeast.cpp
  43. 2 0
      Source/RenderBeast/Source/BsStaticRenderableHandler.cpp

BIN
Data/Engine/GUISkin.asset


BIN
Data/Engine/ResourceManifest.asset


BIN
Data/Engine/Shaders/PPDownsample.bsl.asset


BIN
Data/Engine/Shaders/PPEyeAdaptHistogram.bsl.asset


BIN
Data/Engine/Shaders/PPEyeAdaptHistogramReduce.bsl.asset


BIN
Data/Engine/Shaders/PPEyeAdaptation.bsl.asset


BIN
Data/Engine/Shaders/PPTonemapping.bsl.asset


BIN
Data/Engine/Shaders/PPTonemapping_1.bsl.asset


BIN
Data/Engine/Shaders/PPTonemapping_2.bsl.asset


BIN
Data/Engine/Shaders/PPTonemapping_3.bsl.asset


BIN
Data/Engine/Timestamp.asset


BIN
Data/Engine/arial.ttf.asset


+ 5 - 0
Data/Raw/Engine/Shaders/PPDownsample.bsl

@@ -7,6 +7,11 @@ Parameters =
 	Texture2D 	gInputTex;
 };
 
+Blocks =
+{
+	Block Input;
+};
+
 Technique =
 {
 	Language = "HLSL11";

+ 5 - 0
Data/Raw/Engine/Shaders/PPEyeAdaptHistogram.bsl

@@ -4,6 +4,11 @@ Parameters =
 	RWTexture2D gOutputTex;
 };
 
+Blocks =
+{
+	Block Input;
+};
+
 #define NUM_BUCKETS (THREADGROUP_SIZE_X * THREADGROUP_SIZE_Y)
 
 Technique =

+ 5 - 0
Data/Raw/Engine/Shaders/PPEyeAdaptHistogramReduce.bsl

@@ -6,6 +6,11 @@ Parameters =
 	Texture2D 	gEyeAdaptationTex;
 };
 
+Blocks =
+{
+	Block Input;
+};
+
 Technique =
 {
 	Language = "HLSL11";

+ 5 - 0
Data/Raw/Engine/Shaders/PPEyeAdaptation.bsl

@@ -5,6 +5,11 @@ Parameters =
 	Texture2D 	gHistogramTex;
 };
 
+Blocks =
+{
+	Block Input;
+};
+
 Technique =
 {
 	Language = "HLSL11";

+ 5 - 0
Data/Raw/Engine/Shaders/PPTonemapping.bsl

@@ -9,6 +9,11 @@ Parameters =
 	Texture2D	gEyeAdaptationTex;
 };
 
+Blocks =
+{
+	Block Input;
+};
+
 Technique =
 {
 	Language = "HLSL11";

+ 11 - 0
Source/BansheeCore/Include/BsCommonTypes.h

@@ -141,6 +141,17 @@ namespace BansheeEngine
 		GBL_WRITE_ONLY	
 	};
 
+	/** Types of programs that may run on GPU. */
+	enum GpuProgramType
+	{
+		GPT_VERTEX_PROGRAM, /**< Vertex program. */
+		GPT_FRAGMENT_PROGRAM, /**< Fragment(pixel) program. */
+		GPT_GEOMETRY_PROGRAM, /**< Geometry program. */
+		GPT_DOMAIN_PROGRAM, /**< Domain (tesselation evaluation) program. */
+		GPT_HULL_PROGRAM, /**< Hull (tesselation control) program. */
+		GPT_COMPUTE_PROGRAM /**< Compute program. */
+	};
+
 	/**
 	 * Values that represent hardware buffer usage. These usually determine in what type of memory is buffer placed in,
 	 * however that depends on rendering API.

+ 18 - 0
Source/BansheeCore/Include/BsGpuParam.h

@@ -118,6 +118,9 @@ namespace BansheeEngine
 		 */
 		T get(UINT32 arrayIdx = 0);
 
+		/** Returns meta-data about the parameter. */
+		const GpuParamDataDesc& getDesc() const { return *mParamDesc; }
+
 		/** Checks if param is initialized. */
 		bool operator==(const nullptr_t &nullval) const
 		{
@@ -149,6 +152,9 @@ namespace BansheeEngine
 		/**	Returns the size of the struct in bytes. */
 		UINT32 getElementSize() const;
 
+		/** Returns meta-data about the parameter. */
+		const GpuParamDataDesc& getDesc() const { return *mParamDesc; }
+
 		/**	Checks if param is initialized. */
 		bool operator==(const nullptr_t &nullval) const
 		{
@@ -181,6 +187,9 @@ namespace BansheeEngine
 		/** @copydoc TGpuDataParam::get */
 		TextureType get();
 
+		/** @copydoc TGpuDataParam::getDesc */
+		const GpuParamObjectDesc& getDesc() const { return *mParamDesc; }
+
 		/** Checks if param is initialized. */
 		bool operator==(const nullptr_t &nullval) const
 		{
@@ -213,6 +222,9 @@ namespace BansheeEngine
 		/** @copydoc TGpuDataParam::get */
 		TextureType get();
 
+		/** @copydoc TGpuDataParam::getDesc */
+		const GpuParamObjectDesc& getDesc() const { return *mParamDesc; }
+
 		/**	Checks if param is initialized. */
 		bool operator==(const nullptr_t &nullval) const
 		{
@@ -245,6 +257,9 @@ namespace BansheeEngine
 		/** @copydoc TGpuDataParam::get */
 		BufferType get();
 
+		/** @copydoc TGpuDataParam::getDesc */
+		const GpuParamObjectDesc& getDesc() const { return *mParamDesc; }
+
 		/** Checks if param is initialized. */
 		bool operator==(const nullptr_t &nullval) const
 		{
@@ -277,6 +292,9 @@ namespace BansheeEngine
 		/** @copydoc TGpuDataParam::get */
 		SamplerStateType get();
 
+		/** @copydoc TGpuDataParam::getDesc */
+		const GpuParamObjectDesc& getDesc() const { return *mParamDesc; }
+
 		/**	Checks if param is initialized. */
 		bool operator==(const nullptr_t &nullval) const
 		{

+ 3 - 3
Source/BansheeCore/Include/BsGpuParams.h

@@ -84,6 +84,9 @@ namespace BansheeEngine
 		/** Checks if a parameter block with the specified name exists. */
 		bool hasParamBlock(const String& name) const;
 
+		/**	Gets a descriptor for a parameter block buffer with the specified name. */
+		GpuParamBlockDesc* getParamBlockDesc(const String& name) const;
+
 		/** Returns information that determines which texture surfaces to bind as load/store parameters. */
 		const TextureSurface& getLoadStoreSurface(UINT32 slot) const;
 
@@ -253,9 +256,6 @@ namespace BansheeEngine
 	public:
 		~GpuParamsCore() { }
 
-		/** Uploads all CPU stored parameter buffer data to the GPU buffers. */
-		void updateHardwareBuffers();
-
 		/** @copydoc GpuParamsBase::GpuParamsBase */
 		static SPtr<GpuParamsCore> create(const SPtr<GpuParamDesc>& paramDesc, bool transposeMatrices);
 

+ 0 - 11
Source/BansheeCore/Include/BsGpuProgram.h

@@ -12,17 +12,6 @@ namespace BansheeEngine
 	 *  @{
 	 */
 
-	/** Types of programs that may run on GPU. */
-	enum GpuProgramType
-	{
-		GPT_VERTEX_PROGRAM, /**< Vertex program. */
-		GPT_FRAGMENT_PROGRAM, /**< Fragment(pixel) program. */
-		GPT_GEOMETRY_PROGRAM, /**< Geometry program. */
-		GPT_DOMAIN_PROGRAM, /**< Domain (tesselation evaluation) program. */
-		GPT_HULL_PROGRAM, /**< Hull (tesselation control) program. */
-		GPT_COMPUTE_PROGRAM /**< Compute program. */
-	};
-
 	/**	GPU program profiles representing supported feature sets. */
 	enum GpuProgramProfile
 	{

+ 10 - 0
Source/BansheeCore/Include/BsMaterial.h

@@ -515,6 +515,16 @@ namespace BansheeEngine
 		/** Returns a set of parameters for all GPU programs in the specified shader pass. */
 		SPtr<PassParamsType> getPassParameters(UINT32 passIdx) const { return mParametersPerPass[passIdx]; }
 
+		/** 
+		 * Returns a set of GPU parameters for an individual GPU program of the specified pass. 
+		 *
+		 * @param[in]	passIdx		Pass in which to look the GPU program for in.
+		 * @param[in]	type		Type of the program to retrieve parameters for.
+		 * @return					GPU parameters object that can be used for setting parameters of a GPU program 
+		 *							individually. Returns null if program or pass doesn't exist.
+		 */
+		GpuParamsType getGpuParams(UINT32 passIdx, BansheeEngine::GpuProgramType type);
+
 		/**
 		 * Assign a parameter block buffer with the specified name.
 		 *

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

@@ -43,6 +43,7 @@ namespace BansheeEngine
 																															\
 		const SPtr<GpuParamBlockBufferCore>& getBuffer() const { return mBuffer; }											\
 		const GpuParamBlockDesc& getDesc() const { return mBlockDesc; }														\
+		void flushToGPU() {	mBuffer->flushToGPU(); }																		\
 																															\
 	private:																												\
 		struct META_FirstEntry {};																							\

+ 8 - 27
Source/BansheeCore/Include/BsRenderAPI.h

@@ -174,20 +174,6 @@ namespace BansheeEngine
 		 */
 		static void unbindGpuProgram(CoreAccessor& accessor, GpuProgramType gptype);
 
-		/** 
-		 * @copydoc RenderAPICore::setConstantBuffers()
-		 *
-		 * @param[in]	accessor	Accessor on which will this command be queued for execution.
-		 */
-		static void setConstantBuffers(CoreAccessor& accessor, GpuProgramType gptype, const SPtr<GpuParams>& params);
-
-		/** 
-		 * @copydoc RenderAPICore::setGpuParams()
-		 *
-		 * @param[in]	accessor	Accessor on which will this command be queued for execution.
-		 */
-		static void setGpuParams(CoreAccessor& accessor, GpuProgramType gptype, const SPtr<GpuParams>& params);
-
 		/** 
 		 * @copydoc RenderAPICore::beginFrame()
 		 *
@@ -521,21 +507,16 @@ namespace BansheeEngine
 		virtual void bindGpuProgram(const SPtr<GpuProgramCore>& prg);
 
 		/**
-		 * Binds constant(uniform) GPU program parameters. Caller must ensure these match the previously bound GPU program.
-		 *
-		 * @param[in]	gptype	GPU program slot to bind the buffer to.
-		 * @param[in]	params	Object containing the required constant buffers.
-		 */
-		virtual void setConstantBuffers(GpuProgramType gptype, const SPtr<GpuParamsCore>& params) = 0;
-
-		/** 
-		 * Binds all specified GPU program parameters (textures, buffers, samplers and constant buffers). Caller must
-		 * ensure these match the previously bound GPU program. 
+		 * Assigns a parameter buffer containing constants (uniforms) for use in a GPU program.
 		 *
-		 * @param[in]	gptype	GPU program slot to bind the buffer to.
-		 * @param[in]	params	Object containing the required parameters.
+		 * @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.
 		 */
-		virtual void setGpuParams(GpuProgramType gptype, const SPtr<GpuParamsCore>& params);
+		virtual void setParamBuffer(GpuProgramType gptype, UINT32 slot, const SPtr<GpuParamBlockBufferCore>& buffer, 
+			const GpuParamDesc& paramDesc) = 0;
 
 		/**	
 		 * Unbinds a program of a given type. 

+ 9 - 11
Source/BansheeCore/Source/BsGpuParams.cpp

@@ -125,6 +125,15 @@ UINT32 GpuParamsBase::getDataParamSize(const String& name) const
 		return nullptr;
 	}
 
+	GpuParamBlockDesc* GpuParamsBase::getParamBlockDesc(const String& name) const
+	{
+		auto paramBlockIter = mParamDesc->paramBlocks.find(name);
+		if (paramBlockIter != mParamDesc->paramBlocks.end())
+			return &paramBlockIter->second;
+
+		return nullptr;
+	}
+
 	const TextureSurface& GpuParamsBase::getLoadStoreSurface(UINT32 slot) const
 	{
 		if (slot >= mNumLoadStoreTextures)
@@ -474,17 +483,6 @@ UINT32 GpuParamsBase::getDataParamSize(const String& name) const
 		return std::static_pointer_cast<GpuParamsCore>(getThisPtr());
 	}
 
-	void GpuParamsCore::updateHardwareBuffers()
-	{
-		for (UINT32 i = 0; i < mNumParamBlocks; i++)
-		{
-			if (mParamBlockBuffers[i] != nullptr)
-			{
-				mParamBlockBuffers[i]->flushToGPU();
-			}
-		}
-	}
-
 	void GpuParamsCore::syncToCore(const CoreSyncData& data)
 	{
 		UINT32 loadStoreSurfacesSize = mNumLoadStoreTextures * sizeof(TextureSurface);

+ 25 - 0
Source/BansheeCore/Source/BsMaterial.cpp

@@ -666,6 +666,31 @@ namespace BansheeEngine
 		return createSamplerStateParam(name, gpuParams);
 	}
 
+	template<bool Core>
+	typename TMaterial<Core>::GpuParamsType TMaterial<Core>::getGpuParams(UINT32 passIdx, BansheeEngine::GpuProgramType type)
+	{
+		if (passIdx >= mParametersPerPass.size())
+			return nullptr;
+
+		switch(type)
+		{
+		case GPT_VERTEX_PROGRAM:
+			return mParametersPerPass[passIdx]->mVertParams;
+		case GPT_FRAGMENT_PROGRAM:
+			return mParametersPerPass[passIdx]->mFragParams;
+		case GPT_GEOMETRY_PROGRAM:
+			return mParametersPerPass[passIdx]->mGeomParams;
+		case GPT_HULL_PROGRAM:
+			return mParametersPerPass[passIdx]->mHullParams;
+		case GPT_DOMAIN_PROGRAM:
+			return mParametersPerPass[passIdx]->mDomainParams;
+		case GPT_COMPUTE_PROGRAM:
+			return mParametersPerPass[passIdx]->mComputeParams;
+		}
+
+		return nullptr;
+	}
+
 	template<bool Core>
 	void TMaterial<Core>::setParamBlockBuffer(const String& name, const ParamBlockPtrType& paramBlock)
 	{

+ 2 - 56
Source/BansheeCore/Source/BsRenderAPI.cpp

@@ -15,6 +15,7 @@
 #include "BsRasterizerState.h"
 #include "BsGpuParamDesc.h"
 #include "BsGpuBuffer.h"
+#include "BsGpuParamBlockBuffer.h"
 #include "BsShader.h"
 
 using namespace std::placeholders;
@@ -132,16 +133,6 @@ namespace BansheeEngine
 		accessor.queueCommand(std::bind(&RenderAPICore::unbindGpuProgram, RenderAPICore::instancePtr(), gptype));
 	}
 
-	void RenderAPI::setConstantBuffers(CoreAccessor& accessor, GpuProgramType gptype, const SPtr<GpuParams>& params)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setConstantBuffers, RenderAPICore::instancePtr(), gptype, params->getCore()));
-	}
-
-	void RenderAPI::setGpuParams(CoreAccessor& accessor, GpuProgramType gptype, const SPtr<GpuParams>& params)
-	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setGpuParams, RenderAPICore::instancePtr(), gptype, params->getCore()));
-	}
-
 	void RenderAPI::beginRender(CoreAccessor& accessor)
 	{
 		accessor.queueCommand(std::bind(&RenderAPICore::beginFrame, RenderAPICore::instancePtr()));
@@ -389,52 +380,7 @@ namespace BansheeEngine
 
         return false;
 	}
-
-	void RenderAPICore::setGpuParams(GpuProgramType gptype, const SPtr<GpuParamsCore>& params)
-	{
-		const GpuParamDesc& paramDesc = params->getParamDesc();
-
-		for (auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
-		{
-			SPtr<SamplerStateCore> samplerState = params->getSamplerState(iter->second.slot);
-
-			if (samplerState == nullptr)
-				setSamplerState(gptype, iter->second.slot, SamplerStateCore::getDefault());
-			else
-				setSamplerState(gptype, iter->second.slot, samplerState);
-		}
-
-		for (auto iter = paramDesc.textures.begin(); iter != paramDesc.textures.end(); ++iter)
-		{
-			SPtr<TextureCore> texture = params->getTexture(iter->second.slot);
-
-			setTexture(gptype, iter->second.slot, texture);
-		}
-
-		for (auto iter = paramDesc.loadStoreTextures.begin(); iter != paramDesc.loadStoreTextures.end(); ++iter)
-		{
-			SPtr<TextureCore> texture = params->getLoadStoreTexture(iter->second.slot);
-			const TextureSurface& surface = params->getLoadStoreSurface(iter->second.slot);
-
-			if (texture == nullptr)
-				setLoadStoreTexture(gptype, iter->second.slot, false, nullptr, surface);
-			else
-				setLoadStoreTexture(gptype, iter->second.slot, true, texture, surface);
-		}
-
-		for (auto iter = paramDesc.buffers.begin(); iter != paramDesc.buffers.end(); ++iter)
-		{
-			SPtr<GpuBufferCore> buffer = params->getBuffer(iter->second.slot);
-
-			bool isLoadStore = iter->second.type != GPOT_BYTE_BUFFER &&
-				iter->second.type != GPOT_STRUCTURED_BUFFER;
-
-			setBuffer(gptype, iter->second.slot, buffer, isLoadStore);
-		}
-
-		setConstantBuffers(gptype, params);
-	}
-
+	
 	void RenderAPICore::swapBuffers(const SPtr<RenderTargetCore>& target)
 	{
 		THROW_IF_NOT_CORE_THREAD;

+ 4 - 3
Source/BansheeD3D11RenderAPI/Include/BsD3D11RenderAPI.h

@@ -97,9 +97,10 @@ namespace BansheeEngine
 		/** @copydoc RenderAPICore::unbindGpuProgram */
 		void unbindGpuProgram(GpuProgramType gptype) override;
 
-		/** @copydoc RenderAPICore::setConstantBuffers */
-		void setConstantBuffers(GpuProgramType gptype, const SPtr<GpuParamsCore>& params) override;
-		
+		/** @copydoc RenderAPICore::setParamBuffer */
+		void setParamBuffer(GpuProgramType gptype, UINT32 slot, const SPtr<GpuParamBlockBufferCore>& buffer, 
+			const GpuParamDesc& paramDesc) override;
+
 		/** @copydoc RenderAPICore::setClipPlanesImpl */
 		void setClipPlanesImpl(const PlaneList& clipPlanes) override;
 

+ 33 - 42
Source/BansheeD3D11RenderAPI/Source/BsD3D11RenderAPI.cpp

@@ -614,55 +614,46 @@ namespace BansheeEngine
 		BS_INC_RENDER_STAT(NumGpuProgramBinds);
 	}
 
-	void D3D11RenderAPI::setConstantBuffers(GpuProgramType gptype, const SPtr<GpuParamsCore>& bindableParams)
+	void D3D11RenderAPI::setParamBuffer(GpuProgramType gptype, UINT32 slot, const SPtr<GpuParamBlockBufferCore>& buffer, 
+		const GpuParamDesc& paramDesc)
 	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		bindableParams->updateHardwareBuffers();
-		const GpuParamDesc& paramDesc = bindableParams->getParamDesc();
-
-		// TODO - I assign constant buffers one by one but it might be more efficient to do them all at once?
 		ID3D11Buffer* bufferArray[1];
-		for(auto iter = paramDesc.paramBlocks.begin(); iter != paramDesc.paramBlocks.end(); ++iter)
-		{
-			SPtr<GpuParamBlockBufferCore> currentBlockBuffer = bindableParams->getParamBlockBuffer(iter->second.slot);
 
-			if(currentBlockBuffer != nullptr)
-			{
-				const D3D11GpuParamBlockBufferCore* d3d11paramBlockBuffer = 
-					static_cast<const D3D11GpuParamBlockBufferCore*>(currentBlockBuffer.get());
-				bufferArray[0] = d3d11paramBlockBuffer->getD3D11Buffer();
-			}
-			else
-				bufferArray[0] = nullptr;
+		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(iter->second.slot, 1, bufferArray);
-				break;
-			case GPT_FRAGMENT_PROGRAM:
-				mDevice->getImmediateContext()->PSSetConstantBuffers(iter->second.slot, 1, bufferArray);
-				break;
-			case GPT_GEOMETRY_PROGRAM:
-				mDevice->getImmediateContext()->GSSetConstantBuffers(iter->second.slot, 1, bufferArray);
-				break;
-			case GPT_HULL_PROGRAM:
-				mDevice->getImmediateContext()->HSSetConstantBuffers(iter->second.slot, 1, bufferArray);
-				break;
-			case GPT_DOMAIN_PROGRAM:
-				mDevice->getImmediateContext()->DSSetConstantBuffers(iter->second.slot, 1, bufferArray);
-				break;
-			case GPT_COMPUTE_PROGRAM:
-				mDevice->getImmediateContext()->CSSetConstantBuffers(iter->second.slot, 1, bufferArray);
-				break;
-			};
+		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;
+		};
 
-			BS_INC_RENDER_STAT(NumGpuParamBufferBinds);
-		}
+		BS_INC_RENDER_STAT(NumGpuParamBufferBinds);
 
 		if (mDevice->hasError())
-			BS_EXCEPT(RenderingAPIException, "Failed to setConstantBuffers : " + mDevice->getErrorDescription());
+			BS_EXCEPT(RenderingAPIException, "Failed to setParamBuffer: " + mDevice->getErrorDescription());
 	}
 
 	void D3D11RenderAPI::draw(UINT32 vertexOffset, UINT32 vertexCount, UINT32 instanceCount)

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

@@ -36,8 +36,9 @@ namespace BansheeEngine
 		/** @copydoc RenderAPICore::unbindGpuProgram() */
 		void unbindGpuProgram(GpuProgramType gptype) override;
 
-		/** @copydoc RenderAPICore::setConstantBuffers() */
-		void setConstantBuffers(GpuProgramType gptype, const SPtr<GpuParamsCore>& params) override;
+		/** @copydoc RenderAPICore::setParamBuffer */
+		void setParamBuffer(GpuProgramType gptype, UINT32 slot, const SPtr<GpuParamBlockBufferCore>& buffer,
+			const GpuParamDesc& paramDesc) override;
 
 		/** @copydoc RenderAPICore::setVertexBuffers() */
 		void setVertexBuffers(UINT32 index, SPtr<VertexBufferCore>* buffers, UINT32 numBuffers) override;

+ 27 - 44
Source/BansheeD3D9RenderAPI/Source/BsD3D9RenderAPI.cpp

@@ -257,32 +257,18 @@ namespace BansheeEngine
 		RenderAPICore::unbindGpuProgram(gptype);
 	}
 
-	void D3D9RenderAPI::setConstantBuffers(GpuProgramType gptype, const SPtr<GpuParamsCore>& bindableParams)
+	void D3D9RenderAPI::setParamBuffer(GpuProgramType gptype, UINT32 slot, const SPtr<GpuParamBlockBufferCore>& buffer,
+		const GpuParamDesc& paramDesc)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		bindableParams->updateHardwareBuffers();
-		const GpuParamDesc& paramDesc = bindableParams->getParamDesc();
+		if (buffer == nullptr)
+			return;
 
 		// Read all the buffer data so we can assign it. Not the most efficient way of accessing data
 		// but it is required in order to have standardized buffer interface.
-		UnorderedMap<UINT32, UINT8*> bufferData;
-
-		for(auto& curParam : paramDesc.params)
-		{
-			UINT32 paramBlockSlot = curParam.second.paramBlockSlot;
-			auto iterFind = bufferData.find(paramBlockSlot);
-
-			if(iterFind == bufferData.end())
-			{
-				SPtr<GpuParamBlockBufferCore> paramBlock = bindableParams->getParamBlockBuffer(paramBlockSlot);
-
-				UINT8* data = (UINT8*)bs_alloc(paramBlock->getSize());
-				paramBlock->readFromGPU(data);
-
-				bufferData[paramBlockSlot] = data;
-			}
-		}
+		UINT8* uniformBufferData = (UINT8*)bs_stack_alloc(buffer->getSize());
+		buffer->readFromGPU(uniformBufferData);
 
 		HRESULT hr;
 
@@ -292,11 +278,11 @@ namespace BansheeEngine
 			{
 				for(auto iter = paramDesc.params.begin(); iter != paramDesc.params.end(); ++iter)
 				{
-					const GpuParamDataDesc& paramDesc = iter->second;
+					const GpuParamDataDesc& param = iter->second;
 
-					const UINT8* ptrData = bufferData[paramDesc.paramBlockSlot] + paramDesc.cpuMemOffset * sizeof(UINT32);
+					const UINT8* ptrData = uniformBufferData+ param.cpuMemOffset * sizeof(UINT32);
 
-					switch(paramDesc.type)
+					switch(param.type)
 					{
 					case GPDT_FLOAT1:
 					case GPDT_FLOAT2:
@@ -312,10 +298,10 @@ namespace BansheeEngine
 					case GPDT_MATRIX_4X3:
 					case GPDT_MATRIX_4X4:
 						{
-							UINT32 slotCount = (paramDesc.elementSize / 4) * paramDesc.arraySize;
-							assert (paramDesc.elementSize % 4 == 0 && "Should not have any elements less than 4 wide for D3D9");
+							UINT32 slotCount = (param.elementSize / 4) * param.arraySize;
+							assert (param.elementSize % 4 == 0 && "Should not have any elements less than 4 wide for D3D9");
 
-							if (FAILED(hr = getActiveD3D9Device()->SetVertexShaderConstantF(paramDesc.gpuMemOffset, (const float*)ptrData, slotCount))) 
+							if (FAILED(hr = getActiveD3D9Device()->SetVertexShaderConstantF(param.gpuMemOffset, (const float*)ptrData, slotCount))) 
 								BS_EXCEPT(RenderingAPIException, "Unable to upload vertex shader float parameters.");
 							break;
 						}
@@ -324,15 +310,15 @@ namespace BansheeEngine
 					case GPDT_INT3:
 					case GPDT_INT4:
 						{
-							UINT32 slotCount = (paramDesc.elementSize / 4) * paramDesc.arraySize;
-							assert (paramDesc.elementSize % 4 == 0 && "Should not have any elements less than 4 wide for D3D9");
+							UINT32 slotCount = (param.elementSize / 4) * param.arraySize;
+							assert (param.elementSize % 4 == 0 && "Should not have any elements less than 4 wide for D3D9");
 
-							if (FAILED(hr = getActiveD3D9Device()->SetVertexShaderConstantI(paramDesc.gpuMemOffset, (const INT32*)ptrData, slotCount))) 
+							if (FAILED(hr = getActiveD3D9Device()->SetVertexShaderConstantI(param.gpuMemOffset, (const INT32*)ptrData, slotCount))) 
 								BS_EXCEPT(RenderingAPIException, "Unable to upload vertex shader int parameters.");
 							break;
 						}
 					case GPDT_BOOL:
-						if (FAILED(hr = getActiveD3D9Device()->SetVertexShaderConstantB(paramDesc.gpuMemOffset, (const BOOL*)ptrData, paramDesc.arraySize))) 
+						if (FAILED(hr = getActiveD3D9Device()->SetVertexShaderConstantB(param.gpuMemOffset, (const BOOL*)ptrData, param.arraySize))) 
 							BS_EXCEPT(RenderingAPIException, "Unable to upload vertex shader bool parameters.");
 						break;
 					}
@@ -343,11 +329,11 @@ namespace BansheeEngine
 			{
 				for(auto iter = paramDesc.params.begin(); iter != paramDesc.params.end(); ++iter)
 				{
-					const GpuParamDataDesc& paramDesc = iter->second;
+					const GpuParamDataDesc& param = iter->second;
 
-					const UINT8* ptrData = bufferData[paramDesc.paramBlockSlot] + paramDesc.cpuMemOffset * sizeof(UINT32);
+					const UINT8* ptrData = uniformBufferData + param.cpuMemOffset * sizeof(UINT32);
 
-					switch(paramDesc.type)
+					switch(param.type)
 					{
 					case GPDT_FLOAT1:
 					case GPDT_FLOAT2:
@@ -363,10 +349,10 @@ namespace BansheeEngine
 					case GPDT_MATRIX_4X3:
 					case GPDT_MATRIX_4X4:
 						{
-							UINT32 slotCount = (paramDesc.elementSize / 4) * paramDesc.arraySize;
-							assert (paramDesc.elementSize % 4 == 0 && "Should not have any elements less than 4 wide for D3D9");
+							UINT32 slotCount = (param.elementSize / 4) * param.arraySize;
+							assert (param.elementSize % 4 == 0 && "Should not have any elements less than 4 wide for D3D9");
 
-							if (FAILED(hr = getActiveD3D9Device()->SetPixelShaderConstantF(paramDesc.gpuMemOffset, (const float*)ptrData, slotCount))) 
+							if (FAILED(hr = getActiveD3D9Device()->SetPixelShaderConstantF(param.gpuMemOffset, (const float*)ptrData, slotCount))) 
 								BS_EXCEPT(RenderingAPIException, "Unable to upload pixel shader float parameters.");
 							break;
 						}
@@ -375,15 +361,15 @@ namespace BansheeEngine
 					case GPDT_INT3:
 					case GPDT_INT4:
 						{
-							UINT32 slotCount = (paramDesc.elementSize / 4) * paramDesc.arraySize;
-							assert (paramDesc.elementSize % 4 == 0 && "Should not have any elements less than 4 wide for D3D9");
+							UINT32 slotCount = (param.elementSize / 4) * param.arraySize;
+							assert (param.elementSize % 4 == 0 && "Should not have any elements less than 4 wide for D3D9");
 
-							if (FAILED(hr = getActiveD3D9Device()->SetPixelShaderConstantI(paramDesc.gpuMemOffset, (const INT32*)ptrData, slotCount))) 
+							if (FAILED(hr = getActiveD3D9Device()->SetPixelShaderConstantI(param.gpuMemOffset, (const INT32*)ptrData, slotCount))) 
 								BS_EXCEPT(RenderingAPIException, "Unable to upload pixel shader int parameters.");
 							break;
 						}
 					case GPDT_BOOL:
-						if (FAILED(hr = getActiveD3D9Device()->SetPixelShaderConstantB(paramDesc.gpuMemOffset, (const BOOL*)ptrData, paramDesc.arraySize))) 
+						if (FAILED(hr = getActiveD3D9Device()->SetPixelShaderConstantB(param.gpuMemOffset, (const BOOL*)ptrData, param.arraySize))) 
 							BS_EXCEPT(RenderingAPIException, "Unable to upload pixel shader bool parameters.");
 						break;
 					}
@@ -392,10 +378,7 @@ namespace BansheeEngine
 			break;
 		};
 
-		for(auto& curBufferData : bufferData)
-		{
-			bs_free(curBufferData.second);
-		}
+		bs_stack_free(uniformBufferData);
 
 		BS_INC_RENDER_STAT(NumGpuParamBufferBinds);
 	}

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

@@ -1190,7 +1190,7 @@ namespace BansheeEngine
 				for (auto curRenderData : *renderData)
 				{
 					mIconMaterial.mTexture[passIdx].set(curRenderData.texture);
-					rapi.setGpuParams(GPT_FRAGMENT_PROGRAM, mIconMaterial.mFragParams[passIdx]);
+					RendererUtility::setGpuParams(GPT_FRAGMENT_PROGRAM, mIconMaterial.mFragParams[passIdx]);
 
 					rapi.drawIndexed(curIndexOffset, curRenderData.count * 6, mesh->getVertexOffset(), curRenderData.count * 4);
 					curIndexOffset += curRenderData.count * 6;
@@ -1207,7 +1207,7 @@ namespace BansheeEngine
 			for (auto curRenderData : *renderData)
 			{
 				mAlphaPickingMaterial.mTexture.set(curRenderData.texture);
-				rapi.setGpuParams(GPT_FRAGMENT_PROGRAM, mAlphaPickingMaterial.mFragParams);
+				RendererUtility::setGpuParams(GPT_FRAGMENT_PROGRAM, mAlphaPickingMaterial.mFragParams);
 
 				rapi.drawIndexed(curIndexOffset, curRenderData.count * 6, mesh->getVertexOffset(), curRenderData.count * 4);
 				curIndexOffset += curRenderData.count * 6;

+ 4 - 4
Source/BansheeEditor/Source/BsScenePicking.cpp

@@ -293,16 +293,16 @@ namespace BansheeEngine
 				md.mParamPickingAlphaColor.set(color);
 				md.mParamPickingAlphaTexture.set(renderable.mainTexture->getCore());
 
-				rs.setGpuParams(GPT_VERTEX_PROGRAM, md.mParamPickingAlphaVertParams);
-				rs.setGpuParams(GPT_FRAGMENT_PROGRAM, md.mParamPickingAlphaFragParams);
+				RendererUtility::setGpuParams(GPT_VERTEX_PROGRAM, md.mParamPickingAlphaVertParams);
+				RendererUtility::setGpuParams(GPT_FRAGMENT_PROGRAM, md.mParamPickingAlphaFragParams);
 			}
 			else
 			{
 				md.mParamPickingWVP.set(renderable.wvpTransform);
 				md.mParamPickingColor.set(color);
 
-				rs.setGpuParams(GPT_VERTEX_PROGRAM, md.mParamPickingVertParams);
-				rs.setGpuParams(GPT_FRAGMENT_PROGRAM, md.mParamPickingFragParams);
+				RendererUtility::setGpuParams(GPT_VERTEX_PROGRAM, md.mParamPickingVertParams);
+				RendererUtility::setGpuParams(GPT_FRAGMENT_PROGRAM, md.mParamPickingFragParams);
 			}
 
 			UINT32 numSubmeshes = renderable.mesh->getProperties().getNumSubMeshes();

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

@@ -59,6 +59,14 @@ namespace BansheeEngine
 		 */
 		static void setPassParams(const SPtr<MaterialCore>& material, 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.
+		 */
+		static void setGpuParams(GpuProgramType type, const SPtr<GpuParamsCore>& params);
+
 		/**
 		 * Draws the specified mesh.
 		 *

+ 46 - 36
Source/BansheeEngine/Source/BsRendererUtility.cpp

@@ -11,6 +11,7 @@
 #include "BsRasterizerState.h"
 #include "BsGpuParams.h"
 #include "BsGpuParamDesc.h"
+#include "BsGpuParamBlockBuffer.h"
 #include "BsShapeMeshes3D.h"
 #include "BsLight.h"
 #include "BsShader.h"
@@ -162,7 +163,7 @@ namespace BansheeEngine
 			if (stage.enable)
 			{
 				rs.bindGpuProgram(stage.program);
-				rs.setGpuParams(stage.type, stage.params);
+				setGpuParams(stage.type, stage.params);
 
 			}
 			else
@@ -196,7 +197,7 @@ namespace BansheeEngine
 		if(pass->hasComputeProgram())
 		{
 			rs.bindGpuProgram(pass->getComputeProgram());
-			rs.setGpuParams(GPT_COMPUTE_PROGRAM, passParams->mComputeParams);
+			setGpuParams(GPT_COMPUTE_PROGRAM, passParams->mComputeParams);
 		}
 		else
 			rs.unbindGpuProgram(GPT_COMPUTE_PROGRAM);
@@ -233,50 +234,59 @@ namespace BansheeEngine
 			if (params == nullptr)
 				continue;
 
-			const GpuParamDesc& paramDesc = params->getParamDesc();
+			setGpuParams(stage.type, params);
+		}
+	}
 
-			for (auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
-			{
-				SPtr<SamplerStateCore> samplerState = params->getSamplerState(iter->second.slot);
+	void RendererUtility::setGpuParams(GpuProgramType type, const SPtr<GpuParamsCore>& params)
+	{
+		RenderAPICore& rapi = RenderAPICore::instance();
+		const GpuParamDesc& paramDesc = params->getParamDesc();
 
-				if (samplerState == nullptr)
-					rs.setSamplerState(stage.type, iter->second.slot, SamplerStateCore::getDefault());
-				else
-					rs.setSamplerState(stage.type, iter->second.slot, samplerState);
-			}
+		for (auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
+		{
+			SPtr<SamplerStateCore> samplerState = params->getSamplerState(iter->second.slot);
 
-			for (auto iter = paramDesc.textures.begin(); iter != paramDesc.textures.end(); ++iter)
-			{
-				SPtr<TextureCore> texture = params->getTexture(iter->second.slot);
+			if (samplerState == nullptr)
+				rapi.setSamplerState(type, iter->second.slot, SamplerStateCore::getDefault());
+			else
+				rapi.setSamplerState(type, iter->second.slot, samplerState);
+		}
 
-				if (texture == nullptr)
-					rs.setTexture(stage.type, iter->second.slot, false, nullptr);
-				else
-					rs.setTexture(stage.type, iter->second.slot, true, texture);
-			}
+		for (auto iter = paramDesc.textures.begin(); iter != paramDesc.textures.end(); ++iter)
+		{
+			SPtr<TextureCore> texture = params->getTexture(iter->second.slot);
 
-			for (auto iter = paramDesc.loadStoreTextures.begin(); iter != paramDesc.loadStoreTextures.end(); ++iter)
-			{
-				SPtr<TextureCore> texture = params->getLoadStoreTexture(iter->second.slot);
-				const TextureSurface& surface = params->getLoadStoreSurface(iter->second.slot);
+			rapi.setTexture(type, iter->second.slot, texture);
+		}
 
-				if (texture == nullptr)
-					rs.setLoadStoreTexture(stage.type, iter->second.slot, false, nullptr, surface);
-				else
-					rs.setLoadStoreTexture(stage.type, iter->second.slot, true, texture, surface);
-			}
+		for (auto iter = paramDesc.loadStoreTextures.begin(); iter != paramDesc.loadStoreTextures.end(); ++iter)
+		{
+			SPtr<TextureCore> texture = params->getLoadStoreTexture(iter->second.slot);
+			const TextureSurface& surface = params->getLoadStoreSurface(iter->second.slot);
 
-			for (auto iter = paramDesc.buffers.begin(); iter != paramDesc.buffers.end(); ++iter)
-			{
-				SPtr<GpuBufferCore> buffer = params->getBuffer(iter->second.slot);
+			if (texture == nullptr)
+				rapi.setLoadStoreTexture(type, iter->second.slot, false, nullptr, surface);
+			else
+				rapi.setLoadStoreTexture(type, iter->second.slot, true, texture, surface);
+		}
 
-				bool isLoadStore = iter->second.type != GPOT_BYTE_BUFFER &&
-					iter->second.type != GPOT_STRUCTURED_BUFFER;
+		for (auto iter = paramDesc.buffers.begin(); iter != paramDesc.buffers.end(); ++iter)
+		{
+			SPtr<GpuBufferCore> buffer = params->getBuffer(iter->second.slot);
 
-				rs.setBuffer(stage.type, iter->second.slot, buffer, isLoadStore);
-			}
+			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.paramBlocks.begin(); iter != paramDesc.paramBlocks.end(); ++iter)
+		{
+			SPtr<GpuParamBlockBufferCore> blockBuffer = params->getParamBlockBuffer(iter->second.slot);
+			blockBuffer->flushToGPU();
 
-			rs.setConstantBuffers(stage.type, params);
+			rapi.setParamBuffer(type, iter->second.slot, blockBuffer, paramDesc);
 		}
 	}
 

+ 1 - 1
Source/BansheeGLRenderAPI/Include/BsGLGpuParamBlockBuffer.h

@@ -28,7 +28,7 @@ namespace BansheeEngine
 		GLuint getGLHandle() const { return mGLHandle; }
 	protected:
 		/** @copydoc GpuParamBlockBufferCore::initialize */
-		virtual void initialize()override ;
+		void initialize() override ;
 
 	private:
 		GLuint mGLHandle;

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

@@ -76,8 +76,9 @@ namespace BansheeEngine
 		/** @copydoc RenderAPICore::unbindGpuProgram() */
 		void unbindGpuProgram(GpuProgramType gptype) override;
 
-		/** @copydoc RenderAPICore::setConstantBuffers() */
-		void setConstantBuffers(GpuProgramType gptype, const SPtr<GpuParamsCore>& params) override;
+		/** @copydoc RenderAPICore::setParamBuffer */
+		void setParamBuffer(GpuProgramType gptype, UINT32 slot, const SPtr<GpuParamBlockBufferCore>& buffer, 
+			const GpuParamDesc& paramDesc) override;
 
 		/** @copydoc RenderAPICore::beginFrame() */
 		void beginFrame() override;

+ 100 - 112
Source/BansheeGLRenderAPI/Source/BsGLRenderAPI.cpp

@@ -248,137 +248,125 @@ namespace BansheeEngine
 		RenderAPICore::unbindGpuProgram(gptype);
 	}
 
-	void GLRenderAPI::setConstantBuffers(GpuProgramType gptype, const SPtr<GpuParamsCore>& bindableParams)
+	void GLRenderAPI::setParamBuffer(GpuProgramType gptype, UINT32 slot, const SPtr<GpuParamBlockBufferCore>& buffer, 
+		const GpuParamDesc& paramDesc)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		bindableParams->updateHardwareBuffers();
-		const GpuParamDesc& paramDesc = bindableParams->getParamDesc();
+		if (buffer == nullptr)
+			return;
+
 		SPtr<GLSLGpuProgramCore> activeProgram = getActiveProgram(gptype);
 		GLuint glProgram = activeProgram->getGLHandle();
 
-		UINT8* uniformBufferData = nullptr;
-
-		UINT32 blockBinding = 0;
-		for(auto iter = paramDesc.paramBlocks.begin(); iter != paramDesc.paramBlocks.end(); ++iter)
+		// 0 means uniforms are not in block, in which case we handle it specially
+		if (slot == 0)
 		{
-			SPtr<GpuParamBlockBufferCore> paramBlockBuffer = bindableParams->getParamBlockBuffer(iter->second.slot);
-			if(paramBlockBuffer == nullptr)
-				continue;
+			UINT8* uniformBufferData = (UINT8*)bs_stack_alloc(buffer->getSize());
+			buffer->readFromGPU(uniformBufferData); // TODO - Don't read from GPU!? Just read the cached version
 
-			if(iter->second.slot == 0)
+			bool hasBoundAtLeastOne = false;
+			for (auto iter = paramDesc.params.begin(); iter != paramDesc.params.end(); ++iter)
 			{
-				// 0 means uniforms are not in block, in which case we handle it specially
-				if (uniformBufferData == nullptr && paramBlockBuffer->getSize() > 0)
-				{
-					uniformBufferData = (UINT8*)bs_alloc(paramBlockBuffer->getSize());
-					paramBlockBuffer->readFromGPU(uniformBufferData); // TODO - Don't read from GPU!? Just read the cached version
-				}
+				const GpuParamDataDesc& param = iter->second;
 
-				continue;
-			}
+				if (param.paramBlockSlot != 0) // 0 means uniforms are not in a block
+					continue;
 
-			const GLGpuParamBlockBufferCore* glParamBlockBuffer = static_cast<const GLGpuParamBlockBufferCore*>(paramBlockBuffer.get());
-
-			UINT32 globalBlockBinding = getGLUniformBlockBinding(gptype, blockBinding);
-			glUniformBlockBinding(glProgram, iter->second.slot - 1, globalBlockBinding);
-			glBindBufferRange(GL_UNIFORM_BUFFER, globalBlockBinding, glParamBlockBuffer->getGLHandle(), 0, glParamBlockBuffer->getSize());
-
-			blockBinding++;
-
-			BS_INC_RENDER_STAT(NumGpuParamBufferBinds);
-		}
+				const UINT8* ptrData = uniformBufferData + param.cpuMemOffset * sizeof(UINT32);
+				hasBoundAtLeastOne = true;
 
-		bool hasBoundAtLeastOne = false;
-		for(auto iter = paramDesc.params.begin(); iter != paramDesc.params.end(); ++iter)
-		{
-			const GpuParamDataDesc& paramDesc = iter->second;
-
-			if(paramDesc.paramBlockSlot != 0) // 0 means uniforms are not in a block
-				continue;
+				// Note: We don't transpose matrices here even though we don't use column major format
+				// because they are assumed to be pre-transposed in the GpuParams buffer
+				switch (param.type)
+				{
+				case GPDT_FLOAT1:
+					glProgramUniform1fv(glProgram, param.gpuMemOffset, param.arraySize, (GLfloat*)ptrData);
+					break;
+				case GPDT_FLOAT2:
+					glProgramUniform2fv(glProgram, param.gpuMemOffset, param.arraySize, (GLfloat*)ptrData);
+					break;
+				case GPDT_FLOAT3:
+					glProgramUniform3fv(glProgram, param.gpuMemOffset, param.arraySize, (GLfloat*)ptrData);
+					break;
+				case GPDT_FLOAT4:
+					glProgramUniform4fv(glProgram, param.gpuMemOffset, param.arraySize, (GLfloat*)ptrData);
+					break;
+				case GPDT_MATRIX_2X2:
+					glProgramUniformMatrix2fv(glProgram, param.gpuMemOffset, param.arraySize,
+						GL_FALSE, (GLfloat*)ptrData);
+					break;
+				case GPDT_MATRIX_2X3:
+					glProgramUniformMatrix3x2fv(glProgram, param.gpuMemOffset, param.arraySize,
+						GL_FALSE, (GLfloat*)ptrData);
+					break;
+				case GPDT_MATRIX_2X4:
+					glProgramUniformMatrix4x2fv(glProgram, param.gpuMemOffset, param.arraySize,
+						GL_FALSE, (GLfloat*)ptrData);
+					break;
+				case GPDT_MATRIX_3X2:
+					glProgramUniformMatrix2x3fv(glProgram, param.gpuMemOffset, param.arraySize,
+						GL_FALSE, (GLfloat*)ptrData);
+					break;
+				case GPDT_MATRIX_3X3:
+					glProgramUniformMatrix3fv(glProgram, param.gpuMemOffset, param.arraySize,
+						GL_FALSE, (GLfloat*)ptrData);
+					break;
+				case GPDT_MATRIX_3X4:
+					glProgramUniformMatrix4x3fv(glProgram, param.gpuMemOffset, param.arraySize,
+						GL_FALSE, (GLfloat*)ptrData);
+					break;
+				case GPDT_MATRIX_4X2:
+					glProgramUniformMatrix2x4fv(glProgram, param.gpuMemOffset, param.arraySize,
+						GL_FALSE, (GLfloat*)ptrData);
+					break;
+				case GPDT_MATRIX_4X3:
+					glProgramUniformMatrix3x4fv(glProgram, param.gpuMemOffset, param.arraySize,
+						GL_FALSE, (GLfloat*)ptrData);
+					break;
+				case GPDT_MATRIX_4X4:
+					glProgramUniformMatrix4fv(glProgram, param.gpuMemOffset, param.arraySize,
+						GL_FALSE, (GLfloat*)ptrData);
+					break;
+				case GPDT_INT1:
+					glProgramUniform1iv(glProgram, param.gpuMemOffset, param.arraySize, (GLint*)ptrData);
+					break;
+				case GPDT_INT2:
+					glProgramUniform2iv(glProgram, param.gpuMemOffset, param.arraySize, (GLint*)ptrData);
+					break;
+				case GPDT_INT3:
+					glProgramUniform3iv(glProgram, param.gpuMemOffset, param.arraySize, (GLint*)ptrData);
+					break;
+				case GPDT_INT4:
+					glProgramUniform4iv(glProgram, param.gpuMemOffset, param.arraySize, (GLint*)ptrData);
+					break;
+				case GPDT_BOOL:
+					glProgramUniform1uiv(glProgram, param.gpuMemOffset, param.arraySize, (GLuint*)ptrData);
+					break;
+				default:
+				case GPDT_UNKNOWN:
+					break;
+				}
+			}
 
-			const UINT8* ptrData = uniformBufferData + paramDesc.cpuMemOffset * sizeof(UINT32);
-			hasBoundAtLeastOne = true;
+			if (hasBoundAtLeastOne)
+				BS_INC_RENDER_STAT(NumGpuParamBufferBinds);
 
-			// Note: We don't transpose matrices here even though we don't use column major format
-			// because they are assumed to be pre-transposed in the GpuParams buffer
-			switch(paramDesc.type)
+			if (uniformBufferData != nullptr)
 			{
-			case GPDT_FLOAT1:
-				glProgramUniform1fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLfloat*)ptrData);
-				break;
-			case GPDT_FLOAT2:
-				glProgramUniform2fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLfloat*)ptrData);
-				break;
-			case GPDT_FLOAT3:
-				glProgramUniform3fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLfloat*)ptrData);
-				break;
-			case GPDT_FLOAT4:
-				glProgramUniform4fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLfloat*)ptrData);
-				break;
-			case GPDT_MATRIX_2X2:
-				glProgramUniformMatrix2fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
-					GL_FALSE, (GLfloat*)ptrData);
-				break;
-			case GPDT_MATRIX_2X3:
-				glProgramUniformMatrix3x2fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
-					GL_FALSE, (GLfloat*)ptrData);
-				break;
-			case GPDT_MATRIX_2X4:
-				glProgramUniformMatrix4x2fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
-					GL_FALSE, (GLfloat*)ptrData);
-				break;
-			case GPDT_MATRIX_3X2:
-				glProgramUniformMatrix2x3fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
-					GL_FALSE, (GLfloat*)ptrData);
-				break;
-			case GPDT_MATRIX_3X3:
-				glProgramUniformMatrix3fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
-					GL_FALSE, (GLfloat*)ptrData);
-				break;
-			case GPDT_MATRIX_3X4:
-				glProgramUniformMatrix4x3fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
-					GL_FALSE, (GLfloat*)ptrData);
-				break;
-			case GPDT_MATRIX_4X2:
-				glProgramUniformMatrix2x4fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
-					GL_FALSE, (GLfloat*)ptrData);
-				break;
-			case GPDT_MATRIX_4X3:
-				glProgramUniformMatrix3x4fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
-					GL_FALSE, (GLfloat*)ptrData);
-				break;
-			case GPDT_MATRIX_4X4:
-				glProgramUniformMatrix4fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
-					GL_FALSE, (GLfloat*)ptrData);
-				break;
-			case GPDT_INT1:
-				glProgramUniform1iv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLint*)ptrData);
-				break;
-			case GPDT_INT2:
-				glProgramUniform2iv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLint*)ptrData);
-				break;
-			case GPDT_INT3:
-				glProgramUniform3iv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLint*)ptrData);
-				break;
-			case GPDT_INT4:
-				glProgramUniform4iv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLint*)ptrData);
-				break;
-			case GPDT_BOOL:
-				glProgramUniform1uiv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLuint*)ptrData);
-				break;
-			default:
-			case GPDT_UNKNOWN:
-				break;
+				bs_stack_free(uniformBufferData);
 			}
 		}
+		else
+		{
+			const GLGpuParamBlockBufferCore* glParamBlockBuffer = static_cast<const GLGpuParamBlockBufferCore*>(buffer.get());
 
-		if (hasBoundAtLeastOne)
-			BS_INC_RENDER_STAT(NumGpuParamBufferBinds);
+			UINT32 globalBlockBinding = getGLUniformBlockBinding(gptype, slot - 1);
+			glUniformBlockBinding(glProgram, slot - 1, globalBlockBinding);
+			glBindBufferRange(GL_UNIFORM_BUFFER, globalBlockBinding, glParamBlockBuffer->getGLHandle(), 0, 
+				glParamBlockBuffer->getSize());
 
-		if(uniformBufferData != nullptr)
-		{
-			bs_free(uniformBufferData);
+			BS_INC_RENDER_STAT(NumGpuParamBufferBinds);
 		}
 	}
 

+ 27 - 17
Source/RenderBeast/Include/BsLightRendering.h

@@ -21,16 +21,32 @@ namespace BansheeEngine
 		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatConeTransform)
 	BS_PARAM_BLOCK_END
 
-	/** Manipulates PerLight parameter buffer used in various shaders. */
-	class PerLightParams
+	/** Manipulates parameters used in various light rendering shaders. */
+	class LightRenderingParams
 	{
 	public:
+		LightRenderingParams(const SPtr<MaterialCore>& lightMaterial);
+
+		/** Updates parameters that are common for all lights. */
+		void setStaticParameters(RenderAPICore& rapi, const SPtr<RenderTargets>& gbuffer,
+			const SPtr<GpuParamBlockBufferCore>& perCamera);
+
 		/** Updates data in the parameter buffer from the data in the provided light. */
 		void setParameters(const LightCore* light);
 
 		/** Returns the internal parameter buffer that can be bound to the pipeline. */
 		const SPtr<GpuParamBlockBufferCore>& getBuffer() const;
 	private:
+		GpuParamTextureCore mGBufferA;
+		GpuParamTextureCore mGBufferB;
+		GpuParamTextureCore mGBufferDepth;
+		GpuParamBlockDesc* mPerLightBlockDescFP;
+		GpuParamBlockDesc* mPerLightBlockDescVP;
+		GpuParamBlockDesc* mPerCameraBlockDescFP;
+		GpuParamBlockDesc* mPerCameraBlockDescVP;
+		const GpuParamDesc* mParamDescVP;
+		const GpuParamDesc* mParamDescFP;
+
 		PerLightParamBuffer mBuffer;
 	};
 
@@ -43,15 +59,13 @@ namespace BansheeEngine
 		DirectionalLightMat();
 
 		/** Updates parameters that are common for all lights. */
-		void setStaticParameters(const SPtr<RenderTargets>& gbuffer, const SPtr<GpuParamBlockBufferCore>& perCamera);
+		void setStaticParameters(RenderAPICore& rapi, const SPtr<RenderTargets>& gbuffer, 
+			const SPtr<GpuParamBlockBufferCore>& perCamera);
 
 		/** Updates the parameter buffers used by the material. */
 		void setParameters(const LightCore* light);
 	private:
-		PerLightParams mParams; // Note: Should this buffer be shared between both point and directional lights?
-		MaterialParamTextureCore mGBufferA;
-		MaterialParamTextureCore mGBufferB;
-		MaterialParamTextureCore mGBufferDepth;
+		LightRenderingParams mParams;
 	};
 
 	/** 
@@ -66,15 +80,13 @@ namespace BansheeEngine
 		PointLightInMat();
 
 		/** Updates parameters that are common for all lights.  */
-		void setStaticParameters(const SPtr<RenderTargets>& gbuffer, const SPtr<GpuParamBlockBufferCore>& perCamera);
+		void setStaticParameters(RenderAPICore& rapi, const SPtr<RenderTargets>& gbuffer, 
+			const SPtr<GpuParamBlockBufferCore>& perCamera);
 
 		/** Updates the parameter buffers used by the material. */
 		void setParameters(const LightCore* light);
 	private:
-		PerLightParams mParams; // Note: Should this buffer be shared between both point and directional lights?
-		MaterialParamTextureCore mGBufferA;
-		MaterialParamTextureCore mGBufferB;
-		MaterialParamTextureCore mGBufferDepth;
+		LightRenderingParams mParams;
 	};
 
 	/** 
@@ -89,15 +101,13 @@ namespace BansheeEngine
 		PointLightOutMat();
 
 		/** Updates parameters that are common for all lights.  */
-		void setStaticParameters(const SPtr<RenderTargets>& gbuffer, const SPtr<GpuParamBlockBufferCore>& perCamera);
+		void setStaticParameters(RenderAPICore& rapi, const SPtr<RenderTargets>& gbuffer, 
+			const SPtr<GpuParamBlockBufferCore>& perCamera);
 
 		/** Updates the parameter buffers used by the material. */
 		void setParameters(const LightCore* light);
 	private:
-		PerLightParams mParams; // Note: Should this buffer be shared between both point and directional lights?
-		MaterialParamTextureCore mGBufferA;
-		MaterialParamTextureCore mGBufferB;
-		MaterialParamTextureCore mGBufferDepth;
+		LightRenderingParams mParams;
 	};
 
 	/** @} */

+ 1 - 1
Source/RenderBeast/Include/BsRenderBeast.h

@@ -173,7 +173,7 @@ namespace BansheeEngine
 		 *
 		 * @note	Core thread only.
 		 */
-		void syncRenderOptions(const RenderBeastOptions& options);
+		void syncOptions(const RenderBeastOptions& options);
 
 		/**
 		 * Performs rendering over all camera proxies.

+ 62 - 55
Source/RenderBeast/Source/BsLightRendering.cpp

@@ -10,7 +10,51 @@
 
 namespace BansheeEngine
 {
-	void PerLightParams::setParameters(const LightCore* light)
+	LightRenderingParams::LightRenderingParams(const SPtr<MaterialCore>& material)
+	{
+		auto& texParams = material->getShader()->getTextureParams();
+		SPtr<GpuParamsCore> fragParams = material->getGpuParams(0, GPT_FRAGMENT_PROGRAM);
+		for (auto& entry : texParams)
+		{
+			if (entry.second.rendererSemantic == RPS_GBufferA)
+				fragParams->getTextureParam(entry.second.name, mGBufferA);
+			else if (entry.second.rendererSemantic == RPS_GBufferB)
+				fragParams->getTextureParam(entry.second.name, mGBufferB);
+			else if (entry.second.rendererSemantic == RPS_GBufferDepth)
+				fragParams->getTextureParam(entry.second.name, mGBufferDepth);
+		}
+
+		mParamDescFP = &fragParams->getParamDesc();
+		mPerLightBlockDescFP = fragParams->getParamBlockDesc("PerLight");
+		mPerCameraBlockDescFP = fragParams->getParamBlockDesc("PerCamera");
+
+		SPtr<GpuParamsCore> vertParams = material->getGpuParams(0, GPT_VERTEX_PROGRAM);
+		mParamDescVP = &vertParams->getParamDesc();
+		mPerLightBlockDescVP = vertParams->getParamBlockDesc("PerLight");
+		mPerCameraBlockDescVP = vertParams->getParamBlockDesc("PerCamera");
+	}
+
+	void LightRenderingParams::setStaticParameters(RenderAPICore& rapi, const SPtr<RenderTargets>& gbuffer,
+		const SPtr<GpuParamBlockBufferCore>& perCamera)
+	{
+		rapi.setTexture(GPT_FRAGMENT_PROGRAM, mGBufferA.getDesc().slot, gbuffer->getTextureA());
+		rapi.setTexture(GPT_FRAGMENT_PROGRAM, mGBufferB.getDesc().slot, gbuffer->getTextureB());
+		rapi.setTexture(GPT_FRAGMENT_PROGRAM, mGBufferDepth.getDesc().slot, gbuffer->getTextureDepth());
+
+		rapi.setSamplerState(GPT_FRAGMENT_PROGRAM, 0, SamplerStateCore::getDefault());
+		rapi.setSamplerState(GPT_FRAGMENT_PROGRAM, 1, SamplerStateCore::getDefault());
+		rapi.setSamplerState(GPT_FRAGMENT_PROGRAM, 2, SamplerStateCore::getDefault());
+
+		rapi.setParamBuffer(GPT_FRAGMENT_PROGRAM, mPerLightBlockDescFP->slot, mBuffer.getBuffer(), *mParamDescFP);
+		rapi.setParamBuffer(GPT_FRAGMENT_PROGRAM, mPerCameraBlockDescFP->slot, perCamera, *mParamDescFP);
+
+		if(mPerLightBlockDescVP != nullptr)
+			rapi.setParamBuffer(GPT_VERTEX_PROGRAM, mPerLightBlockDescVP->slot, mBuffer.getBuffer(), *mParamDescVP);
+
+		rapi.setParamBuffer(GPT_VERTEX_PROGRAM, mPerCameraBlockDescVP->slot, perCamera, *mParamDescVP);
+	}
+
+	void LightRenderingParams::setParameters(const LightCore* light)
 	{
 		// Note: I could just copy the data directly to the parameter buffer if I ensured the parameter
 		// layout matches
@@ -65,27 +109,19 @@ namespace BansheeEngine
 
 		Matrix4 transform = Matrix4::TRS(light->getPosition(), light->getRotation(), Vector3::ONE);
 		mBuffer.gMatConeTransform.set(transform);
+
+		mBuffer.flushToGPU();
 	}
 
-	const SPtr<GpuParamBlockBufferCore>& PerLightParams::getBuffer() const
+	const SPtr<GpuParamBlockBufferCore>& LightRenderingParams::getBuffer() const
 	{
 		return mBuffer.getBuffer();
 	}
 	
 	DirectionalLightMat::DirectionalLightMat()
+		:mParams(mMaterial)
 	{
-		mMaterial->setParamBlockBuffer("PerLight", mParams.getBuffer());
-
-		auto& texParams = mMaterial->getShader()->getTextureParams();
-		for (auto& entry : texParams)
-		{
-			if (entry.second.rendererSemantic == RPS_GBufferA)
-				mGBufferA = mMaterial->getParamTexture(entry.second.name);
-			else if (entry.second.rendererSemantic == RPS_GBufferB)
-				mGBufferB = mMaterial->getParamTexture(entry.second.name);
-			else if (entry.second.rendererSemantic == RPS_GBufferDepth)
-				mGBufferDepth = mMaterial->getParamTexture(entry.second.name);
-		}
+		
 	}
 
 	void DirectionalLightMat::_initDefines(ShaderDefines& defines)
@@ -93,13 +129,10 @@ namespace BansheeEngine
 		// Do nothing
 	}
 
-	void DirectionalLightMat::setStaticParameters(const SPtr<RenderTargets>& gbuffer, const SPtr<GpuParamBlockBufferCore>& perCamera)
+	void DirectionalLightMat::setStaticParameters(RenderAPICore& rapi, const SPtr<RenderTargets>& gbuffer, 
+		const SPtr<GpuParamBlockBufferCore>& perCamera)
 	{
-		mGBufferA.set(gbuffer->getTextureA());
-		mGBufferB.set(gbuffer->getTextureB());
-		mGBufferDepth.set(gbuffer->getTextureDepth());
-
-		mMaterial->setParamBlockBuffer("PerCamera", perCamera);
+		mParams.setStaticParameters(rapi, gbuffer, perCamera);
 	}
 
 	void DirectionalLightMat::setParameters(const LightCore* light)
@@ -108,19 +141,9 @@ namespace BansheeEngine
 	}
 
 	PointLightInMat::PointLightInMat()
+		:mParams(mMaterial)
 	{
-		mMaterial->setParamBlockBuffer("PerLight", mParams.getBuffer());
 
-		auto& texParams = mMaterial->getShader()->getTextureParams();
-		for (auto& entry : texParams)
-		{
-			if (entry.second.rendererSemantic == RPS_GBufferA)
-				mGBufferA = mMaterial->getParamTexture(entry.second.name);
-			else if (entry.second.rendererSemantic == RPS_GBufferB)
-				mGBufferB = mMaterial->getParamTexture(entry.second.name);
-			else if (entry.second.rendererSemantic == RPS_GBufferDepth)
-				mGBufferDepth = mMaterial->getParamTexture(entry.second.name);
-		}
 	}
 
 	void PointLightInMat::_initDefines(ShaderDefines& defines)
@@ -128,13 +151,10 @@ namespace BansheeEngine
 		// Do nothing
 	}
 
-	void PointLightInMat::setStaticParameters(const SPtr<RenderTargets>& gbuffer, const SPtr<GpuParamBlockBufferCore>& perCamera)
+	void PointLightInMat::setStaticParameters(RenderAPICore& rapi, const SPtr<RenderTargets>& gbuffer, 
+		const SPtr<GpuParamBlockBufferCore>& perCamera)
 	{
-		mGBufferA.set(gbuffer->getTextureA());
-		mGBufferB.set(gbuffer->getTextureB());
-		mGBufferDepth.set(gbuffer->getTextureDepth());
-
-		mMaterial->setParamBlockBuffer("PerCamera", perCamera);
+		mParams.setStaticParameters(rapi, gbuffer, perCamera);
 	}
 
 	void PointLightInMat::setParameters(const LightCore* light)
@@ -143,19 +163,9 @@ namespace BansheeEngine
 	}
 
 	PointLightOutMat::PointLightOutMat()
+		:mParams(mMaterial)
 	{
-		mMaterial->setParamBlockBuffer("PerLight", mParams.getBuffer());
-
-		auto& texParams = mMaterial->getShader()->getTextureParams();
-		for (auto& entry : texParams)
-		{
-			if (entry.second.rendererSemantic == RPS_GBufferA)
-				mGBufferA = mMaterial->getParamTexture(entry.second.name);
-			else if (entry.second.rendererSemantic == RPS_GBufferB)
-				mGBufferB = mMaterial->getParamTexture(entry.second.name);
-			else if (entry.second.rendererSemantic == RPS_GBufferDepth)
-				mGBufferDepth = mMaterial->getParamTexture(entry.second.name);
-		}
+		
 	}
 
 	void PointLightOutMat::_initDefines(ShaderDefines& defines)
@@ -163,13 +173,10 @@ namespace BansheeEngine
 		// Do nothing
 	}
 
-	void PointLightOutMat::setStaticParameters(const SPtr<RenderTargets>& gbuffer, const SPtr<GpuParamBlockBufferCore>& perCamera)
+	void PointLightOutMat::setStaticParameters(RenderAPICore& rapi, const SPtr<RenderTargets>& gbuffer, 
+		const SPtr<GpuParamBlockBufferCore>& perCamera)
 	{
-		mGBufferA.set(gbuffer->getTextureA());
-		mGBufferB.set(gbuffer->getTextureB());
-		mGBufferDepth.set(gbuffer->getTextureDepth());
-
-		mMaterial->setParamBlockBuffer("PerCamera", perCamera);
+		mParams.setStaticParameters(rapi, gbuffer, perCamera);
 	}
 
 	void PointLightOutMat::setParameters(const LightCore* light)

+ 27 - 33
Source/RenderBeast/Source/BsRenderBeast.cpp

@@ -446,21 +446,7 @@ namespace BansheeEngine
 		return mOptions;
 	}
 
-	void RenderBeast::renderAll() 
-	{
-		// Sync all dirty sim thread CoreObject data to core thread
-		CoreObjectManager::instance().syncToCore(gCoreAccessor());
-
-		if (mOptionsDirty)
-		{
-			gCoreAccessor().queueCommand(std::bind(&RenderBeast::syncRenderOptions, this, *mOptions));
-			mOptionsDirty = false;
-		}
-
-		gCoreAccessor().queueCommand(std::bind(&RenderBeast::renderAllCore, this, gTime().getTime(), gTime().getFrameDelta()));
-	}
-
-	void RenderBeast::syncRenderOptions(const RenderBeastOptions& options)
+	void RenderBeast::syncOptions(const RenderBeastOptions& options)
 	{
 		bool filteringChanged = mCoreOptions->filtering != options.filtering;
 		if (options.filtering == RenderBeastFiltering::Anisotropic)
@@ -483,6 +469,20 @@ namespace BansheeEngine
 		}
 	}
 
+	void RenderBeast::renderAll() 
+	{
+		// Sync all dirty sim thread CoreObject data to core thread
+		CoreObjectManager::instance().syncToCore(gCoreAccessor());
+
+		if (mOptionsDirty)
+		{
+			gCoreAccessor().queueCommand(std::bind(&RenderBeast::syncOptions, this, *mOptions));
+			mOptionsDirty = false;
+		}
+
+		gCoreAccessor().queueCommand(std::bind(&RenderBeast::renderAllCore, this, gTime().getTime(), gTime().getFrameDelta()));
+	}
+
 	void RenderBeast::renderAllCore(float time, float delta)
 	{
 		THROW_IF_NOT_CORE_THREAD;
@@ -533,6 +533,7 @@ namespace BansheeEngine
 	{
 		gProfilerCPU().beginSample("Render");
 
+		RenderAPICore& rapi = RenderAPICore::instance();
 		const CameraCore* camera = rtData.cameras[camIdx];
 		CameraData& camData = mCameraData[camera];
 
@@ -615,7 +616,7 @@ namespace BansheeEngine
 			SPtr<PassCore> dirPass = dirMaterial->getPass(0);
 
 			setPass(dirPass);
-			mDirLightMat->setStaticParameters(camData.target, perCameraBuffer);
+			mDirLightMat->setStaticParameters(rapi, camData.target, perCameraBuffer);
 
 			for (auto& light : mDirectionalLights)
 			{
@@ -623,10 +624,6 @@ namespace BansheeEngine
 					continue;
 
 				mDirLightMat->setParameters(light.internal);
-
-				// TODO - Bind parameters to the pipeline manually as I don't need to re-bind gbuffer textures for every light
-				//  - I can't think of a good way to do this automatically. Probably best to do it in setParameters()
-				setPassParams(dirMaterial->getPassParameters(0), nullptr);
 				gRendererUtility().drawScreenQuad();
 			}
 
@@ -636,7 +633,7 @@ namespace BansheeEngine
 
 			// TODO - Possibly use instanced drawing here as only two meshes are drawn with various properties
 			setPass(pointInsidePass);
-			mPointLightInMat->setStaticParameters(camData.target, perCameraBuffer);
+			mPointLightInMat->setStaticParameters(rapi, camData.target, perCameraBuffer);
 
 			// TODO - Cull lights based on visibility, right now I just iterate over all of them. 
 			for (auto& light : mPointLights)
@@ -653,9 +650,6 @@ namespace BansheeEngine
 
 				mPointLightInMat->setParameters(light.internal);
 
-				// TODO - Bind parameters to the pipeline manually as I don't need to re-bind gbuffer textures for every light
-				//  - I can't think of a good way to do this automatically. Probably best to do it in setParameters()
-				setPassParams(pointInsideMaterial->getPassParameters(0), nullptr);
 				SPtr<MeshCore> mesh = light.internal->getMesh();
 				gRendererUtility().draw(mesh, mesh->getProperties().getSubMesh(0));
 			}
@@ -665,7 +659,7 @@ namespace BansheeEngine
 			SPtr<PassCore> pointOutsidePass = pointOutsideMaterial->getPass(0);
 
 			setPass(pointOutsidePass);
-			mPointLightOutMat->setStaticParameters(camData.target, perCameraBuffer);
+			mPointLightOutMat->setStaticParameters(rapi, camData.target, perCameraBuffer);
 
 			for (auto& light : mPointLights)
 			{
@@ -681,8 +675,6 @@ namespace BansheeEngine
 
 				mPointLightOutMat->setParameters(light.internal);
 
-				// TODO - Bind parameters to the pipeline manually as I don't need to re-bind gbuffer textures for every light
-				setPassParams(pointOutsideMaterial->getPassParameters(0), nullptr);
 				SPtr<MeshCore> mesh = light.internal->getMesh();
 				gRendererUtility().draw(mesh, mesh->getProperties().getSubMesh(0));
 			}
@@ -1107,11 +1099,7 @@ namespace BansheeEngine
 			for (auto iter = paramDesc.textures.begin(); iter != paramDesc.textures.end(); ++iter)
 			{
 				SPtr<TextureCore> texture = params->getTexture(iter->second.slot);
-
-				if (texture == nullptr)
-					rs.setTexture(stage.type, iter->second.slot, false, nullptr);
-				else
-					rs.setTexture(stage.type, iter->second.slot, true, texture);
+				rs.setTexture(stage.type, iter->second.slot, texture);
 			}
 
 			for (auto iter = paramDesc.loadStoreTextures.begin(); iter != paramDesc.loadStoreTextures.end(); ++iter)
@@ -1125,7 +1113,13 @@ namespace BansheeEngine
 					rs.setLoadStoreTexture(stage.type, iter->second.slot, true, texture, surface);
 			}
 
-			rs.setConstantBuffers(stage.type, params);
+			for (auto iter = paramDesc.paramBlocks.begin(); iter != paramDesc.paramBlocks.end(); ++iter)
+			{
+				SPtr<GpuParamBlockBufferCore> blockBuffer = params->getParamBlockBuffer(iter->second.slot);
+				blockBuffer->flushToGPU();
+
+				rs.setParamBuffer(stage.type, iter->second.slot, blockBuffer, paramDesc);
+			}
 		}
 	}
 

+ 2 - 0
Source/RenderBeast/Source/BsStaticRenderableHandler.cpp

@@ -123,6 +123,8 @@ namespace BansheeEngine
 		mPerCameraParams.gMatScreenToWorld.set(cameraData.screenToWorld);
 		mPerCameraParams.gDeviceZToWorldZ.set(cameraData.deviceZToWorldZ);
 		mPerCameraParams.gClipToUVScaleOffset.set(cameraData.clipToUVScaleOffset);
+
+		mPerCameraParams.flushToGPU();
 	}
 
 	void StaticRenderableHandler::updatePerObjectBuffers(RenderableElement& element, const RenderableShaderData& data, const Matrix4& wvpMatrix)