diff --git a/src/graphics/guest_gpu/graphicsRun.cpp b/src/graphics/guest_gpu/graphicsRun.cpp index a68f70905..767866bc7 100644 --- a/src/graphics/guest_gpu/graphicsRun.cpp +++ b/src/graphics/guest_gpu/graphicsRun.cpp @@ -13,7 +13,6 @@ #include "graphics/host_gpu/renderer/render.h" #include "graphics/host_gpu/renderer/renderContext.h" #include "graphics/host_gpu/renderer/sync.h" -#include "graphics/presentation/renderDoc.h" #include "graphics/presentation/videoOut.h" #include "graphics/presentation/window.h" #include "graphics/shader/shader.h" @@ -561,10 +560,6 @@ void GuestGpu::ThreadRun(void* data) { bool GuestGpu::Process(Submission& submission) { const bool first_slice = !submission.started; - if (first_slice && RenderDocCaptureRequested()) { - Common::LockGuard render_lock(m_renderer.GetMutex()); - RenderDocStartCapture(); - } auto& cp = GetProcessor(submission.queue_id); if (first_slice && submission.reset_processor) { diff --git a/src/graphics/presentation/renderDoc.cpp b/src/graphics/presentation/renderDoc.cpp index 0bf7d7c7d..6c0af3021 100644 --- a/src/graphics/presentation/renderDoc.cpp +++ b/src/graphics/presentation/renderDoc.cpp @@ -1,6 +1,8 @@ #include "graphics/presentation/renderDoc.h" #include "common/logging/log.h" +#include "graphics/host_gpu/graphicContext.h" +#include "graphics/host_gpu/renderer/renderContext.h" #include #include @@ -25,13 +27,12 @@ namespace Libs::Graphics { enum class RenderDocState : uint32_t { Idle, Requested, - Starting, Capturing, }; static RENDERDOC_API_1_6_0* g_api = nullptr; static std::atomic g_state = RenderDocState::Idle; -static std::atomic_uint32_t g_captured_flips = 0; +static uint32_t g_captured_flips = 0; static std::atomic_bool g_unavailable_log = false; #if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS @@ -132,21 +133,7 @@ void RenderDocRequestCapture() { } } -bool RenderDocCaptureRequested() { - return g_state.load(std::memory_order_acquire) == RenderDocState::Requested; -} - -bool RenderDocCaptureInProgress() { - return g_state.load(std::memory_order_acquire) == RenderDocState::Capturing; -} - -void RenderDocStartCapture() { - RenderDocState expected = RenderDocState::Requested; - if (g_api == nullptr || !g_state.compare_exchange_strong(expected, RenderDocState::Starting, - std::memory_order_acq_rel)) { - return; - } - +static void StartCapture() { if (g_api->IsFrameCapturing() != 0) { g_state.store(RenderDocState::Idle, std::memory_order_release); LOGF("RenderDoc: capture request ignored because a capture is already active\n"); @@ -164,29 +151,32 @@ void RenderDocStartCapture() { LOGF("RenderDoc: capture failed to start\n"); return; } - g_captured_flips.store(0, std::memory_order_release); + g_captured_flips = 0; g_state.store(RenderDocState::Capturing, std::memory_order_release); LOGF("RenderDoc: capture started\n"); } -void RenderDocEndCapture() { - if (g_api == nullptr || !RenderDocCaptureInProgress()) { +void RenderDocOnGuestFlip(RenderContext& renderer) { + const auto state = g_state.load(std::memory_order_acquire); + if (g_api == nullptr || state == RenderDocState::Idle) { return; } - - const auto ok = g_api->EndFrameCapture(nullptr, nullptr); - g_state.store(RenderDocState::Idle, std::memory_order_release); - LOGF(ok != 0 ? "RenderDoc: capture finished\n" : "RenderDoc: capture failed\n"); -} - -void RenderDocOnGuestFlip() { - if (!RenderDocCaptureInProgress()) { - return; + if (state == RenderDocState::Capturing) { + LOGF("RenderDoc: captured guest flip %u/2\n", ++g_captured_flips); + if (g_captured_flips < 2) { + return; + } } - const auto flip = g_captured_flips.fetch_add(1, std::memory_order_acq_rel) + 1; - LOGF("RenderDoc: captured guest flip %u/2\n", flip); - if (flip >= 2) { - RenderDocEndCapture(); + + // Capture boundaries follow presentation and exclude concurrent queue access. + Common::LockGuard render_lock(renderer.GetMutex()); + Common::LockGuard queue_lock(renderer.GetGraphics().queue_mutex); + if (state == RenderDocState::Requested) { + StartCapture(); + } else { + const auto ok = g_api->EndFrameCapture(nullptr, nullptr); + g_state.store(RenderDocState::Idle, std::memory_order_release); + LOGF(ok != 0 ? "RenderDoc: capture finished\n" : "RenderDoc: capture failed\n"); } } diff --git a/src/graphics/presentation/renderDoc.h b/src/graphics/presentation/renderDoc.h index 28e67aea2..4294ce6c1 100644 --- a/src/graphics/presentation/renderDoc.h +++ b/src/graphics/presentation/renderDoc.h @@ -3,14 +3,12 @@ namespace Libs::Graphics { +class RenderContext; + void RenderDocInit(); void RenderDocRequestCapture(); -void RenderDocStartCapture(); -void RenderDocEndCapture(); -void RenderDocOnGuestFlip(); - -[[nodiscard]] bool RenderDocCaptureRequested(); -[[nodiscard]] bool RenderDocCaptureInProgress(); +// Called by the presentation thread after releasing video-out locks. +void RenderDocOnGuestFlip(RenderContext& renderer); } // namespace Libs::Graphics diff --git a/src/graphics/presentation/videoOut.cpp b/src/graphics/presentation/videoOut.cpp index 957ccf53a..0bdae5c86 100644 --- a/src/graphics/presentation/videoOut.cpp +++ b/src/graphics/presentation/videoOut.cpp @@ -1123,7 +1123,6 @@ bool FlipQueue::Flip(uint32_t micros) { m_mutex.Unlock(); m_presenter.Present(*r.frame); - Graphics::RenderDocOnGuestFlip(); m_mutex.Lock(); if (m_requests.empty() || m_requests.front().id != r.id || @@ -1150,6 +1149,8 @@ bool FlipQueue::Flip(uint32_t micros) { m_mutex.Unlock(); r.cfg->mutex.Unlock(); + Graphics::RenderDocOnGuestFlip(m_presenter.Renderer()); + if (Config::GraphicsDebugDumpEnabled() && Config::GetPrintfDirection() != Config::OutputDirection::Silent) { LOGF("Flip done: %d\n", r.index);