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.

1567 lines
42 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //===========================================================================//
  8. #ifdef D3D_ASYNC_SUPPORTED
  9. #ifndef D3DASYNC_H
  10. #define D3DASYNC_H
  11. #ifdef _WIN32
  12. #pragma once
  13. #endif
  14. // Set this to 1 to allow d3d calls to be buffered and played back on another thread
  15. // Slamming this off - it's causing very hot D3D9 function calls to not be inlined and contain a bunch of unused code. (Does this code even work/add real value any more?)
  16. #define SHADERAPI_USE_SMP 0
  17. // Set this to 1 to allow buffering of the whole frame to memory and then playback (singlethreaded).
  18. // This is for debugging only and is used to test the performance of just calling D3D and rendering without other CPU overhead.
  19. #define SHADERAPI_BUFFER_D3DCALLS 0
  20. #if SHADERAPI_BUFFER_D3DCALLS && !SHADERAPI_USE_SMP
  21. # error "SHADERAPI_USE_SMP must be 1 for SHADERAPI_BUFFER_D3DCALLS to work!"
  22. #endif
  23. #include "recording.h"
  24. #include "strtools.h"
  25. #include "glmgr/dxabstract.h"
  26. #ifdef NDEBUG
  27. #define DO_D3D(x) Dx9Device()->x
  28. #else
  29. #define DO_D3D(x) Dx9Device()->x
  30. //#define DO_D3D(x) { HRESULT hr=Dx9Device()->x; Assert( !FAILED(hr) ); }
  31. #endif
  32. #define PUSHBUFFER_NELEMS 4096
  33. enum PushBufferState
  34. {
  35. PUSHBUFFER_AVAILABLE,
  36. PUSHBUFFER_BEING_FILLED,
  37. PUSHBUFFER_SUBMITTED,
  38. PUSHBUFFER_BEING_USED_FOR_LOCKEDDATA,
  39. };
  40. class PushBuffer
  41. {
  42. friend class D3DDeviceWrapper;
  43. volatile PushBufferState m_State;
  44. uint32 m_BufferData[PUSHBUFFER_NELEMS];
  45. public:
  46. PushBuffer(void)
  47. {
  48. m_State = PUSHBUFFER_AVAILABLE;
  49. }
  50. };
  51. // When running multithreaded, lock for write calls actually return a pointer to temporary memory
  52. // buffer. When the buffer is later unlocked by the caller, data must be queued with the Unlock()
  53. // that lets the d3d thread know how much data to copy from where. One possible optimization for
  54. // things which write a lot of data into lock buffers woudl be to proviude a way for the caller to
  55. // occasionally check if the Lock() has been dequeued. If so, the the data pushed so far could be
  56. // copied asynchronously into the buffer, while the caller would be told to switch to writing
  57. // directly to the vertex buffer.
  58. //
  59. // another possibility would be lock()ing in advance for large ones, such as the world renderer,
  60. // or keeping multiple locked vb's open for meshbuilder.
  61. struct LockedBufferContext
  62. {
  63. PushBuffer *m_pPushBuffer; // if a push buffer was used to hold
  64. // the temporary data, this will be non-null
  65. void *m_pMallocedMemory; // if memory had to be malloc'd, this will be set.
  66. size_t m_MallocSize; // # of bytes malloced if mallocedmem ptr non-null
  67. LockedBufferContext( void )
  68. {
  69. m_pPushBuffer = NULL;
  70. m_pMallocedMemory = NULL;
  71. }
  72. };
  73. // push buffer commands follow
  74. enum PushBufferCommand
  75. {
  76. PBCMD_END, // at end of push buffer
  77. PBCMD_SET_RENDERSTATE, // state, val
  78. PBCMD_SET_TEXTURE, // stage, txtr
  79. PBCMD_DRAWPRIM, // prim type, start v, nprims
  80. PBCMD_DRAWINDEXEDPRIM, // prim type, baseidx, minidx, numv, starti, pcount
  81. PBCMD_SET_PIXEL_SHADER, // shaderptr
  82. PBCMD_SET_VERTEX_SHADER, // shaderptr
  83. PBCMD_SET_PIXEL_SHADER_CONSTANT, // startreg, nregs, data...
  84. PBCMD_SET_BOOLEAN_PIXEL_SHADER_CONSTANT, // startreg, nregs, data...
  85. PBCMD_SET_INTEGER_PIXEL_SHADER_CONSTANT, // startreg, nregs, data...
  86. PBCMD_SET_VERTEX_SHADER_CONSTANT, // startreg, nregs, data...
  87. PBCMD_SET_BOOLEAN_VERTEX_SHADER_CONSTANT, // startreg, nregs, data...
  88. PBCMD_SET_INTEGER_VERTEX_SHADER_CONSTANT, // startreg, nregs, data...
  89. PBCMD_SET_RENDER_TARGET, // idx, targetptr
  90. PBCMD_SET_DEPTH_STENCIL_SURFACE, // surfptr
  91. PBCMD_SET_STREAM_SOURCE, // idx, sptr, ofs, stride
  92. PBCMD_SET_INDICES, // idxbuffer
  93. PBCMD_SET_SAMPLER_STATE, // stage, state, val
  94. PBCMD_UNLOCK_VB, // vptr
  95. PBCMD_UNLOCK_IB, // idxbufptr
  96. PBCMD_SETVIEWPORT, // vp_struct
  97. PBCMD_CLEAR, // count, n rect structs, flags, color, z, stencil
  98. PBCMD_SET_VERTEXDECLARATION, // vdeclptr
  99. PBCMD_BEGIN_SCENE, //
  100. PBCMD_END_SCENE, //
  101. PBCMD_PRESENT, // complicated..see code
  102. PBCMD_SETCLIPPLANE, // idx, 4 floats
  103. PBCMD_STRETCHRECT, // see code
  104. PBCMD_ASYNC_LOCK_VB, // see code
  105. PBCMD_ASYNC_UNLOCK_VB,
  106. PBCMD_ASYNC_LOCK_IB, // see code
  107. PBCMD_ASYNC_UNLOCK_IB,
  108. PBCMD_SET_SCISSOR_RECT, // RECT
  109. };
  110. #define N_DWORDS( x ) (( sizeof(x)+3)/sizeof( DWORD ))
  111. #define N_DWORDS_IN_PTR (N_DWORDS( void * ))
  112. class D3DDeviceWrapper
  113. {
  114. private:
  115. IDirect3DDevice9 *m_pD3DDevice;
  116. bool m_bSupportsTessellation;
  117. int m_nCurrentTessLevel;
  118. TessellationMode_t m_nTessellationMode;
  119. #if SHADERAPI_USE_SMP
  120. uintptr_t m_pASyncThreadHandle;
  121. PushBuffer *m_pCurPushBuffer;
  122. uint32 *m_pOutputPtr;
  123. size_t m_PushBufferFreeSlots;
  124. #endif
  125. #if SHADERAPI_BUFFER_D3DCALLS
  126. bool m_bBufferingD3DCalls;
  127. # define SHADERAPI_BUFFER_MAXRENDERTARGETS 4
  128. IDirect3DSurface9 *m_StoredRenderTargets[SHADERAPI_BUFFER_MAXRENDERTARGETS];
  129. #endif
  130. PushBuffer *FindFreePushBuffer( PushBufferState newstate ); // find a free push buffer and change its state
  131. void GetPushBuffer(void); // set us up to point at a new push buffer
  132. void SubmitPushBufferAndGetANewOne(void); // submit the current push buffer
  133. void ExecutePushBuffer( PushBuffer const *pb);
  134. #if SHADERAPI_USE_SMP
  135. void Synchronize(void); // wait for all commands to be done
  136. #else
  137. FORCEINLINE void Synchronize(void)
  138. {
  139. }
  140. #endif
  141. void SubmitIfNotBusy(void);
  142. #if SHADERAPI_USE_SMP
  143. template<class T> FORCEINLINE void PushStruct( PushBufferCommand cmd, T const *str )
  144. {
  145. int nwords=N_DWORDS( T );
  146. AllocatePushBufferSpace( 1+ nwords );
  147. m_pOutputPtr[0]=cmd;
  148. memcpy( m_pOutputPtr+1, str, sizeof( T ) );
  149. m_pOutputPtr += 1+nwords;
  150. }
  151. FORCEINLINE void AllocatePushBufferSpace(size_t nSlots)
  152. {
  153. // check for N slots of space, and decrement amount of space left
  154. if ( nSlots>m_PushBufferFreeSlots ) // out of room?
  155. {
  156. SubmitPushBufferAndGetANewOne();
  157. }
  158. m_PushBufferFreeSlots -= nSlots;
  159. }
  160. // simple methods for pushing a few words into output buffer
  161. FORCEINLINE void Push( PushBufferCommand cmd )
  162. {
  163. AllocatePushBufferSpace(1);
  164. m_pOutputPtr[0]=cmd;
  165. m_pOutputPtr++;
  166. }
  167. FORCEINLINE void Push( PushBufferCommand cmd, int arg1)
  168. {
  169. AllocatePushBufferSpace(2);
  170. m_pOutputPtr[0]=cmd;
  171. m_pOutputPtr[1]=arg1;
  172. m_pOutputPtr += 2;
  173. }
  174. FORCEINLINE void Push( PushBufferCommand cmd, void *ptr )
  175. {
  176. AllocatePushBufferSpace(1+N_DWORDS_IN_PTR);
  177. *(m_pOutputPtr++)=cmd;
  178. *((void **) m_pOutputPtr)=ptr;
  179. m_pOutputPtr+=N_DWORDS_IN_PTR;
  180. }
  181. FORCEINLINE void Push( PushBufferCommand cmd, void *ptr, void *ptr1 )
  182. {
  183. AllocatePushBufferSpace(1+2*N_DWORDS_IN_PTR);
  184. *(m_pOutputPtr++)=cmd;
  185. *((void **) m_pOutputPtr)=ptr;
  186. m_pOutputPtr+=N_DWORDS_IN_PTR;
  187. *((void **) m_pOutputPtr)=ptr1;
  188. m_pOutputPtr+=N_DWORDS_IN_PTR;
  189. }
  190. FORCEINLINE void Push( PushBufferCommand cmd, void *arg1, uint32 arg2, uint32 arg3, uint32 arg4,
  191. void *arg5)
  192. {
  193. AllocatePushBufferSpace(1+N_DWORDS_IN_PTR+1+1+1+N_DWORDS_IN_PTR);
  194. *(m_pOutputPtr++)=cmd;
  195. *((void **) m_pOutputPtr)=arg1;
  196. m_pOutputPtr+=N_DWORDS_IN_PTR;
  197. *(m_pOutputPtr++)=arg2;
  198. *(m_pOutputPtr++)=arg3;
  199. *(m_pOutputPtr++)=arg4;
  200. *((void **) m_pOutputPtr)=arg5;
  201. m_pOutputPtr+=N_DWORDS_IN_PTR;
  202. }
  203. FORCEINLINE void Push( PushBufferCommand cmd, uint32 arg1, void *ptr )
  204. {
  205. AllocatePushBufferSpace(2+N_DWORDS_IN_PTR);
  206. *(m_pOutputPtr++)=cmd;
  207. *(m_pOutputPtr++)=arg1;
  208. *((void **) m_pOutputPtr)=ptr;
  209. m_pOutputPtr+=N_DWORDS_IN_PTR;
  210. }
  211. FORCEINLINE void Push( PushBufferCommand cmd, uint32 arg1, void *ptr, int arg2, int arg3 )
  212. {
  213. AllocatePushBufferSpace( 4+N_DWORDS_IN_PTR );
  214. *(m_pOutputPtr++)=cmd;
  215. *(m_pOutputPtr++)=arg1;
  216. *((void **) m_pOutputPtr)=ptr;
  217. m_pOutputPtr+=N_DWORDS_IN_PTR;
  218. m_pOutputPtr[0]=arg2;
  219. m_pOutputPtr[1]=arg3;
  220. m_pOutputPtr += 2;
  221. }
  222. FORCEINLINE void Push( PushBufferCommand cmd, int arg1, int arg2)
  223. {
  224. AllocatePushBufferSpace(3);
  225. m_pOutputPtr[0]=cmd;
  226. m_pOutputPtr[1]=arg1;
  227. m_pOutputPtr[2]=arg2;
  228. m_pOutputPtr += 3;
  229. }
  230. FORCEINLINE void Push( PushBufferCommand cmd, int arg1, int arg2, int arg3)
  231. {
  232. AllocatePushBufferSpace(4);
  233. m_pOutputPtr[0]=cmd;
  234. m_pOutputPtr[1]=arg1;
  235. m_pOutputPtr[2]=arg2;
  236. m_pOutputPtr[3]=arg3;
  237. m_pOutputPtr += 4;
  238. }
  239. FORCEINLINE void Push( PushBufferCommand cmd, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6 )
  240. {
  241. AllocatePushBufferSpace(7);
  242. m_pOutputPtr[0]=cmd;
  243. m_pOutputPtr[1]=arg1;
  244. m_pOutputPtr[2]=arg2;
  245. m_pOutputPtr[3]=arg3;
  246. m_pOutputPtr[4]=arg4;
  247. m_pOutputPtr[5]=arg5;
  248. m_pOutputPtr[6]=arg6;
  249. m_pOutputPtr += 7;
  250. }
  251. #else
  252. template<class T> FORCEINLINE void PushStruct( PushBufferCommand cmd, T const *str )
  253. {
  254. }
  255. FORCEINLINE void AllocatePushBufferSpace(size_t nSlots)
  256. {
  257. }
  258. // simple methods for pushing a few words into output buffer
  259. FORCEINLINE void Push( PushBufferCommand cmd )
  260. {
  261. }
  262. FORCEINLINE void Push( PushBufferCommand cmd, int arg1)
  263. {
  264. }
  265. FORCEINLINE void Push( PushBufferCommand cmd, void *ptr )
  266. {
  267. }
  268. FORCEINLINE void Push( PushBufferCommand cmd, void *ptr, void *ptr1 )
  269. {
  270. }
  271. FORCEINLINE void Push( PushBufferCommand cmd, void *arg1, uint32 arg2, uint32 arg3, uint32 arg4,
  272. void *arg5)
  273. {
  274. }
  275. FORCEINLINE void Push( PushBufferCommand cmd, uint32 arg1, void *ptr )
  276. {
  277. }
  278. FORCEINLINE void Push( PushBufferCommand cmd, uint32 arg1, void *ptr, int arg2, int arg3 )
  279. {
  280. }
  281. FORCEINLINE void Push( PushBufferCommand cmd, int arg1, int arg2)
  282. {
  283. }
  284. FORCEINLINE void Push( PushBufferCommand cmd, int arg1, int arg2, int arg3)
  285. {
  286. }
  287. FORCEINLINE void Push( PushBufferCommand cmd, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6 )
  288. {
  289. }
  290. #endif
  291. FORCEINLINE bool ASyncMode(void) const
  292. {
  293. #if SHADERAPI_USE_SMP
  294. # if SHADERAPI_BUFFER_D3DCALLS
  295. return m_bBufferingD3DCalls;
  296. # else
  297. return (m_pASyncThreadHandle != 0 );
  298. # endif
  299. #else
  300. return false;
  301. #endif
  302. }
  303. FORCEINLINE IDirect3DDevice9* Dx9Device(void) const
  304. {
  305. return m_pD3DDevice;
  306. }
  307. void AsynchronousLock( IDirect3DVertexBuffer9* vb, size_t offset, size_t size, void **ptr,
  308. DWORD flags,
  309. LockedBufferContext *lb);
  310. void AsynchronousLock( IDirect3DIndexBuffer9* ib, size_t offset, size_t size, void **ptr,
  311. DWORD flags,
  312. LockedBufferContext *lb);
  313. // handlers for push buffer contexts
  314. void HandleAsynchronousLockVBCommand( uint32 const *dptr );
  315. void HandleAsynchronousUnLockVBCommand( uint32 const *dptr );
  316. void HandleAsynchronousLockIBCommand( uint32 const *dptr );
  317. void HandleAsynchronousUnLockIBCommand( uint32 const *dptr );
  318. public:
  319. #if SHADERAPI_BUFFER_D3DCALLS
  320. void ExecuteAllWork( void );
  321. #endif
  322. void RunThread( void ); // this is what the worker thread runs
  323. void SetASyncMode( bool onoff );
  324. bool IsActive( void )const
  325. {
  326. return m_pD3DDevice != NULL;
  327. }
  328. void D3DeviceWrapper(void)
  329. {
  330. m_pD3DDevice = 0;
  331. #if SHADERAPI_USE_SMP
  332. m_pASyncThreadHandle = 0;
  333. #endif
  334. #if SHADERAPI_BUFFER_D3DCALLS
  335. m_bBufferingD3DCalls = false;
  336. #endif
  337. }
  338. void SetDevicePtr(IDirect3DDevice9 *pD3DDev )
  339. {
  340. m_pD3DDevice = pD3DDev;
  341. }
  342. void SetSupportsTessellation( bool bSupportsTessellation )
  343. {
  344. m_bSupportsTessellation = bSupportsTessellation;
  345. }
  346. void ShutDownDevice(void)
  347. {
  348. if ( ASyncMode() )
  349. {
  350. // sync w/ thread
  351. }
  352. m_pD3DDevice = 0;
  353. }
  354. void FORCEINLINE SetDepthStencilSurface( IDirect3DSurface9 *new_stencil )
  355. {
  356. if ( ASyncMode() )
  357. Push( PBCMD_SET_DEPTH_STENCIL_SURFACE, new_stencil );
  358. else
  359. DO_D3D( SetDepthStencilSurface( new_stencil ) );
  360. }
  361. HRESULT CreateCubeTexture(
  362. UINT EdgeLength,
  363. UINT Levels,
  364. DWORD Usage,
  365. D3DFORMAT Format,
  366. D3DPOOL Pool,
  367. IDirect3DCubeTexture9 ** ppCubeTexture,
  368. HANDLE* pSharedHandle,
  369. char *debugLabel = NULL // <-- OK to not pass this arg, only passed through on DX_TO_GL_ABSTRACTION
  370. )
  371. {
  372. Synchronize();
  373. return m_pD3DDevice->CreateCubeTexture( EdgeLength, Levels, Usage, Format, Pool,
  374. ppCubeTexture, pSharedHandle
  375. #if defined( DX_TO_GL_ABSTRACTION )
  376. ,debugLabel
  377. #endif
  378. );
  379. }
  380. HRESULT CreateVolumeTexture(
  381. UINT Width,
  382. UINT Height,
  383. UINT Depth,
  384. UINT Levels,
  385. DWORD Usage,
  386. D3DFORMAT Format,
  387. D3DPOOL Pool,
  388. IDirect3DVolumeTexture9** ppVolumeTexture,
  389. HANDLE* pSharedHandle,
  390. char *debugLabel = NULL // <-- OK to not pass this arg, only passed through on DX_TO_GL_ABSTRACTION
  391. )
  392. {
  393. Synchronize();
  394. return m_pD3DDevice->CreateVolumeTexture( Width, Height, Depth, Levels,
  395. Usage, Format, Pool, ppVolumeTexture,
  396. pSharedHandle
  397. #if defined( DX_TO_GL_ABSTRACTION )
  398. ,debugLabel
  399. #endif
  400. );
  401. }
  402. HRESULT CreateOffscreenPlainSurface( UINT Width,
  403. UINT Height,
  404. D3DFORMAT Format,
  405. D3DPOOL Pool,
  406. IDirect3DSurface9** ppSurface,
  407. HANDLE* pSharedHandle)
  408. {
  409. Synchronize();
  410. return m_pD3DDevice->CreateOffscreenPlainSurface( Width, Height, Format, Pool,
  411. ppSurface, pSharedHandle);
  412. }
  413. HRESULT CreateTexture(
  414. UINT Width,
  415. UINT Height,
  416. UINT Levels,
  417. DWORD Usage,
  418. D3DFORMAT Format,
  419. D3DPOOL Pool,
  420. IDirect3DTexture9** ppTexture,
  421. HANDLE* pSharedHandle,
  422. char *debugLabel = NULL // <-- OK to not pass this arg, only passed through on DX_TO_GL_ABSTRACTION
  423. )
  424. {
  425. Synchronize();
  426. return m_pD3DDevice->CreateTexture( Width, Height, Levels, Usage,
  427. Format, Pool, ppTexture, pSharedHandle
  428. #if defined( DX_TO_GL_ABSTRACTION )
  429. ,debugLabel
  430. #endif
  431. );
  432. }
  433. HRESULT GetRenderTargetData(
  434. IDirect3DSurface9* pRenderTarget,
  435. IDirect3DSurface9* pDestSurface
  436. )
  437. {
  438. Synchronize();
  439. return m_pD3DDevice->GetRenderTargetData( pRenderTarget, pDestSurface );
  440. }
  441. void GetDeviceCaps( D3DCAPS9 * pCaps )
  442. {
  443. Synchronize();
  444. m_pD3DDevice->GetDeviceCaps( pCaps );
  445. }
  446. LPCSTR GetPixelShaderProfile( void )
  447. {
  448. Synchronize();
  449. return D3DXGetPixelShaderProfile( m_pD3DDevice );
  450. }
  451. HRESULT TestCooperativeLevel( void )
  452. {
  453. // hack! We are going to assume that calling this immediately when in buffered mode isn't going to cause problems.
  454. #if !SHADERAPI_BUFFER_D3DCALLS
  455. Synchronize();
  456. #endif
  457. return m_pD3DDevice->TestCooperativeLevel();
  458. }
  459. HRESULT GetFrontBufferData( UINT iSwapChain, IDirect3DSurface9 * pDestSurface )
  460. {
  461. Synchronize();
  462. return m_pD3DDevice->GetFrontBufferData( iSwapChain, pDestSurface );
  463. }
  464. void SetGammaRamp( int swapchain, int flags, D3DGAMMARAMP const *pRamp)
  465. {
  466. Synchronize();
  467. m_pD3DDevice->SetGammaRamp( swapchain, flags, pRamp);
  468. }
  469. HRESULT GetTexture( DWORD Stage, IDirect3DBaseTexture9 ** ppTexture )
  470. {
  471. Synchronize();
  472. return m_pD3DDevice->GetTexture( Stage, ppTexture );
  473. }
  474. HRESULT GetFVF( DWORD * pFVF )
  475. {
  476. Synchronize();
  477. return m_pD3DDevice->GetFVF( pFVF );
  478. }
  479. HRESULT GetDepthStencilSurface(
  480. IDirect3DSurface9 ** ppZStencilSurface
  481. )
  482. {
  483. Synchronize();
  484. return m_pD3DDevice->GetDepthStencilSurface( ppZStencilSurface );
  485. }
  486. FORCEINLINE void SetClipPlane( int idx, float const * pplane)
  487. {
  488. RECORD_COMMAND( DX8_SET_CLIP_PLANE, 5 );
  489. RECORD_INT( idx );
  490. RECORD_FLOAT( pplane[0] );
  491. RECORD_FLOAT( pplane[1] );
  492. RECORD_FLOAT( pplane[2] );
  493. RECORD_FLOAT( pplane[3] );
  494. #if SHADERAPI_USE_SMP
  495. if ( ASyncMode() )
  496. {
  497. AllocatePushBufferSpace( 6 );
  498. m_pOutputPtr[0]=PBCMD_SETCLIPPLANE;
  499. m_pOutputPtr[1]=idx;
  500. memcpy(m_pOutputPtr+2,pplane, 4*sizeof(float) );
  501. m_pOutputPtr += 6;
  502. }
  503. else
  504. #endif
  505. DO_D3D( SetClipPlane( idx, pplane ) );
  506. }
  507. FORCEINLINE void SetVertexDeclaration( IDirect3DVertexDeclaration9 *decl )
  508. {
  509. RECORD_COMMAND( DX8_SET_VERTEX_DECLARATION, 1 );
  510. RECORD_INT( ( int ) decl );
  511. #if SHADERAPI_USE_SMP
  512. if ( ASyncMode() )
  513. {
  514. Push( PBCMD_SET_VERTEXDECLARATION, decl );
  515. }
  516. else
  517. #endif
  518. DO_D3D( SetVertexDeclaration( decl ) );
  519. }
  520. FORCEINLINE void SetViewport( D3DVIEWPORT9 const *vp )
  521. {
  522. RECORD_COMMAND( DX8_SET_VIEWPORT, 1 );
  523. RECORD_STRUCT( vp, sizeof( *vp ));
  524. #if SHADERAPI_USE_SMP
  525. if ( ASyncMode() )
  526. PushStruct( PBCMD_SETVIEWPORT, vp );
  527. else
  528. #endif
  529. DO_D3D( SetViewport( vp ) );
  530. }
  531. HRESULT GetRenderTarget(
  532. DWORD RenderTargetIndex,
  533. IDirect3DSurface9 ** ppRenderTarget)
  534. {
  535. #if SHADERAPI_BUFFER_D3DCALLS
  536. if ( ASyncMode() )
  537. {
  538. Assert( RenderTargetIndex >= 0 && RenderTargetIndex < SHADERAPI_BUFFER_MAXRENDERTARGETS );
  539. *ppRenderTarget = m_StoredRenderTargets[RenderTargetIndex];
  540. return D3D_OK;
  541. }
  542. #endif
  543. Synchronize();
  544. return m_pD3DDevice->GetRenderTarget( RenderTargetIndex, ppRenderTarget );
  545. }
  546. HRESULT CreateQuery( D3DQUERYTYPE Type, IDirect3DQuery9** ppQuery )
  547. {
  548. Synchronize();
  549. return m_pD3DDevice->CreateQuery( Type, ppQuery );
  550. }
  551. HRESULT CreateRenderTarget(
  552. UINT Width,
  553. UINT Height,
  554. D3DFORMAT Format,
  555. D3DMULTISAMPLE_TYPE MultiSample,
  556. DWORD MultisampleQuality,
  557. BOOL Lockable,
  558. IDirect3DSurface9** ppSurface,
  559. HANDLE* pSharedHandle
  560. )
  561. {
  562. Synchronize();
  563. return m_pD3DDevice->CreateRenderTarget( Width, Height, Format, MultiSample,
  564. MultisampleQuality, Lockable, ppSurface,
  565. pSharedHandle);
  566. }
  567. HRESULT CreateDepthStencilSurface(
  568. UINT Width,
  569. UINT Height,
  570. D3DFORMAT Format,
  571. D3DMULTISAMPLE_TYPE MultiSample,
  572. DWORD MultisampleQuality,
  573. BOOL Discard,
  574. IDirect3DSurface9** ppSurface,
  575. HANDLE* pSharedHandle
  576. )
  577. {
  578. Synchronize();
  579. return m_pD3DDevice->CreateDepthStencilSurface( Width, Height, Format, MultiSample,
  580. MultisampleQuality, Discard, ppSurface,
  581. pSharedHandle );
  582. }
  583. FORCEINLINE void SetRenderTarget( int idx, IDirect3DSurface9 *new_rt )
  584. {
  585. if (ASyncMode())
  586. {
  587. Push( PBCMD_SET_RENDER_TARGET, idx, new_rt );
  588. #if SHADERAPI_BUFFER_D3DCALLS
  589. m_StoredRenderTargets[idx] = new_rt;
  590. #endif
  591. }
  592. else
  593. {
  594. // NOTE: If the debug runtime breaks here on the shadow depth render target that is normal. dx9 doesn't directly support shadow
  595. // depth texturing so we are forced to initialize this texture without the render target flagr
  596. DO_D3D( SetRenderTarget( idx, new_rt) );
  597. }
  598. }
  599. FORCEINLINE void LightEnable( int lidx, bool onoff )
  600. {
  601. RECORD_COMMAND( DX8_LIGHT_ENABLE, 2 );
  602. RECORD_INT( lidx );
  603. RECORD_INT( onoff );
  604. Synchronize();
  605. DO_D3D( LightEnable( lidx, onoff ) );
  606. }
  607. FORCEINLINE void SetRenderState( D3DRENDERSTATETYPE state, DWORD val )
  608. {
  609. // Assert( state >= 0 && state < MAX_NUM_RENDERSTATES );
  610. RECORD_RENDER_STATE( state, val );
  611. if (ASyncMode())
  612. {
  613. Push( PBCMD_SET_RENDERSTATE, state, val );
  614. }
  615. else
  616. DO_D3D( SetRenderState( state, val ) );
  617. }
  618. FORCEINLINE void SetRenderStateInline( D3DRENDERSTATETYPE state, DWORD val )
  619. {
  620. // Assert( state >= 0 && state < MAX_NUM_RENDERSTATES );
  621. RECORD_RENDER_STATE( state, val );
  622. if (ASyncMode())
  623. {
  624. SetRenderState( state, val );
  625. }
  626. else
  627. {
  628. #ifdef DX_TO_GL_ABSTRACTION
  629. DO_D3D( SetRenderStateInline( state, val ) );
  630. #else
  631. DO_D3D( SetRenderState( state, val ) );
  632. #endif
  633. }
  634. }
  635. FORCEINLINE void SetScissorRect( const RECT *pScissorRect )
  636. {
  637. RECORD_COMMAND( DX8_SET_SCISSOR_RECT, 1 );
  638. RECORD_STRUCT( pScissorRect, 4 * sizeof(LONG) );
  639. #if SHADERAPI_USE_SMP
  640. if ( ASyncMode() )
  641. {
  642. AllocatePushBufferSpace( 5 );
  643. m_pOutputPtr[0] = PBCMD_SET_SCISSOR_RECT;
  644. memcpy( m_pOutputPtr + 1, pScissorRect, sizeof( *pScissorRect ) );
  645. }
  646. else
  647. #endif
  648. DO_D3D( SetScissorRect( pScissorRect ) );
  649. }
  650. FORCEINLINE void SetVertexShaderConstantF( UINT StartRegister, CONST float * pConstantData,
  651. UINT Vector4fCount)
  652. {
  653. RECORD_COMMAND( DX8_SET_VERTEX_SHADER_CONSTANT, 3 );
  654. RECORD_INT( StartRegister );
  655. RECORD_INT( Vector4fCount );
  656. RECORD_STRUCT( pConstantData, Vector4fCount * 4 * sizeof(float) );
  657. #if SHADERAPI_USE_SMP
  658. if ( ASyncMode() )
  659. {
  660. AllocatePushBufferSpace(3+4*Vector4fCount);
  661. m_pOutputPtr[0]=PBCMD_SET_VERTEX_SHADER_CONSTANT;
  662. m_pOutputPtr[1]=StartRegister;
  663. m_pOutputPtr[2]=Vector4fCount;
  664. memcpy(m_pOutputPtr+3,pConstantData,sizeof(float)*4*Vector4fCount);
  665. m_pOutputPtr+=3+4*Vector4fCount;
  666. }
  667. else
  668. #endif
  669. DO_D3D( SetVertexShaderConstantF( StartRegister, pConstantData, Vector4fCount ) );
  670. }
  671. FORCEINLINE void SetVertexShaderConstantB( UINT StartRegister, CONST int * pConstantData,
  672. UINT BoolCount)
  673. {
  674. RECORD_COMMAND( DX8_SET_VERTEX_SHADER_CONSTANT, 3 );
  675. RECORD_INT( StartRegister );
  676. RECORD_INT( BoolCount );
  677. RECORD_STRUCT( pConstantData, BoolCount * sizeof(int) );
  678. #if SHADERAPI_USE_SMP
  679. if ( ASyncMode() )
  680. {
  681. AllocatePushBufferSpace(3+BoolCount);
  682. m_pOutputPtr[0]=PBCMD_SET_BOOLEAN_VERTEX_SHADER_CONSTANT;
  683. m_pOutputPtr[1]=StartRegister;
  684. m_pOutputPtr[2]=BoolCount;
  685. memcpy(m_pOutputPtr+3,pConstantData,sizeof(int)*BoolCount);
  686. m_pOutputPtr+=3+BoolCount;
  687. }
  688. else
  689. #endif
  690. DO_D3D( SetVertexShaderConstantB( StartRegister, pConstantData, BoolCount ) );
  691. }
  692. FORCEINLINE void SetVertexShaderConstantI( UINT StartRegister, CONST int * pConstantData,
  693. UINT Vector4IntCount)
  694. {
  695. RECORD_COMMAND( DX8_SET_VERTEX_SHADER_CONSTANT, 3 );
  696. RECORD_INT( StartRegister );
  697. RECORD_INT( Vector4IntCount );
  698. RECORD_STRUCT( pConstantData, Vector4IntCount * 4 * sizeof(int) );
  699. #if SHADERAPI_USE_SMP
  700. if ( ASyncMode() )
  701. {
  702. AllocatePushBufferSpace(3+4*Vector4IntCount);
  703. m_pOutputPtr[0]=PBCMD_SET_INTEGER_VERTEX_SHADER_CONSTANT;
  704. m_pOutputPtr[1]=StartRegister;
  705. m_pOutputPtr[2]=Vector4IntCount;
  706. memcpy(m_pOutputPtr+3,pConstantData,sizeof(int)*4*Vector4IntCount);
  707. m_pOutputPtr+=3+4*Vector4IntCount;
  708. }
  709. else
  710. #endif
  711. DO_D3D( SetVertexShaderConstantI( StartRegister, pConstantData, Vector4IntCount ) );
  712. }
  713. FORCEINLINE void SetPixelShaderConstantF( UINT StartRegister, CONST float * pConstantData,
  714. UINT Vector4fCount)
  715. {
  716. RECORD_COMMAND( DX8_SET_PIXEL_SHADER_CONSTANT, 3 );
  717. RECORD_INT( StartRegister );
  718. RECORD_INT( Vector4fCount );
  719. RECORD_STRUCT( pConstantData, Vector4fCount * 4 * sizeof(float) );
  720. #if SHADERAPI_USE_SMP
  721. if ( ASyncMode() )
  722. {
  723. AllocatePushBufferSpace(3+4*Vector4fCount);
  724. m_pOutputPtr[0]=PBCMD_SET_PIXEL_SHADER_CONSTANT;
  725. m_pOutputPtr[1]=StartRegister;
  726. m_pOutputPtr[2]=Vector4fCount;
  727. memcpy(m_pOutputPtr+3,pConstantData,sizeof(float)*4*Vector4fCount);
  728. m_pOutputPtr+=3+4*Vector4fCount;
  729. }
  730. else
  731. #endif
  732. DO_D3D( SetPixelShaderConstantF( StartRegister, pConstantData, Vector4fCount ) );
  733. }
  734. FORCEINLINE void SetPixelShaderConstantB( UINT StartRegister, CONST int * pConstantData,
  735. UINT BoolCount)
  736. {
  737. RECORD_COMMAND( DX8_SET_PIXEL_SHADER_CONSTANT, 3 );
  738. RECORD_INT( StartRegister );
  739. RECORD_INT( BoolCount );
  740. RECORD_STRUCT( pConstantData, BoolCount * sizeof(int) );
  741. #if SHADERAPI_USE_SMP
  742. if ( ASyncMode() )
  743. {
  744. AllocatePushBufferSpace(3+BoolCount);
  745. m_pOutputPtr[0]=PBCMD_SET_BOOLEAN_PIXEL_SHADER_CONSTANT;
  746. m_pOutputPtr[1]=StartRegister;
  747. m_pOutputPtr[2]=BoolCount;
  748. memcpy(m_pOutputPtr+3,pConstantData,sizeof(int)*BoolCount);
  749. m_pOutputPtr+=3+BoolCount;
  750. }
  751. else
  752. #endif
  753. DO_D3D( SetPixelShaderConstantB( StartRegister, pConstantData, BoolCount ) );
  754. }
  755. FORCEINLINE void SetPixelShaderConstantI( UINT StartRegister, CONST int * pConstantData,
  756. UINT Vector4IntCount)
  757. {
  758. RECORD_COMMAND( DX8_SET_PIXEL_SHADER_CONSTANT, 3 );
  759. RECORD_INT( StartRegister );
  760. RECORD_INT( Vector4IntCount );
  761. RECORD_STRUCT( pConstantData, Vector4IntCount * 4 * sizeof(int) );
  762. #if SHADERAPI_USE_SMP
  763. if ( ASyncMode() )
  764. {
  765. AllocatePushBufferSpace(3+4*Vector4IntCount);
  766. m_pOutputPtr[0]=PBCMD_SET_INTEGER_PIXEL_SHADER_CONSTANT;
  767. m_pOutputPtr[1]=StartRegister;
  768. m_pOutputPtr[2]=Vector4IntCount;
  769. memcpy(m_pOutputPtr+3,pConstantData,sizeof(int)*4*Vector4IntCount);
  770. m_pOutputPtr+=3+4*Vector4IntCount;
  771. }
  772. else
  773. #endif
  774. DO_D3D( SetPixelShaderConstantI( StartRegister, pConstantData, Vector4IntCount ) );
  775. }
  776. HRESULT StretchRect( IDirect3DSurface9 * pSourceSurface,
  777. CONST RECT * pSourceRect,
  778. IDirect3DSurface9 * pDestSurface,
  779. CONST RECT * pDestRect,
  780. D3DTEXTUREFILTERTYPE Filter )
  781. {
  782. #if SHADERAPI_USE_SMP
  783. if ( ASyncMode() )
  784. {
  785. AllocatePushBufferSpace(1+1+1+N_DWORDS( RECT )+1+1+N_DWORDS( RECT ) + 1);
  786. *(m_pOutputPtr++)=PBCMD_STRETCHRECT;
  787. *(m_pOutputPtr++)=(int) pSourceSurface;
  788. *(m_pOutputPtr++)=(pSourceRect != NULL);
  789. if (pSourceRect)
  790. {
  791. memcpy(m_pOutputPtr,pSourceRect,sizeof(RECT));
  792. }
  793. m_pOutputPtr+=N_DWORDS(RECT);
  794. *(m_pOutputPtr++)=(int) pDestSurface;
  795. *(m_pOutputPtr++)=(pDestRect != NULL);
  796. if (pDestRect)
  797. memcpy(m_pOutputPtr,pDestRect,sizeof(RECT));
  798. m_pOutputPtr+=N_DWORDS(RECT);
  799. *(m_pOutputPtr++)=Filter;
  800. return S_OK; // !bug!
  801. }
  802. else
  803. #endif
  804. return m_pD3DDevice->
  805. StretchRect( pSourceSurface, pSourceRect, pDestSurface, pDestRect, Filter );
  806. }
  807. FORCEINLINE void BeginScene(void)
  808. {
  809. RECORD_COMMAND( DX8_BEGIN_SCENE, 0 );
  810. if ( ASyncMode() )
  811. Push( PBCMD_BEGIN_SCENE );
  812. else
  813. DO_D3D( BeginScene() );
  814. }
  815. FORCEINLINE void EndScene(void)
  816. {
  817. RECORD_COMMAND( DX8_END_SCENE, 0 );
  818. if ( ASyncMode() )
  819. Push( PBCMD_END_SCENE );
  820. else
  821. DO_D3D( EndScene() );
  822. }
  823. FORCEINLINE HRESULT Lock( IDirect3DVertexBuffer9* vb, size_t offset, size_t size, void **ptr, DWORD flags )
  824. {
  825. Assert( size ); // lock size of 0 = unknown entire size of buffer = bad
  826. Synchronize();
  827. HRESULT hr = vb->Lock(offset, size, ptr, flags);
  828. switch (hr)
  829. {
  830. case D3DERR_INVALIDCALL:
  831. Warning( "D3DERR_INVALIDCALL - Vertex Buffer Lock Failed in %s on line %d(offset %d, size %d, flags 0x%x)\n", V_UnqualifiedFileName(__FILE__), __LINE__, offset, size, flags );
  832. break;
  833. case D3DERR_DRIVERINTERNALERROR:
  834. Warning( "D3DERR_DRIVERINTERNALERROR - Vertex Buffer Lock Failed in %s on line %d (offset %d, size %d, flags 0x%x)\n", V_UnqualifiedFileName(__FILE__), __LINE__, offset, size, flags );
  835. break;
  836. case D3DERR_OUTOFVIDEOMEMORY:
  837. Warning( "D3DERR_OUTOFVIDEOMEMORY - Vertex Buffer Lock Failed in %s on line %d (offset %d, size %d, flags 0x%x)\n", V_UnqualifiedFileName(__FILE__), __LINE__, offset, size, flags );
  838. break;
  839. }
  840. return hr;
  841. }
  842. FORCEINLINE HRESULT Lock( IDirect3DVertexBuffer9* vb, size_t offset, size_t size, void **ptr,
  843. DWORD flags,
  844. LockedBufferContext *lb)
  845. {
  846. HRESULT hr = D3D_OK;
  847. // asynchronous write-only dynamic vb lock
  848. if ( ASyncMode() )
  849. {
  850. AsynchronousLock( vb, offset, size, ptr, flags, lb );
  851. }
  852. else
  853. {
  854. hr = vb->Lock(offset, size, ptr, flags);
  855. switch (hr)
  856. {
  857. case D3DERR_INVALIDCALL:
  858. Warning( "D3DERR_INVALIDCALL - Vertex Buffer Lock Failed in %s on line %d(offset %d, size %d, flags 0x%x)\n", V_UnqualifiedFileName(__FILE__), __LINE__, offset, size, flags );
  859. break;
  860. case D3DERR_DRIVERINTERNALERROR:
  861. Warning( "D3DERR_DRIVERINTERNALERROR - Vertex Buffer Lock Failed in %s on line %d (offset %d, size %d, flags 0x%x)\n", V_UnqualifiedFileName(__FILE__), __LINE__, offset, size, flags );
  862. break;
  863. case D3DERR_OUTOFVIDEOMEMORY:
  864. Warning( "D3DERR_OUTOFVIDEOMEMORY - Vertex Buffer Lock Failed in %s on line %d (offset %d, size %d, flags 0x%x)\n", V_UnqualifiedFileName(__FILE__), __LINE__, offset, size, flags );
  865. break;
  866. }
  867. }
  868. return hr;
  869. }
  870. FORCEINLINE HRESULT Lock( IDirect3DIndexBuffer9* ib, size_t offset, size_t size, void **ptr, DWORD flags)
  871. {
  872. HRESULT hr = D3D_OK;
  873. Synchronize();
  874. hr = ib->Lock(offset, size, ptr, flags);
  875. switch (hr)
  876. {
  877. case D3DERR_INVALIDCALL:
  878. Warning( "D3DERR_INVALIDCALL - Index Buffer Lock Failed in %s on line %d(offset %d, size %d, flags 0x%x)\n", V_UnqualifiedFileName(__FILE__), __LINE__, offset, size, flags );
  879. break;
  880. case D3DERR_DRIVERINTERNALERROR:
  881. Warning( "D3DERR_DRIVERINTERNALERROR - Index Buffer Lock Failed in %s on line %d (offset %d, size %d, flags 0x%x)\n", V_UnqualifiedFileName(__FILE__), __LINE__, offset, size, flags );
  882. break;
  883. case D3DERR_OUTOFVIDEOMEMORY:
  884. Warning( "D3DERR_OUTOFVIDEOMEMORY - Index Buffer Lock Failed in %s on line %d (offset %d, size %d, flags 0x%x)\n", V_UnqualifiedFileName(__FILE__), __LINE__, offset, size, flags );
  885. break;
  886. }
  887. return hr;
  888. }
  889. // asycnhronous lock of index buffer
  890. FORCEINLINE HRESULT Lock( IDirect3DIndexBuffer9* ib, size_t offset, size_t size, void **ptr, DWORD flags,
  891. LockedBufferContext * lb)
  892. {
  893. HRESULT hr = D3D_OK;
  894. if ( ASyncMode() )
  895. AsynchronousLock( ib, offset, size, ptr, flags, lb );
  896. else
  897. {
  898. hr = ib->Lock(offset, size, ptr, flags);
  899. switch (hr)
  900. {
  901. case D3DERR_INVALIDCALL:
  902. Warning( "D3DERR_INVALIDCALL - Index Buffer Lock Failed in %s on line %d(offset %d, size %d, flags 0x%x)\n", V_UnqualifiedFileName(__FILE__), __LINE__, offset, size, flags );
  903. break;
  904. case D3DERR_DRIVERINTERNALERROR:
  905. Warning( "D3DERR_DRIVERINTERNALERROR - Index Buffer Lock Failed in %s on line %d (offset %d, size %d, flags 0x%x)\n", V_UnqualifiedFileName(__FILE__), __LINE__, offset, size, flags );
  906. break;
  907. case D3DERR_OUTOFVIDEOMEMORY:
  908. Warning( "D3DERR_OUTOFVIDEOMEMORY - Index Buffer Lock Failed in %s on line %d (offset %d, size %d, flags 0x%x)\n", V_UnqualifiedFileName(__FILE__), __LINE__, offset, size, flags );
  909. break;
  910. }
  911. }
  912. return hr;
  913. }
  914. #ifndef DX_TO_GL_ABSTRACTION
  915. FORCEINLINE HRESULT UpdateSurface( IDirect3DSurface9* pSourceSurface, CONST RECT* pSourceRect, IDirect3DSurface9* pDestSurface, CONST POINT* pDestPoint )
  916. {
  917. return m_pD3DDevice->UpdateSurface( pSourceSurface, pSourceRect, pDestSurface, pDestPoint );
  918. }
  919. #endif
  920. void Release( IDirect3DIndexBuffer9* ib )
  921. {
  922. Synchronize();
  923. ib->Release();
  924. }
  925. void Release( IDirect3DVertexBuffer9* vb )
  926. {
  927. Synchronize();
  928. vb->Release();
  929. }
  930. FORCEINLINE void Unlock( IDirect3DVertexBuffer9* vb )
  931. {
  932. // needed for d3d on pc only
  933. if ( ASyncMode() )
  934. Push(PBCMD_UNLOCK_VB, vb);
  935. else
  936. {
  937. HRESULT hr = vb->Unlock( );
  938. if ( FAILED(hr) )
  939. {
  940. Warning( "Vertex Buffer Unlock Failed in %s on line %d\n", V_UnqualifiedFileName(__FILE__), __LINE__ );
  941. }
  942. }
  943. }
  944. FORCEINLINE void Unlock( IDirect3DVertexBuffer9* vb, LockedBufferContext *lb, size_t unlock_size)
  945. {
  946. // needed for d3d on pc only
  947. #if SHADERAPI_USE_SMP
  948. if ( ASyncMode() )
  949. {
  950. AllocatePushBufferSpace( 1+N_DWORDS_IN_PTR+N_DWORDS( LockedBufferContext )+1 );
  951. *(m_pOutputPtr++)=PBCMD_ASYNC_UNLOCK_VB;
  952. *((IDirect3DVertexBuffer9* *) m_pOutputPtr)=vb;
  953. m_pOutputPtr+=N_DWORDS_IN_PTR;
  954. *((LockedBufferContext *) m_pOutputPtr)=*lb;
  955. m_pOutputPtr+=N_DWORDS( LockedBufferContext );
  956. *(m_pOutputPtr++)=unlock_size;
  957. }
  958. else
  959. #endif
  960. {
  961. HRESULT hr = vb->Unlock();
  962. if ( FAILED(hr) )
  963. {
  964. Warning( "Vertex Buffer Unlock Failed in %s on line %d\n", V_UnqualifiedFileName(__FILE__), __LINE__ );
  965. }
  966. }
  967. }
  968. FORCEINLINE void Unlock( IDirect3DIndexBuffer9* ib )
  969. {
  970. // needed for d3d on pc only
  971. if ( ASyncMode() )
  972. Push(PBCMD_UNLOCK_IB, ib);
  973. else
  974. {
  975. HRESULT hr = ib->Unlock();
  976. if ( FAILED(hr) )
  977. {
  978. Warning( "Index Buffer Unlock Failed in %s on line %d\n", V_UnqualifiedFileName(__FILE__), __LINE__ );
  979. }
  980. }
  981. }
  982. FORCEINLINE void Unlock( IDirect3DIndexBuffer9* ib, LockedBufferContext *lb, size_t unlock_size)
  983. {
  984. // needed for d3d on pc only
  985. #if SHADERAPI_USE_SMP
  986. if ( ASyncMode() )
  987. {
  988. AllocatePushBufferSpace( 1+N_DWORDS_IN_PTR+N_DWORDS( LockedBufferContext )+1 );
  989. *(m_pOutputPtr++)=PBCMD_ASYNC_UNLOCK_IB;
  990. *((IDirect3DIndexBuffer9* *) m_pOutputPtr)=ib;
  991. m_pOutputPtr+=N_DWORDS_IN_PTR;
  992. *((LockedBufferContext *) m_pOutputPtr)=*lb;
  993. m_pOutputPtr+=N_DWORDS( LockedBufferContext );
  994. *(m_pOutputPtr++)=unlock_size;
  995. }
  996. else
  997. #endif
  998. {
  999. HRESULT hr = ib->Unlock( );
  1000. if ( FAILED(hr) )
  1001. {
  1002. Warning( "Index Buffer Unlock Failed in %s on line %d\n", V_UnqualifiedFileName(__FILE__), __LINE__ );
  1003. }
  1004. }
  1005. }
  1006. void ShowCursor( bool onoff)
  1007. {
  1008. Synchronize();
  1009. DO_D3D( ShowCursor(onoff) );
  1010. }
  1011. FORCEINLINE void Clear( int count, D3DRECT const *pRects, int Flags, D3DCOLOR color, float Z, int stencil)
  1012. {
  1013. #if SHADERAPI_USE_SMP
  1014. if ( ASyncMode() )
  1015. {
  1016. int n_rects_words = count * N_DWORDS( D3DRECT );
  1017. AllocatePushBufferSpace( 2 + n_rects_words + 4 );
  1018. *(m_pOutputPtr++) = PBCMD_CLEAR;
  1019. *(m_pOutputPtr++) = count;
  1020. if ( count )
  1021. {
  1022. memcpy( m_pOutputPtr, pRects, count * sizeof( D3DRECT ) );
  1023. m_pOutputPtr += n_rects_words;
  1024. }
  1025. *(m_pOutputPtr++) = Flags;
  1026. *( (D3DCOLOR *) m_pOutputPtr ) = color;
  1027. m_pOutputPtr++;
  1028. *( (float *) m_pOutputPtr ) = Z;
  1029. m_pOutputPtr++;
  1030. *(m_pOutputPtr++) = stencil;
  1031. }
  1032. else
  1033. #endif
  1034. DO_D3D( Clear(count, pRects, Flags, color, Z, stencil) );
  1035. }
  1036. HRESULT Reset( D3DPRESENT_PARAMETERS *parms)
  1037. {
  1038. RECORD_COMMAND( DX8_RESET, 1 );
  1039. RECORD_STRUCT( parms, sizeof(*parms) );
  1040. Synchronize();
  1041. return m_pD3DDevice->Reset( parms );
  1042. }
  1043. void Release( void )
  1044. {
  1045. Synchronize();
  1046. DO_D3D( Release() );
  1047. }
  1048. FORCEINLINE void SetTexture(int stage, IDirect3DBaseTexture9 *txtr)
  1049. {
  1050. RECORD_COMMAND( DX8_SET_TEXTURE, 3 );
  1051. RECORD_INT( stage );
  1052. RECORD_INT( -1 );
  1053. RECORD_INT( -1 );
  1054. if (ASyncMode())
  1055. {
  1056. Push( PBCMD_SET_TEXTURE, stage, txtr );
  1057. }
  1058. else
  1059. DO_D3D( SetTexture( stage, txtr) );
  1060. }
  1061. void SetTransform( D3DTRANSFORMSTATETYPE mtrx_id, D3DXMATRIX const *mt)
  1062. {
  1063. RECORD_COMMAND( DX8_SET_TRANSFORM, 2 );
  1064. RECORD_INT( mtrx_id );
  1065. RECORD_STRUCT( mt, sizeof(D3DXMATRIX) );
  1066. Synchronize();
  1067. DO_D3D( SetTransform( mtrx_id, mt) );
  1068. }
  1069. FORCEINLINE void SetSamplerState( int stage, D3DSAMPLERSTATETYPE state, DWORD val)
  1070. {
  1071. RECORD_SAMPLER_STATE( stage, state, val );
  1072. if ( ASyncMode() )
  1073. Push( PBCMD_SET_SAMPLER_STATE, stage, state, val );
  1074. else
  1075. DO_D3D( SetSamplerState( stage, state, val) );
  1076. }
  1077. void SetFVF( int fvf)
  1078. {
  1079. Synchronize();
  1080. DO_D3D( SetFVF( fvf) );
  1081. }
  1082. FORCEINLINE void SetTextureStageState( int stage, D3DTEXTURESTAGESTATETYPE state, DWORD val )
  1083. {
  1084. RECORD_TEXTURE_STAGE_STATE( stage, state, val );
  1085. Synchronize();
  1086. DO_D3D( SetTextureStageState( stage, state, val) );
  1087. }
  1088. FORCEINLINE void DrawPrimitive(
  1089. D3DPRIMITIVETYPE PrimitiveType,
  1090. UINT StartVertex,
  1091. UINT PrimitiveCount
  1092. )
  1093. {
  1094. RECORD_COMMAND( DX8_DRAW_PRIMITIVE, 3 );
  1095. RECORD_INT( PrimitiveType );
  1096. RECORD_INT( StartVertex );
  1097. RECORD_INT( PrimitiveCount );
  1098. if ( ASyncMode() )
  1099. {
  1100. Push( PBCMD_DRAWPRIM, PrimitiveType, StartVertex, PrimitiveCount );
  1101. SubmitIfNotBusy();
  1102. }
  1103. else
  1104. DO_D3D( DrawPrimitive( PrimitiveType, StartVertex, PrimitiveCount ) );
  1105. }
  1106. HRESULT CreateVertexDeclaration(
  1107. CONST D3DVERTEXELEMENT9* pVertexElements,
  1108. IDirect3DVertexDeclaration9** ppDecl
  1109. )
  1110. {
  1111. Synchronize();
  1112. return m_pD3DDevice->CreateVertexDeclaration( pVertexElements, ppDecl );
  1113. }
  1114. HRESULT ValidateDevice( DWORD * pNumPasses )
  1115. {
  1116. Synchronize();
  1117. return m_pD3DDevice->ValidateDevice( pNumPasses );
  1118. }
  1119. HRESULT CreateVertexShader(
  1120. CONST DWORD * pFunction,
  1121. IDirect3DVertexShader9** ppShader,
  1122. const char *pShaderName,
  1123. char *debugLabel = NULL
  1124. )
  1125. {
  1126. Synchronize();
  1127. #ifdef DX_TO_GL_ABSTRACTION
  1128. return m_pD3DDevice->CreateVertexShader( pFunction, ppShader, pShaderName, debugLabel );
  1129. #else
  1130. return m_pD3DDevice->CreateVertexShader( pFunction, ppShader );
  1131. #endif
  1132. }
  1133. HRESULT CreatePixelShader(
  1134. CONST DWORD * pFunction,
  1135. IDirect3DPixelShader9** ppShader,
  1136. const char *pShaderName,
  1137. char *debugLabel = NULL
  1138. )
  1139. {
  1140. Synchronize();
  1141. #ifdef DX_TO_GL_ABSTRACTION
  1142. return m_pD3DDevice->CreatePixelShader( pFunction, ppShader, pShaderName, debugLabel );
  1143. #else
  1144. return m_pD3DDevice->CreatePixelShader( pFunction, ppShader );
  1145. #endif
  1146. }
  1147. FORCEINLINE void SetIndices(
  1148. IDirect3DIndexBuffer9 * pIndexData
  1149. )
  1150. {
  1151. if ( ASyncMode() )
  1152. Push( PBCMD_SET_INDICES, pIndexData );
  1153. else
  1154. DO_D3D( SetIndices( pIndexData ) );
  1155. }
  1156. FORCEINLINE void SetStreamSource(
  1157. UINT StreamNumber,
  1158. IDirect3DVertexBuffer9 * pStreamData,
  1159. UINT OffsetInBytes,
  1160. UINT Stride
  1161. )
  1162. {
  1163. if ( ASyncMode() )
  1164. Push( PBCMD_SET_STREAM_SOURCE, StreamNumber, pStreamData, OffsetInBytes, Stride );
  1165. else
  1166. DO_D3D( SetStreamSource( StreamNumber, pStreamData, OffsetInBytes, Stride ) );
  1167. }
  1168. HRESULT CreateVertexBuffer(
  1169. UINT Length,
  1170. DWORD Usage,
  1171. DWORD FVF,
  1172. D3DPOOL Pool,
  1173. IDirect3DVertexBuffer9** ppVertexBuffer,
  1174. HANDLE* pSharedHandle
  1175. )
  1176. {
  1177. Synchronize();
  1178. return m_pD3DDevice->CreateVertexBuffer( Length, Usage, FVF,
  1179. Pool, ppVertexBuffer, pSharedHandle );
  1180. }
  1181. HRESULT CreateIndexBuffer(
  1182. UINT Length,
  1183. DWORD Usage,
  1184. D3DFORMAT Format,
  1185. D3DPOOL Pool,
  1186. IDirect3DIndexBuffer9** ppIndexBuffer,
  1187. HANDLE* pSharedHandle
  1188. )
  1189. {
  1190. Synchronize();
  1191. return m_pD3DDevice->CreateIndexBuffer( Length, Usage, Format, Pool, ppIndexBuffer,
  1192. pSharedHandle );
  1193. }
  1194. FORCEINLINE void DrawIndexedPrimitive(
  1195. D3DPRIMITIVETYPE Type,
  1196. INT BaseVertexIndex,
  1197. UINT MinIndex,
  1198. UINT NumVertices,
  1199. UINT StartIndex,
  1200. UINT PrimitiveCount )
  1201. {
  1202. RECORD_COMMAND( DX8_DRAW_INDEXED_PRIMITIVE, 6 );
  1203. RECORD_INT( Type );
  1204. RECORD_INT( BaseVertexIndex );
  1205. RECORD_INT( MinIndex );
  1206. RECORD_INT( NumVertices );
  1207. RECORD_INT( StartIndex );
  1208. RECORD_INT( PrimitiveCount );
  1209. if ( ASyncMode() )
  1210. {
  1211. Push(PBCMD_DRAWINDEXEDPRIM,
  1212. Type, BaseVertexIndex, MinIndex, NumVertices, StartIndex, PrimitiveCount );
  1213. // SubmitIfNotBusy();
  1214. }
  1215. else
  1216. {
  1217. DO_D3D( DrawIndexedPrimitive( Type, BaseVertexIndex, MinIndex, NumVertices, StartIndex, PrimitiveCount ) );
  1218. }
  1219. }
  1220. #ifndef DX_TO_GL_ABSTRACTION
  1221. FORCEINLINE void DrawTessellatedIndexedPrimitive( INT BaseVertexIndex, UINT MinIndex, UINT NumVertices,
  1222. UINT StartIndex, UINT PrimitiveCount )
  1223. {
  1224. // Setup our stream-source frequencies
  1225. DO_D3D( SetStreamSourceFreq( 0, D3DSTREAMSOURCE_INDEXEDDATA | PrimitiveCount ) );
  1226. DO_D3D( SetStreamSourceFreq( VertexStreamSpec_t::STREAM_MORPH, D3DSTREAMSOURCE_INSTANCEDATA | 1ul ) );
  1227. DO_D3D( SetStreamSourceFreq( VertexStreamSpec_t::STREAM_SUBDQUADS, D3DSTREAMSOURCE_INSTANCEDATA | 1ul ) );
  1228. int nIndicesPerPatch = ( ( ( m_nCurrentTessLevel + 1 ) * 2 + 2 ) * m_nCurrentTessLevel ) - 2;
  1229. int nVerticesPerPatch = m_nCurrentTessLevel + 1;
  1230. nVerticesPerPatch *= nVerticesPerPatch;
  1231. int nPrimitiveCount = nIndicesPerPatch - 2;
  1232. DO_D3D( DrawIndexedPrimitive( D3DPT_TRIANGLESTRIP, 0, 0, nVerticesPerPatch, 0, nPrimitiveCount ) );
  1233. // Disable instancing
  1234. DO_D3D( SetStreamSourceFreq( 0, 1ul ) );
  1235. DO_D3D( SetStreamSourceFreq( VertexStreamSpec_t::STREAM_MORPH, 1ul ) );
  1236. DO_D3D( SetStreamSourceFreq( VertexStreamSpec_t::STREAM_SUBDQUADS, 1ul ) );
  1237. }
  1238. FORCEINLINE void DrawTessellatedPrimitive( UINT StartVertex, UINT PrimitiveCount )
  1239. {
  1240. // Setup our stream-source frequencies
  1241. DO_D3D( SetStreamSourceFreq( 0, D3DSTREAMSOURCE_INDEXEDDATA | PrimitiveCount ) );
  1242. DO_D3D( SetStreamSourceFreq( VertexStreamSpec_t::STREAM_MORPH, D3DSTREAMSOURCE_INSTANCEDATA | 1ul ) );
  1243. DO_D3D( SetStreamSourceFreq( VertexStreamSpec_t::STREAM_SUBDQUADS, D3DSTREAMSOURCE_INSTANCEDATA | 1ul ) );
  1244. int nIndicesPerPatch = ( ( ( m_nCurrentTessLevel + 1 ) * 2 + 2 ) * m_nCurrentTessLevel ) - 2;
  1245. int nVerticesPerPatch = m_nCurrentTessLevel + 1;
  1246. nVerticesPerPatch *= nVerticesPerPatch;
  1247. int nPrimitiveCount = nIndicesPerPatch - 2;
  1248. DO_D3D( DrawIndexedPrimitive( D3DPT_TRIANGLESTRIP, 0, 0, nVerticesPerPatch, 0, nPrimitiveCount ) );
  1249. // Disable instancing
  1250. DO_D3D( SetStreamSourceFreq( 0, 1ul ) );
  1251. DO_D3D( SetStreamSourceFreq( VertexStreamSpec_t::STREAM_MORPH, 1ul ) );
  1252. DO_D3D( SetStreamSourceFreq( VertexStreamSpec_t::STREAM_SUBDQUADS, 1ul ) );
  1253. }
  1254. FORCEINLINE void SetTessellationLevel( float level )
  1255. {
  1256. // Track our current tessellation level
  1257. m_nCurrentTessLevel = (int)ceil( level );
  1258. }
  1259. #endif
  1260. void SetMaterial( D3DMATERIAL9 const *mat)
  1261. {
  1262. RECORD_COMMAND( DX8_SET_MATERIAL, 1 );
  1263. RECORD_STRUCT( &mat, sizeof(mat) );
  1264. Synchronize();
  1265. DO_D3D( SetMaterial( mat ) );
  1266. }
  1267. FORCEINLINE void SetPixelShader( IDirect3DPixelShader9 *pShader )
  1268. {
  1269. RECORD_COMMAND( DX8_SET_PIXEL_SHADER, 1 );
  1270. RECORD_INT( ( int ) pShader );
  1271. if ( ASyncMode() )
  1272. Push( PBCMD_SET_PIXEL_SHADER, pShader );
  1273. else
  1274. DO_D3D( SetPixelShader( pShader ) );
  1275. }
  1276. FORCEINLINE void SetVertexShader( IDirect3DVertexShader9 *pShader )
  1277. {
  1278. if ( ASyncMode() )
  1279. Push( PBCMD_SET_VERTEX_SHADER, pShader );
  1280. else
  1281. DO_D3D( SetVertexShader( pShader ) );
  1282. }
  1283. #ifdef DX_TO_GL_ABSTRACTION
  1284. FORCEINLINE HRESULT LinkShaderPair( IDirect3DVertexShader9* vs, IDirect3DPixelShader9* ps )
  1285. {
  1286. Assert ( !ASyncMode() );
  1287. return DO_D3D( LinkShaderPair( vs, ps ) );
  1288. }
  1289. HRESULT QueryShaderPair( int index, GLMShaderPairInfo *infoOut )
  1290. {
  1291. Assert ( !ASyncMode() );
  1292. return DO_D3D( QueryShaderPair( index, infoOut ) );
  1293. }
  1294. void SetMaxUsedVertexShaderConstantsHint( uint nMaxReg )
  1295. {
  1296. Assert( !ASyncMode() );
  1297. DO_D3D( SetMaxUsedVertexShaderConstantsHint( nMaxReg ) );
  1298. }
  1299. #endif
  1300. void EvictManagedResources( void )
  1301. {
  1302. if (m_pD3DDevice) // people call this before creating the device
  1303. {
  1304. Synchronize();
  1305. DO_D3D( EvictManagedResources() );
  1306. }
  1307. }
  1308. void SetLight( int i, D3DLIGHT9 const *l)
  1309. {
  1310. RECORD_COMMAND( DX8_SET_LIGHT, 2 );
  1311. RECORD_INT( i );
  1312. RECORD_STRUCT( l, sizeof(*l) );
  1313. Synchronize();
  1314. DO_D3D( SetLight(i, l) );
  1315. }
  1316. void DrawIndexedPrimitiveUP( D3DPRIMITIVETYPE PrimitiveType,
  1317. UINT MinVertexIndex,
  1318. UINT NumVertices,
  1319. UINT PrimitiveCount,
  1320. CONST void * pIndexData,
  1321. D3DFORMAT IndexDataFormat,
  1322. CONST void* pVertexStreamZeroData,
  1323. UINT VertexStreamZeroStride )
  1324. {
  1325. Synchronize();
  1326. DO_D3D( DrawIndexedPrimitiveUP( PrimitiveType, MinVertexIndex, NumVertices, PrimitiveCount,
  1327. pIndexData, IndexDataFormat, pVertexStreamZeroData,
  1328. VertexStreamZeroStride ) );
  1329. }
  1330. HRESULT Present(
  1331. CONST RECT * pSourceRect,
  1332. CONST RECT * pDestRect,
  1333. VD3DHWND hDestWindowOverride,
  1334. CONST RGNDATA * pDirtyRegion)
  1335. {
  1336. RECORD_COMMAND( DX8_PRESENT, 0 );
  1337. #if SHADERAPI_USE_SMP
  1338. if ( ASyncMode() )
  1339. {
  1340. // need to deal with ret code here
  1341. AllocatePushBufferSpace(1+1+
  1342. N_DWORDS( RECT )+1+N_DWORDS( RECT )+1+1+N_DWORDS( RGNDATA ));
  1343. *(m_pOutputPtr++)=PBCMD_PRESENT;
  1344. *(m_pOutputPtr++)=( pSourceRect != NULL );
  1345. if (pSourceRect)
  1346. memcpy(m_pOutputPtr, pSourceRect, sizeof( RECT ) );
  1347. m_pOutputPtr+=N_DWORDS( RECT );
  1348. *(m_pOutputPtr++)=( pDestRect != NULL );
  1349. if (pDestRect)
  1350. memcpy(m_pOutputPtr, pDestRect, sizeof( RECT ) );
  1351. m_pOutputPtr+=N_DWORDS( RECT );
  1352. *(m_pOutputPtr++)=(uint32) hDestWindowOverride;
  1353. *(m_pOutputPtr++)=( pDirtyRegion != NULL );
  1354. if (pDirtyRegion)
  1355. memcpy(m_pOutputPtr, pDirtyRegion, sizeof( RGNDATA ));
  1356. m_pOutputPtr+=N_DWORDS( RGNDATA );
  1357. return S_OK; // not good - caller wants to here about lost devices
  1358. }
  1359. else
  1360. #endif
  1361. return m_pD3DDevice->Present( pSourceRect, pDestRect,
  1362. hDestWindowOverride, pDirtyRegion );
  1363. }
  1364. #if defined( DX_TO_GL_ABSTRACTION )
  1365. void AcquireThreadOwnership( )
  1366. {
  1367. m_pD3DDevice->AcquireThreadOwnership();
  1368. }
  1369. void ReleaseThreadOwnership( )
  1370. {
  1371. m_pD3DDevice->ReleaseThreadOwnership();
  1372. }
  1373. #endif
  1374. };
  1375. #endif // D3DASYNC_H
  1376. #endif // #if D3D_ASYNC_SUPPORTED