//
// Asura_PS3_SPU_SkinningTypes.h
//
// Author: Ben Weston 30/5/2008
//
// Types shared by SPU and PPU code, be careful with these definitions they need to be consistent between both processors & correspond to the data from the tools
//

#if defined ASURA_USE_PRAGMA_ONCE
#pragma once
#endif

#ifndef __ASURA_PS3_SPU_SKINNINGTYPES_H__
#define __ASURA_PS3_SPU_SKINNINGTYPES_H__

#include "Core/Asura_Maths.h"

typedef u_int vec11_11_10;
typedef uint64_t half4;

struct Asura_PS3_SPU_Skinning_StartupInfo {
	uint64_t m_uBarrierAddr;
	uint16_t m_auScissorArea[4];
};

//from SmoothSkin_VD.h
//BW todo: compress the input vertices & possibly interlace so do 4 at once, SPUs are quicker that way.
struct Asura_PS3_SPU_Skinning_InputVertex
{
	Asura_Vector_3 m_xPosition;
	u_short m_xUV[4];
	u_char m_aucBoneIndices[4];
	u_char m_aucBoneWeights[4];
	vec11_11_10 m_xNormal;
	vec11_11_10 m_xTangent;
	vec11_11_10 m_xBinormal;
};

struct Asura_PS3_SPU_Skinning_OutputVertex_PosOnly
{
	float m_afPosition[3]; //BW using only 3 components because edge libraries need it & it saves us memory
};



// "Constants" - values that are used for all vertices being processed, equivalent to the constants used by a vertex program
struct Asura_PS3_SPU_SkinningConstants
{
	Asura_AMatrix4x4	m_xWorldViewProjectionMatrix;
	Asura_AMatrix4x4	m_xWorldMatrix;
	Asura_AVector4		m_xCameraPosition;
	uint64_t			m_uBoneArrayAddr; // pointer to bone array that's *guaranteed not to change for 1 frame*
	u_int				m_uNumBones;
	u_int				m_auPad[1];	 // containing stucture must be a multiple of 16 bytes, not sure how to concatenate these pads
};

//rather than having multiple SPU executables, just use an enum to say what type of shading we need.
enum SPU_SKINNING_MODE {
	SPU_SKINNING_POS_AND_CULL,		// usual case, pos & cull data shared by z-prepass, main render, and pos shared by shadow
	SPU_SKINNING_POS_ONLY_NO_CULL	// don't bother with cull if only shadow is visible
};

// SPU batches, a strip's indices & corresponding verts. Caller must ensure batches fit within SPU RAM (at tools time)
class Asura_PS3_SPU_Skinning_Batch
{
public:
	uint64_t	m_uVertAddr;
	uint64_t	m_uStartIndexAddr;
	uint64_t	m_uCommand; // write the new num indices to the command buffer
	u_int		m_uNumIndices;
	u_int		m_uNumVerts;
};

// SPU task info
class Asura_PS3_SPU_SkinningJob
{
public:
	Asura_PS3_SPU_SkinningJob( u_int uNumVerts=0 ):m_uInputAddr(0),
	m_uNumVerts(uNumVerts),m_eMode(SPU_SKINNING_POS_AND_CULL){}

	Asura_PS3_SPU_SkinningConstants	m_xShaderConstants;
	uint64_t m_uInputAddr; // address of either the input vertex data (if we're not doing culling) or the list of input batches
	uint64_t m_uVertPosOutAddr;
	uint64_t m_uIndicesOutAddr; // for culling
	uint64_t m_uAAIndicesOutAddr;
	u_int m_uNumVerts;
	SPU_SKINNING_MODE m_eMode;
	//u_int m_auPad[2];	 // must be a multiple of 16 bytes
};

#define uSPU_SKINNING_RSX_FLAG	1

#define SPU_SKINNING_MAX_AA_EDGES	(8192) //will always pad it to this amount & doesn't crash if runs out, so pick a number that's just big enough.

#endif //#ifndef __ASURA_PS3_SPU_SKINNINGTYPES_H__



