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.

131 lines
4.5 KiB

  1. //========== Copyright � Valve Corporation, All rights reserved. ========
  2. //
  3. // This is PPU->SPU fifo queue to feed draw jobs
  4. //
  5. #ifndef SPUDRAWQUEUE_HDR
  6. #define SPUDRAWQUEUE_HDR
  7. #include "tier0/dbg.h"
  8. #include "tier1/strtools.h"
  9. #include "vjobs/pcring.h"
  10. #include "ps3/vjobutils_shared.h"
  11. #include "vjobs/spudrawqueue_shared.h"
  12. extern void StallAndWarning( const char * pWarning );
  13. class SpuDrawQueue
  14. {
  15. public:
  16. typedef void ( *FnFlushCallback_t)( SpuDrawQueue * );
  17. typedef void ( *FnStallCallback_t)( SpuDrawQueue *, uint32 * pGet, uint nWords );
  18. void Init( uint nBufferSize, uint32 * pSignal, FnFlushCallback_t fnFlushCallback, FnStallCallback_t fnStallCallback );
  19. void Shutdown();
  20. void PushFlushCallback( FnFlushCallback_t fnFlushCallback );
  21. void PopFlushCallback();
  22. uint32 *AllocWords( uint nWords /*, uint nAlignMask = 0, uint nAlignValue = 0*/ );
  23. void UnallocToAlign();
  24. template<typename T>
  25. T *AllocAligned( )
  26. {
  27. COMPILE_TIME_ASSERT( sizeof( T ) % 4 == 0 );
  28. Align();
  29. return ( T* )AllocWords( sizeof( T ) / 4 );
  30. }
  31. template <typename T>
  32. T *AllocWithHeader( uint nHeader ) { uint32 * pHeader = AllocWords( 1 + sizeof( T ) / 4 ); *pHeader = nHeader; return ( T* )( pHeader + 1 ); }
  33. uint Collect( uint32 * pStartBatch, uint32 * pEndBatch, CDmaListConstructor & dmac );
  34. uint32 * GetCursor(){ return m_pPut; }
  35. uint32 * GetFlushWatermark() {return m_pFlushWatermark;}
  36. void Align();
  37. void Push4( uint32 a, uint32 b, uint32 c, uint32 d ){ uint32 * p = AllocWords( 4 ); p[0] = a; p[1] = b; p[2] = c; p[3] = d; }
  38. void Push3( uint32 a, uint32 b, uint32 c ){ uint32 * p = AllocWords( 3 ); p[0] = a; p[1] = b; p[2] = c; }
  39. void Push2( uint32 a, uint32 b ){ uint32 * p = AllocWords( 2 ); p[0] = a; p[1] = b; }
  40. void Push1( uint32 a ){ uint32 * p = AllocWords( 1 ); p[0] = a; }
  41. enum ConstEnum_t {DMA_ALIGNMENT = 16 };
  42. void SetFlushWatermarkFrom( uint32 *pPut );
  43. uint32 GetSignal()const{ return ( uint32 )m_pPut; }
  44. uint32 * GetBuffer()const{ return m_pBuffer; }
  45. uint32 * GetBufferEnd()const { return m_pBufferEnd; }
  46. uint32 GetBufferWords()const { return m_pBufferEnd - m_pBuffer; }
  47. bool IsValidCursor( uint32 * p )const { return m_pBuffer <= p && p <= m_pBufferEnd && 0 == ( uintp( p ) & 3 ); }
  48. uint32 * NormalizeCursor( uint32 * p ) { Assert( IsValidCursor( p ) ); return ( p >= m_pBufferEnd ? m_pBuffer : p ); }
  49. uint Length( uint32 * pBegin, uint32 * pEnd )const;
  50. protected:
  51. void SetSignal( uint32 nSignal );
  52. public:
  53. uint64 m_nAllocWords;
  54. #ifdef _DEBUG
  55. uint64 m_nAllocCount, m_nCollectCount;
  56. uint64 m_nAllocBreak, m_nCollectBreak;
  57. uint32 * m_nAllocBreakAddress;
  58. #endif
  59. protected:
  60. // the begin and end of the whole buffer
  61. // it must be 16-byte aligned
  62. uint32 *m_pBuffer, *m_pBufferEnd;
  63. // up to this point, we may write stuff. Starting at this point, SPU is reading data
  64. // m_pPut==m_pGet means "buffer empty"
  65. // m_pPut > m_pGet means we can write to the end of the buffer and then start at the start
  66. // m_pPut < m_pGet means we can write from put to get, exclusively
  67. uint32 *m_pGet;
  68. // this is the point where we can write stuff, up to m_pGet
  69. uint32 *m_pPut;
  70. // external signal in the structure where SPU writes
  71. volatile uint32 * m_pSignal;
  72. uint32 *m_pFlushWatermark;
  73. // FlushCallback member is implemented elsewhere. DrawQueue calls this callback
  74. // as an advice to flush the queue. The callback doesn't have to flush the queue
  75. // if the current transaction is deemed atomic. Also, even if the queue is flushed,
  76. // this object does not get immediate feedback until it reads the signal that SPU sets
  77. // much later, asynchronously. This callback is important to slice the long transactions
  78. // into smaller chunks that fit into LS
  79. FnFlushCallback_t m_fnFlushCallback;
  80. FnStallCallback_t m_fnStallCallback;
  81. //enum EnumConst_t{STACK_SIZE = 1 };
  82. FnFlushCallback_t m_fnFlushCallbackStack;
  83. };
  84. inline void SpuDrawQueue::SetSignal( uint32 nSignal )
  85. {
  86. uint32 *pNewGet = (uint32*)nSignal;
  87. // the new get must be between old get and put
  88. Assert( pNewGet == m_pGet ||
  89. ( pNewGet > m_pGet ? m_pPut < m_pGet || pNewGet <= m_pPut // the new get doesn't wrap around the buffer,
  90. : m_pPut < m_pGet && pNewGet <= m_pPut // the new get wraps around the buffer, so the put must wrap around, too
  91. )
  92. );
  93. m_pGet = pNewGet;
  94. }
  95. inline void SpuDrawQueue::Align()
  96. {
  97. while( uintp( m_pPut ) & 0xF )
  98. {
  99. Push1( 0 );
  100. }
  101. }
  102. #endif