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.

223 lines
6.9 KiB

  1. //========== Copyright � Valve Corporation, All rights reserved. ========
  2. // This is shared between SPU and PPU
  3. #ifndef COMMON_PS3_VJOBUTILS_SHARED_HDR
  4. #define COMMON_PS3_VJOBUTILS_SHARED_HDR
  5. #ifndef _PS3
  6. #error "This is PS3 specific header"
  7. #endif
  8. #include "spu_job_shared.h"
  9. #include <cell/spurs/job_descriptor.h>
  10. template <typename T>
  11. inline void AddInputDma( T * pJob, uint nSize, const void * pEa )
  12. {
  13. Assert( !( nSize & 0xF ) );
  14. Assert( !( pJob->header.sizeDmaList & ( sizeof( uint64 ) - 1 ) ) );
  15. //int nError = cellSpursJobGetInputList( &pJob->workArea.dmaList[pJob->header.sizeDmaList / sizeof( uint64_t )], nSize, (uint32) pEa );
  16. //Assert( nError == CELL_OK );
  17. pJob->workArea.dmaList[pJob->header.sizeDmaList / sizeof( uint64_t )] = ( uint64( nSize ) << 32 ) | ( uint32 )pEa;
  18. // ( nSIze << 32 ) | pEa
  19. pJob->header.sizeDmaList += sizeof( uint64_t );
  20. pJob->header.sizeInOrInOut += nSize;
  21. Assert( pJob->header.sizeDmaList <= sizeof( pJob->workArea ) );
  22. }
  23. template <typename T>
  24. inline void AlignInputDma( T * pJob )
  25. {
  26. pJob->workArea.dmaList[pJob->header.sizeDmaList / sizeof( uint64_t )] = 0;
  27. pJob->header.sizeDmaList = AlignValue( pJob->header.sizeDmaList, 16 );
  28. Assert( pJob->header.sizeDmaList <= sizeof( pJob->workArea ) );
  29. }
  30. inline void AddCacheDma( struct CellSpursJob128 * pJob, uint nSize, const void * pEa )
  31. {
  32. int nError = cellSpursJobGetInputList( &pJob->workArea.dmaList[( pJob->header.sizeDmaList + pJob->header.sizeCacheDmaList ) / sizeof( uint64 ) ], nSize, (uint32)pEa );
  33. ( void )nError;
  34. Assert( nError == CELL_OK );
  35. pJob->header.sizeCacheDmaList += sizeof( uint64_t );
  36. }
  37. inline uint64 MakeDmaElement( void * pData, uint nSize )
  38. {
  39. return ((uint32)pData) | (uint64(nSize)<<32);
  40. }
  41. template <uint nSize>
  42. inline void V_memcpy16( void *pDest, const void * pSrc )
  43. {
  44. Assert( !( nSize & 0xF ) && !( uintp( pDest ) & 0xF ) && !( uintp( pSrc ) & 0xF ) );
  45. for( uint i = 0; i < nSize / 16; ++i )
  46. {
  47. ( ( vector unsigned int * ) pDest )[i] = ( ( vector unsigned int * ) pSrc )[i];
  48. }
  49. }
  50. class CDmaListConstructor
  51. {
  52. uint32 *m_pListBegin, *m_pList;
  53. uint m_sizeInOrInOut;
  54. uint m_sizeCacheDmaList;
  55. public:
  56. CDmaListConstructor( void * pList )
  57. {
  58. m_pList = m_pListBegin = ( uint32* )pList;
  59. m_sizeInOrInOut = m_sizeCacheDmaList = 0;
  60. }
  61. void AddInputDma( uint nSize, const void *pEa )
  62. {
  63. Assert( !m_sizeCacheDmaList );
  64. Assert( !( nSize & 0xF ) && nSize <= 16 * 1024 && ( !nSize || pEa ) );
  65. Assert( !IsAddressInStack( pEa ) );
  66. m_pList[0] = nSize;
  67. m_pList[1] = ( uint32 )pEa;
  68. m_pList += 2;
  69. m_sizeInOrInOut += nSize;
  70. }
  71. void AddCacheDma( uint nSize, const void *pEa )
  72. {
  73. // WARNING : NEVER use size=0, as there's a bug in SPURS that can corrupt data if you do
  74. Assert( !IsAddressInStack( pEa ) && pEa && nSize > 0 );
  75. uint32 * pCache = AddBytes( m_pList, m_sizeCacheDmaList );
  76. pCache[0] = nSize;
  77. pCache[1] = ( uint32 )pEa;
  78. m_sizeCacheDmaList += 8;
  79. Assert( m_sizeCacheDmaList <= 32 );
  80. }
  81. void AddInputDmaLargeUnalignedRegion( void * pBegin, void * pEnd )
  82. {
  83. uint32 eaBeginAligned = uint32( pBegin ) & -16;
  84. uint32 eaEndAligned = AlignValue( uint32( pEnd ), 16 );
  85. AddInputDmaLarge( eaEndAligned - eaBeginAligned, ( void* )eaBeginAligned );
  86. }
  87. void* AddInputDmaUnalignedRegion( void * pBegin, void * pEnd, int nAlignment = 16 )
  88. {
  89. uint32 eaBeginAligned = uint32( pBegin ) & -nAlignment;
  90. uint32 eaEndAligned = AlignValue( uint32( pEnd ), nAlignment );
  91. AddInputDma( eaEndAligned - eaBeginAligned, ( void* )eaBeginAligned );
  92. return ( void* )eaBeginAligned;
  93. }
  94. void AddInputDmaLarge( uint nMinReserve, uint nSize, const void * pEa )
  95. {
  96. AddInputDmaLarge( nSize, pEa );
  97. Assert( !( nMinReserve & 15 ) );
  98. if( nMinReserve > nSize )
  99. {
  100. m_sizeInOrInOut += nMinReserve - nSize;
  101. }
  102. }
  103. uint AddInputDmaLargeRegion( const void * pBegin, const void * pEnd )
  104. {
  105. uint nSize = uintp( pEnd ) - uintp( pBegin );
  106. AddInputDmaLarge( nSize, pBegin );
  107. return nSize;
  108. }
  109. void AddInputDmaLarge( uint nSize, const void * pEa )
  110. {
  111. Assert( !( nSize & 0xF ) && nSize < 248 * 1024 );
  112. Assert( !IsAddressInStack( pEa ) );
  113. uint nSizeRemaining = nSize;
  114. uintp eaRemaining = ( uintp )pEa;
  115. const uint nMaxDmaElementSize = 16 * 1024;
  116. while( nSizeRemaining > nMaxDmaElementSize )
  117. {
  118. m_pList[0] = nMaxDmaElementSize;
  119. m_pList[1] = eaRemaining;
  120. m_pList += 2;
  121. nSizeRemaining -= nMaxDmaElementSize;
  122. eaRemaining += nMaxDmaElementSize;
  123. }
  124. m_pList[0] = nSizeRemaining;
  125. m_pList[1] = eaRemaining;
  126. m_pList += 2;
  127. m_sizeInOrInOut += nSize;
  128. }
  129. void AddSizeInOrInOut( uint nAddIoBufferSize )
  130. {
  131. Assert( !( nAddIoBufferSize & 0xF ) );
  132. m_sizeInOrInOut += nAddIoBufferSize;
  133. }
  134. void EnsureCapacityInOrInOut( uint nCapacity )
  135. {
  136. Assert( !( nCapacity & 0xF ) );
  137. m_sizeInOrInOut = Max( m_sizeInOrInOut, nCapacity );
  138. }
  139. void FinishIoBuffer( CellSpursJobHeader * pHeader )
  140. {
  141. FinishInOrIoBuffer( pHeader );
  142. Assert( pHeader->useInOutBuffer == 1 );
  143. }
  144. void FinishInBuffer( CellSpursJobHeader * pHeader )
  145. {
  146. FinishInOrIoBuffer( pHeader );
  147. Assert( pHeader->useInOutBuffer == 0 );
  148. }
  149. void FinishIoBuffer( CellSpursJobHeader * pHeader, void * pParams )
  150. {
  151. FinishIoBuffer( pHeader );
  152. // we only use up to 256 byte jobs, which have up to 26 DMA slots. Check that the params belongs to this job structure
  153. // and check that it doesn't overlap with IO DMA list or cache DMA list
  154. Assert( uintp( pParams ) <= uintp( m_pListBegin + 26 * 2 ) && uintp( pParams ) >= uintp( m_pList ) + m_sizeCacheDmaList );
  155. }
  156. void FinishInBuffer( CellSpursJobHeader * pHeader, void * pParams )
  157. {
  158. FinishInBuffer( pHeader );
  159. // we only use up to 256 byte jobs, which have up to 26 DMA slots. Check that the params belongs to this job structure
  160. // and check that it doesn't overlap with IO DMA list or cache DMA list
  161. Assert( uintp( pParams ) <= uintp( m_pListBegin + 26 * 2 ) && uintp( pParams ) >= uintp( m_pList ) + m_sizeCacheDmaList );
  162. }
  163. inline uint32 * operator [] ( int i )
  164. {
  165. uint32 * pResult = m_pListBegin + 2 * i;
  166. Assert( pResult >= m_pList ); // are we not overwriting the dma list tail that we wrote previously?
  167. return pResult;
  168. }
  169. private:
  170. void FinishInOrIoBuffer( CellSpursJobHeader * pHeader )
  171. {
  172. pHeader->sizeDmaList = uintp( m_pList ) - uintp( m_pListBegin );
  173. pHeader->sizeInOrInOut = m_sizeInOrInOut;
  174. pHeader->sizeCacheDmaList = m_sizeCacheDmaList;
  175. }
  176. // We can't DMA from / to the PPU stack, let's verify that
  177. bool IsAddressInStack( const void * pEa )
  178. {
  179. #if IsPlatformPS3_PPU()
  180. uint64 fp = __reg(1);
  181. void * minStack = ( void* )( ( uint32 ) fp - 16 * 1024 ); // The 16 * 1024 should is not really necessary (as it means somebody addresses some portion that could be erased by the stack.
  182. // Never the less, we want to be more conservative.
  183. void * maxStack = (void *)((uint32)fp + 64 * 1024); // Assume that the stack is 64 Kb deep, make sure there is no allocations around if the stack is smaller
  184. return ( ( pEa >= minStack ) && ( pEa <= maxStack ) );
  185. #else
  186. return false;
  187. #endif
  188. }
  189. };
  190. #endif