Improve Shader Dumper: now outputs decompiled shaders

This commit is contained in:
FernandoS27
2018-10-20 14:10:59 -04:00
parent 7f0645fc10
commit acaa4247c2
4 changed files with 60 additions and 12 deletions

View File

@@ -17,6 +17,7 @@
#include "video_core/engines/shader_header.h"
#include "video_core/renderer_opengl/gl_rasterizer.h"
#include "video_core/renderer_opengl/gl_shader_decompiler.h"
#include "video_core/renderer_opengl/gl_shader_dumper.h"
namespace OpenGL::GLShader::Decompiler {
@@ -278,7 +279,7 @@ public:
const Maxwell3D::Regs::ShaderStage& stage, const std::string& suffix,
const Tegra::Shader::Header& header)
: shader{shader}, declarations{declarations}, stage{stage}, suffix{suffix}, header{header},
fixed_pipeline_output_attributes_used{}, local_memory_size{0} {
fixed_pipeline_output_attributes_used{}, local_memory_size{0}, faulty{false} {
BuildRegisterList();
BuildInputList();
}
@@ -603,6 +604,10 @@ public:
local_memory_size = lmem;
}
bool IsFaulty() {
return faulty;
}
private:
/// Generates declarations for registers.
void GenerateRegisters(const std::string& suffix) {
@@ -942,6 +947,7 @@ private:
const Tegra::Shader::Header& header;
std::unordered_set<Attribute::Index> fixed_pipeline_output_attributes_used;
u64 local_memory_size;
bool faulty;
};
class GLSLGenerator {
@@ -3732,6 +3738,12 @@ private:
}
void Generate(const std::string& suffix) {
u64 hash = ShaderDumper::GenerateHash(program_code);
shader.AddLine(fmt::format("// Program Hash Id: 0x{:x}UL", hash));
faulty |= ShaderDumper::IsProgramMarked(hash);
// Add declarations for all subroutines
for (const auto& subroutine : subroutines) {
shader.AddLine("bool " + subroutine.GetName() + "();");
@@ -3805,6 +3817,7 @@ private:
}
GenerateDeclarations();
faulty = faulty || regs.IsFaulty();
}
/// Add declarations for registers
@@ -3841,8 +3854,8 @@ std::string GetCommonDeclarations() {
}
std::optional<ProgramResult> DecompileProgram(const ProgramCode& program_code, u32 main_offset,
Maxwell3D::Regs::ShaderStage stage,
const std::string& suffix, bool& faulty_shader) {
Maxwell3D::Regs::ShaderStage stage,
const std::string& suffix, bool& faulty_shader) {
try {
const auto subroutines =
ControlFlowAnalyzer(program_code, main_offset, suffix).GetSubroutines();

View File

@@ -1,9 +1,28 @@
#include <unordered_set>
#include "common/file_util.h"
#include "common/hash.h"
#include "video_core/engines/shader_bytecode.h"
#include "video_core/renderer_opengl/gl_shader_dumper.h"
struct DumpSet {
DumpSet() : values{} {
// Insert Marked Shaders here.
values.insert(0);
}
const bool IsMarked(u64 index) const {
return values.count(index) != 0;
}
std::unordered_set<u64> values;
};
auto dump_set = DumpSet{};
bool ShaderDumper::IsProgramMarked(u64 hash) {
return dump_set.IsMarked(hash);
}
template <typename I>
std::string n2hexstr(I w, size_t hex_len = sizeof(I) << 1) {
static const char* digits = "0123456789ABCDEF";
@@ -14,7 +33,6 @@ std::string n2hexstr(I w, size_t hex_len = sizeof(I) << 1) {
}
std::string ShaderDumper::hashName() {
u64 hash = Common::ComputeHash64(program.data(), sizeof(u64) * program.size());
return n2hexstr(hash);
}
@@ -28,7 +46,7 @@ bool IsSchedInstruction(u32 offset, u32 main_offset) {
void ShaderDumper::dump() {
FileUtil::IOFile sFile;
std::string name = prefix + hashName();
std::string name = prefix + hashName() + ".bin";
sFile.Open(name, "wb");
u32 start_offset = 10;
u32 offset = start_offset;
@@ -52,3 +70,11 @@ void ShaderDumper::dump() {
}
sFile.Close();
}
void ShaderDumper::dumpText(const std::string out) {
FileUtil::IOFile sFile;
std::string name = prefix + hashName() + ".txt";
sFile.Open(name, "w");
sFile.WriteString(out);
sFile.Close();
}

View File

@@ -5,17 +5,29 @@
#include <vector>
#include "common/common_types.h"
#include "common/hash.h"
class ShaderDumper {
public:
ShaderDumper(const std::vector<u64>& prog, std::string prefix) : program(prog) {
this->hash = GenerateHash(program);
this->prefix = prefix;
}
void dump();
void dumpText(const std::string out);
static bool IsProgramMarked(u64 hash);
static u64 GenerateHash(const std::vector<u64>& program) {
return Common::ComputeHash64(program.data(), sizeof(u64) * program.size());
}
private:
std::string hashName();
u64 hash;
std::string prefix;
const std::vector<u64>& program;
};

View File

@@ -80,21 +80,16 @@ void main() {
}
)";
if (setup.IsDualProgram()) {
ProgramResult program_b =
Decompiler::DecompileProgram(setup.program.code_b, PROGRAM_OFFSET,
Maxwell3D::Regs::ShaderStage::Vertex, "vertex_b", faultyB)
.get_value_or({});
out += program_b.first;
}
if (faultyA) {
ShaderDumper s(setup.program.code, "VS");
s.dump();
s.dumpText(out);
}
if (faultyB) {
ShaderDumper s(setup.program.code_b, "VS");
s.dump();
s.dumpText(out);
}
return {out, program.second};
}
@@ -134,6 +129,7 @@ void main() {
if (faulty) {
ShaderDumper s(setup.program.code, "GS");
s.dump();
s.dumpText(out);
}
return {out, program.second};
}
@@ -201,6 +197,7 @@ void main() {
if (faulty) {
ShaderDumper s(setup.program.code, "FM");
s.dump();
s.dumpText(out);
}
return {out, program.second};
}