/* 
	definitions for generic SPU job spawning

	3 similar classes are created: main job class, packet class and packet class which runs on its own SPU
	currently parameter count is fixed to a max of 6, 
	if changing parameter count, change it in all 3 class types plus adapt producer/consumer queue
*/

#ifndef __GENERIC_SPUJOB_H
#define __GENERIC_SPUJOB_H
#pragma once

#if defined(PS3)

#include <string.h>
#include <IJobManSPU.h>
#define MAX_PARAM_SIZE_GENERIC 128

struct SNullType
{
	unsigned char dummy[0];
};

template<class ClassType>
struct SClassArg;

template<class ClassType>
struct SClassArg
{
	typedef ClassType* TClassTypePtr;
};

template<>
struct SClassArg<SNullType>
{
	typedef SNullType TClassTypePtr;
};

#if defined(__SPU__)
	template<class ClassName = SNullType>
	struct SGenericSPUJob;

	template<class ClassName>
	struct SGenericSPUJob : public NPPU::CSPUJobBase

#else //__SPU__

	template<const char* ProgramData, class ClassName = SNullType>
	struct SGenericSPUJob;

	template<const char* ProgramData, class ClassName>
	struct SGenericSPUJob : public NPPU::CSPUJobBase

#endif//__SPU__
{
#if !defined(__SPU__)
	static ILINE const NPPU::TJobHandle GetProgramHandle()
	{
		static NPPU::TJobHandle sHandle(GetIJobManSPU()->GetJobHandle(ProgramData, strlen(ProgramData)));
		return sHandle;
	}

#if defined(SUPP_SPU_FRAME_STATS) && !defined(__SPU__)
	static ILINE NPPU::SFrameProfileData* GetFrameProfData()
	{
		static NPPU::SFrameProfileData sFrameProfileData(ProgramData);//one per job instance type
		return &sFrameProfileData;
	}
#endif

	ILINE const uint32 GetJobID()
	{
		return GetProgramHandle()->jobId;
	}

	ILINE const char* GetJobName()
	{
		return GetProgramHandle()->cpString;
	}

	ILINE const uint32 GetJobAddress()
	{
		return (uint32)GetProgramHandle()->jobHandle;
	}
#endif

	ILINE void SetParamDataSize(const unsigned int cParamSize)
	{
		this->m_JobDelegator.SetParamDataSize((cParamSize + 0xF) & ~0xF);
	}

	ILINE void SetupCommonJob(const unsigned int cParamSize)
	{
		this->m_JobDelegator.SetJobParamData((void*)paramMem);
		SetParamDataSize(cParamSize);
#if !defined(__SPU__)
		#if defined(SUPP_SPU_FRAME_STATS)
			this->m_JobDelegator.SetFrameProfData(GetFrameProfData());
		#endif
		this->SetJobProgramData(GetProgramHandle());
#endif
	}

//-------------------------------------------------ctor application, cur. 11 params supported-------------------------------------------------

	ILINE SGenericSPUJob()
	{
		struct SParams
		{
			typename SClassArg<ClassName>::TClassTypePtr pClassInst;
		} _ALIGN(16);

		SetupCommonJob(sizeof(SParams));
	}

	template<class T0>
	ILINE SGenericSPUJob(T0 t0)
	{
		struct SParams
		{
			typename SClassArg<ClassName>::TClassTypePtr pClassInst;
			T0 _t0;
			SParams(T0 t0_) : _t0(t0_){}
		} _ALIGN(16);

		*(SParams*)paramMem = SParams(t0);
		SetupCommonJob(sizeof(SParams));
	}

	template<class T0, class T1>
	ILINE SGenericSPUJob(T0 t0, T1 t1)
	{
		struct SParams
		{
			typename SClassArg<ClassName>::TClassTypePtr pClassInst;
			T0 _t0;
			T1 _t1;
			SParams(T0 t0_, T1 t1_) : _t0(t0_), _t1(t1_){}
		}_ALIGN(16);

		*(SParams*)paramMem = SParams(t0, t1);
		SetupCommonJob(sizeof(SParams));
	}

	template<class T0, class T1, class T2>
	ILINE SGenericSPUJob(T0 t0, T1 t1, T2 t2)
	{
		struct SParams
		{
			typename SClassArg<ClassName>::TClassTypePtr pClassInst;
			T0 _t0;
			T1 _t1;
			T2 _t2;
			SParams(T0 t0_, T1 t1_, T2 t2_) : _t0(t0_), _t1(t1_), _t2(t2_){}
		} _ALIGN(16);

		*(SParams*)paramMem = SParams(t0, t1, t2);
		SetupCommonJob(sizeof(SParams));
	}

	template<class T0, class T1, class T2, class T3>
	ILINE SGenericSPUJob(T0 t0, T1 t1, T2 t2, T3 t3)
	{
		struct SParams
		{
			typename SClassArg<ClassName>::TClassTypePtr pClassInst;
			T0 _t0;
			T1 _t1;
			T2 _t2;
			T3 _t3;
			SParams(T0 t0_, T1 t1_, T2 t2_, T3 t3_) : _t0(t0_), _t1(t1_), _t2(t2_), _t3(t3_){}
		} _ALIGN(16);

		*(SParams*)paramMem = SParams(t0, t1, t2, t3);
		SetupCommonJob(sizeof(SParams));
	}

	template<class T0, class T1, class T2, class T3, class T4>
	ILINE SGenericSPUJob(T0 t0, T1 t1, T2 t2, T3 t3, T4 t4)
	{
		struct SParams
		{
			typename SClassArg<ClassName>::TClassTypePtr pClassInst;
			T0 _t0;
			T1 _t1;
			T2 _t2;
			T3 _t3;
			T4 _t4;
			SParams(T0 t0_, T1 t1_, T2 t2_, T3 t3_, T4 t4_) : _t0(t0_), _t1(t1_), _t2(t2_), _t3(t3_), _t4(t4_){}
		} _ALIGN(16);

		*(SParams*)paramMem = SParams(t0, t1, t2, t3, t4);
		SetupCommonJob(sizeof(SParams));
	}

	template<class T0, class T1, class T2, class T3, class T4, class T5>
	ILINE SGenericSPUJob(T0 t0, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
	{
		struct SParams
		{
			typename SClassArg<ClassName>::TClassTypePtr pClassInst;
			T0 _t0;
			T1 _t1;
			T2 _t2;
			T3 _t3;
			T4 _t4;
			T5 _t5;
			SParams(T0 t0_, T1 t1_, T2 t2_, T3 t3_, T4 t4_, T5 t5_) : _t0(t0_), _t1(t1_), _t2(t2_), _t3(t3_), _t4(t4_), _t5(t5_){}
		} _ALIGN(16);

		*(SParams*)paramMem = SParams(t0, t1, t2, t3, t4, t5);
		SetupCommonJob(sizeof(SParams));
	}
	
	template<class T0, class T1, class T2, class T3, class T4, class T5, class T6>
	ILINE SGenericSPUJob(T0 t0, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
	{
		struct SParams
		{
			typename SClassArg<ClassName>::TClassTypePtr pClassInst;
			T0 _t0;
			T1 _t1;
			T2 _t2;
			T3 _t3;
			T4 _t4;
			T6 _t5;
			T5 _t6;
			SParams(T0 t0_, T1 t1_, T2 t2_, T3 t3_, T4 t4_, T5 t5_, T6 t6_) : _t0(t0_), _t1(t1_), _t2(t2_), _t3(t3_), _t4(t4_), _t5(t5_), _t6(t6_){}
		} _ALIGN(16);

		*(SParams*)paramMem = SParams(t0, t1, t2, t3, t4, t5, t6);
		SetupCommonJob(sizeof(SParams));
	}

	template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7>
	ILINE SGenericSPUJob(T0 t0, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
	{
		struct SParams
		{
			typename SClassArg<ClassName>::TClassTypePtr pClassInst;
			T0 _t0;
			T1 _t1;
			T2 _t2;
			T3 _t3;
			T4 _t4;
			T5 _t5;
			T6 _t6;
			T7 _t7;
			SParams(T0 t0_, T1 t1_, T2 t2_, T3 t3_, T4 t4_, T5 t5_, T6 t6_, T7 t7_) : 
				_t0(t0_), _t1(t1_), _t2(t2_), _t3(t3_), _t4(t4_), _t5(t5_), _t6(t6_), _t7(t7_){}
		} _ALIGN(16);

		*(SParams*)paramMem = SParams(t0, t1, t2, t3, t4, t5, t6, t7);
		SetupCommonJob(sizeof(SParams));
	}

	template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
	ILINE SGenericSPUJob(T0 t0, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
	{
		struct SParams
		{
			typename SClassArg<ClassName>::TClassTypePtr pClassInst;
			T0 _t0;
			T1 _t1;
			T2 _t2;
			T3 _t3;
			T4 _t4;
			T5 _t5;
			T6 _t6;
			T7 _t7;
			T8 _t8;
			SParams(T0 t0_, T1 t1_, T2 t2_, T3 t3_, T4 t4_, T5 t5_, T6 t6_, T7 t7_, T8 t8_) : 
			_t0(t0_), _t1(t1_), _t2(t2_), _t3(t3_), _t4(t4_), _t5(t5_), _t6(t6_), _t7(t7_), _t8(t8_){}
		} _ALIGN(16);

		*(SParams*)paramMem = SParams(t0, t1, t2, t3, t4, t5, t6, t7, t8);
		SetupCommonJob(sizeof(SParams));
	}

	template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
	ILINE SGenericSPUJob(T0 t0, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9)
	{
		struct SParams
		{
			typename SClassArg<ClassName>::TClassTypePtr pClassInst;
			T0 _t0;
			T1 _t1;
			T2 _t2;
			T3 _t3;
			T4 _t4;
			T5 _t5;
			T6 _t6;
			T7 _t7;
			T8 _t8;
			T9 _t9;
			SParams(T0 t0_, T1 t1_, T2 t2_, T3 t3_, T4 t4_, T5 t5_, T6 t6_, T7 t7_, T8 t8_, T9 t9_) : 
			_t0(t0_), _t1(t1_), _t2(t2_), _t3(t3_), _t4(t4_), _t5(t5_), _t6(t6_), _t7(t7_), _t8(t8_), _t9(t9_){}
		} _ALIGN(16);

		*(SParams*)paramMem = SParams(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9);
		SetupCommonJob(sizeof(SParams));
	}

	template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10>
	ILINE SGenericSPUJob(T0 t0, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10)
	{
		struct SParams
		{
			typename SClassArg<ClassName>::TClassTypePtr pClassInst;
			T0 _t0;
			T1 _t1;
			T2 _t2;
			T3 _t3;
			T4 _t4;
			T5 _t5;
			T6 _t6;
			T7 _t7;
			T8 _t8;
			T9 _t9;
			T10 _t10;
			SParams(T0 t0_, T1 t1_, T2 t2_, T3 t3_, T4 t4_, T5 t5_, T6 t6_, T7 t7_, T8 t8_, T9 t9_, T10 t10_) : 
			_t0(t0_), _t1(t1_), _t2(t2_), _t3(t3_), _t4(t4_), _t5(t5_), _t6(t6_), _t7(t7_), _t8(t8_), _t9(t9_), _t10(t10_){}
		} _ALIGN(16);

		*(SParams*)paramMem = SParams(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10);
		SetupCommonJob(sizeof(SParams));
	}

//-------------------------------------------------explicit parameter application, cur. 6 params supported-------------------------------------------------

	template<class T0>
	ILINE void SetParams(T0 t0)
	{
		struct SParams
		{
			typename SClassArg<ClassName>::TClassTypePtr pClassInst;
			T0 _t0;
			SParams(T0 t0_) : _t0(t0_){}
		} _ALIGN(16);

		*(SParams*)paramMem = SParams(t0);
		this->m_JobDelegator.SetParamDataSize((sizeof(SParams) + 0xF) & ~0xF);
	}

	template<class T0, class T1>
	ILINE void SetParams(T0 t0, T1 t1)
	{
		struct SParams
		{
			typename SClassArg<ClassName>::TClassTypePtr pClassInst;
			T0 _t0;
			T1 _t1;
			SParams(T0 t0_, T1 t1_) : _t0(t0_), _t1(t1_){}
		}_ALIGN(16);

		*(SParams*)paramMem = SParams(t0, t1);
		this->m_JobDelegator.SetParamDataSize((sizeof(SParams) + 0xF) & ~0xF);
	}

	template<class T0, class T1, class T2>
	ILINE void SetParams(T0 t0, T1 t1, T2 t2)
	{
		struct SParams
		{
			typename SClassArg<ClassName>::TClassTypePtr pClassInst;
			T0 _t0;
			T1 _t1;
			T2 _t2;
			SParams(T0 t0_, T1 t1_, T2 t2_) : _t0(t0_), _t1(t1_), _t2(t2_){}
		} _ALIGN(16);

		*(SParams*)paramMem = SParams(t0, t1, t2);
		this->m_JobDelegator.SetParamDataSize((sizeof(SParams) + 0xF) & ~0xF);
	}

	template<class T0, class T1, class T2, class T3>
	ILINE void SetParams(T0 t0, T1 t1, T2 t2, T3 t3)
	{
		struct SParams
		{
			typename SClassArg<ClassName>::TClassTypePtr pClassInst;
			T0 _t0;
			T1 _t1;
			T2 _t2;
			T3 _t3;
			SParams(T0 t0_, T1 t1_, T2 t2_, T3 t3_) : _t0(t0_), _t1(t1_), _t2(t2_), _t3(t3_){}
		} _ALIGN(16);

		*(SParams*)paramMem = SParams(t0, t1, t2, t3);
		this->m_JobDelegator.SetParamDataSize((sizeof(SParams) + 0xF) & ~0xF);
	}

	template<class T0, class T1, class T2, class T3, class T4>
	ILINE void SetParams(T0 t0, T1 t1, T2 t2, T3 t3, T4 t4)
	{
		struct SParams
		{
			typename SClassArg<ClassName>::TClassTypePtr pClassInst;
			T0 _t0;
			T1 _t1;
			T2 _t2;
			T3 _t3;
			T4 _t4;
			SParams(T0 t0_, T1 t1_, T2 t2_, T3 t3_, T4 t4_) : _t0(t0_), _t1(t1_), _t2(t2_), _t3(t3_), _t4(t4_){}
		} _ALIGN(16);

		*(SParams*)paramMem = SParams(t0, t1, t2, t3, t4);
		this->m_JobDelegator.SetParamDataSize((sizeof(SParams) + 0xF) & ~0xF);
	}

	template<class T0, class T1, class T2, class T3, class T4, class T5>
	ILINE void SetParams(T0 t0, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
	{
		struct SParams
		{
			typename SClassArg<ClassName>::TClassTypePtr pClassInst;
			T0 _t0;
			T1 _t1;
			T2 _t2;
			T3 _t3;
			T4 _t4;
			T5 _t5;
			SParams(T0 t0_, T1 t1_, T2 t2_, T3 t3_, T4 t4_, T5 t5_) : _t0(t0_), _t1(t1_), _t2(t2_), _t3(t3_), _t4(t4_), _t5(t5_){}
		} _ALIGN(16);

		*(SParams*)paramMem = SParams(t0, t1, t2, t3, t4, t5);
		this->m_JobDelegator.SetParamDataSize((sizeof(SParams) + 0xF) & ~0xF);
	}

	void SetClassInstance(ClassName& rClassInstance)
	{
		STATIC_CHECK(sizeof(ClassName), DO_NOT_SET_INSTANCE_FOR_NULL_TYPE);
		*(ClassName**)paramMem = &rClassInstance;
	}

	unsigned char paramMem[MAX_PARAM_SIZE_GENERIC - sizeof(NPPU::CSPUJobBase)] _ALIGN(128);//parameter memory to store parameters

//-----------------------------------------------spu packet----------------------------------------------	

	struct spu_packet : public NPPU::CSPUPacketBase
	{
		ILINE void SetupCommonJob(const unsigned int cParamSize)
		{
			this->m_JobDelegator.SetJobParamData((void*)paramMem);
		}

		ILINE spu_packet()
		{
			struct SParams
			{
				typename SClassArg<ClassName>::TClassTypePtr pClassInst;
			} _ALIGN(16);

			SetupCommonJob(sizeof(SParams));
		}

		template<class T0>
		ILINE spu_packet(T0 t0)
		{
			struct SParams
			{
				typename SClassArg<ClassName>::TClassTypePtr pClassInst;
				T0 _t0;
				SParams(T0 t0_) : _t0(t0_){}
			} _ALIGN(16);

			*(SParams*)paramMem = SParams(t0);
			SetupCommonJob(sizeof(SParams));
		}

		template<class T0, class T1>
		ILINE spu_packet(T0 t0, T1 t1)
		{
			struct SParams
			{
				typename SClassArg<ClassName>::TClassTypePtr pClassInst;
				T0 _t0;
				T1 _t1;
				SParams(T0 t0_, T1 t1_) : _t0(t0_), _t1(t1_){}
			}_ALIGN(16);

			*(SParams*)paramMem = SParams(t0, t1);
			SetupCommonJob(sizeof(SParams));
		}

		template<class T0, class T1, class T2>
		ILINE spu_packet(T0 t0, T1 t1, T2 t2)
		{
			struct SParams
			{
				typename SClassArg<ClassName>::TClassTypePtr pClassInst;
				T0 _t0;
				T1 _t1;
				T2 _t2;
				SParams(T0 t0_, T1 t1_, T2 t2_) : _t0(t0_), _t1(t1_), _t2(t2_){}
			} _ALIGN(16);

			*(SParams*)paramMem = SParams(t0, t1, t2);
			SetupCommonJob(sizeof(SParams));
		}

		template<class T0, class T1, class T2, class T3>
		ILINE spu_packet(T0 t0, T1 t1, T2 t2, T3 t3)
		{
			struct SParams
			{
				typename SClassArg<ClassName>::TClassTypePtr pClassInst;
				T0 _t0;
				T1 _t1;
				T2 _t2;
				T3 _t3;
				SParams(T0 t0_, T1 t1_, T2 t2_, T3 t3_) : _t0(t0_), _t1(t1_), _t2(t2_), _t3(t3_){}
			} _ALIGN(16);

			*(SParams*)paramMem = SParams(t0, t1, t2, t3);
			SetupCommonJob(sizeof(SParams));
		}

		template<class T0, class T1, class T2, class T3, class T4>
		ILINE spu_packet(T0 t0, T1 t1, T2 t2, T3 t3, T4 t4)
		{
			struct SParams
			{
				typename SClassArg<ClassName>::TClassTypePtr pClassInst;
				T0 _t0;
				T1 _t1;
				T2 _t2;
				T3 _t3;
				T4 _t4;
				SParams(T0 t0_, T1 t1_, T2 t2_, T3 t3_, T4 t4_) : _t0(t0_), _t1(t1_), _t2(t2_), _t3(t3_), _t4(t4_){}
			} _ALIGN(16);

			*(SParams*)paramMem = SParams(t0, t1, t2, t3, t4);
			SetupCommonJob(sizeof(SParams));
		}

		template<class T0, class T1, class T2, class T3, class T4, class T5>
		ILINE spu_packet(T0 t0, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
		{
			struct SParams
			{
				typename SClassArg<ClassName>::TClassTypePtr pClassInst;
				T0 _t0;
				T1 _t1;
				T2 _t2;
				T3 _t3;
				T4 _t4;
				T5 _t5;
				SParams(T0 t0_, T1 t1_, T2 t2_, T3 t3_, T4 t4_, T5 t5_) : _t0(t0_), _t1(t1_), _t2(t2_), _t3(t3_), _t4(t4_), _t5(t5_){}
			} _ALIGN(16);

			*(SParams*)paramMem = SParams(t0, t1, t2, t3, t4, t5);
			SetupCommonJob(sizeof(SParams));
		}

		void SetClassInstance(ClassName& rClassInstance)
		{
			STATIC_CHECK(sizeof(ClassName), DO_NOT_SET_INSTANCE_FOR_NULL_TYPE);
			*(ClassName**)paramMem = &rClassInstance;
		}

		unsigned char paramMem[MAX_PARAM_SIZE_GENERIC] _ALIGN(128);//parameter memory to store parameters
	} _ALIGN(128);

//-----------------------------------------------packet----------------------------------------------	

	struct packet
	{
		ILINE void SetupCommonJob(const unsigned int cParamSize)
		{
			commonDMABase.SetJobParamData((void*)paramMem);
			paramSize = ((cParamSize + 0xF) & ~0xF);
		}

		ILINE packet()
		{
			struct SParams
			{
				typename SClassArg<ClassName>::TClassTypePtr pClassInst;
			} _ALIGN(16);

			SetupCommonJob(sizeof(SParams));
		}

		template<class T0>
		ILINE packet(T0 t0)
		{
			struct SParams
			{
				typename SClassArg<ClassName>::TClassTypePtr pClassInst;
				T0 _t0;
				SParams(T0 t0_) : _t0(t0_){}
			} _ALIGN(16);

			*(SParams*)paramMem = SParams(t0);
			SetupCommonJob(sizeof(SParams));
		}

		template<class T0, class T1>
		ILINE packet(T0 t0, T1 t1)
		{
			struct SParams
			{
				typename SClassArg<ClassName>::TClassTypePtr pClassInst;
				T0 _t0;
				T1 _t1;
				SParams(T0 t0_, T1 t1_) : _t0(t0_), _t1(t1_){}
			}_ALIGN(16);

			*(SParams*)paramMem = SParams(t0, t1);
			SetupCommonJob(sizeof(SParams));
		}

		template<class T0, class T1, class T2>
		ILINE packet(T0 t0, T1 t1, T2 t2)
		{
			struct SParams
			{
				typename SClassArg<ClassName>::TClassTypePtr pClassInst;
				T0 _t0;
				T1 _t1;
				T2 _t2;
				SParams(T0 t0_, T1 t1_, T2 t2_) : _t0(t0_), _t1(t1_), _t2(t2_){}
			} _ALIGN(16);

			*(SParams*)paramMem = SParams(t0, t1, t2);
			SetupCommonJob(sizeof(SParams));
		}

		template<class T0, class T1, class T2, class T3>
		ILINE packet(T0 t0, T1 t1, T2 t2, T3 t3)
		{
			struct SParams
			{
				typename SClassArg<ClassName>::TClassTypePtr pClassInst;
				T0 _t0;
				T1 _t1;
				T2 _t2;
				T3 _t3;
				SParams(T0 t0_, T1 t1_, T2 t2_, T3 t3_) : _t0(t0_), _t1(t1_), _t2(t2_), _t3(t3_){}
			} _ALIGN(16);

			*(SParams*)paramMem = SParams(t0, t1, t2, t3);
			SetupCommonJob(sizeof(SParams));
		}

		template<class T0, class T1, class T2, class T3, class T4>
		ILINE packet(T0 t0, T1 t1, T2 t2, T3 t3, T4 t4)
		{
			struct SParams
			{
				typename SClassArg<ClassName>::TClassTypePtr pClassInst;
				T0 _t0;
				T1 _t1;
				T2 _t2;
				T3 _t3;
				T4 _t4;
				SParams(T0 t0_, T1 t1_, T2 t2_, T3 t3_, T4 t4_) : _t0(t0_), _t1(t1_), _t2(t2_), _t3(t3_), _t4(t4_){}
			} _ALIGN(16);

			*(SParams*)paramMem = SParams(t0, t1, t2, t3, t4);
			SetupCommonJob(sizeof(SParams));
		}

		template<class T0, class T1, class T2, class T3, class T4, class T5>
		ILINE packet(T0 t0, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
		{
			struct SParams
			{
				typename SClassArg<ClassName>::TClassTypePtr pClassInst;
				T0 _t0;
				T1 _t1;
				T2 _t2;
				T3 _t3;
				T4 _t4;
				T5 _t5;
				SParams(T0 t0_, T1 t1_, T2 t2_, T3 t3_, T4 t4_, T5 t5_) : _t0(t0_), _t1(t1_), _t2(t2_), _t3(t3_), _t4(t4_), _t5(t5_){}
			} _ALIGN(16);

			*(SParams*)paramMem = SParams(t0, t1, t2, t3, t4, t5);
			SetupCommonJob(sizeof(SParams));
		}

		void SetClassInstance(ClassName& rClassInstance)
		{
			STATIC_CHECK(sizeof(ClassName), DO_NOT_SET_INSTANCE_FOR_NULL_TYPE);
			*(ClassName**)paramMem = &rClassInstance;
		}
			
		ILINE const unsigned int GetPacketSize() const
		{
			return paramSize;
		}
#if !defined(__SPU__)
		ILINE vec_uint4* const __restrict GetPacketCont() const
		{
			return (vec_uint4*)paramMem;
		}
#endif

private:
		unsigned char paramMem[MAX_PARAM_SIZE_GENERIC - sizeof(unsigned int) - sizeof(NPPU::CCommonDMABase)] _ALIGN(128);//parameter memory to store parameters
		unsigned int paramSize;	//size of set parameters
		NPPU::CCommonDMABase commonDMABase;

		NPPU::CCommonDMABase * GetCommonDMABase()
		{
			return &commonDMABase;
		}

		friend struct SGenericSPUJob;
	} _ALIGN(128);

	ILINE void AddPacket(packet* const cpPacket)
	{
		NPPU::CSPUJobBase::AddPacket(cpPacket->GetCommonDMABase());
	}

} _ALIGN(128);

#define DECLARE_SPU_JOB(func_name, typedef_name)\
	char typedef_name ## scpJobName[] = func_name;\
	typedef SGenericSPUJob<typedef_name ## scpJobName> typedef_name;

#define DECLARE_SPU_CLASS_JOB(func_name, typedef_name, class_name)\
	char typedef_name ## scpJobName[] = func_name;\
	typedef SGenericSPUJob<typedef_name ## scpJobName, class_name> typedef_name;

#endif //PS3
#endif //__GENERIC_SPUJOB_H
