devtools: pm4 - show frame regs

This commit is contained in:
Vinicius Rangel 2024-10-11 17:26:18 -03:00
parent cd10d1c9ab
commit ccd997c6a6
No known key found for this signature in database
GPG Key ID: A5B154D904B761D9
8 changed files with 296 additions and 70 deletions

View File

@ -242,7 +242,8 @@ void L::SetupSettings() {
const ImGuiID dock_id = ImHashStr("FrameDumpDock");
DockBuilderAddNode(dock_id, 0);
DockBuilderSetNodePos(dock_id, ImVec2{50.0, 50.0});
DockBuilderSetNodePos(dock_id, ImVec2{450.0, 150.0});
DockBuilderSetNodeSize(dock_id, ImVec2{400.0, 500.0});
DockBuilderFinish(dock_id);
}

View File

@ -32,8 +32,8 @@ const char* GetOpCodeName(u32 op);
namespace Core::Devtools::Widget {
static bool group_batches = false;
static bool show_markers = true;
static bool group_batches = true;
static bool show_markers = false;
void CmdListViewer::LoadConfig(const char* line) {
int i;
@ -63,10 +63,11 @@ static HdrType GetNext(HdrType this_pm4, uint32_t n) {
return curr_pm4;
}
static void ParsePolygonControl(u32 value) {
void ParsePolygonControl(u32 value, bool begin_table) {
auto const reg = reinterpret_cast<AmdGpu::Liverpool::PolygonControl const&>(value);
if (BeginTable("PA_SU_SC_MODE_CNTL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
if (!begin_table ||
BeginTable("PA_SU_SC_MODE_CNTL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
TableNextRow();
TableSetColumnIndex(0);
Text("CULL_FRONT");
@ -146,14 +147,17 @@ static void ParsePolygonControl(u32 value) {
TableSetColumnIndex(1);
Text("%X", reg.multi_prim_ib_ena.Value());
if (begin_table) {
EndTable();
}
}
}
static void ParseAaConfig(u32 value) {
void ParseAaConfig(u32 value, bool begin_table) {
auto const reg = reinterpret_cast<Liverpool::AaConfig const&>(value);
if (BeginTable("PA_SC_AA_CONFIG", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
if (!begin_table ||
BeginTable("PA_SC_AA_CONFIG", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
TableNextRow();
TableSetColumnIndex(0);
Text("MSAA_NUM_SAMPLES");
@ -184,14 +188,17 @@ static void ParseAaConfig(u32 value) {
TableSetColumnIndex(1);
Text("%X", reg.detail_to_exposed_mode.Value());
if (begin_table) {
EndTable();
}
}
}
static void ParseViewportControl(u32 value) {
void ParseViewportControl(u32 value, bool begin_table) {
auto const reg = reinterpret_cast<Liverpool::ViewportControl const&>(value);
if (BeginTable("PA_CL_VTE_CNTL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
if (!begin_table ||
BeginTable("PA_CL_VTE_CNTL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
TableNextRow();
TableSetColumnIndex(0);
Text("VPORT_X_SCALE_ENA");
@ -252,14 +259,17 @@ static void ParseViewportControl(u32 value) {
TableSetColumnIndex(1);
Text("%X", reg.perfcounter_ref.Value());
if (begin_table) {
EndTable();
}
}
}
static void ParseColorControl(u32 value) {
void ParseColorControl(u32 value, bool begin_table) {
auto const reg = reinterpret_cast<Liverpool::ColorControl const&>(value);
if (BeginTable("CB_COLOR_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
if (!begin_table ||
BeginTable("CB_COLOR_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
TableNextRow();
TableSetColumnIndex(0);
Text("DISABLE_DUAL_QUAD__VI");
@ -284,14 +294,17 @@ static void ParseColorControl(u32 value) {
TableSetColumnIndex(1);
Text("%X", reg.rop3.Value());
if (begin_table) {
EndTable();
}
}
}
static void ParseColor0Info(u32 value) {
void ParseColor0Info(u32 value, bool begin_table) {
auto const reg = reinterpret_cast<Liverpool::ColorBuffer::Color0Info const&>(value);
if (BeginTable("CB_COLOR_INFO", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
if (!begin_table ||
BeginTable("CB_COLOR_INFO", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
TableNextRow();
TableSetColumnIndex(0);
Text("ENDIAN");
@ -400,14 +413,17 @@ static void ParseColor0Info(u32 value) {
TableSetColumnIndex(1);
Text("%X", reg.cmask_addr_type.Value());
if (begin_table) {
EndTable();
}
}
}
static void ParseColor0Attrib(u32 value) {
void ParseColor0Attrib(u32 value, bool begin_table) {
auto const reg = reinterpret_cast<Liverpool::ColorBuffer::Color0Attrib const&>(value);
if (BeginTable("CB_COLOR_ATTRIB", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
if (!begin_table ||
BeginTable("CB_COLOR_ATTRIB", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
TableNextRow();
TableSetColumnIndex(0);
Text("TILE_MODE_INDEX");
@ -444,14 +460,17 @@ static void ParseColor0Attrib(u32 value) {
TableSetColumnIndex(1);
Text("%X", reg.force_dst_alpha_1.Value());
if (begin_table) {
EndTable();
}
}
}
static void ParseBlendControl(u32 value) {
void ParseBlendControl(u32 value, bool begin_table) {
auto const reg = reinterpret_cast<Liverpool::BlendControl const&>(value);
if (BeginTable("CB_BLEND_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
if (!begin_table ||
BeginTable("CB_BLEND_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
TableNextRow();
TableSetColumnIndex(0);
Text("COLOR_SRCBLEND");
@ -510,14 +529,17 @@ static void ParseBlendControl(u32 value) {
TableSetColumnIndex(1);
Text("%X", reg.disable_rop3.Value());
if (begin_table) {
EndTable();
}
}
}
static void ParseDepthRenderControl(u32 value) {
void ParseDepthRenderControl(u32 value, bool begin_table) {
auto const reg = reinterpret_cast<Liverpool::DepthRenderControl const&>(value);
if (BeginTable("DB_RENDER_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
if (!begin_table ||
BeginTable("DB_RENDER_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
TableNextRow();
TableSetColumnIndex(0);
Text("DEPTH_CLEAR_ENABLE");
@ -578,14 +600,17 @@ static void ParseDepthRenderControl(u32 value) {
TableSetColumnIndex(1);
Text("%X", reg.decompress_enable.Value());
if (begin_table) {
EndTable();
}
}
}
static void ParseDepthControl(u32 value) {
void ParseDepthControl(u32 value, bool begin_table) {
auto const reg = reinterpret_cast<Liverpool::DepthControl const&>(value);
if (BeginTable("DB_DEPTH_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
if (!begin_table ||
BeginTable("DB_DEPTH_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
TableNextRow();
TableSetColumnIndex(0);
Text("STENCIL_ENABLE");
@ -648,14 +673,17 @@ static void ParseDepthControl(u32 value) {
TableSetColumnIndex(1);
Text("%X", reg.disable_color_writes_on_depth_pass.Value());
if (begin_table) {
EndTable();
}
}
}
static void ParseEqaa(u32 value) {
void ParseEqaa(u32 value, bool begin_table) {
auto const reg = reinterpret_cast<Liverpool::Eqaa const&>(value);
if (BeginTable("DB_DEPTH_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
if (!begin_table ||
BeginTable("DB_DEPTH_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
TableNextRow();
TableSetColumnIndex(0);
Text("MAX_ANCHOR_SAMPLES");
@ -728,14 +756,17 @@ static void ParseEqaa(u32 value) {
TableSetColumnIndex(1);
Text("%X", reg.enable_postz_overrasterization.Value());
if (begin_table) {
EndTable();
}
}
}
static void ParseZInfo(u32 value) {
void ParseZInfo(u32 value, bool begin_table) {
auto const reg = reinterpret_cast<Liverpool::DepthBuffer::ZInfo const&>(value);
if (BeginTable("DB_DEPTH_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
if (!begin_table ||
BeginTable("DB_DEPTH_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
TableNextRow();
TableSetColumnIndex(0);
Text("FORMAT");
@ -796,9 +827,11 @@ static void ParseZInfo(u32 value) {
TableSetColumnIndex(1);
Text("%X", reg.zrange_precision.Value());
if (begin_table) {
EndTable();
}
}
}
void CmdListViewer::OnNop(AmdGpu::PM4Type3Header const* header, u32 const* body) {
using namespace std::string_view_literals;

View File

@ -22,6 +22,18 @@ namespace Core::Devtools::Widget {
class FrameDumpViewer;
void ParsePolygonControl(u32 value, bool begin_table = true);
void ParseAaConfig(u32 value, bool begin_table = true);
void ParseViewportControl(u32 value, bool begin_table = true);
void ParseColorControl(u32 value, bool begin_table = true);
void ParseColor0Info(u32 value, bool begin_table = true);
void ParseColor0Attrib(u32 value, bool begin_table = true);
void ParseBlendControl(u32 value, bool begin_table = true);
void ParseDepthRenderControl(u32 value, bool begin_table = true);
void ParseDepthControl(u32 value, bool begin_table = true);
void ParseEqaa(u32 value, bool begin_table = true);
void ParseZInfo(u32 value, bool begin_table = true);
class CmdListViewer {
const FrameDumpViewer* parent;

View File

@ -66,11 +66,11 @@ void FrameDumpViewer::Draw() {
char name[32];
snprintf(name, sizeof(name), "Frame #%d dump", id);
static ImGuiID dock_id = ImHashStr("FrameDumpDock");
SetNextWindowDockID(dock_id, ImGuiCond_Appearing);
if (Begin(name, &is_open, ImGuiWindowFlags_NoSavedSettings)) {
if (IsWindowAppearing()) {
auto window = GetCurrentWindow();
static ImGuiID dock_id = ImHashStr("FrameDumpDock");
SetWindowDock(window, dock_id, ImGuiCond_Once | ImGuiCond_FirstUseEver);
SetWindowSize(window, ImVec2{470.0f, 600.0f});
}
BeginGroup();

View File

@ -5,8 +5,10 @@
#include <optional>
#include <string>
#include <imgui.h>
#include <magic_enum.hpp>
#include <stdio.h>
#include "cmd_list.h"
#include "common/io_file.h"
#include "core/devtools/options.h"
#include "imgui_internal.h"
@ -17,7 +19,40 @@
#define pclose _pclose
#endif
#include <iostream>
using namespace ImGui;
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) {
std::array<char, 64> buffer{};
@ -85,31 +120,142 @@ void RegView::ProcessShader(int shader_id) {
};
shader_decomp.emplace(shader_id, std::move(cache));
}
void RegView::SelectShader(int id) {
selected_shader = id;
if (!shader_decomp.contains(id)) {
ProcessShader(id);
}
}
void RegView::DrawRegs() {
const auto& regs = data.regs;
if (BeginTable("REGS", 2, ImGuiTableFlags_Borders)) {
auto& scissor = regs.screen_scissor;
DrawRow("Scissor", "(%d, %d, %d, %d)", scissor.top_left_x, scissor.top_left_y,
scissor.bottom_right_x, scissor.bottom_right_y);
auto cc_mode = regs.color_control.mode.Value();
DrawRow("Color control", "%X (%s)", cc_mode, enum_name(cc_mode).data());
for (int cb = 0; cb < AmdGpu::Liverpool::NumColorBuffers; ++cb) {
PushID(cb);
TableNextRow();
TableNextColumn();
const auto& buffer = regs.color_buffers[cb];
bool open = opened_cb[cb];
if (!buffer || !regs.color_target_mask.GetMask(cb)) {
Text("Color buffer %d", cb);
TableNextColumn();
TextUnformatted("N/A");
} else {
SetNextItemOpen(open);
bool keep_open = TreeNode("cb", "Color buffer %d", cb);
open = opened_cb[cb] = keep_open;
}
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();
}
EndTable();
}
}
RegView::RegView() {
static int unique_id = 0;
id = unique_id++;
char name[64];
char name[128];
snprintf(name, sizeof(name), "BatchView###reg_dump_%d", id);
SetNextWindowPos({400.0f, 200.0f});
SetNextWindowSize({450.0f, 500.0f});
ImGuiID root_dock_id;
Begin(name);
SetWindowPos({400.0f, 200.0f});
{
char dock_name[64];
snprintf(dock_name, sizeof(dock_name), "BatchView###reg_dump_%d/dock_space", id);
auto root_dock_id = ImHashStr(dock_name);
DockSpace(root_dock_id, {}, ImGuiDockNodeFlags_AutoHideTabBar);
root_dock_id = ImHashStr(dock_name);
DockSpace(root_dock_id);
}
End();
ImGuiID up1, down1;
auto center = DockBuilderAddNode(root_dock_id);
DockBuilderSplitNode(center, ImGuiDir_Up, 0.2f, &up1, &down1);
DockBuilderRemoveNodeChildNodes(root_dock_id);
DockBuilderSplitNode(root_dock_id, ImGuiDir_Up, 0.2f, &up1, &down1);
snprintf(name, sizeof(name), "User data###reg_dump_%d/user_data", id);
DockBuilderDockWindow(name, up1);
snprintf(name, sizeof(name), "Regs###reg_dump_%d/regs", id);
DockBuilderDockWindow(name, down1);
snprintf(name, sizeof(name), "Disassembly###reg_dump_%d/disassembly", id);
DockBuilderDockWindow(name, down1);
@ -120,12 +266,13 @@ void RegView::SetData(DebugStateType::RegDump data) {
this->data = std::move(data);
// clear cache
selected_shader = -1;
opened_cb.fill(false);
shader_decomp.clear();
}
void RegView::Draw() {
char name[64];
char name[128];
snprintf(name, sizeof(name), "BatchView###reg_dump_%d", id);
if (Begin(name, &open, ImGuiWindowFlags_MenuBar)) {
const char* names[] = {"vs", "ps", "gs", "es", "hs", "ls"};
@ -136,50 +283,69 @@ void RegView::Draw() {
if (data.regs.stage_enable.IsStageEnabled(i)) {
bool selected = selected_shader == i;
if (Selectable(names[i], &selected)) {
selected_shader = i;
SelectShader(i);
}
}
}
ImGui::EndMenu();
}
if (BeginMenu("Windows")) {
Checkbox("Registers", &show_registers);
Checkbox("User data", &show_user_data);
Checkbox("Disassembly", &show_disassembly);
ImGui::EndMenu();
}
EndMenuBar();
}
if (selected_shader == -1) {
Text("Select a stage");
End();
return;
}
char dock_name[64];
snprintf(dock_name, sizeof(dock_name), "BatchView###reg_dump_%d/dock_space", id);
auto root_dock_id = ImHashStr(dock_name);
DockSpace(root_dock_id, {}, ImGuiDockNodeFlags_AutoHideTabBar);
DockSpace(root_dock_id);
}
End();
auto get_shader = [&]() -> ShaderCache* {
auto shader_cache = shader_decomp.find(selected_shader);
if (shader_cache == shader_decomp.end()) {
ProcessShader(selected_shader);
return;
return nullptr;
}
auto& shader = shader_cache->second;
return &shader_cache->second;
};
if (show_user_data) {
snprintf(name, sizeof(name), "User data###reg_dump_%d/user_data", id);
if (Begin(name, &show_user_data)) {
shader.hex_view.DrawContents(shader.user_data.data(), shader.user_data.size());
auto shader = get_shader();
if (!shader) {
Text("Select a stage");
} else {
shader->hex_view.DrawContents(shader->user_data.data(), shader->user_data.size());
}
}
End();
}
if (show_disassembly) {
snprintf(name, sizeof(name), "Disassembly###reg_dump_%d/disassembly", id);
if (Begin(name, &show_disassembly)) {
shader.dis_view.Render("Disassembly", GetContentRegionAvail());
auto shader = get_shader();
if (!shader) {
Text("Select a stage");
} else {
shader->dis_view.Render("Disassembly", GetContentRegionAvail());
}
}
End();
}
if (show_registers) {
snprintf(name, sizeof(name), "Regs###reg_dump_%d/regs", id);
if (Begin(name, &show_registers)) {
DrawRegs();
}
End();
}
}
} // namespace Core::Devtools::Widget

View File

@ -16,16 +16,24 @@ struct ShaderCache {
class RegView {
int id;
bool first_render = true;
DebugStateType::RegDump data;
std::unordered_map<int, ShaderCache> shader_decomp;
int selected_shader{-1};
std::array<bool, AmdGpu::Liverpool::NumColorBuffers> opened_cb{};
bool show_registers{true};
bool show_user_data{true};
bool show_disassembly{true};
void ProcessShader(int shader_id);
void SelectShader(int shader_id);
void DrawRegs();
public:
bool open = false;

View File

@ -80,6 +80,8 @@ void Initialize(const ::Vulkan::Instance& instance, const Frontend::WindowSDL& w
imgui_font_proggyvector_regular_compressed_size,
16.0f);
GetCurrentContext()->DebugLogFlags |= ImGuiDebugLogFlags_EventDocking;
StyleColorsDark();
::Core::Devtools::Layer::SetupSettings();

View File

@ -772,6 +772,8 @@ struct Liverpool {
BitField<27, 1, u32> fmask_compress_1frag_only;
BitField<28, 1, u32> dcc_enable;
BitField<29, 1, u32> cmask_addr_type;
u32 u32all;
} info;
union Color0Attrib {
BitField<0, 5, TilingMode> tile_mode_index;
@ -780,6 +782,8 @@ struct Liverpool {
BitField<12, 3, u32> num_samples_log2;
BitField<15, 2, u32> num_fragments_log2;
BitField<17, 1, u32> force_dst_alpha_1;
u32 u32all;
} attrib;
INSERT_PADDING_WORDS(1);
u32 cmask_base_address;