Skip to content

Commit 26e40a4

Browse files
authored
Add Metal backend (cemu-project#1287)
1 parent 5520613 commit 26e40a4

File tree

108 files changed

+14989
-456
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

108 files changed

+14989
-456
lines changed

.gitmodules

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818
path = dependencies/imgui
1919
url = https://github.com/ocornut/imgui
2020
shallow = true
21+
[submodule "dependencies/metal-cpp"]
22+
path = dependencies/metal-cpp
23+
url = https://github.com/bkaradzic/metal-cpp.git
24+
shallow = true
2125
[submodule "dependencies/xbyak_aarch64"]
2226
path = dependencies/xbyak_aarch64
2327
url = https://github.com/fujitsu/xbyak_aarch64

CMakeLists.txt

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,20 @@ if (UNIX AND NOT APPLE)
102102
option(ENABLE_BLUEZ "Build with Bluez support" ON)
103103
endif()
104104

105+
if (APPLE)
106+
set(ENABLE_METAL_DEFAULT ON)
107+
else()
108+
set(ENABLE_METAL_DEFAULT OFF)
109+
endif()
110+
105111
option(ENABLE_OPENGL "Enables the OpenGL backend" ON)
106112
option(ENABLE_VULKAN "Enables the Vulkan backend" ON)
113+
option(ENABLE_METAL "Enables the Metal backend" ${ENABLE_METAL_DEFAULT})
107114
option(ENABLE_DISCORD_RPC "Enables the Discord Rich Presence feature" ON)
108115

116+
if (ENABLE_METAL AND NOT APPLE)
117+
message(FATAL_ERROR "Metal backend is only supported on Apple platforms")
118+
endif()
109119

110120
# input backends
111121
if (WIN32)
@@ -180,6 +190,12 @@ if (ENABLE_OPENGL)
180190
find_package(OpenGL REQUIRED)
181191
endif()
182192

193+
if (ENABLE_METAL)
194+
include_directories(${CMAKE_SOURCE_DIR}/dependencies/metal-cpp)
195+
196+
add_definitions(-DENABLE_METAL=1)
197+
endif()
198+
183199
if (ENABLE_DISCORD_RPC)
184200
add_compile_definitions(ENABLE_DISCORD_RPC)
185201
endif()
@@ -204,7 +220,7 @@ endif()
204220

205221
if (ENABLE_CUBEB)
206222
if (NOT ENABLE_VCPKG)
207-
find_package(cubeb)
223+
find_package(cubeb)
208224
endif()
209225
if (NOT cubeb_FOUND)
210226
option(BUILD_TESTS "" OFF)

dependencies/metal-cpp

Submodule metal-cpp added at a63bd17

src/Cafe/CMakeLists.txt

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,69 @@ add_library(CemuCafe
537537
)
538538

539539
if(APPLE)
540-
target_sources(CemuCafe PRIVATE "HW/Latte/Renderer/Vulkan/CocoaSurface.mm")
540+
target_sources(CemuCafe PRIVATE
541+
HW/Latte/Renderer/Vulkan/CocoaSurface.mm
542+
HW/Latte/Renderer/MetalView.mm
543+
HW/Latte/Renderer/MetalView.h
544+
)
545+
endif()
546+
547+
if(ENABLE_METAL)
548+
target_sources(CemuCafe PRIVATE
549+
HW/Latte/Renderer/Metal/CachedFBOMtl.cpp
550+
HW/Latte/Renderer/Metal/CachedFBOMtl.h
551+
HW/Latte/Renderer/Metal/LatteTextureMtl.cpp
552+
HW/Latte/Renderer/Metal/LatteTextureMtl.h
553+
HW/Latte/Renderer/Metal/LatteTextureReadbackMtl.cpp
554+
HW/Latte/Renderer/Metal/LatteTextureReadbackMtl.h
555+
HW/Latte/Renderer/Metal/LatteTextureViewMtl.cpp
556+
HW/Latte/Renderer/Metal/LatteTextureViewMtl.h
557+
HW/Latte/Renderer/Metal/LatteToMtl.cpp
558+
HW/Latte/Renderer/Metal/LatteToMtl.h
559+
HW/Latte/Renderer/Metal/MetalAttachmentsInfo.cpp
560+
HW/Latte/Renderer/Metal/MetalAttachmentsInfo.h
561+
HW/Latte/Renderer/Metal/MetalBufferAllocator.cpp
562+
HW/Latte/Renderer/Metal/MetalBufferAllocator.h
563+
HW/Latte/Renderer/Metal/MetalCommon.h
564+
HW/Latte/Renderer/Metal/MetalCppImpl.cpp
565+
HW/Latte/Renderer/Metal/MetalDepthStencilCache.cpp
566+
HW/Latte/Renderer/Metal/MetalDepthStencilCache.h
567+
HW/Latte/Renderer/Metal/MetalLayer.h
568+
HW/Latte/Renderer/Metal/MetalLayer.mm
569+
HW/Latte/Renderer/Metal/MetalLayerHandle.cpp
570+
HW/Latte/Renderer/Metal/MetalLayerHandle.h
571+
HW/Latte/Renderer/Metal/MetalMemoryManager.cpp
572+
HW/Latte/Renderer/Metal/MetalMemoryManager.h
573+
HW/Latte/Renderer/Metal/MetalOutputShaderCache.cpp
574+
HW/Latte/Renderer/Metal/MetalOutputShaderCache.h
575+
HW/Latte/Renderer/Metal/MetalPerformanceMonitor.h
576+
HW/Latte/Renderer/Metal/MetalPipelineCache.cpp
577+
HW/Latte/Renderer/Metal/MetalPipelineCache.h
578+
HW/Latte/Renderer/Metal/MetalPipelineCompiler.cpp
579+
HW/Latte/Renderer/Metal/MetalPipelineCompiler.h
580+
HW/Latte/Renderer/Metal/MetalQuery.cpp
581+
HW/Latte/Renderer/Metal/MetalQuery.h
582+
HW/Latte/Renderer/Metal/MetalRenderer.cpp
583+
HW/Latte/Renderer/Metal/MetalRenderer.h
584+
HW/Latte/Renderer/Metal/MetalSamplerCache.cpp
585+
HW/Latte/Renderer/Metal/MetalSamplerCache.h
586+
HW/Latte/Renderer/Metal/MetalVoidVertexPipeline.cpp
587+
HW/Latte/Renderer/Metal/MetalVoidVertexPipeline.h
588+
HW/Latte/Renderer/Metal/RendererShaderMtl.cpp
589+
HW/Latte/Renderer/Metal/RendererShaderMtl.h
590+
HW/Latte/Renderer/Metal/UtilityShaderSource.h
591+
)
592+
593+
target_sources(CemuCafe PRIVATE
594+
HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSLAttrDecoder.cpp
595+
HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSL.cpp
596+
HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSLHeader.hpp
597+
)
598+
599+
target_link_libraries(CemuCafe PRIVATE
600+
"-framework Metal"
601+
"-framework QuartzCore"
602+
)
541603
endif()
542604

543605
if(CEMU_ARCHITECTURE MATCHES "(aarch64)|(AARCH64)|(arm64)|(ARM64)")

src/Cafe/CafeSystem.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,17 @@ void InfoLog_PrintActiveSettings()
249249
if (ActiveSettings::GetGraphicsAPI() == GraphicAPI::kVulkan)
250250
{
251251
cemuLog_log(LogType::Force, "Async compile: {}", GetConfig().async_compile.GetValue() ? "true" : "false");
252-
if(!GetConfig().vk_accurate_barriers.GetValue())
252+
if (!GetConfig().vk_accurate_barriers.GetValue())
253+
cemuLog_log(LogType::Force, "Accurate barriers are disabled!");
254+
}
255+
else if (ActiveSettings::GetGraphicsAPI() == GraphicAPI::kMetal)
256+
{
257+
cemuLog_log(LogType::Force, "Async compile: {}", GetConfig().async_compile.GetValue() ? "true" : "false");
258+
cemuLog_log(LogType::Force, "Force mesh shaders: {}", GetConfig().force_mesh_shaders.GetValue() ? "true" : "false");
259+
cemuLog_log(LogType::Force, "Fast math: {}", g_current_game_profile->GetShaderFastMath() ? "true" : "false");
260+
cemuLog_log(LogType::Force, "Buffer cache type: {}", g_current_game_profile->GetBufferCacheMode());
261+
cemuLog_log(LogType::Force, "Position invariance: {}", g_current_game_profile->GetPositionInvariance());
262+
if (!GetConfig().vk_accurate_barriers.GetValue())
253263
cemuLog_log(LogType::Force, "Accurate barriers are disabled!");
254264
}
255265
cemuLog_log(LogType::Force, "Console language: {}", stdx::to_underlying(config.console_language.GetValue()));
@@ -1027,7 +1037,7 @@ namespace CafeSystem
10271037
{
10281038
// starting with Cemu 1.27.0 /vol/storage_mlc01/ is virtualized, meaning that it doesn't point to one singular host os folder anymore
10291039
// instead it now uses a more complex solution to source titles with various formats (folder, wud, wua) from the game paths and host mlc path
1030-
1040+
10311041
// todo - mount /vol/storage_mlc01/ with base priority to the host mlc?
10321042

10331043
// since mounting titles is an expensive operation we have to avoid mounting all titles at once

src/Cafe/GameProfile/GameProfile.cpp

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ bool gameProfile_loadIntegerOption(IniParser& iniParser, const char* optionName,
127127
{
128128
cemuLog_log(LogType::Force, "Value '{}' is out of range for option '{}' in game profile", *option_value, optionName);
129129
return false;
130-
}
130+
}
131131
}
132132

133133
template<typename T>
@@ -224,8 +224,11 @@ bool GameProfile::Load(uint64_t title_id)
224224
gameProfile_loadIntegerOption(&iniParser, "graphics_api", &graphicsApi, -1, 0, 1);
225225
if (graphicsApi.value != -1)
226226
m_graphics_api = (GraphicAPI)graphicsApi.value;
227-
227+
228228
gameProfile_loadEnumOption(iniParser, "accurateShaderMul", m_accurateShaderMul);
229+
gameProfile_loadBooleanOption2(iniParser, "shaderFastMath", m_shaderFastMath);
230+
gameProfile_loadEnumOption(iniParser, "metalBufferCacheMode2", m_metalBufferCacheMode);
231+
gameProfile_loadEnumOption(iniParser, "positionInvariance2", m_positionInvariance);
229232

230233
// legacy support
231234
auto option_precompiledShaders = iniParser.FindOption("precompiledShaders");
@@ -277,7 +280,7 @@ bool GameProfile::Load(uint64_t title_id)
277280
void GameProfile::Save(uint64_t title_id)
278281
{
279282
auto gameProfileDir = ActiveSettings::GetConfigPath("gameProfiles");
280-
if (std::error_code ex_ec; !fs::exists(gameProfileDir, ex_ec))
283+
if (std::error_code ex_ec; !fs::exists(gameProfileDir, ex_ec))
281284
fs::create_directories(gameProfileDir, ex_ec);
282285
auto gameProfilePath = gameProfileDir / fmt::format("{:016x}.ini", title_id);
283286
FileStream* fs = FileStream::createFile2(gameProfilePath);
@@ -292,22 +295,23 @@ void GameProfile::Save(uint64_t title_id)
292295

293296
#define WRITE_OPTIONAL_ENTRY(__NAME) if (m_##__NAME) fs->writeLine(fmt::format("{} = {}", #__NAME, m_##__NAME.value()).c_str());
294297
#define WRITE_ENTRY(__NAME) fs->writeLine(fmt::format("{} = {}", #__NAME, m_##__NAME).c_str());
298+
#define WRITE_ENTRY_NUMBERED(__NAME, __NUM) fs->writeLine(fmt::format("{} = {}", #__NAME #__NUM, m_##__NAME).c_str());
295299

296300
fs->writeLine("[General]");
297301
WRITE_OPTIONAL_ENTRY(loadSharedLibraries);
298302
WRITE_ENTRY(startWithPadView);
299-
300303
fs->writeLine("");
301304

302-
303305
fs->writeLine("[CPU]");
304306
WRITE_OPTIONAL_ENTRY(cpuMode);
305307
WRITE_ENTRY(threadQuantum);
306-
307308
fs->writeLine("");
308309

309310
fs->writeLine("[Graphics]");
310311
WRITE_ENTRY(accurateShaderMul);
312+
WRITE_ENTRY(shaderFastMath);
313+
WRITE_ENTRY_NUMBERED(metalBufferCacheMode, 2);
314+
WRITE_ENTRY_NUMBERED(positionInvariance, 2);
311315
WRITE_OPTIONAL_ENTRY(precompiledShaders);
312316
WRITE_OPTIONAL_ENTRY(graphics_api);
313317
fs->writeLine("");
@@ -323,6 +327,7 @@ void GameProfile::Save(uint64_t title_id)
323327

324328
#undef WRITE_OPTIONAL_ENTRY
325329
#undef WRITE_ENTRY
330+
#undef WRITE_ENTRY_NUMBERED
326331

327332
delete fs;
328333
}
@@ -337,6 +342,9 @@ void GameProfile::ResetOptional()
337342

338343
// graphic settings
339344
m_accurateShaderMul = AccurateShaderMulOption::True;
345+
m_shaderFastMath = true;
346+
m_metalBufferCacheMode = MetalBufferCacheMode::Auto;
347+
m_positionInvariance = PositionInvariance::Auto;
340348
// cpu settings
341349
m_threadQuantum = kThreadQuantumDefault;
342350
m_cpuMode.reset(); // CPUModeOption::kSingleCoreRecompiler;
@@ -354,9 +362,12 @@ void GameProfile::Reset()
354362
// general settings
355363
m_loadSharedLibraries = true;
356364
m_startWithPadView = false;
357-
365+
358366
// graphic settings
359367
m_accurateShaderMul = AccurateShaderMulOption::True;
368+
m_shaderFastMath = true;
369+
m_metalBufferCacheMode = MetalBufferCacheMode::Auto;
370+
m_positionInvariance = PositionInvariance::Auto;
360371
m_precompiledShaders = PrecompiledShaderOption::Auto;
361372
// cpu settings
362373
m_threadQuantum = kThreadQuantumDefault;

src/Cafe/GameProfile/GameProfile.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ class GameProfile
3131

3232
[[nodiscard]] const std::optional<GraphicAPI>& GetGraphicsAPI() const { return m_graphics_api; }
3333
[[nodiscard]] const AccurateShaderMulOption& GetAccurateShaderMul() const { return m_accurateShaderMul; }
34+
[[nodiscard]] bool GetShaderFastMath() const { return m_shaderFastMath; }
35+
[[nodiscard]] MetalBufferCacheMode GetBufferCacheMode() const { return m_metalBufferCacheMode; }
36+
[[nodiscard]] PositionInvariance GetPositionInvariance() const { return m_positionInvariance; }
3437
[[nodiscard]] const std::optional<PrecompiledShaderOption>& GetPrecompiledShadersState() const { return m_precompiledShaders; }
3538

3639
[[nodiscard]] uint32 GetThreadQuantum() const { return m_threadQuantum; }
@@ -54,6 +57,9 @@ class GameProfile
5457
// graphic settings
5558
std::optional<GraphicAPI> m_graphics_api{};
5659
AccurateShaderMulOption m_accurateShaderMul = AccurateShaderMulOption::True;
60+
bool m_shaderFastMath = true;
61+
MetalBufferCacheMode m_metalBufferCacheMode = MetalBufferCacheMode::Auto;
62+
PositionInvariance m_positionInvariance = PositionInvariance::Auto;
5763
std::optional<PrecompiledShaderOption> m_precompiledShaders{};
5864
// cpu settings
5965
uint32 m_threadQuantum = kThreadQuantumDefault; // values: 20000 45000 60000 80000 100000

0 commit comments

Comments
 (0)