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.

943 lines
23 KiB

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