1 /* 2 * Copyright 2011-2019 Branimir Karadzic. All rights reserved. 3 * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause 4 */ 5 6 #ifndef BGFX_RENDERER_D3D9_H_HEADER_GUARD 7 #define BGFX_RENDERER_D3D9_H_HEADER_GUARD 8 9 #define BGFX_CONFIG_RENDERER_DIRECT3D9EX BX_PLATFORM_WINDOWS 10 11 #if BX_PLATFORM_WINDOWS 12 # include <sal.h> 13 # include <d3d9.h> 14 #endif // BX_PLATFORM_ 15 16 #ifndef D3DSTREAMSOURCE_INDEXEDDATA 17 # define D3DSTREAMSOURCE_INDEXEDDATA (1<<30) 18 #endif// D3DSTREAMSOURCE_INDEXEDDATA 19 20 #ifndef D3DSTREAMSOURCE_INSTANCEDATA 21 # define D3DSTREAMSOURCE_INSTANCEDATA (2<<30) 22 #endif // D3DSTREAMSOURCE_INSTANCEDATA 23 24 #include "renderer.h" 25 #include "renderer_d3d.h" 26 #include "nvapi.h" 27 28 #define BGFX_D3D9_PROFILER_BEGIN(_view, _abgr) \ 29 BX_MACRO_BLOCK_BEGIN \ 30 PIX_BEGINEVENT(_abgr, s_viewNameW[_view]); \ 31 BGFX_PROFILER_BEGIN(s_viewName[view], _abgr); \ 32 BX_MACRO_BLOCK_END 33 34 #define BGFX_D3D9_PROFILER_BEGIN_LITERAL(_name, _abgr) \ 35 BX_MACRO_BLOCK_BEGIN \ 36 PIX_BEGINEVENT(_abgr, L"" # _name); \ 37 BGFX_PROFILER_BEGIN_LITERAL("" # _name, _abgr); \ 38 BX_MACRO_BLOCK_END 39 40 #define BGFX_D3D9_PROFILER_END() \ 41 BX_MACRO_BLOCK_BEGIN \ 42 BGFX_PROFILER_END(); \ 43 PIX_ENDEVENT(); \ 44 BX_MACRO_BLOCK_END 45 46 namespace bgfx { namespace d3d9 47 { 48 # if defined(D3D_DISABLE_9EX) 49 # define D3DFMT_S8_LOCKABLE D3DFORMAT( 85) 50 # define D3DFMT_A1 D3DFORMAT(118) 51 # endif // defined(D3D_DISABLE_9EX) 52 53 # ifndef D3DFMT_ATI1 54 # define D3DFMT_ATI1 ( (D3DFORMAT)BX_MAKEFOURCC('A', 'T', 'I', '1') ) 55 # endif // D3DFMT_ATI1 56 57 # ifndef D3DFMT_ATI2 58 # define D3DFMT_ATI2 ( (D3DFORMAT)BX_MAKEFOURCC('A', 'T', 'I', '2') ) 59 # endif // D3DFMT_ATI2 60 61 # ifndef D3DFMT_ATOC 62 # define D3DFMT_ATOC ( (D3DFORMAT)BX_MAKEFOURCC('A', 'T', 'O', 'C') ) 63 # endif // D3DFMT_ATOC 64 65 # ifndef D3DFMT_DF16 66 # define D3DFMT_DF16 ( (D3DFORMAT)BX_MAKEFOURCC('D', 'F', '1', '6') ) 67 # endif // D3DFMT_DF16 68 69 # ifndef D3DFMT_DF24 70 # define D3DFMT_DF24 ( (D3DFORMAT)BX_MAKEFOURCC('D', 'F', '2', '4') ) 71 # endif // D3DFMT_DF24 72 73 # ifndef D3DFMT_INST 74 # define D3DFMT_INST ( (D3DFORMAT)BX_MAKEFOURCC('I', 'N', 'S', 'T') ) 75 # endif // D3DFMT_INST 76 77 # ifndef D3DFMT_INTZ 78 # define D3DFMT_INTZ ( (D3DFORMAT)BX_MAKEFOURCC('I', 'N', 'T', 'Z') ) 79 # endif // D3DFMT_INTZ 80 81 # ifndef D3DFMT_NULL 82 # define D3DFMT_NULL ( (D3DFORMAT)BX_MAKEFOURCC('N', 'U', 'L', 'L') ) 83 # endif // D3DFMT_NULL 84 85 # ifndef D3DFMT_RESZ 86 # define D3DFMT_RESZ ( (D3DFORMAT)BX_MAKEFOURCC('R', 'E', 'S', 'Z') ) 87 # endif // D3DFMT_RESZ 88 89 # ifndef D3DFMT_RAWZ 90 # define D3DFMT_RAWZ ( (D3DFORMAT)BX_MAKEFOURCC('R', 'A', 'W', 'Z') ) 91 # endif // D3DFMT_RAWZ 92 93 # ifndef D3DFMT_S8_LOCKABLE 94 # define D3DFMT_S8_LOCKABLE ( (D3DFORMAT)85) 95 # endif // D3DFMT_S8_LOCKABLE 96 97 # ifndef D3DFMT_A1 98 # define D3DFMT_A1 ( (D3DFORMAT)118) 99 # endif // D3DFMT_A1 100 101 struct ExtendedFormat 102 { 103 enum Enum 104 { 105 Ati1, 106 Ati2, 107 Df16, 108 Df24, 109 Inst, 110 Intz, 111 Null, 112 Resz, 113 Rawz, 114 Atoc, 115 116 Count, 117 }; 118 119 D3DFORMAT m_fmt; 120 DWORD m_usage; 121 D3DRESOURCETYPE m_type; 122 bool m_supported; 123 }; 124 125 struct Msaa 126 { 127 D3DMULTISAMPLE_TYPE m_type; 128 DWORD m_quality; 129 }; 130 131 struct IndexBufferD3D9 132 { IndexBufferD3D9IndexBufferD3D9133 IndexBufferD3D9() 134 : m_ptr(NULL) 135 , m_dynamic(NULL) 136 , m_size(0) 137 , m_flags(BGFX_BUFFER_NONE) 138 { 139 } 140 141 void create(uint32_t _size, void* _data, uint16_t _flags); 142 void update(uint32_t _offset, uint32_t _size, void* _data, bool _discard = false) 143 { 144 if (NULL != m_dynamic 145 && _data != m_dynamic) 146 { 147 bx::memCopy(&m_dynamic[_offset], _data, _size); 148 } 149 150 void* buffer; 151 DX_CHECK(m_ptr->Lock(_offset 152 , _size 153 , &buffer 154 , _discard || (m_dynamic && 0 == _offset && m_size == _size) ? D3DLOCK_DISCARD : 0 155 ) ); 156 157 bx::memCopy(buffer, _data, _size); 158 159 DX_CHECK(m_ptr->Unlock() ); 160 } 161 destroyIndexBufferD3D9162 void destroy() 163 { 164 if (NULL != m_ptr) 165 { 166 DX_RELEASE(m_ptr, 0); 167 168 if (NULL != m_dynamic) 169 { 170 BX_FREE(g_allocator, m_dynamic); 171 m_dynamic = NULL; 172 } 173 } 174 } 175 176 void preReset(); 177 void postReset(); 178 179 IDirect3DIndexBuffer9* m_ptr; 180 uint8_t* m_dynamic; 181 uint32_t m_size; 182 uint16_t m_flags; 183 }; 184 185 struct VertexBufferD3D9 186 { VertexBufferD3D9VertexBufferD3D9187 VertexBufferD3D9() 188 : m_ptr(NULL) 189 , m_dynamic(NULL) 190 , m_size(0) 191 { 192 } 193 194 void create(uint32_t _size, void* _data, VertexLayoutHandle _layoutHandle); 195 void update(uint32_t _offset, uint32_t _size, void* _data, bool _discard = false) 196 { 197 if (NULL != m_dynamic 198 && _data != m_dynamic) 199 { 200 bx::memCopy(&m_dynamic[_offset], _data, _size); 201 } 202 203 void* buffer; 204 DX_CHECK(m_ptr->Lock(_offset 205 , _size 206 , &buffer 207 , _discard || (m_dynamic && 0 == _offset && m_size == _size) ? D3DLOCK_DISCARD : 0 208 ) ); 209 210 bx::memCopy(buffer, _data, _size); 211 212 DX_CHECK(m_ptr->Unlock() ); 213 } 214 destroyVertexBufferD3D9215 void destroy() 216 { 217 if (NULL != m_ptr) 218 { 219 DX_RELEASE(m_ptr, 0); 220 221 if (NULL != m_dynamic) 222 { 223 BX_FREE(g_allocator, m_dynamic); 224 m_dynamic = NULL; 225 } 226 } 227 } 228 229 void preReset(); 230 void postReset(); 231 232 IDirect3DVertexBuffer9* m_ptr; 233 uint8_t* m_dynamic; 234 uint32_t m_size; 235 VertexLayoutHandle m_layoutHandle; 236 }; 237 238 struct ShaderD3D9 239 { ShaderD3D9ShaderD3D9240 ShaderD3D9() 241 : m_vertexShader(NULL) 242 , m_constantBuffer(NULL) 243 , m_numPredefined(0) 244 , m_type(0) 245 { 246 } 247 248 void create(const Memory* _mem); 249 destroyShaderD3D9250 void destroy() 251 { 252 if (NULL != m_constantBuffer) 253 { 254 UniformBuffer::destroy(m_constantBuffer); 255 m_constantBuffer = NULL; 256 } 257 m_numPredefined = 0; 258 259 switch (m_type) 260 { 261 case 0: DX_RELEASE(m_vertexShader, 0); BX_FALLTHROUGH; 262 default: DX_RELEASE(m_pixelShader, 0); 263 } 264 } 265 266 union 267 { 268 // X360 doesn't have interface inheritance (can't use IUnknown*). 269 IDirect3DVertexShader9* m_vertexShader; 270 IDirect3DPixelShader9* m_pixelShader; 271 }; 272 UniformBuffer* m_constantBuffer; 273 PredefinedUniform m_predefined[PredefinedUniform::Count]; 274 uint8_t m_numPredefined; 275 uint8_t m_type; 276 }; 277 278 struct ProgramD3D9 279 { createProgramD3D9280 void create(const ShaderD3D9* _vsh, const ShaderD3D9* _fsh) 281 { 282 m_vsh = _vsh; 283 m_fsh = _fsh; 284 285 bx::memCopy(&m_predefined[0], _vsh->m_predefined, _vsh->m_numPredefined*sizeof(PredefinedUniform) ); 286 m_numPredefined = _vsh->m_numPredefined; 287 288 if (NULL != _fsh) 289 { 290 bx::memCopy(&m_predefined[_vsh->m_numPredefined], _fsh->m_predefined, _fsh->m_numPredefined*sizeof(PredefinedUniform) ); 291 m_numPredefined += _fsh->m_numPredefined; 292 } 293 } 294 destroyProgramD3D9295 void destroy() 296 { 297 m_numPredefined = 0; 298 m_vsh = NULL; 299 m_fsh = NULL; 300 } 301 302 const ShaderD3D9* m_vsh; 303 const ShaderD3D9* m_fsh; 304 305 PredefinedUniform m_predefined[PredefinedUniform::Count*2]; 306 uint8_t m_numPredefined; 307 }; 308 309 struct TextureD3D9 310 { 311 enum Enum 312 { 313 Texture2D, 314 Texture3D, 315 TextureCube, 316 }; 317 TextureD3D9TextureD3D9318 TextureD3D9() 319 : m_ptr(NULL) 320 , m_surface(NULL) 321 , m_staging(NULL) 322 , m_textureFormat(TextureFormat::Unknown) 323 { 324 } 325 326 void createTexture(uint32_t _width, uint32_t _height, uint8_t _numMips); 327 void createVolumeTexture(uint32_t _width, uint32_t _height, uint32_t _depth, uint8_t _numMips); 328 void createCubeTexture(uint32_t _width, uint8_t _numMips); 329 330 uint8_t* lock(uint8_t _side, uint8_t _lod, uint32_t& _pitch, uint32_t& _slicePitch, const Rect* _rect = NULL); 331 void unlock(uint8_t _side, uint8_t _lod); 332 void dirty(uint8_t _side, const Rect& _rect, uint16_t _z, uint16_t _depth); 333 IDirect3DSurface9* getSurface(uint8_t _side = 0, uint8_t _mip = 0) const; 334 335 void create(const Memory* _mem, uint64_t _flags, uint8_t _skip); 336 337 void destroy(bool _resize = false) 338 { 339 if (0 == (m_flags & BGFX_SAMPLER_INTERNAL_SHARED) ) 340 { 341 if (_resize) 342 { 343 // BK - at the time of resize there might be one reference held by frame buffer 344 // surface. This frame buffer will be recreated later, and release reference 345 // to existing surface. That's why here we don't care about ref count. 346 m_ptr->Release(); 347 } 348 else 349 { 350 DX_RELEASE(m_ptr, 0); 351 } 352 } 353 DX_RELEASE(m_surface, 0); 354 DX_RELEASE(m_staging, 0); 355 m_textureFormat = TextureFormat::Unknown; 356 } 357 overrideInternalTextureD3D9358 void overrideInternal(uintptr_t _ptr) 359 { 360 destroy(); 361 m_flags |= BGFX_SAMPLER_INTERNAL_SHARED; 362 m_ptr = (IDirect3DBaseTexture9*)_ptr; 363 } 364 365 void updateBegin(uint8_t _side, uint8_t _mip); 366 void update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem); 367 void updateEnd(); 368 void commit(uint8_t _stage, uint32_t _flags, const float _palette[][4]); 369 void resolve(uint8_t _resolve) const; 370 371 void preReset(); 372 void postReset(); 373 374 union 375 { 376 IDirect3DBaseTexture9* m_ptr; 377 IDirect3DTexture9* m_texture2d; 378 IDirect3DVolumeTexture9* m_texture3d; 379 IDirect3DCubeTexture9* m_textureCube; 380 }; 381 382 IDirect3DSurface9* m_surface; 383 384 union 385 { 386 IDirect3DBaseTexture9* m_staging; 387 IDirect3DTexture9* m_staging2d; 388 IDirect3DVolumeTexture9* m_staging3d; 389 IDirect3DCubeTexture9* m_stagingCube; 390 }; 391 392 uint64_t m_flags; 393 uint32_t m_width; 394 uint32_t m_height; 395 uint32_t m_depth; 396 uint8_t m_numMips; 397 uint8_t m_type; 398 uint8_t m_requestedFormat; 399 uint8_t m_textureFormat; 400 }; 401 402 struct FrameBufferD3D9 403 { FrameBufferD3D9FrameBufferD3D9404 FrameBufferD3D9() 405 : m_hwnd(NULL) 406 , m_denseIdx(UINT16_MAX) 407 , m_num(0) 408 , m_numTh(0) 409 , m_dsIdx(UINT8_MAX) 410 , m_needResolve(false) 411 , m_needPresent(false) 412 { 413 } 414 415 void create(uint8_t _num, const Attachment* _attachment); 416 void create(uint16_t _denseIdx, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _format, TextureFormat::Enum _depthFormat); 417 uint16_t destroy(); 418 HRESULT present(); 419 void resolve() const; 420 void preReset(); 421 void postReset(); 422 void createNullColorRT(); 423 void set(); 424 425 IDirect3DSurface9* m_surface[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS-1]; 426 IDirect3DSwapChain9* m_swapChain; 427 HWND m_hwnd; 428 uint32_t m_width; 429 uint32_t m_height; 430 431 Attachment m_attachment[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS]; 432 uint16_t m_denseIdx; 433 uint8_t m_num; 434 uint8_t m_numTh; 435 uint8_t m_dsIdx; 436 bool m_needResolve; 437 bool m_needPresent; 438 }; 439 440 struct TimerQueryD3D9 441 { TimerQueryD3D9TimerQueryD3D9442 TimerQueryD3D9() 443 : m_control(BX_COUNTOF(m_query) ) 444 { 445 } 446 447 void postReset(); 448 void preReset(); 449 uint32_t begin(uint32_t _resultIdx); 450 void end(uint32_t _idx); 451 bool update(); 452 453 struct Query 454 { 455 IDirect3DQuery9* m_disjoint; 456 IDirect3DQuery9* m_begin; 457 IDirect3DQuery9* m_end; 458 IDirect3DQuery9* m_freq; 459 uint32_t m_resultIdx; 460 bool m_ready; 461 }; 462 463 struct Result 464 { resetTimerQueryD3D9::Result465 void reset() 466 { 467 m_begin = 0; 468 m_end = 0; 469 m_frequency = 1; 470 m_pending = 0; 471 } 472 473 uint64_t m_begin; 474 uint64_t m_end; 475 uint64_t m_frequency; 476 uint32_t m_pending; 477 }; 478 479 Result m_result[BGFX_CONFIG_MAX_VIEWS+1]; 480 481 Query m_query[BGFX_CONFIG_MAX_VIEWS*4]; 482 bx::RingBufferControl m_control; 483 }; 484 485 struct OcclusionQueryD3D9 486 { OcclusionQueryD3D9OcclusionQueryD3D9487 OcclusionQueryD3D9() 488 : m_control(BX_COUNTOF(m_query) ) 489 { 490 } 491 492 void postReset(); 493 void preReset(); 494 void begin(Frame* _render, OcclusionQueryHandle _handle); 495 void end(); 496 void resolve(Frame* _render, bool _wait = false); 497 void invalidate(OcclusionQueryHandle _handle); 498 499 struct Query 500 { 501 IDirect3DQuery9* m_ptr; 502 OcclusionQueryHandle m_handle; 503 }; 504 505 Query m_query[BGFX_CONFIG_MAX_OCCLUSION_QUERIES]; 506 bx::RingBufferControl m_control; 507 }; 508 509 } /* namespace d3d9 */ } // namespace bgfx 510 511 #endif // BGFX_RENDERER_D3D9_H_HEADER_GUARD 512