diff --git a/renderdoc/api/app/renderdoc_app.h b/renderdoc/api/app/renderdoc_app.h index ceb42747c..e2b428c55 100644 --- a/renderdoc/api/app/renderdoc_app.h +++ b/renderdoc/api/app/renderdoc_app.h @@ -226,7 +226,12 @@ enum InAppOverlay // API breaking change history: // Version 1 -> 2 - strings changed from wchar_t* to char* (UTF-8) -#define RENDERDOC_API_VERSION 2 +// Version 2 -> 3 - StartFrameCapture, EndFrameCapture and SetActiveWindow take +// 'device' pointer as well as window handles. +// This is either ID3D11Device* or the GL context (HGLRC/GLXContext) +// You can still pass NULL to both to capture the default, as long as +// there's only one device/window pair alive. +#define RENDERDOC_API_VERSION 3 ////////////////////////////////////////////////////////////////////////// // In-program functions @@ -250,17 +255,17 @@ typedef bool32 (RENDERDOC_CC *pRENDERDOC_GetCapture)(uint32_t idx, char *logfile extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_SetCaptureOptions(const CaptureOptions *opts); typedef void (RENDERDOC_CC *pRENDERDOC_SetCaptureOptions)(const CaptureOptions *opts); -extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_SetActiveWindow(void *wndHandle); -typedef void (RENDERDOC_CC *pRENDERDOC_SetActiveWindow)(void *wndHandle); +extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_SetActiveWindow(void *device, void *wndHandle); +typedef void (RENDERDOC_CC *pRENDERDOC_SetActiveWindow)(void *device, void *wndHandle); extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_TriggerCapture(); typedef void (RENDERDOC_CC *pRENDERDOC_TriggerCapture)(); -extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_StartFrameCapture(void *wndHandle); -typedef void (RENDERDOC_CC *pRENDERDOC_StartFrameCapture)(void *wndHandle); +extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_StartFrameCapture(void *device, void *wndHandle); +typedef void (RENDERDOC_CC *pRENDERDOC_StartFrameCapture)(void *device, void *wndHandle); -extern "C" RENDERDOC_API bool32 RENDERDOC_CC RENDERDOC_EndFrameCapture(void *wndHandle); -typedef bool32 (RENDERDOC_CC *pRENDERDOC_EndFrameCapture)(void *wndHandle); +extern "C" RENDERDOC_API bool32 RENDERDOC_CC RENDERDOC_EndFrameCapture(void *device, void *wndHandle); +typedef bool32 (RENDERDOC_CC *pRENDERDOC_EndFrameCapture)(void *device, void *wndHandle); extern "C" RENDERDOC_API uint32_t RENDERDOC_CC RENDERDOC_GetOverlayBits(); typedef uint32_t (RENDERDOC_CC *pRENDERDOC_GetOverlayBits)(); diff --git a/renderdoc/core/core.cpp b/renderdoc/core/core.cpp index 7cc7ed7f5..1816b0ff7 100644 --- a/renderdoc/core/core.cpp +++ b/renderdoc/core/core.cpp @@ -160,7 +160,6 @@ RenderDoc::RenderDoc() m_Replay = false; - m_Focus = false; m_Cap = false; m_FocusKeys.clear(); @@ -311,66 +310,88 @@ void RenderDoc::Shutdown() } } -void RenderDoc::StartFrameCapture(void *wnd) +void RenderDoc::StartFrameCapture(void *dev, void *wnd) { - if(wnd == NULL) + if(dev == NULL || wnd == NULL) { + // if we have a single window frame capturer, use that in preference if(m_WindowFrameCapturers.size() == 1) { - m_WindowFrameCapturers.begin()->second.FrameCapturer->StartFrameCapture(wnd); + auto it = m_WindowFrameCapturers.begin(); + it->second.FrameCapturer->StartFrameCapture(it->first.dev, it->first.wnd); } + // otherwise, see if we only have one default capturer + else if(m_DefaultFrameCapturers.size() == 1) + { + (*m_DefaultFrameCapturers.begin())->StartFrameCapture(dev, wnd); + } + // otherwise we can't capture with NULL handles else { - RDCERR("Multiple frame capture methods registered, can't capture by NULL window"); + RDCERR("Multiple frame capture methods registered, can't capture by NULL handles"); } return; } - auto it = m_WindowFrameCapturers.find(wnd); + DeviceWnd dw(dev, wnd); + + auto it = m_WindowFrameCapturers.find(dw); if(it == m_WindowFrameCapturers.end()) { - RDCERR("Couldn't find frame capturer for this window %p", wnd); + RDCERR("Couldn't find frame capturer for device %p window %p", dev, wnd); return; } - it->second.FrameCapturer->StartFrameCapture(wnd); + it->second.FrameCapturer->StartFrameCapture(dev, wnd); } -void RenderDoc::SetActiveWindow(void *wnd) +void RenderDoc::SetActiveWindow(void *dev, void *wnd) { - auto it = m_WindowFrameCapturers.find(wnd); + DeviceWnd dw(dev, wnd); + + auto it = m_WindowFrameCapturers.find(dw); if(it == m_WindowFrameCapturers.end()) { - RDCERR("Couldn't find frame capturer for this window %p", wnd); + RDCERR("Couldn't find frame capturer for device %p window %p", dev, wnd); return; } - it->second.FrameCapturer->SetActiveWindow(wnd); + m_ActiveWindow = dw; } -bool RenderDoc::EndFrameCapture(void *wnd) +bool RenderDoc::EndFrameCapture(void *dev, void *wnd) { - if(wnd == NULL) + if(dev == NULL || wnd == NULL) { + // if we have a single window frame capturer, use that in preference if(m_WindowFrameCapturers.size() == 1) { - return m_WindowFrameCapturers.begin()->second.FrameCapturer->EndFrameCapture(wnd); + auto it = m_WindowFrameCapturers.begin(); + return it->second.FrameCapturer->EndFrameCapture(it->first.dev, it->first.wnd); } + // otherwise, see if we only have one default capturer + else if(m_DefaultFrameCapturers.size() == 1) + { + (*m_DefaultFrameCapturers.begin())->EndFrameCapture(dev, wnd); + } + // otherwise we can't capture with NULL handles else { - RDCERR("Multiple frame capture methods registered, can't capture by NULL window"); + RDCERR("Multiple frame capture methods registered, can't capture by NULL handles"); } return false; } - auto it = m_WindowFrameCapturers.find(wnd); + DeviceWnd dw(dev, wnd); + + auto it = m_WindowFrameCapturers.find(dw); if(it == m_WindowFrameCapturers.end()) { - RDCERR("Couldn't find frame capturer for this window %p", wnd); + RDCERR("Couldn't find frame capturer for device %p, window %p", dev, wnd); return false; } - return it->second.FrameCapturer->EndFrameCapture(wnd); + return it->second.FrameCapturer->EndFrameCapture(dev, wnd); } void RenderDoc::Tick() @@ -385,9 +406,32 @@ void RenderDoc::Tick() for(size_t i=0; i < m_CaptureKeys.size(); i++) cur_cap |= Keyboard::GetKeyState(m_CaptureKeys[i]); if(!prev_focus && cur_focus) - FocusToggle(); + { + m_Cap = false; + + // can only shift focus if we have multiple windows + if(m_WindowFrameCapturers.size() > 1) + { + for(auto it = m_WindowFrameCapturers.begin(); it != m_WindowFrameCapturers.end(); ++it) + { + if(it->first == m_ActiveWindow) + { + auto nextit = it; ++nextit; + + if(nextit != m_WindowFrameCapturers.end()) + m_ActiveWindow = nextit->first; + else + m_ActiveWindow = m_WindowFrameCapturers.begin()->first; + + break; + } + } + } + } if(!prev_cap && cur_cap) - TriggerCapture(); + { + TriggerCapture(); + } prev_focus = cur_focus; prev_cap = cur_cap; @@ -729,15 +773,27 @@ void RenderDoc::SuccessfullyWrittenLog() } } -void RenderDoc::AddFrameCapturer(void *wnd, IFrameCapturer *cap) +void RenderDoc::AddDefaultFrameCapturer(IFrameCapturer *cap) { - if(wnd == NULL || cap == NULL) + m_DefaultFrameCapturers.insert(cap); +} + +void RenderDoc::RemoveDefaultFrameCapturer(IFrameCapturer *cap) +{ + m_DefaultFrameCapturers.erase(cap); +} + +void RenderDoc::AddFrameCapturer(void *dev, void *wnd, IFrameCapturer *cap) +{ + if(dev == NULL || wnd == NULL || cap == NULL) { RDCERR("Invalid FrameCapturer combination: %#p / %#p", wnd, cap); return; } + + DeviceWnd dw(dev, wnd); - auto it = m_WindowFrameCapturers.find(wnd); + auto it = m_WindowFrameCapturers.find(dw); if(it != m_WindowFrameCapturers.end()) { if(it->second.FrameCapturer != cap) @@ -747,19 +803,35 @@ void RenderDoc::AddFrameCapturer(void *wnd, IFrameCapturer *cap) } else { - m_WindowFrameCapturers[wnd].FrameCapturer = cap; + m_WindowFrameCapturers[dw].FrameCapturer = cap; } + + // the first one we see becomes the default + if(m_ActiveWindow == DeviceWnd()) + m_ActiveWindow = dw; } -void RenderDoc::RemoveFrameCapturer(void *wnd) +void RenderDoc::RemoveFrameCapturer(void *dev, void *wnd) { - auto it = m_WindowFrameCapturers.find(wnd); + DeviceWnd dw(dev, wnd); + + auto it = m_WindowFrameCapturers.find(dw); if(it != m_WindowFrameCapturers.end()) { it->second.RefCount--; if(it->second.RefCount <= 0) + { + if(m_ActiveWindow == dw) + { + if(m_WindowFrameCapturers.size() == 1) + m_ActiveWindow = DeviceWnd(); + else + m_ActiveWindow = m_WindowFrameCapturers.begin()->first; + } + m_WindowFrameCapturers.erase(it); + } } else { diff --git a/renderdoc/core/core.h b/renderdoc/core/core.h index 9d01ccf26..671c126ee 100644 --- a/renderdoc/core/core.h +++ b/renderdoc/core/core.h @@ -62,9 +62,8 @@ struct ICrashHandler struct IFrameCapturer { - virtual void StartFrameCapture(void *wnd) = 0; - virtual void SetActiveWindow(void *wnd) = 0; - virtual bool EndFrameCapture(void *wnd) = 0; + virtual void StartFrameCapture(void *dev, void *wnd) = 0; + virtual bool EndFrameCapture(void *dev, void *wnd) = 0; }; enum LogState @@ -236,14 +235,20 @@ class RenderDoc void Tick(); - void AddFrameCapturer(void *wnd, IFrameCapturer *cap); - void RemoveFrameCapturer(void *wnd); - - void StartFrameCapture(void *wnd); - void SetActiveWindow(void *wnd); - bool EndFrameCapture(void *wnd); + void AddFrameCapturer(void *dev, void *wnd, IFrameCapturer *cap); + void RemoveFrameCapturer(void *dev, void *wnd); + + // add window-less frame capturers for use via users capturing + // manually through the renderdoc API with NULL device/window handles + void AddDefaultFrameCapturer(IFrameCapturer *cap); + void RemoveDefaultFrameCapturer(IFrameCapturer *cap); + + void StartFrameCapture(void *dev, void *wnd); + void SetActiveWindow(void *dev, void *wnd); + bool EndFrameCapture(void *dev, void *wnd); + + bool IsActiveWindow(void *dev, void *wnd) { return dev == m_ActiveWindow.dev && wnd == m_ActiveWindow.wnd; } - void FocusToggle() { m_Focus = true; m_Cap = false; } void TriggerCapture() { m_Cap = true; } uint32_t GetOverlayBits() { return m_Overlay; } @@ -267,7 +272,6 @@ class RenderDoc const vector &GetFocusKeys() { return m_FocusKeys; } const vector &GetCaptureKeys() { return m_CaptureKeys; } - bool ShouldFocusToggle() { bool ret = m_Focus; m_Focus = false; return ret; } bool ShouldTriggerCapture(uint32_t frameNumber); private: RenderDoc(); @@ -277,7 +281,6 @@ class RenderDoc bool m_Replay; - bool m_Focus; bool m_Cap; vector m_FocusKeys; @@ -319,7 +322,27 @@ class RenderDoc int RefCount; }; - map m_WindowFrameCapturers; + struct DeviceWnd + { + DeviceWnd() : dev(NULL), wnd(NULL) {} + DeviceWnd(void *d, void *w) : dev(d), wnd(w) {} + void *dev; + void *wnd; + + bool operator ==(const DeviceWnd &o) const + { + return dev == o.dev && wnd == o.wnd; + } + bool operator <(const DeviceWnd &o) const + { + if(dev != o.dev) return dev < o.dev; + return wnd < o.wnd; + } + }; + + map m_WindowFrameCapturers; + DeviceWnd m_ActiveWindow; + set m_DefaultFrameCapturers; volatile bool m_RemoteServerThreadShutdown; volatile bool m_RemoteClientThreadShutdown; diff --git a/renderdoc/driver/d3d11/d3d11_device.cpp b/renderdoc/driver/d3d11/d3d11_device.cpp index 485c2eeef..b681729b3 100644 --- a/renderdoc/driver/d3d11/d3d11_device.cpp +++ b/renderdoc/driver/d3d11/d3d11_device.cpp @@ -288,8 +288,6 @@ WrappedID3D11Device::WrappedID3D11Device(ID3D11Device* realDevice, D3D11InitPara m_FailedReason = CaptureSucceeded; m_Failures = 0; - m_SwapChain = NULL; - m_FrameTimer.Restart(); m_AppControlledCapture = false; @@ -343,7 +341,7 @@ WrappedID3D11Device::WrappedID3D11Device(ID3D11Device* realDevice, D3D11InitPara m_DeviceRecord->NumSubResources = 0; m_DeviceRecord->SubResources = NULL; - RenderDoc::Inst().AddFrameCapturer(this, this); + RenderDoc::Inst().AddDefaultFrameCapturer(this); } ID3D11DeviceContext *context = NULL; @@ -417,6 +415,8 @@ WrappedID3D11Device::~WrappedID3D11Device() if(m_pCurrentWrappedDevice == this) m_pCurrentWrappedDevice = NULL; + RenderDoc::Inst().RemoveDefaultFrameCapturer(this); + for(auto it = m_CachedStateObjects.begin(); it != m_CachedStateObjects.end(); ++it) if(*it) (*it)->Release(); @@ -456,9 +456,6 @@ WrappedID3D11Device::~WrappedID3D11Device() SAFE_DELETE(it->second); m_LayoutDXBC.clear(); m_LayoutDescs.clear(); - - if(!RenderDoc::Inst().IsReplayApp()) - RenderDoc::Inst().RemoveFrameCapturer(this); if(RenderDoc::Inst().GetCrashHandler()) RenderDoc::Inst().GetCrashHandler()->UnregisterMemoryRegion(this); @@ -2327,6 +2324,8 @@ void WrappedID3D11Device::ReleaseSwapchainResources(IDXGISwapChain *swap) swap->GetDesc(&desc); Keyboard::RemoveInputWindow(desc.OutputWindow); + + RenderDoc::Inst().RemoveFrameCapturer(this, desc.OutputWindow); } auto it = m_SwapChains.find(swap); @@ -2335,14 +2334,6 @@ void WrappedID3D11Device::ReleaseSwapchainResources(IDXGISwapChain *swap) SAFE_RELEASE(it->second); m_SwapChains.erase(it); } - - if(swap == m_SwapChain) - { - if(m_SwapChains.empty()) - m_SwapChain = NULL; - else - m_SwapChain = m_SwapChains.begin()->first; - } } bool WrappedID3D11Device::Serialise_SetSwapChainTexture(IDXGISwapChain *swap, DXGI_SWAP_CHAIN_DESC *swapDesc, UINT buffer, ID3D11Texture2D *pTex) @@ -2442,11 +2433,8 @@ void WrappedID3D11Device::SetSwapChainTexture(IDXGISwapChain *swap, DXGI_SWAP_CH swap->GetDesc(&sdesc); Keyboard::AddInputWindow(sdesc.OutputWindow); - } - if(m_SwapChain == NULL) - { - m_SwapChain = swap; + RenderDoc::Inst().AddFrameCapturer(this, sdesc.OutputWindow, this); } } @@ -2474,7 +2462,7 @@ int WrappedID3D11Device::EndEvent() return m_pCurrentWrappedDevice->m_pImmediateContext->ThreadSafe_EndEvent(); } -void WrappedID3D11Device::StartFrameCapture(void *wnd) +void WrappedID3D11Device::StartFrameCapture(void *dev, void *wnd) { if(m_State != WRITING_IDLE) return; @@ -2526,24 +2514,7 @@ void WrappedID3D11Device::StartFrameCapture(void *wnd) RDCLOG("Starting capture, frame %u", m_FrameCounter); } -void WrappedID3D11Device::SetActiveWindow(void *wnd) -{ - for(auto it=m_SwapChains.begin(); it!=m_SwapChains.end(); ++it) - { - DXGI_SWAP_CHAIN_DESC swapDesc; - it->first->GetDesc(&swapDesc); - - if(swapDesc.OutputWindow == wnd) - { - m_SwapChain = it->first; - return; - } - } - - RDCERR("Output window %p provided for active window corresponds with no known swap chain", wnd); -} - -bool WrappedID3D11Device::EndFrameCapture(void *wnd) +bool WrappedID3D11Device::EndFrameCapture(void *dev, void *wnd) { if(m_State != WRITING_CAPFRAME) return true; @@ -2996,7 +2967,6 @@ HRESULT WrappedID3D11Device::Present(IDXGISwapChain *swap, UINT SyncInterval, UI if((Flags & DXGI_PRESENT_TEST) != 0) return S_OK; - RenderDoc::Inst().SetCurrentDriver(RDC_D3D11); m_pCurrentWrappedDevice = this; if(m_State == WRITING_IDLE) @@ -3008,6 +2978,10 @@ HRESULT WrappedID3D11Device::Present(IDXGISwapChain *swap, UINT SyncInterval, UI m_pImmediateContext->BeginFrame(); + DXGI_SWAP_CHAIN_DESC swapdesc; + swap->GetDesc(&swapdesc); + bool activeWindow = RenderDoc::Inst().IsActiveWindow(this, swapdesc.OutputWindow); + if(m_State == WRITING_IDLE) { D3D11RenderState old = *m_pImmediateContext->GetCurrentPipelineState(); @@ -3055,7 +3029,7 @@ HRESULT WrappedID3D11Device::Present(IDXGISwapChain *swap, UINT SyncInterval, UI GetDebugManager()->SetOutputDimensions(swapDesc.BufferDesc.Width, swapDesc.BufferDesc.Height); GetDebugManager()->SetOutputWindow(swapDesc.OutputWindow); - if(swap == m_SwapChain) + if(activeWindow) { vector keys = RenderDoc::Inst().GetCaptureKeys(); @@ -3131,7 +3105,7 @@ HRESULT WrappedID3D11Device::Present(IDXGISwapChain *swap, UINT SyncInterval, UI { vector keys = RenderDoc::Inst().GetFocusKeys(); - string str = "Inactive swapchain."; + string str = "D3D11. Inactive swapchain."; for(size_t i=0; i < keys.size(); i++) { @@ -3151,48 +3125,20 @@ HRESULT WrappedID3D11Device::Present(IDXGISwapChain *swap, UINT SyncInterval, UI old.ApplyState(m_pImmediateContext); } - - if(RenderDoc::Inst().ShouldFocusToggle()) - { - IDXGISwapChain *s = m_SwapChain; - m_SwapChain = NULL; - - for(auto it=m_SwapChains.begin(); it!=m_SwapChains.end(); ++it) - { - auto next = it; next++; - if(it->first == s) - { - if(next != m_SwapChains.end()) - m_SwapChain = next->first; - else - m_SwapChain = m_SwapChains.begin()->first; - break; - } - } - - if(m_SwapChain == NULL) - m_SwapChain = swap; - - DXGI_SWAP_CHAIN_DESC swapDesc = {0}; - m_SwapChain->GetDesc(&swapDesc); - GetDebugManager()->SetOutputDimensions(swapDesc.BufferDesc.Width, swapDesc.BufferDesc.Height); - GetDebugManager()->SetOutputWindow(swapDesc.OutputWindow); - } } - if(swap != m_SwapChain || m_SwapChain == NULL) + if(!activeWindow) return S_OK; - DXGI_SWAP_CHAIN_DESC swapDesc = {0}; - m_SwapChain->GetDesc(&swapDesc); + RenderDoc::Inst().SetCurrentDriver(RDC_D3D11); // kill any current capture that isn't application defined if(m_State == WRITING_CAPFRAME && !m_AppControlledCapture) - EndFrameCapture(swapDesc.OutputWindow); + EndFrameCapture(this, swapdesc.OutputWindow); if(RenderDoc::Inst().ShouldTriggerCapture(m_FrameCounter) && m_State == WRITING_IDLE) { - StartFrameCapture(swapDesc.OutputWindow); + StartFrameCapture(this, swapdesc.OutputWindow); m_AppControlledCapture = false; } diff --git a/renderdoc/driver/d3d11/d3d11_device.h b/renderdoc/driver/d3d11/d3d11_device.h index 922d894d3..a86797056 100644 --- a/renderdoc/driver/d3d11/d3d11_device.h +++ b/renderdoc/driver/d3d11/d3d11_device.h @@ -238,7 +238,6 @@ private: static WrappedID3D11Device *m_pCurrentWrappedDevice; - IDXGISwapChain *m_SwapChain; map m_SwapChains; uint32_t m_FrameCounter; @@ -300,9 +299,8 @@ public: void Serialise_CaptureScope(uint64_t offset); - void StartFrameCapture(void *wnd); - void SetActiveWindow(void *wnd); - bool EndFrameCapture(void *wnd); + void StartFrameCapture(void *dev, void *wnd); + bool EndFrameCapture(void *dev, void *wnd); //////////////////////////////////////////////////////////////// // log replaying diff --git a/renderdoc/driver/dxgi/dxgi_wrapped.cpp b/renderdoc/driver/dxgi/dxgi_wrapped.cpp index 5202b4063..54dac7607 100644 --- a/renderdoc/driver/dxgi/dxgi_wrapped.cpp +++ b/renderdoc/driver/dxgi/dxgi_wrapped.cpp @@ -271,16 +271,12 @@ WrappedIDXGISwapChain2::WrappedIDXGISwapChain2(IDXGISwapChain* real, HWND wnd, W } } - if(m_Wnd) RenderDoc::Inst().AddFrameCapturer(m_Wnd, m_pDevice); - SAFE_ADDREF(m_pDevice); } WrappedIDXGISwapChain2::~WrappedIDXGISwapChain2() { m_pDevice->ReleaseSwapchainResources(this); - - if(m_Wnd) RenderDoc::Inst().RemoveFrameCapturer(m_Wnd); for(int i=0; i < MAX_NUM_BACKBUFFERS; i++) { diff --git a/renderdoc/driver/gl/gl_driver.cpp b/renderdoc/driver/gl/gl_driver.cpp index 2b0d3f818..f1612468c 100644 --- a/renderdoc/driver/gl/gl_driver.cpp +++ b/renderdoc/driver/gl/gl_driver.cpp @@ -673,17 +673,19 @@ WrappedOpenGL::WrappedOpenGL(const char *logfile, const GLHookSet &funcs) m_FrameTimer.Restart(); + m_AppControlledCapture = false; + m_TotalTime = m_AvgFrametime = m_MinFrametime = m_MaxFrametime = 0.0; m_CurFileSize = 0; m_RealDebugFunc = NULL; m_RealDebugFuncParam = NULL; - + m_DrawcallStack.push_back(&m_ParentDrawcall); - m_CurEventID = 0; - m_CurDrawcallID = 0; + m_CurEventID = 0; + m_CurDrawcallID = 0; m_FirstEventID = 0; m_LastEventID = ~0U; @@ -752,6 +754,8 @@ WrappedOpenGL::WrappedOpenGL(const char *logfile, const GLHookSet &funcs) m_FakeVAOID = GetResourceManager()->RegisterResource(VertexArrayRes(NULL, 0)); GetResourceManager()->AddResourceRecord(m_FakeVAOID); GetResourceManager()->MarkDirtyResource(m_FakeVAOID); + + RenderDoc::Inst().AddDefaultFrameCapturer(this); } else { @@ -899,6 +903,8 @@ WrappedOpenGL::~WrappedOpenGL() if(m_FakeBB_Color) m_Real.glDeleteTextures(1, &m_FakeBB_Color); if(m_FakeBB_DepthStencil) m_Real.glDeleteTextures(1, &m_FakeBB_DepthStencil); + RenderDoc::Inst().RemoveDefaultFrameCapturer(this); + SAFE_DELETE(m_pSerialiser); GetResourceManager()->ReleaseCurrentResource(m_DeviceResourceID); @@ -967,12 +973,32 @@ void WrappedOpenGL::DeleteContext(void *contextHandle) m_ContextData.erase(contextHandle); } +void WrappedOpenGL::ContextData::UnassociateWindow(void *wndHandle) +{ + auto it = windows.find(wndHandle); + if(it != windows.end()) + { + windows.erase(wndHandle); + RenderDoc::Inst().RemoveFrameCapturer(ctx, wndHandle); + } +} + +void WrappedOpenGL::ContextData::AssociateWindow(WrappedOpenGL *gl, void *wndHandle) +{ + auto it = windows.find(wndHandle); + if(it == windows.end()) + RenderDoc::Inst().AddFrameCapturer(ctx, wndHandle, gl); + + windows[wndHandle] = Timing::GetUnixTimestamp(); +} + void WrappedOpenGL::CreateContext(GLWindowingData winData, void *shareContext, GLInitParams initParams, bool core, bool attribsCreate) { // TODO: support multiple GL contexts more explicitly m_InitParams = initParams; ContextData &ctxdata = m_ContextData[winData.ctx]; + ctxdata.ctx = winData.ctx; ctxdata.isCore = core; ctxdata.attribsCreate = attribsCreate; } @@ -1920,15 +1946,54 @@ void WrappedOpenGL::FreeTargetResource(ResourceId id) } } -void WrappedOpenGL::Present(void *windowHandle) +void WrappedOpenGL::SwapBuffers(void *windowHandle) { - RenderDoc::Inst().SetCurrentDriver(RDC_OpenGL); - if(m_State == WRITING_IDLE) RenderDoc::Inst().Tick(); m_FrameCounter++; // first present becomes frame #1, this function is at the end of the frame + ContextData &ctxdata = GetCtxData(); + + // we only handle context-window associations here as it's too common to + // create invisible helper windows while creating contexts, that then + // become the default window. + // Since we only capture windows that do SwapBuffers (i.e. if you're doing + // headless rendering then you must capture via the API anyway), this + // isn't a big problem. + // + // Also we only set up associations for capturable windows. + if(ctxdata.Modern()) + { + for(auto it=m_ContextData.begin(); it != m_ContextData.end(); ++it) + if(it->first != ctxdata.ctx) + it->second.UnassociateWindow(windowHandle); + + ctxdata.AssociateWindow(this, windowHandle); + } + + bool activeWindow = RenderDoc::Inst().IsActiveWindow(ctxdata.ctx, windowHandle); + + // look at previous associations and decay any that are too old + uint64_t ref = Timing::GetUnixTimestamp() - 5; // 5 seconds + + for(auto cit=m_ContextData.begin(); cit != m_ContextData.end(); ++cit) + { + for(auto wit=cit->second.windows.begin(); wit != cit->second.windows.end(); ) + { + if(wit->second < ref) + { + auto remove = wit; + ++wit; + cit->second.windows.erase(remove); + } + else + { + ++wit; + } + } + } + if(m_State == WRITING_IDLE) { m_FrameTimes.push_back(m_FrameTimer.GetMilliseconds()); @@ -1960,15 +2025,13 @@ void WrappedOpenGL::Present(void *windowHandle) uint32_t overlay = RenderDoc::Inst().GetOverlayBits(); - if((overlay & eOverlay_Enabled) && m_Real.glGetIntegerv && m_Real.glReadBuffer && m_Real.glBindFramebuffer && m_Real.glBindBuffer && m_Real.glReadPixels) + if(overlay & eOverlay_Enabled) { RenderTextState textState; - ContextData &ctxdata = GetCtxData(); - textState.Push(m_Real, ctxdata.Modern()); - // TODO: handle selecting active window amongst many + if(activeWindow) { vector keys = RenderDoc::Inst().GetCaptureKeys(); @@ -2046,6 +2109,38 @@ void WrappedOpenGL::Present(void *windowHandle) y += 1.0f; #endif } + else + { + vector keys = RenderDoc::Inst().GetFocusKeys(); + + string str = "OpenGL. Inactive window."; + + if(ctxdata.Modern()) + { + for(size_t i=0; i < keys.size(); i++) + { + if(i == 0) + str += " "; + else + str += ", "; + + str += ToStr::Get(keys[i]); + } + + if(!keys.empty()) + str += " to cycle between windows."; + } + else + { + if(!ctxdata.attribsCreate) + { + str += "\nContext not created via CreateContextAttribs. Capturing disabled.\n"; + } + str += "Only OpenGL 3.2+ contexts are supported."; + } + + RenderOverlayText(0.0f, 0.0f, str.c_str()); + } textState.Pop(m_Real, ctxdata.Modern()); @@ -2060,195 +2155,229 @@ void WrappedOpenGL::Present(void *windowHandle) } } } - - // kill any current capture - if(m_State == WRITING_CAPFRAME) - { - //if(HasSuccessfulCapture()) - { - RDCLOG("Finished capture, Frame %u", m_FrameCounter); - - EndCaptureFrame(); - FinishCapture(); - - const uint32_t maxSize = 1024; - - byte *thpixels = NULL; - uint32_t thwidth = 0; - uint32_t thheight = 0; - - if(m_Real.glGetIntegerv && m_Real.glReadBuffer && m_Real.glBindFramebuffer && m_Real.glBindBuffer && m_Real.glReadPixels) - { - RDCGLenum prevReadBuf = eGL_BACK; - GLint prevBuf = 0; - GLint packBufBind = 0; - GLint prevPackRowLen = 0; - GLint prevPackSkipRows = 0; - GLint prevPackSkipPixels = 0; - GLint prevPackAlignment = 0; - m_Real.glGetIntegerv(eGL_READ_BUFFER, (GLint *)&prevReadBuf); - m_Real.glGetIntegerv(eGL_READ_FRAMEBUFFER_BINDING, &prevBuf); - m_Real.glGetIntegerv(eGL_PIXEL_PACK_BUFFER_BINDING, &packBufBind); - m_Real.glGetIntegerv(eGL_PACK_ROW_LENGTH, &prevPackRowLen); - m_Real.glGetIntegerv(eGL_PACK_SKIP_ROWS, &prevPackSkipRows); - m_Real.glGetIntegerv(eGL_PACK_SKIP_PIXELS, &prevPackSkipPixels); - m_Real.glGetIntegerv(eGL_PACK_ALIGNMENT, &prevPackAlignment); - - m_Real.glBindFramebuffer(eGL_READ_FRAMEBUFFER, 0); - m_Real.glReadBuffer(eGL_BACK); - m_Real.glBindBuffer(eGL_PIXEL_PACK_BUFFER, 0); - m_Real.glPixelStorei(eGL_PACK_ROW_LENGTH, 0); - m_Real.glPixelStorei(eGL_PACK_SKIP_ROWS, 0); - m_Real.glPixelStorei(eGL_PACK_SKIP_PIXELS, 0); - m_Real.glPixelStorei(eGL_PACK_ALIGNMENT, 1); - - thwidth = m_InitParams.width; - thheight = m_InitParams.height; - - thpixels = new byte[thwidth*thheight*3]; - - m_Real.glReadPixels(0, 0, thwidth, thheight, eGL_RGB, eGL_UNSIGNED_BYTE, thpixels); - - for(uint32_t y=0; y <= thheight/2; y++) - { - for(uint32_t x=0; x < thwidth; x++) - { - byte save[3]; - save[0] = thpixels[y*(thwidth*3) + x*3 + 0]; - save[1] = thpixels[y*(thwidth*3) + x*3 + 1]; - save[2] = thpixels[y*(thwidth*3) + x*3 + 2]; - - thpixels[y*(thwidth*3) + x*3 + 0] = thpixels[(thheight-1-y)*(thwidth*3) + x*3 + 0]; - thpixels[y*(thwidth*3) + x*3 + 1] = thpixels[(thheight-1-y)*(thwidth*3) + x*3 + 1]; - thpixels[y*(thwidth*3) + x*3 + 2] = thpixels[(thheight-1-y)*(thwidth*3) + x*3 + 2]; - - thpixels[(thheight-1-y)*(thwidth*3) + x*3 + 0] = save[0]; - thpixels[(thheight-1-y)*(thwidth*3) + x*3 + 1] = save[1]; - thpixels[(thheight-1-y)*(thwidth*3) + x*3 + 2] = save[2]; - } - } - - m_Real.glBindBuffer(eGL_PIXEL_PACK_BUFFER, packBufBind); - m_Real.glBindFramebuffer(eGL_READ_FRAMEBUFFER, prevBuf); - m_Real.glReadBuffer(prevReadBuf); - m_Real.glPixelStorei(eGL_PACK_ROW_LENGTH, prevPackRowLen); - m_Real.glPixelStorei(eGL_PACK_SKIP_ROWS, prevPackSkipRows); - m_Real.glPixelStorei(eGL_PACK_SKIP_PIXELS, prevPackSkipPixels); - m_Real.glPixelStorei(eGL_PACK_ALIGNMENT, prevPackAlignment); - } - - byte *jpgbuf = NULL; - int len = thwidth*thheight; - - if(len > 0) - { - jpgbuf = new byte[len]; - - jpge::params p; - - p.m_quality = 40; - - bool success = jpge::compress_image_to_jpeg_file_in_memory(jpgbuf, len, thwidth, thheight, 3, thpixels, p); - - if(!success) - { - RDCERR("Failed to compress to jpg"); - SAFE_DELETE_ARRAY(jpgbuf); - thwidth = 0; - thheight = 0; - } - } - - Serialiser *m_pFileSerialiser = RenderDoc::Inst().OpenWriteSerialiser(m_FrameCounter, &m_InitParams, jpgbuf, len, thwidth, thheight); - - { - SCOPED_SERIALISE_CONTEXT(DEVICE_INIT); - - SERIALISE_ELEMENT(ResourceId, immContextId, m_ContextResourceID); - SERIALISE_ELEMENT(ResourceId, vaoId, m_FakeVAOID); - - m_pFileSerialiser->Insert(scope.Get(true)); - } - - RDCDEBUG("Inserting Resource Serialisers"); - - GetResourceManager()->InsertReferencedChunks(m_pFileSerialiser); - - GetResourceManager()->InsertInitialContentsChunks(m_pFileSerialiser); - - RDCDEBUG("Creating Capture Scope"); - - { - SCOPED_SERIALISE_CONTEXT(CAPTURE_SCOPE); - - Serialise_CaptureScope(0); - - m_pFileSerialiser->Insert(scope.Get(true)); - } - - { - RDCDEBUG("Getting Resource Record"); - - GLResourceRecord *record = m_ResourceManager->GetResourceRecord(m_ContextResourceID); - - RDCDEBUG("Accumulating context resource list"); - - map recordlist; - record->Insert(recordlist); - - RDCDEBUG("Flushing %u records to file serialiser", (uint32_t)recordlist.size()); - - for(auto it = recordlist.begin(); it != recordlist.end(); ++it) - m_pFileSerialiser->Insert(it->second); - - RDCDEBUG("Done"); - } - - m_CurFileSize += m_pFileSerialiser->FlushToDisk(); - - RenderDoc::Inst().SuccessfullyWrittenLog(); - - SAFE_DELETE(m_pFileSerialiser); - - m_State = WRITING_IDLE; - - GetResourceManager()->MarkUnwrittenResources(); - - GetResourceManager()->ClearReferencedResources(); - } - } + + if(!activeWindow) + return; + + RenderDoc::Inst().SetCurrentDriver(RDC_OpenGL); // only allow capturing on 'modern' created contexts - if(GetCtxData().Modern() && RenderDoc::Inst().ShouldTriggerCapture(m_FrameCounter) && m_State == WRITING_IDLE && m_FrameRecord.empty()) + if(ctxdata.Legacy()) + return; + + // kill any current capture that isn't application defined + if(m_State == WRITING_CAPFRAME && !m_AppControlledCapture) + EndFrameCapture(this, windowHandle); + + // for now, only allow one captured frame at all + if(!m_FrameRecord.empty()) + return; + + if(RenderDoc::Inst().ShouldTriggerCapture(m_FrameCounter) && m_State == WRITING_IDLE) { - m_State = WRITING_CAPFRAME; + StartFrameCapture(this, windowHandle); - GLWindowingData &prevctx = m_ActiveContexts[Threading::GetCurrentID()]; + m_AppControlledCapture = false; + } +} - bool switchedContext = false; - if(prevctx.ctx == NULL) +void WrappedOpenGL::StartFrameCapture(void *dev, void *wnd) +{ + m_State = WRITING_CAPFRAME; + + m_AppControlledCapture = true; + + GLWindowingData &prevctx = m_ActiveContexts[Threading::GetCurrentID()]; + + bool switchedContext = false; + if(prevctx.ctx == NULL) + { + MakeContextCurrent(m_DefaultContexts[Threading::GetCurrentID()]); + switchedContext = true; + } + + FetchFrameRecord record; + record.frameInfo.frameNumber = m_FrameCounter+1; + record.frameInfo.captureTime = Timing::GetUnixTimestamp(); + m_FrameRecord.push_back(record); + + GetResourceManager()->ClearReferencedResources(); + + GetResourceManager()->MarkResourceFrameReferenced(m_DeviceResourceID, eFrameRef_Write); + GetResourceManager()->PrepareInitialContents(); + + AttemptCapture(); + BeginCaptureFrame(); + + if(switchedContext) + MakeContextCurrent(prevctx); + + RDCLOG("Starting capture, frame %u", m_FrameCounter); +} + +bool WrappedOpenGL::EndFrameCapture(void *dev, void *wnd) +{ + if(m_State != WRITING_CAPFRAME) return true; + + CaptureFailReason reason = CaptureSucceeded; + + //if(HasSuccessfulCapture(reason)) + { + RDCLOG("Finished capture, Frame %u", m_FrameCounter); + + ContextEndFrame(); + FinishCapture(); + + const uint32_t maxSize = 1024; + + byte *thpixels = NULL; + uint32_t thwidth = 0; + uint32_t thheight = 0; + + if(m_Real.glGetIntegerv && m_Real.glReadBuffer && m_Real.glBindFramebuffer && m_Real.glBindBuffer && m_Real.glReadPixels) { - MakeContextCurrent(m_DefaultContexts[Threading::GetCurrentID()]); - switchedContext = true; + RDCGLenum prevReadBuf = eGL_BACK; + GLint prevBuf = 0; + GLint packBufBind = 0; + GLint prevPackRowLen = 0; + GLint prevPackSkipRows = 0; + GLint prevPackSkipPixels = 0; + GLint prevPackAlignment = 0; + m_Real.glGetIntegerv(eGL_READ_BUFFER, (GLint *)&prevReadBuf); + m_Real.glGetIntegerv(eGL_READ_FRAMEBUFFER_BINDING, &prevBuf); + m_Real.glGetIntegerv(eGL_PIXEL_PACK_BUFFER_BINDING, &packBufBind); + m_Real.glGetIntegerv(eGL_PACK_ROW_LENGTH, &prevPackRowLen); + m_Real.glGetIntegerv(eGL_PACK_SKIP_ROWS, &prevPackSkipRows); + m_Real.glGetIntegerv(eGL_PACK_SKIP_PIXELS, &prevPackSkipPixels); + m_Real.glGetIntegerv(eGL_PACK_ALIGNMENT, &prevPackAlignment); + + m_Real.glBindFramebuffer(eGL_READ_FRAMEBUFFER, 0); + m_Real.glReadBuffer(eGL_BACK); + m_Real.glBindBuffer(eGL_PIXEL_PACK_BUFFER, 0); + m_Real.glPixelStorei(eGL_PACK_ROW_LENGTH, 0); + m_Real.glPixelStorei(eGL_PACK_SKIP_ROWS, 0); + m_Real.glPixelStorei(eGL_PACK_SKIP_PIXELS, 0); + m_Real.glPixelStorei(eGL_PACK_ALIGNMENT, 1); + + thwidth = m_InitParams.width; + thheight = m_InitParams.height; + + thpixels = new byte[thwidth*thheight*3]; + + m_Real.glReadPixels(0, 0, thwidth, thheight, eGL_RGB, eGL_UNSIGNED_BYTE, thpixels); + + for(uint32_t y=0; y <= thheight/2; y++) + { + for(uint32_t x=0; x < thwidth; x++) + { + byte save[3]; + save[0] = thpixels[y*(thwidth*3) + x*3 + 0]; + save[1] = thpixels[y*(thwidth*3) + x*3 + 1]; + save[2] = thpixels[y*(thwidth*3) + x*3 + 2]; + + thpixels[y*(thwidth*3) + x*3 + 0] = thpixels[(thheight-1-y)*(thwidth*3) + x*3 + 0]; + thpixels[y*(thwidth*3) + x*3 + 1] = thpixels[(thheight-1-y)*(thwidth*3) + x*3 + 1]; + thpixels[y*(thwidth*3) + x*3 + 2] = thpixels[(thheight-1-y)*(thwidth*3) + x*3 + 2]; + + thpixels[(thheight-1-y)*(thwidth*3) + x*3 + 0] = save[0]; + thpixels[(thheight-1-y)*(thwidth*3) + x*3 + 1] = save[1]; + thpixels[(thheight-1-y)*(thwidth*3) + x*3 + 2] = save[2]; + } + } + + m_Real.glBindBuffer(eGL_PIXEL_PACK_BUFFER, packBufBind); + m_Real.glBindFramebuffer(eGL_READ_FRAMEBUFFER, prevBuf); + m_Real.glReadBuffer(prevReadBuf); + m_Real.glPixelStorei(eGL_PACK_ROW_LENGTH, prevPackRowLen); + m_Real.glPixelStorei(eGL_PACK_SKIP_ROWS, prevPackSkipRows); + m_Real.glPixelStorei(eGL_PACK_SKIP_PIXELS, prevPackSkipPixels); + m_Real.glPixelStorei(eGL_PACK_ALIGNMENT, prevPackAlignment); } - FetchFrameRecord record; - record.frameInfo.frameNumber = m_FrameCounter+1; - record.frameInfo.captureTime = Timing::GetUnixTimestamp(); - m_FrameRecord.push_back(record); + byte *jpgbuf = NULL; + int len = thwidth*thheight; + + if(len > 0) + { + jpgbuf = new byte[len]; + + jpge::params p; + + p.m_quality = 40; + + bool success = jpge::compress_image_to_jpeg_file_in_memory(jpgbuf, len, thwidth, thheight, 3, thpixels, p); + + if(!success) + { + RDCERR("Failed to compress to jpg"); + SAFE_DELETE_ARRAY(jpgbuf); + thwidth = 0; + thheight = 0; + } + } + + Serialiser *m_pFileSerialiser = RenderDoc::Inst().OpenWriteSerialiser(m_FrameCounter, &m_InitParams, jpgbuf, len, thwidth, thheight); + + { + SCOPED_SERIALISE_CONTEXT(DEVICE_INIT); + + SERIALISE_ELEMENT(ResourceId, immContextId, m_ContextResourceID); + SERIALISE_ELEMENT(ResourceId, vaoId, m_FakeVAOID); + + m_pFileSerialiser->Insert(scope.Get(true)); + } + + RDCDEBUG("Inserting Resource Serialisers"); + + GetResourceManager()->InsertReferencedChunks(m_pFileSerialiser); + + GetResourceManager()->InsertInitialContentsChunks(m_pFileSerialiser); + + RDCDEBUG("Creating Capture Scope"); + + { + SCOPED_SERIALISE_CONTEXT(CAPTURE_SCOPE); + + Serialise_CaptureScope(0); + + m_pFileSerialiser->Insert(scope.Get(true)); + } + + { + RDCDEBUG("Getting Resource Record"); + + GLResourceRecord *record = m_ResourceManager->GetResourceRecord(m_ContextResourceID); + + RDCDEBUG("Accumulating context resource list"); + + map recordlist; + record->Insert(recordlist); + + RDCDEBUG("Flushing %u records to file serialiser", (uint32_t)recordlist.size()); + + for(auto it = recordlist.begin(); it != recordlist.end(); ++it) + m_pFileSerialiser->Insert(it->second); + + RDCDEBUG("Done"); + } + + m_CurFileSize += m_pFileSerialiser->FlushToDisk(); + + RenderDoc::Inst().SuccessfullyWrittenLog(); + + SAFE_DELETE(m_pFileSerialiser); + + m_State = WRITING_IDLE; + + GetResourceManager()->MarkUnwrittenResources(); GetResourceManager()->ClearReferencedResources(); - GetResourceManager()->MarkResourceFrameReferenced(m_DeviceResourceID, eFrameRef_Write); - GetResourceManager()->PrepareInitialContents(); - - AttemptCapture(); - BeginCaptureFrame(); - - if(switchedContext) - MakeContextCurrent(prevctx); - - RDCLOG("Starting capture, frame %u", m_FrameCounter); + return true; + } + //else + { + // failed to capture } } @@ -2273,7 +2402,7 @@ void WrappedOpenGL::Serialise_CaptureScope(uint64_t offset) } } -void WrappedOpenGL::EndCaptureFrame() +void WrappedOpenGL::ContextEndFrame() { SCOPED_SERIALISE_CONTEXT(CONTEXT_CAPTURE_FOOTER); @@ -2314,7 +2443,7 @@ void WrappedOpenGL::AttemptCapture() m_DebugMessages.clear(); { - RDCDEBUG("Immediate Context %llu Attempting capture", GetContextResourceID()); + RDCDEBUG("GL Context %llu Attempting capture", GetContextResourceID()); //m_SuccessfulCapture = true; diff --git a/renderdoc/driver/gl/gl_driver.h b/renderdoc/driver/gl/gl_driver.h index 5d794ff65..4cb400c12 100644 --- a/renderdoc/driver/gl/gl_driver.h +++ b/renderdoc/driver/gl/gl_driver.h @@ -61,6 +61,12 @@ struct GLInitParams : public RDCInitParams uint32_t SerialiseVersion; }; +enum CaptureFailReason +{ + CaptureSucceeded = 0, + CaptureFailed_UncappedUnmap, +}; + struct DrawcallTreeNode { DrawcallTreeNode() {} @@ -93,7 +99,7 @@ struct Replacement GLResource res; }; -class WrappedOpenGL +class WrappedOpenGL : public IFrameCapturer { private: const GLHookSet &m_Real; @@ -124,6 +130,7 @@ class WrappedOpenGL // internals Serialiser *m_pSerialiser; LogState m_State; + bool m_AppControlledCapture; GLReplay m_Replay; @@ -311,8 +318,8 @@ class WrappedOpenGL bool Serialise_BeginCaptureFrame(bool applyInitialState); void BeginCaptureFrame(); void FinishCapture(); - void EndCaptureFrame(); - + void ContextEndFrame(); + struct ContextData { ContextData() @@ -333,6 +340,8 @@ class WrappedOpenGL m_ProgramPipeline = m_Program = 0; } + void *ctx; + bool built; bool ready; @@ -340,6 +349,18 @@ class WrappedOpenGL bool attribsCreate; bool isCore; + // map from window handle void* to uint64_t unix timestamp with + // the last time a window was seen/associated with this context. + // Decays after a few seconds since there's no good explicit + // 'remove' type call for GL, only wglCreateContext/wglMakeCurrent + map windows; + + // a window is only associated with one context at once, so any + // time we associate a window, it broadcasts to all other + // contexts to let them know to remove it + void UnassociateWindow(void *wndHandle); + void AssociateWindow(WrappedOpenGL *gl, void *wndHandle); + bool Legacy() { return !attribsCreate || version < 32; } bool Modern() { return !Legacy(); } @@ -445,7 +466,15 @@ class WrappedOpenGL void DeleteContext(void *contextHandle); void ActivateContext(GLWindowingData winData); void WindowSize(void *windowHandle, uint32_t w, uint32_t h); - void Present(void *windowHandle); + void SwapBuffers(void *windowHandle); + + void StartFrameCapture(); + + void EndFrameCapture(); + + + void StartFrameCapture(void *dev, void *wnd); + bool EndFrameCapture(void *dev, void *wnd); IMPLEMENT_FUNCTION_SERIALISED(void, glBindTexture(GLenum target, GLuint texture)); IMPLEMENT_FUNCTION_SERIALISED(void, glBindTextures(GLuint first, GLsizei count, const GLuint *textures)); diff --git a/renderdoc/driver/gl/wrappers/gl_debug_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_debug_funcs.cpp index 2aa3d99af..22200efa8 100644 --- a/renderdoc/driver/gl/wrappers/gl_debug_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_debug_funcs.cpp @@ -202,7 +202,7 @@ void WrappedOpenGL::glInsertEventMarkerEXT(GLsizei length, const GLchar *marker) void WrappedOpenGL::glFrameTerminatorGREMEDY() { - Present(NULL); + SwapBuffers(NULL); } void WrappedOpenGL::glStringMarkerGREMEDY(GLsizei len, const void *string) diff --git a/renderdoc/hooks/gl_win32_hooks.cpp b/renderdoc/hooks/gl_win32_hooks.cpp index 6fd524a5f..ef4794c29 100644 --- a/renderdoc/hooks/gl_win32_hooks.cpp +++ b/renderdoc/hooks/gl_win32_hooks.cpp @@ -518,7 +518,7 @@ class OpenGLHook : LibraryHook glhooks.GetDriver()->WindowSize(w, r.right-r.left, r.bottom-r.top); - glhooks.GetDriver()->Present(w); + glhooks.GetDriver()->SwapBuffers(w); return glhooks.SwapBuffers_hook()(dc); } diff --git a/renderdoc/replay/entry_points.cpp b/renderdoc/replay/entry_points.cpp index efdc651b0..cbb3d7cef 100644 --- a/renderdoc/replay/entry_points.cpp +++ b/renderdoc/replay/entry_points.cpp @@ -246,9 +246,9 @@ uint32_t RENDERDOC_CC RENDERDOC_InjectIntoProcess(uint32_t pid, const char *logf } extern "C" RENDERDOC_API -void RENDERDOC_CC RENDERDOC_SetActiveWindow(void *wndHandle) +void RENDERDOC_CC RENDERDOC_SetActiveWindow(void *device, void *wndHandle) { - RenderDoc::Inst().SetActiveWindow(wndHandle); + RenderDoc::Inst().SetActiveWindow(device, wndHandle); } extern "C" RENDERDOC_API @@ -258,15 +258,15 @@ void RENDERDOC_CC RENDERDOC_TriggerCapture() } extern "C" RENDERDOC_API -void RENDERDOC_CC RENDERDOC_StartFrameCapture(void *wndHandle) +void RENDERDOC_CC RENDERDOC_StartFrameCapture(void *device, void *wndHandle) { - RenderDoc::Inst().StartFrameCapture(wndHandle); + RenderDoc::Inst().StartFrameCapture(device, wndHandle); } extern "C" RENDERDOC_API -bool32 RENDERDOC_CC RENDERDOC_EndFrameCapture(void *wndHandle) +bool32 RENDERDOC_CC RENDERDOC_EndFrameCapture(void *device, void *wndHandle) { - return RenderDoc::Inst().EndFrameCapture(wndHandle); + return RenderDoc::Inst().EndFrameCapture(device, wndHandle); } extern "C" RENDERDOC_API