prepare for shader cache

This commit is contained in:
Samuliak 2024-08-14 11:57:01 +02:00
parent 13834ca9cb
commit 53efb9e5b2
3 changed files with 74 additions and 11 deletions

View File

@ -665,22 +665,21 @@ void MetalRenderer::draw_beginSequence()
if (!rasterizerEnable == false) if (!rasterizerEnable == false)
m_state.m_skipDrawSequence = true; m_state.m_skipDrawSequence = true;
// TODO: is this even needed?
if (!m_state.m_activeFBO)
m_state.m_skipDrawSequence = true;
} }
void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32 instanceCount, uint32 count, MPTR indexDataMPTR, Latte::LATTE_VGT_DMA_INDEX_TYPE::E_INDEX_TYPE indexType, bool isFirst) void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32 instanceCount, uint32 count, MPTR indexDataMPTR, Latte::LATTE_VGT_DMA_INDEX_TYPE::E_INDEX_TYPE indexType, bool isFirst)
{ {
//if (m_state.skipDrawSequence) // TODO: uncomment
//if (m_state.m_skipDrawSequence)
//{ //{
// return; // return;
//} //}
// Render pass // Render pass
if (!m_state.m_activeFBO)
{
debug_printf("no active FBO, skipping draw\n");
return;
}
auto renderCommandEncoder = GetRenderCommandEncoder(); auto renderCommandEncoder = GetRenderCommandEncoder();
// Shaders // Shaders

View File

@ -2,22 +2,40 @@
#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 "Cafe/HW/Latte/Renderer/Metal/MetalCommon.h" #include "Cafe/HW/Latte/Renderer/Metal/MetalCommon.h"
#include "Cemu/FileCache/FileCache.h"
#include "config/ActiveSettings.h"
#include "Cemu/Logging/CemuLogging.h" #include "Cemu/Logging/CemuLogging.h"
#include "Common/precompiled.h" #include "Common/precompiled.h"
bool s_isLoadingShadersMtl{ false };
class FileCache* s_mslCache{nullptr};
extern std::atomic_int g_compiled_shaders_total;
extern std::atomic_int g_compiled_shaders_async;
RendererShaderMtl::RendererShaderMtl(MetalRenderer* mtlRenderer, ShaderType type, uint64 baseHash, uint64 auxHash, bool isGameShader, bool isGfxPackShader, const std::string& mslCode) RendererShaderMtl::RendererShaderMtl(MetalRenderer* mtlRenderer, ShaderType type, uint64 baseHash, uint64 auxHash, bool isGameShader, bool isGfxPackShader, const std::string& mslCode)
: RendererShader(type, baseHash, auxHash, isGameShader, isGfxPackShader), m_mtlr{mtlRenderer} : RendererShader(type, baseHash, auxHash, isGameShader, isGfxPackShader), m_mtlr{mtlRenderer}
{ {
// Fragment functions are compiled just-in-time if (LoadBinary())
return;
if (m_type == ShaderType::kFragment) if (m_type == ShaderType::kFragment)
{ {
// Fragment functions are compiled just-in-time
m_mslCode = mslCode; m_mslCode = mslCode;
} }
else else
{ {
Compile(mslCode); Compile(mslCode);
} }
// Store the compiled shader in the cache
StoreBinary();
// Count shader compilation
if (!s_isLoadingShadersMtl)
g_compiled_shaders_total++;
} }
RendererShaderMtl::~RendererShaderMtl() RendererShaderMtl::~RendererShaderMtl()
@ -69,17 +87,29 @@ void RendererShaderMtl::CompileFragmentFunction(CachedFBOMtl* activeFBO)
void RendererShaderMtl::ShaderCacheLoading_begin(uint64 cacheTitleId) void RendererShaderMtl::ShaderCacheLoading_begin(uint64 cacheTitleId)
{ {
cemuLog_log(LogType::MetalLogging, "RendererShaderMtl::ShaderCacheLoading_begin not implemented!"); if (s_mslCache)
{
delete s_mslCache;
}
uint32 spirvCacheMagic = GeneratePrecompiledCacheId();
const std::string cacheFilename = fmt::format("{:016x}_msl.bin", cacheTitleId);
const fs::path cachePath = ActiveSettings::GetCachePath("shaderCache/precompiled/{}", cacheFilename);
s_mslCache = FileCache::Open(cachePath, true, spirvCacheMagic);
if (!s_mslCache)
cemuLog_log(LogType::Force, "Unable to open MSL cache {}", cacheFilename);
s_isLoadingShadersMtl = true;
} }
void RendererShaderMtl::ShaderCacheLoading_end() void RendererShaderMtl::ShaderCacheLoading_end()
{ {
cemuLog_log(LogType::MetalLogging, "RendererShaderMtl::ShaderCacheLoading_end not implemented!"); s_isLoadingShadersMtl = false;
} }
void RendererShaderMtl::ShaderCacheLoading_Close() void RendererShaderMtl::ShaderCacheLoading_Close()
{ {
cemuLog_log(LogType::MetalLogging, "RendererShaderMtl::ShaderCacheLoading_Close not implemented!"); delete s_mslCache;
g_compiled_shaders_total = 0;
g_compiled_shaders_async = 0;
} }
void RendererShaderMtl::Compile(const std::string& mslCode) void RendererShaderMtl::Compile(const std::string& mslCode)
@ -95,3 +125,33 @@ void RendererShaderMtl::Compile(const std::string& mslCode)
m_function = library->newFunction(NS::String::string("main0", NS::ASCIIStringEncoding)); m_function = library->newFunction(NS::String::string("main0", NS::ASCIIStringEncoding));
library->release(); library->release();
} }
bool RendererShaderMtl::LoadBinary()
{
// HACK: since fragment functions are compiled just-in-time, we cannot load them from the cache
if (m_type == ShaderType::kFragment)
return false;
uint64 h1, h2;
GenerateShaderPrecompiledCacheFilename(m_type, m_baseHash, m_auxHash, h1, h2);
if (!s_mslCache->GetFile({h1, h2 }, m_binary))
return false;
// TODO: implement
return false;
return true;
}
void RendererShaderMtl::StoreBinary()
{
if (m_binary.size() == 0)
{
// TODO: retrieve the binary from the function
return;
}
uint64 h1, h2;
GenerateShaderPrecompiledCacheFilename(m_type, m_baseHash, m_auxHash, h1, h2);
s_mslCache->AddFileAsync({h1, h2 }, m_binary.data(), m_binary.size());
}

View File

@ -58,7 +58,11 @@ private:
MTL::Function* m_function = nullptr; MTL::Function* m_function = nullptr;
std::vector<uint8> m_binary;
std::string m_mslCode; std::string m_mslCode;
void Compile(const std::string& mslCode); void Compile(const std::string& mslCode);
bool LoadBinary();
void StoreBinary();
}; };