Skip to content

Commit 54fe473

Browse files
committed
Initial code for macOS support.
1 parent da5db2a commit 54fe473

18 files changed

+289
-7
lines changed

CMakePresets.json

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,62 @@
113113
"CMAKE_BUILD_TYPE": "Release",
114114
"CMAKE_INTERPROCEDURAL_OPTIMIZATION": true
115115
}
116+
},
117+
{
118+
"name": "macos-base",
119+
"hidden": true,
120+
"generator": "Ninja",
121+
"binaryDir": "${sourceDir}/out/build/${presetName}",
122+
"installDir": "${sourceDir}/out/install/${presetName}",
123+
"cacheVariables": {
124+
"CMAKE_OSX_ARCHITECTURES": "x86_64",
125+
"CMAKE_TOOLCHAIN_FILE": {
126+
"value": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
127+
"type": "FILEPATH"
128+
},
129+
"VCPKG_TARGET_TRIPLET": {
130+
"value": "x64-osx",
131+
"type": "STRING"
132+
}
133+
},
134+
"environment": {
135+
"VCPKG_ROOT": "${sourceDir}/thirdparty/vcpkg"
136+
},
137+
"condition": {
138+
"type": "equals",
139+
"lhs": "${hostSystemName}",
140+
"rhs": "Darwin"
141+
},
142+
"vendor": {
143+
"microsoft.com/VisualStudioRemoteSettings/CMake/2.0": {
144+
"remoteSourceRootDir": "$env{HOME}/.vs/$ms{projectDirName}"
145+
}
146+
}
147+
},
148+
{
149+
"name": "macos-debug",
150+
"displayName": "macOS-Debug",
151+
"inherits": "macos-base",
152+
"cacheVariables": {
153+
"CMAKE_BUILD_TYPE": "Debug"
154+
}
155+
},
156+
{
157+
"name": "macos-relwithdebinfo",
158+
"displayName": "macOS-RelWithDebInfo",
159+
"inherits": "macos-base",
160+
"cacheVariables": {
161+
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
162+
}
163+
},
164+
{
165+
"name": "macos-release",
166+
"displayName": "macOS-Release",
167+
"inherits": "macos-base",
168+
"cacheVariables": {
169+
"CMAKE_BUILD_TYPE": "Release",
170+
"CMAKE_INTERPROCEDURAL_OPTIMIZATION": true
171+
}
116172
}
117173
]
118174
}

UnleashedRecomp/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,14 @@ elseif (CMAKE_SYSTEM_NAME MATCHES "Linux")
9797
"os/linux/user_linux.cpp"
9898
"os/linux/version_linux.cpp"
9999
)
100+
elseif (APPLE)
101+
set(UNLEASHED_RECOMP_OS_CXX_SOURCES
102+
"os/macos/logger_macos.cpp"
103+
"os/macos/media_macos.cpp"
104+
"os/macos/process_macos.cpp"
105+
"os/macos/user_macos.cpp"
106+
"os/macos/version_macos.cpp"
107+
)
100108
endif()
101109

102110
set(UNLEASHED_RECOMP_CPU_CXX_SOURCES

UnleashedRecomp/framework.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,47 @@ inline std::unique_ptr<uint8_t[]> ReadAllBytes(const char* filePath, size_t& fil
6363

6464
return data;
6565
}
66+
67+
#ifndef __cpp_lib_atomic_ref
68+
// Polyfill for std::atomic_ref
69+
namespace std {
70+
template <typename value_type>
71+
class atomic_ref
72+
{
73+
public:
74+
atomic_ref(value_type& ref)
75+
{
76+
ptr = reinterpret_cast<std::atomic<value_type>*>(&ref);
77+
}
78+
79+
void store(value_type desired)
80+
{
81+
ptr->store(desired);
82+
}
83+
84+
bool compare_exchange_weak(value_type& expected, value_type desired)
85+
{
86+
return ptr->compare_exchange_weak(expected, desired);
87+
}
88+
89+
void wait(value_type old)
90+
{
91+
ptr->wait(old);
92+
}
93+
94+
void notify_one()
95+
{
96+
ptr->notify_one();
97+
}
98+
99+
bool operator=(const value_type& rhs)
100+
{
101+
store(rhs);
102+
}
103+
104+
private:
105+
std::atomic<value_type>* ptr;
106+
};
107+
}
108+
#endif
109+

UnleashedRecomp/gpu/rhi/plume_render_interface_types.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
#undef ControlMask
2727
#undef Success
2828
#elif defined(__APPLE__)
29-
typedef struct _NSWindow NSWindow;
29+
typedef void CAMetalLayer;
3030
#endif
3131

3232
#ifdef SDL_VULKAN_ENABLED
@@ -52,9 +52,9 @@ namespace plume {
5252
};
5353
#elif defined(__APPLE__)
5454
struct RenderWindow {
55-
NSWindow* window;
55+
CAMetalLayer* layer;
5656
bool operator==(const struct RenderWindow& rhs) const {
57-
return window == rhs.window;
57+
return layer == rhs.layer;
5858
}
5959
bool operator!=(const struct RenderWindow& rhs) const { return !(*this == rhs); }
6060
};

UnleashedRecomp/gpu/rhi/plume_vulkan.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ namespace plume {
5151
VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
5252
# elif defined(__linux__)
5353
VK_KHR_XLIB_SURFACE_EXTENSION_NAME,
54+
# elif defined(__APPLE__)
55+
VK_EXT_METAL_SURFACE_EXTENSION_NAME,
56+
VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME,
5457
# endif
5558
};
5659

@@ -65,7 +68,11 @@ namespace plume {
6568
VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME,
6669
VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME,
6770
# ifdef VULKAN_OBJECT_NAMES_ENABLED
68-
VK_EXT_DEBUG_UTILS_EXTENSION_NAME
71+
VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
72+
# endif
73+
# ifdef __APPLE__
74+
// Vulkan spec requires this to be enabled if supported.
75+
VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME,
6976
# endif
7077
};
7178

@@ -2045,6 +2052,18 @@ namespace plume {
20452052
fprintf(stderr, "vkCreateXlibSurfaceKHR failed with error code 0x%X.\n", res);
20462053
return;
20472054
}
2055+
# elif defined(__APPLE__)
2056+
assert(renderWindow.window != nullptr);
2057+
VkMetalSurfaceCreateInfoEXT surfaceCreateInfo = {};
2058+
surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT;
2059+
surfaceCreateInfo.pLayer = renderWindow.layer;
2060+
2061+
VulkanInterface *renderInterface = commandQueue->device->renderInterface;
2062+
res = vkCreateMetalSurfaceEXT(renderInterface->instance, &surfaceCreateInfo, nullptr, &surface);
2063+
if (res != VK_SUCCESS) {
2064+
fprintf(stderr, "vkCreateMetalSurfaceEXT failed with error code 0x%X.\n", res);
2065+
return;
2066+
}
20482067
# endif
20492068

20502069
VkBool32 presentSupported = false;
@@ -4321,6 +4340,10 @@ namespace plume {
43214340
}
43224341
}
43234342
# endif
4343+
4344+
# ifdef __APPLE__
4345+
createInfo.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
4346+
# endif
43244347

43254348
res = vkCreateInstance(&createInfo, nullptr, &instance);
43264349
if (res != VK_SUCCESS) {

UnleashedRecomp/gpu/rhi/plume_vulkan.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@
2020
#define VK_USE_PLATFORM_ANDROID_KHR
2121
#elif defined(__linux__)
2222
#define VK_USE_PLATFORM_XLIB_KHR
23+
#elif defined(__APPLE__)
24+
#define VK_USE_PLATFORM_METAL_EXT
25+
// For VK_KHR_portability_subset
26+
#define VK_ENABLE_BETA_EXTENSIONS
2327
#endif
2428

2529
#include <volk.h>

UnleashedRecomp/install/update_checker.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,9 @@ void UpdateChecker::visitWebsite()
166166
#elif defined(__linux__)
167167
std::string command = "xdg-open " + std::string(VISIT_URL) + " &";
168168
std::system(command.c_str());
169+
#elif defined(__APPLE__)
170+
std::string command = "open " + std::string(VISIT_URL) + " &";
171+
std::system(command.c_str());
169172
#else
170173
static_assert(false, "Visit website not implemented for this platform.");
171174
#endif
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#include <os/logger.h>
2+
3+
void os::logger::Init()
4+
{
5+
}
6+
7+
void os::logger::Log(const std::string_view str, ELogType type, const char* func)
8+
{
9+
if (func)
10+
{
11+
fmt::println("[{}] {}", func, str);
12+
}
13+
else
14+
{
15+
fmt::println("{}", str);
16+
}
17+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#include <os/media.h>
2+
3+
bool os::media::IsExternalMediaPlaying()
4+
{
5+
// This functionality is not supported in macOS.
6+
return false;
7+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#include <os/process.h>
2+
3+
#include <mach-o/dyld.h>
4+
#include <signal.h>
5+
#include <unistd.h>
6+
7+
std::filesystem::path os::process::GetExecutablePath()
8+
{
9+
uint32_t exePathSize = PATH_MAX;
10+
char exePath[PATH_MAX] = {};
11+
if (_NSGetExecutablePath(exePath, &exePathSize) == 0)
12+
{
13+
return std::filesystem::path(std::u8string_view((const char8_t*)(exePath)));
14+
}
15+
else
16+
{
17+
return std::filesystem::path();
18+
}
19+
}
20+
21+
std::filesystem::path os::process::GetWorkingDirectory()
22+
{
23+
char cwd[PATH_MAX] = {};
24+
char *res = getcwd(cwd, sizeof(cwd));
25+
if (res != nullptr)
26+
{
27+
return std::filesystem::path(std::u8string_view((const char8_t*)(cwd)));
28+
}
29+
else
30+
{
31+
return std::filesystem::path();
32+
}
33+
}
34+
35+
bool os::process::SetWorkingDirectory(const std::filesystem::path& path)
36+
{
37+
return chdir(path.c_str()) == 0;
38+
}
39+
40+
bool os::process::StartProcess(const std::filesystem::path& path, const std::vector<std::string>& args, std::filesystem::path work)
41+
{
42+
pid_t pid = fork();
43+
if (pid < 0)
44+
return false;
45+
46+
if (pid == 0)
47+
{
48+
setsid();
49+
50+
std::u8string workU8 = work.u8string();
51+
chdir((const char*)(workU8.c_str()));
52+
53+
std::u8string pathU8 = path.u8string();
54+
std::vector<char*> argStrs;
55+
argStrs.push_back((char*)(pathU8.c_str()));
56+
for (const std::string& arg : args)
57+
argStrs.push_back((char *)(arg.c_str()));
58+
59+
argStrs.push_back(nullptr);
60+
execvp((const char*)(pathU8.c_str()), argStrs.data());
61+
raise(SIGKILL);
62+
}
63+
64+
return true;
65+
}
66+
67+
void os::process::CheckConsole()
68+
{
69+
// Always visible on macOS.
70+
g_consoleVisible = true;
71+
}
72+
73+
void os::process::ShowConsole()
74+
{
75+
// Unnecessary on macOS.
76+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include <os/registry.h>
2+
3+
// TODO: Implement
4+
inline bool os::registry::Init()
5+
{
6+
return false;
7+
}
8+
9+
// TODO: read from file?
10+
template<typename T>
11+
bool os::registry::ReadValue(const std::string_view& name, T& data)
12+
{
13+
return false;
14+
}
15+
16+
// TODO: write to file?
17+
template<typename T>
18+
bool os::registry::WriteValue(const std::string_view& name, const T& data)
19+
{
20+
return false;
21+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include <os/user.h>
2+
3+
bool os::user::IsDarkTheme()
4+
{
5+
return false;
6+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#include <os/version.h>
2+
3+
os::version::OSVersion os::version::GetOSVersion()
4+
{
5+
assert(false && "Unimplemented.");
6+
return os::version::OSVersion();
7+
}

UnleashedRecomp/os/registry.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,6 @@ namespace os::registry
1515
#include <os/win32/registry_win32.inl>
1616
#elif defined(__linux__)
1717
#include <os/linux/registry_linux.inl>
18+
#elif defined(__APPLE__)
19+
#include <os/macos/registry_macos.inl>
1820
#endif

UnleashedRecomp/ui/button_guide.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ std::unique_ptr<GuestTexture> g_upKBMIcons;
2020

2121
float g_sideMargins = DEFAULT_SIDE_MARGINS;
2222

23-
std::vector<Button> g_buttons;
23+
static std::vector<Button> g_buttons;
2424

2525
std::unordered_map<EButtonIcon, float> g_iconWidths =
2626
{

UnleashedRecomp/ui/game_window.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,8 @@ void GameWindow::Init(const char* sdlVideoDriver)
211211
s_renderWindow = s_pWindow;
212212
#elif defined(__linux__)
213213
s_renderWindow = { info.info.x11.display, info.info.x11.window };
214+
#elif defined(__APPLE__)
215+
s_renderWindow = { SDL_Metal_GetLayer(SDL_Metal_CreateView(s_pWindow)) };
214216
#else
215217
static_assert(false, "Unknown platform.");
216218
#endif

UnleashedRecomp/ui/message_window.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ static ImFont* g_fntSeurat;
4141

4242
std::string g_text;
4343
int g_result;
44-
std::vector<std::string> g_buttons;
44+
static std::vector<std::string> g_buttons;
4545
int g_defaultButtonIndex;
4646
int g_cancelButtonIndex;
4747

0 commit comments

Comments
 (0)