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.

272 lines
8.5 KiB

  1. //================ Copyright (c) Valve Corporation. All Rights Reserved. ===========================
  2. //
  3. //
  4. //
  5. //==================================================================================================
  6. //--------------------------------------------------------------------------------------------------
  7. // Inlcudes
  8. //--------------------------------------------------------------------------------------------------
  9. #include <libsn_spu.h>
  10. #include "SpuMgr_spu.h"
  11. #include "gcmdraw_spu.h"
  12. #include "gcmdrawstate.h"
  13. #include "gcmstate.h"
  14. //--------------------------------------------------------------------------------------------------
  15. // Globals
  16. //--------------------------------------------------------------------------------------------------
  17. ALIGN16 VertexShader9Data_t gVertexShaderData ALIGN16_POST;
  18. ALIGN16 PixelShader9Data_t gPixelShaderData ALIGN16_POST;
  19. ALIGN16 CellGcmContextData gGcmContext ALIGN16_POST ALIGN16_POST;
  20. ALIGN16 CPs3gcmGlobalState g_ps3gcmGlobalState ALIGN16_POST ;
  21. ALIGN16 CPs3gcmTextureLayout::Format_t g_ps3texFormats[PS3_TEX_MAX_FORMAT_COUNT] ALIGN16_POST;
  22. ALIGN16 IDirect3DVertexDeclaration9 gDecl ALIGN16_POST;
  23. ALIGN16 CellGcmContextData* gpGcmContext = &gGcmContext ALIGN16_POST;
  24. ALIGN16 uint8 gFp[0x2000] ALIGN16_POST;
  25. ALIGN16 uint8 gVp[0x2000] ALIGN16_POST;
  26. ALIGN16 CPs3gcmTextureLayout gaLayout[D3D_MAX_TEXTURES] ALIGN16_POST;
  27. ALIGN16 uint8 gaECB[3][0x1000];
  28. ALIGN16 CPs3gcmLocalMemoryBlock gLmBlock ALIGN16_POST;
  29. int gEA;
  30. //--------------------------------------------------------------------------------------------------
  31. // Routine to DMA in texture Layouts
  32. //--------------------------------------------------------------------------------------------------
  33. void GetTextureLayouts()
  34. {
  35. // Loop and DMA in texture layouts
  36. for (uint32 lp = 0; lp < ARRAYSIZE(gaLayout); lp++)
  37. {
  38. uintp ea = gpGcmDrawState->m_textures[lp].m_eaLayout;
  39. gEA = ea;
  40. if (ea) gSpuMgr.DmaGetSAFE( &gaLayout[lp], ea, sizeof(CPs3gcmTextureLayout), SPU_DMAGET_TAG );
  41. }
  42. gSpuMgr.DmaDone( SPU_DMAGET_TAG_WAIT );
  43. }
  44. //--------------------------------------------------------------------------------------------------
  45. // main()
  46. //--------------------------------------------------------------------------------------------------
  47. //--------------------------------------------------------------------------------------------------
  48. // Protocol
  49. //
  50. // Simplest possible for starters :
  51. // PPU sends SPU Mbx the last part of the drawcall to perform.
  52. // SPU performs it and DMAs down the data. When it's complete it send the PPUMbx the length of the drawcall
  53. // PPU prepares next packet which waits on PPUMbx completion before sending another.
  54. //
  55. // Relies on PPU calling cellGcmReserveMethodSize with 16k, so that the SPU can go ahead and DMA back the
  56. // draw..
  57. //--------------------------------------------------------------------------------------------------
  58. int main(void)
  59. {
  60. gSpuMgr.Init();
  61. // Initialise SPUs drawstate class
  62. uint32 eaGcmDrawState;
  63. gpGcmDrawState->Init();
  64. uint8* pData = gpGcmDrawState->m_pData;
  65. // Initialise context
  66. gGcmContext.begin = (uint32*)MemAlloc_AllocAligned(GCM_DS_FIFOPERDRAW * GCM_NUMDRAWCALLS_SPU, 128);
  67. gGcmContext.end = gGcmContext.begin + (GCM_DS_FIFOPERDRAW * GCM_NUMDRAWCALLS_SPU)/4;
  68. gGcmContext.callback = NULL;
  69. // Pull in globalstate
  70. volatile uint32 eagGlobalState;
  71. gSpuMgr.ReadMailbox( (uint32_t *) &eagGlobalState );
  72. gSpuMgr.DmaGetUNSAFE( &g_ps3gcmGlobalState, eagGlobalState, SPUMGR_ALIGN_UP( sizeof(g_ps3gcmGlobalState), 16 ), SPU_DMAGET_TAG );
  73. gSpuMgr.DmaDone( SPU_DMAGET_TAG_WAIT );
  74. while(1)
  75. {
  76. uint32 startidx, count, loop;
  77. gSpuMgr.ReadMailbox( (uint32_t *) &startidx );
  78. count = startidx >>16;
  79. startidx &= 0xFFFF;
  80. gpGcmContext->current = gpGcmContext->begin;
  81. // Loop over the drawstates
  82. for (loop = 0; loop < count; loop++)
  83. {
  84. uint32 idx = (startidx +loop) % GCM_DRAWSTATE_MAX;
  85. eaGcmDrawState = g_ps3gcmGlobalState.m_eaDrawStates + (idx*sizeof(CGcmDrawState));
  86. // Read drawstate
  87. gSpuMgr.DmaGetUNSAFE( gpGcmDrawState, eaGcmDrawState, SPUMGR_ALIGN_UP( DRAWSTATE_SIZEOFDMA, 16 ), SPU_DMAGET_TAG );
  88. gSpuMgr.DmaDone( SPU_DMAGET_TAG_WAIT );
  89. // Read Fixed Data
  90. gSpuMgr.DmaGetUNSAFE( &gFixedData[0], uintp(gpGcmDrawState->m_pFixed), SPUMGR_ALIGN_UP(sizeof(gFixedData[0]), 16), SPU_DMAGET_TAG );
  91. gSpuMgr.DmaDone( SPU_DMAGET_TAG_WAIT );
  92. gpGcmDrawState->m_pFixed = &gFixedData[0];
  93. // Read Packed Data
  94. uint32* pParam = gpGcmDrawState->m_param;
  95. if (gpGcmDrawState->m_cmd & 0x80000000) snPause();
  96. gpGcmDrawState->m_cmd &= 0x7fffffff;
  97. uint32 packSize = gpGcmDrawState->m_pDataCursor - gpGcmDrawState->m_pData;
  98. gSpuMgr.DmaGetUNSAFE( pData, uintp(gpGcmDrawState->m_pData), SPUMGR_ALIGN_UP( packSize, 16 ), SPU_DMAGET_TAG );
  99. gpGcmDrawState->m_pData = pData;
  100. gpGcmDrawState->m_pDataCursor = pData + packSize;
  101. // DMA in any ECBs we will need...
  102. for ( uint32 lp = 0; lp < 3; lp++ )
  103. {
  104. if (gpGcmDrawState->m_aECB[lp])
  105. {
  106. gSpuMgr.DmaGetSAFE( gaECB[lp], uintp(gpGcmDrawState->m_aECB[lp]), gpGcmDrawState->m_aSizeECB[lp], SPU_DMAGET_TAG );
  107. gpGcmDrawState->m_aECB[lp] = gaECB[lp];
  108. }
  109. }
  110. gSpuMgr.DmaDone( SPU_DMAGET_TAG_WAIT );
  111. // Read Pixel Shader and Vertex Shader
  112. if ( (gpGcmDrawState->m_cmd != CmdCommitStates) && (gpGcmDrawState->m_cmd != CmdEndFrame ))
  113. {
  114. if(gpGcmDrawState->m_pVertexShaderData)
  115. {
  116. gSpuMgr.DmaGetUNSAFE( &gVertexShaderData, uintp(gpGcmDrawState->m_pVertexShaderData), SPUMGR_ALIGN_UP( sizeof(gVertexShaderData), 16 ), SPU_DMAGET_TAG );
  117. gpGcmDrawState->m_pVertexShaderData = &gVertexShaderData;
  118. gSpuMgr.DmaDone( SPU_DMAGET_TAG_WAIT );
  119. // FPHeader, UCode, patches etc...
  120. uintp ea = uintp(gVertexShaderData.m_pVertexShaderCmdBuffer);
  121. gSpuMgr.DmaGetUNSAFE( &gVp, ea, SPUMGR_ALIGN_UP((gVertexShaderData.m_nVertexShaderCmdBufferWords*4),16), SPU_DMAGET_TAG );
  122. gVertexShaderData.m_pVertexShaderCmdBuffer = (uint32*)gVp;
  123. }
  124. if(gpGcmDrawState->m_pPixelShaderData)
  125. {
  126. // PS Data
  127. gSpuMgr.DmaGetUNSAFE( &gPixelShaderData, uintp(gpGcmDrawState->m_pPixelShaderData), SPUMGR_ALIGN_UP( sizeof(gPixelShaderData), 16 ), SPU_DMAGET_TAG );
  128. gpGcmDrawState->m_pPixelShaderData = &gPixelShaderData;
  129. gSpuMgr.DmaDone( SPU_DMAGET_TAG_WAIT );
  130. // FPHeader, UCode, patches etc...
  131. uintp ea = uintp(gPixelShaderData.m_eaFp);
  132. gSpuMgr.DmaGetUNSAFE( &gFp, ea, SPUMGR_ALIGN_UP(gPixelShaderData.m_nTotalSize,16), SPU_DMAGET_TAG );
  133. gPixelShaderData.m_eaFp = (FpHeader_t*)gFp;
  134. }
  135. // Decl
  136. gSpuMgr.DmaGetUNSAFE( &gDecl, uintp(pParam[0]), SPUMGR_ALIGN_UP( sizeof(gDecl), 16 ), SPU_DMAGET_TAG );
  137. // Texture Fomrats
  138. gSpuMgr.DmaGetUNSAFE( &g_ps3texFormats, uintp(pParam[4]), SPUMGR_ALIGN_UP( sizeof(g_ps3texFormats), 16 ), SPU_DMAGET_TAG );
  139. gSpuMgr.DmaDone( SPU_DMAGET_TAG_WAIT );
  140. }
  141. // Process command
  142. switch(gpGcmDrawState->m_cmd)
  143. {
  144. case CmdCommitStates:
  145. case CmdEndFrame:
  146. gpGcmDrawState->CommitStates();
  147. break;
  148. case CmdDrawPrim:
  149. gpGcmDrawState->CommitAll(&gDecl, pParam[1]);
  150. // Draw
  151. GCM_FUNC( cellGcmSetDrawIndexArray,
  152. pParam[2], pParam[5],
  153. CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16, CELL_GCM_LOCATION_LOCAL,
  154. pParam[3] );
  155. break;
  156. case CmdDrawPrimUP:
  157. {
  158. D3DStreamDesc &dsd = g_dxGcmVertexStreamSources[0];
  159. dsd.m_offset = 0;
  160. dsd.m_stride = pParam[2];
  161. dsd.m_vtxBuffer = ( IDirect3DVertexBuffer9 * )( uintp )1; // invalid pointer, but non-NULL to signal it's a real vertex buffer;
  162. dsd.m_nLocalBufferOffset = 0;
  163. gpGcmDrawState->CommitAll(&gDecl, 0);
  164. GCM_FUNC(cellGcmSetCallCommand, pParam[1]);
  165. }
  166. break;
  167. }
  168. } // End Loop over drawstates
  169. // DMA out packet
  170. // first fill context to a 16B boundary
  171. while (uintp(gpGcmContext->current) & 0xf)
  172. {
  173. *gpGcmContext->current = 0;
  174. gpGcmContext->current++;
  175. }
  176. // Send to fifo
  177. uint32 bytesUsed = (uint8*)gpGcmContext->current - (uint8*)gpGcmContext->begin;
  178. gSpuMgr.DmaSync();
  179. gSpuMgr.DmaPut(gpGcmDrawState->m_eaOutputFIFO, (void*)gpGcmContext->begin,
  180. bytesUsed, SPU_DMAPUT_TAG);
  181. gSpuMgr.DmaDone(SPU_DMAPUT_TAG_WAIT);
  182. // Send to SPU mailbox
  183. gSpuMgr.WriteMailbox(gpGcmDrawState->m_eaOutputFIFO + bytesUsed);
  184. }
  185. }