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

Added a way to manually and easily construct GPU parameter block buffers

BearishSun 10 лет назад
Родитель
Сommit
a50dc98156

+ 1 - 0
BansheeCore/BansheeCore.vcxproj

@@ -302,6 +302,7 @@
     <ClInclude Include="Include\BsMeshImportOptions.h" />
     <ClInclude Include="Include\BsMeshImportOptionsRTTI.h" />
     <ClInclude Include="Include\BsMeshUtility.h" />
+    <ClInclude Include="Include\BsParamBlocks.h" />
     <ClInclude Include="Include\BsPrefab.h" />
     <ClInclude Include="Include\BsPrefabDiff.h" />
     <ClInclude Include="Include\BsPrefabDiffRTTI.h" />

+ 3 - 0
BansheeCore/BansheeCore.vcxproj.filters

@@ -575,6 +575,9 @@
     <ClInclude Include="Include\Win32\BsWin32Window.h">
       <Filter>Header Files\Win32</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsParamBlocks.h">
+      <Filter>Header Files\Renderer</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsCoreApplication.cpp">

+ 12 - 0
BansheeCore/Include/BsGpuParams.h

@@ -20,6 +20,18 @@ namespace BansheeEngine
 		TextureSurface surface;
 	};
 
+	/**
+	 * @brief	Helper structure whose specializations convert an engine data type into a GPU program data parameter type. 
+	 */
+	template<class T> struct TGpuDataParamInfo { };
+	template<> struct TGpuDataParamInfo < float > { enum { TypeId = GPDT_FLOAT1 }; };
+	template<> struct TGpuDataParamInfo < Color > { enum { TypeId = GPDT_FLOAT4 }; };
+	template<> struct TGpuDataParamInfo < Vector2 > { enum { TypeId = GPDT_FLOAT2 }; };
+	template<> struct TGpuDataParamInfo < Vector3 > { enum { TypeId = GPDT_FLOAT3 }; };
+	template<> struct TGpuDataParamInfo < Vector4 > { enum { TypeId = GPDT_FLOAT4 }; };
+	template<> struct TGpuDataParamInfo < Matrix3 > { enum { TypeId = GPDT_MATRIX_3X3 }; };
+	template<> struct TGpuDataParamInfo < Matrix4 > { enum { TypeId = GPDT_MATRIX_4X4 }; };
+
 	/**
 	 * @brief	Contains functionality common for both sim and core thread
 	 *			version of GpuParams.

+ 0 - 5
BansheeCore/Include/BsGpuProgram.h

@@ -140,11 +140,6 @@ namespace BansheeEngine
 		 */
 		virtual bool isAdjacencyInfoRequired() const { return mNeedsAdjacencyInfo; }
 
-		/**
-		 * @brief	Checks whether the program expects matrices in column major format.
-		 */
-		virtual bool hasColumnMajorMatrices() const { return false; }
-
 		/**
 		 * @copydoc	GpuProgram::createParameters
 		 */

+ 89 - 0
BansheeCore/Include/BsParamBlocks.h

@@ -0,0 +1,89 @@
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsGpuParamDesc.h"
+#include "BsGpuParams.h"
+#include "BsRenderAPI.h"
+#include "BsGpuParamBlockBuffer.h"
+
+namespace BansheeEngine
+{
+	/**
+	 * Macros used for manually constructing parameter block buffers used by GPU programs.
+	 */
+
+#define BS_PARAM_BLOCK_BEGIN(Name)																							\
+	struct Name																												\
+	{																														\
+		Name()																												\
+		{																													\
+			SPtr<GpuParamDesc> paramsDesc = bs_shared_ptr_new<GpuParamDesc>();												\
+			paramsDesc->params = getEntries();																				\
+																															\
+			RenderAPICore& rapi = RenderAPICore::instance();																\
+																															\
+			GpuParamBlockDesc blockDesc = rapi.generateParamBlockDesc(#Name, paramsDesc->params);							\
+			paramsDesc->paramBlocks[#Name] = blockDesc;																		\
+																															\
+			mParams = GpuParamsCore::create(paramsDesc, rapi.getGpuProgramHasColumnMajorMatrices());						\
+																															\
+			mBuffer = GpuParamBlockBufferCore::create(blockDesc.blockSize);													\
+			mParams->setParamBlockBuffer(#Name, mBuffer);																	\
+			initEntries();																									\
+		}																													\
+																															\
+		const SPtr<GpuParamBlockBufferCore>& getBuffer() const { return mBuffer; }											\
+																															\
+	private:																												\
+		struct META_FirstEntry {};																							\
+		static void META_GetPrevEntries(Map<String, GpuParamDataDesc>& params, META_FirstEntry id) { }						\
+		void META_InitPrevEntry(const SPtr<GpuParamsCore>& params, META_FirstEntry id) { }									\
+																															\
+		typedef META_FirstEntry 
+
+#define BS_PARAM_BLOCK_ENTRY_ARRAY(Type, Name, NumElements)																	\
+		META_Entry_##Name;																									\
+																															\
+		struct META_NextEntry_##Name {};																					\
+		static void META_GetPrevEntries(Map<String, GpuParamDataDesc>& params, META_NextEntry_##Name id)					\
+		{																													\
+			META_GetPrevEntries(params, META_Entry_##Name##());																\
+																															\
+			GpuParamDataDesc& newEntry = params[#Name];																		\
+			newEntry.name = #Name;																							\
+			newEntry.type = (GpuParamDataType)TGpuDataParamInfo<Type>::TypeId;												\
+			newEntry.arraySize = NumElements;																				\
+		}																													\
+																															\
+		void META_InitPrevEntry(const SPtr<GpuParamsCore>& params, META_NextEntry_##Name id)								\
+		{																													\
+			params->getParam(#Name, Name);																					\
+		}																													\
+																															\
+	public:																													\
+		TGpuDataParam<Type, true> Name;																						\
+																															\
+	private:																												\
+		typedef META_NextEntry_##Name
+
+#define BS_PARAM_BLOCK_ENTRY(Type, Name) BS_PARAM_BLOCK_ENTRY_ARRAY(Type, Name, 1)
+
+#define BS_PARAM_BLOCK_END																									\
+		META_LastEntry;																										\
+																															\
+		static Map<String, GpuParamDataDesc> getEntries()																	\
+		{																													\
+			Map<String, GpuParamDataDesc> entries;																			\
+			META_GetPrevEntries(entries, META_LastEntry());																	\
+			return entries;																									\
+		}																													\
+																															\
+		void initEntries()																									\
+		{																													\
+			META_InitPrevEntry(mParams, META_LastEntry());																	\
+		}																													\
+																															\
+		SPtr<GpuParamsCore> mParams;																						\
+		SPtr<GpuParamBlockBufferCore> mBuffer;																				\
+	};
+}

+ 6 - 1
BansheeCore/Include/BsRenderAPI.h

@@ -432,6 +432,11 @@ namespace BansheeEngine
 		 */
 		virtual bool getVertexColorFlipRequired() const { return false; }
 
+		/**
+		 * @brief	Checks whether GPU programs expect matrices in column major format.
+		 */
+		virtual bool getGpuProgramHasColumnMajorMatrices() const { return false; }
+
 		/**
 		 * @brief	Generates a parameter block description and calculates per-parameter offsets for the provided gpu
 		 * 			data parameters. The offsets are render API specific and correspond to std140 layout for OpenGL, and
@@ -444,7 +449,7 @@ namespace BansheeEngine
 		 * @returns	Descriptor for the parameter block holding the provided parameters as laid out by the default render
 		 * 			API layout.
 		 */
-		//virtual GpuParamBlockDesc generateParamBlockDesc(const String& name, Vector<GpuParamDataDesc>& params) = 0;
+		virtual GpuParamBlockDesc generateParamBlockDesc(const String& name, Map<String, GpuParamDataDesc>& params) = 0;
 
 		/************************************************************************/
 		/* 							INTERNAL METHODS				        	*/

+ 0 - 9
BansheeCore/Source/BsGpuParams.cpp

@@ -194,15 +194,6 @@ UINT32 GpuParamsBase::getDataParamSize(const String& name) const
 		_markCoreDirty();
 	}
 
-	template<class T> struct TDataParamInfo { };
-	template<> struct TDataParamInfo < float > { enum { TypeId = GPDT_FLOAT1 }; };
-	template<> struct TDataParamInfo < Color > { enum { TypeId = GPDT_FLOAT4 }; };
-	template<> struct TDataParamInfo < Vector2 > { enum { TypeId = GPDT_FLOAT2 }; };
-	template<> struct TDataParamInfo < Vector3 > { enum { TypeId = GPDT_FLOAT3 }; };
-	template<> struct TDataParamInfo < Vector4 > { enum { TypeId = GPDT_FLOAT4 }; };
-	template<> struct TDataParamInfo < Matrix3 > { enum { TypeId = GPDT_MATRIX_3X3 }; };
-	template<> struct TDataParamInfo < Matrix4 > { enum { TypeId = GPDT_MATRIX_4X4 }; };
-
 	template<bool Core>
 	template<class T> 
 	void TGpuParams<Core>::getParam(const String& name, TGpuDataParam<T, Core>& output) const

+ 2 - 2
BansheeCore/Source/BsGpuProgram.cpp

@@ -43,7 +43,7 @@ namespace BansheeEngine
 
 	SPtr<GpuParamsCore> GpuProgramCore::createParameters()
 	{
-		return GpuParamsCore::create(mParametersDesc, hasColumnMajorMatrices());
+		return GpuParamsCore::create(mParametersDesc, RenderAPICore::instance().getGpuProgramHasColumnMajorMatrices());
 	}
 
 	SPtr<GpuProgramCore> GpuProgramCore::create(const String& source, const String& entryPoint, const String& language, GpuProgramType gptype,
@@ -72,7 +72,7 @@ namespace BansheeEngine
 
 	GpuParamsPtr GpuProgram::createParameters()
 	{
-		return GpuParams::create(getCore()->getParamDesc(), getCore()->hasColumnMajorMatrices());
+		return GpuParams::create(getCore()->getParamDesc(), RenderAPICore::instance().getGpuProgramHasColumnMajorMatrices());
 	}
 
 	GpuParamDescPtr GpuProgram::getParamDesc() const

+ 0 - 6
BansheeD3D11RenderAPI/Include/BsD3D11GpuProgram.h

@@ -13,11 +13,6 @@ namespace BansheeEngine
 	public:
 		virtual ~D3D11GpuProgramCore();
 
-		/**
-		 * @copydoc	GpuProgramCore::hasColumnMajorMatrices
-		 */
-		bool hasColumnMajorMatrices() const override { return mColumnMajorMatrices; }
-
 		/**
 		 * @brief	Returns compiled shader microcode.
 		 */
@@ -64,7 +59,6 @@ namespace BansheeEngine
 	protected:
 		static UINT32 GlobalProgramId;
 
-		bool mColumnMajorMatrices;
 		bool mEnableBackwardsCompatibility;
 		UINT32 mProgramId;
 

+ 5 - 0
BansheeD3D11RenderAPI/Include/BsD3D11RenderAPI.h

@@ -176,6 +176,11 @@ namespace BansheeEngine
 		 */
 		float getMaximumDepthInputValue() override;
 
+		/**
+		 * @copydoc RenderAPICore::generateParamBlockDesc()
+		 */
+		GpuParamBlockDesc generateParamBlockDesc(const String& name, Map<String, GpuParamDataDesc>& params) override;
+
 		/************************************************************************/
 		/* 				Internal use by DX11 RenderSystem only                  */
 		/************************************************************************/

+ 2 - 5
BansheeD3D11RenderAPI/Source/BsD3D11GpuProgram.cpp

@@ -16,7 +16,7 @@ namespace BansheeEngine
 	D3D11GpuProgramCore::D3D11GpuProgramCore(const String& source, const String& entryPoint, GpuProgramType gptype,
 		GpuProgramProfile profile, bool isAdjacencyInfoRequired)
 		: GpuProgramCore(source, entryPoint, gptype, profile, isAdjacencyInfoRequired),
-		mColumnMajorMatrices(false), mEnableBackwardsCompatibility(false), mProgramId(0)
+		mEnableBackwardsCompatibility(false), mProgramId(0)
 	{
 
 	}
@@ -73,10 +73,7 @@ namespace BansheeEngine
 		compileFlags |= D3DCOMPILE_SKIP_OPTIMIZATION;
 #endif
 
-		if (mColumnMajorMatrices)
-			compileFlags |= D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR;
-		else
-			compileFlags |= D3DCOMPILE_PACK_MATRIX_ROW_MAJOR;
+		compileFlags |= D3DCOMPILE_PACK_MATRIX_ROW_MAJOR;
 
 		if (mEnableBackwardsCompatibility)
 			compileFlags |= D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY;

+ 6 - 0
BansheeD3D11RenderAPI/Source/BsD3D11RenderAPI.cpp

@@ -1055,6 +1055,12 @@ namespace BansheeEngine
 		return 1.0f;
 	}
 
+	GpuParamBlockDesc D3D11RenderAPI::generateParamBlockDesc(const String& name, Map<String, GpuParamDataDesc>& params)
+	{
+		// TODO - Not implemented
+		return GpuParamBlockDesc();
+	}
+
 	/************************************************************************/
 	/* 								PRIVATE		                     		*/
 	/************************************************************************/

+ 7 - 12
BansheeD3D9RenderAPI/Include/BsD3D9GpuProgram.h

@@ -38,11 +38,6 @@ namespace BansheeEngine
 		 */
 		void setOptimizationLevel(OptimizationLevel opt) { mOptimisationLevel = opt; }
 
-		/**
-		 * @copydoc	GpuProgramCore::hasColumnMajorMatrices
-		 */
-		bool hasColumnMajorMatrices() const { return mColumnMajorMatrices; }
-
     protected:
 		friend class D3D9HLSLProgramFactory;
 
@@ -52,7 +47,7 @@ namespace BansheeEngine
 		/**
 		 * @copydoc GpuProgramCore::initialize
 		 */
-		void initialize();
+		void initialize() override;
       
 		/**
 		 * @brief	Loads the GPU program from compiled microcode.
@@ -83,12 +78,12 @@ namespace BansheeEngine
 		/**
 		 * @copydoc D3D9Resource::notifyOnDeviceCreate
 		 */
-		virtual void notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device);
+		virtual void notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device) override;
 
 		/**
 		 * @copydoc D3D9Resource::notifyOnDeviceDestroy
 		 */
-		virtual void notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device);
+		virtual void notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device) override;
 
     protected:
 		friend class D3D9HLSLProgramFactory;
@@ -98,7 +93,7 @@ namespace BansheeEngine
 		/**
 		 * @copydoc	D3D9GpuProgramCore::loadFromMicrocode
 		 */
-        void loadFromMicrocode(IDirect3DDevice9* d3d9Device, ID3DXBuffer* microcode);
+		void loadFromMicrocode(IDirect3DDevice9* d3d9Device, ID3DXBuffer* microcode) override;
 
 	protected:
 		Map<IDirect3DDevice9*, IDirect3DVertexShader9*>	mMapDeviceToVertexShader;
@@ -118,12 +113,12 @@ namespace BansheeEngine
 		/**
 		 * @copydoc D3D9Resource::notifyOnDeviceCreate
 		 */
-		virtual void notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device);
+		virtual void notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device) override;
 
 		/**
 		 * @copydoc D3D9Resource::notifyOnDeviceDestroy
 		 */
-		virtual void notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device);
+		virtual void notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device) override;
 
     protected:
 		friend class D3D9HLSLProgramFactory;
@@ -133,7 +128,7 @@ namespace BansheeEngine
 		/**
 		 * @copydoc	D3D9GpuProgramCore::loadFromMicrocode
 		 */
-        void loadFromMicrocode(IDirect3DDevice9* d3d9Device, ID3DXBuffer* microcode);
+		void loadFromMicrocode(IDirect3DDevice9* d3d9Device, ID3DXBuffer* microcode) override;
 
 	protected:
 		Map<IDirect3DDevice9*, IDirect3DPixelShader9*> mMapDeviceToPixelShader;

+ 5 - 0
BansheeD3D9RenderAPI/Include/BsD3D9RenderAPI.h

@@ -176,6 +176,11 @@ namespace BansheeEngine
 		 */
 		bool getVertexColorFlipRequired() const override { return true; }
 
+		/**
+		 * @copydoc RenderAPICore::generateParamBlockDesc()
+		 */
+		GpuParamBlockDesc generateParamBlockDesc(const String& name, Map<String, GpuParamDataDesc>& params) override;
+
 		/************************************************************************/
 		/* 				Internal use by DX9 RenderAPI only                   */
 		/************************************************************************/

+ 2 - 5
BansheeD3D9RenderAPI/Source/BsD3D9GpuProgram.cpp

@@ -15,7 +15,7 @@ namespace BansheeEngine
     D3D9GpuProgramCore::D3D9GpuProgramCore(const String& source, const String& entryPoint, 
 		GpuProgramType gptype, GpuProgramProfile profile)
 		: GpuProgramCore(source, entryPoint, gptype, profile, false),
-		mMicrocode(nullptr), mColumnMajorMatrices(false), mOptimisationLevel(OPT_DEFAULT)
+		mMicrocode(nullptr), mOptimisationLevel(OPT_DEFAULT)
     { }
 
 	D3D9GpuProgramCore::~D3D9GpuProgramCore()
@@ -114,10 +114,7 @@ namespace BansheeEngine
 
 		// Populate compile flags
 		DWORD compileFlags = 0;
-		if (mColumnMajorMatrices)
-			compileFlags |= D3DXSHADER_PACKMATRIX_COLUMNMAJOR;
-		else
-			compileFlags |= D3DXSHADER_PACKMATRIX_ROWMAJOR;
+		compileFlags |= D3DXSHADER_PACKMATRIX_ROWMAJOR;
 
 #if BS_DEBUG_MODE
 		compileFlags |= D3DXSHADER_DEBUG;

+ 6 - 0
BansheeD3D9RenderAPI/Source/BsD3D9RenderAPI.cpp

@@ -1474,6 +1474,12 @@ namespace BansheeEngine
 		dest[2][3] = (dest[2][3] + dest[3][3]) / 2;
 	}
 
+	GpuParamBlockDesc D3D9RenderAPI::generateParamBlockDesc(const String& name, Map<String, GpuParamDataDesc>& params)
+	{
+		// TODO - Not implemented
+		return GpuParamBlockDesc();
+	}
+
 	/************************************************************************/
 	/* 								PRIVATE		                     		*/
 	/************************************************************************/

+ 6 - 1
BansheeGLRenderAPI/Include/BsGLRenderAPI.h

@@ -169,10 +169,15 @@ namespace BansheeEngine
 		 */
 		void convertProjectionMatrix(const Matrix4& matrix, Matrix4& dest) override;
 
+		/**
+		 * @copydoc RenderAPICore::getGpuProgramHasColumnMajorMatrices
+		 */
+		bool getGpuProgramHasColumnMajorMatrices() const override;
+
 		/**
 		 * @copydoc RenderAPICore::generateParamBlockDesc()
 		 */
-		GpuParamBlockDesc generateParamBlockDesc(const String& name, Vector<GpuParamDataDesc>& params);
+		GpuParamBlockDesc generateParamBlockDesc(const String& name, Map<String, GpuParamDataDesc>& params) override;
 
 		/************************************************************************/
 		/* 				Internal use by OpenGL RenderSystem only                */

+ 8 - 4
BansheeGLRenderAPI/Source/BsGLRenderAPI.cpp

@@ -2118,7 +2118,12 @@ namespace BansheeEngine
 		dest = matrix;
 	}
 
-	GpuParamBlockDesc GLRenderAPI::generateParamBlockDesc(const String& name, Vector<GpuParamDataDesc>& params)
+	bool GLRenderAPI::getGpuProgramHasColumnMajorMatrices() const 
+	{ 
+		return true; 
+	}
+
+	GpuParamBlockDesc GLRenderAPI::generateParamBlockDesc(const String& name, Map<String, GpuParamDataDesc>& params)
 	{
 		GpuParamBlockDesc block;
 		block.blockSize = 0;
@@ -2126,11 +2131,10 @@ namespace BansheeEngine
 		block.name = name;
 		block.slot = 0;
 
-		UINT32 numParams = (UINT32)params.size();
 		UINT32 curOffset = 0;
-		for (UINT32 i = 0; i < numParams; i++)
+		for (auto& entry : params)
 		{
-			GpuParamDataDesc& param = params[i];
+			GpuParamDataDesc& param = entry.second;
 
 			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[param.type];
 			UINT32 sizeBytes = typeInfo.size;

+ 0 - 5
BansheeGLRenderAPI/Source/GLSL/include/BsGLSLGpuProgram.h

@@ -36,11 +36,6 @@ namespace BansheeEngine
 		 */
 		UINT32 getProgramID() const { return mProgramID; }
 
-		/**
-		 * @copydoc	GpuProgramCore::hasColumnMajorMatrices
-		 */
-		bool hasColumnMajorMatrices() const override { return true; }
-
 	private:
 		friend class GLSLProgramFactory;
 

+ 32 - 0
RenderBeast/Include/BsLightRendering.h

@@ -2,9 +2,37 @@
 
 #include "BsRenderBeastPrerequisites.h"
 #include "BsRendererMaterial.h"
+#include "BsParamBlocks.h"
 
 namespace BansheeEngine
 {
+	BS_PARAM_BLOCK_BEGIN(PerLightParamBuffer)
+		BS_PARAM_BLOCK_ENTRY(Vector4, gLightPositionAndType)
+		BS_PARAM_BLOCK_ENTRY(Vector4, gLightColorAndIntensity)
+		BS_PARAM_BLOCK_ENTRY(Vector2, gLightSpotAngles)
+		BS_PARAM_BLOCK_ENTRY(Vector3, gLightDirection)
+		BS_PARAM_BLOCK_ENTRY(Vector4, gLightGeometry)
+	BS_PARAM_BLOCK_END
+
+	/**
+	 * Manipulates PerLight parameter buffer used in various shaders.
+	 */
+	class PerLightParams
+	{
+	public:
+		/**
+		 * 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:
+		PerLightParamBuffer mBuffer;
+	};
+
 	/**
 	 * Shader that renders directional light sources during deferred rendering light pass. 
 	 */
@@ -22,6 +50,8 @@ namespace BansheeEngine
 		 * @copydoc RendererMaterial::initialize
 		 */
 		void initialize() override;
+
+		PerLightParams mParams; // Note: Should this buffer be shared between both point and directional lights?
 	};
 
 	/**
@@ -41,5 +71,7 @@ namespace BansheeEngine
 		 * @copydoc RendererMaterial::initialize
 		 */
 		void initialize() override;
+
+		PerLightParams mParams; // Note: Should this buffer be shared between both point and directional lights?
 	};
 }

+ 45 - 79
RenderBeast/Source/BsLightRendering.cpp

@@ -3,113 +3,79 @@
 #include "BsGpuParams.h"
 #include "BsLight.h"
 
+
 namespace BansheeEngine
 {
-	/**
-	 * Manipulates PerLight parameter buffer used in various shaders.
-	 */
-	class PerLightParamBuffer
+	void PerLightParams::setParameters(const LightCore* light)
 	{
-	public:
-		// TODO - Doc
-		void initialize()
+		// Note: I could just copy the data directly to the parameter buffer if I ensured the parameter
+		// layout matches
+
+		Vector4 positionAndType = (Vector4)light->getPosition();
+
+		switch (light->getType())
 		{
-			// TODO - This is never called
-			// TODO - Create the buffer (think of an automated way of doing it, creating the desc and retrieving the params.
-			
-			mParams->getParam("gLightPositionAndType", mParamLightPositionAndType);
-			mParams->getParam("gLightColorAndIntensity", mParamLightColorAndIntensity);
-			mParams->getParam("gLightSpotAngles", mParamLightSpotAngles);
-			mParams->getParam("gLightDirection", mParamLightDirection);
-			mParams->getParam("gLightGeometry", mParamLightGeometry);
+		case LightType::Directional:
+			positionAndType.w = 0;
+			break;
+		case LightType::Point:
+			positionAndType.w = 0.3f;
+			break;
+		case LightType::Spot:
+			positionAndType.w = 0.8f;
+			break;
 		}
 
-		// TODO - Doc
-		void setParameters(const LightCore* light)
-		{
-			// Note: I could just copy the data directly to the parameter buffer if I ensured the parameter
-			// layout matches
-
-			Vector4 positionAndType = (Vector4)light->getPosition();
-
-			switch (light->getType())
-			{
-			case LightType::Directional:
-				positionAndType.w = 0;
-				break;
-			case LightType::Point:
-				positionAndType.w = 0.3f;
-				break;
-			case LightType::Spot:
-				positionAndType.w = 0.8f;
-				break;
-			}
-
-			mParamLightPositionAndType.set(positionAndType);
+		mBuffer.gLightPositionAndType.set(positionAndType);
 			
-			Vector4 colorAndIntensity;
-			colorAndIntensity.x = light->getColor().r;
-			colorAndIntensity.y = light->getColor().g;
-			colorAndIntensity.z = light->getColor().b;
-			colorAndIntensity.w = light->getIntensity();
-
-			mParamLightColorAndIntensity.set(colorAndIntensity);
-
-			Vector2 spotAngles;
-			spotAngles.x = light->getSpotFalloffAngle().valueDegrees();
-			spotAngles.y = light->getSpotAngle().valueDegrees();
-
-			mParamLightSpotAngles.set(spotAngles);
+		Vector4 colorAndIntensity;
+		colorAndIntensity.x = light->getColor().r;
+		colorAndIntensity.y = light->getColor().g;
+		colorAndIntensity.z = light->getColor().b;
+		colorAndIntensity.w = light->getIntensity();
 
-			mParamLightDirection.set(light->getRotation().zAxis());
+		mBuffer.gLightColorAndIntensity.set(colorAndIntensity);
 
-			Vector4 lightGeometry;
-			lightGeometry.x = 20; // Cone geometry sides
-			lightGeometry.y = 10; // Cone geometry slices
-			lightGeometry.z = light->getBounds().getRadius();
+		Vector2 spotAngles;
+		spotAngles.x = light->getSpotFalloffAngle().valueDegrees();
+		spotAngles.y = light->getSpotAngle().valueDegrees();
 
-			lightGeometry.w = light->getSpotAngle().valueDegrees();
+		mBuffer.gLightSpotAngles.set(spotAngles);
 
-			mParamLightGeometry.set(lightGeometry);
-		}
-
-		// TODO - Doc
-		SPtr<GpuParamBlockBufferCore> getBuffer()
-		{
-			return mParams->getParamBlockBuffer(0);
-		}
+		mBuffer.gLightDirection.set(light->getRotation().zAxis());
 
-		static PerLightParamBuffer instance;
+		Vector4 lightGeometry;
+		lightGeometry.x = 20; // Cone geometry sides
+		lightGeometry.y = 10; // Cone geometry slices
+		lightGeometry.z = light->getBounds().getRadius();
 
-	private:
-		SPtr<GpuParamsCore> mParams;
+		lightGeometry.w = light->getSpotAngle().valueDegrees();
 
-		GpuParamVec4Core mParamLightPositionAndType;
-		GpuParamVec4Core mParamLightColorAndIntensity;
-		GpuParamVec2Core mParamLightSpotAngles;
-		GpuParamVec3Core mParamLightDirection;
-		GpuParamVec4Core mParamLightGeometry;
-	};
-
-	PerLightParamBuffer PerLightParamBuffer::instance;
+		mBuffer.gLightGeometry.set(lightGeometry);
+	}
 
+	const SPtr<GpuParamBlockBufferCore>& PerLightParams::getBuffer() const
+	{
+		return mBuffer.getBuffer();
+	}
+	
 	void DirectionalLightMat::setParameters(const LightCore* light)
 	{
-		PerLightParamBuffer::instance.setParameters(light);
+		mParams.setParameters(light);
 	}
 
 	void DirectionalLightMat::initialize()
 	{
-		mMaterial->setParamBlockBuffer("PerLight", PerLightParamBuffer::instance.getBuffer());
+		mMaterial->setParamBlockBuffer("PerLight", mParams.getBuffer());
 	}
 
 	void PointLightMat::setParameters(const LightCore* light)
 	{
-		PerLightParamBuffer::instance.setParameters(light);
+		mParams.setParameters(light);
 	}
 
 	void PointLightMat::initialize()
 	{
-		mMaterial->setParamBlockBuffer("PerLight", PerLightParamBuffer::instance.getBuffer());
+		mMaterial->setParamBlockBuffer("PerLight", mParams.getBuffer());
 	}
 }