prepare for AIR cache

This commit is contained in:
Samuliak 2025-01-15 14:27:38 +01:00
parent 21bc5f247b
commit 1e3a3ef298
No known key found for this signature in database
4 changed files with 101 additions and 6 deletions

View file

@ -2,9 +2,6 @@
#include "Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.h"
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
#include "Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h"
#include "Common/precompiled.h"
#include "Metal/MTLResource.hpp"
#include "Metal/MTLTexture.hpp"
LatteTextureMtl::LatteTextureMtl(class MetalRenderer* mtlRenderer, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle,
Latte::E_HWTILEMODE tileMode, bool isDepth)
@ -12,7 +9,7 @@ LatteTextureMtl::LatteTextureMtl(class MetalRenderer* mtlRenderer, Latte::E_DIM
{
MTL::TextureDescriptor* desc = MTL::TextureDescriptor::alloc()->init();
desc->setStorageMode(MTL::StorageModePrivate);
desc->setCpuCacheMode(MTL::CPUCacheModeWriteCombined);
//desc->setCpuCacheMode(MTL::CPUCacheModeWriteCombined);
sint32 effectiveBaseWidth = width;
sint32 effectiveBaseHeight = height;

View file

@ -101,3 +101,11 @@ inline bool FormatIsRenderable(Latte::E_GX2SURFFMT format)
{
return !Latte::IsCompressedFormat(format);
}
template <typename... T>
inline void executeCommand(fmt::format_string<T...> fmt, T&&... args) {
std::string command = fmt::format(fmt, std::forward<T>(args)...);
int res = system(command.c_str());
if (res != 0)
cemuLog_log(LogType::Force, "command \"{}\" failed with exit code {}", command, res);
}

View file

@ -2,14 +2,21 @@
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
#include "Cafe/HW/Latte/Renderer/Metal/MetalCommon.h"
//#include "Cemu/FileCache/FileCache.h"
//#include "config/ActiveSettings.h"
#include "Cemu/FileCache/FileCache.h"
#include "config/ActiveSettings.h"
#include "Cemu/Logging/CemuLogging.h"
#include "Common/precompiled.h"
#include "GameProfile/GameProfile.h"
#include "util/helpers/helpers.h"
#define METAL_AIR_CACHE_NAME "Cemu_AIR_cache"
#define METAL_AIR_CACHE_PATH "/Volumes/" METAL_AIR_CACHE_NAME
#define METAL_AIR_CACHE_SIZE (512 * 1024 * 1024)
#define METAL_AIR_CACHE_BLOCK_COUNT (METAL_AIR_CACHE_SIZE / 512)
static bool s_isLoadingShadersMtl{false};
static std::atomic<bool> s_hasRAMFilesystem{false};
class FileCache* s_airCache{nullptr};
extern std::atomic_int g_compiled_shaders_total;
extern std::atomic_int g_compiled_shaders_async;
@ -88,12 +95,44 @@ private:
// TODO: find out if it would be possible to cache compiled Metal shaders
void RendererShaderMtl::ShaderCacheLoading_begin(uint64 cacheTitleId)
{
s_isLoadingShadersMtl = true;
// Open AIR cache
if (s_airCache)
{
delete s_airCache;
s_airCache = nullptr;
}
uint32 airCacheMagic = GeneratePrecompiledCacheId();
const std::string cacheFilename = fmt::format("{:016x}_air.bin", cacheTitleId);
const fs::path cachePath = ActiveSettings::GetCachePath("shaderCache/precompiled/{}", cacheFilename);
s_airCache = FileCache::Open(cachePath, true, airCacheMagic);
if (!s_airCache)
cemuLog_log(LogType::Force, "Unable to open AIR cache {}", cacheFilename);
// Maximize shader compilation speed
static_cast<MetalRenderer*>(g_renderer.get())->SetShouldMaximizeConcurrentCompilation(true);
}
void RendererShaderMtl::ShaderCacheLoading_end()
{
s_isLoadingShadersMtl = false;
// Close the AIR cache
if (s_airCache)
{
delete s_airCache;
s_airCache = nullptr;
}
// Close RAM filesystem
if (s_hasRAMFilesystem)
{
executeCommand("diskutil eject {}", METAL_AIR_CACHE_PATH);
s_hasRAMFilesystem = false;
}
// Reset shader compilation speed
static_cast<MetalRenderer*>(g_renderer.get())->SetShouldMaximizeConcurrentCompilation(false);
}
@ -174,6 +213,49 @@ bool RendererShaderMtl::ShouldCountCompilation() const
void RendererShaderMtl::CompileInternal()
{
// First, try to retrieve the compiled shader from the AIR cache
if (s_isLoadingShadersMtl && (m_isGameShader && !m_isGfxPackShader) && s_airCache)
{
cemu_assert_debug(m_baseHash != 0);
uint64 h1, h2;
GenerateShaderPrecompiledCacheFilename(m_type, m_baseHash, m_auxHash, h1, h2);
std::vector<uint8> cacheFileData;
if (s_airCache->GetFile({ h1, h2 }, cacheFileData))
{
CompileFromAIR(std::span<uint8>(cacheFileData.data(), cacheFileData.size()));
FinishCompilation();
}
else
{
// Ensure that RAM filesystem exists
if (!s_hasRAMFilesystem)
{
s_hasRAMFilesystem = true;
executeCommand("diskutil erasevolume HFS+ {} $(hdiutil attach -nomount ram://{})", METAL_AIR_CACHE_NAME, METAL_AIR_CACHE_BLOCK_COUNT);
}
// The shader is not in the cache, compile it
std::string filename = fmt::format("{}_{}", h1, h2);
// TODO: store the source
executeCommand("xcrun -sdk macosx metal -o {}.ir -c {}.metal", filename, filename);
executeCommand("xcrun -sdk macosx metallib -o {}.metallib {}.ir", filename, filename);
// TODO: clean up
// Load from the newly Generated AIR
// std::span<uint8> airData = ;
//CompileFromAIR(std::span<uint8>((uint8*)cacheFileData.data(), cacheFileData.size() / sizeof(uint8)));
FinishCompilation();
// Store in the cache
uint64 h1, h2;
GenerateShaderPrecompiledCacheFilename(m_type, m_baseHash, m_auxHash, h1, h2);
//s_airCache->AddFile({ h1, h2 }, airData.data(), airData.size());
}
return;
}
// Compile from source
MTL::CompileOptions* options = MTL::CompileOptions::alloc()->init();
// TODO: always disable fast math for problematic shaders
if (g_current_game_profile->GetFastMath())
@ -200,6 +282,12 @@ void RendererShaderMtl::CompileInternal()
g_compiled_shaders_total++;
}
void RendererShaderMtl::CompileFromAIR(std::span<uint8> data)
{
// TODO: implement this
printf("LOADING SHADER FROM AIR CACHE\n");
}
void RendererShaderMtl::FinishCompilation()
{
m_mslCode.clear();

View file

@ -69,5 +69,7 @@ private:
void CompileInternal();
void CompileFromAIR(std::span<uint8> data);
void FinishCompilation();
};