Counter Strike : Global Offensive Source Code
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

//================ 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);
}
}