Skip to content

Commit

Permalink
devtools: shader debug viewer
Browse files Browse the repository at this point in the history
  • Loading branch information
viniciuslrangel committed Dec 1, 2024
1 parent 8cfcf1c commit 4eb651b
Show file tree
Hide file tree
Showing 13 changed files with 285 additions and 61 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,8 @@ set(DEV_TOOLS src/core/devtools/layer.cpp
src/core/devtools/widget/reg_popup.h
src/core/devtools/widget/reg_view.cpp
src/core/devtools/widget/reg_view.h
src/core/devtools/widget/shader_list.cpp
src/core/devtools/widget/shader_list.h
src/core/devtools/widget/text_editor.cpp
src/core/devtools/widget/text_editor.h
)
Expand Down
12 changes: 12 additions & 0 deletions src/common/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ static std::string backButtonBehavior = "left";
static bool useSpecialPad = false;
static int specialPadClass = 1;
static bool isDebugDump = false;
static bool isShaderDebug = false;
static bool isShowSplash = false;
static bool isAutoUpdate = false;
static bool isNullGpu = false;
Expand Down Expand Up @@ -158,6 +159,10 @@ bool debugDump() {
return isDebugDump;
}

bool collectShadersForDebug() {
return isShaderDebug;
}

bool showSplash() {
return isShowSplash;
}
Expand Down Expand Up @@ -230,6 +235,10 @@ void setDebugDump(bool enable) {
isDebugDump = enable;
}

void setCollectShaderForDebug(bool enable) {
isShaderDebug = enable;
}

void setShowSplash(bool enable) {
isShowSplash = enable;
}
Expand Down Expand Up @@ -565,6 +574,7 @@ void load(const std::filesystem::path& path) {
const toml::value& debug = data.at("Debug");

isDebugDump = toml::find_or<bool>(debug, "DebugDump", false);
isShaderDebug = toml::find_or<bool>(debug, "CollectShader", false);
}

if (data.contains("GUI")) {
Expand Down Expand Up @@ -655,6 +665,7 @@ void save(const std::filesystem::path& path) {
data["Vulkan"]["rdocMarkersEnable"] = vkMarkers;
data["Vulkan"]["crashDiagnostic"] = vkCrashDiagnostic;
data["Debug"]["DebugDump"] = isDebugDump;
data["Debug"]["CollectShader"] = isShaderDebug;
data["GUI"]["theme"] = mw_themes;
data["GUI"]["iconSize"] = m_icon_size;
data["GUI"]["sliderPos"] = m_slider_pos;
Expand Down Expand Up @@ -710,6 +721,7 @@ void setDefaultValues() {
useSpecialPad = false;
specialPadClass = 1;
isDebugDump = false;
isShaderDebug = false;
isShowSplash = false;
isAutoUpdate = false;
isNullGpu = false;
Expand Down
2 changes: 2 additions & 0 deletions src/common/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ u32 getScreenHeight();
s32 getGpuId();

bool debugDump();
bool collectShadersForDebug();
bool showSplash();
bool autoUpdate();
bool nullGpu();
Expand All @@ -46,6 +47,7 @@ bool isRdocEnabled();
u32 vblankDiv();

void setDebugDump(bool enable);
void setCollectShaderForDebug(bool enable);
void setShowSplash(bool enable);
void setAutoUpdate(bool enable);
void setNullGpu(bool enable);
Expand Down
11 changes: 9 additions & 2 deletions src/core/debug_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ void DebugStateImpl::PushRegsDump(uintptr_t base_addr, uintptr_t header_addr,
if (is_compute) {
dump.is_compute = true;
const auto& cs = dump.regs.cs_program;
dump.cs_data = ComputerShaderDump{
dump.cs_data = PipelineComputerProgramDump{
.cs_program = cs,
.code = std::vector<u32>{cs.Code().begin(), cs.Code().end()},
};
Expand All @@ -167,7 +167,7 @@ void DebugStateImpl::PushRegsDump(uintptr_t base_addr, uintptr_t header_addr,
auto stage = regs.ProgramForStage(i);
if (stage->address_lo != 0) {
auto code = stage->Code();
dump.stages[i] = ShaderDump{
dump.stages[i] = PipelineShaderProgramDump{
.user_data = *stage,
.code = std::vector<u32>{code.begin(), code.end()},
};
Expand All @@ -176,3 +176,10 @@ void DebugStateImpl::PushRegsDump(uintptr_t base_addr, uintptr_t header_addr,
}
}
}

void DebugStateImpl::CollectShader(const std::string& name, std::span<const u32> spv,
std::span<const u32> raw_code) {
shader_dump_list.emplace_back(name, std::vector<u32>{spv.begin(), spv.end()},
std::vector<u32>{raw_code.begin(), raw_code.end()});
std::ranges::sort(shader_dump_list, {}, &ShaderDump::name);
}
48 changes: 42 additions & 6 deletions src/core/debug_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ namespace Core::Devtools {
class Layer;
namespace Widget {
class FrameGraph;
}
class ShaderList;
} // namespace Widget
} // namespace Core::Devtools

namespace DebugStateType {
Expand All @@ -49,12 +50,12 @@ struct QueueDump {
uintptr_t base_addr;
};

struct ShaderDump {
struct PipelineShaderProgramDump {
Vulkan::Liverpool::ShaderProgram user_data{};
std::vector<u32> code{};
};

struct ComputerShaderDump {
struct PipelineComputerProgramDump {
Vulkan::Liverpool::ComputeProgram cs_program{};
std::vector<u32> code{};
};
Expand All @@ -63,8 +64,8 @@ struct RegDump {
bool is_compute{false};
static constexpr size_t MaxShaderStages = 5;
Vulkan::Liverpool::Regs regs{};
std::array<ShaderDump, MaxShaderStages> stages{};
ComputerShaderDump cs_data{};
std::array<PipelineShaderProgramDump, MaxShaderStages> stages{};
PipelineComputerProgramDump cs_data{};
};

struct FrameDump {
Expand All @@ -73,9 +74,41 @@ struct FrameDump {
std::unordered_map<uintptr_t, RegDump> regs; // address -> reg dump
};

struct ShaderDump {
std::string name;
std::vector<u32> spv;
std::vector<u32> raw_code;

std::string cache_spv_disasm{};
std::string cache_raw_disasm{};

ShaderDump(std::string name, std::vector<u32> spv, std::vector<u32> raw_code)
: name(std::move(name)), spv(std::move(spv)), raw_code(std::move(raw_code)) {}

ShaderDump(const ShaderDump& other) = delete;
ShaderDump(ShaderDump&& other) noexcept
: name{std::move(other.name)}, spv{std::move(other.spv)},
raw_code{std::move(other.raw_code)}, cache_spv_disasm{std::move(other.cache_spv_disasm)},
cache_raw_disasm{std::move(other.cache_raw_disasm)} {}
ShaderDump& operator=(const ShaderDump& other) = delete;
ShaderDump& operator=(ShaderDump&& other) noexcept {
if (this == &other)
return *this;
name = std::move(other.name);
spv = std::move(other.spv);
raw_code = std::move(other.raw_code);
cache_spv_disasm = std::move(other.cache_spv_disasm);
cache_raw_disasm = std::move(other.cache_raw_disasm);
return *this;
}
};

class DebugStateImpl {
friend class Core::Devtools::Layer;
friend class Core::Devtools::Widget::FrameGraph;
friend class Core::Devtools::Widget::ShaderList;

std::queue<std::string> debug_message_popup;

std::mutex guest_threads_mutex{};
std::vector<ThreadID> guest_threads{};
Expand All @@ -94,7 +127,7 @@ class DebugStateImpl {
std::shared_mutex frame_dump_list_mutex;
std::vector<FrameDump> frame_dump_list{};

std::queue<std::string> debug_message_popup;
std::vector<ShaderDump> shader_dump_list{};

public:
void ShowDebugMessage(std::string message) {
Expand Down Expand Up @@ -152,6 +185,9 @@ class DebugStateImpl {

void PushRegsDump(uintptr_t base_addr, uintptr_t header_addr,
const AmdGpu::Liverpool::Regs& regs, bool is_compute = false);

void CollectShader(const std::string& name, std::span<const u32> spv,
std::span<const u32> raw_code);
};
} // namespace DebugStateType

Expand Down
32 changes: 25 additions & 7 deletions src/core/devtools/layer.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "layer.h"

#include <imgui.h>

#include "common/config.h"
Expand All @@ -9,12 +11,12 @@
#include "core/debug_state.h"
#include "imgui/imgui_std.h"
#include "imgui_internal.h"
#include "layer.h"
#include "options.h"
#include "video_core/renderer_vulkan/vk_presenter.h"
#include "widget/frame_dump.h"
#include "widget/frame_graph.h"
#include "widget/memory_map.h"
#include "widget/shader_list.h"

extern std::unique_ptr<Vulkan::Presenter> presenter;

Expand All @@ -37,6 +39,7 @@ static float debug_popup_timing = 3.0f;
static bool just_opened_options = false;

static Widget::MemoryMapViewer memory_map;
static Widget::ShaderList shader_list;

// clang-format off
static std::string help_text =
Expand Down Expand Up @@ -66,6 +69,7 @@ void L::DrawMenuBar() {
}
if (BeginMenu("GPU Tools")) {
MenuItem("Show frame info", nullptr, &frame_graph.is_open);
MenuItem("Show loaded shaders", nullptr, &shader_list.open);
if (BeginMenu("Dump frames")) {
SliderInt("Count", &dump_frame_count, 1, 5);
if (MenuItem("Dump", "Ctrl+Alt+F9", nullptr, !DebugState.DumpingCurrentFrame())) {
Expand Down Expand Up @@ -184,19 +188,29 @@ void L::DrawAdvanced() {
bool close_popup_options = true;
if (BeginPopupModal("GPU Tools Options", &close_popup_options,
ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings)) {
static char disassembly_cli[512];
static char disassembler_cli_isa[512];
static char disassembler_cli_spv[512];
static bool frame_dump_render_on_collapse;

if (just_opened_options) {
just_opened_options = false;
auto s = Options.disassembly_cli.copy(disassembly_cli, sizeof(disassembly_cli) - 1);
disassembly_cli[s] = '\0';
auto s = Options.disassembler_cli_isa.copy(disassembler_cli_isa,
sizeof(disassembler_cli_isa) - 1);
disassembler_cli_isa[s] = '\0';
s = Options.disassembler_cli_spv.copy(disassembler_cli_spv,
sizeof(disassembler_cli_spv) - 1);
disassembler_cli_spv[s] = '\0';
frame_dump_render_on_collapse = Options.frame_dump_render_on_collapse;
}

InputText("Shader disassembler: ", disassembly_cli, sizeof(disassembly_cli));
InputText("Shader isa disassembler: ", disassembler_cli_isa, sizeof(disassembler_cli_isa));
if (IsItemHovered()) {
SetTooltip(R"(Command to disassemble shaders. Example "dis.exe" --raw "{src}")");
SetTooltip(R"(Command to disassemble shaders. Example: dis.exe --raw "{src}")");
}
InputText("Shader SPIRV disassembler: ", disassembler_cli_spv,
sizeof(disassembler_cli_spv));
if (IsItemHovered()) {
SetTooltip(R"(Command to disassemble shaders. Example: spirv-cross -V "{src}")");
}
Checkbox("Show frame dump popups even when collapsed", &frame_dump_render_on_collapse);
if (IsItemHovered()) {
Expand All @@ -205,7 +219,8 @@ void L::DrawAdvanced() {
}

if (Button("Save")) {
Options.disassembly_cli = disassembly_cli;
Options.disassembler_cli_isa = disassembler_cli_isa;
Options.disassembler_cli_spv = disassembler_cli_spv;
Options.frame_dump_render_on_collapse = frame_dump_render_on_collapse;
SaveIniSettingsToDisk(io.IniFilename);
CloseCurrentPopup();
Expand All @@ -232,6 +247,9 @@ void L::DrawAdvanced() {
if (memory_map.open) {
memory_map.Draw();
}
if (shader_list.open) {
shader_list.Draw();
}
}

void L::DrawSimple() {
Expand Down
11 changes: 8 additions & 3 deletions src/core/devtools/options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,12 @@ TOptions Options;
void LoadOptionsConfig(const char* line) {
char str[512];
int i;
if (sscanf(line, "disassembly_cli=%511[^\n]", str) == 1) {
Options.disassembly_cli = str;
if (sscanf(line, "disassembler_cli_isa=%511[^\n]", str) == 1) {
Options.disassembler_cli_isa = str;
return;
}
if (sscanf(line, "disassembler_cli_spv=%511[^\n]", str) == 1) {
Options.disassembler_cli_spv = str;
return;
}
if (sscanf(line, "frame_dump_render_on_collapse=%d", &i) == 1) {
Expand All @@ -23,7 +27,8 @@ void LoadOptionsConfig(const char* line) {
}

void SerializeOptionsConfig(ImGuiTextBuffer* buf) {
buf->appendf("disassembly_cli=%s\n", Options.disassembly_cli.c_str());
buf->appendf("disassembler_cli_isa=%s\n", Options.disassembler_cli_isa.c_str());
buf->appendf("disassembler_cli_spv=%s\n", Options.disassembler_cli_spv.c_str());
buf->appendf("frame_dump_render_on_collapse=%d\n", Options.frame_dump_render_on_collapse);
}

Expand Down
3 changes: 2 additions & 1 deletion src/core/devtools/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ struct ImGuiTextBuffer;
namespace Core::Devtools {

struct TOptions {
std::string disassembly_cli{};
std::string disassembler_cli_isa{"clrxdisasm --raw \"{src}\""};
std::string disassembler_cli_spv{"spirv-cross -V \"{src}\""};
bool frame_dump_render_on_collapse{false};
};

Expand Down
Loading

0 comments on commit 4eb651b

Please sign in to comment.