From c15e5116ab12aa7c91e8ce8b1d44b070a534faef Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Thu, 11 Apr 2024 11:04:43 +0200 Subject: [PATCH] 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 --- CMakeLists.txt | 30 ++++++++++++------ build_files/cmake/Modules/FindMoltenVK.cmake | 4 +-- .../cmake/platform/platform_apple.cmake | 6 ++++ intern/ghost/intern/GHOST_ContextVK.cc | 31 ++++++++++++------- source/blender/gpu/vulkan/vk_backend.cc | 4 ++- source/creator/creator_args.cc | 12 +++---- 6 files changed, 56 insertions(+), 31 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9189d15955e..669d17f61f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 diff --git a/build_files/cmake/Modules/FindMoltenVK.cmake b/build_files/cmake/Modules/FindMoltenVK.cmake index 5d91b56140e..528d969eb19 100644 --- a/build_files/cmake/Modules/FindMoltenVK.cmake +++ b/build_files/cmake/Modules/FindMoltenVK.cmake @@ -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 diff --git a/build_files/cmake/platform/platform_apple.cmake b/build_files/cmake/platform/platform_apple.cmake index 2e381d33f8c..52a4ec91124 100644 --- a/build_files/cmake/platform/platform_apple.cmake +++ b/build_files/cmake/platform/platform_apple.cmake @@ -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) diff --git a/intern/ghost/intern/GHOST_ContextVK.cc b/intern/ghost/intern/GHOST_ContextVK.cc index 5109d6118ff..e610def3eed 100644 --- a/intern/ghost/intern/GHOST_ContextVK.cc +++ b/intern/ghost/intern/GHOST_ContextVK.cc @@ -32,10 +32,6 @@ #include -/* 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 { diff --git a/source/blender/gpu/vulkan/vk_backend.cc b/source/blender/gpu/vulkan/vk_backend.cc index 299b4937858..13316a3a654 100644 --- a/source/blender/gpu/vulkan/vk_backend.cc +++ b/source/blender/gpu/vulkan/vk_backend.cc @@ -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; } diff --git a/source/creator/creator_args.cc b/source/creator/creator_args.cc index b9d848b6688..07ffa0c7d13 100644 --- a/source/creator/creator_args.cc +++ b/source/creator/creator_args.cc @@ -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*/)