mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-06-04 17:53:17 +00:00
Render without rendering (#2152)
* presenter: render the game inside a ImGui window * presenter: render the previous frame to keep the render rendering * swapchain: fix swapchain image view format not being converted to unorm * devtools: fix frame graph timing
This commit is contained in:
parent
440a693fae
commit
56a6c95730
19 changed files with 306 additions and 110 deletions
|
@ -131,6 +131,8 @@ class DebugStateImpl {
|
|||
friend class Core::Devtools::Widget::FrameGraph;
|
||||
friend class Core::Devtools::Widget::ShaderList;
|
||||
|
||||
bool showing_debug_menu_bar = false;
|
||||
|
||||
std::queue<std::string> debug_message_popup;
|
||||
|
||||
std::mutex guest_threads_mutex{};
|
||||
|
@ -153,6 +155,9 @@ class DebugStateImpl {
|
|||
std::vector<ShaderDump> shader_dump_list{};
|
||||
|
||||
public:
|
||||
float Framerate = 1.0f / 60.0f;
|
||||
float FrameDeltaTime;
|
||||
|
||||
void ShowDebugMessage(std::string message) {
|
||||
if (message.empty()) {
|
||||
return;
|
||||
|
@ -160,6 +165,10 @@ public:
|
|||
debug_message_popup.push(std::move(message));
|
||||
}
|
||||
|
||||
bool& ShowingDebugMenuBar() {
|
||||
return showing_debug_menu_bar;
|
||||
}
|
||||
|
||||
void AddCurrentThreadToGuestList();
|
||||
|
||||
void RemoveCurrentThreadFromGuestList();
|
||||
|
|
|
@ -28,7 +28,6 @@ static bool show_simple_fps = false;
|
|||
static bool visibility_toggled = false;
|
||||
|
||||
static float fps_scale = 1.0f;
|
||||
static bool show_advanced_debug = false;
|
||||
static int dump_frame_count = 1;
|
||||
|
||||
static Widget::FrameGraph frame_graph;
|
||||
|
@ -253,8 +252,8 @@ void L::DrawAdvanced() {
|
|||
}
|
||||
|
||||
void L::DrawSimple() {
|
||||
const auto io = GetIO();
|
||||
Text("%.1f FPS (%.2f ms)", io.Framerate, 1000.0f / io.Framerate);
|
||||
const float frameRate = DebugState.Framerate;
|
||||
Text("%d FPS (%.1f ms)", static_cast<int>(std::round(1.0f / frameRate)), frameRate * 1000.0f);
|
||||
}
|
||||
|
||||
static void LoadSettings(const char* line) {
|
||||
|
@ -265,7 +264,7 @@ static void LoadSettings(const char* line) {
|
|||
return;
|
||||
}
|
||||
if (sscanf(line, "show_advanced_debug=%d", &i) == 1) {
|
||||
show_advanced_debug = i != 0;
|
||||
DebugState.ShowingDebugMenuBar() = i != 0;
|
||||
return;
|
||||
}
|
||||
if (sscanf(line, "show_frame_graph=%d", &i) == 1) {
|
||||
|
@ -310,7 +309,7 @@ void L::SetupSettings() {
|
|||
handler.WriteAllFn = [](ImGuiContext*, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf) {
|
||||
buf->appendf("[%s][Data]\n", handler->TypeName);
|
||||
buf->appendf("fps_scale=%f\n", fps_scale);
|
||||
buf->appendf("show_advanced_debug=%d\n", show_advanced_debug);
|
||||
buf->appendf("show_advanced_debug=%d\n", DebugState.ShowingDebugMenuBar());
|
||||
buf->appendf("show_frame_graph=%d\n", frame_graph.is_open);
|
||||
buf->appendf("dump_frame_count=%d\n", dump_frame_count);
|
||||
buf->append("\n");
|
||||
|
@ -336,12 +335,12 @@ void L::Draw() {
|
|||
|
||||
if (!DebugState.IsGuestThreadsPaused()) {
|
||||
const auto fn = DebugState.flip_frame_count.load();
|
||||
frame_graph.AddFrame(fn, io.DeltaTime);
|
||||
frame_graph.AddFrame(fn, DebugState.FrameDeltaTime);
|
||||
}
|
||||
|
||||
if (IsKeyPressed(ImGuiKey_F10, false)) {
|
||||
if (io.KeyCtrl) {
|
||||
show_advanced_debug = !show_advanced_debug;
|
||||
DebugState.ShowingDebugMenuBar() ^= true;
|
||||
} else {
|
||||
show_simple_fps = !show_simple_fps;
|
||||
}
|
||||
|
@ -376,7 +375,7 @@ void L::Draw() {
|
|||
End();
|
||||
}
|
||||
|
||||
if (show_advanced_debug) {
|
||||
if (DebugState.ShowingDebugMenuBar()) {
|
||||
PushFont(io.Fonts->Fonts[IMGUI_FONT_MONO]);
|
||||
PushID("DevtoolsLayer");
|
||||
DrawAdvanced();
|
||||
|
|
|
@ -83,15 +83,13 @@ void FrameGraph::Draw() {
|
|||
|
||||
auto isSystemPaused = DebugState.IsGuestThreadsPaused();
|
||||
|
||||
static float deltaTime;
|
||||
static float frameRate;
|
||||
|
||||
if (!isSystemPaused) {
|
||||
deltaTime = io.DeltaTime * 1000.0f;
|
||||
deltaTime = DebugState.FrameDeltaTime * 1000.0f;
|
||||
frameRate = 1000.0f / deltaTime;
|
||||
}
|
||||
|
||||
Text("Frame time: %.3f ms (%.1f FPS)", deltaTime, frameRate);
|
||||
Text("Presenter time: %.3f ms (%.1f FPS)", io.DeltaTime * 1000.0f, 1.0f / io.DeltaTime);
|
||||
Text("Flip frame: %d Gnm submit frame: %d", DebugState.flip_frame_count.load(),
|
||||
DebugState.gnm_frame_count.load());
|
||||
|
||||
|
|
|
@ -16,6 +16,9 @@ class FrameGraph {
|
|||
|
||||
std::array<FrameInfo, FRAME_BUFFER_SIZE> frame_list{};
|
||||
|
||||
float deltaTime{};
|
||||
float frameRate{};
|
||||
|
||||
void DrawFrameGraph();
|
||||
|
||||
public:
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/config.h"
|
||||
#include "common/debug.h"
|
||||
|
@ -207,6 +205,13 @@ void VideoOutDriver::DrawBlankFrame() {
|
|||
presenter->Present(empty_frame);
|
||||
}
|
||||
|
||||
void VideoOutDriver::DrawLastFrame() {
|
||||
const auto frame = presenter->PrepareLastFrame();
|
||||
if (frame != nullptr) {
|
||||
presenter->Present(frame, true);
|
||||
}
|
||||
}
|
||||
|
||||
bool VideoOutDriver::SubmitFlip(VideoOutPort* port, s32 index, s64 flip_arg,
|
||||
bool is_eop /*= false*/) {
|
||||
{
|
||||
|
@ -278,17 +283,24 @@ void VideoOutDriver::PresentThread(std::stop_token token) {
|
|||
return {};
|
||||
};
|
||||
|
||||
auto delay = std::chrono::microseconds{0};
|
||||
while (!token.stop_requested()) {
|
||||
timer.Start();
|
||||
|
||||
if (DebugState.IsGuestThreadsPaused()) {
|
||||
DrawLastFrame();
|
||||
timer.End();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if it's time to take a request.
|
||||
auto& vblank_status = main_port.vblank_status;
|
||||
if (vblank_status.count % (main_port.flip_rate + 1) == 0) {
|
||||
const auto request = receive_request();
|
||||
if (!request) {
|
||||
if (!main_port.is_open || DebugState.IsGuestThreadsPaused()) {
|
||||
if (!main_port.is_open) {
|
||||
DrawBlankFrame();
|
||||
} else {
|
||||
DrawLastFrame();
|
||||
}
|
||||
} else {
|
||||
Flip(request);
|
||||
|
|
|
@ -102,7 +102,8 @@ private:
|
|||
};
|
||||
|
||||
void Flip(const Request& req);
|
||||
void DrawBlankFrame(); // Used when there is no flip request to keep ImGui up to date
|
||||
void DrawBlankFrame(); // Video port out not open
|
||||
void DrawLastFrame(); // Used when there is no flip request
|
||||
void SubmitFlipInternal(VideoOutPort* port, s32 index, s64 flip_arg, bool is_eop = false);
|
||||
void PresentThread(std::stop_token token);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue