mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-07 07:21:18 +12:00
prepare for AIR cache
This commit is contained in:
parent
21bc5f247b
commit
1e3a3ef298
4 changed files with 101 additions and 6 deletions
|
@ -2,9 +2,6 @@
|
||||||
#include "Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.h"
|
||||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
|
||||||
#include "Cafe/HW/Latte/Renderer/Metal/LatteToMtl.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,
|
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)
|
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();
|
MTL::TextureDescriptor* desc = MTL::TextureDescriptor::alloc()->init();
|
||||||
desc->setStorageMode(MTL::StorageModePrivate);
|
desc->setStorageMode(MTL::StorageModePrivate);
|
||||||
desc->setCpuCacheMode(MTL::CPUCacheModeWriteCombined);
|
//desc->setCpuCacheMode(MTL::CPUCacheModeWriteCombined);
|
||||||
|
|
||||||
sint32 effectiveBaseWidth = width;
|
sint32 effectiveBaseWidth = width;
|
||||||
sint32 effectiveBaseHeight = height;
|
sint32 effectiveBaseHeight = height;
|
||||||
|
|
|
@ -101,3 +101,11 @@ inline bool FormatIsRenderable(Latte::E_GX2SURFFMT format)
|
||||||
{
|
{
|
||||||
return !Latte::IsCompressedFormat(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);
|
||||||
|
}
|
||||||
|
|
|
@ -2,14 +2,21 @@
|
||||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
|
||||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalCommon.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalCommon.h"
|
||||||
|
|
||||||
//#include "Cemu/FileCache/FileCache.h"
|
#include "Cemu/FileCache/FileCache.h"
|
||||||
//#include "config/ActiveSettings.h"
|
#include "config/ActiveSettings.h"
|
||||||
#include "Cemu/Logging/CemuLogging.h"
|
#include "Cemu/Logging/CemuLogging.h"
|
||||||
#include "Common/precompiled.h"
|
#include "Common/precompiled.h"
|
||||||
#include "GameProfile/GameProfile.h"
|
#include "GameProfile/GameProfile.h"
|
||||||
#include "util/helpers/helpers.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 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_total;
|
||||||
extern std::atomic_int g_compiled_shaders_async;
|
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
|
// TODO: find out if it would be possible to cache compiled Metal shaders
|
||||||
void RendererShaderMtl::ShaderCacheLoading_begin(uint64 cacheTitleId)
|
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
|
// Maximize shader compilation speed
|
||||||
static_cast<MetalRenderer*>(g_renderer.get())->SetShouldMaximizeConcurrentCompilation(true);
|
static_cast<MetalRenderer*>(g_renderer.get())->SetShouldMaximizeConcurrentCompilation(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererShaderMtl::ShaderCacheLoading_end()
|
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);
|
static_cast<MetalRenderer*>(g_renderer.get())->SetShouldMaximizeConcurrentCompilation(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,6 +213,49 @@ bool RendererShaderMtl::ShouldCountCompilation() const
|
||||||
|
|
||||||
void RendererShaderMtl::CompileInternal()
|
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();
|
MTL::CompileOptions* options = MTL::CompileOptions::alloc()->init();
|
||||||
// TODO: always disable fast math for problematic shaders
|
// TODO: always disable fast math for problematic shaders
|
||||||
if (g_current_game_profile->GetFastMath())
|
if (g_current_game_profile->GetFastMath())
|
||||||
|
@ -200,6 +282,12 @@ void RendererShaderMtl::CompileInternal()
|
||||||
g_compiled_shaders_total++;
|
g_compiled_shaders_total++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RendererShaderMtl::CompileFromAIR(std::span<uint8> data)
|
||||||
|
{
|
||||||
|
// TODO: implement this
|
||||||
|
printf("LOADING SHADER FROM AIR CACHE\n");
|
||||||
|
}
|
||||||
|
|
||||||
void RendererShaderMtl::FinishCompilation()
|
void RendererShaderMtl::FinishCompilation()
|
||||||
{
|
{
|
||||||
m_mslCode.clear();
|
m_mslCode.clear();
|
||||||
|
|
|
@ -69,5 +69,7 @@ private:
|
||||||
|
|
||||||
void CompileInternal();
|
void CompileInternal();
|
||||||
|
|
||||||
|
void CompileFromAIR(std::span<uint8> data);
|
||||||
|
|
||||||
void FinishCompilation();
|
void FinishCompilation();
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue