mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-08-04 08:22:32 +00:00
devtools: pm4 - show color buffer info as popup
add ux improvements for open new windows with shift+click better window titles
This commit is contained in:
parent
ccd997c6a6
commit
dbce929d7b
@ -353,16 +353,18 @@ set(DEV_TOOLS src/core/devtools/layer.cpp
|
|||||||
src/core/devtools/gcn/gcn_shader_regs.cpp
|
src/core/devtools/gcn/gcn_shader_regs.cpp
|
||||||
src/core/devtools/widget/cmd_list.cpp
|
src/core/devtools/widget/cmd_list.cpp
|
||||||
src/core/devtools/widget/cmd_list.h
|
src/core/devtools/widget/cmd_list.h
|
||||||
|
src/core/devtools/widget/common.h
|
||||||
src/core/devtools/widget/frame_dump.cpp
|
src/core/devtools/widget/frame_dump.cpp
|
||||||
src/core/devtools/widget/frame_dump.h
|
src/core/devtools/widget/frame_dump.h
|
||||||
src/core/devtools/widget/frame_graph.cpp
|
src/core/devtools/widget/frame_graph.cpp
|
||||||
src/core/devtools/widget/frame_graph.h
|
src/core/devtools/widget/frame_graph.h
|
||||||
src/core/devtools/widget/imgui_memory_editor.h
|
src/core/devtools/widget/imgui_memory_editor.h
|
||||||
|
src/core/devtools/widget/reg_popup.cpp
|
||||||
|
src/core/devtools/widget/reg_popup.h
|
||||||
src/core/devtools/widget/reg_view.cpp
|
src/core/devtools/widget/reg_view.cpp
|
||||||
src/core/devtools/widget/reg_view.h
|
src/core/devtools/widget/reg_view.h
|
||||||
src/core/devtools/widget/text_editor.cpp
|
src/core/devtools/widget/text_editor.cpp
|
||||||
src/core/devtools/widget/text_editor.h
|
src/core/devtools/widget/text_editor.h
|
||||||
src/core/devtools/widget/types.h
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set(COMMON src/common/logging/backend.cpp
|
set(COMMON src/common/logging/backend.cpp
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <imgui.h>
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/native_clock.h"
|
#include "common/native_clock.h"
|
||||||
#include "common/singleton.h"
|
#include "common/singleton.h"
|
||||||
#include "debug_state.h"
|
#include "debug_state.h"
|
||||||
#include "devtools/widget/types.h"
|
#include "devtools/widget/common.h"
|
||||||
#include "libraries/kernel/time_management.h"
|
#include "libraries/kernel/time_management.h"
|
||||||
#include "libraries/system/msgdialog.h"
|
#include "libraries/system/msgdialog.h"
|
||||||
#include "video_core/amdgpu/pm4_cmds.h"
|
#include "video_core/amdgpu/pm4_cmds.h"
|
||||||
|
@ -105,9 +105,15 @@ void L::DrawAdvanced() {
|
|||||||
DebugState.should_show_frame_dump = false;
|
DebugState.should_show_frame_dump = false;
|
||||||
std::unique_lock lock{DebugState.frame_dump_list_mutex};
|
std::unique_lock lock{DebugState.frame_dump_list_mutex};
|
||||||
while (!DebugState.frame_dump_list.empty()) {
|
while (!DebugState.frame_dump_list.empty()) {
|
||||||
auto frame_dump = std::move(DebugState.frame_dump_list.back());
|
const auto& frame_dump = DebugState.frame_dump_list.back();
|
||||||
DebugState.frame_dump_list.pop_back();
|
|
||||||
frame_viewers.emplace_back(frame_dump);
|
frame_viewers.emplace_back(frame_dump);
|
||||||
|
DebugState.frame_dump_list.pop_back();
|
||||||
|
}
|
||||||
|
static bool first_time = true;
|
||||||
|
if (first_time) {
|
||||||
|
first_time = false;
|
||||||
|
DebugState.ShowDebugMessage("Tip: You can shift+click any\n"
|
||||||
|
"popup to open a new window");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,6 +63,21 @@ static HdrType GetNext(HdrType this_pm4, uint32_t n) {
|
|||||||
return curr_pm4;
|
return curr_pm4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool IsDrawCall(AmdGpu::PM4ItOpcode opcode) {
|
||||||
|
using AmdGpu::PM4ItOpcode;
|
||||||
|
switch (opcode) {
|
||||||
|
case PM4ItOpcode::DispatchDirect:
|
||||||
|
case PM4ItOpcode::DispatchIndirect:
|
||||||
|
case PM4ItOpcode::DrawIndex2:
|
||||||
|
case PM4ItOpcode::DrawIndexAuto:
|
||||||
|
case PM4ItOpcode::DrawIndexOffset2:
|
||||||
|
case PM4ItOpcode::DrawIndexIndirect:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ParsePolygonControl(u32 value, bool begin_table) {
|
void ParsePolygonControl(u32 value, bool begin_table) {
|
||||||
auto const reg = reinterpret_cast<AmdGpu::Liverpool::PolygonControl const&>(value);
|
auto const reg = reinterpret_cast<AmdGpu::Liverpool::PolygonControl const&>(value);
|
||||||
|
|
||||||
@ -888,7 +903,7 @@ void CmdListViewer::OnSetBase(AmdGpu::PM4Type3Header const* header, u32 const* b
|
|||||||
Separator();
|
Separator();
|
||||||
BeginGroup();
|
BeginGroup();
|
||||||
|
|
||||||
auto const* pkt = reinterpret_cast<AmdGpu::PM4CmdSetBase const*>(header);
|
// auto const* pkt = reinterpret_cast<AmdGpu::PM4CmdSetBase const*>(header);
|
||||||
Text("BASE_INDEX: %08X", body[0]);
|
Text("BASE_INDEX: %08X", body[0]);
|
||||||
Text("ADDRESS0 : %08X", body[1]);
|
Text("ADDRESS0 : %08X", body[1]);
|
||||||
Text("ADDRESS1 : %08X", body[2]);
|
Text("ADDRESS1 : %08X", body[2]);
|
||||||
@ -1077,9 +1092,10 @@ void CmdListViewer::OnDispatch(AmdGpu::PM4Type3Header const* header, u32 const*
|
|||||||
EndGroup();
|
EndGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
CmdListViewer::CmdListViewer(const FrameDumpViewer* parent, const std::vector<u32>& cmd_list,
|
CmdListViewer::CmdListViewer(DebugStateType::FrameDump* _frame_dump,
|
||||||
uintptr_t base_addr, std::string name)
|
const std::vector<u32>& cmd_list, uintptr_t _base_addr,
|
||||||
: parent(parent), base_addr(base_addr), name(std::move(name)) {
|
std::string _name)
|
||||||
|
: frame_dump(_frame_dump), base_addr(_base_addr), name(std::move(_name)) {
|
||||||
using namespace AmdGpu;
|
using namespace AmdGpu;
|
||||||
|
|
||||||
cmdb_addr = (uintptr_t)cmd_list.data();
|
cmdb_addr = (uintptr_t)cmd_list.data();
|
||||||
@ -1131,11 +1147,7 @@ CmdListViewer::CmdListViewer(const FrameDumpViewer* parent, const std::vector<u3
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opcode == PM4ItOpcode::DispatchDirect || opcode == PM4ItOpcode::DispatchIndirect ||
|
if (IsDrawCall(opcode)) {
|
||||||
opcode == PM4ItOpcode::DrawIndex2 || opcode == PM4ItOpcode::DrawIndexAuto ||
|
|
||||||
opcode == PM4ItOpcode::DrawIndexOffset2 || opcode == PM4ItOpcode::DrawIndexIndirect
|
|
||||||
// ...
|
|
||||||
) {
|
|
||||||
// All these commands are terminated by NOP at the end, so
|
// All these commands are terminated by NOP at the end, so
|
||||||
// it is safe to skip it to be even with CP
|
// it is safe to skip it to be even with CP
|
||||||
// next_pm4_hdr = get_next(next_pm4_hdr, 1);
|
// next_pm4_hdr = get_next(next_pm4_hdr, 1);
|
||||||
@ -1179,6 +1191,34 @@ CmdListViewer::CmdListViewer(const FrameDumpViewer* parent, const std::vector<u3
|
|||||||
void CmdListViewer::Draw() {
|
void CmdListViewer::Draw() {
|
||||||
const auto& ctx = *GetCurrentContext();
|
const auto& ctx = *GetCurrentContext();
|
||||||
|
|
||||||
|
if (batch_view.open) {
|
||||||
|
batch_view.Draw();
|
||||||
|
}
|
||||||
|
for (auto it = extra_batch_view.begin(); it != extra_batch_view.end();) {
|
||||||
|
if (!it->open) {
|
||||||
|
it = extra_batch_view.erase(it);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
it->Draw();
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdb_view.Open) {
|
||||||
|
MemoryEditor::Sizes s;
|
||||||
|
cmdb_view.CalcSizes(s, cmdb_size, cmdb_addr);
|
||||||
|
SetNextWindowSize({s.WindowWidth, s.WindowWidth * 0.6f}, ImGuiCond_FirstUseEver);
|
||||||
|
SetNextWindowSizeConstraints({0.0f}, {s.WindowWidth, FLT_MAX});
|
||||||
|
if (Begin(cmdb_view_name.c_str(), &cmdb_view.Open,
|
||||||
|
ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings)) {
|
||||||
|
cmdb_view.DrawContents((void*)cmdb_addr, cmdb_size, base_addr);
|
||||||
|
if (cmdb_view.ContentsWidthChanged) {
|
||||||
|
cmdb_view.CalcSizes(s, cmdb_size, cmdb_addr);
|
||||||
|
SetWindowSize({s.WindowWidth, s.WindowWidth * 0.6f});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
End();
|
||||||
|
}
|
||||||
|
|
||||||
PushID(name.c_str());
|
PushID(name.c_str());
|
||||||
if (BeginChild("cmd_queue", {})) {
|
if (BeginChild("cmd_queue", {})) {
|
||||||
|
|
||||||
@ -1213,10 +1253,17 @@ void CmdListViewer::Draw() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
u32 batch_id = ~0u;
|
u32 batch_id = ~0u;
|
||||||
s32 current_highlight_batch = -1;
|
u32 current_highlight_batch = ~0u;
|
||||||
|
|
||||||
|
int id = 0;
|
||||||
|
PushID(0);
|
||||||
for (const auto& event : events) {
|
for (const auto& event : events) {
|
||||||
auto processed_size = 0ull;
|
PopID();
|
||||||
|
PushID(id++);
|
||||||
|
|
||||||
|
if (std::holds_alternative<BatchBegin>(event)) {
|
||||||
|
batch_id = std::get<BatchBegin>(event).id;
|
||||||
|
}
|
||||||
|
|
||||||
if (show_markers) {
|
if (show_markers) {
|
||||||
if (std::holds_alternative<PushMarker>(event)) {
|
if (std::holds_alternative<PushMarker>(event)) {
|
||||||
@ -1243,11 +1290,6 @@ void CmdListViewer::Draw() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::holds_alternative<BatchBegin>(event)) {
|
|
||||||
batch_id = std::get<BatchBegin>(event).id;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!std::holds_alternative<BatchInfo>(event)) {
|
if (!std::holds_alternative<BatchInfo>(event)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1274,15 +1316,35 @@ void CmdListViewer::Draw() {
|
|||||||
PushStyleColor(ImGuiCol_Text, ImVec4{1.0f, 0.7f, 0.7f, 1.0f});
|
PushStyleColor(ImGuiCol_Text, ImVec4{1.0f, 0.7f, 0.7f, 1.0f});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!group_batches || CollapsingHeader(batch_hdr)) {
|
const auto open_batch_view = [&, this] {
|
||||||
auto bb = ctx.LastItemData.Rect;
|
if (frame_dump->regs.contains(batch.command_addr)) {
|
||||||
if (group_batches) {
|
auto data = frame_dump->regs.at(batch.command_addr);
|
||||||
if (IsItemToggledOpen()) {
|
if (GetIO().KeyShift) {
|
||||||
if (parent->frame_dump.regs.contains(batch.command_addr)) {
|
auto& pop = extra_batch_view.emplace_back();
|
||||||
batch_view.SetData(parent->frame_dump.regs.at(batch.command_addr));
|
pop.SetData(data, batch_id);
|
||||||
|
pop.open = true;
|
||||||
|
} else {
|
||||||
|
batch_view.SetData(data, batch_id);
|
||||||
batch_view.open = true;
|
batch_view.open = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
bool show_batch_content = true;
|
||||||
|
|
||||||
|
if (group_batches) {
|
||||||
|
show_batch_content =
|
||||||
|
CollapsingHeader(batch_hdr, ImGuiTreeNodeFlags_AllowOverlap);
|
||||||
|
SameLine(GetContentRegionAvail().x - 40.0f);
|
||||||
|
if (Button("->", {40.0f, 0.0f})) {
|
||||||
|
open_batch_view();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (show_batch_content) {
|
||||||
|
auto processed_size = 0ull;
|
||||||
|
auto bb = ctx.LastItemData.Rect;
|
||||||
|
if (group_batches) {
|
||||||
Indent();
|
Indent();
|
||||||
}
|
}
|
||||||
auto const batch_sz = batch.end_addr - batch.start_addr;
|
auto const batch_sz = batch.end_addr - batch.start_addr;
|
||||||
@ -1300,9 +1362,23 @@ void CmdListViewer::Draw() {
|
|||||||
cmdb_addr + batch.start_addr + processed_size,
|
cmdb_addr + batch.start_addr + processed_size,
|
||||||
Gcn::GetOpCodeName((u32)op));
|
Gcn::GetOpCodeName((u32)op));
|
||||||
|
|
||||||
if (TreeNode(header_name)) {
|
bool open_pm4 = TreeNode(header_name);
|
||||||
const bool just_opened = IsItemToggledOpen();
|
if (!group_batches) {
|
||||||
if (just_opened) {
|
if (IsDrawCall(op)) {
|
||||||
|
SameLine(GetContentRegionAvail().x - 40.0f);
|
||||||
|
if (Button("->", {40.0f, 0.0f})) {
|
||||||
|
open_batch_view();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (IsItemHovered() && ctx.IO.KeyShift) {
|
||||||
|
if (BeginTooltip()) {
|
||||||
|
Text("Batch %d", batch_id);
|
||||||
|
EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (open_pm4) {
|
||||||
|
if (IsItemToggledOpen()) {
|
||||||
// Editor
|
// Editor
|
||||||
cmdb_view.GotoAddrAndHighlight(
|
cmdb_view.GotoAddrAndHighlight(
|
||||||
reinterpret_cast<size_t>(pm4_hdr) - cmdb_addr,
|
reinterpret_cast<size_t>(pm4_hdr) - cmdb_addr,
|
||||||
@ -1383,6 +1459,7 @@ void CmdListViewer::Draw() {
|
|||||||
Separator();
|
Separator();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PopID();
|
||||||
|
|
||||||
highlight_batch = current_highlight_batch;
|
highlight_batch = current_highlight_batch;
|
||||||
|
|
||||||
@ -1391,34 +1468,6 @@ void CmdListViewer::Draw() {
|
|||||||
}
|
}
|
||||||
EndChild();
|
EndChild();
|
||||||
PopID();
|
PopID();
|
||||||
|
|
||||||
if (cmdb_view.Open) {
|
|
||||||
MemoryEditor::Sizes s;
|
|
||||||
cmdb_view.CalcSizes(s, cmdb_size, cmdb_addr);
|
|
||||||
SetNextWindowSize({s.WindowWidth, s.WindowWidth * 0.6f}, ImGuiCond_FirstUseEver);
|
|
||||||
SetNextWindowSizeConstraints({0.0f}, {s.WindowWidth, FLT_MAX});
|
|
||||||
if (Begin(cmdb_view_name.c_str(), &cmdb_view.Open,
|
|
||||||
ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings)) {
|
|
||||||
cmdb_view.DrawContents((void*)cmdb_addr, cmdb_size, base_addr);
|
|
||||||
if (cmdb_view.ContentsWidthChanged) {
|
|
||||||
cmdb_view.CalcSizes(s, cmdb_size, cmdb_addr);
|
|
||||||
SetWindowSize({s.WindowWidth, s.WindowWidth * 0.6f});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
End();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (batch_view.open) {
|
|
||||||
batch_view.Draw();
|
|
||||||
}
|
|
||||||
for (auto it = extra_batch_view.begin(); it != extra_batch_view.end(); ++it) {
|
|
||||||
if (!it->open) {
|
|
||||||
it = extra_batch_view.erase(it);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
it->Draw();
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Core::Devtools::Widget
|
} // namespace Core::Devtools::Widget
|
@ -5,13 +5,14 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
#include "imgui_memory_editor.h"
|
#include "imgui_memory_editor.h"
|
||||||
#include "reg_view.h"
|
#include "reg_view.h"
|
||||||
#include "types.h"
|
|
||||||
|
|
||||||
namespace AmdGpu {
|
namespace AmdGpu {
|
||||||
union PM4Type3Header;
|
union PM4Type3Header;
|
||||||
@ -36,7 +37,7 @@ void ParseZInfo(u32 value, bool begin_table = true);
|
|||||||
|
|
||||||
class CmdListViewer {
|
class CmdListViewer {
|
||||||
|
|
||||||
const FrameDumpViewer* parent;
|
DebugStateType::FrameDump* frame_dump;
|
||||||
|
|
||||||
uintptr_t base_addr;
|
uintptr_t base_addr;
|
||||||
std::string name;
|
std::string name;
|
||||||
@ -49,22 +50,22 @@ class CmdListViewer {
|
|||||||
|
|
||||||
int batch_bp{-1};
|
int batch_bp{-1};
|
||||||
int vqid{255};
|
int vqid{255};
|
||||||
s32 highlight_batch{-1};
|
u32 highlight_batch{~0u};
|
||||||
|
|
||||||
RegView batch_view;
|
RegView batch_view;
|
||||||
std::vector<RegView> extra_batch_view;
|
std::vector<RegView> extra_batch_view;
|
||||||
|
|
||||||
void OnNop(AmdGpu::PM4Type3Header const* header, u32 const* body);
|
static void OnNop(AmdGpu::PM4Type3Header const* header, u32 const* body);
|
||||||
void OnSetBase(AmdGpu::PM4Type3Header const* header, u32 const* body);
|
static void OnSetBase(AmdGpu::PM4Type3Header const* header, u32 const* body);
|
||||||
void OnSetContextReg(AmdGpu::PM4Type3Header const* header, u32 const* body);
|
static void OnSetContextReg(AmdGpu::PM4Type3Header const* header, u32 const* body);
|
||||||
void OnSetShReg(AmdGpu::PM4Type3Header const* header, u32 const* body);
|
static void OnSetShReg(AmdGpu::PM4Type3Header const* header, u32 const* body);
|
||||||
void OnDispatch(AmdGpu::PM4Type3Header const* header, u32 const* body);
|
static void OnDispatch(AmdGpu::PM4Type3Header const* header, u32 const* body);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void LoadConfig(const char* line);
|
static void LoadConfig(const char* line);
|
||||||
static void SerializeConfig(ImGuiTextBuffer* buf);
|
static void SerializeConfig(ImGuiTextBuffer* buf);
|
||||||
|
|
||||||
explicit CmdListViewer(const FrameDumpViewer* parent, const std::vector<u32>& cmd_list,
|
explicit CmdListViewer(DebugStateType::FrameDump* frame_dump, const std::vector<u32>& cmd_list,
|
||||||
uintptr_t base_addr = 0, std::string name = "");
|
uintptr_t base_addr = 0, std::string name = "");
|
||||||
|
|
||||||
void Draw();
|
void Draw();
|
||||||
|
77
src/core/devtools/widget/common.h
Normal file
77
src/core/devtools/widget/common.h
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
|
#include "common/types.h"
|
||||||
|
#include "video_core/amdgpu/pm4_opcodes.h"
|
||||||
|
|
||||||
|
namespace Core::Devtools::Widget {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generic PM4 header
|
||||||
|
*/
|
||||||
|
union PM4Header {
|
||||||
|
struct {
|
||||||
|
u32 reserved : 16;
|
||||||
|
u32 count : 14;
|
||||||
|
u32 type : 2; // PM4_TYPE
|
||||||
|
};
|
||||||
|
u32 u32All;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PushMarker {
|
||||||
|
std::string name{};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PopMarker {};
|
||||||
|
|
||||||
|
struct BatchBegin {
|
||||||
|
u32 id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BatchInfo {
|
||||||
|
u32 id;
|
||||||
|
std::string marker{};
|
||||||
|
size_t start_addr;
|
||||||
|
size_t end_addr;
|
||||||
|
size_t command_addr;
|
||||||
|
AmdGpu::PM4ItOpcode type;
|
||||||
|
bool bypass{false};
|
||||||
|
};
|
||||||
|
|
||||||
|
using GPUEvent = std::variant<PushMarker, PopMarker, BatchBegin, BatchInfo>;
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
void DrawRow(const char* text, const char* fmt, Args... args) {
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted(text);
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
char buf[128];
|
||||||
|
snprintf(buf, sizeof(buf), fmt, args...);
|
||||||
|
ImGui::TextUnformatted(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V, typename... Extra>
|
||||||
|
void DrawMultipleRow(const char* text, const char* fmt, V arg, Extra&&... extra_args) {
|
||||||
|
DrawRow(text, fmt, arg);
|
||||||
|
if constexpr (sizeof...(extra_args) > 0) {
|
||||||
|
DrawMultipleRow(std::forward<Extra>(extra_args)...);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
static void DoTooltip(const char* str_id, Args&&... args) {
|
||||||
|
if (ImGui::BeginTooltip()) {
|
||||||
|
if (ImGui::BeginTable(str_id, 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||||
|
DrawMultipleRow(std::forward<Args>(args)...);
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Core::Devtools::Widget
|
@ -36,7 +36,8 @@ static std::array<char, 3> small_int_to_str(const s32 i) {
|
|||||||
|
|
||||||
namespace Core::Devtools::Widget {
|
namespace Core::Devtools::Widget {
|
||||||
|
|
||||||
FrameDumpViewer::FrameDumpViewer(FrameDump _frame_dump) : frame_dump(std::move(_frame_dump)) {
|
FrameDumpViewer::FrameDumpViewer(const FrameDump& _frame_dump)
|
||||||
|
: frame_dump(std::make_shared<FrameDump>(_frame_dump)) {
|
||||||
static int unique_id = 0;
|
static int unique_id = 0;
|
||||||
id = unique_id++;
|
id = unique_id++;
|
||||||
|
|
||||||
@ -44,15 +45,14 @@ FrameDumpViewer::FrameDumpViewer(FrameDump _frame_dump) : frame_dump(std::move(_
|
|||||||
selected_submit_num = 0;
|
selected_submit_num = 0;
|
||||||
selected_queue_num2 = 0;
|
selected_queue_num2 = 0;
|
||||||
|
|
||||||
cmd_list_viewer.reserve(frame_dump.queues.size());
|
cmd_list_viewer.reserve(frame_dump->queues.size());
|
||||||
for (const auto& cmd : frame_dump.queues) {
|
for (const auto& cmd : frame_dump->queues) {
|
||||||
const auto fname =
|
const auto fname =
|
||||||
fmt::format("{}_{}_{:02}_{:02}", id, magic_enum::enum_name(selected_queue_type),
|
fmt::format("{}_{}_{:02}_{:02}", id, magic_enum::enum_name(selected_queue_type),
|
||||||
selected_submit_num, selected_queue_num2);
|
selected_submit_num, selected_queue_num2);
|
||||||
cmd_list_viewer.emplace_back(this, cmd.data, cmd.base_addr, fname);
|
cmd_list_viewer.emplace_back(frame_dump.get(), cmd.data, cmd.base_addr, fname);
|
||||||
if (cmd.type == QueueType::dcb && cmd.submit_num == selected_submit_num &&
|
if (cmd.type == QueueType::dcb && cmd.submit_num == 0 && cmd.num2 == 0) {
|
||||||
cmd.num2 == selected_queue_num2) {
|
selected_cmd = static_cast<s32>(cmd_list_viewer.size() - 1);
|
||||||
selected_cmd = cmd_list_viewer.size() - 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -96,7 +96,7 @@ void FrameDumpViewer::Draw() {
|
|||||||
magic_enum::enum_name(selected_queue_type),
|
magic_enum::enum_name(selected_queue_type),
|
||||||
selected_submit_num, selected_queue_num2);
|
selected_submit_num, selected_queue_num2);
|
||||||
Common::FS::IOFile file(fname, Common::FS::FileAccessMode::Write);
|
Common::FS::IOFile file(fname, Common::FS::FileAccessMode::Write);
|
||||||
auto& data = frame_dump.queues[selected_cmd].data;
|
const auto& data = frame_dump->queues[selected_cmd].data;
|
||||||
if (file.IsOpen()) {
|
if (file.IsOpen()) {
|
||||||
DebugState.ShowDebugMessage(fmt::format("Dumping cmd as {}", fname));
|
DebugState.ShowDebugMessage(fmt::format("Dumping cmd as {}", fname));
|
||||||
file.Write(data);
|
file.Write(data);
|
||||||
@ -112,7 +112,7 @@ void FrameDumpViewer::Draw() {
|
|||||||
if (BeginCombo("##select_submit_num", small_int_to_str(selected_submit_num).data(),
|
if (BeginCombo("##select_submit_num", small_int_to_str(selected_submit_num).data(),
|
||||||
ImGuiComboFlags_WidthFitPreview)) {
|
ImGuiComboFlags_WidthFitPreview)) {
|
||||||
std::array<bool, 32> available_submits{};
|
std::array<bool, 32> available_submits{};
|
||||||
for (const auto& cmd : frame_dump.queues) {
|
for (const auto& cmd : frame_dump->queues) {
|
||||||
if (cmd.type == selected_queue_type) {
|
if (cmd.type == selected_queue_type) {
|
||||||
available_submits[cmd.submit_num] = true;
|
available_submits[cmd.submit_num] = true;
|
||||||
}
|
}
|
||||||
@ -137,7 +137,7 @@ void FrameDumpViewer::Draw() {
|
|||||||
if (BeginCombo("##select_queue_num2", small_int_to_str(selected_queue_num2).data(),
|
if (BeginCombo("##select_queue_num2", small_int_to_str(selected_queue_num2).data(),
|
||||||
ImGuiComboFlags_WidthFitPreview)) {
|
ImGuiComboFlags_WidthFitPreview)) {
|
||||||
std::array<bool, 32> available_queues{};
|
std::array<bool, 32> available_queues{};
|
||||||
for (const auto& cmd : frame_dump.queues) {
|
for (const auto& cmd : frame_dump->queues) {
|
||||||
if (cmd.type == selected_queue_type && cmd.submit_num == selected_submit_num) {
|
if (cmd.type == selected_queue_type && cmd.submit_num == selected_submit_num) {
|
||||||
available_queues[cmd.num2] = true;
|
available_queues[cmd.num2] = true;
|
||||||
}
|
}
|
||||||
@ -152,12 +152,12 @@ void FrameDumpViewer::Draw() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (selected) {
|
if (selected) {
|
||||||
const auto it = std::ranges::find_if(frame_dump.queues, [&](const auto& cmd) {
|
const auto it = std::ranges::find_if(frame_dump->queues, [&](const auto& cmd) {
|
||||||
return cmd.type == selected_queue_type &&
|
return cmd.type == selected_queue_type &&
|
||||||
cmd.submit_num == selected_submit_num && cmd.num2 == selected_queue_num2;
|
cmd.submit_num == selected_submit_num && cmd.num2 == selected_queue_num2;
|
||||||
});
|
});
|
||||||
if (it != frame_dump.queues.end()) {
|
if (it != frame_dump->queues.end()) {
|
||||||
selected_cmd = std::distance(frame_dump.queues.begin(), it);
|
selected_cmd = static_cast<s32>(std::distance(frame_dump->queues.begin(), it));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EndCombo();
|
EndCombo();
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
#include "cmd_list.h"
|
#include "cmd_list.h"
|
||||||
#include "core/debug_state.h"
|
#include "core/debug_state.h"
|
||||||
#include "imgui_memory_editor.h"
|
|
||||||
|
|
||||||
namespace Core::Devtools::Widget {
|
namespace Core::Devtools::Widget {
|
||||||
|
|
||||||
@ -17,7 +16,7 @@ class CmdListViewer;
|
|||||||
class FrameDumpViewer {
|
class FrameDumpViewer {
|
||||||
friend class CmdListViewer;
|
friend class CmdListViewer;
|
||||||
|
|
||||||
DebugStateType::FrameDump frame_dump;
|
std::shared_ptr<DebugStateType::FrameDump> frame_dump;
|
||||||
int id;
|
int id;
|
||||||
|
|
||||||
std::vector<CmdListViewer> cmd_list_viewer;
|
std::vector<CmdListViewer> cmd_list_viewer;
|
||||||
@ -30,7 +29,7 @@ class FrameDumpViewer {
|
|||||||
public:
|
public:
|
||||||
bool is_open = true;
|
bool is_open = true;
|
||||||
|
|
||||||
explicit FrameDumpViewer(DebugStateType::FrameDump frame_dump);
|
explicit FrameDumpViewer(const DebugStateType::FrameDump& frame_dump);
|
||||||
|
|
||||||
~FrameDumpViewer();
|
~FrameDumpViewer();
|
||||||
|
|
||||||
|
107
src/core/devtools/widget/reg_popup.cpp
Normal file
107
src/core/devtools/widget/reg_popup.cpp
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "reg_popup.h"
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <imgui.h>
|
||||||
|
#include <magic_enum.hpp>
|
||||||
|
|
||||||
|
#include "cmd_list.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
using namespace ImGui;
|
||||||
|
using magic_enum::enum_name;
|
||||||
|
|
||||||
|
namespace Core::Devtools::Widget {
|
||||||
|
|
||||||
|
void RegPopup::DrawColorBuffer(const AmdGpu::Liverpool::ColorBuffer& buffer) {
|
||||||
|
if (BeginTable("COLOR_BUFFER", 2, ImGuiTableFlags_Borders)) {
|
||||||
|
TableNextRow();
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
DrawMultipleRow(
|
||||||
|
"BASE_ADDR", "%X", buffer.base_address,
|
||||||
|
"PITCH.TILE_MAX", "%X", buffer.pitch.tile_max,
|
||||||
|
"PITCH.FMASK_TILE_MAX", "%X", buffer.pitch.fmask_tile_max,
|
||||||
|
"SLICE.TILE_MAX", "%X", buffer.slice.tile_max,
|
||||||
|
"VIEW.SLICE_START", "%X", buffer.view.slice_start,
|
||||||
|
"VIEW.SLICE_MAX", "%X", buffer.view.slice_max
|
||||||
|
);
|
||||||
|
|
||||||
|
TableNextRow();
|
||||||
|
TableNextColumn();
|
||||||
|
if (TreeNode("Color0Info")) {
|
||||||
|
TableNextRow();
|
||||||
|
TableNextColumn();
|
||||||
|
ParseColor0Info(buffer.info.u32all, false);
|
||||||
|
TreePop();
|
||||||
|
}
|
||||||
|
|
||||||
|
TableNextRow();
|
||||||
|
TableNextColumn();
|
||||||
|
if (TreeNode("Color0Attrib")) {
|
||||||
|
TableNextRow();
|
||||||
|
TableNextColumn();
|
||||||
|
ParseColor0Attrib(buffer.attrib.u32all, false);
|
||||||
|
TreePop();
|
||||||
|
}
|
||||||
|
|
||||||
|
TableNextRow();
|
||||||
|
DrawMultipleRow(
|
||||||
|
"CMASK_BASE_EXT", "%X", buffer.cmask_base_address,
|
||||||
|
"FMASK_BASE_EXT", "%X", buffer.fmask_base_address,
|
||||||
|
"FMASK_SLICE.TILE_MAX", "%X", buffer.fmask_slice.tile_max,
|
||||||
|
"CLEAR_WORD0", "%X", buffer.clear_word0,
|
||||||
|
"CLEAR_WORD1", "%X", buffer.clear_word1
|
||||||
|
);
|
||||||
|
|
||||||
|
DrawMultipleRow(
|
||||||
|
"Pitch()", "%X", buffer.Pitch(),
|
||||||
|
"Height()", "%X", buffer.Height(),
|
||||||
|
"Address()", "%X", buffer.Address(),
|
||||||
|
"CmaskAddress", "%X", buffer.CmaskAddress(),
|
||||||
|
"FmaskAddress", "%X", buffer.FmaskAddress(),
|
||||||
|
"NumSamples()", "%X", buffer.NumSamples(),
|
||||||
|
"NumSlices()", "%X", buffer.NumSlices(),
|
||||||
|
"GetColorSliceSize()", "%X", buffer.GetColorSliceSize()
|
||||||
|
);
|
||||||
|
|
||||||
|
auto tiling_mode = buffer.GetTilingMode();
|
||||||
|
auto num_format = buffer.NumFormat();
|
||||||
|
DrawRow("GetTilingMode()", "%X (%s)", tiling_mode, enum_name(tiling_mode).data());
|
||||||
|
DrawRow("IsTiled()", "%X", buffer.IsTiled());
|
||||||
|
DrawRow("NumFormat()", "%X (%s)", num_format, enum_name(num_format).data());
|
||||||
|
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
EndTable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RegPopup::RegPopup() {
|
||||||
|
static int unique_id = 0;
|
||||||
|
id = unique_id++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegPopup::SetData(AmdGpu::Liverpool::ColorBuffer color_buffer, u32 batch_id, u32 cb_id) {
|
||||||
|
this->data = color_buffer;
|
||||||
|
this->title = fmt::format("Batch #{} CB #{}", batch_id, cb_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegPopup::Draw() {
|
||||||
|
|
||||||
|
char name[128];
|
||||||
|
snprintf(name, sizeof(name), "%s###reg_popup_%d", title.c_str(), id);
|
||||||
|
|
||||||
|
SetNextWindowSize({250.0f, 300.0f}, ImGuiCond_FirstUseEver);
|
||||||
|
if (Begin(name, &open, ImGuiWindowFlags_NoSavedSettings)) {
|
||||||
|
if (const auto* buffer = std::get_if<AmdGpu::Liverpool::ColorBuffer>(&data)) {
|
||||||
|
DrawColorBuffer(*buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
End();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Core::Devtools::Widget
|
31
src/core/devtools/widget/reg_popup.h
Normal file
31
src/core/devtools/widget/reg_popup.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
|
#include "common/types.h"
|
||||||
|
#include "video_core/renderer_vulkan/liverpool_to_vk.h"
|
||||||
|
|
||||||
|
namespace Core::Devtools::Widget {
|
||||||
|
|
||||||
|
class RegPopup {
|
||||||
|
int id;
|
||||||
|
|
||||||
|
std::variant<AmdGpu::Liverpool::ColorBuffer> data;
|
||||||
|
std::string title{};
|
||||||
|
|
||||||
|
void DrawColorBuffer(const AmdGpu::Liverpool::ColorBuffer& buffer);
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool open = false;
|
||||||
|
|
||||||
|
RegPopup();
|
||||||
|
|
||||||
|
void SetData(AmdGpu::Liverpool::ColorBuffer color_buffer, u32 batch_id, u32 cb_id);
|
||||||
|
|
||||||
|
void Draw();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Core::Devtools::Widget
|
@ -8,7 +8,7 @@
|
|||||||
#include <magic_enum.hpp>
|
#include <magic_enum.hpp>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "cmd_list.h"
|
#include "common.h"
|
||||||
#include "common/io_file.h"
|
#include "common/io_file.h"
|
||||||
#include "core/devtools/options.h"
|
#include "core/devtools/options.h"
|
||||||
#include "imgui_internal.h"
|
#include "imgui_internal.h"
|
||||||
@ -19,41 +19,9 @@
|
|||||||
#define pclose _pclose
|
#define pclose _pclose
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace ImGui;
|
using namespace ImGui;
|
||||||
using magic_enum::enum_name;
|
using magic_enum::enum_name;
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
void DrawRow(const char* text, const char* fmt, Args... args) {
|
|
||||||
TableNextColumn();
|
|
||||||
TextUnformatted(text);
|
|
||||||
TableNextColumn();
|
|
||||||
char buf[128];
|
|
||||||
snprintf(buf, sizeof(buf), fmt, args...);
|
|
||||||
TextUnformatted(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename V, typename... Extra>
|
|
||||||
void DrawMultipleRow(const char* text, const char* fmt, V arg, Extra&&... extra_args) {
|
|
||||||
DrawRow(text, fmt, arg);
|
|
||||||
if constexpr (sizeof...(extra_args) > 0) {
|
|
||||||
DrawMultipleRow(std::forward<Extra>(extra_args)...);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Must end with EndTable
|
|
||||||
template <typename... Args>
|
|
||||||
static void DoTooltip(const char* str_id, Args&&... args) {
|
|
||||||
if (BeginTooltip()) {
|
|
||||||
if (BeginTable(str_id, 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
|
||||||
DrawMultipleRow(std::forward<Args>(args)...);
|
|
||||||
EndTable();
|
|
||||||
}
|
|
||||||
EndTooltip();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::optional<std::string> exec_cli(const char* cli) {
|
static std::optional<std::string> exec_cli(const char* cli) {
|
||||||
std::array<char, 64> buffer{};
|
std::array<char, 64> buffer{};
|
||||||
std::string output;
|
std::string output;
|
||||||
@ -132,9 +100,9 @@ void RegView::DrawRegs() {
|
|||||||
|
|
||||||
if (BeginTable("REGS", 2, ImGuiTableFlags_Borders)) {
|
if (BeginTable("REGS", 2, ImGuiTableFlags_Borders)) {
|
||||||
|
|
||||||
auto& scissor = regs.screen_scissor;
|
auto& s = regs.screen_scissor;
|
||||||
DrawRow("Scissor", "(%d, %d, %d, %d)", scissor.top_left_x, scissor.top_left_y,
|
DrawRow("Scissor", "(%d, %d, %d, %d)", s.top_left_x, s.top_left_y, s.bottom_right_x,
|
||||||
scissor.bottom_right_x, scissor.bottom_right_y);
|
s.bottom_right_y);
|
||||||
|
|
||||||
auto cc_mode = regs.color_control.mode.Value();
|
auto cc_mode = regs.color_control.mode.Value();
|
||||||
DrawRow("Color control", "%X (%s)", cc_mode, enum_name(cc_mode).data());
|
DrawRow("Color control", "%X (%s)", cc_mode, enum_name(cc_mode).data());
|
||||||
@ -147,77 +115,40 @@ void RegView::DrawRegs() {
|
|||||||
|
|
||||||
const auto& buffer = regs.color_buffers[cb];
|
const auto& buffer = regs.color_buffers[cb];
|
||||||
|
|
||||||
bool open = opened_cb[cb];
|
const auto open_new_popup = [&] {
|
||||||
if (!buffer || !regs.color_target_mask.GetMask(cb)) {
|
auto& pop = extra_reg_popup.emplace_back();
|
||||||
|
pop.SetData(buffer, batch_id, cb);
|
||||||
|
pop.open = true;
|
||||||
|
};
|
||||||
|
|
||||||
Text("Color buffer %d", cb);
|
Text("Color buffer %d", cb);
|
||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
|
if (!buffer || !regs.color_target_mask.GetMask(cb)) {
|
||||||
TextUnformatted("N/A");
|
TextUnformatted("N/A");
|
||||||
|
} else if (last_selected_cb == cb && default_reg_popup.open) {
|
||||||
|
if (SmallButton("x")) {
|
||||||
|
if (GetIO().KeyShift) {
|
||||||
|
open_new_popup();
|
||||||
} else {
|
} else {
|
||||||
SetNextItemOpen(open);
|
default_reg_popup.open = false;
|
||||||
bool keep_open = TreeNode("cb", "Color buffer %d", cb);
|
}
|
||||||
open = opened_cb[cb] = keep_open;
|
}
|
||||||
|
} else {
|
||||||
|
if (SmallButton("->")) {
|
||||||
|
if (GetIO().KeyShift) {
|
||||||
|
open_new_popup();
|
||||||
|
} else {
|
||||||
|
last_selected_cb = cb;
|
||||||
|
default_reg_popup.SetData(buffer, batch_id, cb);
|
||||||
|
if (!default_reg_popup.open) {
|
||||||
|
default_reg_popup.open = true;
|
||||||
|
auto popup_pos =
|
||||||
|
GetCurrentContext()->LastItemData.Rect.Max + ImVec2(5.0f, 0.0f);
|
||||||
|
SetNextWindowPos(popup_pos, ImGuiCond_Always);
|
||||||
|
default_reg_popup.Draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (open) {
|
|
||||||
TableNextRow();
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
|
|
||||||
DrawMultipleRow(
|
|
||||||
"BASE_ADDR", "%X", buffer.base_address,
|
|
||||||
"PITCH.TILE_MAX", "%X", buffer.pitch.tile_max,
|
|
||||||
"PITCH.FMASK_TILE_MAX", "%X", buffer.pitch.fmask_tile_max,
|
|
||||||
"SLICE.TILE_MAX", "%X", buffer.slice.tile_max,
|
|
||||||
"VIEW.SLICE_START", "%X", buffer.view.slice_start,
|
|
||||||
"VIEW.SLICE_MAX", "%X", buffer.view.slice_max
|
|
||||||
);
|
|
||||||
|
|
||||||
TableNextRow();
|
|
||||||
TableNextColumn();
|
|
||||||
if (TreeNode("Color0Info")) {
|
|
||||||
TableNextRow();
|
|
||||||
TableNextColumn();
|
|
||||||
ParseColor0Info(buffer.info.u32all, false);
|
|
||||||
TreePop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TableNextRow();
|
|
||||||
TableNextColumn();
|
|
||||||
if (TreeNode("Color0Attrib")) {
|
|
||||||
TableNextRow();
|
|
||||||
TableNextColumn();
|
|
||||||
ParseColor0Attrib(buffer.attrib.u32all, false);
|
|
||||||
TreePop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawMultipleRow(
|
|
||||||
"CMASK_BASE_EXT", "%X", buffer.cmask_base_address,
|
|
||||||
"FMASK_BASE_EXT", "%X", buffer.fmask_base_address,
|
|
||||||
"FMASK_SLICE.TILE_MAX", "%X", buffer.fmask_slice.tile_max,
|
|
||||||
"CLEAR_WORD0", "%X", buffer.clear_word0,
|
|
||||||
"CLEAR_WORD1", "%X", buffer.clear_word1
|
|
||||||
);
|
|
||||||
|
|
||||||
DrawMultipleRow(
|
|
||||||
"Pitch()", "%X", buffer.Pitch(),
|
|
||||||
"Height()", "%X", buffer.Height(),
|
|
||||||
"Address()", "%X", buffer.Address(),
|
|
||||||
"CmaskAddress", "%X", buffer.CmaskAddress(),
|
|
||||||
"FmaskAddress", "%X", buffer.FmaskAddress(),
|
|
||||||
"NumSamples()", "%X", buffer.NumSamples(),
|
|
||||||
"NumSlices()", "%X", buffer.NumSlices(),
|
|
||||||
"GetColorSliceSize()", "%X", buffer.GetColorSliceSize()
|
|
||||||
);
|
|
||||||
|
|
||||||
auto tiling_mode = buffer.GetTilingMode();
|
|
||||||
auto num_format = buffer.NumFormat();
|
|
||||||
DrawRow("GetTilingMode()", "%X (%s)", tiling_mode, enum_name(tiling_mode).data());
|
|
||||||
DrawRow("IsTiled()", "%X", buffer.IsTiled());
|
|
||||||
DrawRow("NumFormat()", "%X (%s)", num_format, enum_name(num_format).data());
|
|
||||||
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
TreePop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PopID();
|
PopID();
|
||||||
@ -262,18 +193,20 @@ RegView::RegView() {
|
|||||||
DockBuilderFinish(root_dock_id);
|
DockBuilderFinish(root_dock_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegView::SetData(DebugStateType::RegDump data) {
|
void RegView::SetData(DebugStateType::RegDump data, u32 batch_id) {
|
||||||
this->data = std::move(data);
|
this->data = std::move(data);
|
||||||
|
this->batch_id = batch_id;
|
||||||
// clear cache
|
// clear cache
|
||||||
selected_shader = -1;
|
selected_shader = -1;
|
||||||
opened_cb.fill(false);
|
|
||||||
shader_decomp.clear();
|
shader_decomp.clear();
|
||||||
|
default_reg_popup.open = false;
|
||||||
|
extra_reg_popup.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegView::Draw() {
|
void RegView::Draw() {
|
||||||
|
|
||||||
char name[128];
|
char name[128];
|
||||||
snprintf(name, sizeof(name), "BatchView###reg_dump_%d", id);
|
snprintf(name, sizeof(name), "BatchView %u###reg_dump_%d", batch_id, id);
|
||||||
if (Begin(name, &open, ImGuiWindowFlags_MenuBar)) {
|
if (Begin(name, &open, ImGuiWindowFlags_MenuBar)) {
|
||||||
const char* names[] = {"vs", "ps", "gs", "es", "hs", "ls"};
|
const char* names[] = {"vs", "ps", "gs", "es", "hs", "ls"};
|
||||||
|
|
||||||
@ -346,6 +279,18 @@ void RegView::Draw() {
|
|||||||
}
|
}
|
||||||
End();
|
End();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (default_reg_popup.open) {
|
||||||
|
default_reg_popup.Draw();
|
||||||
|
}
|
||||||
|
for (auto it = extra_reg_popup.begin(); it != extra_reg_popup.end();) {
|
||||||
|
if (!it->open) {
|
||||||
|
it = extra_reg_popup.erase(it);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
it->Draw();
|
||||||
|
++it;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Core::Devtools::Widget
|
} // namespace Core::Devtools::Widget
|
@ -4,6 +4,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "core/debug_state.h"
|
#include "core/debug_state.h"
|
||||||
#include "imgui_memory_editor.h"
|
#include "imgui_memory_editor.h"
|
||||||
|
#include "reg_popup.h"
|
||||||
#include "text_editor.h"
|
#include "text_editor.h"
|
||||||
|
|
||||||
namespace Core::Devtools::Widget {
|
namespace Core::Devtools::Widget {
|
||||||
@ -16,13 +17,15 @@ struct ShaderCache {
|
|||||||
|
|
||||||
class RegView {
|
class RegView {
|
||||||
int id;
|
int id;
|
||||||
bool first_render = true;
|
|
||||||
|
|
||||||
DebugStateType::RegDump data;
|
DebugStateType::RegDump data;
|
||||||
|
u32 batch_id{~0u};
|
||||||
|
|
||||||
std::unordered_map<int, ShaderCache> shader_decomp;
|
std::unordered_map<int, ShaderCache> shader_decomp;
|
||||||
int selected_shader{-1};
|
int selected_shader{-1};
|
||||||
std::array<bool, AmdGpu::Liverpool::NumColorBuffers> opened_cb{};
|
RegPopup default_reg_popup;
|
||||||
|
int last_selected_cb{-1};
|
||||||
|
std::vector<RegPopup> extra_reg_popup;
|
||||||
|
|
||||||
bool show_registers{true};
|
bool show_registers{true};
|
||||||
bool show_user_data{true};
|
bool show_user_data{true};
|
||||||
@ -39,7 +42,7 @@ public:
|
|||||||
|
|
||||||
RegView();
|
RegView();
|
||||||
|
|
||||||
void SetData(DebugStateType::RegDump data);
|
void SetData(DebugStateType::RegDump data, u32 batch_id);
|
||||||
|
|
||||||
void Draw();
|
void Draw();
|
||||||
};
|
};
|
||||||
|
@ -1,48 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <variant>
|
|
||||||
|
|
||||||
#include "common/types.h"
|
|
||||||
#include "video_core/amdgpu/pm4_opcodes.h"
|
|
||||||
|
|
||||||
namespace Core::Devtools::Widget {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Generic PM4 header
|
|
||||||
*/
|
|
||||||
union PM4Header {
|
|
||||||
struct {
|
|
||||||
u32 reserved : 16;
|
|
||||||
u32 count : 14;
|
|
||||||
u32 type : 2; // PM4_TYPE
|
|
||||||
};
|
|
||||||
u32 u32All;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PushMarker {
|
|
||||||
std::string name{};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PopMarker {};
|
|
||||||
|
|
||||||
struct BatchBegin {
|
|
||||||
u32 id;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BatchInfo {
|
|
||||||
u32 id;
|
|
||||||
std::string marker{};
|
|
||||||
size_t start_addr;
|
|
||||||
size_t end_addr;
|
|
||||||
size_t command_addr;
|
|
||||||
AmdGpu::PM4ItOpcode type;
|
|
||||||
bool bypass{false};
|
|
||||||
};
|
|
||||||
|
|
||||||
using GPUEvent = std::variant<PushMarker, PopMarker, BatchBegin, BatchInfo>;
|
|
||||||
|
|
||||||
} // namespace Core::Devtools::Widget
|
|
@ -80,8 +80,6 @@ void Initialize(const ::Vulkan::Instance& instance, const Frontend::WindowSDL& w
|
|||||||
imgui_font_proggyvector_regular_compressed_size,
|
imgui_font_proggyvector_regular_compressed_size,
|
||||||
16.0f);
|
16.0f);
|
||||||
|
|
||||||
GetCurrentContext()->DebugLogFlags |= ImGuiDebugLogFlags_EventDocking;
|
|
||||||
|
|
||||||
StyleColorsDark();
|
StyleColorsDark();
|
||||||
|
|
||||||
::Core::Devtools::Layer::SetupSettings();
|
::Core::Devtools::Layer::SetupSettings();
|
||||||
|
Loading…
Reference in New Issue
Block a user