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.
101 lines
3.2 KiB
101 lines
3.2 KiB
//========== Copyright © Valve Corporation, All rights reserved. ========
|
|
//
|
|
// This job chain wrapper is an infinite job chain with dynamic job submission
|
|
// It is single-threaded and not very fast in the current implementation,
|
|
// so it'll need to be optimized if we ever become SPU bound and use it often.
|
|
// To make it multithreaded, the easiest way is to lock every operation
|
|
// with a compare-exchange flag and a spin-wait, and use getllar to update "this" and the flag atomically
|
|
//
|
|
#if !defined( VJOBSCHAINU4_HDR ) && defined( _PS3 )
|
|
#define VJOBSCHAINU4_HDR
|
|
|
|
#include <cell/spurs.h>
|
|
#include "ps3/job_notify.h"
|
|
#include "ps3/spu_job_shared.h"
|
|
struct VJobsRoot;
|
|
|
|
|
|
struct ALIGN128 VjobChain4BufferHeader_t
|
|
{
|
|
public:
|
|
CellSpursJob64 m_jobNotify;
|
|
job_notify::NotifyArea_t m_notifyArea;
|
|
}
|
|
ALIGN128_POST;
|
|
|
|
struct VjobChain4Buffer_t: public VjobChain4BufferHeader_t
|
|
{
|
|
public:
|
|
enum ConstEnum_t
|
|
{
|
|
VERBATIM_COMMAND_COUNT = 2 // we employ syncronization scheme: SYNC, JOB(notify), ...
|
|
};
|
|
uint64 m_spursCommands[32]; // there will be at least verbatim commands, a user command, and a NEXT
|
|
|
|
void Init( VJobsRoot * pRoot, cell::Spurs::JobChain * pSpursJobChain, uint nMaxCommandsPerBuffer );
|
|
};
|
|
|
|
// VjobChain4 has only 1 jobchain but double-buffers it to facilitate continuous wait-free execution
|
|
class ALIGN16 VjobChain4
|
|
{
|
|
protected:
|
|
enum ConstEnum_t {
|
|
BUFFER_COUNT = 4
|
|
};
|
|
VjobChain4 * m_eaThis;
|
|
cell::Spurs::JobChain *m_pSpursJobChain;
|
|
VjobChain4Buffer_t * m_pBuffers[BUFFER_COUNT];
|
|
VjobChain4Buffer_t * m_pFrontBuffer;
|
|
uint m_nFrontBuffer; // the buffer currently in use
|
|
|
|
uint m_nMaxCommandsPerBuffer; // max count of commands fitting into one buffer
|
|
uint m_nFrontBufferCommandCount; // count of commands in the current front buffer
|
|
uint m_nSpinWaitNotify; // did we spin waiting for job_notify ? if we did, we probably need to increase the command buffer size
|
|
|
|
|
|
const char * m_pName;
|
|
|
|
public:
|
|
#ifndef SPU
|
|
int Init( VJobsRoot * pRoot, uint nMaxContention, uint nMinCommandsPerBuffer, uint8_t nVjobChainPriority[8], uint nSizeOfJobDescriptor, uint nMaxGrabbedJob, const char* pName, uint nDmaTags );
|
|
void Shutdown(){End();Join();}
|
|
void End();
|
|
void Join();
|
|
void Run(){ m_pSpursJobChain->run();}
|
|
#endif
|
|
uint64* Push( );
|
|
const char * GetName()const {return m_pName;}
|
|
|
|
protected:
|
|
void WaitForEntryNotify( VjobChain4Buffer_t * eaBuffer );
|
|
uint64* StartCommandBuffer( uint nNext1Buffer );
|
|
uint64* SwapCommandBuffer( );
|
|
}
|
|
ALIGN128_POST;
|
|
|
|
|
|
|
|
inline uint64* VjobChain4::Push( )
|
|
{
|
|
uint64 * pInsertionPoint;
|
|
Assert( m_nFrontBufferCommandCount < m_nMaxCommandsPerBuffer );
|
|
if( m_nFrontBufferCommandCount == m_nMaxCommandsPerBuffer - 1 )
|
|
{
|
|
// time to switch the buffer
|
|
pInsertionPoint = SwapCommandBuffer( );
|
|
}
|
|
else
|
|
{
|
|
Assert( VjobDmaGetUint64( (uint)&m_pFrontBuffer->m_spursCommands[ m_nFrontBufferCommandCount + 1 ], DMATAG_SYNC, 0, 0 ) == CELL_SPURS_JOB_COMMAND_JTS );
|
|
LWSYNC_PPU_ONLY(); // Important: this sync ensures that both the command header AND JTS are written before SPU sees them
|
|
pInsertionPoint = &m_pFrontBuffer->m_spursCommands[ m_nFrontBufferCommandCount ];
|
|
m_nFrontBufferCommandCount ++;
|
|
}
|
|
return pInsertionPoint;
|
|
}
|
|
|
|
extern vec_uint4 g_cellSpursJts16;
|
|
|
|
extern void FillSpursJts( uint64 * eaCommands, uint nBufferCount );
|
|
|
|
#endif
|