Team Fortress 2 Source Code as on 22/4/2020
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.

825 lines
20 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // methods for muti-core dx9 threading
  6. //===========================================================================//
  7. #ifdef D3D_ASYNC_SUPPORTED
  8. #include "glmgr/dxabstract.h"
  9. #include "utlsymbol.h"
  10. #include "utlvector.h"
  11. #include "utldict.h"
  12. #include "utlbuffer.h"
  13. #include "UtlStringMap.h"
  14. #include "locald3dtypes.h"
  15. #include "shaderapidx8_global.h"
  16. #include "recording.h"
  17. #include "tier0/vprof.h"
  18. #include "materialsystem/imaterialsystem.h"
  19. #include "materialsystem/imaterialsystemhardwareconfig.h"
  20. #include "shaderapidx8.h"
  21. #include "materialsystem/IShader.h"
  22. #include "utllinkedlist.h"
  23. #include "IShaderSystem.h"
  24. #include "tier0/fasttimer.h"
  25. #include <stdlib.h>
  26. #include "convar.h"
  27. #include "materialsystem/shader_vcs_version.h"
  28. #include "datacache/idatacache.h"
  29. #include "winutils.h"
  30. #include "tier0/memdbgon.h"
  31. #if SHADERAPI_USE_SMP
  32. // Set this to 1 to get vprof nodes for playing back the command stream. This is good for counting calls in a frame, etc.
  33. #define SHADERAPI_VPROF_BUFFER_PLAYBACK 1
  34. #if SHADERAPI_VPROF_BUFFER_PLAYBACK && SHADERAPI_BUFFER_D3DCALLS
  35. #define VPROF_BUFFER_PLAYBACK(name) VPROF(name)
  36. #else
  37. #define VPROF_BUFFER_PLAYBACK(name) ((void)0)
  38. #endif
  39. template<class T, int QSIZE> class FixedWorkQueue
  40. {
  41. T Data[QSIZE];
  42. char pad0[256];
  43. volatile int n_added;
  44. int write_index;
  45. char pad1[256]; // make sure these don't share cache lines
  46. volatile int n_removed;
  47. int read_index;
  48. public:
  49. FixedWorkQueue(void)
  50. {
  51. read_index=write_index=0;
  52. n_added=n_removed=0;
  53. }
  54. int IsEmpty(void)
  55. {
  56. return (n_added==n_removed);
  57. }
  58. int IsFull(void)
  59. {
  60. return (n_added-n_removed)>=QSIZE;
  61. }
  62. T GetWorkUnit(void)
  63. {
  64. if (IsEmpty())
  65. return 0;
  66. return Data[read_index];
  67. }
  68. void MarkUnitDone(void)
  69. {
  70. n_removed++;
  71. read_index=(read_index+1) % QSIZE;
  72. }
  73. void AddWorkUnit(T unit)
  74. {
  75. #if SHADERAPI_BUFFER_D3DCALLS
  76. Assert( !IsFull() );
  77. #else
  78. while (IsFull())
  79. Sleep(0);
  80. #endif
  81. Data[write_index]=unit;
  82. n_added++;
  83. write_index=(write_index+1) % QSIZE;
  84. }
  85. };
  86. #if SHADERAPI_BUFFER_D3DCALLS
  87. #define N_PUSH_BUFFERS 5000
  88. #else
  89. #define N_PUSH_BUFFERS 500
  90. #endif
  91. static volatile PushBuffer *PushBuffers[N_PUSH_BUFFERS];
  92. FixedWorkQueue<PushBuffer *, N_PUSH_BUFFERS> PBQueue;
  93. #ifdef WIN32
  94. void __cdecl OurThreadInit( void * ourthis )
  95. #else
  96. unsigned int OurThreadInit( void * ourthis )
  97. #endif
  98. {
  99. (( D3DDeviceWrapper *) ourthis )->RunThread();
  100. #ifndef WIN32
  101. return 0;
  102. #endif
  103. }
  104. void D3DDeviceWrapper::RunThread( void )
  105. {
  106. SetThreadAffinityMask(GetCurrentThread(), 2);
  107. for(;;)
  108. {
  109. PushBuffer *Pbuf=PBQueue.GetWorkUnit();
  110. if (! Pbuf)
  111. {
  112. ; //Sleep(0);
  113. }
  114. else
  115. {
  116. ExecutePushBuffer( Pbuf );
  117. PBQueue.MarkUnitDone();
  118. Pbuf->m_State = PUSHBUFFER_AVAILABLE;
  119. }
  120. }
  121. }
  122. #if SHADERAPI_BUFFER_D3DCALLS
  123. void D3DDeviceWrapper::ExecuteAllWork( void )
  124. {
  125. if( !m_bBufferingD3DCalls )
  126. return;
  127. VPROF_BUDGET( "ExecuteAllWork", "ExecuteAllWork" );
  128. SubmitPushBufferAndGetANewOne();
  129. PushBuffer *Pbuf;
  130. while( ( Pbuf = PBQueue.GetWorkUnit() ) != NULL )
  131. {
  132. ExecutePushBuffer( Pbuf );
  133. PBQueue.MarkUnitDone();
  134. Pbuf->m_State = PUSHBUFFER_AVAILABLE;
  135. }
  136. m_bBufferingD3DCalls = false;
  137. }
  138. #endif
  139. #if SHADERAPI_BUFFER_D3DCALLS
  140. #define MAXIMUM_NUMBER_OF_BUFFERS_LOCKED_AT_ONCE 1600
  141. #else
  142. #define MAXIMUM_NUMBER_OF_BUFFERS_LOCKED_AT_ONCE 16
  143. #endif
  144. struct RememberedPointer
  145. {
  146. void *m_pKey;
  147. void *m_pRememberedPtr;
  148. } RememberedPointerHistory[MAXIMUM_NUMBER_OF_BUFFERS_LOCKED_AT_ONCE];
  149. void D3DDeviceWrapper::SetASyncMode( bool onoff )
  150. {
  151. #if SHADERAPI_BUFFER_D3DCALLS
  152. if ( onoff )
  153. {
  154. m_bBufferingD3DCalls = true;
  155. // allocate push buffers if we need to
  156. if ( PushBuffers[0] == NULL )
  157. {
  158. for(int i=0; i<N_PUSH_BUFFERS; i++)
  159. PushBuffers[i]=new PushBuffer;
  160. }
  161. // create thread and init communications
  162. memset( RememberedPointerHistory,0,sizeof(RememberedPointerHistory) );
  163. }
  164. #else
  165. if ( onoff )
  166. {
  167. if (! m_pASyncThreadHandle )
  168. {
  169. // allocate push buffers if we need to
  170. if ( PushBuffers[0] == NULL )
  171. {
  172. for(int i=0; i<N_PUSH_BUFFERS; i++)
  173. PushBuffers[i]=new PushBuffer;
  174. }
  175. // create thread and init communications
  176. memset( RememberedPointerHistory,0,sizeof(RememberedPointerHistory) );
  177. SetThreadAffinityMask(GetCurrentThread(), 1);
  178. #ifdef WIN32
  179. m_pASyncThreadHandle = _beginthread( OurThreadInit, 128*1024, this );
  180. #else
  181. m_pASyncThreadHandle = (uintptr_t)CreateSimpleThread( OurThreadInit, this, 128*1024 );
  182. #endif
  183. }
  184. }
  185. else
  186. {
  187. Synchronize();
  188. }
  189. #endif
  190. }
  191. PushBuffer *D3DDeviceWrapper::FindFreePushBuffer( PushBufferState newstate )
  192. {
  193. VPROF_BUFFER_PLAYBACK( "D3DDeviceWrapper::FindFreePushBuffer" );
  194. for(;;)
  195. {
  196. for(int i=0;i<N_PUSH_BUFFERS;i++)
  197. {
  198. if (PushBuffers[i]->m_State == PUSHBUFFER_AVAILABLE )
  199. {
  200. PushBuffers[i]->m_State = newstate;
  201. return (PushBuffer *) PushBuffers[i];
  202. }
  203. }
  204. // hmm, out of push buffers. better sleep and try again later
  205. SubmitPushBufferAndGetANewOne();
  206. Sleep(0);
  207. }
  208. }
  209. void D3DDeviceWrapper::GetPushBuffer( void )
  210. {
  211. VPROF_BUFFER_PLAYBACK( "D3DDeviceWrapper::GetPushBuffer" );
  212. m_pCurPushBuffer = FindFreePushBuffer( PUSHBUFFER_BEING_FILLED );
  213. m_pOutputPtr = m_pCurPushBuffer->m_BufferData;
  214. m_PushBufferFreeSlots = PUSHBUFFER_NELEMS - 1; // leave room for end marker
  215. }
  216. void D3DDeviceWrapper::SubmitPushBufferAndGetANewOne( void )
  217. {
  218. VPROF_BUFFER_PLAYBACK( "D3DDeviceWrapper::SubmitPushBufferAndGetANewOne" );
  219. // submit the current push buffer
  220. if ( m_pCurPushBuffer )
  221. {
  222. if (m_pOutputPtr == m_pCurPushBuffer->m_BufferData) // haven't done anyting, don't bother
  223. return;
  224. *(m_pOutputPtr) = PBCMD_END; // mark end
  225. m_pCurPushBuffer->m_State = PUSHBUFFER_SUBMITTED;
  226. // here, enqueue for task
  227. PBQueue.AddWorkUnit( m_pCurPushBuffer );
  228. }
  229. GetPushBuffer();
  230. }
  231. void D3DDeviceWrapper::SubmitIfNotBusy( void )
  232. {
  233. VPROF_BUFFER_PLAYBACK( "D3DDeviceWrapper::SubmitIfNotBusy" );
  234. if ( PBQueue.IsEmpty() )
  235. SubmitPushBufferAndGetANewOne();
  236. }
  237. void D3DDeviceWrapper::Synchronize( void )
  238. {
  239. #if SHADERAPI_BUFFER_D3DCALLS
  240. if( m_bBufferingD3DCalls )
  241. {
  242. Assert( 0 );
  243. Error( "Synchronize not supported with SHADERAPI_BUFFER_D3DCALLS" );
  244. }
  245. return;
  246. #endif
  247. if ( ASyncMode())
  248. {
  249. SubmitPushBufferAndGetANewOne();
  250. // here, wait for queue to become empty
  251. while (! PBQueue.IsEmpty() )
  252. {
  253. // Sleep(1);
  254. }
  255. }
  256. }
  257. void D3DDeviceWrapper::AsynchronousLock( IDirect3DIndexBuffer9* ib,
  258. size_t offset, size_t size, void **ptr,
  259. DWORD flags,
  260. LockedBufferContext *lb)
  261. {
  262. VPROF_BUFFER_PLAYBACK( "D3DDeviceWrapper::AsynchronousLock index" );
  263. if ( size <= sizeof( PushBuffers[0]->m_BufferData ))
  264. {
  265. // can use one of our pushbuffers for this
  266. lb->m_pPushBuffer = FindFreePushBuffer( PUSHBUFFER_BEING_USED_FOR_LOCKEDDATA );
  267. *(ptr) = lb->m_pPushBuffer->m_BufferData;
  268. Assert( *ptr );
  269. lb->m_pMallocedMemory = NULL;
  270. }
  271. else // out of buffer space or size too big
  272. {
  273. lb->m_pPushBuffer = NULL;
  274. lb->m_pMallocedMemory = new uint8 [ size ];
  275. *(ptr) = lb->m_pMallocedMemory;
  276. }
  277. // now, push lock commands
  278. AllocatePushBufferSpace( 1+N_DWORDS_IN_PTR+3 );
  279. *(m_pOutputPtr++)=PBCMD_ASYNC_LOCK_IB;
  280. *((LPDIRECT3DINDEXBUFFER *) m_pOutputPtr)=ib;
  281. m_pOutputPtr+=N_DWORDS_IN_PTR;
  282. *(m_pOutputPtr++)=offset;
  283. *(m_pOutputPtr++)=size;
  284. *(m_pOutputPtr++)=flags;
  285. }
  286. void D3DDeviceWrapper::AsynchronousLock( IDirect3DVertexBuffer9* vb,
  287. size_t offset, size_t size, void **ptr,
  288. DWORD flags,
  289. LockedBufferContext *lb)
  290. {
  291. VPROF_BUFFER_PLAYBACK( "D3DDeviceWrapper::AsynchronousLock vertex" );
  292. // we have commands in flight. Need to use temporary memory for this lock.
  293. // if the size needed is < the amount of space in a push buffer, we can use
  294. // a push buffer for the buffer. Otherwise, we're going to malloc one.
  295. if ( size <= sizeof( PushBuffers[0]->m_BufferData ))
  296. {
  297. // can use one of our pushbuffers for this
  298. lb->m_pPushBuffer = FindFreePushBuffer( PUSHBUFFER_BEING_USED_FOR_LOCKEDDATA );
  299. *(ptr) = lb->m_pPushBuffer->m_BufferData;
  300. Assert( *ptr );
  301. lb->m_pMallocedMemory = NULL;
  302. }
  303. else // out of buffer space or size too big
  304. {
  305. lb->m_pPushBuffer = NULL;
  306. lb->m_pMallocedMemory = new uint8 [ size ];
  307. *(ptr) = lb->m_pMallocedMemory;
  308. }
  309. // now, push lock commands
  310. AllocatePushBufferSpace( 1+N_DWORDS_IN_PTR+3 );
  311. *(m_pOutputPtr++)=PBCMD_ASYNC_LOCK_VB;
  312. *((LPDIRECT3DVERTEXBUFFER *) m_pOutputPtr)=vb;
  313. m_pOutputPtr+=N_DWORDS_IN_PTR;
  314. *(m_pOutputPtr++)=offset;
  315. *(m_pOutputPtr++)=size;
  316. *(m_pOutputPtr++)=flags;
  317. }
  318. inline void RememberLockedPointer( void *key, void *value )
  319. {
  320. VPROF_BUFFER_PLAYBACK( "RememberLockedPointer" );
  321. int repl=-1;
  322. int i;
  323. for(i=0;i<MAXIMUM_NUMBER_OF_BUFFERS_LOCKED_AT_ONCE;i++)
  324. {
  325. if ( RememberedPointerHistory[i].m_pKey==key )
  326. break;
  327. if ( (repl == -1 ) && (RememberedPointerHistory[i].m_pRememberedPtr == 0 ) )
  328. repl=i;
  329. }
  330. if (i != MAXIMUM_NUMBER_OF_BUFFERS_LOCKED_AT_ONCE )
  331. {
  332. RememberedPointerHistory[i].m_pRememberedPtr = value;
  333. if ( value==NULL )
  334. RememberedPointerHistory[i].m_pKey = NULL;
  335. }
  336. else
  337. {
  338. if (repl == -1 )
  339. {
  340. Assert( 0 );
  341. }
  342. else
  343. {
  344. RememberedPointerHistory[repl].m_pKey = key;
  345. RememberedPointerHistory[repl].m_pRememberedPtr = value;
  346. }
  347. }
  348. }
  349. inline void *RecallLockedPointer( void *key )
  350. {
  351. VPROF_BUFFER_PLAYBACK( "RecallLockedPointer" );
  352. for(int i=0;i<MAXIMUM_NUMBER_OF_BUFFERS_LOCKED_AT_ONCE;i++)
  353. if ( RememberedPointerHistory[i].m_pKey == key )
  354. return RememberedPointerHistory[i].m_pRememberedPtr;
  355. return NULL;
  356. }
  357. void D3DDeviceWrapper::HandleAsynchronousLockVBCommand( uint32 const *dptr )
  358. {
  359. dptr++;
  360. LPDIRECT3DVERTEXBUFFER vb=*((LPDIRECT3DVERTEXBUFFER *) dptr);
  361. dptr+=N_DWORDS_IN_PTR;
  362. uint32 offset=*(dptr++);
  363. uint32 size=*(dptr++);
  364. uint32 flags=*(dptr++);
  365. void *locked_ptr=0;
  366. vb->Lock( offset, size, &locked_ptr, flags );
  367. RememberLockedPointer( vb, locked_ptr );
  368. }
  369. void D3DDeviceWrapper::HandleAsynchronousUnLockVBCommand( uint32 const *dptr )
  370. {
  371. dptr++;
  372. LPDIRECT3DVERTEXBUFFER vb=*((LPDIRECT3DVERTEXBUFFER *) dptr);
  373. dptr+=N_DWORDS_IN_PTR;
  374. LockedBufferContext lb=*((LockedBufferContext *) dptr);
  375. dptr+=N_DWORDS( LockedBufferContext );
  376. size_t unlock_size=*( dptr++ );
  377. void *locked_data=RecallLockedPointer( vb );
  378. Assert( locked_data );
  379. if (lb.m_pPushBuffer)
  380. {
  381. Assert( ! lb.m_pMallocedMemory );
  382. if ( locked_data )
  383. memcpy( locked_data, lb.m_pPushBuffer->m_BufferData, unlock_size );
  384. lb.m_pPushBuffer->m_State = PUSHBUFFER_AVAILABLE;
  385. }
  386. else if ( lb.m_pMallocedMemory )
  387. {
  388. Assert( ! lb.m_pPushBuffer );
  389. if ( locked_data )
  390. memcpy( locked_data, lb.m_pMallocedMemory, unlock_size );
  391. delete[] ((uint8 *) lb.m_pMallocedMemory);
  392. }
  393. // now, actually unlock
  394. RememberLockedPointer( vb, NULL );
  395. vb->Unlock();
  396. }
  397. void D3DDeviceWrapper::HandleAsynchronousLockIBCommand( uint32 const *dptr )
  398. {
  399. dptr++;
  400. LPDIRECT3DINDEXBUFFER ib=*((LPDIRECT3DINDEXBUFFER *) dptr);
  401. Assert( ib );
  402. dptr+=N_DWORDS_IN_PTR;
  403. uint32 offset=*(dptr++);
  404. uint32 size=*(dptr++);
  405. uint32 flags=*(dptr++);
  406. void *locked_ptr=0;
  407. ib->Lock( offset, size, &locked_ptr, flags );
  408. RememberLockedPointer( ib, locked_ptr );
  409. }
  410. void D3DDeviceWrapper::HandleAsynchronousUnLockIBCommand( uint32 const *dptr )
  411. {
  412. dptr++;
  413. LPDIRECT3DINDEXBUFFER ib=*((LPDIRECT3DINDEXBUFFER *) dptr);
  414. dptr+=N_DWORDS_IN_PTR;
  415. LockedBufferContext lb=*((LockedBufferContext *) dptr);
  416. dptr+=N_DWORDS( LockedBufferContext );
  417. size_t unlock_size=*( dptr++ );
  418. void *locked_data=RecallLockedPointer( ib );
  419. Assert( locked_data );
  420. if (lb.m_pPushBuffer)
  421. {
  422. Assert( ! lb.m_pMallocedMemory );
  423. if ( locked_data )
  424. memcpy( locked_data, lb.m_pPushBuffer->m_BufferData, unlock_size );
  425. lb.m_pPushBuffer->m_State = PUSHBUFFER_AVAILABLE;
  426. }
  427. else if ( lb.m_pMallocedMemory )
  428. {
  429. Assert( ! lb.m_pPushBuffer );
  430. if ( locked_data )
  431. memcpy( locked_data, lb.m_pMallocedMemory, unlock_size );
  432. delete[] ((uint8 *) lb.m_pMallocedMemory);
  433. }
  434. // now, actually unlock
  435. RememberLockedPointer( ib, NULL );
  436. ib->Unlock();
  437. }
  438. static inline void *FetchPtr( uint32 const *mem)
  439. {
  440. void **p=(void **) mem;
  441. return *p;
  442. }
  443. #define CALC_STATS 1
  444. #if CALC_STATS
  445. int n_commands_executed=0;
  446. int n_pbs_executed=0;
  447. #endif
  448. void D3DDeviceWrapper::ExecutePushBuffer( PushBuffer const* pb)
  449. {
  450. VPROF_BUFFER_PLAYBACK( "D3DDeviceWrapper::ExecutePushBuffer" );
  451. uint32 const *dptr=pb->m_BufferData;
  452. n_pbs_executed++;
  453. for(;;)
  454. {
  455. n_commands_executed++;
  456. switch( dptr[0] )
  457. {
  458. case PBCMD_END:
  459. {
  460. VPROF_BUFFER_PLAYBACK( "END" );
  461. n_commands_executed--; // doesn't count
  462. return;
  463. }
  464. case PBCMD_SET_RENDERSTATE:
  465. {
  466. VPROF_BUFFER_PLAYBACK( "SET_RENDERSTATE" );
  467. Dx9Device()->SetRenderState((D3DRENDERSTATETYPE) dptr[1],dptr[2]);
  468. dptr+=3;
  469. break;
  470. }
  471. case PBCMD_SET_SAMPLER_STATE:
  472. {
  473. VPROF_BUFFER_PLAYBACK( "SET_SAMPLER_STATE" );
  474. Dx9Device()->SetSamplerState(dptr[1], (D3DSAMPLERSTATETYPE) dptr[2], dptr[3]);
  475. dptr+=4;
  476. break;
  477. }
  478. case PBCMD_DRAWPRIM:
  479. {
  480. VPROF_BUFFER_PLAYBACK( "DRAWPRIM" );
  481. tmZone( TELEMETRY_LEVEL2, TMZF_NONE, "Dx9Device()->DrawPrimitive" );
  482. Dx9Device()->DrawPrimitive( (D3DPRIMITIVETYPE) dptr[1], dptr[2], dptr[3] );
  483. dptr+=4;
  484. break;
  485. }
  486. case PBCMD_DRAWINDEXEDPRIM:
  487. {
  488. VPROF_BUFFER_PLAYBACK( "DRAWINDEXEDPRIM" );
  489. tmZone( TELEMETRY_LEVEL2, TMZF_NONE, "Dx9Device()->DrawIndexedPrimitive" );
  490. Dx9Device()->DrawIndexedPrimitive( (D3DPRIMITIVETYPE) dptr[1], dptr[2], dptr[3],
  491. dptr[4], dptr[5], dptr[6]);
  492. dptr+=7;
  493. break;
  494. }
  495. case PBCMD_SET_STREAM_SOURCE:
  496. {
  497. VPROF_BUFFER_PLAYBACK( "SET_STREAM_SOURCE" );
  498. Dx9Device()->SetStreamSource( dptr[1],(IDirect3DVertexBuffer9 *) FetchPtr(dptr+2),
  499. dptr[3],dptr[4] );
  500. dptr += 4+N_DWORDS( IDirect3DVertexBuffer9 * );
  501. break;
  502. }
  503. case PBCMD_SET_TEXTURE:
  504. {
  505. VPROF_BUFFER_PLAYBACK( "SET_TEXTURE" );
  506. Dx9Device()->SetTexture( dptr[1],(IDirect3DBaseTexture *) FetchPtr(dptr+2));
  507. dptr += 2+N_DWORDS_IN_PTR;
  508. break;
  509. }
  510. case PBCMD_SET_RENDER_TARGET:
  511. {
  512. VPROF_BUFFER_PLAYBACK( "SET_RENDER_TARGET" );
  513. Dx9Device()->SetRenderTarget( dptr[1],(IDirect3DSurface *) FetchPtr(dptr+2));
  514. dptr += 2+N_DWORDS_IN_PTR;
  515. break;
  516. }
  517. case PBCMD_SET_PIXEL_SHADER:
  518. {
  519. VPROF_BUFFER_PLAYBACK( "SET_PIXEL_SHADER" );
  520. Dx9Device()->SetPixelShader( (IDirect3DPixelShader9 *) FetchPtr(dptr+1));
  521. dptr += 1+N_DWORDS_IN_PTR;
  522. break;
  523. }
  524. case PBCMD_SET_INDICES:
  525. {
  526. VPROF_BUFFER_PLAYBACK( "SET_INDICES" );
  527. Dx9Device()->SetIndices( (IDirect3DIndexBuffer9*) FetchPtr(dptr+1));
  528. dptr += 1+N_DWORDS_IN_PTR;
  529. break;
  530. }
  531. case PBCMD_SET_DEPTH_STENCIL_SURFACE:
  532. {
  533. VPROF_BUFFER_PLAYBACK( "SET_DEPTH_STENCIL_SURFACE" );
  534. Dx9Device()->SetDepthStencilSurface( (IDirect3DSurface9*) FetchPtr(dptr+1));
  535. dptr += 1+N_DWORDS_IN_PTR;
  536. break;
  537. }
  538. case PBCMD_SETVIEWPORT:
  539. {
  540. VPROF_BUFFER_PLAYBACK( "SETVIEWPORT" );
  541. Dx9Device()->SetViewport( (D3DVIEWPORT9 const *) (dptr+1) );
  542. dptr += 1+N_DWORDS(D3DVIEWPORT9);
  543. break;
  544. }
  545. case PBCMD_SET_VERTEX_SHADER:
  546. {
  547. VPROF_BUFFER_PLAYBACK( "SET_VERTEX_SHADER" );
  548. Dx9Device()->SetVertexShader( (IDirect3DVertexShader9 *) FetchPtr(dptr+1));
  549. dptr += 1+N_DWORDS_IN_PTR;
  550. break;
  551. }
  552. case PBCMD_ASYNC_LOCK_VB:
  553. {
  554. VPROF_BUFFER_PLAYBACK( "ASYNC_LOCK_VB" );
  555. HandleAsynchronousLockVBCommand(dptr);
  556. dptr+=1+N_DWORDS_IN_PTR+3;
  557. break;
  558. }
  559. case PBCMD_ASYNC_UNLOCK_VB:
  560. {
  561. VPROF_BUFFER_PLAYBACK( "ASYNC_UNLOCK_VB" );
  562. HandleAsynchronousUnLockVBCommand( dptr );
  563. dptr+=1+N_DWORDS_IN_PTR+N_DWORDS( LockedBufferContext )+1;
  564. break;
  565. }
  566. case PBCMD_ASYNC_LOCK_IB:
  567. {
  568. VPROF_BUFFER_PLAYBACK( "ASYNC_LOCK_IB" );
  569. HandleAsynchronousLockIBCommand(dptr);
  570. dptr+=1+N_DWORDS_IN_PTR+3;
  571. break;
  572. }
  573. case PBCMD_ASYNC_UNLOCK_IB:
  574. {
  575. VPROF_BUFFER_PLAYBACK( "ASYNC_UNLOCK_IB" );
  576. HandleAsynchronousUnLockIBCommand( dptr );
  577. dptr+=1+N_DWORDS_IN_PTR+N_DWORDS( LockedBufferContext )+1;
  578. break;
  579. }
  580. case PBCMD_UNLOCK_VB:
  581. {
  582. VPROF_BUFFER_PLAYBACK( "UNLOCK_VB" );
  583. IDirect3DVertexBuffer9 *p=(IDirect3DVertexBuffer9 *) FetchPtr(dptr+1);
  584. p->Unlock();
  585. dptr += 1+N_DWORDS_IN_PTR;
  586. break;
  587. }
  588. case PBCMD_UNLOCK_IB:
  589. {
  590. VPROF_BUFFER_PLAYBACK( "UNLOCK_IB" );
  591. IDirect3DIndexBuffer9 *p=(IDirect3DIndexBuffer9 *) FetchPtr(dptr+1);
  592. p->Unlock();
  593. dptr += 1+N_DWORDS_IN_PTR;
  594. break;
  595. }
  596. case PBCMD_SET_VERTEX_SHADER_CONSTANT:
  597. {
  598. VPROF_BUFFER_PLAYBACK( "SET_VERTEX_SHADER_CONSTANT" );
  599. Dx9Device()->SetVertexShaderConstantF( dptr[1], (float const *) dptr+3, dptr[2]);
  600. dptr += 3+4*dptr[2];
  601. break;
  602. }
  603. case PBCMD_SET_BOOLEAN_VERTEX_SHADER_CONSTANT:
  604. {
  605. VPROF_BUFFER_PLAYBACK( "SET_BOOLEAN_VERTEX_SHADER_CONSTANT" );
  606. Dx9Device()->SetVertexShaderConstantB( dptr[1], (int const *) dptr+3, dptr[2]);
  607. dptr += 3+dptr[2];
  608. break;
  609. }
  610. case PBCMD_SET_INTEGER_VERTEX_SHADER_CONSTANT:
  611. {
  612. VPROF_BUFFER_PLAYBACK( "SET_INTEGER_VERTEX_SHADER_CONSTANT" );
  613. Dx9Device()->SetVertexShaderConstantI( dptr[1], (int const *) dptr+3, dptr[2]);
  614. dptr += 3+4*dptr[2];
  615. break;
  616. }
  617. case PBCMD_SET_PIXEL_SHADER_CONSTANT:
  618. {
  619. VPROF_BUFFER_PLAYBACK( "SET_PIXEL_SHADER_CONSTANT" );
  620. Dx9Device()->SetPixelShaderConstantF( dptr[1], (float const *) dptr+3, dptr[2]);
  621. dptr += 3+4*dptr[2];
  622. break;
  623. }
  624. case PBCMD_SET_BOOLEAN_PIXEL_SHADER_CONSTANT:
  625. {
  626. VPROF_BUFFER_PLAYBACK( "SET_BOOLEAN_PIXEL_SHADER_CONSTANT" );
  627. Dx9Device()->SetPixelShaderConstantB( dptr[1], (int const *) dptr+3, dptr[2]);
  628. dptr += 3+dptr[2];
  629. break;
  630. }
  631. case PBCMD_SET_INTEGER_PIXEL_SHADER_CONSTANT:
  632. {
  633. VPROF_BUFFER_PLAYBACK( "SET_INTEGER_PIXEL_SHADER_CONSTANT" );
  634. Dx9Device()->SetPixelShaderConstantI( dptr[1], (int const *) dptr+3, dptr[2]);
  635. dptr += 3+4*dptr[2];
  636. break;
  637. }
  638. case PBCMD_BEGIN_SCENE:
  639. {
  640. VPROF_BUFFER_PLAYBACK( "BEGIN_SCENE" );
  641. Dx9Device()->BeginScene();
  642. dptr++;
  643. break;
  644. }
  645. case PBCMD_END_SCENE:
  646. {
  647. VPROF_BUFFER_PLAYBACK( "END_SCENE" );
  648. Dx9Device()->EndScene();
  649. dptr++;
  650. break;
  651. }
  652. case PBCMD_CLEAR:
  653. {
  654. VPROF_BUFFER_PLAYBACK( "CLEAR" );
  655. dptr++;
  656. int count=*(dptr++);
  657. D3DRECT const *pRects=0;
  658. if (count)
  659. {
  660. pRects=(D3DRECT const *) dptr;
  661. dptr+=count*N_DWORDS( D3DRECT );
  662. }
  663. int flags=*(dptr++);
  664. D3DCOLOR color=*((D3DCOLOR const *) (dptr++));
  665. float z=*((float const *) (dptr++));
  666. int stencil=*(dptr++);
  667. Dx9Device()->Clear( count, pRects, flags, color, z, stencil );
  668. break;
  669. }
  670. case PBCMD_SET_VERTEXDECLARATION:
  671. {
  672. VPROF_BUFFER_PLAYBACK( "SET_VERTEXDECLARATION" );
  673. Dx9Device()->SetVertexDeclaration( (IDirect3DVertexDeclaration9 *) FetchPtr(dptr+1));
  674. dptr += 1+N_DWORDS_IN_PTR;
  675. break;
  676. }
  677. case PBCMD_SETCLIPPLANE:
  678. {
  679. VPROF_BUFFER_PLAYBACK( "SETCLIPPLANE" );
  680. Dx9Device()->SetClipPlane( dptr[1], (float const *) dptr+2 );
  681. dptr+=6;
  682. }
  683. break;
  684. case PBCMD_STRETCHRECT:
  685. {
  686. VPROF_BUFFER_PLAYBACK( "STRETCHRECT" );
  687. dptr++;
  688. IDirect3DSurface9 *pSourceSurface=(IDirect3DSurface9 *) FetchPtr(dptr);
  689. dptr+=N_DWORDS_IN_PTR;
  690. RECT const *pSourceRect=0;
  691. if (*(dptr++))
  692. pSourceRect=(RECT const *) dptr;
  693. dptr += N_DWORDS( RECT );
  694. IDirect3DSurface9 *pDestSurface= (IDirect3DSurface9 *) FetchPtr( dptr );
  695. dptr += N_DWORDS_IN_PTR;
  696. RECT const *pDestRect=0;
  697. if (*(dptr++))
  698. pDestRect=(RECT const *) dptr;
  699. dptr += N_DWORDS( RECT );
  700. D3DTEXTUREFILTERTYPE Filter = (D3DTEXTUREFILTERTYPE) *(dptr++);
  701. Dx9Device()->StretchRect( pSourceSurface, pSourceRect,
  702. pDestSurface, pDestRect,
  703. Filter );
  704. }
  705. break;
  706. case PBCMD_PRESENT:
  707. {
  708. VPROF_BUFFER_PLAYBACK( "PRESENT" );
  709. dptr++;
  710. RECT const *pSourceRect=0;
  711. if (* (dptr++) )
  712. pSourceRect=(RECT const *) dptr;
  713. dptr+=N_DWORDS( RECT );
  714. RECT const *pDestRect = 0;
  715. if (* (dptr++) )
  716. pDestRect=(RECT const *) dptr;
  717. dptr+=N_DWORDS( RECT );
  718. VD3DHWND hDestWindowOverride = (VD3DHWND) *(dptr++);
  719. RGNDATA const *pDirtyRegion=0;
  720. if ( *(dptr++) )
  721. pDirtyRegion= (RGNDATA const *) dptr;
  722. dptr+=N_DWORDS( RGNDATA );
  723. tmZone( TELEMETRY_LEVEL1, TMZF_NONE, "!D3DPresent" );
  724. Dx9Device()->Present( pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion );
  725. break;
  726. }
  727. case PBCMD_SET_SCISSOR_RECT:
  728. {
  729. VPROF_BUFFER_PLAYBACK( "SET_SCISSOR_RECT" );
  730. dptr++;
  731. const RECT *pRect = ( RECT * )FetchPtr( dptr );
  732. dptr += sizeof( RECT );
  733. Dx9Device()->SetScissorRect( pRect );
  734. }
  735. }
  736. }
  737. }
  738. #endif
  739. #endif // D3D_ASYNC_SUPPORTED