mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-08-05 08:52:36 +00:00
devtools: frame dump: search by shader name
This commit is contained in:
parent
5c48c77ad4
commit
be2729d6cb
@ -11,6 +11,7 @@
|
|||||||
#include "libraries/kernel/time.h"
|
#include "libraries/kernel/time.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"
|
||||||
|
#include "video_core/renderer_vulkan/vk_pipeline_cache.h"
|
||||||
|
|
||||||
using namespace DebugStateType;
|
using namespace DebugStateType;
|
||||||
|
|
||||||
@ -168,8 +169,12 @@ void DebugStateImpl::PushRegsDump(uintptr_t base_addr, uintptr_t header_addr,
|
|||||||
if ((*dump)->regs.stage_enable.IsStageEnabled(i)) {
|
if ((*dump)->regs.stage_enable.IsStageEnabled(i)) {
|
||||||
auto stage = (*dump)->regs.ProgramForStage(i);
|
auto stage = (*dump)->regs.ProgramForStage(i);
|
||||||
if (stage->address_lo != 0) {
|
if (stage->address_lo != 0) {
|
||||||
|
const auto& info = AmdGpu::Liverpool::SearchBinaryInfo(stage->Address<u32*>());
|
||||||
auto code = stage->Code();
|
auto code = stage->Code();
|
||||||
(*dump)->stages[i] = PipelineShaderProgramDump{
|
(*dump)->stages[i] = PipelineShaderProgramDump{
|
||||||
|
.name = Vulkan::PipelineCache::GetShaderName(Shader::StageFromIndex(i),
|
||||||
|
info.shader_hash),
|
||||||
|
.hash = info.shader_hash,
|
||||||
.user_data = *stage,
|
.user_data = *stage,
|
||||||
.code = std::vector<u32>{code.begin(), code.end()},
|
.code = std::vector<u32>{code.begin(), code.end()},
|
||||||
};
|
};
|
||||||
@ -191,7 +196,10 @@ void DebugStateImpl::PushRegsDumpCompute(uintptr_t base_addr, uintptr_t header_a
|
|||||||
auto& cs = (*dump)->regs.cs_program;
|
auto& cs = (*dump)->regs.cs_program;
|
||||||
cs = cs_state;
|
cs = cs_state;
|
||||||
|
|
||||||
|
const auto& info = AmdGpu::Liverpool::SearchBinaryInfo(cs.Address<u32*>());
|
||||||
(*dump)->cs_data = PipelineComputerProgramDump{
|
(*dump)->cs_data = PipelineComputerProgramDump{
|
||||||
|
.name = Vulkan::PipelineCache::GetShaderName(Shader::Stage::Compute, info.shader_hash),
|
||||||
|
.hash = info.shader_hash,
|
||||||
.cs_program = cs,
|
.cs_program = cs,
|
||||||
.code = std::vector<u32>{cs.Code().begin(), cs.Code().end()},
|
.code = std::vector<u32>{cs.Code().begin(), cs.Code().end()},
|
||||||
};
|
};
|
||||||
|
@ -50,11 +50,15 @@ struct QueueDump {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct PipelineShaderProgramDump {
|
struct PipelineShaderProgramDump {
|
||||||
|
std::string name;
|
||||||
|
u64 hash;
|
||||||
Vulkan::Liverpool::ShaderProgram user_data{};
|
Vulkan::Liverpool::ShaderProgram user_data{};
|
||||||
std::vector<u32> code{};
|
std::vector<u32> code{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PipelineComputerProgramDump {
|
struct PipelineComputerProgramDump {
|
||||||
|
std::string name;
|
||||||
|
u64 hash;
|
||||||
Vulkan::Liverpool::ComputeProgram cs_program{};
|
Vulkan::Liverpool::ComputeProgram cs_program{};
|
||||||
std::vector<u32> code{};
|
std::vector<u32> code{};
|
||||||
};
|
};
|
||||||
|
@ -1174,7 +1174,7 @@ CmdListViewer::CmdListViewer(DebugStateType::FrameDump* _frame_dump,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CmdListViewer::Draw(bool only_batches_view) {
|
void CmdListViewer::Draw(bool only_batches_view, CmdListFilter& filter) {
|
||||||
const auto& ctx = *GetCurrentContext();
|
const auto& ctx = *GetCurrentContext();
|
||||||
|
|
||||||
if (batch_view.open) {
|
if (batch_view.open) {
|
||||||
@ -1285,6 +1285,41 @@ void CmdListViewer::Draw(bool only_batches_view) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto& batch = std::get<BatchInfo>(event);
|
auto& batch = std::get<BatchInfo>(event);
|
||||||
|
|
||||||
|
// filtering
|
||||||
|
{
|
||||||
|
bool remove = false;
|
||||||
|
|
||||||
|
if (filter.shader_name[0] != '\0') {
|
||||||
|
remove = true;
|
||||||
|
std::string_view shader_name{filter.shader_name};
|
||||||
|
const auto& data = frame_dump->regs.find(batch.command_addr);
|
||||||
|
if (data != frame_dump->regs.end()) {
|
||||||
|
DebugStateType::RegDump& dump = data->second;
|
||||||
|
if (dump.is_compute) {
|
||||||
|
if (dump.cs_data.name.contains(shader_name)) {
|
||||||
|
remove = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < DebugStateType::RegDump::MaxShaderStages; ++i) {
|
||||||
|
if (dump.regs.stage_enable.IsStageEnabled(i)) {
|
||||||
|
auto& stage = dump.stages[i];
|
||||||
|
if (stage.name.contains(shader_name)) {
|
||||||
|
remove = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remove) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto const* pm4_hdr =
|
auto const* pm4_hdr =
|
||||||
reinterpret_cast<PM4Header const*>(cmdb_addr + batch.start_addr);
|
reinterpret_cast<PM4Header const*>(cmdb_addr + batch.start_addr);
|
||||||
|
|
||||||
|
@ -35,6 +35,10 @@ void ParseDepthControl(u32 value, bool begin_table = true);
|
|||||||
void ParseEqaa(u32 value, bool begin_table = true);
|
void ParseEqaa(u32 value, bool begin_table = true);
|
||||||
void ParseZInfo(u32 value, bool begin_table = true);
|
void ParseZInfo(u32 value, bool begin_table = true);
|
||||||
|
|
||||||
|
struct CmdListFilter {
|
||||||
|
char shader_name[128]{};
|
||||||
|
};
|
||||||
|
|
||||||
class CmdListViewer {
|
class CmdListViewer {
|
||||||
|
|
||||||
DebugStateType::FrameDump* frame_dump;
|
DebugStateType::FrameDump* frame_dump;
|
||||||
@ -70,7 +74,7 @@ public:
|
|||||||
explicit CmdListViewer(DebugStateType::FrameDump* frame_dump, 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(bool only_batches_view = false);
|
void Draw(bool only_batches_view, CmdListFilter& filter);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Core::Devtools::Widget
|
} // namespace Core::Devtools::Widget
|
||||||
|
@ -132,6 +132,15 @@ void FrameDumpViewer::Draw() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
EndDisabled();
|
EndDisabled();
|
||||||
|
SameLine();
|
||||||
|
if (BeginMenu("Filter")) {
|
||||||
|
|
||||||
|
TextUnformatted("Shader name");
|
||||||
|
SameLine();
|
||||||
|
InputText("##filter_shader", filter.shader_name, sizeof(filter.shader_name));
|
||||||
|
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
|
||||||
TextEx("Submit num");
|
TextEx("Submit num");
|
||||||
SameLine();
|
SameLine();
|
||||||
@ -187,7 +196,7 @@ void FrameDumpViewer::Draw() {
|
|||||||
EndGroup();
|
EndGroup();
|
||||||
}
|
}
|
||||||
if (is_showing && selected_cmd != -1) {
|
if (is_showing && selected_cmd != -1) {
|
||||||
cmd_list_viewer[selected_cmd].Draw(is_collapsed);
|
cmd_list_viewer[selected_cmd].Draw(is_collapsed, filter);
|
||||||
}
|
}
|
||||||
End();
|
End();
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,8 @@ class FrameDumpViewer {
|
|||||||
s32 selected_queue_num2;
|
s32 selected_queue_num2;
|
||||||
s32 selected_cmd = -1;
|
s32 selected_cmd = -1;
|
||||||
|
|
||||||
|
CmdListFilter filter;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool is_open = true;
|
bool is_open = true;
|
||||||
|
|
||||||
|
@ -292,6 +292,17 @@ void RegView::Draw() {
|
|||||||
EndMenuBar();
|
EndMenuBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* shader_name = "_";
|
||||||
|
if (data.is_compute) {
|
||||||
|
shader_name = data.cs_data.name.c_str();
|
||||||
|
} else if (selected_shader >= 0) {
|
||||||
|
shader_name = data.stages[selected_shader].name.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
TextUnformatted("Shader: ");
|
||||||
|
SameLine();
|
||||||
|
TextUnformatted(shader_name);
|
||||||
|
|
||||||
if (!data.is_compute &&
|
if (!data.is_compute &&
|
||||||
BeginChild("STAGES", {},
|
BeginChild("STAGES", {},
|
||||||
ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_AutoResizeY)) {
|
ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_AutoResizeY)) {
|
||||||
|
@ -234,12 +234,13 @@ void ShaderList::Draw() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
InputTextEx("##search_shader", "Search by name", search_box, sizeof(search_box), {},
|
InputTextEx("##search_shader", "Search by name", search_box, sizeof(search_box), {},
|
||||||
ImGuiInputTextFlags_None, nullptr, nullptr);
|
ImGuiInputTextFlags_None);
|
||||||
|
|
||||||
auto width = GetContentRegionAvail().x;
|
auto width = GetContentRegionAvail().x;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (const auto& shader : DebugState.shader_dump_list) {
|
for (const auto& shader : DebugState.shader_dump_list) {
|
||||||
if (search_box[0] != '\0' && !shader.name.contains(search_box)) {
|
if (search_box[0] != '\0' && !shader.name.contains(search_box)) {
|
||||||
|
i++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
char name[128];
|
char name[128];
|
||||||
|
@ -497,7 +497,7 @@ vk::ShaderModule PipelineCache::CompileModule(Shader::Info& info, Shader::Runtim
|
|||||||
module = CompileSPV(spv, instance.GetDevice());
|
module = CompileSPV(spv, instance.GetDevice());
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto name = fmt::format("{}_{:#018x}_{}", info.stage, info.pgm_hash, perm_idx);
|
const auto name = GetShaderName(info.stage, info.pgm_hash, perm_idx);
|
||||||
Vulkan::SetObjectName(instance.GetDevice(), module, name);
|
Vulkan::SetObjectName(instance.GetDevice(), module, name);
|
||||||
if (Config::collectShadersForDebug()) {
|
if (Config::collectShadersForDebug()) {
|
||||||
DebugState.CollectShader(name, info.l_stage, module, spv, code,
|
DebugState.CollectShader(name, info.l_stage, module, spv, code,
|
||||||
@ -572,6 +572,14 @@ std::optional<vk::ShaderModule> PipelineCache::ReplaceShader(vk::ShaderModule mo
|
|||||||
return new_module;
|
return new_module;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string PipelineCache::GetShaderName(Shader::Stage stage, u64 hash,
|
||||||
|
std::optional<size_t> perm) {
|
||||||
|
if (perm) {
|
||||||
|
return fmt::format("{}_{:#018x}_{}", stage, hash, *perm);
|
||||||
|
}
|
||||||
|
return fmt::format("{}_{:#018x}", stage, hash);
|
||||||
|
}
|
||||||
|
|
||||||
void PipelineCache::DumpShader(std::span<const u32> code, u64 hash, Shader::Stage stage,
|
void PipelineCache::DumpShader(std::span<const u32> code, u64 hash, Shader::Stage stage,
|
||||||
size_t perm_idx, std::string_view ext) {
|
size_t perm_idx, std::string_view ext) {
|
||||||
if (!Config::dumpShaders()) {
|
if (!Config::dumpShaders()) {
|
||||||
@ -583,7 +591,7 @@ void PipelineCache::DumpShader(std::span<const u32> code, u64 hash, Shader::Stag
|
|||||||
if (!std::filesystem::exists(dump_dir)) {
|
if (!std::filesystem::exists(dump_dir)) {
|
||||||
std::filesystem::create_directories(dump_dir);
|
std::filesystem::create_directories(dump_dir);
|
||||||
}
|
}
|
||||||
const auto filename = fmt::format("{}_{:#018x}_{}.{}", stage, hash, perm_idx, ext);
|
const auto filename = fmt::format("{}.{}", GetShaderName(stage, hash, perm_idx), ext);
|
||||||
const auto file = IOFile{dump_dir / filename, FileAccessMode::Write};
|
const auto file = IOFile{dump_dir / filename, FileAccessMode::Write};
|
||||||
file.WriteSpan(code);
|
file.WriteSpan(code);
|
||||||
}
|
}
|
||||||
@ -597,7 +605,7 @@ std::optional<std::vector<u32>> PipelineCache::GetShaderPatch(u64 hash, Shader::
|
|||||||
if (!std::filesystem::exists(patch_dir)) {
|
if (!std::filesystem::exists(patch_dir)) {
|
||||||
std::filesystem::create_directories(patch_dir);
|
std::filesystem::create_directories(patch_dir);
|
||||||
}
|
}
|
||||||
const auto filename = fmt::format("{}_{:#018x}_{}.{}", stage, hash, perm_idx, ext);
|
const auto filename = fmt::format("{}.{}", GetShaderName(stage, hash, perm_idx), ext);
|
||||||
const auto filepath = patch_dir / filename;
|
const auto filepath = patch_dir / filename;
|
||||||
if (!std::filesystem::exists(filepath)) {
|
if (!std::filesystem::exists(filepath)) {
|
||||||
return {};
|
return {};
|
||||||
|
@ -65,6 +65,9 @@ public:
|
|||||||
std::optional<vk::ShaderModule> ReplaceShader(vk::ShaderModule module,
|
std::optional<vk::ShaderModule> ReplaceShader(vk::ShaderModule module,
|
||||||
std::span<const u32> spv_code);
|
std::span<const u32> spv_code);
|
||||||
|
|
||||||
|
static std::string GetShaderName(Shader::Stage stage, u64 hash,
|
||||||
|
std::optional<size_t> perm = {});
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool RefreshGraphicsKey();
|
bool RefreshGraphicsKey();
|
||||||
bool RefreshComputeKey();
|
bool RefreshComputeKey();
|
||||||
|
Loading…
Reference in New Issue
Block a user