From 025d806c70d82b94b9fc9419cf57e44d20aa9742 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Wed, 9 Nov 2016 14:29:37 -0800 Subject: [PATCH] Present swap chain only when it's updated. --- src/renderer_d3d11.cpp | 31 +++++++++++++---- src/renderer_d3d11.h | 4 +++ src/renderer_d3d9.cpp | 76 +++++++++++++++++++++++++----------------- src/renderer_d3d9.h | 7 ++-- src/renderer_gl.cpp | 16 +++++++-- src/renderer_gl.h | 2 ++ 6 files changed, 96 insertions(+), 40 deletions(-) diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index d5ba0868b..7f61195de 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -2255,13 +2255,13 @@ BX_PRAGMA_DIAGNOSTIC_POP(); for (uint32_t ii = 1, num = m_numWindows; ii < num && SUCCEEDED(hr); ++ii) { - hr = m_frameBuffers[m_windows[ii].idx].m_swapChain->Present(syncInterval, 0); + hr = m_frameBuffers[m_windows[ii].idx].present(syncInterval); } if (SUCCEEDED(hr) ) { m_ovr.flip(); - m_ovr.swap(_hmd); // TODO - move this out of end-of-frame + m_ovr.swap(_hmd); if (!m_ovr.isEnabled()) { @@ -2574,10 +2574,7 @@ BX_PRAGMA_DIAGNOSTIC_POP(); invalidateTextureStage(); FrameBufferD3D11& frameBuffer = m_frameBuffers[_fbh.idx]; - m_deviceCtx->OMSetRenderTargets(frameBuffer.m_num, frameBuffer.m_rtv, frameBuffer.m_dsv); - - m_currentColor = frameBuffer.m_rtv[0]; - m_currentDepthStencil = frameBuffer.m_dsv; + frameBuffer.set(); } m_fbh = _fbh; @@ -4712,6 +4709,7 @@ BX_PRAGMA_DIAGNOSTIC_POP(); m_swapChain = NULL; m_numTh = _num; + m_needPresent = false; memcpy(m_attachment, _attachment, _num*sizeof(Attachment) ); postReset(); @@ -4773,6 +4771,7 @@ BX_PRAGMA_DIAGNOSTIC_POP(); m_num = 0; m_numTh = 0; + m_needPresent = false; uint16_t denseIdx = m_denseIdx; m_denseIdx = UINT16_MAX; @@ -5018,6 +5017,26 @@ BX_PRAGMA_DIAGNOSTIC_POP(); } } + void FrameBufferD3D11::set() + { + s_renderD3D11->m_deviceCtx->OMSetRenderTargets(m_num, m_rtv, m_dsv); + m_needPresent = UINT16_MAX != m_denseIdx; + s_renderD3D11->m_currentColor = m_rtv[0]; + s_renderD3D11->m_currentDepthStencil = m_dsv; + } + + HRESULT FrameBufferD3D11::present(uint32_t _syncInterval) + { + if (m_needPresent) + { + HRESULT hr = m_swapChain->Present(_syncInterval, 0); + m_needPresent = false; + return hr; + } + + return S_OK; + } + void TimerQueryD3D11::postReset() { ID3D11Device* device = s_renderD3D11->m_device; diff --git a/src/renderer_d3d11.h b/src/renderer_d3d11.h index 796e99c39..5c47fb530 100644 --- a/src/renderer_d3d11.h +++ b/src/renderer_d3d11.h @@ -269,6 +269,7 @@ namespace bgfx { namespace d3d11 , m_denseIdx(UINT16_MAX) , m_num(0) , m_numTh(0) + , m_needPresent(false) { } @@ -279,6 +280,8 @@ namespace bgfx { namespace d3d11 void postReset(); void resolve(); void clear(const Clear& _clear, const float _palette[][4]); + void set(); + HRESULT present(uint32_t _syncInterval); ID3D11RenderTargetView* m_rtv[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS-1]; ID3D11ShaderResourceView* m_srv[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS-1]; @@ -291,6 +294,7 @@ namespace bgfx { namespace d3d11 uint16_t m_denseIdx; uint8_t m_num; uint8_t m_numTh; + bool m_needPresent; }; struct TimerQueryD3D11 diff --git a/src/renderer_d3d9.cpp b/src/renderer_d3d9.cpp index 78a167d3e..2c662adf8 100644 --- a/src/renderer_d3d9.cpp +++ b/src/renderer_d3d9.cpp @@ -1369,35 +1369,7 @@ namespace bgfx { namespace d3d9 } else { - const FrameBufferD3D9& frameBuffer = m_frameBuffers[_fbh.idx]; - - // If frame buffer has only depth attachment D3DFMT_NULL - // render target is created. - const uint32_t fbnum = bx::uint32_max(2, frameBuffer.m_numTh); - const uint8_t dsIdx = frameBuffer.m_dsIdx; - - DX_CHECK(m_device->SetDepthStencilSurface(UINT8_MAX == dsIdx - ? m_backBufferDepthStencil - : frameBuffer.m_surface[dsIdx] - ) ); - - uint32_t rtIdx = 0; - for (uint32_t ii = 0; ii < fbnum; ++ii) - { - IDirect3DSurface9* surface = frameBuffer.m_surface[ii]; - if (ii != dsIdx) - { - DX_CHECK(m_device->SetRenderTarget(rtIdx, surface) ); - ++rtIdx; - } - } - - for (uint32_t ii = rtIdx, num = g_caps.limits.maxFBAttachments; ii < num; ++ii) - { - DX_CHECK(m_device->SetRenderTarget(ii, NULL) ); - } - - DX_CHECK(m_device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE) ); + m_frameBuffers[_fbh.idx].set(); } m_fbh = _fbh; @@ -3245,6 +3217,7 @@ namespace bgfx { namespace d3d9 m_denseIdx = _denseIdx; m_num = 1; m_needResolve = false; + m_needPresent = false; } uint16_t FrameBufferD3D9::destroy() @@ -3274,6 +3247,7 @@ namespace bgfx { namespace d3d9 m_hwnd = NULL; m_num = 0; m_numTh = 0; + m_needPresent = false; uint16_t denseIdx = m_denseIdx; m_denseIdx = UINT16_MAX; @@ -3283,7 +3257,14 @@ namespace bgfx { namespace d3d9 HRESULT FrameBufferD3D9::present() { - return m_swapChain->Present(NULL, NULL, m_hwnd, NULL, 0); + if (m_needPresent) + { + HRESULT hr = m_swapChain->Present(NULL, NULL, m_hwnd, NULL, 0); + m_needPresent = false; + return hr; + } + + return S_OK; } void FrameBufferD3D9::resolve() const @@ -3382,6 +3363,41 @@ namespace bgfx { namespace d3d9 ) ); } + void FrameBufferD3D9::set() + { + m_needPresent = UINT16_MAX != m_denseIdx; + + // If frame buffer has only depth attachment D3DFMT_NULL + // render target is created. + const uint32_t fbnum = bx::uint32_max(2, m_numTh); + const uint8_t dsIdx = m_dsIdx; + + IDirect3DDevice9* device = s_renderD3D9->m_device; + + DX_CHECK(device->SetDepthStencilSurface(UINT8_MAX == dsIdx + ? s_renderD3D9->m_backBufferDepthStencil + : m_surface[dsIdx] + ) ); + + uint32_t rtIdx = 0; + for (uint32_t ii = 0; ii < fbnum; ++ii) + { + IDirect3DSurface9* surface = m_surface[ii]; + if (ii != dsIdx) + { + DX_CHECK(device->SetRenderTarget(rtIdx, surface) ); + ++rtIdx; + } + } + + for (uint32_t ii = rtIdx, num = g_caps.limits.maxFBAttachments; ii < num; ++ii) + { + DX_CHECK(device->SetRenderTarget(ii, NULL) ); + } + + DX_CHECK(device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE) ); + } + void TimerQueryD3D9::postReset() { IDirect3DDevice9* device = s_renderD3D9->m_device; diff --git a/src/renderer_d3d9.h b/src/renderer_d3d9.h index dc5f234b7..c85cddc56 100644 --- a/src/renderer_d3d9.h +++ b/src/renderer_d3d9.h @@ -393,10 +393,11 @@ namespace bgfx { namespace d3d9 FrameBufferD3D9() : m_hwnd(NULL) , m_denseIdx(UINT16_MAX) - , m_needResolve(0) , m_num(0) , m_numTh(0) , m_dsIdx(UINT8_MAX) + , m_needResolve(false) + , m_needPresent(false) { } @@ -408,6 +409,7 @@ namespace bgfx { namespace d3d9 void preReset(); void postReset(); void createNullColorRT(); + void set(); IDirect3DSurface9* m_surface[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS-1]; IDirect3DSwapChain9* m_swapChain; @@ -417,10 +419,11 @@ namespace bgfx { namespace d3d9 Attachment m_attachment[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS]; uint16_t m_denseIdx; - bool m_needResolve; uint8_t m_num; uint8_t m_numTh; uint8_t m_dsIdx; + bool m_needResolve; + bool m_needPresent; }; struct TimerQueryD3D9 diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index 9017c00ca..333cc5dea 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -2277,11 +2277,16 @@ namespace bgfx { namespace gl { for (uint32_t ii = 1, num = m_numWindows; ii < num; ++ii) { - m_glctx.swap(m_frameBuffers[m_windows[ii].idx].m_swapChain); + FrameBufferGL& frameBuffer = m_frameBuffers[m_windows[ii].idx]; + if (frameBuffer.m_needPresent) + { + m_glctx.swap(frameBuffer.m_swapChain); + frameBuffer.m_needPresent = false; + } } m_ovr.flip(); - m_ovr.swap(_hmd); // TODO - move this out of end-of-frame + m_ovr.swap(_hmd); // need to swap GL render context even if OVR is enabled to get the mirror texture in the output m_glctx.swap(); @@ -2761,6 +2766,7 @@ namespace bgfx { namespace gl if (UINT16_MAX != frameBuffer.m_denseIdx) { m_glctx.makeCurrent(frameBuffer.m_swapChain); + frameBuffer.m_needPresent = true; } else { @@ -5767,6 +5773,8 @@ namespace bgfx { namespace gl m_numTh = _num; memcpy(m_attachment, _attachment, _num*sizeof(Attachment) ); + m_needPresent = false; + postReset(); } @@ -5918,7 +5926,9 @@ namespace bgfx { namespace gl m_swapChain = s_renderGL->m_glctx.createSwapChain(_nwh); m_width = _width; m_height = _height; + m_numTh = 0; m_denseIdx = _denseIdx; + m_needPresent = false; } uint16_t FrameBufferGL::destroy() @@ -5938,6 +5948,8 @@ namespace bgfx { namespace gl memset(m_fbo, 0, sizeof(m_fbo) ); uint16_t denseIdx = m_denseIdx; m_denseIdx = UINT16_MAX; + m_needPresent = false; + m_numTh = 0; return denseIdx; } diff --git a/src/renderer_gl.h b/src/renderer_gl.h index 012f90d0f..b95e285c8 100644 --- a/src/renderer_gl.h +++ b/src/renderer_gl.h @@ -1308,6 +1308,7 @@ namespace bgfx { namespace gl : m_swapChain(NULL) , m_denseIdx(UINT16_MAX) , m_num(0) + , m_needPresent(false) { memset(m_fbo, 0, sizeof(m_fbo) ); } @@ -1326,6 +1327,7 @@ namespace bgfx { namespace gl uint16_t m_denseIdx; uint8_t m_num; uint8_t m_numTh; + bool m_needPresent; Attachment m_attachment[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS]; };