void debugDumpTexture(virt_ptr<const GX2Texture> texture) { if (!sDumpTextures.load(std::memory_order_relaxed)) { return; } createDumpDirectory(); // Write text dump of GX2Texture structure to texture_X.txt auto filename = fmt::format("texture_{}", texture); if (platform::fileExists("dump/" + filename + ".txt")) { return; } auto file = std::ofstream { "dump/" + filename + ".txt", std::ofstream::out }; auto out = fmt::memory_buffer {}; fmt::format_to(out, "surface.dim = {}\n", gx2::to_string(texture->surface.dim)); fmt::format_to(out, "surface.width = {}\n", texture->surface.width); fmt::format_to(out, "surface.height = {}\n", texture->surface.height); fmt::format_to(out, "surface.depth = {}\n", texture->surface.depth); fmt::format_to(out, "surface.mipLevels = {}\n", texture->surface.mipLevels); fmt::format_to(out, "surface.format = {}\n", gx2::to_string(texture->surface.format)); fmt::format_to(out, "surface.aa = {}\n", gx2::to_string(texture->surface.aa)); fmt::format_to(out, "surface.use = {}\n", gx2::to_string(texture->surface.use)); fmt::format_to(out, "surface.resourceFlags = {}\n", texture->surface.resourceFlags); fmt::format_to(out, "surface.imageSize = {}\n", texture->surface.imageSize); fmt::format_to(out, "surface.image = {}\n", texture->surface.image); fmt::format_to(out, "surface.mipmapSize = {}\n", texture->surface.mipmapSize); fmt::format_to(out, "surface.mipmaps = {}\n", texture->surface.mipmaps); fmt::format_to(out, "surface.tileMode = {}\n", gx2::to_string(texture->surface.tileMode)); fmt::format_to(out, "surface.swizzle = {}\n", texture->surface.swizzle); fmt::format_to(out, "surface.alignment = {}\n", texture->surface.alignment); fmt::format_to(out, "surface.pitch = {}\n", texture->surface.pitch); fmt::format_to(out, "viewFirstMip = {}\n", texture->viewFirstMip); fmt::format_to(out, "viewNumMips = {}\n", texture->viewNumMips); fmt::format_to(out, "viewFirstSlice = {}\n", texture->viewFirstSlice); fmt::format_to(out, "viewNumSlices = {}\n", texture->viewNumSlices); file << std::string_view { out.data(), out.size() }; if (!texture->surface.image || !texture->surface.imageSize) { return; } // Write GTX file gfd::GFDFile gtx; gfd::GFDTexture gfdTexture; gx2ToGFDTexture(texture.get(), gfdTexture); gtx.textures.push_back(gfdTexture); gfd::writeFile(gtx, "dump/" + filename + ".gtx"); }
void GX2DebugDumpTexture(const GX2Texture *texture) { if (!config::gx2::dump_textures) { return; } createDumpDirectory(); // Write text dump of GX2Texture structure to texture_X.txt auto filename = "texture_" + GX2PointerAsString(texture); if (platform::fileExists("dump/" + filename + ".txt")) { return; } auto file = std::ofstream { "dump/" + filename + ".txt", std::ofstream::out }; auto format = fmt::MemoryWriter {}; format << "surface.dim = " << GX2EnumAsString(texture->surface.dim) << '\n' << "surface.width = " << texture->surface.width << '\n' << "surface.height = " << texture->surface.height << '\n' << "surface.depth = " << texture->surface.depth << '\n' << "surface.mipLevels = " << texture->surface.mipLevels << '\n' << "surface.format = " << GX2EnumAsString(texture->surface.format) << '\n' << "surface.aa = " << GX2EnumAsString(texture->surface.aa) << '\n' << "surface.use = " << GX2EnumAsString(texture->surface.use) << '\n' << "surface.resourceFlags = " << texture->surface.resourceFlags << '\n' << "surface.imageSize = " << texture->surface.imageSize << '\n' << "surface.image = " << GX2PointerAsString(texture->surface.image) << '\n' << "surface.mipmapSize = " << texture->surface.mipmapSize << '\n' << "surface.mipmaps = " << GX2PointerAsString(texture->surface.mipmaps) << '\n' << "surface.tileMode = " << GX2EnumAsString(texture->surface.tileMode) << '\n' << "surface.swizzle = " << texture->surface.swizzle << '\n' << "surface.alignment = " << texture->surface.alignment << '\n' << "surface.pitch = " << texture->surface.pitch << '\n' << "viewFirstMip = " << texture->viewFirstMip << '\n' << "viewNumMips = " << texture->viewNumMips << '\n' << "viewFirstSlice = " << texture->viewFirstSlice << '\n' << "viewNumSlices = " << texture->viewNumSlices << '\n'; file << format.str(); if (!texture->surface.image || !texture->surface.imageSize) { return; } // Write GTX GX2DebugDumpGTX(texture); }
static void debugDumpShader(const std::string_view &filename, const std::string_view &info, virt_ptr<ShaderType> shader, bool isSubroutine = false) { std::string output; // Write binary of shader data to shader_pixel_X.bin createDumpDirectory(); auto outputBin = fmt::format("dump/{}.bin", filename); if (platform::fileExists(outputBin)) { return; } if (shader->data) { gLog->debug("Dumping shader {}", filename); debugDumpData(outputBin, shader->data, shader->size); } // Write GSH file if (shader->data) { gfd::GFDFile gsh; addShader(gsh, shader); gfd::writeFile(gsh, fmt::format("dump/{}.gsh", filename)); } // Write text of shader to shader_pixel_X.txt auto file = std::ofstream { fmt::format("dump/{}.txt", filename), std::ofstream::out }; // Disassemble if (shader->data) { output = latte::disassemble(gsl::make_span(shader->data.get(), shader->size), isSubroutine); } file << info << std::endl << "Disassembly:" << std::endl << output << std::endl; }
static void GX2DebugDumpShader(const std::string &filename, const std::string &info, uint8_t *data, size_t size) { std::string output; // Write binary of shader data to shader_pixel_X.bin createDumpDirectory(); if (platform::fileExists("dump/" + filename + ".bin")) { return; } GX2DebugDumpData("dump/" + filename + ".bin", data, size); // Write text of shader to shader_pixel_X.txt auto file = std::ofstream { "dump/" + filename + ".txt", std::ofstream::out }; // Disassemble latte::disassemble(output, gsl::as_span(data, size)); file << info << std::endl << "Disassembly:" << std::endl << output << std::endl; output.clear(); // Decompiled latte::Shader decompiled; latte::decode(decompiled, latte::Shader::Vertex, gsl::as_span(data, size)); gpu::opengl::glsl::generateBody(decompiled, output); file << "Decompiled:" << std::endl << output << std::endl; }