Skip to content

Devtools - Shader editing #1705

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/common/string_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ std::vector<std::string> SplitString(const std::string& str, char delimiter) {
return output;
}

std::string_view U8stringToString(std::u8string_view u8str) {
return std::string_view{reinterpret_cast<const char*>(u8str.data()), u8str.size()};
}

#ifdef _WIN32
static std::wstring CPToUTF16(u32 code_page, std::string_view input) {
const auto size =
Expand Down
2 changes: 2 additions & 0 deletions src/common/string_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ void ToLowerInPlace(std::string& str);

std::vector<std::string> SplitString(const std::string& str, char delimiter);

std::string_view U8stringToString(std::u8string_view u8str);

#ifdef _WIN32
[[nodiscard]] std::string UTF16ToUTF8(std::wstring_view input);
[[nodiscard]] std::wstring UTF8ToUTF16W(std::string_view str);
Expand Down
11 changes: 6 additions & 5 deletions src/core/debug_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,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);
void DebugStateImpl::CollectShader(const std::string& name, vk::ShaderModule module,
std::span<const u32> spv, std::span<const u32> raw_code,
std::span<const u32> patch_spv, bool is_patched) {
shader_dump_list.emplace_back(name, module, std::vector<u32>{spv.begin(), spv.end()},
std::vector<u32>{raw_code.begin(), raw_code.end()},
std::vector<u32>{patch_spv.begin(), patch_spv.end()}, is_patched);
}
42 changes: 30 additions & 12 deletions src/core/debug_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

#include "common/types.h"
#include "video_core/amdgpu/liverpool.h"
#include "video_core/renderer_vulkan/vk_pipeline_cache.h"
#include "video_core/renderer_vulkan/vk_graphics_pipeline.h"

#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
Expand Down Expand Up @@ -76,29 +76,46 @@ struct FrameDump {

struct ShaderDump {
std::string name;
vk::ShaderModule module;

std::vector<u32> spv;
std::vector<u32> raw_code;
std::vector<u32> isa;

std::vector<u32> patch_spv;
std::string patch_source{};

bool loaded_data = false;
bool is_patched = false;
std::string cache_spv_disasm{};
std::string cache_raw_disasm{};
std::string cache_isa_disasm{};
std::string cache_patch_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(std::string name, vk::ShaderModule module, std::vector<u32> spv,
std::vector<u32> isa, std::vector<u32> patch_spv, bool is_patched)
: name(std::move(name)), module(module), spv(std::move(spv)), isa(std::move(isa)),
patch_spv(std::move(patch_spv)), is_patched(is_patched) {}

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)} {}
: name{std::move(other.name)}, module{std::move(other.module)}, spv{std::move(other.spv)},
isa{std::move(other.isa)}, patch_spv{std::move(other.patch_spv)},
patch_source{std::move(other.patch_source)},
cache_spv_disasm{std::move(other.cache_spv_disasm)},
cache_isa_disasm{std::move(other.cache_isa_disasm)},
cache_patch_disasm{std::move(other.cache_patch_disasm)} {}
ShaderDump& operator=(const ShaderDump& other) = delete;
ShaderDump& operator=(ShaderDump&& other) noexcept {
if (this == &other)
return *this;
name = std::move(other.name);
module = std::move(other.module);
spv = std::move(other.spv);
raw_code = std::move(other.raw_code);
isa = std::move(other.isa);
patch_spv = std::move(other.patch_spv);
patch_source = std::move(other.patch_source);
cache_spv_disasm = std::move(other.cache_spv_disasm);
cache_raw_disasm = std::move(other.cache_raw_disasm);
cache_isa_disasm = std::move(other.cache_isa_disasm);
cache_patch_disasm = std::move(other.cache_patch_disasm);
return *this;
}
};
Expand Down Expand Up @@ -186,8 +203,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);
void CollectShader(const std::string& name, vk::ShaderModule module, std::span<const u32> spv,
std::span<const u32> raw_code, std::span<const u32> patch_spv,
bool is_patched);
};
} // namespace DebugStateType

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

struct TOptions {
std::string disassembler_cli_isa{"clrxdisasm --raw \"{src}\""};
std::string disassembler_cli_spv{"spirv-cross -V \"{src}\""};
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
31 changes: 22 additions & 9 deletions src/core/devtools/widget/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ static bool IsDrawCall(AmdGpu::PM4ItOpcode opcode) {
inline std::optional<std::string> exec_cli(const char* cli) {
std::array<char, 64> buffer{};
std::string output;
const auto f = popen(cli, "r");
const auto f = popen(cli, "rt");
if (!f) {
pclose(f);
return {};
Expand All @@ -129,31 +129,44 @@ inline std::optional<std::string> exec_cli(const char* cli) {
return output;
}

inline std::string RunDisassembler(const std::string& disassembler_cli,
const std::vector<u32>& shader_code) {
template <typename T>
inline std::string RunDisassembler(const std::string& disassembler_cli, const T& shader_code,
bool* success = nullptr) {
std::string shader_dis;

if (disassembler_cli.empty()) {
shader_dis = "No disassembler set";
if (success) {
*success = false;
}
} else {
auto bin_path = std::filesystem::temp_directory_path() / "shadps4_tmp_shader.bin";

constexpr std::string_view src_arg = "{src}";
std::string cli = disassembler_cli;
std::string cli = disassembler_cli + " 2>&1";
const auto pos = cli.find(src_arg);
if (pos == std::string::npos) {
DebugState.ShowDebugMessage("Disassembler CLI does not contain {src} argument\n" +
disassembler_cli);
shader_dis = "Disassembler CLI does not contain {src} argument";
if (success) {
*success = false;
}
} else {
cli.replace(pos, src_arg.size(), "\"" + bin_path.string() + "\"");
Common::FS::IOFile file(bin_path, Common::FS::FileAccessMode::Write);
file.Write(shader_code);
file.Close();

auto result = exec_cli(cli.c_str());
shader_dis = result.value_or("Could not disassemble shader");
if (shader_dis.empty()) {
shader_dis = "Disassembly empty or failed";
if (result) {
shader_dis = result.value();
if (success) {
*success = true;
}
} else {
if (success) {
*success = false;
}
shader_dis = "Could not disassemble shader";
}

std::filesystem::remove(bin_path);
Expand Down
Loading
Loading