//========= Copyright © Valve Corporation, All rights reserved. ====// // // Fragment Program Constant Patcher: an SPU implementation, V0 // #ifndef PS3_SHADER_CONSTANT_PATCH_SPU_HDR #define PS3_SHADER_CONSTANT_PATCH_SPU_HDR #ifdef _PS3 #include "vjobs/fpcpatch_shared.h" #include #include #ifdef _DEBUG //#define DEBUG_FPC_PATCHER #endif class FpcPatchState { public: job_fpcpatch::FpcPatchState_t * m_pSharedState; uint32 m_nEndOfJournalIdx; // this is PPU-side variable only, written by PPU only fltx4 * GetBufferStart(){ return m_pSharedState->GetBufferStart() ; } // the buffer start address uint32 m_nBufferMask; // the number of Qwords in the buffer //#ifdef _DEBUG //int m_nRangesAdded; //#endif public: FpcPatchState(){m_pSharedState = NULL;} void Init( job_fpcpatch::FpcPatchState_t * pSharedState, uint32 nBufferQwords ); void Reset(); uint AddRange( uint32 nStart, uint32 nCount, const float * pData ); void GetSyncState( fltx4 * pRegisters ); protected: fltx4 * AddInternalPtr() { fltx4 * pOut = GetBufferStart() + ( m_nEndOfJournalIdx & m_nBufferMask ); m_nEndOfJournalIdx++; return pOut; } void AddInternal( const fltx4 f4 ) { *AddInternalPtr() = f4; } inline void AddInternalBlock( const void *pBlock, const uint32 numFltx4s ) { // Fit the first portion until the end of the buffer, second portion at start uint32 const nCurrentIdx = ( m_nEndOfJournalIdx & m_nBufferMask ); // the start index to copy to uint32 const numFltx4sUntilEnd = ( -nCurrentIdx ) & m_nBufferMask; // number of fltx4's from the nCurrentIdx to the end of the current buffer ring uint32 const numFirstCopy = MIN( numFltx4sUntilEnd, numFltx4s ); // number of fltx4's to copy first memcpy( GetBufferStart() + nCurrentIdx, pBlock, numFirstCopy * sizeof( fltx4 ) ); memcpy( GetBufferStart(), ( ( fltx4* ) pBlock ) + numFirstCopy, ( numFltx4s - numFirstCopy ) * sizeof( fltx4 ) ); m_nEndOfJournalIdx += numFltx4s; } }; struct IDirect3DPixelShader9 ; class CFragmentProgramConstantPatcher_SPU { public: CFragmentProgramConstantPatcher_SPU(); ~CFragmentProgramConstantPatcher_SPU(); void InitLocal( void *pBuffer, uint nSize ); void Shutdown(); // semantics should match cgGLSetFragmentRegisterBlock() void SetFragmentRegisterBlock( uint StartRegister, uint Vector4fCount, const float* pConstantData ); // semantics of cgGLBindProgram( pPixelShader->m_pixProgram->m_CGprogram ) void BindProgram( const CgBinaryProgram *prog ); void BindProgram( const struct IDirect3DPixelShader9 * prog ); void BeginScene(); void EndScene(); //job_fpcpatch::FpcPatchState_t * GetSharedState(){return m_state.m_pSharedState; } uint GetStateEndOfJournalIdx() { return m_state.m_nEndOfJournalIdx; } uint GetJournalCapacity() const { return m_state.m_nBufferMask + 1; } int GetJournalSpaceUsedSince( uint nMarker )const{ return int( m_state.m_nEndOfJournalIdx - nMarker ); } int GetJournalSpaceLeftSince( uint nMarker )const{ return int( ( m_state.m_nBufferMask + 1 ) - ( m_state.m_nEndOfJournalIdx - nMarker ) ); } protected: void ResetPut(); void * FpcPatch( const struct CgBinaryProgram * prog, void * pFragmentProgramDestination, uint32 * pJts ); void FpcPatch2( const job_fpcpatch2::FpHeader_t * psh, uint nFpDmaSize, void *pPatchedProgram, uint32 * pJts ); protected: friend class CSpuGcm; FpcPatchState m_state; uint32* m_pBuffer, *m_pBufferEnd; int m_nIoOffsetDelta; // m_pBuffer + m_nIoOffsetDelta == IO offset usable by RSX uint32 * m_pPutFragmentProgram; uint m_nFpcPatchCounterAtBeginScene; // used for timing uint m_nFpcPatchCounterOfLastSyncJob; uint m_nBufferLocation;// CELL_GCM_LOCATION_MAIN uint m_nFpcPatchCounter, m_nFpcPatchSyncMask; //uint m_nStartRangesAfterLastSync; // this is the index used to upload only the useful constants to SPU bool m_isBufferPassedIn; bool m_bFpcPatchOnPpu, m_bEnableSPU; #ifdef DEBUG_FPC_PATCHER void ValidatePatchedProgram( const CgBinaryProgram *prog, void * pPatchedUcode ); fltx4 *m_pSyncState; bool m_bTestAlwaysStateSync; bool m_bSync; // don't use JTS, but just patch synchronously (may be more stable with GPAD) #endif }; extern CFragmentProgramConstantPatcher_SPU g_pixelShaderPatcher; // Patches pixel shader constants #endif #endif