You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
273 lines
8.5 KiB
273 lines
8.5 KiB
//================ Copyright (c) Valve Corporation. All Rights Reserved. ===========================
|
|
//
|
|
//
|
|
//
|
|
//==================================================================================================
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Inlcudes
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
#include <libsn_spu.h>
|
|
#include "SpuMgr_spu.h"
|
|
#include "gcmdraw_spu.h"
|
|
#include "gcmdrawstate.h"
|
|
#include "gcmstate.h"
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Globals
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
ALIGN16 VertexShader9Data_t gVertexShaderData ALIGN16_POST;
|
|
ALIGN16 PixelShader9Data_t gPixelShaderData ALIGN16_POST;
|
|
|
|
ALIGN16 CellGcmContextData gGcmContext ALIGN16_POST ALIGN16_POST;
|
|
|
|
ALIGN16 CPs3gcmGlobalState g_ps3gcmGlobalState ALIGN16_POST ;
|
|
|
|
ALIGN16 CPs3gcmTextureLayout::Format_t g_ps3texFormats[PS3_TEX_MAX_FORMAT_COUNT] ALIGN16_POST;
|
|
|
|
ALIGN16 IDirect3DVertexDeclaration9 gDecl ALIGN16_POST;
|
|
|
|
ALIGN16 CellGcmContextData* gpGcmContext = &gGcmContext ALIGN16_POST;
|
|
|
|
ALIGN16 uint8 gFp[0x2000] ALIGN16_POST;
|
|
ALIGN16 uint8 gVp[0x2000] ALIGN16_POST;
|
|
|
|
ALIGN16 CPs3gcmTextureLayout gaLayout[D3D_MAX_TEXTURES] ALIGN16_POST;
|
|
|
|
ALIGN16 uint8 gaECB[3][0x1000];
|
|
|
|
ALIGN16 CPs3gcmLocalMemoryBlock gLmBlock ALIGN16_POST;
|
|
|
|
int gEA;
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Routine to DMA in texture Layouts
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
void GetTextureLayouts()
|
|
{
|
|
// Loop and DMA in texture layouts
|
|
|
|
for (uint32 lp = 0; lp < ARRAYSIZE(gaLayout); lp++)
|
|
{
|
|
uintp ea = gpGcmDrawState->m_textures[lp].m_eaLayout;
|
|
|
|
gEA = ea;
|
|
|
|
if (ea) gSpuMgr.DmaGetSAFE( &gaLayout[lp], ea, sizeof(CPs3gcmTextureLayout), SPU_DMAGET_TAG );
|
|
}
|
|
|
|
gSpuMgr.DmaDone( SPU_DMAGET_TAG_WAIT );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// main()
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Protocol
|
|
//
|
|
// Simplest possible for starters :
|
|
// PPU sends SPU Mbx the last part of the drawcall to perform.
|
|
// SPU performs it and DMAs down the data. When it's complete it send the PPUMbx the length of the drawcall
|
|
// PPU prepares next packet which waits on PPUMbx completion before sending another.
|
|
//
|
|
// Relies on PPU calling cellGcmReserveMethodSize with 16k, so that the SPU can go ahead and DMA back the
|
|
// draw..
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
int main(void)
|
|
{
|
|
gSpuMgr.Init();
|
|
|
|
// Initialise SPUs drawstate class
|
|
|
|
uint32 eaGcmDrawState;
|
|
gpGcmDrawState->Init();
|
|
uint8* pData = gpGcmDrawState->m_pData;
|
|
|
|
// Initialise context
|
|
|
|
gGcmContext.begin = (uint32*)MemAlloc_AllocAligned(GCM_DS_FIFOPERDRAW * GCM_NUMDRAWCALLS_SPU, 128);
|
|
gGcmContext.end = gGcmContext.begin + (GCM_DS_FIFOPERDRAW * GCM_NUMDRAWCALLS_SPU)/4;
|
|
gGcmContext.callback = NULL;
|
|
|
|
// Pull in globalstate
|
|
|
|
volatile uint32 eagGlobalState;
|
|
|
|
gSpuMgr.ReadMailbox( (uint32_t *) &eagGlobalState );
|
|
gSpuMgr.DmaGetUNSAFE( &g_ps3gcmGlobalState, eagGlobalState, SPUMGR_ALIGN_UP( sizeof(g_ps3gcmGlobalState), 16 ), SPU_DMAGET_TAG );
|
|
gSpuMgr.DmaDone( SPU_DMAGET_TAG_WAIT );
|
|
|
|
while(1)
|
|
{
|
|
uint32 startidx, count, loop;
|
|
gSpuMgr.ReadMailbox( (uint32_t *) &startidx );
|
|
count = startidx >>16;
|
|
startidx &= 0xFFFF;
|
|
|
|
gpGcmContext->current = gpGcmContext->begin;
|
|
|
|
// Loop over the drawstates
|
|
|
|
for (loop = 0; loop < count; loop++)
|
|
{
|
|
uint32 idx = (startidx +loop) % GCM_DRAWSTATE_MAX;
|
|
eaGcmDrawState = g_ps3gcmGlobalState.m_eaDrawStates + (idx*sizeof(CGcmDrawState));
|
|
|
|
// Read drawstate
|
|
|
|
gSpuMgr.DmaGetUNSAFE( gpGcmDrawState, eaGcmDrawState, SPUMGR_ALIGN_UP( DRAWSTATE_SIZEOFDMA, 16 ), SPU_DMAGET_TAG );
|
|
gSpuMgr.DmaDone( SPU_DMAGET_TAG_WAIT );
|
|
|
|
// Read Fixed Data
|
|
|
|
gSpuMgr.DmaGetUNSAFE( &gFixedData[0], uintp(gpGcmDrawState->m_pFixed), SPUMGR_ALIGN_UP(sizeof(gFixedData[0]), 16), SPU_DMAGET_TAG );
|
|
gSpuMgr.DmaDone( SPU_DMAGET_TAG_WAIT );
|
|
gpGcmDrawState->m_pFixed = &gFixedData[0];
|
|
|
|
// Read Packed Data
|
|
|
|
uint32* pParam = gpGcmDrawState->m_param;
|
|
|
|
if (gpGcmDrawState->m_cmd & 0x80000000) snPause();
|
|
gpGcmDrawState->m_cmd &= 0x7fffffff;
|
|
|
|
uint32 packSize = gpGcmDrawState->m_pDataCursor - gpGcmDrawState->m_pData;
|
|
gSpuMgr.DmaGetUNSAFE( pData, uintp(gpGcmDrawState->m_pData), SPUMGR_ALIGN_UP( packSize, 16 ), SPU_DMAGET_TAG );
|
|
gpGcmDrawState->m_pData = pData;
|
|
gpGcmDrawState->m_pDataCursor = pData + packSize;
|
|
|
|
// DMA in any ECBs we will need...
|
|
|
|
for ( uint32 lp = 0; lp < 3; lp++ )
|
|
{
|
|
if (gpGcmDrawState->m_aECB[lp])
|
|
{
|
|
gSpuMgr.DmaGetSAFE( gaECB[lp], uintp(gpGcmDrawState->m_aECB[lp]), gpGcmDrawState->m_aSizeECB[lp], SPU_DMAGET_TAG );
|
|
gpGcmDrawState->m_aECB[lp] = gaECB[lp];
|
|
}
|
|
}
|
|
|
|
gSpuMgr.DmaDone( SPU_DMAGET_TAG_WAIT );
|
|
|
|
// Read Pixel Shader and Vertex Shader
|
|
|
|
if ( (gpGcmDrawState->m_cmd != CmdCommitStates) && (gpGcmDrawState->m_cmd != CmdEndFrame ))
|
|
{
|
|
if(gpGcmDrawState->m_pVertexShaderData)
|
|
{
|
|
gSpuMgr.DmaGetUNSAFE( &gVertexShaderData, uintp(gpGcmDrawState->m_pVertexShaderData), SPUMGR_ALIGN_UP( sizeof(gVertexShaderData), 16 ), SPU_DMAGET_TAG );
|
|
gpGcmDrawState->m_pVertexShaderData = &gVertexShaderData;
|
|
|
|
gSpuMgr.DmaDone( SPU_DMAGET_TAG_WAIT );
|
|
|
|
// FPHeader, UCode, patches etc...
|
|
|
|
uintp ea = uintp(gVertexShaderData.m_pVertexShaderCmdBuffer);
|
|
gSpuMgr.DmaGetUNSAFE( &gVp, ea, SPUMGR_ALIGN_UP((gVertexShaderData.m_nVertexShaderCmdBufferWords*4),16), SPU_DMAGET_TAG );
|
|
gVertexShaderData.m_pVertexShaderCmdBuffer = (uint32*)gVp;
|
|
|
|
}
|
|
|
|
if(gpGcmDrawState->m_pPixelShaderData)
|
|
{
|
|
// PS Data
|
|
|
|
gSpuMgr.DmaGetUNSAFE( &gPixelShaderData, uintp(gpGcmDrawState->m_pPixelShaderData), SPUMGR_ALIGN_UP( sizeof(gPixelShaderData), 16 ), SPU_DMAGET_TAG );
|
|
gpGcmDrawState->m_pPixelShaderData = &gPixelShaderData;
|
|
|
|
gSpuMgr.DmaDone( SPU_DMAGET_TAG_WAIT );
|
|
|
|
// FPHeader, UCode, patches etc...
|
|
|
|
uintp ea = uintp(gPixelShaderData.m_eaFp);
|
|
gSpuMgr.DmaGetUNSAFE( &gFp, ea, SPUMGR_ALIGN_UP(gPixelShaderData.m_nTotalSize,16), SPU_DMAGET_TAG );
|
|
gPixelShaderData.m_eaFp = (FpHeader_t*)gFp;
|
|
}
|
|
|
|
// Decl
|
|
|
|
gSpuMgr.DmaGetUNSAFE( &gDecl, uintp(pParam[0]), SPUMGR_ALIGN_UP( sizeof(gDecl), 16 ), SPU_DMAGET_TAG );
|
|
|
|
// Texture Fomrats
|
|
|
|
gSpuMgr.DmaGetUNSAFE( &g_ps3texFormats, uintp(pParam[4]), SPUMGR_ALIGN_UP( sizeof(g_ps3texFormats), 16 ), SPU_DMAGET_TAG );
|
|
|
|
gSpuMgr.DmaDone( SPU_DMAGET_TAG_WAIT );
|
|
|
|
|
|
}
|
|
|
|
// Process command
|
|
|
|
switch(gpGcmDrawState->m_cmd)
|
|
{
|
|
case CmdCommitStates:
|
|
case CmdEndFrame:
|
|
gpGcmDrawState->CommitStates();
|
|
break;
|
|
|
|
case CmdDrawPrim:
|
|
gpGcmDrawState->CommitAll(&gDecl, pParam[1]);
|
|
|
|
// Draw
|
|
|
|
GCM_FUNC( cellGcmSetDrawIndexArray,
|
|
pParam[2], pParam[5],
|
|
CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16, CELL_GCM_LOCATION_LOCAL,
|
|
pParam[3] );
|
|
|
|
|
|
|
|
break;
|
|
|
|
case CmdDrawPrimUP:
|
|
{
|
|
D3DStreamDesc &dsd = g_dxGcmVertexStreamSources[0];
|
|
|
|
dsd.m_offset = 0;
|
|
dsd.m_stride = pParam[2];
|
|
dsd.m_vtxBuffer = ( IDirect3DVertexBuffer9 * )( uintp )1; // invalid pointer, but non-NULL to signal it's a real vertex buffer;
|
|
dsd.m_nLocalBufferOffset = 0;
|
|
|
|
gpGcmDrawState->CommitAll(&gDecl, 0);
|
|
GCM_FUNC(cellGcmSetCallCommand, pParam[1]);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} // End Loop over drawstates
|
|
|
|
// DMA out packet
|
|
// first fill context to a 16B boundary
|
|
|
|
while (uintp(gpGcmContext->current) & 0xf)
|
|
{
|
|
*gpGcmContext->current = 0;
|
|
gpGcmContext->current++;
|
|
}
|
|
|
|
// Send to fifo
|
|
|
|
uint32 bytesUsed = (uint8*)gpGcmContext->current - (uint8*)gpGcmContext->begin;
|
|
|
|
gSpuMgr.DmaSync();
|
|
gSpuMgr.DmaPut(gpGcmDrawState->m_eaOutputFIFO, (void*)gpGcmContext->begin,
|
|
bytesUsed, SPU_DMAPUT_TAG);
|
|
gSpuMgr.DmaDone(SPU_DMAPUT_TAG_WAIT);
|
|
|
|
// Send to SPU mailbox
|
|
|
|
gSpuMgr.WriteMailbox(gpGcmDrawState->m_eaOutputFIFO + bytesUsed);
|
|
|
|
}
|
|
|
|
}
|