mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-13 05:20:45 +00:00
Tweak how device/window handles work with NULL, to now wildcard match
* This makes it a bit easier to specify what you want to capture without requiring redundant information.
This commit is contained in:
@@ -244,11 +244,26 @@ typedef uint32_t (RENDERDOC_CC *pRENDERDOC_GetCapture)(uint32_t idx, char *logfi
|
||||
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_TriggerCapture();
|
||||
typedef void (RENDERDOC_CC *pRENDERDOC_TriggerCapture)();
|
||||
|
||||
// In the below functions 'device pointer' corresponds to the API specific handle, e.g.
|
||||
// ID3D11Device, or the GL context pointer.
|
||||
// The 'window handle' is the OS's native window handle (HWND or GLXDrawable).
|
||||
|
||||
// This must match precisely to a pair, and it sets the RenderDoc in-app overlay to select that
|
||||
// window as 'active' and respond to keypresses.
|
||||
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)();
|
||||
// Either parameter can be NULL to wild-card match, such that you can capture from any
|
||||
// device to a particular window, or a particular device to any window.
|
||||
// In either case, if there are two or more possible matching (device,window) pairs it
|
||||
// is undefined which one will be captured.
|
||||
// You can pass (NULL, NULL) if you know you only have one device and one window, and
|
||||
// it will match. Likewise if you have not created a window at all (only off-screen
|
||||
// rendering), then NULL window pointer will capture, whether you pass a NULL device
|
||||
// or specify a device among multiple.
|
||||
|
||||
extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_StartFrameCapture(void *device, void *wndHandle);
|
||||
typedef void (RENDERDOC_CC *pRENDERDOC_StartFrameCapture)(void *device, void *wndHandle);
|
||||
|
||||
+62
-63
@@ -30,6 +30,8 @@
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "data/version.h"
|
||||
#include "crash_handler.h"
|
||||
|
||||
@@ -310,39 +312,51 @@ void RenderDoc::Shutdown()
|
||||
}
|
||||
}
|
||||
|
||||
void RenderDoc::StartFrameCapture(void *dev, void *wnd)
|
||||
IFrameCapturer *RenderDoc::MatchFrameCapturer(void *dev, void *wnd)
|
||||
{
|
||||
if(dev == NULL || wnd == NULL)
|
||||
{
|
||||
// if we have a single window frame capturer, use that in preference
|
||||
if(m_WindowFrameCapturers.size() == 1)
|
||||
{
|
||||
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 handles");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
DeviceWnd dw(dev, wnd);
|
||||
|
||||
auto it = m_WindowFrameCapturers.find(dw);
|
||||
if(it == m_WindowFrameCapturers.end())
|
||||
// lower_bound and the DeviceWnd ordering (pointer compares, dev over wnd) means that if either
|
||||
// element in dw is NULL we can go forward from this iterator and find the first wildcardMatch
|
||||
// note that if dev is specified and wnd is NULL, this will actually point at the first
|
||||
// wildcardMatch already and we can use it immediately (since which window of multiple we
|
||||
// choose is undefined, so up to us). If dev is NULL there is no window ordering (since dev is
|
||||
// the primary sorting value) so we just iterate through the whole map. It should be small in
|
||||
// the majority of cases
|
||||
auto it = m_WindowFrameCapturers.lower_bound(dw);
|
||||
|
||||
while(it != m_WindowFrameCapturers.end())
|
||||
{
|
||||
RDCERR("Couldn't find frame capturer for device %p window %p", dev, wnd);
|
||||
return;
|
||||
if(it->first.wildcardMatch(dw)) break;
|
||||
++it;
|
||||
}
|
||||
|
||||
it->second.FrameCapturer->StartFrameCapture(dev, wnd);
|
||||
if(it == m_WindowFrameCapturers.end())
|
||||
{
|
||||
// handle off-screen rendering where there are no device/window pairs in
|
||||
// m_WindowFrameCapturers, instead we use the first matching device frame capturer
|
||||
if(wnd == NULL)
|
||||
{
|
||||
auto defaultit = m_DeviceFrameCapturers.find(dev);
|
||||
if(defaultit == m_DeviceFrameCapturers.end() && !m_DeviceFrameCapturers.empty())
|
||||
defaultit = m_DeviceFrameCapturers.begin();
|
||||
|
||||
if(defaultit != m_DeviceFrameCapturers.end())
|
||||
return defaultit->second;
|
||||
}
|
||||
|
||||
RDCERR("Couldn't find matching frame capturer for device %p window %p", dev, wnd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return it->second.FrameCapturer;
|
||||
}
|
||||
|
||||
void RenderDoc::StartFrameCapture(void *dev, void *wnd)
|
||||
{
|
||||
IFrameCapturer *frameCap = MatchFrameCapturer(dev, wnd);
|
||||
if(frameCap)
|
||||
frameCap->StartFrameCapture(dev, wnd);
|
||||
}
|
||||
|
||||
void RenderDoc::SetActiveWindow(void *dev, void *wnd)
|
||||
@@ -361,37 +375,10 @@ void RenderDoc::SetActiveWindow(void *dev, void *wnd)
|
||||
|
||||
bool RenderDoc::EndFrameCapture(void *dev, void *wnd)
|
||||
{
|
||||
if(dev == NULL || wnd == NULL)
|
||||
{
|
||||
// if we have a single window frame capturer, use that in preference
|
||||
if(m_WindowFrameCapturers.size() == 1)
|
||||
{
|
||||
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 handles");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
DeviceWnd dw(dev, wnd);
|
||||
|
||||
auto it = m_WindowFrameCapturers.find(dw);
|
||||
if(it == m_WindowFrameCapturers.end())
|
||||
{
|
||||
RDCERR("Couldn't find frame capturer for device %p, window %p", dev, wnd);
|
||||
return false;
|
||||
}
|
||||
|
||||
return it->second.FrameCapturer->EndFrameCapture(dev, wnd);
|
||||
IFrameCapturer *frameCap = MatchFrameCapturer(dev, wnd);
|
||||
if(frameCap)
|
||||
return frameCap->EndFrameCapture(dev, wnd);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RenderDoc::IsRemoteAccessConnected()
|
||||
@@ -779,14 +766,26 @@ void RenderDoc::SuccessfullyWrittenLog()
|
||||
}
|
||||
}
|
||||
|
||||
void RenderDoc::AddDefaultFrameCapturer(IFrameCapturer *cap)
|
||||
void RenderDoc::AddDeviceFrameCapturer(void *dev, IFrameCapturer *cap)
|
||||
{
|
||||
m_DefaultFrameCapturers.insert(cap);
|
||||
if(dev == NULL || cap == NULL)
|
||||
{
|
||||
RDCERR("Invalid FrameCapturer combination: %#p / %#p", dev, cap);
|
||||
return;
|
||||
}
|
||||
|
||||
m_DeviceFrameCapturers[dev] = cap;
|
||||
}
|
||||
|
||||
void RenderDoc::RemoveDefaultFrameCapturer(IFrameCapturer *cap)
|
||||
void RenderDoc::RemoveDeviceFrameCapturer(void *dev)
|
||||
{
|
||||
m_DefaultFrameCapturers.erase(cap);
|
||||
if(dev == NULL)
|
||||
{
|
||||
RDCERR("Invalid device pointer: %#p / %#p", dev);
|
||||
return;
|
||||
}
|
||||
|
||||
m_DeviceFrameCapturers.erase(dev);
|
||||
}
|
||||
|
||||
void RenderDoc::AddFrameCapturer(void *dev, void *wnd, IFrameCapturer *cap)
|
||||
@@ -803,7 +802,7 @@ void RenderDoc::AddFrameCapturer(void *dev, void *wnd, IFrameCapturer *cap)
|
||||
if(it != m_WindowFrameCapturers.end())
|
||||
{
|
||||
if(it->second.FrameCapturer != cap)
|
||||
RDCERR("New different FrameCapturer being registered for known window!");
|
||||
RDCERR("New different FrameCapturer being registered for known device/window pair!");
|
||||
|
||||
it->second.RefCount++;
|
||||
}
|
||||
|
||||
+17
-3
@@ -241,8 +241,8 @@ class RenderDoc
|
||||
|
||||
// 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 AddDeviceFrameCapturer(void *dev, IFrameCapturer *cap);
|
||||
void RemoveDeviceFrameCapturer(void *dev);
|
||||
|
||||
void StartFrameCapture(void *dev, void *wnd);
|
||||
void SetActiveWindow(void *dev, void *wnd);
|
||||
@@ -334,16 +334,30 @@ class RenderDoc
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
bool wildcardMatch(const DeviceWnd &o) const
|
||||
{
|
||||
if(dev == NULL || o.dev == NULL)
|
||||
return wnd == NULL || o.wnd == NULL || wnd == o.wnd;
|
||||
|
||||
if(wnd == NULL || o.wnd == NULL)
|
||||
return dev == NULL || o.dev == NULL || dev == o.dev;
|
||||
|
||||
return *this == o;
|
||||
}
|
||||
};
|
||||
|
||||
map<DeviceWnd, FrameCap> m_WindowFrameCapturers;
|
||||
DeviceWnd m_ActiveWindow;
|
||||
set<IFrameCapturer *> m_DefaultFrameCapturers;
|
||||
map<void *, IFrameCapturer *> m_DeviceFrameCapturers;
|
||||
|
||||
IFrameCapturer *MatchFrameCapturer(void *dev, void *wnd);
|
||||
|
||||
volatile bool m_RemoteServerThreadShutdown;
|
||||
volatile bool m_RemoteClientThreadShutdown;
|
||||
|
||||
@@ -342,7 +342,7 @@ WrappedID3D11Device::WrappedID3D11Device(ID3D11Device* realDevice, D3D11InitPara
|
||||
m_DeviceRecord->NumSubResources = 0;
|
||||
m_DeviceRecord->SubResources = NULL;
|
||||
|
||||
RenderDoc::Inst().AddDefaultFrameCapturer(this);
|
||||
RenderDoc::Inst().AddDeviceFrameCapturer((ID3D11Device *)this, this);
|
||||
}
|
||||
|
||||
ID3D11DeviceContext *context = NULL;
|
||||
@@ -416,7 +416,7 @@ WrappedID3D11Device::~WrappedID3D11Device()
|
||||
if(m_pCurrentWrappedDevice == this)
|
||||
m_pCurrentWrappedDevice = NULL;
|
||||
|
||||
RenderDoc::Inst().RemoveDefaultFrameCapturer(this);
|
||||
RenderDoc::Inst().RemoveDeviceFrameCapturer((ID3D11Device *)this);
|
||||
|
||||
for(auto it = m_CachedStateObjects.begin(); it != m_CachedStateObjects.end(); ++it)
|
||||
if(*it)
|
||||
|
||||
@@ -760,8 +760,6 @@ 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
|
||||
{
|
||||
@@ -909,8 +907,6 @@ 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);
|
||||
@@ -962,6 +958,8 @@ void WrappedOpenGL::DeleteContext(void *contextHandle)
|
||||
{
|
||||
ContextData &ctxdata = m_ContextData[contextHandle];
|
||||
|
||||
RenderDoc::Inst().RemoveDeviceFrameCapturer(ctxdata.ctx);
|
||||
|
||||
if(ctxdata.built && ctxdata.ready)
|
||||
{
|
||||
if(ctxdata.Program)
|
||||
@@ -1007,6 +1005,8 @@ void WrappedOpenGL::CreateContext(GLWindowingData winData, void *shareContext, G
|
||||
ctxdata.ctx = winData.ctx;
|
||||
ctxdata.isCore = core;
|
||||
ctxdata.attribsCreate = attribsCreate;
|
||||
|
||||
RenderDoc::Inst().AddDeviceFrameCapturer(ctxdata.ctx, this);
|
||||
}
|
||||
|
||||
void WrappedOpenGL::RegisterContext(GLWindowingData winData, void *shareContext, bool core, bool attribsCreate)
|
||||
@@ -2186,7 +2186,7 @@ void WrappedOpenGL::SwapBuffers(void *windowHandle)
|
||||
|
||||
// kill any current capture that isn't application defined
|
||||
if(m_State == WRITING_CAPFRAME && !m_AppControlledCapture)
|
||||
EndFrameCapture(this, windowHandle);
|
||||
EndFrameCapture(ctxdata.ctx, windowHandle);
|
||||
|
||||
// for now, only allow one captured frame at all
|
||||
if(!m_FrameRecord.empty())
|
||||
@@ -2194,7 +2194,7 @@ void WrappedOpenGL::SwapBuffers(void *windowHandle)
|
||||
|
||||
if(RenderDoc::Inst().ShouldTriggerCapture(m_FrameCounter) && m_State == WRITING_IDLE)
|
||||
{
|
||||
StartFrameCapture(this, windowHandle);
|
||||
StartFrameCapture(ctxdata.ctx, windowHandle);
|
||||
|
||||
m_AppControlledCapture = false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user