mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-06 06:51:18 +12:00
add an option to capture GPU frame
This commit is contained in:
parent
40dab1e212
commit
1d8806cf06
3 changed files with 71 additions and 0 deletions
|
@ -303,6 +303,17 @@ void MetalRenderer::SwapBuffers(bool swapTV, bool swapDRC)
|
||||||
|
|
||||||
// Debug
|
// Debug
|
||||||
m_performanceMonitor.ResetPerFrameData();
|
m_performanceMonitor.ResetPerFrameData();
|
||||||
|
|
||||||
|
// GPU capture
|
||||||
|
if (m_capturing)
|
||||||
|
{
|
||||||
|
EndCapture();
|
||||||
|
}
|
||||||
|
else if (m_captureFrame)
|
||||||
|
{
|
||||||
|
StartCapture();
|
||||||
|
m_captureFrame = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetalRenderer::HandleScreenshotRequest(LatteTextureView* texView, bool padView) {
|
void MetalRenderer::HandleScreenshotRequest(LatteTextureView* texView, bool padView) {
|
||||||
|
@ -2161,3 +2172,27 @@ void MetalRenderer::EnsureImGuiBackend()
|
||||||
//ImGui_ImplMetal_CreateFontsTexture(m_device);
|
//ImGui_ImplMetal_CreateFontsTexture(m_device);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MetalRenderer::StartCapture()
|
||||||
|
{
|
||||||
|
auto captureManager = MTL::CaptureManager::sharedCaptureManager();
|
||||||
|
auto desc = MTL::CaptureDescriptor::alloc()->init();
|
||||||
|
desc->setCaptureObject(m_device);
|
||||||
|
|
||||||
|
NS::Error* error = nullptr;
|
||||||
|
captureManager->startCapture(desc, &error);
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
cemuLog_log(LogType::Force, "Failed to start GPU capture: {}", error->localizedDescription()->utf8String());
|
||||||
|
}
|
||||||
|
|
||||||
|
m_capturing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MetalRenderer::EndCapture()
|
||||||
|
{
|
||||||
|
auto captureManager = MTL::CaptureManager::sharedCaptureManager();
|
||||||
|
captureManager->stopCapture();
|
||||||
|
|
||||||
|
m_capturing = false;
|
||||||
|
}
|
||||||
|
|
|
@ -460,6 +460,12 @@ public:
|
||||||
m_occlusionQuery.m_lastCommandBuffer = GetAndRetainCurrentCommandBufferIfNotCompleted();
|
m_occlusionQuery.m_lastCommandBuffer = GetAndRetainCurrentCommandBufferIfNotCompleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GPU capture
|
||||||
|
void CaptureFrame()
|
||||||
|
{
|
||||||
|
m_captureFrame = true;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MetalLayerHandle m_mainLayer;
|
MetalLayerHandle m_mainLayer;
|
||||||
MetalLayerHandle m_padLayer;
|
MetalLayerHandle m_padLayer;
|
||||||
|
@ -533,6 +539,11 @@ private:
|
||||||
// State
|
// State
|
||||||
MetalState m_state;
|
MetalState m_state;
|
||||||
|
|
||||||
|
// GPU capture
|
||||||
|
bool m_captureFrame = false;
|
||||||
|
bool m_capturing = false;
|
||||||
|
|
||||||
|
// Helpers
|
||||||
MetalLayerHandle& GetLayer(bool mainWindow)
|
MetalLayerHandle& GetLayer(bool mainWindow)
|
||||||
{
|
{
|
||||||
return (mainWindow ? m_mainLayer : m_padLayer);
|
return (mainWindow ? m_mainLayer : m_padLayer);
|
||||||
|
@ -541,4 +552,8 @@ private:
|
||||||
void SwapBuffer(bool mainWindow);
|
void SwapBuffer(bool mainWindow);
|
||||||
|
|
||||||
void EnsureImGuiBackend();
|
void EnsureImGuiBackend();
|
||||||
|
|
||||||
|
// GPU capture
|
||||||
|
void StartCapture();
|
||||||
|
void EndCapture();
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
|
||||||
|
#include "Cafe/HW/Latte/Renderer/Renderer.h"
|
||||||
#include "gui/wxgui.h"
|
#include "gui/wxgui.h"
|
||||||
#include "gui/MainWindow.h"
|
#include "gui/MainWindow.h"
|
||||||
#include "gui/guiWrapper.h"
|
#include "gui/guiWrapper.h"
|
||||||
|
@ -137,6 +139,7 @@ enum
|
||||||
MAINFRAME_MENU_ID_DEBUG_VIEW_TEXTURE_RELATIONS,
|
MAINFRAME_MENU_ID_DEBUG_VIEW_TEXTURE_RELATIONS,
|
||||||
MAINFRAME_MENU_ID_DEBUG_AUDIO_AUX_ONLY,
|
MAINFRAME_MENU_ID_DEBUG_AUDIO_AUX_ONLY,
|
||||||
MAINFRAME_MENU_ID_DEBUG_VK_ACCURATE_BARRIERS,
|
MAINFRAME_MENU_ID_DEBUG_VK_ACCURATE_BARRIERS,
|
||||||
|
MAINFRAME_MENU_ID_DEBUG_GPU_CAPTURE,
|
||||||
|
|
||||||
// debug->logging
|
// debug->logging
|
||||||
MAINFRAME_MENU_ID_DEBUG_LOGGING0 = 21500,
|
MAINFRAME_MENU_ID_DEBUG_LOGGING0 = 21500,
|
||||||
|
@ -212,6 +215,7 @@ EVT_MENU(MAINFRAME_MENU_ID_DEBUG_DUMP_CURL_REQUESTS, MainWindow::OnDebugSetting)
|
||||||
EVT_MENU(MAINFRAME_MENU_ID_DEBUG_RENDER_UPSIDE_DOWN, MainWindow::OnDebugSetting)
|
EVT_MENU(MAINFRAME_MENU_ID_DEBUG_RENDER_UPSIDE_DOWN, MainWindow::OnDebugSetting)
|
||||||
EVT_MENU(MAINFRAME_MENU_ID_DEBUG_AUDIO_AUX_ONLY, MainWindow::OnDebugSetting)
|
EVT_MENU(MAINFRAME_MENU_ID_DEBUG_AUDIO_AUX_ONLY, MainWindow::OnDebugSetting)
|
||||||
EVT_MENU(MAINFRAME_MENU_ID_DEBUG_VK_ACCURATE_BARRIERS, MainWindow::OnDebugSetting)
|
EVT_MENU(MAINFRAME_MENU_ID_DEBUG_VK_ACCURATE_BARRIERS, MainWindow::OnDebugSetting)
|
||||||
|
EVT_MENU(MAINFRAME_MENU_ID_DEBUG_GPU_CAPTURE, MainWindow::OnDebugSetting)
|
||||||
EVT_MENU(MAINFRAME_MENU_ID_DEBUG_DUMP_RAM, MainWindow::OnDebugSetting)
|
EVT_MENU(MAINFRAME_MENU_ID_DEBUG_DUMP_RAM, MainWindow::OnDebugSetting)
|
||||||
EVT_MENU(MAINFRAME_MENU_ID_DEBUG_DUMP_FST, MainWindow::OnDebugSetting)
|
EVT_MENU(MAINFRAME_MENU_ID_DEBUG_DUMP_FST, MainWindow::OnDebugSetting)
|
||||||
// debug -> View ...
|
// debug -> View ...
|
||||||
|
@ -1007,6 +1011,20 @@ void MainWindow::OnDebugSetting(wxCommandEvent& event)
|
||||||
if(!GetConfig().vk_accurate_barriers)
|
if(!GetConfig().vk_accurate_barriers)
|
||||||
wxMessageBox(_("Warning: Disabling the accurate barriers option will lead to flickering graphics but may improve performance. It is highly recommended to leave it turned on."), _("Accurate barriers are off"), wxOK);
|
wxMessageBox(_("Warning: Disabling the accurate barriers option will lead to flickering graphics but may improve performance. It is highly recommended to leave it turned on."), _("Accurate barriers are off"), wxOK);
|
||||||
}
|
}
|
||||||
|
else if (event.GetId() == MAINFRAME_MENU_ID_DEBUG_GPU_CAPTURE)
|
||||||
|
{
|
||||||
|
#if ENABLE_METAL
|
||||||
|
if (g_renderer->GetType() == RendererAPI::Metal)
|
||||||
|
{
|
||||||
|
static_cast<MetalRenderer*>(g_renderer.get())->CaptureFrame();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxMessageBox(_("GPU capture is only supported on Metal."), _("Error"), wxOK | wxCENTRE | wxICON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
else if (event.GetId() == MAINFRAME_MENU_ID_DEBUG_AUDIO_AUX_ONLY)
|
else if (event.GetId() == MAINFRAME_MENU_ID_DEBUG_AUDIO_AUX_ONLY)
|
||||||
ActiveSettings::EnableAudioOnlyAux(event.IsChecked());
|
ActiveSettings::EnableAudioOnlyAux(event.IsChecked());
|
||||||
else if (event.GetId() == MAINFRAME_MENU_ID_DEBUG_DUMP_RAM)
|
else if (event.GetId() == MAINFRAME_MENU_ID_DEBUG_DUMP_RAM)
|
||||||
|
@ -2254,6 +2272,9 @@ void MainWindow::RecreateMenu()
|
||||||
auto accurateBarriers = debugMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_VK_ACCURATE_BARRIERS, _("&Accurate barriers (Vulkan)"), wxEmptyString);
|
auto accurateBarriers = debugMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_VK_ACCURATE_BARRIERS, _("&Accurate barriers (Vulkan)"), wxEmptyString);
|
||||||
accurateBarriers->Check(GetConfig().vk_accurate_barriers);
|
accurateBarriers->Check(GetConfig().vk_accurate_barriers);
|
||||||
|
|
||||||
|
auto gpuCapture = debugMenu->Append(MAINFRAME_MENU_ID_DEBUG_VK_ACCURATE_BARRIERS, _("&GPU capture (Metal)"), wxEmptyString);
|
||||||
|
gpuCapture->Enable(m_game_launched && g_renderer->GetType() == RendererAPI::Metal);
|
||||||
|
|
||||||
debugMenu->AppendSeparator();
|
debugMenu->AppendSeparator();
|
||||||
|
|
||||||
#ifdef CEMU_DEBUG_ASSERT
|
#ifdef CEMU_DEBUG_ASSERT
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue