mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-12-03 22:44:18 +01:00
141 lines
4.4 KiB
C++
141 lines
4.4 KiB
C++
|
#include "Cemu/FileCache/FileCache.h"
|
||
|
#include "Cafe/HW/Latte/Core/LatteShaderCache.h"
|
||
|
#include <regex>
|
||
|
|
||
|
void MergeShaderCacheFile(std::string fileName)
|
||
|
{
|
||
|
// parse titleId from fileName
|
||
|
uint64 titleId = 0;
|
||
|
if (sscanf(fileName.c_str(), "%I64x", &titleId) != 1)
|
||
|
return;
|
||
|
|
||
|
const std::string mainPath = "shaderCache/transferable/" + fileName;
|
||
|
const std::string mergeSourcePath = "shaderCache/transferable/merge/" + fileName;
|
||
|
if (!fs::exists(mainPath) || !fs::exists(mergeSourcePath))
|
||
|
return;
|
||
|
// open both caches
|
||
|
FileCache* mainCache = FileCache::Open(boost::nowide::widen(mainPath));
|
||
|
FileCache* sourceCache = FileCache::Open(boost::nowide::widen(mergeSourcePath));
|
||
|
if (!mainCache && !sourceCache)
|
||
|
{
|
||
|
printf("Failed to open cache files for %s\n", fileName.c_str());
|
||
|
if (mainCache)
|
||
|
delete mainCache;
|
||
|
if (sourceCache)
|
||
|
delete sourceCache;
|
||
|
return;
|
||
|
}
|
||
|
// begin merging
|
||
|
printf("Merging shaders %I64x...", titleId);
|
||
|
uint32 numMergedEntries = 0; // number of files added to the main cache file
|
||
|
for (sint32 i = 0; i < sourceCache->GetFileCount(); i++)
|
||
|
{
|
||
|
uint64 name1, name2;
|
||
|
std::vector<uint8> fileData;
|
||
|
if (!sourceCache->GetFileByIndex(i, &name1, &name2, fileData))
|
||
|
continue;
|
||
|
std::vector<uint8> existingfileData;
|
||
|
if (mainCache->HasFile({ name1, name2 }))
|
||
|
continue;
|
||
|
mainCache->AddFile({ name1, name2 }, fileData.data(), (sint32)fileData.size());
|
||
|
numMergedEntries++;
|
||
|
}
|
||
|
printf(" -> Added %d new shaders for a total of %d\n", numMergedEntries, mainCache->GetFileCount());
|
||
|
|
||
|
delete mainCache;
|
||
|
delete sourceCache;
|
||
|
|
||
|
fs::remove(mergeSourcePath);
|
||
|
}
|
||
|
|
||
|
void MergePipelineCacheFile(std::string fileName)
|
||
|
{
|
||
|
// parse titleId from fileName
|
||
|
uint64 titleId = 0;
|
||
|
if (sscanf(fileName.c_str(), "%I64x", &titleId) != 1)
|
||
|
return;
|
||
|
|
||
|
const std::string mainPath = "shaderCache/transferable/" + fileName;
|
||
|
const std::string mergeSourcePath = "shaderCache/transferable/merge/" + fileName;
|
||
|
if (!fs::exists(mainPath) || !fs::exists(mergeSourcePath))
|
||
|
return;
|
||
|
// open both caches
|
||
|
const uint32 cacheFileVersion = 1;
|
||
|
FileCache* mainCache = FileCache::Open(boost::nowide::widen(mainPath));
|
||
|
FileCache* sourceCache = FileCache::Open(boost::nowide::widen(mergeSourcePath));
|
||
|
if (!mainCache && !sourceCache)
|
||
|
{
|
||
|
printf("Failed to open cache files for %s\n", fileName.c_str());
|
||
|
if (mainCache)
|
||
|
delete mainCache;
|
||
|
if (sourceCache)
|
||
|
delete sourceCache;
|
||
|
return;
|
||
|
}
|
||
|
// begin merging
|
||
|
printf("Merging pipelines %I64x...", titleId);
|
||
|
uint32 numMergedEntries = 0; // number of files added to the main cache file
|
||
|
for (sint32 i = 0; i < sourceCache->GetFileCount(); i++)
|
||
|
{
|
||
|
uint64 name1, name2;
|
||
|
std::vector<uint8> fileData;
|
||
|
if (!sourceCache->GetFileByIndex(i, &name1, &name2, fileData))
|
||
|
continue;
|
||
|
std::vector<uint8> existingfileData;
|
||
|
if (mainCache->HasFile({ name1, name2 }))
|
||
|
continue;
|
||
|
mainCache->AddFile({ name1, name2 }, fileData.data(), (sint32)fileData.size());
|
||
|
numMergedEntries++;
|
||
|
}
|
||
|
printf(" -> Added %d new pipelines for a total of %d\n", numMergedEntries, mainCache->GetFileCount());
|
||
|
|
||
|
delete mainCache;
|
||
|
delete sourceCache;
|
||
|
|
||
|
fs::remove(mergeSourcePath);
|
||
|
}
|
||
|
|
||
|
void MergeShaderAndPipelineCacheFiles()
|
||
|
{
|
||
|
printf("Scanning for shader cache files to merge...\n");
|
||
|
for (const auto& it : fs::directory_iterator("shaderCache/transferable/"))
|
||
|
{
|
||
|
if (fs::is_directory(it))
|
||
|
continue;
|
||
|
auto filename = it.path().filename().generic_string();
|
||
|
if (std::regex_match(filename, std::regex("^[0-9a-fA-F]{16}(?:_shaders.bin)")))
|
||
|
MergeShaderCacheFile(filename);
|
||
|
}
|
||
|
printf("\nScanning for pipeline cache files to merge...\n");
|
||
|
for (const auto& it : fs::directory_iterator("shaderCache/transferable/"))
|
||
|
{
|
||
|
if (fs::is_directory(it))
|
||
|
continue;
|
||
|
auto filename = it.path().filename().generic_string();
|
||
|
if (std::regex_match(filename, std::regex("^[0-9a-fA-F]{16}(?:_vkpipeline.bin)")))
|
||
|
MergePipelineCacheFile(filename);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ToolShaderCacheMerger()
|
||
|
{
|
||
|
printf("****************************************************\n");
|
||
|
printf("****************************************************\n");
|
||
|
printf("Shader and pipeline cache merging tool\n");
|
||
|
printf("This tool will merge any shader caches placed in:\n");
|
||
|
printf("shaderCache/transferable/merge/\n");
|
||
|
printf("into the files of the same name in:\n");
|
||
|
printf("shaderCache/transferable/\n");
|
||
|
printf("****************************************************\n");
|
||
|
printf("****************************************************\n");
|
||
|
printf("\n");
|
||
|
|
||
|
MergeShaderAndPipelineCacheFiles();
|
||
|
|
||
|
|
||
|
printf("done!\n");
|
||
|
while (true)
|
||
|
Sleep(1000);
|
||
|
exit(0);
|
||
|
}
|