/* * Copyright 2011-2023 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE */ #ifndef BGFX_RENDERER_D3D9_H_HEADER_GUARD #define BGFX_RENDERER_D3D9_H_HEADER_GUARD #define BGFX_CONFIG_RENDERER_DIRECT3D9EX (BX_PLATFORM_LINUX || BX_PLATFORM_WINDOWS) #include <sal.h> #include <unknwn.h> #include <d3d9.h> #ifndef D3DSTREAMSOURCE_INDEXEDDATA # define D3DSTREAMSOURCE_INDEXEDDATA (1<<30) #endif// D3DSTREAMSOURCE_INDEXEDDATA #ifndef D3DSTREAMSOURCE_INSTANCEDATA # define D3DSTREAMSOURCE_INSTANCEDATA (2<<30) #endif // D3DSTREAMSOURCE_INSTANCEDATA #include "renderer.h" #include "renderer_d3d.h" #include "nvapi.h" #define BGFX_D3D9_PROFILER_BEGIN(_view, _abgr) \ BX_MACRO_BLOCK_BEGIN \ PIX_BEGINEVENT(_abgr, s_viewNameW[_view]); \ BGFX_PROFILER_BEGIN(s_viewName[view], _abgr); \ BX_MACRO_BLOCK_END #define BGFX_D3D9_PROFILER_BEGIN_LITERAL(_name, _abgr) \ BX_MACRO_BLOCK_BEGIN \ PIX_BEGINEVENT(_abgr, L"" _name); \ BGFX_PROFILER_BEGIN_LITERAL("" _name, _abgr); \ BX_MACRO_BLOCK_END #define BGFX_D3D9_PROFILER_END() \ BX_MACRO_BLOCK_BEGIN \ BGFX_PROFILER_END(); \ PIX_ENDEVENT(); \ BX_MACRO_BLOCK_END namespace bgfx { namespace d3d9 { # if defined(D3D_DISABLE_9EX) # define D3DFMT_S8_LOCKABLE D3DFORMAT( 85) # define D3DFMT_A1 D3DFORMAT(118) # endif // defined(D3D_DISABLE_9EX) # ifndef D3DFMT_ATI1 # define D3DFMT_ATI1 ( (D3DFORMAT)BX_MAKEFOURCC('A', 'T', 'I', '1') ) # endif // D3DFMT_ATI1 # ifndef D3DFMT_ATI2 # define D3DFMT_ATI2 ( (D3DFORMAT)BX_MAKEFOURCC('A', 'T', 'I', '2') ) # endif // D3DFMT_ATI2 # ifndef D3DFMT_ATOC # define D3DFMT_ATOC ( (D3DFORMAT)BX_MAKEFOURCC('A', 'T', 'O', 'C') ) # endif // D3DFMT_ATOC # ifndef D3DFMT_DF16 # define D3DFMT_DF16 ( (D3DFORMAT)BX_MAKEFOURCC('D', 'F', '1', '6') ) # endif // D3DFMT_DF16 # ifndef D3DFMT_DF24 # define D3DFMT_DF24 ( (D3DFORMAT)BX_MAKEFOURCC('D', 'F', '2', '4') ) # endif // D3DFMT_DF24 # ifndef D3DFMT_INST # define D3DFMT_INST ( (D3DFORMAT)BX_MAKEFOURCC('I', 'N', 'S', 'T') ) # endif // D3DFMT_INST # ifndef D3DFMT_INTZ # define D3DFMT_INTZ ( (D3DFORMAT)BX_MAKEFOURCC('I', 'N', 'T', 'Z') ) # endif // D3DFMT_INTZ # ifndef D3DFMT_NULL # define D3DFMT_NULL ( (D3DFORMAT)BX_MAKEFOURCC('N', 'U', 'L', 'L') ) # endif // D3DFMT_NULL # ifndef D3DFMT_RESZ # define D3DFMT_RESZ ( (D3DFORMAT)BX_MAKEFOURCC('R', 'E', 'S', 'Z') ) # endif // D3DFMT_RESZ # ifndef D3DFMT_RAWZ # define D3DFMT_RAWZ ( (D3DFORMAT)BX_MAKEFOURCC('R', 'A', 'W', 'Z') ) # endif // D3DFMT_RAWZ # ifndef D3DFMT_S8_LOCKABLE # define D3DFMT_S8_LOCKABLE ( (D3DFORMAT)85) # endif // D3DFMT_S8_LOCKABLE # ifndef D3DFMT_A1 # define D3DFMT_A1 ( (D3DFORMAT)118) # endif // D3DFMT_A1 struct ExtendedFormat { enum Enum { Ati1, Ati2, Df16, Df24, Inst, Intz, Null, Resz, Rawz, Atoc, Count, }; D3DFORMAT m_fmt; DWORD m_usage; D3DRESOURCETYPE m_type; bool m_supported; }; struct Msaa { D3DMULTISAMPLE_TYPE m_type; DWORD m_quality; }; struct IndexBufferD3D9 { IndexBufferD3D9() : m_ptr(NULL) , m_dynamic(NULL) , m_size(0) , m_flags(BGFX_BUFFER_NONE) { } void create(uint32_t _size, void* _data, uint16_t _flags); void update(uint32_t _offset, uint32_t _size, void* _data, bool _discard = false) { if (NULL != m_dynamic && _data != m_dynamic) { bx::memCopy(&m_dynamic[_offset], _data, _size); } void* buffer; DX_CHECK(m_ptr->Lock(_offset , _size , &buffer , _discard || (m_dynamic && 0 == _offset && m_size == _size) ? D3DLOCK_DISCARD : 0 ) ); bx::memCopy(buffer, _data, _size); DX_CHECK(m_ptr->Unlock() ); } void destroy() { if (NULL != m_ptr) { DX_RELEASE(m_ptr, 0); if (NULL != m_dynamic) { BX_FREE(g_allocator, m_dynamic); m_dynamic = NULL; } } } void preReset(); void postReset(); IDirect3DIndexBuffer9* m_ptr; uint8_t* m_dynamic; uint32_t m_size; uint16_t m_flags; }; struct VertexBufferD3D9 { VertexBufferD3D9() : m_ptr(NULL) , m_dynamic(NULL) , m_size(0) { } void create(uint32_t _size, void* _data, VertexLayoutHandle _layoutHandle); void update(uint32_t _offset, uint32_t _size, void* _data, bool _discard = false) { if (NULL != m_dynamic && _data != m_dynamic) { bx::memCopy(&m_dynamic[_offset], _data, _size); } void* buffer; DX_CHECK(m_ptr->Lock(_offset , _size , &buffer , _discard || (m_dynamic && 0 == _offset && m_size == _size) ? D3DLOCK_DISCARD : 0 ) ); bx::memCopy(buffer, _data, _size); DX_CHECK(m_ptr->Unlock() ); } void destroy() { if (NULL != m_ptr) { DX_RELEASE(m_ptr, 0); if (NULL != m_dynamic) { BX_FREE(g_allocator, m_dynamic); m_dynamic = NULL; } } } void preReset(); void postReset(); IDirect3DVertexBuffer9* m_ptr; uint8_t* m_dynamic; uint32_t m_size; VertexLayoutHandle m_layoutHandle; }; struct ShaderD3D9 { ShaderD3D9() : m_vertexShader(NULL) , m_constantBuffer(NULL) , m_numPredefined(0) , m_type(0) { } void create(const Memory* _mem); void destroy() { if (NULL != m_constantBuffer) { UniformBuffer::destroy(m_constantBuffer); m_constantBuffer = NULL; } m_numPredefined = 0; switch (m_type) { case 0: DX_RELEASE(m_vertexShader, 0); BX_FALLTHROUGH; default: DX_RELEASE(m_pixelShader, 0); } } union { // X360 doesn't have interface inheritance (can't use IUnknown*). IDirect3DVertexShader9* m_vertexShader; IDirect3DPixelShader9* m_pixelShader; }; UniformBuffer* m_constantBuffer; PredefinedUniform m_predefined[PredefinedUniform::Count]; uint8_t m_numPredefined; uint8_t m_type; }; struct ProgramD3D9 { void create(const ShaderD3D9* _vsh, const ShaderD3D9* _fsh) { m_vsh = _vsh; m_fsh = _fsh; bx::memCopy(&m_predefined[0], _vsh->m_predefined, _vsh->m_numPredefined*sizeof(PredefinedUniform) ); m_numPredefined = _vsh->m_numPredefined; if (NULL != _fsh) { bx::memCopy(&m_predefined[_vsh->m_numPredefined], _fsh->m_predefined, _fsh->m_numPredefined*sizeof(PredefinedUniform) ); m_numPredefined += _fsh->m_numPredefined; } } void destroy() { m_numPredefined = 0; m_vsh = NULL; m_fsh = NULL; } const ShaderD3D9* m_vsh; const ShaderD3D9* m_fsh; PredefinedUniform m_predefined[PredefinedUniform::Count*2]; uint8_t m_numPredefined; }; struct TextureD3D9 { enum Enum { Texture2D, Texture3D, TextureCube, }; TextureD3D9() : m_ptr(NULL) , m_surface(NULL) , m_staging(NULL) , m_textureFormat(TextureFormat::Unknown) { } void createTexture(uint32_t _width, uint32_t _height, uint8_t _numMips); void createVolumeTexture(uint32_t _width, uint32_t _height, uint32_t _depth, uint8_t _numMips); void createCubeTexture(uint32_t _width, uint8_t _numMips); uint8_t* lock(uint8_t _side, uint8_t _lod, uint32_t& _pitch, uint32_t& _slicePitch, const Rect* _rect = NULL); void unlock(uint8_t _side, uint8_t _lod); void dirty(uint8_t _side, const Rect& _rect, uint16_t _z, uint16_t _depth); IDirect3DSurface9* getSurface(uint8_t _side = 0, uint8_t _mip = 0) const; void create(const Memory* _mem, uint64_t _flags, uint8_t _skip); void destroy(bool _resize = false) { if (0 == (m_flags & BGFX_SAMPLER_INTERNAL_SHARED) ) { if (_resize) { // BK - at the time of resize there might be one reference held by frame buffer // surface. This frame buffer will be recreated later, and release reference // to existing surface. That's why here we don't care about ref count. m_ptr->Release(); } else { DX_RELEASE(m_ptr, 0); } } DX_RELEASE(m_surface, 0); DX_RELEASE(m_staging, 0); m_textureFormat = TextureFormat::Unknown; } void overrideInternal(uintptr_t _ptr) { destroy(); m_flags |= BGFX_SAMPLER_INTERNAL_SHARED; m_ptr = (IDirect3DBaseTexture9*)_ptr; } void updateBegin(uint8_t _side, uint8_t _mip); void update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem); void updateEnd(); void commit(uint8_t _stage, uint32_t _flags, const float _palette[][4]); void resolve(uint8_t _resolve) const; void preReset(); void postReset(); union { IDirect3DBaseTexture9* m_ptr; IDirect3DTexture9* m_texture2d; IDirect3DVolumeTexture9* m_texture3d; IDirect3DCubeTexture9* m_textureCube; }; IDirect3DSurface9* m_surface; union { IDirect3DBaseTexture9* m_staging; IDirect3DTexture9* m_staging2d; IDirect3DVolumeTexture9* m_staging3d; IDirect3DCubeTexture9* m_stagingCube; }; uint64_t m_flags; uint32_t m_width; uint32_t m_height; uint32_t m_depth; uint8_t m_numMips; uint8_t m_type; uint8_t m_requestedFormat; uint8_t m_textureFormat; }; struct FrameBufferD3D9 { FrameBufferD3D9() : m_hwnd(NULL) , m_denseIdx(UINT16_MAX) , m_num(0) , m_numTh(0) , m_dsIdx(UINT8_MAX) , m_needResolve(false) , m_needPresent(false) { } void create(uint8_t _num, const Attachment* _attachment); void create(uint16_t _denseIdx, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _format, TextureFormat::Enum _depthFormat); uint16_t destroy(); HRESULT present(); void resolve() const; void preReset(); void postReset(); void createNullColorRT(); void set(); IDirect3DSurface9* m_surface[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS-1]; IDirect3DSwapChain9* m_swapChain; HWND m_hwnd; uint32_t m_width; uint32_t m_height; Attachment m_attachment[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS]; uint16_t m_denseIdx; uint8_t m_num; uint8_t m_numTh; uint8_t m_dsIdx; bool m_needResolve; bool m_needPresent; }; struct TimerQueryD3D9 { TimerQueryD3D9() : m_control(BX_COUNTOF(m_query) ) { } void postReset(); void preReset(); uint32_t begin(uint32_t _resultIdx, uint32_t _frameNum); void end(uint32_t _idx); bool update(); struct Query { IDirect3DQuery9* m_disjoint; IDirect3DQuery9* m_begin; IDirect3DQuery9* m_end; IDirect3DQuery9* m_freq; uint32_t m_resultIdx; uint32_t m_frameNum; bool m_ready; }; struct Result { void reset() { m_begin = 0; m_end = 0; m_frequency = 1; m_pending = 0; m_frameNum = 0; } uint64_t m_begin; uint64_t m_end; uint64_t m_frequency; uint32_t m_pending; uint32_t m_frameNum; }; Result m_result[BGFX_CONFIG_MAX_VIEWS+1]; Query m_query[BGFX_CONFIG_MAX_VIEWS*4]; bx::RingBufferControl m_control; }; struct OcclusionQueryD3D9 { OcclusionQueryD3D9() : m_control(BX_COUNTOF(m_query) ) { } void postReset(); void preReset(); void begin(Frame* _render, OcclusionQueryHandle _handle); void end(); void resolve(Frame* _render, bool _wait = false); void invalidate(OcclusionQueryHandle _handle); struct Query { IDirect3DQuery9* m_ptr; OcclusionQueryHandle m_handle; }; Query m_query[BGFX_CONFIG_MAX_OCCLUSION_QUERIES]; bx::RingBufferControl m_control; }; } /* namespace d3d9 */ } // namespace bgfx #endif // BGFX_RENDERER_D3D9_H_HEADER_GUARD