mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 02:47:02 +02:00
shader: cache registered code identities instead of parsing legacy footers
Co-authored-by: Mac <me@itsmemac.com> Co-authored-by: Senaxx <michelbeld@gmail.com>
This commit is contained in:
@@ -41,44 +41,33 @@
|
||||
|
||||
namespace Libs::Graphics {
|
||||
|
||||
struct ShaderBinaryInfo {
|
||||
uint8_t signature[7];
|
||||
uint8_t version;
|
||||
uint32_t pssl_or_cg : 1;
|
||||
uint32_t cached : 1;
|
||||
uint32_t type : 4;
|
||||
uint32_t source_type : 2;
|
||||
uint32_t length : 24;
|
||||
uint8_t chunk_usage_base_offset_dw;
|
||||
uint8_t num_input_usage_slots;
|
||||
uint8_t is_srt : 1;
|
||||
uint8_t is_srt_used_info_valid : 1;
|
||||
uint8_t is_extended_usage_info : 1;
|
||||
uint8_t reserved2 : 5;
|
||||
uint8_t reserved3;
|
||||
uint32_t hash0;
|
||||
uint32_t hash1;
|
||||
uint32_t crc32;
|
||||
struct ShaderMapEntry {
|
||||
ShaderMappedData data;
|
||||
uint64_t hash;
|
||||
};
|
||||
|
||||
static std::unique_ptr<std::unordered_map<uint64_t, ShaderMappedData>> g_shader_map;
|
||||
static std::unique_ptr<std::unordered_map<uint64_t, ShaderMapEntry>> g_shader_map;
|
||||
static std::mutex g_shader_map_mutex;
|
||||
|
||||
void ShaderInit() {
|
||||
EXIT_IF(g_shader_map != nullptr);
|
||||
|
||||
g_shader_map = std::make_unique<std::unordered_map<uint64_t, ShaderMappedData>>();
|
||||
g_shader_map = std::make_unique<std::unordered_map<uint64_t, ShaderMapEntry>>();
|
||||
}
|
||||
|
||||
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",
|
||||
addr, data.code_size_bytes);
|
||||
}
|
||||
const auto hash = XXH3_64bits(reinterpret_cast<const void*>(addr), data.code_size_bytes);
|
||||
std::scoped_lock lock(g_shader_map_mutex);
|
||||
|
||||
(*g_shader_map)[addr] = data;
|
||||
(*g_shader_map)[addr] = {data, hash};
|
||||
}
|
||||
|
||||
static ShaderMappedData ShaderGetMappedData(uint64_t addr, const char* label) {
|
||||
static ShaderMapEntry ShaderGetMappedData(uint64_t addr, const char* label) {
|
||||
EXIT_IF(g_shader_map == nullptr);
|
||||
|
||||
std::scoped_lock lock(g_shader_map_mutex);
|
||||
@@ -90,37 +79,15 @@ static ShaderMappedData ShaderGetMappedData(uint64_t addr, const char* label) {
|
||||
EXIT("%s shader=0x%016" PRIx64 " is missing from ShaderMap\n", label, addr);
|
||||
}
|
||||
|
||||
static const ShaderBinaryInfo* GetBinaryInfo(const uint32_t* code) {
|
||||
EXIT_IF(code == nullptr);
|
||||
|
||||
if (code[0] == 0xBEEB03FF) {
|
||||
return reinterpret_cast<const ShaderBinaryInfo*>(code +
|
||||
static_cast<size_t>(code[1] + 1) * 2);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static uint64_t GetDeclaredShaderHash(uint64_t shader_addr) {
|
||||
const auto* header = GetBinaryInfo(reinterpret_cast<const uint32_t*>(shader_addr));
|
||||
return header != nullptr ? (static_cast<uint64_t>(header->hash1) << 32u) | header->hash0 : 0;
|
||||
}
|
||||
|
||||
static ShaderParams GetShaderParams(uint64_t shader_addr, const char* label, uint64_t declared_hash,
|
||||
static ShaderParams GetShaderParams(uint64_t shader_addr, uint64_t hash,
|
||||
std::span<const uint32_t> user_data,
|
||||
const ShaderMappedData& data, uint32_t user_data_base = 0) {
|
||||
if (data.code_size_bytes == 0 || data.code_size_bytes % sizeof(uint32_t) != 0) {
|
||||
EXIT("%s hash=0x%016" PRIx64 " shader=0x%016" PRIx64
|
||||
" has invalid AGC shader_size=0x%08" PRIx32 "\n",
|
||||
label, declared_hash, shader_addr, data.code_size_bytes);
|
||||
}
|
||||
const auto code_words = data.code_size_bytes / sizeof(uint32_t);
|
||||
const auto code = std::span {reinterpret_cast<const uint32_t*>(shader_addr), code_words};
|
||||
ShaderParams params {
|
||||
.code = code,
|
||||
.user_data_count = static_cast<uint32_t>(user_data.size()) + user_data_base,
|
||||
.hash = declared_hash != 0 ? declared_hash
|
||||
: XXH3_64bits(code.data(), code.size_bytes()),
|
||||
.hash = hash,
|
||||
};
|
||||
EXIT_IF(user_data.size() > HW::UserSgprInfo::SGPRS_MAX ||
|
||||
params.user_data_count > params.user_data.size());
|
||||
@@ -726,11 +693,10 @@ void BuildStageStaticKey(const ShaderComputeInputInfo& info, std::vector<uint32_
|
||||
ShaderParams PrepareProgram(const HW::VertexShaderInfo& regs, const HW::Context& context,
|
||||
const HW::UserConfig& user_config, ShaderVertexInputInfo& info) {
|
||||
const auto& sh = context.GetShaderRegisters();
|
||||
const auto data = ShaderGetMappedData(regs.es_regs.data_addr, "ShaderGetInputInfoVS():");
|
||||
const auto [data, hash] = ShaderGetMappedData(regs.es_regs.data_addr, "ShaderGetInputInfoVS():");
|
||||
const bool merged = (context.GetShaderStages() & 0x20u) != 0;
|
||||
auto params = GetShaderParams(
|
||||
regs.es_regs.data_addr, "ShaderRecompiler VS",
|
||||
GetDeclaredShaderHash(regs.es_regs.data_addr),
|
||||
regs.es_regs.data_addr, hash,
|
||||
std::span<const uint32_t>(regs.gs_user_sgpr.value, regs.gs_regs.rsrc2.user_sgpr), data,
|
||||
merged ? 8u : 0u);
|
||||
if (!merged) {
|
||||
@@ -755,10 +721,9 @@ ShaderParams PrepareProgram(const HW::VertexShaderInfo& regs, const HW::Context&
|
||||
mesh.scratch_size_dwords = data.scratch_size_dwords;
|
||||
if (data.type == Prospero::ShaderBinaryType::kGsFront) {
|
||||
EXIT_IF(regs.gs_regs.data_addr == 0);
|
||||
const auto back = ShaderGetMappedData(regs.gs_regs.data_addr, "ShaderGetInputInfoGS():");
|
||||
const auto [back, back_hash] = ShaderGetMappedData(regs.gs_regs.data_addr, "ShaderGetInputInfoGS():");
|
||||
const auto back_params =
|
||||
GetShaderParams(regs.gs_regs.data_addr, "ShaderRecompiler GS",
|
||||
GetDeclaredShaderHash(regs.gs_regs.data_addr), {}, back);
|
||||
GetShaderParams(regs.gs_regs.data_addr, back_hash, {}, back);
|
||||
params.back_code = back_params.code;
|
||||
params.user_data[0] = static_cast<uint32_t>(regs.gs_regs.user_data_addr);
|
||||
params.user_data[1] = static_cast<uint32_t>(regs.gs_regs.user_data_addr >> 32u);
|
||||
@@ -797,9 +762,9 @@ std::array<ShaderParams, 3>
|
||||
PrepareTessellationPrograms(const HW::VertexShaderInfo& regs, const HW::Context& context,
|
||||
std::array<ShaderVertexInputInfo, 3>& input_info) {
|
||||
const auto& sh = context.GetShaderRegisters();
|
||||
const auto local = ShaderGetMappedData(regs.ls_regs.data_addr, "ShaderGetInputInfoLS():");
|
||||
const auto control = ShaderGetMappedData(regs.hs_regs.data_addr, "ShaderGetInputInfoHS():");
|
||||
const auto evaluation = ShaderGetMappedData(regs.es_regs.data_addr, "ShaderGetInputInfoTES():");
|
||||
const auto [local, local_hash] = ShaderGetMappedData(regs.ls_regs.data_addr, "ShaderGetInputInfoLS():");
|
||||
const auto [control, control_hash] = ShaderGetMappedData(regs.hs_regs.data_addr, "ShaderGetInputInfoHS():");
|
||||
const auto [evaluation, evaluation_hash] = ShaderGetMappedData(regs.es_regs.data_addr, "ShaderGetInputInfoTES():");
|
||||
EXIT_NOT_IMPLEMENTED(local.type != Prospero::ShaderBinaryType::kHsFront ||
|
||||
control.type != Prospero::ShaderBinaryType::kHsBack ||
|
||||
evaluation.type != Prospero::ShaderBinaryType::kGs);
|
||||
@@ -810,12 +775,9 @@ PrepareTessellationPrograms(const HW::VertexShaderInfo& regs, const HW::Context&
|
||||
const auto local_users = std::span(regs.hs_user_sgpr.value, regs.hs_regs.rsrc2.user_sgpr);
|
||||
const auto evaluation_users = std::span(regs.gs_user_sgpr.value, regs.gs_regs.rsrc2.user_sgpr);
|
||||
std::array<ShaderParams, 3> params {
|
||||
GetShaderParams(regs.ls_regs.data_addr, "ShaderRecompiler LS",
|
||||
GetDeclaredShaderHash(regs.ls_regs.data_addr), local_users, local),
|
||||
GetShaderParams(regs.hs_regs.data_addr, "ShaderRecompiler HS",
|
||||
GetDeclaredShaderHash(regs.hs_regs.data_addr), local_users, control, 8u),
|
||||
GetShaderParams(regs.es_regs.data_addr, "ShaderRecompiler TES",
|
||||
GetDeclaredShaderHash(regs.es_regs.data_addr), evaluation_users,
|
||||
GetShaderParams(regs.ls_regs.data_addr, local_hash, local_users, local),
|
||||
GetShaderParams(regs.hs_regs.data_addr, control_hash, local_users, control, 8u),
|
||||
GetShaderParams(regs.es_regs.data_addr, evaluation_hash, evaluation_users,
|
||||
evaluation),
|
||||
};
|
||||
// The fused HS back half receives its separate user-data address in s0:s1.
|
||||
@@ -855,19 +817,19 @@ ShaderParams PrepareProgram(
|
||||
const HW::PixelShaderInfo& regs, const HW::ShaderRegisters& sh,
|
||||
std::span<const Prospero::ColorComponentMapping, 8> target_export_mapping,
|
||||
ShaderPixelInputInfo& ps_info) {
|
||||
const auto data = ShaderGetMappedData(regs.ps_regs.data_addr, "ShaderGetInputInfoPS():");
|
||||
const auto [data, hash] = ShaderGetMappedData(regs.ps_regs.data_addr, "ShaderGetInputInfoPS():");
|
||||
ShaderGetStaticInputInfoPS(regs, sh, target_export_mapping, data, ps_info);
|
||||
return GetShaderParams(
|
||||
regs.ps_regs.data_addr, "ShaderRecompiler PS", GetDeclaredShaderHash(regs.ps_regs.data_addr),
|
||||
regs.ps_regs.data_addr, hash,
|
||||
std::span<const uint32_t>(regs.ps_user_sgpr.value, regs.ps_regs.rsrc2.user_sgpr), data);
|
||||
}
|
||||
|
||||
ShaderParams PrepareProgram(const HW::ComputeShaderInfo& regs, const HW::ShaderRegisters& sh,
|
||||
ShaderComputeInputInfo& info) {
|
||||
const auto data = ShaderGetMappedData(regs.cs_regs.data_addr, "ShaderGetInputInfoCS():");
|
||||
const auto [data, hash] = ShaderGetMappedData(regs.cs_regs.data_addr, "ShaderGetInputInfoCS():");
|
||||
ShaderGetStaticInputInfoCS(regs, sh, data, info);
|
||||
return GetShaderParams(
|
||||
regs.cs_regs.data_addr, "ShaderRecompiler CS", GetDeclaredShaderHash(regs.cs_regs.data_addr),
|
||||
regs.cs_regs.data_addr, hash,
|
||||
std::span<const uint32_t>(regs.cs_user_sgpr.value, regs.cs_regs.user_sgpr), data);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user