Vulkan: MoltenVK Support for Developers

MoltenVK original intent was to let developers work on a mac system developing
for the vulkan eco-system. MoltenVK doesn't support all the features that we
require and would require additional workarounds to be actually supported.

It is not expected that we will release Blender with MoltenVK for this reason.
But it still has value for shader developers to validate shaders on metal and
vulkan on a single platform.

![image](/attachments/9a4a9904-a5f6-4922-896d-744dfb78244c)

Pull Request: https://projects.blender.org/blender/blender/pulls/117940
This commit is contained in:
Jeroen Bakker
2024-04-11 11:04:43 +02:00
parent fc68a05e7e
commit c15e5116ab
6 changed files with 56 additions and 31 deletions

View File

@@ -870,19 +870,29 @@ else()
endif()
# Vulkan
if(NOT APPLE)
option(WITH_VULKAN_BACKEND "Enable Vulkan as graphics backend (experimental)" ON)
option(WITH_VULKAN_GUARDEDALLOC "\
Use guardedalloc for host allocations done inside Vulkan (development option)"
OFF
)
option(WITH_VULKAN_BACKEND "Enable Vulkan as graphics backend (experimental)" ON)
option(WITH_VULKAN_GUARDEDALLOC "Use guardedalloc for host allocations done inside Vulkan (development option)"
OFF
)
mark_as_advanced(
WITH_VULKAN_BACKEND
WITH_VULKAN_GUARDEDALLOC
)
if(APPLE)
option(WITH_VULKAN_MOLTENVK "Enable Vulkan over MoltenVK (development option)" OFF)
mark_as_advanced(
WITH_VULKAN_BACKEND
WITH_VULKAN_GUARDEDALLOC
WITH_VULKAN_MOLTENVK
)
if(NOT WITH_EXPERIMENTAL_FEATURES)
set(WITH_VULKAN_BACKEND OFF)
endif()
if(APPLE AND NOT WITH_VULKAN_MOLTENVK)
set(WITH_VULKAN_BACKEND OFF)
endif()
if(NOT WITH_EXPERIMENTAL_FEATURES)
if (APPLE)
set(WITH_VULKAN_MOLTENVK OFF)
endif()
set(WITH_VULKAN_BACKEND OFF)
endif()
# Metal

View File

@@ -43,11 +43,11 @@ find_path(MOLTENVK_INCLUDE_DIR
find_library(MOLTENVK_LIBRARY
NAMES
MoltenVK
libMoltenVK.dylib
HINTS
${_moltenvk_SEARCH_DIRS}
PATH_SUFFIXES
dylib/macOS
dynamic/dylib/macOS
)
# handle the QUIETLY and REQUIRED arguments and set MOLTENVK_FOUND to TRUE if

View File

@@ -108,6 +108,12 @@ if(WITH_OPENSUBDIV)
endif()
add_bundled_libraries(opensubdiv/lib)
if(WITH_VULKAN_BACKEND)
find_package(MoltenVK REQUIRED)
find_package(ShaderC REQUIRED)
find_package(Vulkan REQUIRED)
endif()
if(WITH_CODEC_SNDFILE)
find_package(SndFile)
find_library(_sndfile_FLAC_LIBRARY NAMES flac HINTS ${LIBDIR}/sndfile/lib)

View File

@@ -32,10 +32,6 @@
#include <sys/stat.h>
/* Set to 0 to allow devices that do not have the required features.
* This allows development on OSX until we really needs these features. */
#define STRICT_REQUIREMENTS true
/*
* Should we only select surfaces that are known to be compatible. Or should we in case no
* compatible surfaces have been found select the first one.
@@ -226,14 +222,15 @@ class GHOST_DeviceVK {
queue_create_infos.push_back(graphic_queue_create_info);
VkPhysicalDeviceFeatures device_features = {};
#if STRICT_REQUIREMENTS
#ifndef __APPLE__
device_features.geometryShader = VK_TRUE;
device_features.dualSrcBlend = VK_TRUE;
/* MoltenVK supports logicOp, needs to be build with MVK_USE_METAL_PRIVATE_API. */
device_features.logicOp = VK_TRUE;
#endif
device_features.dualSrcBlend = VK_TRUE;
device_features.imageCubeArray = VK_TRUE;
device_features.multiViewport = VK_TRUE;
device_features.shaderClipDistance = VK_TRUE;
#endif
device_features.drawIndirectFirstInstance = VK_TRUE;
device_features.fragmentStoresAndAtomics = VK_TRUE;
device_features.samplerAnisotropy = features.features.samplerAnisotropy;
@@ -355,7 +352,11 @@ static GHOST_TSuccess ensure_vulkan_device(VkInstance vk_instance,
}
}
#if STRICT_REQUIREMENTS
#ifdef __APPLE__
if (!device_vk.features.features.dualSrcBlend || !device_vk.features.features.imageCubeArray) {
continue;
}
#else
if (!device_vk.features.features.geometryShader || !device_vk.features.features.dualSrcBlend ||
!device_vk.features.features.logicOp || !device_vk.features.features.imageCubeArray)
{
@@ -1000,8 +1001,7 @@ GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
if (use_window_surface) {
const char *native_surface_extension_name = getPlatformSpecificSurfaceExtension();
requireExtension(extensions_available, extensions_enabled, "VK_KHR_surface");
requireExtension(extensions_available, extensions_enabled, VK_KHR_SURFACE_EXTENSION_NAME);
requireExtension(extensions_available, extensions_enabled, native_surface_extension_name);
extensions_device.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
@@ -1010,10 +1010,13 @@ GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
extensions_device.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
/* Enable MoltenVK required instance extensions. */
#ifdef VK_MVK_MOLTENVK_EXTENSION_NAME
#ifdef __APPLE__
requireExtension(
extensions_available, extensions_enabled, "VK_KHR_get_physical_device_properties2");
extensions_available, extensions_enabled, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
#endif
requireExtension(extensions_available,
extensions_enabled,
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
VkInstance instance = VK_NULL_HANDLE;
if (!vulkan_device.has_value()) {
@@ -1046,6 +1049,10 @@ GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
create_info.pNext = &validationFeatures;
}
#ifdef __APPLE__
create_info.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
#endif
VK_CHECK(vkCreateInstance(&create_info, nullptr, &instance));
}
else {

View File

@@ -103,7 +103,9 @@ void VKBackend::detect_workarounds(VKDevice &device)
!device.physical_device_vulkan_12_features_get().shaderOutputViewportIndex;
/* AMD GPUs don't support texture formats that use are aligned to 24 or 48 bits. */
if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)) {
if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY) ||
GPU_type_matches(GPU_DEVICE_APPLE, GPU_OS_MAC, GPU_DRIVER_ANY))
{
workarounds.not_aligned_pixel_formats = true;
}

View File

@@ -1400,15 +1400,15 @@ static const char arg_handle_gpu_backend_set_doc[] =
"\tForce to use a specific GPU backend. Valid options: "
# ifdef WITH_OPENGL_BACKEND
"'opengl'"
# if defined(WITH_VULKAN_BACKEND)
" or "
# endif
# endif
# ifdef WITH_VULKAN_BACKEND
"'vulkan' (experimental)"
# endif
# ifdef WITH_METAL_BACKEND
"'metal'"
# endif
# ifdef WITH_VULKAN_BACKEND
# if defined(WITH_OPENGL_BACKEND) || defined(WITH_METAL_BACKEND)
" or "
# endif
"'vulkan' (experimental)"
# endif
".";
static int arg_handle_gpu_backend_set(int argc, const char **argv, void * /*data*/)