video_core: Do not spam file IO when reading vulkan shader disk cache (#1774)

This commit is contained in:
PabloMK7 2026-02-23 15:45:26 +01:00 committed by GitHub
parent fcb345e273
commit 8b72dcb235
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 48 additions and 7 deletions

View file

@ -301,11 +301,11 @@ ShaderDiskCache::CacheEntry::CacheEntryHeader ShaderDiskCache::CacheFile::ReadAt
CacheEntry::CacheEntryHeader header;
if (file.ReadAtArray(&header, 1, position) == sizeof(CacheEntry::CacheEntryHeader)) {
return header;
if (!ReadFromFileCached(&header, position, sizeof(header))) {
return CacheEntry::CacheEntryHeader();
}
return CacheEntry::CacheEntryHeader();
return header;
}
ShaderDiskCache::CacheEntry ShaderDiskCache::CacheFile::ReadAt(size_t position) {
@ -323,8 +323,8 @@ ShaderDiskCache::CacheEntry ShaderDiskCache::CacheFile::ReadAt(size_t position)
u32 payload_size = res.header.entry_size - headers_size;
std::vector<u8> payload(payload_size);
if (file.ReadAtBytes(payload.data(), payload_size,
position + sizeof(CacheEntry::CacheEntryHeader)) == payload_size) {
if (ReadFromFileCached(payload.data(), (position + sizeof(CacheEntry::CacheEntryHeader)),
payload_size)) {
// Decompress data if needed
if (res.header.zstd_compressed) {
if (Common::Compression::GetDecompressedSize(payload) <
@ -344,6 +344,7 @@ ShaderDiskCache::CacheEntry ShaderDiskCache::CacheFile::ReadAt(size_t position)
size_t ShaderDiskCache::CacheFile::GetTotalEntries() {
if (!file.IsGood()) {
next_entry_id = SIZE_MAX;
file_size = 0;
return next_entry_id;
}
@ -351,7 +352,7 @@ size_t ShaderDiskCache::CacheFile::GetTotalEntries() {
return next_entry_id;
}
const size_t file_size = file.GetSize();
file_size = file.GetSize();
if (file_size == 0) {
next_entry_id = 0;
return next_entry_id;
@ -363,6 +364,7 @@ size_t ShaderDiskCache::CacheFile::GetTotalEntries() {
footer.version == CacheEntry::CacheEntryFooter::ENTRY_VERSION) {
next_entry_id = footer.entry_id + 1;
} else {
file_size = 0;
return SIZE_MAX;
}
@ -428,7 +430,9 @@ bool ShaderDiskCache::CacheFile::SwitchMode(CacheOpMode mode) {
switch (mode) {
case CacheOpMode::READ: {
next_entry_id = SIZE_MAX; // Force reading entries agains
next_entry_id = SIZE_MAX; // Force reading entries again
cached_file_data_start = 0;
cached_file_data.clear();
file = FileUtil::IOFile(filepath, "rb");
bool is_open = file.IsGood();
if (is_open) {
@ -443,6 +447,8 @@ bool ShaderDiskCache::CacheFile::SwitchMode(CacheOpMode mode) {
return false;
}
file.Close();
cached_file_data_start = 0;
cached_file_data.clear();
curr_mode = mode;
if (next_entry_id == SIZE_MAX) {
// Cannot append if getting total items fails
@ -454,6 +460,8 @@ bool ShaderDiskCache::CacheFile::SwitchMode(CacheOpMode mode) {
}
case CacheOpMode::DELETE: {
next_entry_id = SIZE_MAX;
cached_file_data_start = 0;
cached_file_data.clear();
file.Close();
curr_mode = mode;
return FileUtil::Delete(filepath);
@ -473,6 +481,34 @@ bool ShaderDiskCache::CacheFile::SwitchMode(CacheOpMode mode) {
return false;
}
bool ShaderDiskCache::CacheFile::ReadFromFileCached(void* dst, size_t position, size_t size) {
if (!dst || position + size > file_size) {
return false;
}
size_t offset = position - cached_file_data_start;
if (position < cached_file_data_start || offset > cached_file_data.size() ||
size > cached_file_data.size() - offset) {
if (size > CacheEntry::MAX_ENTRY_SIZE) {
return false;
}
size_t to_read = std::min<size_t>(CacheEntry::MAX_ENTRY_SIZE, file_size - position);
cached_file_data_start = position;
cached_file_data.resize(to_read);
if (file.ReadAtBytes(cached_file_data.data(), to_read, position) != to_read) {
return false;
}
offset = 0;
}
std::memcpy(dst, cached_file_data.data() + offset, size);
return true;
}
std::string ShaderDiskCache::GetVSFile(u64 title_id, bool is_temp) const {
return parent.GetTransferableDir() + DIR_SEP + fmt::format("{:016X}_vs", title_id) +
(is_temp ? "_temp" : "") + ".vkch";

View file

@ -292,9 +292,14 @@ private:
bool SwitchMode(CacheOpMode mode);
private:
bool ReadFromFileCached(void* dst, size_t absolute_pos, size_t size);
CacheOpMode curr_mode = CacheOpMode::NONE;
std::string filepath;
FileUtil::IOFile file{};
size_t file_size;
size_t cached_file_data_start{};
std::vector<u8> cached_file_data;
std::atomic<size_t> next_entry_id = SIZE_MAX;
Common::ThreadWorker append_worker{1, "Disk Shader Cache Append Worker"};
};