/****************************************************************************** * The MIT License (MIT) * * Copyright (c) 2017-2026 Baldur Karlsson * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. ******************************************************************************/ #include "Code/pyrenderdoc/PythonContext.h" #include "Windows/PythonShell.h" // a forwarder that invokes onto the UI thread wherever necessary. // Note this does NOT make CaptureContext thread safe. We just invoke for any potentially UI // operations. All invokes are blocking, so there can't be any times when the UI thread waits // on the python thread. template struct UIThreadInvoker : Obj { UIThreadInvoker(PythonShell *sh, Obj &o) : m_Shell(sh), m_Obj(o) {} virtual ~UIThreadInvoker() {} PythonShell *m_Shell; Obj &m_Obj; template void InvokeVoidFunction(F ptr, paramTypes... params) { if(!GUIInvoke::onUIThread()) { PythonContext *scriptContext = m_Shell->GetScriptContext(); if(scriptContext) scriptContext->PausePythonThreading(); GUIInvoke::blockcall(m_Shell, [this, ptr, params...]() { (m_Obj.*ptr)(params...); }); if(scriptContext) scriptContext->ResumePythonThreading(); return; } (m_Obj.*ptr)(params...); } template R InvokeRetFunction(F ptr, paramTypes... params) { if(!GUIInvoke::onUIThread()) { R ret; PythonContext *scriptContext = m_Shell->GetScriptContext(); if(scriptContext) scriptContext->PausePythonThreading(); GUIInvoke::blockcall(m_Shell, [this, &ret, ptr, params...]() { ret = (m_Obj.*ptr)(params...); }); if(scriptContext) scriptContext->ResumePythonThreading(); return ret; } return (m_Obj.*ptr)(params...); } }; struct MiniQtInvoker : UIThreadInvoker { MiniQtInvoker(PythonShell *shell, IMiniQtHelper &obj) : UIThreadInvoker(shell, obj) {} virtual ~MiniQtInvoker() {} void InvokeOntoUIThread(std::function callback) { // this function is already thread safe since it's invoking, so just call it directly m_Obj.InvokeOntoUIThread(callback); } /////////////////////////////////////////////////////////////////////// // all functions invoke onto the UI thread since they deal with widgets! /////////////////////////////////////////////////////////////////////// QWidget *CreateToplevelWidget(const rdcstr &windowTitle, WidgetCallback closed) { return InvokeRetFunction(&IMiniQtHelper::CreateToplevelWidget, windowTitle, closed); } void CloseToplevelWidget(QWidget *widget) { InvokeVoidFunction(&IMiniQtHelper::CloseToplevelWidget, widget); } // widget hierarchy void SetWidgetName(QWidget *widget, const rdcstr &name) { InvokeVoidFunction(&IMiniQtHelper::SetWidgetName, widget, name); } rdcstr GetWidgetName(QWidget *widget) { return InvokeRetFunction(&IMiniQtHelper::GetWidgetName, widget); } rdcstr GetWidgetType(QWidget *widget) { return InvokeRetFunction(&IMiniQtHelper::GetWidgetType, widget); } QWidget *FindChildByName(QWidget *parent, const rdcstr &name) { return InvokeRetFunction(&IMiniQtHelper::FindChildByName, parent, name); } QWidget *GetParent(QWidget *widget) { return InvokeRetFunction(&IMiniQtHelper::GetParent, widget); } int32_t GetNumChildren(QWidget *widget) { return InvokeRetFunction(&IMiniQtHelper::GetNumChildren, widget); } QWidget *GetChild(QWidget *parent, int32_t index) { return InvokeRetFunction(&IMiniQtHelper::GetChild, parent, index); } void DestroyWidget(QWidget *widget) { InvokeVoidFunction(&IMiniQtHelper::DestroyWidget, widget); } // dialogs bool ShowWidgetAsDialog(QWidget *widget) { return InvokeRetFunction(&IMiniQtHelper::ShowWidgetAsDialog, widget); } void CloseCurrentDialog(bool success) { InvokeVoidFunction(&IMiniQtHelper::CloseCurrentDialog, success); } // layout functions QWidget *CreateHorizontalContainer() { return InvokeRetFunction(&IMiniQtHelper::CreateHorizontalContainer); } QWidget *CreateVerticalContainer() { return InvokeRetFunction(&IMiniQtHelper::CreateVerticalContainer); } QWidget *CreateGridContainer() { return InvokeRetFunction(&IMiniQtHelper::CreateGridContainer); } QWidget *CreateSpacer(bool horizontal) { return InvokeRetFunction(&IMiniQtHelper::CreateSpacer, horizontal); } void ClearContainedWidgets(QWidget *parent) { InvokeVoidFunction(&IMiniQtHelper::ClearContainedWidgets, parent); } void AddGridWidget(QWidget *parent, int32_t row, int32_t column, QWidget *child, int32_t rowSpan, int32_t columnSpan) { InvokeVoidFunction(&IMiniQtHelper::AddGridWidget, parent, row, column, child, rowSpan, columnSpan); } void AddWidget(QWidget *parent, QWidget *child) { InvokeVoidFunction(&IMiniQtHelper::AddWidget, parent, child); } void InsertWidget(QWidget *parent, int32_t index, QWidget *child) { InvokeVoidFunction(&IMiniQtHelper::InsertWidget, parent, index, child); } // widget manipulation void SetWidgetText(QWidget *widget, const rdcstr &text) { InvokeVoidFunction(&IMiniQtHelper::SetWidgetText, widget, text); } rdcstr GetWidgetText(QWidget *widget) { return InvokeRetFunction(&IMiniQtHelper::GetWidgetText, widget); } void SetWidgetFont(QWidget *widget, const rdcstr &font, int32_t fontSize, bool bold, bool italic) { InvokeVoidFunction(&IMiniQtHelper::SetWidgetFont, widget, font, fontSize, bold, italic); } void SetWidgetEnabled(QWidget *widget, bool enabled) { InvokeVoidFunction(&IMiniQtHelper::SetWidgetEnabled, widget, enabled); } bool IsWidgetEnabled(QWidget *widget) { return InvokeRetFunction(&IMiniQtHelper::IsWidgetEnabled, widget); } void SetWidgetVisible(QWidget *widget, bool visible) { InvokeVoidFunction(&IMiniQtHelper::SetWidgetVisible, widget, visible); } bool IsWidgetVisible(QWidget *widget) { return InvokeRetFunction(&IMiniQtHelper::IsWidgetVisible, widget); } // specific widgets QWidget *CreateGroupBox(bool collapsible) { return InvokeRetFunction(&IMiniQtHelper::CreateGroupBox, collapsible); } QWidget *CreateButton(WidgetCallback pressed) { return InvokeRetFunction(&IMiniQtHelper::CreateButton, pressed); } QWidget *CreateLabel() { return InvokeRetFunction(&IMiniQtHelper::CreateLabel); } void SetLabelImage(QWidget *widget, const bytebuf &data, int32_t width, int32_t height, bool alpha) { InvokeVoidFunction(&IMiniQtHelper::SetLabelImage, widget, data, width, height, alpha); } QWidget *CreateOutputRenderingWidget() { return InvokeRetFunction(&IMiniQtHelper::CreateOutputRenderingWidget); } WindowingData GetWidgetWindowingData(QWidget *widget) { return InvokeRetFunction(&IMiniQtHelper::GetWidgetWindowingData, widget); } void SetWidgetReplayOutput(QWidget *widget, IReplayOutput *output) { InvokeVoidFunction(&IMiniQtHelper::SetWidgetReplayOutput, widget, output); } void SetWidgetBackgroundColor(QWidget *widget, float red, float green, float blue) { InvokeVoidFunction(&IMiniQtHelper::SetWidgetBackgroundColor, widget, red, green, blue); } QWidget *CreateCheckbox(WidgetCallback changed) { return InvokeRetFunction(&IMiniQtHelper::CreateCheckbox, changed); } QWidget *CreateRadiobox(WidgetCallback changed) { return InvokeRetFunction(&IMiniQtHelper::CreateRadiobox, changed); } void SetWidgetChecked(QWidget *checkableWidget, bool checked) { InvokeVoidFunction(&IMiniQtHelper::SetWidgetChecked, checkableWidget, checked); } bool IsWidgetChecked(QWidget *checkableWidget) { return InvokeRetFunction(&IMiniQtHelper::IsWidgetChecked, checkableWidget); } QWidget *CreateSpinbox(int32_t decimalPlaces, double step) { return InvokeRetFunction(&IMiniQtHelper::CreateSpinbox, decimalPlaces, step); } void SetSpinboxBounds(QWidget *spinbox, double minVal, double maxVal) { InvokeVoidFunction(&IMiniQtHelper::SetSpinboxBounds, spinbox, minVal, maxVal); } void SetSpinboxValue(QWidget *spinbox, double value) { InvokeVoidFunction(&IMiniQtHelper::SetSpinboxValue, spinbox, value); } double GetSpinboxValue(QWidget *spinbox) { return InvokeRetFunction(&IMiniQtHelper::GetSpinboxValue, spinbox); } QWidget *CreateTextBox(bool singleLine, WidgetCallback changed) { return InvokeRetFunction(&IMiniQtHelper::CreateTextBox, singleLine, changed); } QWidget *CreateComboBox(bool editable, WidgetCallback changed) { return InvokeRetFunction(&IMiniQtHelper::CreateComboBox, editable, changed); } void SetComboOptions(QWidget *combo, const rdcarray &options) { InvokeVoidFunction(&IMiniQtHelper::SetComboOptions, combo, options); } size_t GetComboCount(QWidget *combo) { return InvokeRetFunction(&IMiniQtHelper::GetComboCount, combo); } void SelectComboOption(QWidget *combo, const rdcstr &option) { InvokeVoidFunction(&IMiniQtHelper::SelectComboOption, combo, option); } QWidget *CreateProgressBar(bool horizontal) { return InvokeRetFunction(&IMiniQtHelper::CreateProgressBar, horizontal); } void ResetProgressBar(QWidget *pbar) { InvokeVoidFunction(&IMiniQtHelper::ResetProgressBar, pbar); } void SetProgressBarValue(QWidget *pbar, int32_t value) { InvokeVoidFunction(&IMiniQtHelper::SetProgressBarValue, pbar, value); } void UpdateProgressBarValue(QWidget *pbar, int32_t delta) { InvokeVoidFunction(&IMiniQtHelper::UpdateProgressBarValue, pbar, delta); } int32_t GetProgressBarValue(QWidget *pbar) { return InvokeRetFunction(&IMiniQtHelper::GetProgressBarValue, pbar); } void SetProgressBarRange(QWidget *pbar, int32_t minimum, int32_t maximum) { InvokeVoidFunction(&IMiniQtHelper::SetProgressBarRange, pbar, minimum, maximum); } int32_t GetProgressBarMinimum(QWidget *pbar) { return InvokeRetFunction(&IMiniQtHelper::GetProgressBarMinimum, pbar); } int32_t GetProgressBarMaximum(QWidget *pbar) { return InvokeRetFunction(&IMiniQtHelper::GetProgressBarMaximum, pbar); } }; struct ExtensionInvoker : UIThreadInvoker { MiniQtInvoker *m_MiniQt; ExtensionInvoker(PythonShell *shell, IExtensionManager &obj) : UIThreadInvoker(shell, obj) { m_MiniQt = new MiniQtInvoker(shell, obj.GetMiniQtHelper()); } virtual ~ExtensionInvoker() { delete m_MiniQt; } // /////////////////////////////////////////////////////////////////////// // pass-through functions that don't need the UI thread /////////////////////////////////////////////////////////////////////// // rdcarray GetInstalledExtensions() { return m_Obj.GetInstalledExtensions(); } rdcarray GetLoadedExtensions() { return m_Obj.GetLoadedExtensions(); } bool IsExtensionLoaded(rdcstr name) { return m_Obj.IsExtensionLoaded(name); } rdcstr LoadExtension(rdcstr name) { return m_Obj.LoadExtension(name); } bool IsPythonDebuggerConnected() { return m_Obj.IsPythonDebuggerConnected(); } IMiniQtHelper &GetMiniQtHelper() { return *m_MiniQt; } // /////////////////////////////////////////////////////////////////////// // functions that invoke onto the UI thread /////////////////////////////////////////////////////////////////////// // void RegisterWindowMenu(WindowMenu base, const rdcarray &submenus, ExtensionCallback callback) { InvokeVoidFunction(&IExtensionManager::RegisterWindowMenu, base, submenus, callback); } void RegisterPanelMenu(PanelMenu base, const rdcarray &submenus, ExtensionCallback callback) { InvokeVoidFunction(&IExtensionManager::RegisterPanelMenu, base, submenus, callback); } void RegisterContextMenu(ContextMenu base, const rdcarray &submenus, ExtensionCallback callback) { InvokeVoidFunction(&IExtensionManager::RegisterContextMenu, base, submenus, callback); } void MessageDialog(const rdcstr &text, const rdcstr &title) { InvokeVoidFunction(&IExtensionManager::MessageDialog, text, title); } void ErrorDialog(const rdcstr &text, const rdcstr &title) { InvokeVoidFunction(&IExtensionManager::ErrorDialog, text, title); } DialogButton QuestionDialog(const rdcstr &text, const rdcarray &options, const rdcstr &title) { return InvokeRetFunction(&IExtensionManager::QuestionDialog, text, options, title); } rdcstr OpenFileName(const rdcstr &caption, const rdcstr &dir, const rdcstr &filter) { return InvokeRetFunction(&IExtensionManager::OpenFileName, caption, dir, filter); } rdcstr OpenDirectoryName(const rdcstr &caption, const rdcstr &dir) { return InvokeRetFunction(&IExtensionManager::OpenDirectoryName, caption, dir); } rdcstr SaveFileName(const rdcstr &caption, const rdcstr &dir, const rdcstr &filter) { return InvokeRetFunction(&IExtensionManager::SaveFileName, caption, dir, filter); } void MenuDisplaying(ContextMenu contextMenu, QMenu *menu, const ExtensionCallbackData &data) { InvokeVoidFunction( (void(IExtensionManager::*)(ContextMenu, QMenu *, const ExtensionCallbackData &)) & IExtensionManager::MenuDisplaying, contextMenu, menu, data); } void MenuDisplaying(PanelMenu panelMenu, QMenu *menu, QWidget *extensionButton, const ExtensionCallbackData &data) { InvokeVoidFunction( (void(IExtensionManager::*)(PanelMenu, QMenu *, QWidget *, const ExtensionCallbackData &)) & IExtensionManager::MenuDisplaying, panelMenu, menu, extensionButton, data); } }; struct ReplayControllerInvoker : IReplayController { ReplayControllerInvoker(PythonShell *shell, ICaptureContext &ctx) : m_Shell(shell), m_Ctx(ctx) {} virtual ~ReplayControllerInvoker() {} PythonShell *m_Shell; ICaptureContext &m_Ctx; template void InvokeVoidFunction(F ptr, paramTypes... params) { PythonContext *scriptContext = m_Shell->GetScriptContext(); if(scriptContext) scriptContext->PausePythonThreading(); m_Ctx.Replay().BlockInvoke( [ptr, params...](IReplayController *replay) { (replay->*ptr)(params...); }); if(scriptContext) scriptContext->ResumePythonThreading(); } template R InvokeRetFunction(F ptr, paramTypes... params) { R ret = R(); PythonContext *scriptContext = m_Shell->GetScriptContext(); if(scriptContext) scriptContext->PausePythonThreading(); m_Ctx.Replay().BlockInvoke( [&ret, ptr, params...](IReplayController *replay) { ret = (replay->*ptr)(params...); }); if(scriptContext) scriptContext->ResumePythonThreading(); return ret; } template R &InvokeRetRefFunction(F ptr, paramTypes... params) { R *ret = NULL; PythonContext *scriptContext = m_Shell->GetScriptContext(); if(scriptContext) scriptContext->PausePythonThreading(); m_Ctx.Replay().BlockInvoke( [&ret, ptr, params...](IReplayController *replay) { ret = &(replay->*ptr)(params...); }); if(scriptContext) scriptContext->ResumePythonThreading(); return *ret; } APIProperties GetAPIProperties() { return InvokeRetFunction(&IReplayController::GetAPIProperties); } rdcarray GetSupportedWindowSystems() { return InvokeRetFunction>(&IReplayController::GetSupportedWindowSystems); } IReplayOutput *CreateOutput(WindowingData window, ReplayOutputType type) { return InvokeRetFunction(&IReplayController::CreateOutput, window, type); } void Shutdown() {} void ReplayLoop(WindowingData window, ResourceId texid) {} rdcstr CreateRGPProfile(WindowingData window) { return InvokeRetFunction(&IReplayController::CreateRGPProfile, window); } void CancelReplayLoop() {} void FileChanged() {} void SetFrameEvent(uint32_t eventId, bool force) {} const D3D11Pipe::State *GetD3D11PipelineState() { return InvokeRetFunction(&IReplayController::GetD3D11PipelineState); } const D3D12Pipe::State *GetD3D12PipelineState() { return InvokeRetFunction(&IReplayController::GetD3D12PipelineState); } const GLPipe::State *GetGLPipelineState() { return InvokeRetFunction(&IReplayController::GetGLPipelineState); } const VKPipe::State *GetVulkanPipelineState() { return InvokeRetFunction(&IReplayController::GetVulkanPipelineState); } const PipeState &GetPipelineState() { return InvokeRetRefFunction(&IReplayController::GetPipelineState); } rdcarray GetDescriptors(ResourceId descriptorStore, const rdcarray &ranges) { return InvokeRetFunction>(&IReplayController::GetDescriptors, descriptorStore, ranges); } rdcarray GetSamplerDescriptors(ResourceId descriptorStore, const rdcarray &ranges) { return InvokeRetFunction>(&IReplayController::GetSamplerDescriptors, descriptorStore, ranges); } const rdcarray &GetDescriptorAccess() { return InvokeRetRefFunction>( &IReplayController::GetDescriptorAccess); } rdcarray GetDescriptorLocations(ResourceId descriptorStore, const rdcarray &ranges) { return InvokeRetFunction>( &IReplayController::GetDescriptorLocations, descriptorStore, ranges); } rdcarray GetDisassemblyTargets(bool withPipeline) { return InvokeRetFunction>(&IReplayController::GetDisassemblyTargets, withPipeline); } rdcstr DisassembleShader(ResourceId pipeline, const ShaderReflection *refl, const rdcstr &target) { return InvokeRetFunction(&IReplayController::DisassembleShader, pipeline, refl, target); } void SetCustomShaderIncludes(const rdcarray &directories) {} rdcpair BuildCustomShader(const rdcstr &entry, ShaderEncoding sourceEncoding, bytebuf source, const ShaderCompileFlags &compileFlags, ShaderStage type) { return InvokeRetFunction>( &IReplayController::BuildCustomShader, entry, sourceEncoding, source, compileFlags, type); } void FreeCustomShader(ResourceId id) {} rdcpair BuildTargetShader(const rdcstr &entry, ShaderEncoding sourceEncoding, bytebuf source, const ShaderCompileFlags &compileFlags, ShaderStage type) { return InvokeRetFunction>( &IReplayController::BuildTargetShader, entry, sourceEncoding, source, compileFlags, type); } rdcarray GetTargetShaderEncodings() { return InvokeRetFunction>(&IReplayController::GetTargetShaderEncodings); } rdcarray GetCustomShaderEncodings() { return InvokeRetFunction>(&IReplayController::GetCustomShaderEncodings); } rdcarray GetCustomShaderSourcePrefixes() { return InvokeRetFunction>( &IReplayController::GetCustomShaderSourcePrefixes); } void ReplaceResource(ResourceId original, ResourceId replacement) {} void ClearReplayCache() {} void ReloadShaderDebugInformation() {} void RemoveReplacement(ResourceId id) {} void FreeTargetResource(ResourceId id) {} FrameDescription GetFrameInfo() { return InvokeRetFunction(&IReplayController::GetFrameInfo); } const SDFile &GetStructuredFile() { return InvokeRetRefFunction(&IReplayController::GetStructuredFile); } void AddFakeMarkers() {} const rdcarray &GetRootActions() { return InvokeRetRefFunction>(&IReplayController::GetRootActions); } rdcarray FetchCounters(const rdcarray &counters) { return InvokeRetFunction>(&IReplayController::FetchCounters, counters); } rdcarray EnumerateCounters() { return InvokeRetFunction>(&IReplayController::EnumerateCounters); } CounterDescription DescribeCounter(GPUCounter counter) { return InvokeRetFunction(&IReplayController::DescribeCounter, counter); } const rdcarray &GetResources() { return InvokeRetRefFunction>(&IReplayController::GetResources); } const rdcarray &GetTextures() { return InvokeRetRefFunction>(&IReplayController::GetTextures); } const rdcarray &GetBuffers() { return InvokeRetRefFunction>(&IReplayController::GetBuffers); } const rdcarray &GetDescriptorStores() { return InvokeRetRefFunction>( &IReplayController::GetDescriptorStores); } rdcarray GetDebugMessages() { return InvokeRetFunction>(&IReplayController::GetDebugMessages); } ResultDetails GetFatalErrorStatus() { return InvokeRetFunction(&IReplayController::GetFatalErrorStatus); } rdcarray GetShaderEntryPoints(ResourceId shader) { return InvokeRetFunction>(&IReplayController::GetShaderEntryPoints, shader); } const ShaderReflection *GetShader(ResourceId pipeline, ResourceId shader, ShaderEntryPoint entry) { return InvokeRetFunction(&IReplayController::GetShader, pipeline, shader, entry); } PixelValue PickPixel(ResourceId textureId, uint32_t x, uint32_t y, const Subresource &sub, CompType typeCast) { return InvokeRetFunction(&IReplayController::PickPixel, textureId, x, y, sub, typeCast); } rdcpair GetMinMax(ResourceId textureId, const Subresource &sub, CompType typeCast) { return InvokeRetFunction>(&IReplayController::GetMinMax, textureId, sub, typeCast); } rdcarray GetHistogram(ResourceId textureId, const Subresource &sub, CompType typeCast, float minval, float maxval, const rdcfixedarray &channels) { return InvokeRetFunction>(&IReplayController::GetHistogram, textureId, sub, typeCast, minval, maxval, channels); } rdcarray PixelHistory(ResourceId texture, uint32_t x, uint32_t y, const Subresource &sub, CompType typeCast) { return InvokeRetFunction>(&IReplayController::PixelHistory, texture, x, y, sub, typeCast); } ShaderDebugTrace *DebugVertex(uint32_t vertid, uint32_t instid, uint32_t idx, uint32_t view) { return InvokeRetFunction(&IReplayController::DebugVertex, vertid, instid, idx, view); } ShaderDebugTrace *DebugPixel(uint32_t x, uint32_t y, const DebugPixelInputs &inputs) { return InvokeRetFunction(&IReplayController::DebugPixel, x, y, inputs); } ShaderDebugTrace *DebugThread(const rdcfixedarray &groupid, const rdcfixedarray &threadid) { return InvokeRetFunction(&IReplayController::DebugThread, groupid, threadid); } ShaderDebugTrace *DebugMeshThread(const rdcfixedarray &groupid, const rdcfixedarray &threadid) { return InvokeRetFunction(&IReplayController::DebugMeshThread, groupid, threadid); } rdcarray ContinueDebug(ShaderDebugger *debugger) { return InvokeRetFunction>(&IReplayController::ContinueDebug, debugger); } void FreeTrace(ShaderDebugTrace *trace) { return InvokeVoidFunction(&IReplayController::FreeTrace, trace); } rdcarray GetUsage(ResourceId id) { return InvokeRetFunction>(&IReplayController::GetUsage, id); } rdcarray GetCBufferVariableContents(ResourceId pipeline, ResourceId shader, ShaderStage stage, const rdcstr &entryPoint, uint32_t cbufslot, ResourceId buffer, uint64_t offset, uint64_t length) { return InvokeRetFunction>( &IReplayController::GetCBufferVariableContents, pipeline, shader, stage, entryPoint, cbufslot, buffer, offset, length); } ResultDetails SaveTexture(const TextureSave &saveData, const rdcstr &path) { return InvokeRetFunction(&IReplayController::SaveTexture, saveData, path); } MeshFormat GetPostVSData(uint32_t instance, uint32_t view, MeshDataStage stage) { return InvokeRetFunction(&IReplayController::GetPostVSData, instance, view, stage); } bytebuf GetBufferData(ResourceId buff, uint64_t offset, uint64_t len) { return InvokeRetFunction(&IReplayController::GetBufferData, buff, offset, len); } bytebuf GetTextureData(ResourceId tex, const Subresource &sub) { return InvokeRetFunction(&IReplayController::GetTextureData, tex, sub); } }; struct IMainWindowInvoker : UIThreadInvoker { IMainWindowInvoker(PythonShell *shell, IMainWindow &obj) : UIThreadInvoker(shell, obj) {} virtual ~IMainWindowInvoker() {} QWidget *Widget() { return m_Obj.Widget(); } void RegisterShortcut(const rdcstr &shortcut, QWidget *widget, ShortcutCallback callback) { return InvokeVoidFunction(&IMainWindow::RegisterShortcut, shortcut, widget, callback); } void UnregisterShortcut(const rdcstr &shortcut, QWidget *widget) { return InvokeVoidFunction(&IMainWindow::UnregisterShortcut, shortcut, widget); } void BringToFront() { return InvokeVoidFunction(&IMainWindow::BringToFront); } }; struct IEventBrowserInvoker : UIThreadInvoker { IEventBrowserInvoker(PythonShell *shell, IEventBrowser &obj) : UIThreadInvoker(shell, obj) {} virtual ~IEventBrowserInvoker() {} QWidget *Widget() { return m_Obj.Widget(); } void UpdateDurationColumn() { return InvokeVoidFunction(&IEventBrowser::UpdateDurationColumn); } APIEvent GetAPIEventForEID(uint32_t eventId) { return InvokeRetFunction(&IEventBrowser::GetAPIEventForEID, eventId); } const ActionDescription *GetActionForEID(uint32_t eventId) { return InvokeRetFunction(&IEventBrowser::GetActionForEID, eventId); } rdcstr GetEventName(uint32_t eventId) { return InvokeRetFunction(&IEventBrowser::GetEventName, eventId); } bool IsAPIEventVisible(uint32_t eventId) { return InvokeRetFunction(&IEventBrowser::IsAPIEventVisible, eventId); } bool RegisterEventFilterFunction(const rdcstr &name, const rdcstr &description, EventFilterCallback filter, FilterParseCallback parser, AutoCompleteCallback completer) { return InvokeRetFunction(&IEventBrowser::RegisterEventFilterFunction, name, description, filter, parser, completer); } bool UnregisterEventFilterFunction(const rdcstr &name) { return InvokeRetFunction(&IEventBrowser::UnregisterEventFilterFunction, name); } void SetCurrentFilterText(const rdcstr &text) { return InvokeVoidFunction(&IEventBrowser::SetCurrentFilterText, text); }; rdcstr GetCurrentFilterText() { return InvokeRetFunction(&IEventBrowser::GetCurrentFilterText); } void SetUseCustomActionNames(bool use) { return InvokeVoidFunction(&IEventBrowser::SetUseCustomActionNames, use); } void SetShowParameterNames(bool show) { return InvokeVoidFunction(&IEventBrowser::SetShowParameterNames, show); } void SetShowAllParameters(bool show) { return InvokeVoidFunction(&IEventBrowser::SetShowAllParameters, show); } void SetEmptyRegionsVisible(bool show) { return InvokeVoidFunction(&IEventBrowser::SetEmptyRegionsVisible, show); } void SetHighlightedAnnotation(const rdcstr &annotationPath) { return InvokeVoidFunction(&IEventBrowser::SetHighlightedAnnotation, annotationPath); } rdcstr GetHighlightedAnnotation() { return InvokeRetFunction(&IEventBrowser::GetHighlightedAnnotation); } void SetDurationColumnVisible(bool show) { return InvokeVoidFunction(&IEventBrowser::SetDurationColumnVisible, show); } void SetAnnotationColumnVisible(bool show) { return InvokeVoidFunction(&IEventBrowser::SetAnnotationColumnVisible, show); } }; struct IAPIInspectorInvoker : UIThreadInvoker { IAPIInspectorInvoker(PythonShell *shell, IAPIInspector &obj) : UIThreadInvoker(shell, obj) {} virtual ~IAPIInspectorInvoker() {} QWidget *Widget() { return m_Obj.Widget(); } virtual void Refresh() { return InvokeVoidFunction(&IAPIInspector::Refresh); } virtual void RevealParameter(SDObject *param) { return InvokeVoidFunction(&IAPIInspector::RevealParameter, param); } }; struct IAnnotationViewerInvoker : UIThreadInvoker { IAnnotationViewerInvoker(PythonShell *shell, IAnnotationViewer &obj) : UIThreadInvoker(shell, obj) { } virtual ~IAnnotationViewerInvoker() {} QWidget *Widget() { return m_Obj.Widget(); } void RevealAnnotation(const rdcstr &keyPath) { return InvokeVoidFunction(&IAnnotationViewer::RevealAnnotation, keyPath); } }; struct ITextureViewerInvoker : UIThreadInvoker { ITextureViewerInvoker(PythonShell *shell, ITextureViewer &obj) : UIThreadInvoker(shell, obj) {} virtual ~ITextureViewerInvoker() {} QWidget *Widget() { return m_Obj.Widget(); } void ViewTexture(ResourceId resourceId, CompType typeCast, bool focus) { return InvokeVoidFunction(&ITextureViewer::ViewTexture, resourceId, typeCast, focus); } void ViewFollowedResource(FollowType followType, ShaderStage stage, int32_t index, int32_t arrayElement) { return InvokeVoidFunction(&ITextureViewer::ViewFollowedResource, followType, stage, index, arrayElement); } ResourceId GetCurrentResource() { return InvokeRetFunction(&ITextureViewer::GetCurrentResource); } Subresource GetSelectedSubresource() { return InvokeRetFunction(&ITextureViewer::GetSelectedSubresource); } void SetSelectedSubresource(Subresource sub) { return InvokeVoidFunction(&ITextureViewer::SetSelectedSubresource, sub); } void GotoLocation(uint32_t x, uint32_t y) { return InvokeVoidFunction(&ITextureViewer::GotoLocation, x, y); } rdcpair GetPickedLocation() { return InvokeRetFunction>(&ITextureViewer::GetPickedLocation); } DebugOverlay GetTextureOverlay() { return InvokeRetFunction(&ITextureViewer::GetTextureOverlay); } void SetTextureOverlay(DebugOverlay overlay) { return InvokeVoidFunction(&ITextureViewer::SetTextureOverlay, overlay); } bool IsZoomAutoFit() { return InvokeRetFunction(&ITextureViewer::IsZoomAutoFit); } TextureDisplay GetTextureDisplay() { return InvokeRetFunction(&ITextureViewer::GetTextureDisplay); } float GetZoomLevel() { return InvokeRetFunction(&ITextureViewer::GetZoomLevel); } void SetZoomLevel(bool autofit, float zoom) { return InvokeVoidFunction(&ITextureViewer::SetZoomLevel, autofit, zoom); } rdcpair GetHistogramRange() { return InvokeRetFunction>(&ITextureViewer::GetHistogramRange); } void SetHistogramRange(float blackpoint, float whitepoint) { return InvokeVoidFunction(&ITextureViewer::SetHistogramRange, blackpoint, whitepoint); } uint32_t GetChannelVisibilityBits() { return InvokeRetFunction(&ITextureViewer::GetChannelVisibilityBits); } rdcfixedarray GetChannelVisibility() { return InvokeRetFunction>(&ITextureViewer::GetChannelVisibility); } void SetChannelVisibility(bool red, bool green, bool blue, bool alpha) { return InvokeVoidFunction(&ITextureViewer::SetChannelVisibility, red, green, blue, alpha); } }; struct IBufferViewerInvoker : UIThreadInvoker { IBufferViewerInvoker(PythonShell *shell, IBufferViewer &obj) : UIThreadInvoker(shell, obj) {} virtual ~IBufferViewerInvoker() {} QWidget *Widget() { return m_Obj.Widget(); } void ScrollToRow(int32_t row, MeshDataStage stage) { return InvokeVoidFunction(&IBufferViewer::ScrollToRow, row, stage); } void ScrollToColumn(int32_t column, MeshDataStage stage) { return InvokeVoidFunction(&IBufferViewer::ScrollToColumn, column, stage); } void ShowMeshData(MeshDataStage stage) { return InvokeVoidFunction(&IBufferViewer::ShowMeshData, stage); } void SetCurrentInstance(int32_t instance) { return InvokeVoidFunction(&IBufferViewer::SetCurrentInstance, instance); } void SetCurrentView(int32_t view) { return InvokeVoidFunction(&IBufferViewer::SetCurrentView, view); } void SetPreviewStage(MeshDataStage stage) { return InvokeVoidFunction(&IBufferViewer::SetPreviewStage, stage); } }; struct IPipelineStateViewerInvoker : UIThreadInvoker { IPipelineStateViewerInvoker(PythonShell *shell, IPipelineStateViewer &obj) : UIThreadInvoker(shell, obj) { } virtual ~IPipelineStateViewerInvoker() {} QWidget *Widget() { return m_Obj.Widget(); } virtual bool SaveShaderFile(const ShaderReflection *shader) { return InvokeRetFunction(&IPipelineStateViewer::SaveShaderFile, shader); } virtual void SelectPipelineStage(PipelineStage stage) { return InvokeVoidFunction(&IPipelineStateViewer::SelectPipelineStage, stage); } }; struct ICaptureConnectionInvoker : UIThreadInvoker { ICaptureConnectionInvoker(PythonShell *shell, ICaptureConnection &obj) : UIThreadInvoker(shell, obj) { // delete ourself when the connection dies obj.RegisterClosedCallback([this](ICaptureConnection *) { delete this; }); } virtual ~ICaptureConnectionInvoker() {} QWidget *Widget() { return m_Obj.Widget(); } void RegisterClosedCallback(ClosedCallback method) { return InvokeVoidFunction(&ICaptureConnection::RegisterClosedCallback, method); } bool IsConnected() { return InvokeRetFunction(&ICaptureConnection::IsConnected); } void PreventAutoClose() { return InvokeVoidFunction(&ICaptureConnection::PreventAutoClose); } rdcarray GetAPIs() { return InvokeRetFunction>(&ICaptureConnection::GetAPIs); } void QueueCapture(int frameNumber, int numFrames) { return InvokeVoidFunction(&ICaptureConnection::QueueCapture, frameNumber, numFrames); } void TimedCapture(float secondsDelay, int numFrames) { return InvokeVoidFunction(&ICaptureConnection::TimedCapture, secondsDelay, numFrames); } void CycleActiveWindow() { return InvokeVoidFunction(&ICaptureConnection::CycleActiveWindow); } rdcstr Target() { return InvokeRetFunction(&ICaptureConnection::Target); } rdcstr Hostname() { return InvokeRetFunction(&ICaptureConnection::Hostname); } rdcstr FriendlyHostname() { return InvokeRetFunction(&ICaptureConnection::FriendlyHostname); } void Close(bool discardUnsaved) { return InvokeVoidFunction(&ICaptureConnection::Close, discardUnsaved); } rdcarray GetCaptures() { return InvokeRetFunction>(&ICaptureConnection::GetCaptures); } void OpenCapture(uint32_t ID) { return InvokeVoidFunction(&ICaptureConnection::OpenCapture, ID); } void DeleteCapture(uint32_t ID, bool promptForSave) { return InvokeVoidFunction(&ICaptureConnection::DeleteCapture, ID, promptForSave); } void SaveCapture(uint32_t ID, rdcstr filename) { return InvokeVoidFunction(&ICaptureConnection::SaveCapture, ID, filename); } rdcarray GetChildProcesses() { return InvokeRetFunction>(&ICaptureConnection::GetChildProcesses); } ICaptureConnection *ConnectToChild(uint32_t pid) { ICaptureConnection *ret = InvokeRetFunction(&ICaptureConnection::ConnectToChild, pid); if(!ret) return ret; return new ICaptureConnectionInvoker(m_Shell, *ret); } }; struct ICaptureDialogInvoker : UIThreadInvoker { ICaptureDialogInvoker(PythonShell *shell, ICaptureDialog &obj) : UIThreadInvoker(shell, obj) {} virtual ~ICaptureDialogInvoker() {} QWidget *Widget() { return m_Obj.Widget(); } bool IsInjectMode() { return InvokeRetFunction(&ICaptureDialog::IsInjectMode); } void SetInjectMode(bool inject) { return InvokeVoidFunction(&ICaptureDialog::SetInjectMode, inject); } void SetExecutableFilename(const rdcstr &filename) { return InvokeVoidFunction(&ICaptureDialog::SetExecutableFilename, filename); } void SetWorkingDirectory(const rdcstr &dir) { return InvokeVoidFunction(&ICaptureDialog::SetWorkingDirectory, dir); } void SetCommandLine(const rdcstr &cmd) { return InvokeVoidFunction(&ICaptureDialog::SetCommandLine, cmd); } void SetEnvironmentModifications(const rdcarray &modifications) { return InvokeVoidFunction(&ICaptureDialog::SetEnvironmentModifications, modifications); } void SetSettings(CaptureSettings settings) { return InvokeVoidFunction(&ICaptureDialog::SetSettings, settings); } CaptureSettings Settings() { return InvokeRetFunction(&ICaptureDialog::Settings); } ICaptureConnection *Launch() { ICaptureConnection *ret = InvokeRetFunction(&ICaptureDialog::Launch); if(!ret) return ret; return new ICaptureConnectionInvoker(m_Shell, *ret); } void LoadSettings(const rdcstr &filename) { return InvokeVoidFunction(&ICaptureDialog::LoadSettings, filename); } void SaveSettings(const rdcstr &filename) { return InvokeVoidFunction(&ICaptureDialog::SaveSettings, filename); } void UpdateGlobalHook() { return InvokeVoidFunction(&ICaptureDialog::UpdateGlobalHook); } void UpdateRemoteHost() { return InvokeVoidFunction(&ICaptureDialog::UpdateRemoteHost); } }; struct IDebugMessageViewInvoker : UIThreadInvoker { IDebugMessageViewInvoker(PythonShell *shell, IDebugMessageView &obj) : UIThreadInvoker(shell, obj) { } virtual ~IDebugMessageViewInvoker() {} QWidget *Widget() { return m_Obj.Widget(); } }; struct IDiagnosticLogViewInvoker : UIThreadInvoker { IDiagnosticLogViewInvoker(PythonShell *shell, IDiagnosticLogView &obj) : UIThreadInvoker(shell, obj) { } virtual ~IDiagnosticLogViewInvoker() {} QWidget *Widget() { return m_Obj.Widget(); } }; struct ICommentViewInvoker : UIThreadInvoker { ICommentViewInvoker(PythonShell *shell, ICommentView &obj) : UIThreadInvoker(shell, obj) {} virtual ~ICommentViewInvoker() {} QWidget *Widget() { return m_Obj.Widget(); } virtual void SetComments(const rdcstr &text) { return InvokeVoidFunction(&ICommentView::SetComments, text); } virtual rdcstr GetComments() { return InvokeRetFunction(&ICommentView::GetComments); } }; struct IPerformanceCounterViewerInvoker : UIThreadInvoker { IPerformanceCounterViewerInvoker(PythonShell *shell, IPerformanceCounterViewer &obj) : UIThreadInvoker(shell, obj) { } virtual ~IPerformanceCounterViewerInvoker() {} QWidget *Widget() { return m_Obj.Widget(); } void UpdateDurationColumn() { return InvokeVoidFunction(&IPerformanceCounterViewer::UpdateDurationColumn); } }; struct IStatisticsViewerInvoker : UIThreadInvoker { IStatisticsViewerInvoker(PythonShell *shell, IStatisticsViewer &obj) : UIThreadInvoker(shell, obj) { } virtual ~IStatisticsViewerInvoker() {} QWidget *Widget() { return m_Obj.Widget(); } }; struct ITimelineBarInvoker : UIThreadInvoker { ITimelineBarInvoker(PythonShell *shell, ITimelineBar &obj) : UIThreadInvoker(shell, obj) {} virtual ~ITimelineBarInvoker() {} QWidget *Widget() { return m_Obj.Widget(); } void HighlightResourceUsage(ResourceId id) { return InvokeVoidFunction(&ITimelineBar::HighlightResourceUsage, id); } void HighlightHistory(ResourceId id, const rdcarray &history) { return InvokeVoidFunction(&ITimelineBar::HighlightHistory, id, history); } }; struct IPythonShellInvoker : UIThreadInvoker { IPythonShellInvoker(PythonShell *shell, IPythonShell &obj) : UIThreadInvoker(shell, obj) {} virtual ~IPythonShellInvoker() {} QWidget *Widget() { return m_Obj.Widget(); } bool CheckUnsavedChanges() { return InvokeRetFunction(&IPythonShell::CheckUnsavedChanges); } bool LoadScriptFromFilename(rdcstr filename) { return InvokeRetFunction(&IPythonShell::LoadScriptFromFilename, filename); } void CreateNewScriptEditor(rdcstr name, rdcstr text) { return InvokeVoidFunction(&IPythonShell::CreateNewScriptEditor, name, text); } rdcstr GetScriptText() { return InvokeRetFunction(&IPythonShell::GetScriptText); } void RunScript() { return InvokeVoidFunction(&IPythonShell::RunScript); } void AttachDebugger(const rdcstr &extensionName) { return InvokeVoidFunction(&IPythonShell::AttachDebugger, extensionName); } void SetExtensionOutputFilter(const rdcstr &extensionName) { return InvokeVoidFunction(&IPythonShell::SetExtensionOutputFilter, extensionName); } void SetScriptOutputFilter() { return InvokeVoidFunction(&IPythonShell::SetScriptOutputFilter); } void RemoveOutputFilter() { return InvokeVoidFunction(&IPythonShell::RemoveOutputFilter); } void ShowOutput() { return InvokeVoidFunction(&IPythonShell::ShowOutput); } void ShowREPL() { return InvokeVoidFunction(&IPythonShell::ShowREPL); } void ShowHelp() { return InvokeVoidFunction(&IPythonShell::ShowHelp); } }; struct IResourceInspectorInvoker : UIThreadInvoker { IResourceInspectorInvoker(PythonShell *shell, IResourceInspector &obj) : UIThreadInvoker(shell, obj) { } virtual ~IResourceInspectorInvoker() {} QWidget *Widget() { return m_Obj.Widget(); } void Inspect(ResourceId id) { return InvokeVoidFunction(&IResourceInspector::Inspect, id); } ResourceId CurrentResource() { return InvokeRetFunction(&IResourceInspector::CurrentResource); } void RevealParameter(SDObject *param) { return InvokeVoidFunction(&IResourceInspector::RevealParameter, param); } }; struct CaptureContextInvoker : UIThreadInvoker { ExtensionInvoker *m_Ext; ReplayControllerInvoker m_ReplayController; #define WINDOW_INVOKER(iface) \ iface##Invoker *m_invoker##iface = NULL; \ iface *WrapInvoker(iface *i) \ { \ if(!m_invoker##iface || &m_invoker##iface->m_Obj != i) \ { \ delete m_invoker##iface; \ m_invoker##iface = new iface##Invoker(m_Shell, *i); \ } \ return m_invoker##iface; \ } WINDOW_INVOKER(IMainWindow); WINDOW_INVOKER(IEventBrowser); WINDOW_INVOKER(IAPIInspector); WINDOW_INVOKER(IAnnotationViewer); WINDOW_INVOKER(ITextureViewer); WINDOW_INVOKER(IBufferViewer); WINDOW_INVOKER(IPipelineStateViewer); WINDOW_INVOKER(ICaptureDialog); WINDOW_INVOKER(IDebugMessageView); WINDOW_INVOKER(IDiagnosticLogView); WINDOW_INVOKER(ICommentView); WINDOW_INVOKER(IPerformanceCounterViewer); WINDOW_INVOKER(IStatisticsViewer); WINDOW_INVOKER(ITimelineBar); WINDOW_INVOKER(IPythonShell); WINDOW_INVOKER(IResourceInspector); CaptureContextInvoker(PythonShell *shell, ICaptureContext &obj) : UIThreadInvoker(shell, obj), m_ReplayController(shell, obj) { m_Ext = new ExtensionInvoker(shell, obj.Extensions()); } virtual ~CaptureContextInvoker() { delete m_Ext; } // /////////////////////////////////////////////////////////////////////// // pass-through functions that don't need the UI thread /////////////////////////////////////////////////////////////////////// // virtual void InvokeOntoUIThread(std::function callback) override { return m_Obj.InvokeOntoUIThread(callback); } virtual rdcstr TempCaptureFilename(const rdcstr &appname) override { return m_Obj.TempCaptureFilename(appname); } virtual IExtensionManager &Extensions() override { return *m_Ext; } virtual IReplayManager &Replay() override { return m_Obj.Replay(); } virtual bool IsCaptureLoaded() override { return m_Obj.IsCaptureLoaded(); } virtual bool IsCaptureLocal() override { return m_Obj.IsCaptureLocal(); } virtual bool IsCaptureTemporary() override { return m_Obj.IsCaptureTemporary(); } virtual bool IsCaptureLoading() override { return m_Obj.IsCaptureLoading(); } virtual ResultDetails GetFatalError() override { return m_Obj.GetFatalError(); } virtual rdcstr GetCaptureFilename() override { return m_Obj.GetCaptureFilename(); } virtual CaptureModifications GetCaptureModifications() override { return m_Obj.GetCaptureModifications(); } virtual FrameDescription FrameInfo() override { return m_Obj.FrameInfo(); } virtual APIProperties APIProps() override { return m_Obj.APIProps(); } virtual rdcarray TargetShaderEncodings() override { return m_Obj.TargetShaderEncodings(); } virtual rdcarray CustomShaderEncodings() override { return m_Obj.CustomShaderEncodings(); } virtual rdcarray CustomShaderSourcePrefixes() override { return m_Obj.CustomShaderSourcePrefixes(); } virtual uint32_t CurSelectedEvent() override { return m_Obj.CurSelectedEvent(); } virtual uint32_t CurEvent() override { return m_Obj.CurEvent(); } virtual const ActionDescription *CurSelectedAction() override { return m_Obj.CurSelectedAction(); } virtual const ActionDescription *CurAction() override { return m_Obj.CurAction(); } virtual const ActionDescription *GetFirstAction() override { return m_Obj.GetFirstAction(); } virtual const ActionDescription *GetLastAction() override { return m_Obj.GetLastAction(); } virtual const rdcarray &CurRootActions() override { return m_Obj.CurRootActions(); } virtual const ResourceDescription *GetResource(ResourceId id) const override { return m_Obj.GetResource(id); } virtual const rdcarray &GetResources() override { return m_Obj.GetResources(); } virtual rdcstr GetResourceName(ResourceId id) const override { return m_Obj.GetResourceName(id); } virtual rdcstr GetResourceNameUnsuffixed(ResourceId id) const override { return m_Obj.GetResourceNameUnsuffixed(id); } virtual bool IsAutogeneratedName(ResourceId id) override { return m_Obj.IsAutogeneratedName(id); } virtual bool HasResourceCustomName(ResourceId id) override { return m_Obj.HasResourceCustomName(id); } virtual int32_t ResourceNameCacheID() const override { return m_Obj.ResourceNameCacheID(); } virtual TextureDescription *GetTexture(ResourceId id) override { return m_Obj.GetTexture(id); } virtual const rdcarray &GetTextures() override { return m_Obj.GetTextures(); } virtual BufferDescription *GetBuffer(ResourceId id) override { return m_Obj.GetBuffer(id); } virtual DescriptorStoreDescription *GetDescriptorStore(ResourceId id) override { return m_Obj.GetDescriptorStore(id); } virtual const rdcarray &GetBuffers() const override { return m_Obj.GetBuffers(); } virtual const ActionDescription *GetAction(uint32_t eventId) override { return m_Obj.GetAction(eventId); } virtual void ClearReplayCache() override { return m_Obj.ClearReplayCache(); } virtual bool OpenRGPProfile(const rdcstr &filename) override { return m_Obj.OpenRGPProfile(filename); } virtual IRGPInterop *GetRGPInterop() override { return m_Obj.GetRGPInterop(); } virtual const SDFile &GetStructuredFile() override { return m_Obj.GetStructuredFile(); } virtual WindowingSystem CurWindowingSystem() override { return m_Obj.CurWindowingSystem(); } virtual const rdcarray &DebugMessages() override { return m_Obj.DebugMessages(); } virtual int32_t UnreadMessageCount() override { return m_Obj.UnreadMessageCount(); } virtual void MarkMessagesRead() override { return m_Obj.MarkMessagesRead(); } virtual rdcstr GetNotes(const rdcstr &key) override { return m_Obj.GetNotes(key); } virtual rdcarray GetBookmarks() override { return m_Obj.GetBookmarks(); } virtual const D3D11Pipe::State *CurD3D11PipelineState() override { return m_Obj.CurD3D11PipelineState(); } virtual const D3D12Pipe::State *CurD3D12PipelineState() override { return m_Obj.CurD3D12PipelineState(); } virtual const GLPipe::State *CurGLPipelineState() override { return m_Obj.CurGLPipelineState(); } virtual const VKPipe::State *CurVulkanPipelineState() override { return m_Obj.CurVulkanPipelineState(); } virtual const PipeState &CurPipelineState() override { return m_Obj.CurPipelineState(); } virtual PersistentConfig &Config() override { return m_Obj.Config(); } // /////////////////////////////////////////////////////////////////////// // functions that invoke onto the UI thread /////////////////////////////////////////////////////////////////////// // virtual void ConnectToRemoteServer(RemoteHost host) override { InvokeVoidFunction(&ICaptureContext::ConnectToRemoteServer, host); } virtual WindowingData CreateWindowingData(QWidget *window) override { return InvokeRetFunction(&ICaptureContext::CreateWindowingData, window); } virtual void LoadCapture(const rdcstr &capture, const ReplayOptions &opts, const rdcstr &origFilename, bool temporary, bool local) override { InvokeVoidFunction(&ICaptureContext::LoadCapture, capture, opts, origFilename, temporary, local); } virtual bool SaveCaptureTo(const rdcstr &capture) override { return InvokeRetFunction(&ICaptureContext::SaveCaptureTo, capture); } virtual void RecompressCapture() override { InvokeVoidFunction(&ICaptureContext::RecompressCapture); } virtual void CloseCapture() override { InvokeVoidFunction(&ICaptureContext::CloseCapture); } virtual IReplayController *GetBlockingController() override { if(!m_Obj.IsCaptureLoaded()) return NULL; return &m_ReplayController; } virtual bool ImportCapture(const CaptureFileFormat &fmt, const rdcstr &importfile, const rdcstr &rdcfile) override { return InvokeRetFunction(&ICaptureContext::ImportCapture, fmt, importfile, rdcfile); } virtual void ExportCapture(const CaptureFileFormat &fmt, const rdcstr &exportfile) override { InvokeVoidFunction(&ICaptureContext::ExportCapture, fmt, exportfile); } virtual void SetEventID(const rdcarray &exclude, uint32_t selectedEventID, uint32_t eventId, bool force = false) override { InvokeVoidFunction(&ICaptureContext::SetEventID, exclude, selectedEventID, eventId, force); } virtual void RefreshStatus() override { InvokeVoidFunction(&ICaptureContext::RefreshStatus); } virtual bool IsResourceReplaced(ResourceId id) override { return InvokeRetFunction(&ICaptureContext::IsResourceReplaced, id); } virtual ResourceId GetResourceReplacement(ResourceId id) override { return InvokeRetFunction(&ICaptureContext::GetResourceReplacement, id); } virtual void RegisterReplacement(ResourceId from, ResourceId to) override { InvokeVoidFunction(&ICaptureContext::RegisterReplacement, from, to); } virtual void UnregisterReplacement(ResourceId id) override { InvokeVoidFunction(&ICaptureContext::UnregisterReplacement, id); } virtual void AddCaptureViewer(ICaptureViewer *viewer) override { InvokeVoidFunction(&ICaptureContext::AddCaptureViewer, viewer); } virtual void RemoveCaptureViewer(ICaptureViewer *viewer) override { InvokeVoidFunction(&ICaptureContext::RemoveCaptureViewer, viewer); } virtual void AddMessages(const rdcarray &msgs) override { InvokeVoidFunction(&ICaptureContext::AddMessages, msgs); } virtual void ClearMessages() override { InvokeVoidFunction(&ICaptureContext::ClearMessages); } virtual void SetResourceCustomName(ResourceId id, const rdcstr &name) override { InvokeVoidFunction(&ICaptureContext::SetResourceCustomName, id, name); } virtual void SetNotes(const rdcstr &key, const rdcstr &contents) override { InvokeVoidFunction(&ICaptureContext::SetNotes, key, contents); } virtual void SetBookmark(const EventBookmark &mark) override { InvokeVoidFunction(&ICaptureContext::SetBookmark, mark); } virtual void RemoveBookmark(uint32_t EID) override { InvokeVoidFunction(&ICaptureContext::RemoveBookmark, EID); } virtual void EmbedDependentFiles() override { InvokeVoidFunction(&ICaptureContext::EmbedDependentFiles); } virtual void RemoveDependentFiles() override { InvokeVoidFunction(&ICaptureContext::RemoveDependentFiles); } virtual void DelayedCallback(uint32_t milliseconds, std::function callback) override { if(!GUIInvoke::onUIThread()) { PythonContext *scriptContext = m_Shell->GetScriptContext(); if(scriptContext) scriptContext->PausePythonThreading(); GUIInvoke::call(m_Shell, [this, milliseconds, callback]() { m_Obj.DelayedCallback(milliseconds, callback); }); if(scriptContext) scriptContext->ResumePythonThreading(); return; } m_Obj.DelayedCallback(milliseconds, callback); } virtual IMainWindow *GetMainWindow() override { return WrapInvoker(InvokeRetFunction(&ICaptureContext::GetMainWindow)); } virtual IEventBrowser *GetEventBrowser() override { return WrapInvoker(InvokeRetFunction(&ICaptureContext::GetEventBrowser)); } virtual IAPIInspector *GetAPIInspector() override { return WrapInvoker(InvokeRetFunction(&ICaptureContext::GetAPIInspector)); } virtual IAnnotationViewer *GetAnnotationViewer() override { return WrapInvoker(InvokeRetFunction(&ICaptureContext::GetAnnotationViewer)); } virtual ITextureViewer *GetTextureViewer() override { return WrapInvoker(InvokeRetFunction(&ICaptureContext::GetTextureViewer)); } virtual IBufferViewer *GetMeshPreview() override { return WrapInvoker(InvokeRetFunction(&ICaptureContext::GetMeshPreview)); } virtual IPipelineStateViewer *GetPipelineViewer() override { return WrapInvoker(InvokeRetFunction(&ICaptureContext::GetPipelineViewer)); } virtual ICaptureDialog *GetCaptureDialog() override { return WrapInvoker(InvokeRetFunction(&ICaptureContext::GetCaptureDialog)); } virtual IDebugMessageView *GetDebugMessageView() override { return WrapInvoker(InvokeRetFunction(&ICaptureContext::GetDebugMessageView)); } virtual IDiagnosticLogView *GetDiagnosticLogView() override { return WrapInvoker( InvokeRetFunction(&ICaptureContext::GetDiagnosticLogView)); } virtual ICommentView *GetCommentView() override { return WrapInvoker(InvokeRetFunction(&ICaptureContext::GetCommentView)); } virtual IPerformanceCounterViewer *GetPerformanceCounterViewer() override { return WrapInvoker(InvokeRetFunction( &ICaptureContext::GetPerformanceCounterViewer)); } virtual IStatisticsViewer *GetStatisticsViewer() override { return WrapInvoker(InvokeRetFunction(&ICaptureContext::GetStatisticsViewer)); } virtual ITimelineBar *GetTimelineBar() override { return WrapInvoker(InvokeRetFunction(&ICaptureContext::GetTimelineBar)); } virtual IPythonShell *GetPythonShell() override { return WrapInvoker(InvokeRetFunction(&ICaptureContext::GetPythonShell)); } virtual IResourceInspector *GetResourceInspector() override { return WrapInvoker( InvokeRetFunction(&ICaptureContext::GetResourceInspector)); } virtual bool HasEventBrowser() override { return InvokeRetFunction(&ICaptureContext::HasEventBrowser); } virtual bool HasAPIInspector() override { return InvokeRetFunction(&ICaptureContext::HasAPIInspector); } virtual bool HasAnnotationViewer() override { return InvokeRetFunction(&ICaptureContext::HasAnnotationViewer); } virtual bool HasTextureViewer() override { return InvokeRetFunction(&ICaptureContext::HasTextureViewer); } virtual bool HasPipelineViewer() override { return InvokeRetFunction(&ICaptureContext::HasPipelineViewer); } virtual bool HasMeshPreview() override { return InvokeRetFunction(&ICaptureContext::HasMeshPreview); } virtual bool HasCaptureDialog() override { return InvokeRetFunction(&ICaptureContext::HasCaptureDialog); } virtual bool HasDebugMessageView() override { return InvokeRetFunction(&ICaptureContext::HasDebugMessageView); } virtual bool HasDiagnosticLogView() override { return InvokeRetFunction(&ICaptureContext::HasDiagnosticLogView); } virtual bool HasCommentView() override { return InvokeRetFunction(&ICaptureContext::HasCommentView); } virtual bool HasPerformanceCounterViewer() override { return InvokeRetFunction(&ICaptureContext::HasPerformanceCounterViewer); } virtual bool HasStatisticsViewer() override { return InvokeRetFunction(&ICaptureContext::HasStatisticsViewer); } virtual bool HasTimelineBar() override { return InvokeRetFunction(&ICaptureContext::HasTimelineBar); } virtual bool HasPythonShell() override { return InvokeRetFunction(&ICaptureContext::HasPythonShell); } virtual bool HasResourceInspector() override { return InvokeRetFunction(&ICaptureContext::HasResourceInspector); } virtual void ShowEventBrowser() override { InvokeVoidFunction(&ICaptureContext::ShowEventBrowser); } virtual void ShowAPIInspector() override { InvokeVoidFunction(&ICaptureContext::ShowAPIInspector); } virtual void ShowAnnotationViewer() override { InvokeVoidFunction(&ICaptureContext::ShowAnnotationViewer); } virtual void ShowTextureViewer() override { InvokeVoidFunction(&ICaptureContext::ShowTextureViewer); } virtual void ShowMeshPreview() override { InvokeVoidFunction(&ICaptureContext::ShowMeshPreview); } virtual void ShowPipelineViewer() override { InvokeVoidFunction(&ICaptureContext::ShowPipelineViewer); } virtual void ShowCaptureDialog() override { InvokeVoidFunction(&ICaptureContext::ShowCaptureDialog); } virtual void ShowDebugMessageView() override { InvokeVoidFunction(&ICaptureContext::ShowDebugMessageView); } virtual void ShowDiagnosticLogView() override { InvokeVoidFunction(&ICaptureContext::ShowDiagnosticLogView); } virtual void ShowCommentView() override { InvokeVoidFunction(&ICaptureContext::ShowCommentView); } virtual void ShowPerformanceCounterViewer() override { InvokeVoidFunction(&ICaptureContext::ShowPerformanceCounterViewer); } virtual void ShowStatisticsViewer() override { InvokeVoidFunction(&ICaptureContext::ShowStatisticsViewer); } virtual void ShowTimelineBar() override { InvokeVoidFunction(&ICaptureContext::ShowTimelineBar); } virtual void ShowPythonShell() override { InvokeVoidFunction(&ICaptureContext::ShowPythonShell); } virtual void ShowResourceInspector() override { InvokeVoidFunction(&ICaptureContext::ShowResourceInspector); } virtual IShaderViewer *EditShader(ResourceId id, ShaderStage stage, const rdcstr &entryPoint, const rdcstrpairs &files, KnownShaderTool knownTool, ShaderEncoding shaderEncoding, ShaderCompileFlags flags, IShaderViewer::SaveCallback saveCallback, IShaderViewer::RevertCallback revertCallback) override { return InvokeRetFunction(&ICaptureContext::EditShader, id, stage, entryPoint, files, knownTool, shaderEncoding, flags, saveCallback, revertCallback); } virtual IShaderViewer *DebugShader(const ShaderReflection *shader, ResourceId pipeline, ShaderDebugTrace *trace, const rdcstr &debugContext) override { return InvokeRetFunction(&ICaptureContext::DebugShader, shader, pipeline, trace, debugContext); } virtual IShaderViewer *ViewShader(const ShaderReflection *shader, ResourceId pipeline) override { return InvokeRetFunction(&ICaptureContext::ViewShader, shader, pipeline); } virtual IShaderMessageViewer *ViewShaderMessages(ShaderStageMask stages) override { return InvokeRetFunction(&ICaptureContext::ViewShaderMessages, stages); } virtual IDescriptorViewer *ViewDescriptorStore(ResourceId id) override { return InvokeRetFunction(&ICaptureContext::ViewDescriptorStore, id); } virtual IDescriptorViewer *ViewDescriptors(const rdcarray &descriptors, const rdcarray &samplerDescriptors) override { return InvokeRetFunction(&ICaptureContext::ViewDescriptors, descriptors, samplerDescriptors); } virtual IBufferViewer *ViewBuffer(uint64_t byteOffset, uint64_t byteSize, ResourceId id, const rdcstr &format = "") override { return InvokeRetFunction(&ICaptureContext::ViewBuffer, byteOffset, byteSize, id, format); } virtual IBufferViewer *ViewTextureAsBuffer(ResourceId id, const Subresource &sub, const rdcstr &format = "") override { return InvokeRetFunction(&ICaptureContext::ViewTextureAsBuffer, id, sub, format); } virtual IBufferViewer *ViewConstantBuffer(ShaderStage stage, uint32_t slot, uint32_t idx) override { return InvokeRetFunction(&ICaptureContext::ViewConstantBuffer, stage, slot, idx); } virtual IPixelHistoryView *ViewPixelHistory(ResourceId texID, uint32_t x, uint32_t y, uint32_t view, const TextureDisplay &display) override { return InvokeRetFunction(&ICaptureContext::ViewPixelHistory, texID, x, y, view, display); } virtual QWidget *CreateBuiltinWindow(const rdcstr &objectName) override { return InvokeRetFunction(&ICaptureContext::CreateBuiltinWindow, objectName); } virtual void BuiltinWindowClosed(QWidget *window) override { InvokeVoidFunction(&ICaptureContext::BuiltinWindowClosed, window); } virtual void RaiseDockWindow(QWidget *dockWindow) override { InvokeVoidFunction(&ICaptureContext::RaiseDockWindow, dockWindow); } virtual void AddDockWindow(QWidget *newWindow, DockReference ref, QWidget *refWindow, float percentage = 0.5f) override { InvokeVoidFunction(&ICaptureContext::AddDockWindow, newWindow, ref, refWindow, percentage); } }; ICaptureContext *MakeCaptureContextInvoker(PythonShell *shell, ICaptureContext &ctx) { return new CaptureContextInvoker(shell, ctx); } void FreeCaptureContextInvoker(ICaptureContext *ctx) { CaptureContextInvoker *invoker = (CaptureContextInvoker *)ctx; delete invoker; }