Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for macOS #7

Merged
merged 2 commits into from
Jan 24, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ set_target_properties(svulkan2 PROPERTIES POSITION_INDEPENDENT_CODE TRUE)
target_compile_definitions(imgui PRIVATE VK_NO_PROTOTYPES)
target_compile_definitions(svulkan2 PUBLIC VK_NO_PROTOTYPES)

if (${SAPIEN_MACOS})
target_compile_definitions(svulkan2 PUBLIC SAPIEN_MACOS)
target_compile_definitions(svulkan2 PUBLIC VK_USE_PLATFORM_MACOS_MVK)
target_compile_definitions(svulkan2 PUBLIC VK_ENABLE_BETA_EXTENSIONS)
endif()
if (${VK_VALIDATION})
target_compile_definitions(svulkan2 PUBLIC VK_VALIDATION)
endif()

target_include_directories(svulkan2 PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
Expand Down
28 changes: 28 additions & 0 deletions cmake/glfw.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,31 @@ endif()

set_target_properties(glfw PROPERTIES POSITION_INDEPENDENT_CODE ON)
target_compile_definitions(glfw INTERFACE GLFW_INCLUDE_VULKAN)

# apply patch
if(APPLE)
set(PATCH_FILE "${CMAKE_CURRENT_SOURCE_DIR}/patches/glfw-3.3.3-for-apple.patch")
execute_process(
COMMAND git apply --check ${PATCH_FILE}
WORKING_DIRECTORY ${glfw_SOURCE_DIR}
RESULT_VARIABLE PATCH_RESULT
OUTPUT_QUIET
ERROR_QUIET
)
if(PATCH_RESULT EQUAL 0)
execute_process(
COMMAND git apply ${PATCH_FILE}
WORKING_DIRECTORY ${glfw_SOURCE_DIR}
RESULT_VARIABLE APPLY_RESULT
OUTPUT_VARIABLE APPLY_OUTPUT
ERROR_VARIABLE APPLY_ERROR
)
if(NOT APPLY_RESULT EQUAL 0)
message(FATAL_ERROR "Failed to apply glfw patch:\n${APPLY_OUTPUT}\n${APPLY_ERROR}")
else()
message(STATUS "Glfw patch applied successfully.")
endif()
else()
message(STATUS "Glfw patch already applied.")
endif()
endif()
3 changes: 3 additions & 0 deletions cmake/openexr.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,7 @@ set(BUILD_WEBSITE OFF CACHE BOOL "" FORCE)
set(OPENEXR_BUILD_PYTHON OFF CACHE BOOL "" FORCE)
set(OPENEXR_FORCE_INTERNAL_IMATH ON CACHE BOOL "" FORCE)

if(APPLE)
set(OPENEXR_FORCE_INTERNAL_DEFLATE ON CACHE BOOL "Force using an internal libdeflate")
endif()
FetchContent_MakeAvailable(openexr)
28 changes: 28 additions & 0 deletions cmake/openvr.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,31 @@ endif()
if (NOT MSVC)
target_compile_options(openvr_api PRIVATE -include ${CMAKE_CURRENT_SOURCE_DIR}/cmake/openvr_definitions.h)
endif()

# apply patch
if(APPLE)
set(PATCH_FILE "${CMAKE_CURRENT_SOURCE_DIR}/patches/openvr-v2.2.3-for-apple.patch")
execute_process(
COMMAND git apply --check ${PATCH_FILE}
WORKING_DIRECTORY ${openvr_SOURCE_DIR}
RESULT_VARIABLE PATCH_RESULT
OUTPUT_QUIET
ERROR_QUIET
)
if(PATCH_RESULT EQUAL 0)
execute_process(
COMMAND git apply ${PATCH_FILE}
WORKING_DIRECTORY ${openvr_SOURCE_DIR}
RESULT_VARIABLE APPLY_RESULT
OUTPUT_VARIABLE APPLY_OUTPUT
ERROR_VARIABLE APPLY_ERROR
)
if(NOT APPLY_RESULT EQUAL 0)
message(FATAL_ERROR "Failed to apply openvr patch:\n${APPLY_OUTPUT}\n${APPLY_ERROR}")
else()
message(STATUS "Openvr patch applied successfully.")
endif()
else()
message(STATUS "Openvr patch already applied.")
endif()
endif()
20 changes: 19 additions & 1 deletion include/svulkan2/core/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,21 @@ std::string getLogLevel();
}; // namespace logger

namespace core {

#ifdef SAPIEN_MACOS
struct VkSamplerCreateInfoCompare {
bool operator()(const vk::SamplerCreateInfo& lhs, const vk::SamplerCreateInfo& rhs) const {
return std::tie(
lhs.sType, lhs.pNext, lhs.flags, lhs.magFilter, lhs.minFilter, lhs.mipmapMode,
lhs.addressModeU, lhs.addressModeV, lhs.addressModeW, lhs.mipLodBias, lhs.anisotropyEnable,
lhs.maxAnisotropy, lhs.compareEnable, lhs.compareOp, lhs.minLod, lhs.maxLod, lhs.borderColor,
lhs.unnormalizedCoordinates) <
std::tie(rhs.sType, rhs.pNext, rhs.flags, rhs.magFilter, rhs.minFilter, rhs.mipmapMode,
rhs.addressModeU, rhs.addressModeV, rhs.addressModeW, rhs.mipLodBias, rhs.anisotropyEnable,
rhs.maxAnisotropy, rhs.compareEnable, rhs.compareOp, rhs.minLod, rhs.maxLod, rhs.borderColor,
rhs.unnormalizedCoordinates);
}
};
#endif
class Instance;
class PhysicalDevice;
class Device;
Expand Down Expand Up @@ -103,7 +117,11 @@ class Context : public std::enable_shared_from_this<Context> {
void createDescriptorPool();

std::mutex mSamplerLock{};
#ifdef SAPIEN_MACOS
std::map<vk::SamplerCreateInfo, vk::UniqueSampler, VkSamplerCreateInfoCompare> mSamplerRegistry;
#else
std::map<vk::SamplerCreateInfo, vk::UniqueSampler> mSamplerRegistry;
#endif
};

} // namespace core
Expand Down
13 changes: 13 additions & 0 deletions patches/glfw-3.3.3-for-apple.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
diff --git a/src/vulkan.c b/src/vulkan.c
index 22c54e4..05598ce 100644
--- a/src/vulkan.c
+++ b/src/vulkan.c
@@ -57,6 +57,8 @@ GLFWbool _glfwInitVulkan(int mode)
_glfw.vk.handle = _glfw_dlopen("vulkan-1.dll");
#elif defined(_GLFW_COCOA)
_glfw.vk.handle = _glfw_dlopen("libvulkan.1.dylib");
+ if (!_glfw.vk.handle)
+ _glfw.vk.handle = _glfw_dlopen(getenv("SAPIEN_VULKAN_LIBRARY_PATH"));
if (!_glfw.vk.handle)
_glfw.vk.handle = _glfwLoadLocalVulkanLoaderNS();
#else
37 changes: 37 additions & 0 deletions patches/openvr-v2.2.3-for-apple.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index fb4c785..21c6cd7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -60,7 +60,7 @@ elseif(APPLE)
set(PLATFORM_NAME "osx")
add_definitions(-DOSX -DPOSIX)
if(BUILD_UNIVERSAL)
- set(CMAKE_OSX_ARCHITECTURES "i386;x86_64")
+ set(CMAKE_OSX_ARCHITECTURES "i386;x86_64;arm64")
endif()
if(BUILD_OSX_I386)
set(PROCESSOR_ARCH "32")
diff --git a/src/vrcore/pathtools_public.cpp b/src/vrcore/pathtools_public.cpp
index 161522b..0885879 100644
--- a/src/vrcore/pathtools_public.cpp
+++ b/src/vrcore/pathtools_public.cpp
@@ -21,7 +21,6 @@

#if defined OSX
#include <Foundation/Foundation.h>
-#include <AppKit/AppKit.h>
#include <mach-o/dyld.h>
#define _S_IFDIR S_IFDIR // really from tier0/platform.h which we dont have yet
#endif
diff --git a/src/vrcore/vrpathregistry_public.cpp b/src/vrcore/vrpathregistry_public.cpp
index 0fbff25..822374e 100644
--- a/src/vrcore/vrpathregistry_public.cpp
+++ b/src/vrcore/vrpathregistry_public.cpp
@@ -14,7 +14,6 @@
#undef GetEnvironmentVariable
#elif defined OSX
#include <Foundation/Foundation.h>
-#include <AppKit/AppKit.h>
#elif defined(LINUX)
#include <dlfcn.h>
#include <stdio.h>
10 changes: 8 additions & 2 deletions src/common/profiler.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
#include "svulkan2/common/profiler.h"
#ifdef SVULKAN2_CUDA_INTEROP
#include <nvtx3/nvToolsExt.h>
#endif

namespace svulkan2 {

#ifdef SVULKAN2_CUDA_INTEROP
void ProfilerEvent(char const *name) { nvtxMarkA(name); }
void ProfilerBlockBegin(char const *name) { nvtxRangePushA(name); }
void ProfilerBlockEnd() { nvtxRangePop(); }

#else
void ProfilerEvent(char const *name) { }
void ProfilerBlockBegin(char const *name) { }
void ProfilerBlockEnd() { }
#endif
} // namespace sapien
4 changes: 4 additions & 0 deletions src/core/allocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,11 @@ Allocator::Allocator(Device &device) {
vk::BufferUsageFlagBits::eVertexBuffer |
vk::BufferUsageFlagBits::eIndexBuffer |
vk::BufferUsageFlagBits::eTransferDst);
#if !defined(VK_USE_PLATFORM_MACOS_MVK)
vk::ExternalMemoryBufferCreateInfo externalMemoryBufferInfo(
vk::ExternalMemoryHandleTypeFlagBits::eOpaqueFd);
bufferInfo.setPNext(&externalMemoryBufferInfo);
#endif

vk::MemoryRequirements memReq;
{
Expand All @@ -110,9 +112,11 @@ Allocator::Allocator(Device &device) {
// poolInfo.minAllocationAlignment = std::max(
// std::max(limits.minStorageBufferOffsetAlignment, limits.minTexelBufferOffsetAlignment),
// limits.minUniformBufferOffsetAlignment);
#if !defined(VK_USE_PLATFORM_MACOS_MVK)
mExternalAllocInfo =
vk::ExportMemoryAllocateInfo(vk::ExternalMemoryHandleTypeFlagBits::eOpaqueFd);
poolInfo.pMemoryAllocateNext = &mExternalAllocInfo;
#endif
vmaCreatePool(mMemoryAllocator, &poolInfo, &mExternalMemoryPool);
}

Expand Down
5 changes: 4 additions & 1 deletion src/core/buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,19 @@ Buffer::Buffer(std::shared_ptr<Device> device, vk::DeviceSize size,
}

vk::BufferCreateInfo bufferInfo({}, size, usageFlags);
#if !defined(VK_USE_PLATFORM_MACOS_MVK)
vk::ExternalMemoryBufferCreateInfo externalMemoryBufferInfo(
vk::ExternalMemoryHandleTypeFlagBits::eOpaqueFd);
#endif

VmaAllocationCreateInfo memoryInfo{};
memoryInfo.usage = memoryUsage;
memoryInfo.flags = allocationFlags;

if (external) {
#if !defined(VK_USE_PLATFORM_MACOS_MVK)
bufferInfo.setPNext(&externalMemoryBufferInfo);

#endif
if (memoryUsage != VMA_MEMORY_USAGE_GPU_ONLY) {
throw std::runtime_error("external buffer can only be device local");
}
Expand Down
4 changes: 4 additions & 0 deletions src/core/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ Device::Device(std::shared_ptr<PhysicalDevice> physicalDevice) : mPhysicalDevice
features.features.setShaderInt64(true);
}

#ifdef VK_USE_PLATFORM_MACOS_MVK
deviceExtensions.push_back(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME);
#endif

deviceExtensions.push_back(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);

if (mPhysicalDevice->getPickedDeviceInfo().cudaId >= 0) {
Expand Down
48 changes: 47 additions & 1 deletion src/core/instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ Instance::Instance(uint32_t appVersion, uint32_t engineVersion, uint32_t apiVers

// ========== set up extensions ========== //
std::vector<const char *> extensions;
#ifdef VK_USE_PLATFORM_MACOS_MVK
extensions.push_back(VK_MVK_MACOS_SURFACE_EXTENSION_NAME);
#endif
auto vkEnumerateInstanceExtensionProperties =
mDynamicLoader->getProcAddress<PFN_vkEnumerateInstanceExtensionProperties>(
"vkEnumerateInstanceExtensionProperties");
Expand Down Expand Up @@ -172,6 +175,41 @@ Instance::Instance(uint32_t appVersion, uint32_t engineVersion, uint32_t apiVers
}
}
}
// Get extensions supported by the instance and store for later use
std::vector<std::string> supportedInstanceExtensions;
uint32_t extCount = 0;
VULKAN_HPP_DEFAULT_DISPATCHER.vkEnumerateInstanceExtensionProperties(nullptr, &extCount, nullptr);
if (extCount > 0) {
std::vector<VkExtensionProperties> extensions(extCount);
if (VULKAN_HPP_DEFAULT_DISPATCHER.vkEnumerateInstanceExtensionProperties(nullptr, &extCount, &extensions.front()) == VK_SUCCESS) {
for (VkExtensionProperties& extension : extensions) {
supportedInstanceExtensions.push_back(extension.extensionName);
}
}
}
std::vector<const char*> enabledInstanceExtensions;
#ifdef VK_USE_PLATFORM_MACOS_MVK
// SRS - When running on iOS/macOS with MoltenVK, enable VK_KHR_get_physical_device_properties2 if not already enabled by the example (required by VK_KHR_portability_subset)
if (std::find(enabledInstanceExtensions.begin(), enabledInstanceExtensions.end(), VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) == enabledInstanceExtensions.end()) {
enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
}
#endif
// Enabled requested instance extensions
if (enabledInstanceExtensions.size() > 0) {
for (const char * enabledExtension : enabledInstanceExtensions) {
// Output message if requested extension is not available
if (std::find(supportedInstanceExtensions.begin(), supportedInstanceExtensions.end(), enabledExtension) == supportedInstanceExtensions.end()) {
printf("Enabled instance extension %s is not present at instance level.\n", enabledExtension);
}
extensions.push_back(enabledExtension);
}
}
#if defined(VK_USE_PLATFORM_MACOS_MVK) && defined(VK_KHR_portability_enumeration)
// SRS - When running on iOS/macOS with MoltenVK and VK_KHR_portability_enumeration is defined and supported by the instance, enable the extension and the flag
if (std::find(supportedInstanceExtensions.begin(), supportedInstanceExtensions.end(), VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME) != supportedInstanceExtensions.end()) {
extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
}
#endif

// vr
if (enableVR && vr::VR_IsHmdPresent()) {
Expand Down Expand Up @@ -203,6 +241,9 @@ Instance::Instance(uint32_t appVersion, uint32_t engineVersion, uint32_t apiVers

try {
auto info = vk::InstanceCreateInfo({}, &appInfo, layers, extensions);
#ifdef VK_USE_PLATFORM_MACOS_MVK
info.flags |= vk::InstanceCreateFlagBits::eEnumeratePortabilityKHR;
#endif
#ifdef VK_VALIDATION
info.setPNext(&validationFeatures);
#endif
Expand Down Expand Up @@ -373,7 +414,10 @@ std::vector<PhysicalDeviceInfo> Instance::summarizePhysicalDevices() const {
bool discrete = deviceType == vk::PhysicalDeviceType::eDiscreteGpu;

ss << std::setw(3) << ord++ << std::setw(40) << name.substr(0, 39).c_str() << std::setw(10)
<< present << std::setw(10) << supported << std::setw(25) << std::hex << PCIToString(pci)
<< present << std::setw(10) << supported << std::setw(25)
#ifdef SVULKAN2_CUDA_INTEROP
<< std::hex << PCIToString(pci)
#endif
<< std::dec << std::setw(10) << (cudaId < 0 ? "No Device" : std::to_string(cudaId))
<< std::setw(15) << rayTracing << std::setw(10) << discrete << std::setw(15) << subgroupSize
<< std::endl;
Expand Down Expand Up @@ -473,13 +517,15 @@ static inline uint32_t computeDevicePriority(PhysicalDeviceInfo const &info,
std::string pciString = hint.substr(4);

// pci can be parsed
#ifdef SVULKAN2_CUDA_INTEROP
try {
auto pci = parsePCIString(pciString);
if (info.pci == pci) {
return 1000;
}
} catch (std::runtime_error const &) {
}
#endif

// only bus is provided
try {
Expand Down
16 changes: 16 additions & 0 deletions src/renderer/gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,21 @@ void GuiWindow::initImgui() {
&instance);

// create a pool for allocating descriptor sets
#ifdef VK_USE_PLATFORM_MACOS_MVK
vk::DescriptorPoolSize pool_sizes[] = {{vk::DescriptorType::eSampler, 100},
{vk::DescriptorType::eCombinedImageSampler, 100},
{vk::DescriptorType::eSampledImage, 100},
{vk::DescriptorType::eStorageImage, 100},
{vk::DescriptorType::eUniformTexelBuffer, 100},
{vk::DescriptorType::eStorageTexelBuffer, 100},
{vk::DescriptorType::eUniformBuffer, 100},
{vk::DescriptorType::eStorageBuffer, 100},
{vk::DescriptorType::eUniformBufferDynamic, 100},
{vk::DescriptorType::eStorageBufferDynamic, 100},
{vk::DescriptorType::eInputAttachment, 100}};
auto info = vk::DescriptorPoolCreateInfo(vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet,
100 * 11, 11, pool_sizes);
#else
vk::DescriptorPoolSize pool_sizes[] = {{vk::DescriptorType::eSampler, 1000},
{vk::DescriptorType::eCombinedImageSampler, 1000},
{vk::DescriptorType::eSampledImage, 1000},
Expand All @@ -215,6 +230,7 @@ void GuiWindow::initImgui() {
{vk::DescriptorType::eInputAttachment, 1000}};
auto info = vk::DescriptorPoolCreateInfo(vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet,
1000 * 11, 11, pool_sizes);
#endif
mDescriptorPool = device.createDescriptorPoolUnique(info);

mImguiRenderPass = createImguiRenderPass(device, mSurfaceFormat.format);
Expand Down
10 changes: 9 additions & 1 deletion src/renderer/renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,17 @@ Renderer::Renderer(std::shared_ptr<RendererConfig> config) {
vk::DescriptorPoolSize pool_sizes[] = {
{vk::DescriptorType::eCombinedImageSampler,
100}, // render targets and input textures TODO: configure instead of 100
#ifdef VK_USE_PLATFORM_MACOS_MVK
{vk::DescriptorType::eUniformBuffer, 100},
#endif
};
auto info = vk::DescriptorPoolCreateInfo(vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet,
100, 1, pool_sizes);
#ifdef VK_USE_PLATFORM_MACOS_MVK
200, 2,
#else
100, 1,
#endif
pool_sizes);
mDescriptorPool = mContext->getDevice().createDescriptorPoolUnique(info);

mObjectPool = std::make_unique<core::DynamicDescriptorPool>(
Expand Down
Loading