diff --git a/qrenderdoc/Code/CaptureContext.cpp b/qrenderdoc/Code/CaptureContext.cpp index 69a690a86..e9a2814b6 100644 --- a/qrenderdoc/Code/CaptureContext.cpp +++ b/qrenderdoc/Code/CaptureContext.cpp @@ -2005,6 +2005,13 @@ void CaptureContext::LoadEdits(const QString &data) } } +void CaptureContext::ClearReplayCache() +{ + m_CustomNameCachedID++; + + Replay().AsyncInvoke([](IReplayController *r) { r->ClearReplayCache(); }); +} + bool CaptureContext::OpenRGPProfile(const rdcstr &filename) { delete m_RGP; diff --git a/qrenderdoc/Code/CaptureContext.h b/qrenderdoc/Code/CaptureContext.h index 7541de474..ca5c11cfd 100644 --- a/qrenderdoc/Code/CaptureContext.h +++ b/qrenderdoc/Code/CaptureContext.h @@ -163,6 +163,7 @@ public: const ActionDescription *CurAction() override { return GetAction(CurEvent()); } const ActionDescription *GetFirstAction() override { return m_FirstAction; }; const ActionDescription *GetLastAction() override { return m_LastAction; }; + void ClearReplayCache() override; bool OpenRGPProfile(const rdcstr &filename) override; IRGPInterop *GetRGPInterop() override { return m_RGP; } const rdcarray &CurRootActions() override { return *m_Actions; } diff --git a/qrenderdoc/Code/Interface/QRDInterface.h b/qrenderdoc/Code/Interface/QRDInterface.h index 14ff0fc9a..33fe617b5 100644 --- a/qrenderdoc/Code/Interface/QRDInterface.h +++ b/qrenderdoc/Code/Interface/QRDInterface.h @@ -2264,6 +2264,11 @@ again, any previous connection will be closed. )"); virtual bool OpenRGPProfile(const rdcstr &filename) = 0; + DOCUMENT(R"(Clear any cached data from previous replays and ensure subsequent replays fully +re-initialise any data, including e.g. bindless feedback, printf results or mesh output data. +)"); + virtual void ClearReplayCache() = 0; + DOCUMENT(R"(Returns the current interop handle for RGP. This may return ``None`` in several cases: diff --git a/qrenderdoc/Windows/PythonShell.cpp b/qrenderdoc/Windows/PythonShell.cpp index e2fa8817a..ee33c584e 100644 --- a/qrenderdoc/Windows/PythonShell.cpp +++ b/qrenderdoc/Windows/PythonShell.cpp @@ -531,6 +531,7 @@ struct CaptureContextInvoker : ObjectForwarder { 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); diff --git a/qrenderdoc/Windows/ShaderMessageViewer.cpp b/qrenderdoc/Windows/ShaderMessageViewer.cpp index 03d48a628..a70f029fd 100644 --- a/qrenderdoc/Windows/ShaderMessageViewer.cpp +++ b/qrenderdoc/Windows/ShaderMessageViewer.cpp @@ -621,7 +621,7 @@ void ShaderMessageViewer::OnCaptureClosed() void ShaderMessageViewer::OnEventChanged(uint32_t eventId) { ResourceId shaders[NumShaderStages]; - bool editsChanged = false; + bool needRefresh = false; QString staleReason; for(ShaderStage s : values()) @@ -632,13 +632,24 @@ void ShaderMessageViewer::OnEventChanged(uint32_t eventId) // either an edit has been applied, updated, or removed if these don't match if(shaders[idx] != m_ReplacedShaders[idx]) { - editsChanged = true; - staleReason += QFormatStr(", %1").arg(ToQStr(s, m_API)); + needRefresh = true; + if(staleReason.isEmpty()) + staleReason = tr("there are edits to shaders typed "); + else + staleReason += lit(", "); + staleReason += QFormatStr("%1").arg(ToQStr(s, m_API)); } } + if(!needRefresh && m_ResourceCacheID != m_Ctx.ResourceNameCacheID()) + { + staleReason = tr("The replay information is out of date"); + m_ResourceCacheID = m_Ctx.ResourceNameCacheID(); + needRefresh = true; + } + // if the edits haven't changed, just skip - if(!editsChanged) + if(!needRefresh) return; // if it's the current event we can update with the latest @@ -656,15 +667,12 @@ void ShaderMessageViewer::OnEventChanged(uint32_t eventId) } else { - staleReason.remove(0, 2); - // otherwise we can't - just update the stale status ui->staleStatus->show(); - ui->staleStatus->setText( - tr("Messages are stale because edits to %1 shaders have changed since they were fetched.\n" - "Select the event @%2 to refresh.") - .arg(staleReason) - .arg(m_EID)); + ui->staleStatus->setText(tr("Messages are stale because %1 since the messages were fetched.\n" + "Select the event @%2 to refresh.") + .arg(staleReason) + .arg(m_EID)); ui->messages->beginUpdate(); diff --git a/qrenderdoc/Windows/ShaderMessageViewer.h b/qrenderdoc/Windows/ShaderMessageViewer.h index 60cd3b885..1e596e2c4 100644 --- a/qrenderdoc/Windows/ShaderMessageViewer.h +++ b/qrenderdoc/Windows/ShaderMessageViewer.h @@ -71,6 +71,8 @@ private: bool m_Multiview = false, m_Multisampled = false; + int m_ResourceCacheID = -1; + GraphicsAPI m_API; uint32_t m_EID; const ActionDescription *m_Action; diff --git a/renderdoc/api/replay/renderdoc_replay.h b/renderdoc/api/replay/renderdoc_replay.h index dac8d1595..9ec572d51 100644 --- a/renderdoc/api/replay/renderdoc_replay.h +++ b/renderdoc/api/replay/renderdoc_replay.h @@ -722,6 +722,11 @@ See :meth:`BuildTargetShader`, :meth:`RemoveReplacement`. )"); virtual void ReplaceResource(ResourceId original, ResourceId replacement) = 0; + DOCUMENT(R"(Clear any cached data from previous replays and ensure subsequent replays fully +re-initialise any data, including e.g. bindless feedback, printf results or mesh output data. +)"); + virtual void ClearReplayCache() = 0; + DOCUMENT(R"(Remove any previously specified replacement for an object. See :meth:`ReplaceResource`. diff --git a/renderdoc/core/image_viewer.cpp b/renderdoc/core/image_viewer.cpp index 2d2c3764c..ab84631e2 100644 --- a/renderdoc/core/image_viewer.cpp +++ b/renderdoc/core/image_viewer.cpp @@ -368,6 +368,7 @@ public: errors = "Building target shaders is unsupported"; } void ReplaceResource(ResourceId from, ResourceId to) {} + void ClearReplayCache() {} void RemoveReplacement(ResourceId id) {} // these are proxy functions, and will never be used ResourceId CreateProxyTexture(const TextureDescription &templateTex) diff --git a/renderdoc/core/replay_proxy.cpp b/renderdoc/core/replay_proxy.cpp index d0893ce75..a5b240dff 100644 --- a/renderdoc/core/replay_proxy.cpp +++ b/renderdoc/core/replay_proxy.cpp @@ -1391,6 +1391,31 @@ void ReplayProxy::FreeTargetResource(ResourceId id) PROXY_FUNCTION(FreeTargetResource, id); } +template +void ReplayProxy::Proxied_ClearReplayCache(ParamSerialiser ¶mser, ReturnSerialiser &retser) +{ + const ReplayProxyPacket expectedPacket = eReplayProxy_ClearReplayCache; + ReplayProxyPacket packet = eReplayProxy_ClearReplayCache; + + { + BEGIN_PARAMS(); + END_PARAMS(); + } + + { + REMOTE_EXECUTION(); + if(paramser.IsReading() && !paramser.IsErrored() && !m_IsErrored) + m_Remote->ClearReplayCache(); + } + + SERIALISE_RETURN_VOID(); +} + +void ReplayProxy::ClearReplayCache() +{ + PROXY_FUNCTION(ClearReplayCache); +} + template rdcarray ReplayProxy::Proxied_GetTargetShaderEncodings(ParamSerialiser ¶mser, ReturnSerialiser &retser) @@ -3169,6 +3194,7 @@ bool ReplayProxy::Tick(int type) } case eReplayProxy_ReplaceResource: ReplaceResource(ResourceId(), ResourceId()); break; case eReplayProxy_RemoveReplacement: RemoveReplacement(ResourceId()); break; + case eReplayProxy_ClearReplayCache: ClearReplayCache(); break; case eReplayProxy_DebugVertex: DebugVertex(0, 0, 0, 0, 0); break; case eReplayProxy_DebugPixel: DebugPixel(0, 0, 0, DebugPixelInputs()); break; case eReplayProxy_DebugThread: diff --git a/renderdoc/core/replay_proxy.h b/renderdoc/core/replay_proxy.h index 945bc53f6..972e530f1 100644 --- a/renderdoc/core/replay_proxy.h +++ b/renderdoc/core/replay_proxy.h @@ -112,6 +112,8 @@ enum ReplayProxyPacket eReplayProxy_GetDescriptorAccess, eReplayProxy_GetDescriptorLocations, eReplayProxy_GetDescriptorStores, + + eReplayProxy_ClearReplayCache, }; DECLARE_REFLECTION_ENUM(ReplayProxyPacket); @@ -561,6 +563,7 @@ public: ResourceId &id, rdcstr &errors); IMPLEMENT_FUNCTION_PROXIED(void, ReplaceResource, ResourceId from, ResourceId to); IMPLEMENT_FUNCTION_PROXIED(void, RemoveReplacement, ResourceId id); + IMPLEMENT_FUNCTION_PROXIED(void, ClearReplayCache); // these functions are not part of the replay driver interface - they are similar to GetBufferData // and GetTextureData, but they do extra work to try and optimise transfer by delta-encoding the diff --git a/renderdoc/driver/d3d11/d3d11_replay.cpp b/renderdoc/driver/d3d11/d3d11_replay.cpp index 9f9d40146..443c57b3a 100644 --- a/renderdoc/driver/d3d11/d3d11_replay.cpp +++ b/renderdoc/driver/d3d11/d3d11_replay.cpp @@ -2717,6 +2717,11 @@ void D3D11Replay::RemoveReplacement(ResourceId id) ClearPostVSCache(); } +void D3D11Replay::ClearReplayCache() +{ + ClearPostVSCache(); +} + D3D11DebugManager *D3D11Replay::GetDebugManager() { return m_pDevice->GetDebugManager(); diff --git a/renderdoc/driver/d3d11/d3d11_replay.h b/renderdoc/driver/d3d11/d3d11_replay.h index 861d1bfc0..6af10e5ec 100644 --- a/renderdoc/driver/d3d11/d3d11_replay.h +++ b/renderdoc/driver/d3d11/d3d11_replay.h @@ -253,6 +253,7 @@ public: rdcstr &errors); void ReplaceResource(ResourceId from, ResourceId to); void RemoveReplacement(ResourceId id); + void ClearReplayCache(); rdcarray EnumerateCounters(); CounterDescription DescribeCounter(GPUCounter counterID); diff --git a/renderdoc/driver/d3d12/d3d12_replay.cpp b/renderdoc/driver/d3d12/d3d12_replay.cpp index 2a41b4199..c41bbd138 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.cpp +++ b/renderdoc/driver/d3d12/d3d12_replay.cpp @@ -3619,6 +3619,12 @@ void D3D12Replay::RemoveReplacement(ResourceId id) } } +void D3D12Replay::ClearReplayCache() +{ + ClearPostVSCache(); + ClearFeedbackCache(); +} + void D3D12Replay::RefreshDerivedReplacements() { D3D12ResourceManager *rm = m_pDevice->GetResourceManager(); diff --git a/renderdoc/driver/d3d12/d3d12_replay.h b/renderdoc/driver/d3d12/d3d12_replay.h index feae52bd6..db97dc8aa 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.h +++ b/renderdoc/driver/d3d12/d3d12_replay.h @@ -216,6 +216,7 @@ public: rdcstr &errors); void ReplaceResource(ResourceId from, ResourceId to); void RemoveReplacement(ResourceId id); + void ClearReplayCache(); rdcarray EnumerateCounters(); CounterDescription DescribeCounter(GPUCounter counterID); diff --git a/renderdoc/driver/gl/gl_replay.cpp b/renderdoc/driver/gl/gl_replay.cpp index 21fbd4751..e74f85f5d 100644 --- a/renderdoc/driver/gl/gl_replay.cpp +++ b/renderdoc/driver/gl/gl_replay.cpp @@ -3753,6 +3753,11 @@ void GLReplay::FreeTargetResource(ResourceId id) m_pDriver->FreeTargetResource(id); } +void GLReplay::ClearReplayCache() +{ + ClearPostVSCache(); +} + ResourceId GLReplay::CreateProxyTexture(const TextureDescription &templateTex) { WrappedOpenGL &drv = *m_pDriver; diff --git a/renderdoc/driver/gl/gl_replay.h b/renderdoc/driver/gl/gl_replay.h index 115e4cbbf..a6ced0912 100644 --- a/renderdoc/driver/gl/gl_replay.h +++ b/renderdoc/driver/gl/gl_replay.h @@ -213,6 +213,7 @@ public: void ReplaceResource(ResourceId from, ResourceId to); void RemoveReplacement(ResourceId id); + void ClearReplayCache(); rdcarray EnumerateCounters(); CounterDescription DescribeCounter(GPUCounter counterID); diff --git a/renderdoc/driver/vulkan/vk_replay.cpp b/renderdoc/driver/vulkan/vk_replay.cpp index f0a982502..9a2232676 100644 --- a/renderdoc/driver/vulkan/vk_replay.cpp +++ b/renderdoc/driver/vulkan/vk_replay.cpp @@ -4914,6 +4914,12 @@ void VulkanReplay::FreeTargetResource(ResourceId id) m_pDriver->ReleaseResource(GetResourceManager()->GetCurrentResource(id)); } +void VulkanReplay::ClearReplayCache() +{ + ClearPostVSCache(); + ClearFeedbackCache(); +} + void VulkanReplay::ReplaceResource(ResourceId from, ResourceId to) { // remove existing shader replacement diff --git a/renderdoc/driver/vulkan/vk_replay.h b/renderdoc/driver/vulkan/vk_replay.h index da4811e08..ca0c6b164 100644 --- a/renderdoc/driver/vulkan/vk_replay.h +++ b/renderdoc/driver/vulkan/vk_replay.h @@ -418,6 +418,7 @@ public: void ReplaceResource(ResourceId from, ResourceId to); void RemoveReplacement(ResourceId id); + void ClearReplayCache(); void RenderMesh(uint32_t eventId, const rdcarray &secondaryDraws, const MeshDisplay &cfg); diff --git a/renderdoc/replay/dummy_driver.cpp b/renderdoc/replay/dummy_driver.cpp index b33553003..7310dd1b7 100644 --- a/renderdoc/replay/dummy_driver.cpp +++ b/renderdoc/replay/dummy_driver.cpp @@ -261,6 +261,10 @@ void DummyDriver::FreeTargetResource(ResourceId id) { } +void DummyDriver::ClearReplayCache() +{ +} + rdcarray DummyDriver::EnumerateCounters() { return {}; diff --git a/renderdoc/replay/dummy_driver.h b/renderdoc/replay/dummy_driver.h index e4692a543..fb9a7251e 100644 --- a/renderdoc/replay/dummy_driver.h +++ b/renderdoc/replay/dummy_driver.h @@ -97,6 +97,7 @@ public: void ReplaceResource(ResourceId from, ResourceId to); void RemoveReplacement(ResourceId id); void FreeTargetResource(ResourceId id); + void ClearReplayCache(); rdcarray EnumerateCounters(); CounterDescription DescribeCounter(GPUCounter counterID); diff --git a/renderdoc/replay/replay_controller.cpp b/renderdoc/replay/replay_controller.cpp index 0830a74c6..1dbebad25 100644 --- a/renderdoc/replay/replay_controller.cpp +++ b/renderdoc/replay/replay_controller.cpp @@ -2174,6 +2174,13 @@ void ReplayController::RemoveReplacement(ResourceId id) m_Outputs[i]->Display(); } +void ReplayController::ClearReplayCache() +{ + CHECK_REPLAY_THREAD(); + + m_pDevice->ClearReplayCache(); +} + RDResult ReplayController::CreateDevice(RDCFile *rdc, const ReplayOptions &opts) { CHECK_REPLAY_THREAD(); diff --git a/renderdoc/replay/replay_controller.h b/renderdoc/replay/replay_controller.h index 6a55f0662..bda3b4e5c 100644 --- a/renderdoc/replay/replay_controller.h +++ b/renderdoc/replay/replay_controller.h @@ -178,6 +178,7 @@ public: void ReplaceResource(ResourceId from, ResourceId to); void RemoveReplacement(ResourceId id); void FreeTargetResource(ResourceId id); + void ClearReplayCache(); FrameDescription GetFrameInfo(); const SDFile &GetStructuredFile(); diff --git a/renderdoc/replay/replay_driver.h b/renderdoc/replay/replay_driver.h index 2a18388b4..f9228266b 100644 --- a/renderdoc/replay/replay_driver.h +++ b/renderdoc/replay/replay_driver.h @@ -213,6 +213,7 @@ public: virtual void ReplaceResource(ResourceId from, ResourceId to) = 0; virtual void RemoveReplacement(ResourceId id) = 0; virtual void FreeTargetResource(ResourceId id) = 0; + virtual void ClearReplayCache() = 0; virtual rdcarray EnumerateCounters() = 0; virtual CounterDescription DescribeCounter(GPUCounter counterID) = 0;