shader: hash only the program code and literal buffer

This commit is contained in:
nmzik committed 2026-10-30 03:29:45 +01:00
1 parent 1703836d06
commit ae67e2db51
2 files changed
+59 -2

No files matched your search

+22 -2
View File
@@ -1,5 +1,6 @@
#include "graphics/shader/shader.h"
#include "common/alignment.h"
#include "common/assert.h"
#include "common/common.h"
#include "common/emulatorConfig.h"
@@ -19,6 +20,7 @@
#include <algorithm>
#include <bit>
#include <cstdio>
#include <cstring>
#include <memory>
#include <mutex>
#include <span>
@@ -59,15 +61,33 @@ void ShaderInit() {
g_shader_map = std::make_unique<std::unordered_map<uint64_t, ShaderMapEntry>>();
}
// The program's code and, at align16(code size), its literal buffer, as sized by the 0x30-byte
// footer that ends a binary; the whole binary when the footer is unknown.
static uint32_t ShaderProgramSize(const uint32_t* binary, uint32_t size) {
constexpr uint32_t FooterSize = 0x30;
if (size < FooterSize) return size;
// Magic, then version, code size and literal buffer size at +0x10.
const auto* footer = binary + (size - FooterSize) / 4;
const auto end = Common::AlignUp(uint64_t {footer[5]}, 16) + footer[6];
if (std::memcmp(footer, "barefoot", 8) != 0 || footer[4] != 1 || footer[5] == 0 ||
end % 4 != 0 || end > size - FooterSize) {
return size;
}
return static_cast<uint32_t>(end);
}
void ShaderMapUserData(uint64_t addr, const ShaderMappedData& data) {
EXIT_IF(g_shader_map == nullptr);
if (addr == 0 || data.code_size_bytes == 0 || data.code_size_bytes % sizeof(uint32_t) != 0) {
EXIT("ShaderMapUserData shader=0x%016" PRIx64 " has invalid AGC shader_size=0x%08" PRIx32 "\n",
EXIT("ShaderMapUserData shader=0x%016" PRIx64 " has invalid shader_size=0x%08" PRIx32 "\n",
addr, data.code_size_bytes);
}
const auto hash = XXH3_64bits(reinterpret_cast<const void*>(addr), data.code_size_bytes);
const auto* binary = reinterpret_cast<const uint32_t*>(addr);
ShaderMapData mapped {data};
// Translation reads the bytes the hash covers.
mapped.code_size_bytes = ShaderProgramSize(binary, data.code_size_bytes);
const auto hash = XXH3_64bits(binary, mapped.code_size_bytes);
mapped.vertex_error =
ShaderReadVertexMetadata(data, HW::UserSgprInfo::SGPRS_MAX, mapped.vertex);
std::scoped_lock lock(g_shader_map_mutex);