Devtools: PM4 Explorer (#1094)

* Devtools: Pause system

* Devtools: pm4 viewer

- new menu bar
- refactored video_info layer
- dump & inspect pm4 packets
- removed dumpPM4 config
- renamed System to DebugState
- add docking space
- simple video info constrained to window size

* Devtools: pm4 viewer - add combo to select the queue

* Devtools: pm4 viewer - add hex editor

* Devtools: pm4 viewer - dump current cmd

* add monospaced font to devtools

* Devtools: pm4 viewer - use spec op name

avoid some allocations
This commit is contained in:
Vinicius Rangel 2024-10-03 17:43:23 -03:00 committed by GitHub
parent 009f956d8d
commit af398e3684
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
46 changed files with 19323 additions and 242 deletions

View file

@ -10,6 +10,9 @@
#define IM_COL32_GRAY(x) IM_COL32(x, x, x, 0xFF)
#define IMGUI_FONT_TEXT 0
#define IMGUI_FONT_MONO 1
namespace ImGui {
namespace Easing {
@ -27,6 +30,20 @@ inline void CentralizeWindow() {
SetNextWindowPos(display_size / 2.0f, ImGuiCond_Always, {0.5f});
}
inline void KeepWindowInside(ImVec2 display_size = GetIO().DisplaySize) {
const auto cur_pos = GetWindowPos();
if (cur_pos.x < 0.0f || cur_pos.y < 0.0f) {
SetWindowPos(ImMax(cur_pos, ImVec2(0.0f, 0.0f)));
return;
}
const auto cur_size = GetWindowSize();
const auto bottom_right = cur_pos + cur_size;
if (bottom_right.x > display_size.x || bottom_right.y > display_size.y) {
const auto max_pos = display_size - cur_size;
SetWindowPos(ImMin(cur_pos, max_pos));
}
}
inline void KeepNavHighlight() {
GetCurrentContext()->NavDisableHighlight = false;
}

View file

@ -1,121 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <imgui.h>
#include "common/config.h"
#include "common/types.h"
#include "imgui_internal.h"
#include "video_info.h"
using namespace ImGui;
struct FrameInfo {
u32 num;
float delta;
};
static bool show = false;
static bool show_advanced = false;
static u32 current_frame = 0;
constexpr float TARGET_FPS = 60.0f;
constexpr u32 FRAME_BUFFER_SIZE = 1024;
constexpr float BAR_WIDTH_MULT = 1.4f;
constexpr float BAR_HEIGHT_MULT = 1.25f;
constexpr float FRAME_GRAPH_PADDING_Y = 3.0f;
static std::array<FrameInfo, FRAME_BUFFER_SIZE> frame_list;
static float frame_graph_height = 50.0f;
static void DrawSimple() {
const auto io = GetIO();
Text("FPS: %.1f (%.3f ms)", io.Framerate, 1000.0f / io.Framerate);
}
static void DrawAdvanced() {
const auto& ctx = *GetCurrentContext();
const auto& io = ctx.IO;
const auto& window = *ctx.CurrentWindow;
auto& draw_list = *window.DrawList;
Text("Frame time: %.3f ms (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
SeparatorText("Frame graph");
const float full_width = GetContentRegionAvail().x;
{ // Frame graph - inspired by
// https://asawicki.info/news_1758_an_idea_for_visualization_of_frame_times
auto pos = GetCursorScreenPos();
const ImVec2 size{full_width, frame_graph_height + FRAME_GRAPH_PADDING_Y * 2.0f};
ItemSize(size);
if (!ItemAdd({pos, pos + size}, GetID("FrameGraph"))) {
return;
}
float target_dt = 1.0f / (TARGET_FPS * (float)Config::vblankDiv());
float cur_pos_x = pos.x + full_width;
pos.y += FRAME_GRAPH_PADDING_Y;
const float final_pos_y = pos.y + frame_graph_height;
draw_list.AddRectFilled({pos.x, pos.y - FRAME_GRAPH_PADDING_Y},
{pos.x + full_width, final_pos_y + FRAME_GRAPH_PADDING_Y},
IM_COL32(0x33, 0x33, 0x33, 0xFF));
draw_list.PushClipRect({pos.x, pos.y}, {pos.x + full_width, final_pos_y}, true);
for (u32 i = 0; i < FRAME_BUFFER_SIZE; ++i) {
const auto& frame_info = frame_list[(current_frame - i) % FRAME_BUFFER_SIZE];
const float dt_factor = target_dt / frame_info.delta;
const float width = std::ceil(BAR_WIDTH_MULT / dt_factor);
const float height =
std::min(std::log2(BAR_HEIGHT_MULT / dt_factor) / 3.0f, 1.0f) * frame_graph_height;
ImU32 color;
if (dt_factor >= 0.95f) { // BLUE
color = IM_COL32(0x33, 0x33, 0xFF, 0xFF);
} else if (dt_factor >= 0.5f) { // GREEN <> YELLOW
float t = 1.0f - (dt_factor - 0.5f) * 2.0f;
int r = (int)(0xFF * t);
color = IM_COL32(r, 0xFF, 0, 0xFF);
} else { // YELLOW <> RED
float t = dt_factor * 2.0f;
int g = (int)(0xFF * t);
color = IM_COL32(0xFF, g, 0, 0xFF);
}
draw_list.AddRectFilled({cur_pos_x - width, final_pos_y - height},
{cur_pos_x, final_pos_y}, color);
cur_pos_x -= width;
if (cur_pos_x < width) {
break;
}
}
draw_list.PopClipRect();
}
}
void Layers::VideoInfo::Draw() {
const auto io = GetIO();
const FrameInfo frame_info{
.num = ++current_frame,
.delta = io.DeltaTime,
};
frame_list[current_frame % FRAME_BUFFER_SIZE] = frame_info;
if (IsKeyPressed(ImGuiKey_F10, false)) {
const bool changed_ctrl = io.KeyCtrl != show_advanced;
show_advanced = io.KeyCtrl;
show = changed_ctrl || !show;
}
if (show) {
if (show_advanced) {
if (Begin("Video Debug Info", nullptr, ImGuiWindowFlags_NoDecoration)) {
DrawAdvanced();
}
} else {
if (Begin("Video Info", nullptr, ImGuiWindowFlags_NoDecoration)) {
DrawSimple();
}
}
End();
}
}

View file

@ -1,22 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "imgui/imgui_layer.h"
namespace Vulkan {
class RendererVulkan;
}
namespace ImGui::Layers {
class VideoInfo : public Layer {
::Vulkan::RendererVulkan* renderer{};
public:
explicit VideoInfo(::Vulkan::RendererVulkan* renderer) : renderer(renderer) {}
void Draw() override;
};
} // namespace ImGui::Layers

View file

@ -7,6 +7,7 @@ add_executable(Dear_ImGui_FontEmbed ${CMAKE_SOURCE_DIR}/externals/dear_imgui/mis
set(FONT_LIST
NotoSansJP-Regular.ttf
ProggyVector-Regular.ttf
)
set(OutputList "")

Binary file not shown.

View file

@ -6,6 +6,7 @@
#include "common/config.h"
#include "common/path_util.h"
#include "core/devtools/layer.h"
#include "imgui/imgui_layer.h"
#include "imgui_core.h"
#include "imgui_impl_sdl3.h"
@ -16,6 +17,7 @@
#include "video_core/renderer_vulkan/renderer_vulkan.h"
#include "imgui_fonts/notosansjp_regular.ttf.g.cpp"
#include "imgui_fonts/proggyvector_regular.ttf.g.cpp"
static void CheckVkResult(const vk::Result err) {
LOG_ERROR(ImGui, "Vulkan error {}", vk::to_string(err));
@ -74,12 +76,16 @@ void Initialize(const ::Vulkan::Instance& instance, const Frontend::WindowSDL& w
ImFontConfig font_cfg{};
font_cfg.OversampleH = 2;
font_cfg.OversampleV = 1;
io.Fonts->AddFontFromMemoryCompressedTTF(imgui_font_notosansjp_regular_compressed_data,
imgui_font_notosansjp_regular_compressed_size, 16.0f,
&font_cfg, ranges.Data);
io.FontDefault = io.Fonts->AddFontFromMemoryCompressedTTF(
imgui_font_notosansjp_regular_compressed_data,
imgui_font_notosansjp_regular_compressed_size, 16.0f, &font_cfg, ranges.Data);
io.Fonts->AddFontFromMemoryCompressedTTF(imgui_font_proggyvector_regular_compressed_data,
imgui_font_proggyvector_regular_compressed_size,
16.0f);
StyleColorsDark();
::Core::Devtools::Layer::SetupSettings();
Sdl::Init(window.GetSdlWindow());
const Vulkan::InitInfo vk_info{
@ -166,6 +172,8 @@ void NewFrame() {
Sdl::NewFrame();
ImGui::NewFrame();
DockSpaceOverViewport(0, GetMainViewport(), ImGuiDockNodeFlags_PassthruCentralNode);
for (auto* layer : layers) {
layer->Draw();
}