diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /materialsystem/shaderapidx9/d3d_async.h | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'materialsystem/shaderapidx9/d3d_async.h')
| -rw-r--r-- | materialsystem/shaderapidx9/d3d_async.h | 1567 |
1 files changed, 1567 insertions, 0 deletions
diff --git a/materialsystem/shaderapidx9/d3d_async.h b/materialsystem/shaderapidx9/d3d_async.h new file mode 100644 index 0000000..7deb2f3 --- /dev/null +++ b/materialsystem/shaderapidx9/d3d_async.h @@ -0,0 +1,1567 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//===========================================================================// + +#ifdef D3D_ASYNC_SUPPORTED + +#ifndef D3DASYNC_H +#define D3DASYNC_H + +#ifdef _WIN32 +#pragma once +#endif + +// Set this to 1 to allow d3d calls to be buffered and played back on another thread +// 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?) +#define SHADERAPI_USE_SMP 0 + +// Set this to 1 to allow buffering of the whole frame to memory and then playback (singlethreaded). +// This is for debugging only and is used to test the performance of just calling D3D and rendering without other CPU overhead. +#define SHADERAPI_BUFFER_D3DCALLS 0 + +#if SHADERAPI_BUFFER_D3DCALLS && !SHADERAPI_USE_SMP +# error "SHADERAPI_USE_SMP must be 1 for SHADERAPI_BUFFER_D3DCALLS to work!" +#endif + +#include "recording.h" +#include "strtools.h" +#include "glmgr/dxabstract.h" + +#ifdef NDEBUG +#define DO_D3D(x) Dx9Device()->x +#else +#define DO_D3D(x) Dx9Device()->x +//#define DO_D3D(x) { HRESULT hr=Dx9Device()->x; Assert( !FAILED(hr) ); } +#endif + +#define PUSHBUFFER_NELEMS 4096 + +enum PushBufferState +{ + PUSHBUFFER_AVAILABLE, + PUSHBUFFER_BEING_FILLED, + PUSHBUFFER_SUBMITTED, + PUSHBUFFER_BEING_USED_FOR_LOCKEDDATA, +}; + +class PushBuffer +{ + friend class D3DDeviceWrapper; + + volatile PushBufferState m_State; + uint32 m_BufferData[PUSHBUFFER_NELEMS]; +public: + PushBuffer(void) + { + m_State = PUSHBUFFER_AVAILABLE; + } +}; + +// When running multithreaded, lock for write calls actually return a pointer to temporary memory +// buffer. When the buffer is later unlocked by the caller, data must be queued with the Unlock() +// that lets the d3d thread know how much data to copy from where. One possible optimization for +// things which write a lot of data into lock buffers woudl be to proviude a way for the caller to +// occasionally check if the Lock() has been dequeued. If so, the the data pushed so far could be +// copied asynchronously into the buffer, while the caller would be told to switch to writing +// directly to the vertex buffer. +// +// another possibility would be lock()ing in advance for large ones, such as the world renderer, +// or keeping multiple locked vb's open for meshbuilder. + +struct LockedBufferContext +{ + PushBuffer *m_pPushBuffer; // if a push buffer was used to hold + // the temporary data, this will be non-null + void *m_pMallocedMemory; // if memory had to be malloc'd, this will be set. + + size_t m_MallocSize; // # of bytes malloced if mallocedmem ptr non-null + + LockedBufferContext( void ) + { + m_pPushBuffer = NULL; + m_pMallocedMemory = NULL; + } + +}; + + + +// push buffer commands follow +enum PushBufferCommand +{ + PBCMD_END, // at end of push buffer + PBCMD_SET_RENDERSTATE, // state, val + PBCMD_SET_TEXTURE, // stage, txtr + PBCMD_DRAWPRIM, // prim type, start v, nprims + PBCMD_DRAWINDEXEDPRIM, // prim type, baseidx, minidx, numv, starti, pcount + PBCMD_SET_PIXEL_SHADER, // shaderptr + PBCMD_SET_VERTEX_SHADER, // shaderptr + PBCMD_SET_PIXEL_SHADER_CONSTANT, // startreg, nregs, data... + PBCMD_SET_BOOLEAN_PIXEL_SHADER_CONSTANT, // startreg, nregs, data... + PBCMD_SET_INTEGER_PIXEL_SHADER_CONSTANT, // startreg, nregs, data... + PBCMD_SET_VERTEX_SHADER_CONSTANT, // startreg, nregs, data... + PBCMD_SET_BOOLEAN_VERTEX_SHADER_CONSTANT, // startreg, nregs, data... + PBCMD_SET_INTEGER_VERTEX_SHADER_CONSTANT, // startreg, nregs, data... + PBCMD_SET_RENDER_TARGET, // idx, targetptr + PBCMD_SET_DEPTH_STENCIL_SURFACE, // surfptr + PBCMD_SET_STREAM_SOURCE, // idx, sptr, ofs, stride + PBCMD_SET_INDICES, // idxbuffer + PBCMD_SET_SAMPLER_STATE, // stage, state, val + PBCMD_UNLOCK_VB, // vptr + PBCMD_UNLOCK_IB, // idxbufptr + PBCMD_SETVIEWPORT, // vp_struct + PBCMD_CLEAR, // count, n rect structs, flags, color, z, stencil + PBCMD_SET_VERTEXDECLARATION, // vdeclptr + PBCMD_BEGIN_SCENE, // + PBCMD_END_SCENE, // + PBCMD_PRESENT, // complicated..see code + PBCMD_SETCLIPPLANE, // idx, 4 floats + PBCMD_STRETCHRECT, // see code + PBCMD_ASYNC_LOCK_VB, // see code + PBCMD_ASYNC_UNLOCK_VB, + PBCMD_ASYNC_LOCK_IB, // see code + PBCMD_ASYNC_UNLOCK_IB, + PBCMD_SET_SCISSOR_RECT, // RECT +}; + + + +#define N_DWORDS( x ) (( sizeof(x)+3)/sizeof( DWORD )) +#define N_DWORDS_IN_PTR (N_DWORDS( void * )) + +class D3DDeviceWrapper +{ +private: + IDirect3DDevice9 *m_pD3DDevice; + bool m_bSupportsTessellation; + int m_nCurrentTessLevel; + TessellationMode_t m_nTessellationMode; + +#if SHADERAPI_USE_SMP + uintptr_t m_pASyncThreadHandle; + PushBuffer *m_pCurPushBuffer; + uint32 *m_pOutputPtr; + size_t m_PushBufferFreeSlots; +#endif + +#if SHADERAPI_BUFFER_D3DCALLS + bool m_bBufferingD3DCalls; +# define SHADERAPI_BUFFER_MAXRENDERTARGETS 4 + IDirect3DSurface9 *m_StoredRenderTargets[SHADERAPI_BUFFER_MAXRENDERTARGETS]; +#endif + + PushBuffer *FindFreePushBuffer( PushBufferState newstate ); // find a free push buffer and change its state + + void GetPushBuffer(void); // set us up to point at a new push buffer + void SubmitPushBufferAndGetANewOne(void); // submit the current push buffer + void ExecutePushBuffer( PushBuffer const *pb); + +#if SHADERAPI_USE_SMP + void Synchronize(void); // wait for all commands to be done +#else + FORCEINLINE void Synchronize(void) + { + } +#endif + + + void SubmitIfNotBusy(void); + +#if SHADERAPI_USE_SMP + template<class T> FORCEINLINE void PushStruct( PushBufferCommand cmd, T const *str ) + { + int nwords=N_DWORDS( T ); + AllocatePushBufferSpace( 1+ nwords ); + m_pOutputPtr[0]=cmd; + memcpy( m_pOutputPtr+1, str, sizeof( T ) ); + m_pOutputPtr += 1+nwords; + } + + FORCEINLINE void AllocatePushBufferSpace(size_t nSlots) + { + // check for N slots of space, and decrement amount of space left + if ( nSlots>m_PushBufferFreeSlots ) // out of room? + { + SubmitPushBufferAndGetANewOne(); + } + m_PushBufferFreeSlots -= nSlots; + } + + // simple methods for pushing a few words into output buffer + FORCEINLINE void Push( PushBufferCommand cmd ) + { + AllocatePushBufferSpace(1); + m_pOutputPtr[0]=cmd; + m_pOutputPtr++; + } + + FORCEINLINE void Push( PushBufferCommand cmd, int arg1) + { + AllocatePushBufferSpace(2); + m_pOutputPtr[0]=cmd; + m_pOutputPtr[1]=arg1; + m_pOutputPtr += 2; + } + + FORCEINLINE void Push( PushBufferCommand cmd, void *ptr ) + { + AllocatePushBufferSpace(1+N_DWORDS_IN_PTR); + *(m_pOutputPtr++)=cmd; + *((void **) m_pOutputPtr)=ptr; + m_pOutputPtr+=N_DWORDS_IN_PTR; + } + + FORCEINLINE void Push( PushBufferCommand cmd, void *ptr, void *ptr1 ) + { + AllocatePushBufferSpace(1+2*N_DWORDS_IN_PTR); + *(m_pOutputPtr++)=cmd; + *((void **) m_pOutputPtr)=ptr; + m_pOutputPtr+=N_DWORDS_IN_PTR; + *((void **) m_pOutputPtr)=ptr1; + m_pOutputPtr+=N_DWORDS_IN_PTR; + } + + FORCEINLINE void Push( PushBufferCommand cmd, void *arg1, uint32 arg2, uint32 arg3, uint32 arg4, + void *arg5) + { + AllocatePushBufferSpace(1+N_DWORDS_IN_PTR+1+1+1+N_DWORDS_IN_PTR); + *(m_pOutputPtr++)=cmd; + *((void **) m_pOutputPtr)=arg1; + m_pOutputPtr+=N_DWORDS_IN_PTR; + *(m_pOutputPtr++)=arg2; + *(m_pOutputPtr++)=arg3; + *(m_pOutputPtr++)=arg4; + *((void **) m_pOutputPtr)=arg5; + m_pOutputPtr+=N_DWORDS_IN_PTR; + + } + + FORCEINLINE void Push( PushBufferCommand cmd, uint32 arg1, void *ptr ) + { + AllocatePushBufferSpace(2+N_DWORDS_IN_PTR); + *(m_pOutputPtr++)=cmd; + *(m_pOutputPtr++)=arg1; + *((void **) m_pOutputPtr)=ptr; + m_pOutputPtr+=N_DWORDS_IN_PTR; + } + + FORCEINLINE void Push( PushBufferCommand cmd, uint32 arg1, void *ptr, int arg2, int arg3 ) + { + AllocatePushBufferSpace( 4+N_DWORDS_IN_PTR ); + *(m_pOutputPtr++)=cmd; + *(m_pOutputPtr++)=arg1; + *((void **) m_pOutputPtr)=ptr; + m_pOutputPtr+=N_DWORDS_IN_PTR; + m_pOutputPtr[0]=arg2; + m_pOutputPtr[1]=arg3; + m_pOutputPtr += 2; + } + + FORCEINLINE void Push( PushBufferCommand cmd, int arg1, int arg2) + { + AllocatePushBufferSpace(3); + m_pOutputPtr[0]=cmd; + m_pOutputPtr[1]=arg1; + m_pOutputPtr[2]=arg2; + m_pOutputPtr += 3; + } + + FORCEINLINE void Push( PushBufferCommand cmd, int arg1, int arg2, int arg3) + { + AllocatePushBufferSpace(4); + m_pOutputPtr[0]=cmd; + m_pOutputPtr[1]=arg1; + m_pOutputPtr[2]=arg2; + m_pOutputPtr[3]=arg3; + m_pOutputPtr += 4; + } + + FORCEINLINE void Push( PushBufferCommand cmd, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6 ) + { + AllocatePushBufferSpace(7); + m_pOutputPtr[0]=cmd; + m_pOutputPtr[1]=arg1; + m_pOutputPtr[2]=arg2; + m_pOutputPtr[3]=arg3; + m_pOutputPtr[4]=arg4; + m_pOutputPtr[5]=arg5; + m_pOutputPtr[6]=arg6; + m_pOutputPtr += 7; + } + +#else + template<class T> FORCEINLINE void PushStruct( PushBufferCommand cmd, T const *str ) + { + } + + FORCEINLINE void AllocatePushBufferSpace(size_t nSlots) + { + } + + // simple methods for pushing a few words into output buffer + FORCEINLINE void Push( PushBufferCommand cmd ) + { + } + + FORCEINLINE void Push( PushBufferCommand cmd, int arg1) + { + } + + FORCEINLINE void Push( PushBufferCommand cmd, void *ptr ) + { + } + + FORCEINLINE void Push( PushBufferCommand cmd, void *ptr, void *ptr1 ) + { + } + + FORCEINLINE void Push( PushBufferCommand cmd, void *arg1, uint32 arg2, uint32 arg3, uint32 arg4, + void *arg5) + { + } + + FORCEINLINE void Push( PushBufferCommand cmd, uint32 arg1, void *ptr ) + { + } + + FORCEINLINE void Push( PushBufferCommand cmd, uint32 arg1, void *ptr, int arg2, int arg3 ) + { + } + + FORCEINLINE void Push( PushBufferCommand cmd, int arg1, int arg2) + { + } + + FORCEINLINE void Push( PushBufferCommand cmd, int arg1, int arg2, int arg3) + { + } + + FORCEINLINE void Push( PushBufferCommand cmd, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6 ) + { + } + +#endif + + FORCEINLINE bool ASyncMode(void) const + { +#if SHADERAPI_USE_SMP +# if SHADERAPI_BUFFER_D3DCALLS + return m_bBufferingD3DCalls; +# else + return (m_pASyncThreadHandle != 0 ); +# endif +#else + return false; +#endif + } + + FORCEINLINE IDirect3DDevice9* Dx9Device(void) const + { + return m_pD3DDevice; + } + + void AsynchronousLock( IDirect3DVertexBuffer9* vb, size_t offset, size_t size, void **ptr, + DWORD flags, + LockedBufferContext *lb); + + void AsynchronousLock( IDirect3DIndexBuffer9* ib, size_t offset, size_t size, void **ptr, + DWORD flags, + LockedBufferContext *lb); + + // handlers for push buffer contexts + void HandleAsynchronousLockVBCommand( uint32 const *dptr ); + void HandleAsynchronousUnLockVBCommand( uint32 const *dptr ); + void HandleAsynchronousLockIBCommand( uint32 const *dptr ); + void HandleAsynchronousUnLockIBCommand( uint32 const *dptr ); + +public: + +#if SHADERAPI_BUFFER_D3DCALLS + void ExecuteAllWork( void ); +#endif + void RunThread( void ); // this is what the worker thread runs + + void SetASyncMode( bool onoff ); + + + bool IsActive( void )const + { + return m_pD3DDevice != NULL; + } + + void D3DeviceWrapper(void) + { + m_pD3DDevice = 0; +#if SHADERAPI_USE_SMP + m_pASyncThreadHandle = 0; +#endif +#if SHADERAPI_BUFFER_D3DCALLS + m_bBufferingD3DCalls = false; +#endif + } + + void SetDevicePtr(IDirect3DDevice9 *pD3DDev ) + { + m_pD3DDevice = pD3DDev; + } + + void SetSupportsTessellation( bool bSupportsTessellation ) + { + m_bSupportsTessellation = bSupportsTessellation; + } + + void ShutDownDevice(void) + { + if ( ASyncMode() ) + { + // sync w/ thread + } + m_pD3DDevice = 0; + } + + void FORCEINLINE SetDepthStencilSurface( IDirect3DSurface9 *new_stencil ) + { + if ( ASyncMode() ) + Push( PBCMD_SET_DEPTH_STENCIL_SURFACE, new_stencil ); + else + DO_D3D( SetDepthStencilSurface( new_stencil ) ); + } + + HRESULT CreateCubeTexture( + UINT EdgeLength, + UINT Levels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DCubeTexture9 ** ppCubeTexture, + HANDLE* pSharedHandle, + char *debugLabel = NULL // <-- OK to not pass this arg, only passed through on DX_TO_GL_ABSTRACTION + ) + { + Synchronize(); + return m_pD3DDevice->CreateCubeTexture( EdgeLength, Levels, Usage, Format, Pool, + ppCubeTexture, pSharedHandle + #if defined( DX_TO_GL_ABSTRACTION ) + ,debugLabel + #endif + ); + } + + HRESULT CreateVolumeTexture( + UINT Width, + UINT Height, + UINT Depth, + UINT Levels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DVolumeTexture9** ppVolumeTexture, + HANDLE* pSharedHandle, + char *debugLabel = NULL // <-- OK to not pass this arg, only passed through on DX_TO_GL_ABSTRACTION + ) + { + Synchronize(); + return m_pD3DDevice->CreateVolumeTexture( Width, Height, Depth, Levels, + Usage, Format, Pool, ppVolumeTexture, + pSharedHandle + #if defined( DX_TO_GL_ABSTRACTION ) + ,debugLabel + #endif + ); + } + + HRESULT CreateOffscreenPlainSurface( UINT Width, + UINT Height, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DSurface9** ppSurface, + HANDLE* pSharedHandle) + { + Synchronize(); + return m_pD3DDevice->CreateOffscreenPlainSurface( Width, Height, Format, Pool, + ppSurface, pSharedHandle); + } + + HRESULT CreateTexture( + UINT Width, + UINT Height, + UINT Levels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DTexture9** ppTexture, + HANDLE* pSharedHandle, + char *debugLabel = NULL // <-- OK to not pass this arg, only passed through on DX_TO_GL_ABSTRACTION + ) + { + Synchronize(); + return m_pD3DDevice->CreateTexture( Width, Height, Levels, Usage, + Format, Pool, ppTexture, pSharedHandle + #if defined( DX_TO_GL_ABSTRACTION ) + ,debugLabel + #endif + ); + } + + HRESULT GetRenderTargetData( + IDirect3DSurface9* pRenderTarget, + IDirect3DSurface9* pDestSurface + ) + { + Synchronize(); + return m_pD3DDevice->GetRenderTargetData( pRenderTarget, pDestSurface ); + } + + + void GetDeviceCaps( D3DCAPS9 * pCaps ) + { + Synchronize(); + m_pD3DDevice->GetDeviceCaps( pCaps ); + } + + LPCSTR GetPixelShaderProfile( void ) + { + Synchronize(); + return D3DXGetPixelShaderProfile( m_pD3DDevice ); + } + + HRESULT TestCooperativeLevel( void ) + { + // hack! We are going to assume that calling this immediately when in buffered mode isn't going to cause problems. +#if !SHADERAPI_BUFFER_D3DCALLS + Synchronize(); +#endif + return m_pD3DDevice->TestCooperativeLevel(); + } + + HRESULT GetFrontBufferData( UINT iSwapChain, IDirect3DSurface9 * pDestSurface ) + { + Synchronize(); + return m_pD3DDevice->GetFrontBufferData( iSwapChain, pDestSurface ); + } + + void SetGammaRamp( int swapchain, int flags, D3DGAMMARAMP const *pRamp) + { + Synchronize(); + m_pD3DDevice->SetGammaRamp( swapchain, flags, pRamp); + } + + HRESULT GetTexture( DWORD Stage, IDirect3DBaseTexture9 ** ppTexture ) + { + Synchronize(); + return m_pD3DDevice->GetTexture( Stage, ppTexture ); + } + + HRESULT GetFVF( DWORD * pFVF ) + { + Synchronize(); + return m_pD3DDevice->GetFVF( pFVF ); + } + + HRESULT GetDepthStencilSurface( + IDirect3DSurface9 ** ppZStencilSurface + ) + { + Synchronize(); + return m_pD3DDevice->GetDepthStencilSurface( ppZStencilSurface ); + } + + FORCEINLINE void SetClipPlane( int idx, float const * pplane) + { + RECORD_COMMAND( DX8_SET_CLIP_PLANE, 5 ); + RECORD_INT( idx ); + RECORD_FLOAT( pplane[0] ); + RECORD_FLOAT( pplane[1] ); + RECORD_FLOAT( pplane[2] ); + RECORD_FLOAT( pplane[3] ); +#if SHADERAPI_USE_SMP + if ( ASyncMode() ) + { + AllocatePushBufferSpace( 6 ); + m_pOutputPtr[0]=PBCMD_SETCLIPPLANE; + m_pOutputPtr[1]=idx; + memcpy(m_pOutputPtr+2,pplane, 4*sizeof(float) ); + m_pOutputPtr += 6; + } + else +#endif + DO_D3D( SetClipPlane( idx, pplane ) ); + } + + FORCEINLINE void SetVertexDeclaration( IDirect3DVertexDeclaration9 *decl ) + { + RECORD_COMMAND( DX8_SET_VERTEX_DECLARATION, 1 ); + RECORD_INT( ( int ) decl ); + +#if SHADERAPI_USE_SMP + if ( ASyncMode() ) + { + Push( PBCMD_SET_VERTEXDECLARATION, decl ); + } + else +#endif + DO_D3D( SetVertexDeclaration( decl ) ); + } + + FORCEINLINE void SetViewport( D3DVIEWPORT9 const *vp ) + { + RECORD_COMMAND( DX8_SET_VIEWPORT, 1 ); + RECORD_STRUCT( vp, sizeof( *vp )); + +#if SHADERAPI_USE_SMP + if ( ASyncMode() ) + PushStruct( PBCMD_SETVIEWPORT, vp ); + else +#endif + DO_D3D( SetViewport( vp ) ); + } + + HRESULT GetRenderTarget( + DWORD RenderTargetIndex, + IDirect3DSurface9 ** ppRenderTarget) + { +#if SHADERAPI_BUFFER_D3DCALLS + if ( ASyncMode() ) + { + Assert( RenderTargetIndex >= 0 && RenderTargetIndex < SHADERAPI_BUFFER_MAXRENDERTARGETS ); + *ppRenderTarget = m_StoredRenderTargets[RenderTargetIndex]; + return D3D_OK; + } +#endif + Synchronize(); + return m_pD3DDevice->GetRenderTarget( RenderTargetIndex, ppRenderTarget ); + } + + HRESULT CreateQuery( D3DQUERYTYPE Type, IDirect3DQuery9** ppQuery ) + { + Synchronize(); + return m_pD3DDevice->CreateQuery( Type, ppQuery ); + } + + HRESULT CreateRenderTarget( + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, + BOOL Lockable, + IDirect3DSurface9** ppSurface, + HANDLE* pSharedHandle + ) + { + Synchronize(); + return m_pD3DDevice->CreateRenderTarget( Width, Height, Format, MultiSample, + MultisampleQuality, Lockable, ppSurface, + pSharedHandle); + } + + HRESULT CreateDepthStencilSurface( + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, + BOOL Discard, + IDirect3DSurface9** ppSurface, + HANDLE* pSharedHandle + ) + { + Synchronize(); + return m_pD3DDevice->CreateDepthStencilSurface( Width, Height, Format, MultiSample, + MultisampleQuality, Discard, ppSurface, + pSharedHandle ); + } + + + FORCEINLINE void SetRenderTarget( int idx, IDirect3DSurface9 *new_rt ) + { + if (ASyncMode()) + { + Push( PBCMD_SET_RENDER_TARGET, idx, new_rt ); +#if SHADERAPI_BUFFER_D3DCALLS + m_StoredRenderTargets[idx] = new_rt; +#endif + } + else + { + // NOTE: If the debug runtime breaks here on the shadow depth render target that is normal. dx9 doesn't directly support shadow + // depth texturing so we are forced to initialize this texture without the render target flagr + DO_D3D( SetRenderTarget( idx, new_rt) ); + } + } + + FORCEINLINE void LightEnable( int lidx, bool onoff ) + { + RECORD_COMMAND( DX8_LIGHT_ENABLE, 2 ); + RECORD_INT( lidx ); + RECORD_INT( onoff ); + + Synchronize(); + DO_D3D( LightEnable( lidx, onoff ) ); + } + + FORCEINLINE void SetRenderState( D3DRENDERSTATETYPE state, DWORD val ) + { +// Assert( state >= 0 && state < MAX_NUM_RENDERSTATES ); + RECORD_RENDER_STATE( state, val ); + if (ASyncMode()) + { + Push( PBCMD_SET_RENDERSTATE, state, val ); + } + else + DO_D3D( SetRenderState( state, val ) ); + } + + FORCEINLINE void SetRenderStateInline( D3DRENDERSTATETYPE state, DWORD val ) + { + // Assert( state >= 0 && state < MAX_NUM_RENDERSTATES ); + RECORD_RENDER_STATE( state, val ); + if (ASyncMode()) + { + SetRenderState( state, val ); + } + else + { +#ifdef DX_TO_GL_ABSTRACTION + DO_D3D( SetRenderStateInline( state, val ) ); +#else + DO_D3D( SetRenderState( state, val ) ); +#endif + } + } + + FORCEINLINE void SetScissorRect( const RECT *pScissorRect ) + { + RECORD_COMMAND( DX8_SET_SCISSOR_RECT, 1 ); + RECORD_STRUCT( pScissorRect, 4 * sizeof(LONG) ); +#if SHADERAPI_USE_SMP + if ( ASyncMode() ) + { + AllocatePushBufferSpace( 5 ); + m_pOutputPtr[0] = PBCMD_SET_SCISSOR_RECT; + memcpy( m_pOutputPtr + 1, pScissorRect, sizeof( *pScissorRect ) ); + } + else +#endif + DO_D3D( SetScissorRect( pScissorRect ) ); + } + + FORCEINLINE void SetVertexShaderConstantF( UINT StartRegister, CONST float * pConstantData, + UINT Vector4fCount) + { + RECORD_COMMAND( DX8_SET_VERTEX_SHADER_CONSTANT, 3 ); + RECORD_INT( StartRegister ); + RECORD_INT( Vector4fCount ); + RECORD_STRUCT( pConstantData, Vector4fCount * 4 * sizeof(float) ); +#if SHADERAPI_USE_SMP + if ( ASyncMode() ) + { + AllocatePushBufferSpace(3+4*Vector4fCount); + m_pOutputPtr[0]=PBCMD_SET_VERTEX_SHADER_CONSTANT; + m_pOutputPtr[1]=StartRegister; + m_pOutputPtr[2]=Vector4fCount; + memcpy(m_pOutputPtr+3,pConstantData,sizeof(float)*4*Vector4fCount); + m_pOutputPtr+=3+4*Vector4fCount; + } + else +#endif + DO_D3D( SetVertexShaderConstantF( StartRegister, pConstantData, Vector4fCount ) ); + } + + FORCEINLINE void SetVertexShaderConstantB( UINT StartRegister, CONST int * pConstantData, + UINT BoolCount) + { + RECORD_COMMAND( DX8_SET_VERTEX_SHADER_CONSTANT, 3 ); + RECORD_INT( StartRegister ); + RECORD_INT( BoolCount ); + RECORD_STRUCT( pConstantData, BoolCount * sizeof(int) ); +#if SHADERAPI_USE_SMP + if ( ASyncMode() ) + { + AllocatePushBufferSpace(3+BoolCount); + m_pOutputPtr[0]=PBCMD_SET_BOOLEAN_VERTEX_SHADER_CONSTANT; + m_pOutputPtr[1]=StartRegister; + m_pOutputPtr[2]=BoolCount; + memcpy(m_pOutputPtr+3,pConstantData,sizeof(int)*BoolCount); + m_pOutputPtr+=3+BoolCount; + } + else +#endif + DO_D3D( SetVertexShaderConstantB( StartRegister, pConstantData, BoolCount ) ); + } + + FORCEINLINE void SetVertexShaderConstantI( UINT StartRegister, CONST int * pConstantData, + UINT Vector4IntCount) + { + RECORD_COMMAND( DX8_SET_VERTEX_SHADER_CONSTANT, 3 ); + RECORD_INT( StartRegister ); + RECORD_INT( Vector4IntCount ); + RECORD_STRUCT( pConstantData, Vector4IntCount * 4 * sizeof(int) ); +#if SHADERAPI_USE_SMP + if ( ASyncMode() ) + { + AllocatePushBufferSpace(3+4*Vector4IntCount); + m_pOutputPtr[0]=PBCMD_SET_INTEGER_VERTEX_SHADER_CONSTANT; + m_pOutputPtr[1]=StartRegister; + m_pOutputPtr[2]=Vector4IntCount; + memcpy(m_pOutputPtr+3,pConstantData,sizeof(int)*4*Vector4IntCount); + m_pOutputPtr+=3+4*Vector4IntCount; + } + else +#endif + DO_D3D( SetVertexShaderConstantI( StartRegister, pConstantData, Vector4IntCount ) ); + } + + FORCEINLINE void SetPixelShaderConstantF( UINT StartRegister, CONST float * pConstantData, + UINT Vector4fCount) + { + RECORD_COMMAND( DX8_SET_PIXEL_SHADER_CONSTANT, 3 ); + RECORD_INT( StartRegister ); + RECORD_INT( Vector4fCount ); + RECORD_STRUCT( pConstantData, Vector4fCount * 4 * sizeof(float) ); +#if SHADERAPI_USE_SMP + if ( ASyncMode() ) + { + AllocatePushBufferSpace(3+4*Vector4fCount); + m_pOutputPtr[0]=PBCMD_SET_PIXEL_SHADER_CONSTANT; + m_pOutputPtr[1]=StartRegister; + m_pOutputPtr[2]=Vector4fCount; + memcpy(m_pOutputPtr+3,pConstantData,sizeof(float)*4*Vector4fCount); + m_pOutputPtr+=3+4*Vector4fCount; + } + else +#endif + DO_D3D( SetPixelShaderConstantF( StartRegister, pConstantData, Vector4fCount ) ); + } + + FORCEINLINE void SetPixelShaderConstantB( UINT StartRegister, CONST int * pConstantData, + UINT BoolCount) + { + RECORD_COMMAND( DX8_SET_PIXEL_SHADER_CONSTANT, 3 ); + RECORD_INT( StartRegister ); + RECORD_INT( BoolCount ); + RECORD_STRUCT( pConstantData, BoolCount * sizeof(int) ); +#if SHADERAPI_USE_SMP + if ( ASyncMode() ) + { + AllocatePushBufferSpace(3+BoolCount); + m_pOutputPtr[0]=PBCMD_SET_BOOLEAN_PIXEL_SHADER_CONSTANT; + m_pOutputPtr[1]=StartRegister; + m_pOutputPtr[2]=BoolCount; + memcpy(m_pOutputPtr+3,pConstantData,sizeof(int)*BoolCount); + m_pOutputPtr+=3+BoolCount; + } + else +#endif + DO_D3D( SetPixelShaderConstantB( StartRegister, pConstantData, BoolCount ) ); + } + + FORCEINLINE void SetPixelShaderConstantI( UINT StartRegister, CONST int * pConstantData, + UINT Vector4IntCount) + { + RECORD_COMMAND( DX8_SET_PIXEL_SHADER_CONSTANT, 3 ); + RECORD_INT( StartRegister ); + RECORD_INT( Vector4IntCount ); + RECORD_STRUCT( pConstantData, Vector4IntCount * 4 * sizeof(int) ); +#if SHADERAPI_USE_SMP + if ( ASyncMode() ) + { + AllocatePushBufferSpace(3+4*Vector4IntCount); + m_pOutputPtr[0]=PBCMD_SET_INTEGER_PIXEL_SHADER_CONSTANT; + m_pOutputPtr[1]=StartRegister; + m_pOutputPtr[2]=Vector4IntCount; + memcpy(m_pOutputPtr+3,pConstantData,sizeof(int)*4*Vector4IntCount); + m_pOutputPtr+=3+4*Vector4IntCount; + } + else +#endif + DO_D3D( SetPixelShaderConstantI( StartRegister, pConstantData, Vector4IntCount ) ); + } + + HRESULT StretchRect( IDirect3DSurface9 * pSourceSurface, + CONST RECT * pSourceRect, + IDirect3DSurface9 * pDestSurface, + CONST RECT * pDestRect, + D3DTEXTUREFILTERTYPE Filter ) + { +#if SHADERAPI_USE_SMP + if ( ASyncMode() ) + { + AllocatePushBufferSpace(1+1+1+N_DWORDS( RECT )+1+1+N_DWORDS( RECT ) + 1); + *(m_pOutputPtr++)=PBCMD_STRETCHRECT; + *(m_pOutputPtr++)=(int) pSourceSurface; + *(m_pOutputPtr++)=(pSourceRect != NULL); + if (pSourceRect) + { + memcpy(m_pOutputPtr,pSourceRect,sizeof(RECT)); + } + m_pOutputPtr+=N_DWORDS(RECT); + *(m_pOutputPtr++)=(int) pDestSurface; + *(m_pOutputPtr++)=(pDestRect != NULL); + if (pDestRect) + memcpy(m_pOutputPtr,pDestRect,sizeof(RECT)); + m_pOutputPtr+=N_DWORDS(RECT); + *(m_pOutputPtr++)=Filter; + return S_OK; // !bug! + } + else +#endif + return m_pD3DDevice-> + StretchRect( pSourceSurface, pSourceRect, pDestSurface, pDestRect, Filter ); + } + + + FORCEINLINE void BeginScene(void) + { + RECORD_COMMAND( DX8_BEGIN_SCENE, 0 ); + if ( ASyncMode() ) + Push( PBCMD_BEGIN_SCENE ); + else + DO_D3D( BeginScene() ); + } + + FORCEINLINE void EndScene(void) + { + RECORD_COMMAND( DX8_END_SCENE, 0 ); + if ( ASyncMode() ) + Push( PBCMD_END_SCENE ); + else + DO_D3D( EndScene() ); + } + + FORCEINLINE HRESULT Lock( IDirect3DVertexBuffer9* vb, size_t offset, size_t size, void **ptr, DWORD flags ) + { + Assert( size ); // lock size of 0 = unknown entire size of buffer = bad + Synchronize(); + + HRESULT hr = vb->Lock(offset, size, ptr, flags); + switch (hr) + { + case D3DERR_INVALIDCALL: + 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 ); + break; + case D3DERR_DRIVERINTERNALERROR: + 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 ); + break; + case D3DERR_OUTOFVIDEOMEMORY: + 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 ); + break; + } + + return hr; + } + + + FORCEINLINE HRESULT Lock( IDirect3DVertexBuffer9* vb, size_t offset, size_t size, void **ptr, + DWORD flags, + LockedBufferContext *lb) + { + + HRESULT hr = D3D_OK; + + // asynchronous write-only dynamic vb lock + if ( ASyncMode() ) + { + AsynchronousLock( vb, offset, size, ptr, flags, lb ); + } + else + { + hr = vb->Lock(offset, size, ptr, flags); + switch (hr) + { + case D3DERR_INVALIDCALL: + 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 ); + break; + case D3DERR_DRIVERINTERNALERROR: + 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 ); + break; + case D3DERR_OUTOFVIDEOMEMORY: + 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 ); + break; + } + } + + return hr; + } + + FORCEINLINE HRESULT Lock( IDirect3DIndexBuffer9* ib, size_t offset, size_t size, void **ptr, DWORD flags) + { + HRESULT hr = D3D_OK; + + Synchronize(); + + hr = ib->Lock(offset, size, ptr, flags); + switch (hr) + { + case D3DERR_INVALIDCALL: + 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 ); + break; + case D3DERR_DRIVERINTERNALERROR: + 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 ); + break; + case D3DERR_OUTOFVIDEOMEMORY: + 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 ); + break; + } + + return hr; + } + + // asycnhronous lock of index buffer + FORCEINLINE HRESULT Lock( IDirect3DIndexBuffer9* ib, size_t offset, size_t size, void **ptr, DWORD flags, + LockedBufferContext * lb) + { + HRESULT hr = D3D_OK; + + if ( ASyncMode() ) + AsynchronousLock( ib, offset, size, ptr, flags, lb ); + else + { + hr = ib->Lock(offset, size, ptr, flags); + switch (hr) + { + case D3DERR_INVALIDCALL: + 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 ); + break; + case D3DERR_DRIVERINTERNALERROR: + 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 ); + break; + case D3DERR_OUTOFVIDEOMEMORY: + 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 ); + break; + } + } + + return hr; + } + +#ifndef DX_TO_GL_ABSTRACTION + FORCEINLINE HRESULT UpdateSurface( IDirect3DSurface9* pSourceSurface, CONST RECT* pSourceRect, IDirect3DSurface9* pDestSurface, CONST POINT* pDestPoint ) + { + return m_pD3DDevice->UpdateSurface( pSourceSurface, pSourceRect, pDestSurface, pDestPoint ); + } +#endif + + void Release( IDirect3DIndexBuffer9* ib ) + { + Synchronize(); + ib->Release(); + } + + void Release( IDirect3DVertexBuffer9* vb ) + { + Synchronize(); + vb->Release(); + } + + FORCEINLINE void Unlock( IDirect3DVertexBuffer9* vb ) + { + // needed for d3d on pc only + if ( ASyncMode() ) + Push(PBCMD_UNLOCK_VB, vb); + else + { + HRESULT hr = vb->Unlock( ); + + if ( FAILED(hr) ) + { + Warning( "Vertex Buffer Unlock Failed in %s on line %d\n", V_UnqualifiedFileName(__FILE__), __LINE__ ); + } + } + } + + FORCEINLINE void Unlock( IDirect3DVertexBuffer9* vb, LockedBufferContext *lb, size_t unlock_size) + { + // needed for d3d on pc only +#if SHADERAPI_USE_SMP + if ( ASyncMode() ) + { + AllocatePushBufferSpace( 1+N_DWORDS_IN_PTR+N_DWORDS( LockedBufferContext )+1 ); + *(m_pOutputPtr++)=PBCMD_ASYNC_UNLOCK_VB; + *((IDirect3DVertexBuffer9* *) m_pOutputPtr)=vb; + m_pOutputPtr+=N_DWORDS_IN_PTR; + *((LockedBufferContext *) m_pOutputPtr)=*lb; + m_pOutputPtr+=N_DWORDS( LockedBufferContext ); + *(m_pOutputPtr++)=unlock_size; + } + else +#endif + { + HRESULT hr = vb->Unlock(); + + if ( FAILED(hr) ) + { + Warning( "Vertex Buffer Unlock Failed in %s on line %d\n", V_UnqualifiedFileName(__FILE__), __LINE__ ); + } + } + } + + FORCEINLINE void Unlock( IDirect3DIndexBuffer9* ib ) + { + // needed for d3d on pc only + if ( ASyncMode() ) + Push(PBCMD_UNLOCK_IB, ib); + else + { + HRESULT hr = ib->Unlock(); + + if ( FAILED(hr) ) + { + Warning( "Index Buffer Unlock Failed in %s on line %d\n", V_UnqualifiedFileName(__FILE__), __LINE__ ); + } + } + } + + FORCEINLINE void Unlock( IDirect3DIndexBuffer9* ib, LockedBufferContext *lb, size_t unlock_size) + { + // needed for d3d on pc only +#if SHADERAPI_USE_SMP + if ( ASyncMode() ) + { + AllocatePushBufferSpace( 1+N_DWORDS_IN_PTR+N_DWORDS( LockedBufferContext )+1 ); + *(m_pOutputPtr++)=PBCMD_ASYNC_UNLOCK_IB; + *((IDirect3DIndexBuffer9* *) m_pOutputPtr)=ib; + m_pOutputPtr+=N_DWORDS_IN_PTR; + *((LockedBufferContext *) m_pOutputPtr)=*lb; + m_pOutputPtr+=N_DWORDS( LockedBufferContext ); + *(m_pOutputPtr++)=unlock_size; + } + else +#endif + { + HRESULT hr = ib->Unlock( ); + + if ( FAILED(hr) ) + { + Warning( "Index Buffer Unlock Failed in %s on line %d\n", V_UnqualifiedFileName(__FILE__), __LINE__ ); + } + } + } + + void ShowCursor( bool onoff) + { + Synchronize(); + DO_D3D( ShowCursor(onoff) ); + } + + FORCEINLINE void Clear( int count, D3DRECT const *pRects, int Flags, D3DCOLOR color, float Z, int stencil) + { +#if SHADERAPI_USE_SMP + if ( ASyncMode() ) + { + int n_rects_words = count * N_DWORDS( D3DRECT ); + AllocatePushBufferSpace( 2 + n_rects_words + 4 ); + *(m_pOutputPtr++) = PBCMD_CLEAR; + *(m_pOutputPtr++) = count; + if ( count ) + { + memcpy( m_pOutputPtr, pRects, count * sizeof( D3DRECT ) ); + m_pOutputPtr += n_rects_words; + } + *(m_pOutputPtr++) = Flags; + *( (D3DCOLOR *) m_pOutputPtr ) = color; + m_pOutputPtr++; + *( (float *) m_pOutputPtr ) = Z; + m_pOutputPtr++; + *(m_pOutputPtr++) = stencil; + } + else +#endif + DO_D3D( Clear(count, pRects, Flags, color, Z, stencil) ); + } + + HRESULT Reset( D3DPRESENT_PARAMETERS *parms) + { + RECORD_COMMAND( DX8_RESET, 1 ); + RECORD_STRUCT( parms, sizeof(*parms) ); + Synchronize(); + return m_pD3DDevice->Reset( parms ); + } + + void Release( void ) + { + Synchronize(); + DO_D3D( Release() ); + } + + FORCEINLINE void SetTexture(int stage, IDirect3DBaseTexture9 *txtr) + { + RECORD_COMMAND( DX8_SET_TEXTURE, 3 ); + RECORD_INT( stage ); + RECORD_INT( -1 ); + RECORD_INT( -1 ); + if (ASyncMode()) + { + Push( PBCMD_SET_TEXTURE, stage, txtr ); + } + else + DO_D3D( SetTexture( stage, txtr) ); + } + void SetTransform( D3DTRANSFORMSTATETYPE mtrx_id, D3DXMATRIX const *mt) + { + RECORD_COMMAND( DX8_SET_TRANSFORM, 2 ); + RECORD_INT( mtrx_id ); + RECORD_STRUCT( mt, sizeof(D3DXMATRIX) ); + Synchronize(); + DO_D3D( SetTransform( mtrx_id, mt) ); + } + + FORCEINLINE void SetSamplerState( int stage, D3DSAMPLERSTATETYPE state, DWORD val) + { + RECORD_SAMPLER_STATE( stage, state, val ); + if ( ASyncMode() ) + Push( PBCMD_SET_SAMPLER_STATE, stage, state, val ); + else + DO_D3D( SetSamplerState( stage, state, val) ); + } + + void SetFVF( int fvf) + { + Synchronize(); + DO_D3D( SetFVF( fvf) ); + } + + FORCEINLINE void SetTextureStageState( int stage, D3DTEXTURESTAGESTATETYPE state, DWORD val ) + { + RECORD_TEXTURE_STAGE_STATE( stage, state, val ); + Synchronize(); + DO_D3D( SetTextureStageState( stage, state, val) ); + } + + FORCEINLINE void DrawPrimitive( + D3DPRIMITIVETYPE PrimitiveType, + UINT StartVertex, + UINT PrimitiveCount + ) + { + RECORD_COMMAND( DX8_DRAW_PRIMITIVE, 3 ); + RECORD_INT( PrimitiveType ); + RECORD_INT( StartVertex ); + RECORD_INT( PrimitiveCount ); + if ( ASyncMode() ) + { + Push( PBCMD_DRAWPRIM, PrimitiveType, StartVertex, PrimitiveCount ); + SubmitIfNotBusy(); + } + else + DO_D3D( DrawPrimitive( PrimitiveType, StartVertex, PrimitiveCount ) ); + + } + + HRESULT CreateVertexDeclaration( + CONST D3DVERTEXELEMENT9* pVertexElements, + IDirect3DVertexDeclaration9** ppDecl + ) + { + Synchronize(); + return m_pD3DDevice->CreateVertexDeclaration( pVertexElements, ppDecl ); + } + + + HRESULT ValidateDevice( DWORD * pNumPasses ) + { + Synchronize(); + return m_pD3DDevice->ValidateDevice( pNumPasses ); + } + + + + HRESULT CreateVertexShader( + CONST DWORD * pFunction, + IDirect3DVertexShader9** ppShader, + const char *pShaderName, + char *debugLabel = NULL + ) + { + Synchronize(); + #ifdef DX_TO_GL_ABSTRACTION + return m_pD3DDevice->CreateVertexShader( pFunction, ppShader, pShaderName, debugLabel ); + #else + return m_pD3DDevice->CreateVertexShader( pFunction, ppShader ); + #endif + } + + HRESULT CreatePixelShader( + CONST DWORD * pFunction, + IDirect3DPixelShader9** ppShader, + const char *pShaderName, + char *debugLabel = NULL + ) + { + Synchronize(); + #ifdef DX_TO_GL_ABSTRACTION + return m_pD3DDevice->CreatePixelShader( pFunction, ppShader, pShaderName, debugLabel ); + #else + return m_pD3DDevice->CreatePixelShader( pFunction, ppShader ); + #endif + } + + + FORCEINLINE void SetIndices( + IDirect3DIndexBuffer9 * pIndexData + ) + { + if ( ASyncMode() ) + Push( PBCMD_SET_INDICES, pIndexData ); + else + DO_D3D( SetIndices( pIndexData ) ); + } + + FORCEINLINE void SetStreamSource( + UINT StreamNumber, + IDirect3DVertexBuffer9 * pStreamData, + UINT OffsetInBytes, + UINT Stride + ) + { + if ( ASyncMode() ) + Push( PBCMD_SET_STREAM_SOURCE, StreamNumber, pStreamData, OffsetInBytes, Stride ); + else + DO_D3D( SetStreamSource( StreamNumber, pStreamData, OffsetInBytes, Stride ) ); + } + + + HRESULT CreateVertexBuffer( + UINT Length, + DWORD Usage, + DWORD FVF, + D3DPOOL Pool, + IDirect3DVertexBuffer9** ppVertexBuffer, + HANDLE* pSharedHandle + ) + { + Synchronize(); + return m_pD3DDevice->CreateVertexBuffer( Length, Usage, FVF, + Pool, ppVertexBuffer, pSharedHandle ); + } + + HRESULT CreateIndexBuffer( + UINT Length, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DIndexBuffer9** ppIndexBuffer, + HANDLE* pSharedHandle + ) + { + Synchronize(); + return m_pD3DDevice->CreateIndexBuffer( Length, Usage, Format, Pool, ppIndexBuffer, + pSharedHandle ); + } + + + FORCEINLINE void DrawIndexedPrimitive( + D3DPRIMITIVETYPE Type, + INT BaseVertexIndex, + UINT MinIndex, + UINT NumVertices, + UINT StartIndex, + UINT PrimitiveCount ) + { + RECORD_COMMAND( DX8_DRAW_INDEXED_PRIMITIVE, 6 ); + RECORD_INT( Type ); + RECORD_INT( BaseVertexIndex ); + RECORD_INT( MinIndex ); + RECORD_INT( NumVertices ); + RECORD_INT( StartIndex ); + RECORD_INT( PrimitiveCount ); + if ( ASyncMode() ) + { + Push(PBCMD_DRAWINDEXEDPRIM, + Type, BaseVertexIndex, MinIndex, NumVertices, StartIndex, PrimitiveCount ); +// SubmitIfNotBusy(); + } + else + { + DO_D3D( DrawIndexedPrimitive( Type, BaseVertexIndex, MinIndex, NumVertices, StartIndex, PrimitiveCount ) ); + } + } + +#ifndef DX_TO_GL_ABSTRACTION + FORCEINLINE void DrawTessellatedIndexedPrimitive( INT BaseVertexIndex, UINT MinIndex, UINT NumVertices, + UINT StartIndex, UINT PrimitiveCount ) + { + // Setup our stream-source frequencies + DO_D3D( SetStreamSourceFreq( 0, D3DSTREAMSOURCE_INDEXEDDATA | PrimitiveCount ) ); + DO_D3D( SetStreamSourceFreq( VertexStreamSpec_t::STREAM_MORPH, D3DSTREAMSOURCE_INSTANCEDATA | 1ul ) ); + DO_D3D( SetStreamSourceFreq( VertexStreamSpec_t::STREAM_SUBDQUADS, D3DSTREAMSOURCE_INSTANCEDATA | 1ul ) ); + + int nIndicesPerPatch = ( ( ( m_nCurrentTessLevel + 1 ) * 2 + 2 ) * m_nCurrentTessLevel ) - 2; + int nVerticesPerPatch = m_nCurrentTessLevel + 1; + nVerticesPerPatch *= nVerticesPerPatch; + int nPrimitiveCount = nIndicesPerPatch - 2; + DO_D3D( DrawIndexedPrimitive( D3DPT_TRIANGLESTRIP, 0, 0, nVerticesPerPatch, 0, nPrimitiveCount ) ); + + // Disable instancing + DO_D3D( SetStreamSourceFreq( 0, 1ul ) ); + DO_D3D( SetStreamSourceFreq( VertexStreamSpec_t::STREAM_MORPH, 1ul ) ); + DO_D3D( SetStreamSourceFreq( VertexStreamSpec_t::STREAM_SUBDQUADS, 1ul ) ); + } + + FORCEINLINE void DrawTessellatedPrimitive( UINT StartVertex, UINT PrimitiveCount ) + { + + // Setup our stream-source frequencies + DO_D3D( SetStreamSourceFreq( 0, D3DSTREAMSOURCE_INDEXEDDATA | PrimitiveCount ) ); + DO_D3D( SetStreamSourceFreq( VertexStreamSpec_t::STREAM_MORPH, D3DSTREAMSOURCE_INSTANCEDATA | 1ul ) ); + DO_D3D( SetStreamSourceFreq( VertexStreamSpec_t::STREAM_SUBDQUADS, D3DSTREAMSOURCE_INSTANCEDATA | 1ul ) ); + + int nIndicesPerPatch = ( ( ( m_nCurrentTessLevel + 1 ) * 2 + 2 ) * m_nCurrentTessLevel ) - 2; + int nVerticesPerPatch = m_nCurrentTessLevel + 1; + nVerticesPerPatch *= nVerticesPerPatch; + int nPrimitiveCount = nIndicesPerPatch - 2; + DO_D3D( DrawIndexedPrimitive( D3DPT_TRIANGLESTRIP, 0, 0, nVerticesPerPatch, 0, nPrimitiveCount ) ); + + // Disable instancing + DO_D3D( SetStreamSourceFreq( 0, 1ul ) ); + DO_D3D( SetStreamSourceFreq( VertexStreamSpec_t::STREAM_MORPH, 1ul ) ); + DO_D3D( SetStreamSourceFreq( VertexStreamSpec_t::STREAM_SUBDQUADS, 1ul ) ); + } + + FORCEINLINE void SetTessellationLevel( float level ) + { + // Track our current tessellation level + m_nCurrentTessLevel = (int)ceil( level ); + } +#endif + + void SetMaterial( D3DMATERIAL9 const *mat) + { + RECORD_COMMAND( DX8_SET_MATERIAL, 1 ); + RECORD_STRUCT( &mat, sizeof(mat) ); + Synchronize(); + DO_D3D( SetMaterial( mat ) ); + } + + FORCEINLINE void SetPixelShader( IDirect3DPixelShader9 *pShader ) + { + RECORD_COMMAND( DX8_SET_PIXEL_SHADER, 1 ); + RECORD_INT( ( int ) pShader ); + if ( ASyncMode() ) + Push( PBCMD_SET_PIXEL_SHADER, pShader ); + else + DO_D3D( SetPixelShader( pShader ) ); + } + + FORCEINLINE void SetVertexShader( IDirect3DVertexShader9 *pShader ) + { + if ( ASyncMode() ) + Push( PBCMD_SET_VERTEX_SHADER, pShader ); + else + DO_D3D( SetVertexShader( pShader ) ); + } + +#ifdef DX_TO_GL_ABSTRACTION + FORCEINLINE HRESULT LinkShaderPair( IDirect3DVertexShader9* vs, IDirect3DPixelShader9* ps ) + { + Assert ( !ASyncMode() ); + return DO_D3D( LinkShaderPair( vs, ps ) ); + } + + HRESULT QueryShaderPair( int index, GLMShaderPairInfo *infoOut ) + { + Assert ( !ASyncMode() ); + return DO_D3D( QueryShaderPair( index, infoOut ) ); + } + + void SetMaxUsedVertexShaderConstantsHint( uint nMaxReg ) + { + Assert( !ASyncMode() ); + DO_D3D( SetMaxUsedVertexShaderConstantsHint( nMaxReg ) ); + } + +#endif + + void EvictManagedResources( void ) + { + if (m_pD3DDevice) // people call this before creating the device + { + Synchronize(); + DO_D3D( EvictManagedResources() ); + } + } + + void SetLight( int i, D3DLIGHT9 const *l) + { + RECORD_COMMAND( DX8_SET_LIGHT, 2 ); + RECORD_INT( i ); + RECORD_STRUCT( l, sizeof(*l) ); + + Synchronize(); + DO_D3D( SetLight(i, l) ); + } + + void DrawIndexedPrimitiveUP( D3DPRIMITIVETYPE PrimitiveType, + UINT MinVertexIndex, + UINT NumVertices, + UINT PrimitiveCount, + CONST void * pIndexData, + D3DFORMAT IndexDataFormat, + CONST void* pVertexStreamZeroData, + UINT VertexStreamZeroStride ) + { + Synchronize(); + DO_D3D( DrawIndexedPrimitiveUP( PrimitiveType, MinVertexIndex, NumVertices, PrimitiveCount, + pIndexData, IndexDataFormat, pVertexStreamZeroData, + VertexStreamZeroStride ) ); + } + + HRESULT Present( + CONST RECT * pSourceRect, + CONST RECT * pDestRect, + VD3DHWND hDestWindowOverride, + CONST RGNDATA * pDirtyRegion) + { + RECORD_COMMAND( DX8_PRESENT, 0 ); +#if SHADERAPI_USE_SMP + if ( ASyncMode() ) + { + // need to deal with ret code here + AllocatePushBufferSpace(1+1+ + N_DWORDS( RECT )+1+N_DWORDS( RECT )+1+1+N_DWORDS( RGNDATA )); + *(m_pOutputPtr++)=PBCMD_PRESENT; + *(m_pOutputPtr++)=( pSourceRect != NULL ); + if (pSourceRect) + memcpy(m_pOutputPtr, pSourceRect, sizeof( RECT ) ); + m_pOutputPtr+=N_DWORDS( RECT ); + *(m_pOutputPtr++)=( pDestRect != NULL ); + if (pDestRect) + memcpy(m_pOutputPtr, pDestRect, sizeof( RECT ) ); + m_pOutputPtr+=N_DWORDS( RECT ); + *(m_pOutputPtr++)=(uint32) hDestWindowOverride; + *(m_pOutputPtr++)=( pDirtyRegion != NULL ); + if (pDirtyRegion) + memcpy(m_pOutputPtr, pDirtyRegion, sizeof( RGNDATA )); + m_pOutputPtr+=N_DWORDS( RGNDATA ); + return S_OK; // not good - caller wants to here about lost devices + } + else +#endif + return m_pD3DDevice->Present( pSourceRect, pDestRect, + hDestWindowOverride, pDirtyRegion ); + } + + +#if defined( DX_TO_GL_ABSTRACTION ) + + void AcquireThreadOwnership( ) + { + m_pD3DDevice->AcquireThreadOwnership(); + } + + void ReleaseThreadOwnership( ) + { + m_pD3DDevice->ReleaseThreadOwnership(); + } + +#endif + +}; + +#endif // D3DASYNC_H + +#endif // #if D3D_ASYNC_SUPPORTED |