Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
13 changes: 10 additions & 3 deletions app/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2019-2024, Arm Limited and Contributors
# Copyright (c) 2019-2025, Arm Limited and Contributors
#
# SPDX-License-Identifier: Apache-2.0
#
Expand Down Expand Up @@ -135,7 +135,7 @@ if(IOS)
XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY "YES"
)
endif ()
# No need to search for Vulkan package or MoltenVK library, Vulkan cache variables already defined on Apple platforms by global_options.cmake
# Vulkan cache variables already defined by main project CMakeLists and updated on Apple platforms by global_options.cmake
if(Vulkan_LIBRARY AND ${Vulkan_VERSION} VERSION_GREATER_EQUAL 1.3.278)
target_sources(${PROJECT_NAME} PRIVATE
${Vulkan_Target_SDK}/iOS/share/vulkan
Expand Down Expand Up @@ -163,17 +163,24 @@ if(IOS)
set(FRAMEWORKS_TO_EMBED)
if(Vulkan_MoltenVK_LIBRARY)
list(APPEND FRAMEWORKS_TO_EMBED "${Vulkan_MoltenVK_LIBRARY};")
message(STATUS "Embedding Vulkan driver: ${Vulkan_MoltenVK_LIBRARY}")
# add support for potentially other iOS Vulkan drivers here...
#elseif(OTHER_IOS_VULKAN_DRIVER)
#list(APPEND FRAMEWORKS_TO_EMBED "${OTHER_IOS_VULKAN_DRIVER};")
#message(STATUS "Embedding Vulkan driver: ${OTHER_IOS_VULKAN_DRIVER}")
else()
message(FATAL_ERROR "Can't find MoltenVK library. Please install the Vulkan SDK or MoltenVK project and set VULKAN_SDK.")
message(FATAL_ERROR "Can't find Vulkan driver for iOS. Please install the Vulkan SDK and run: 'source <MY_SDK_PATH>/iOS/setup-env.sh'")
endif()
if(Vulkan_LIBRARY)
list(APPEND FRAMEWORKS_TO_EMBED "${Vulkan_LIBRARY};")
message(STATUS "Embedding Vulkan loader: ${Vulkan_LIBRARY}")
endif()
if(Vulkan_Layer_VALIDATION)
# trouble is can't turn this on/off if XCode decides to build debug and we're configured for release. Need to revist
# note the Vulkan validation layer must be present and enabled even in release mode for the shader_debugprintf sample
#if(("${VKB_DEBUG}" STREQUAL "ON") OR ("${VKB_VALIDATION_LAYERS}" STREQUAL "ON"))
list(APPEND FRAMEWORKS_TO_EMBED "${Vulkan_Layer_VALIDATION}")
message(STATUS "Embedding Vulkan Validation Layer: ${Vulkan_Layer_VALIDATION}")
#endif()
endif()
set_target_properties(${PROJECT_NAME} PROPERTIES
Expand Down
24 changes: 16 additions & 8 deletions bldsys/cmake/global_options.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@ endif()

if(APPLE)
cmake_minimum_required(VERSION 3.24)
set(VKB_ENABLE_PORTABILITY ON CACHE BOOL "Enable portability enumeration and subset features in the framework. This is required to be set when running on Apple platforms." FORCE)
option(VKB_ENABLE_PORTABILITY "Enable portability enumeration and subset features in the framework. This is default ON for Apple platforms." ON)

# the following assumes MoltenVK is used for these cases: a) standalone deployment on macOS (i.e. set USE_MoltenVK=ON), and b) for iOS deployment
# if this assumption changes (e.g. KosmicKrisp adds standalone or iOS support), then this section will require modification to handle optionality
find_package(Vulkan QUIET OPTIONAL_COMPONENTS MoltenVK)
if(USE_MoltenVK OR (IOS AND (NOT Vulkan_MoltenVK_FOUND OR ${CMAKE_OSX_SYSROOT} STREQUAL "iphonesimulator")))
# if using MoltenVK, or MoltenVK for iOS was not found, or using iOS Simulator, look for MoltenVK in the Vulkan SDK and MoltenVK project locations
# if using MoltenVK standalone, or MoltenVK for iOS not found or using iOS Simulator, look for MoltenVK in Vulkan SDK and MoltenVK project paths
if(NOT Vulkan_MoltenVK_LIBRARY)
# since both are available in the Vulkan SDK and MoltenVK github project, make sure we look for MoltenVK framework on iOS and dylib on macOS
set(_saved_cmake_find_framework ${CMAKE_FIND_FRAMEWORK})
Expand All @@ -58,7 +60,8 @@ if(APPLE)
# on iOS we can control Vulkan library loading priority by selecting which libraries are embedded in the iOS application bundle
if(IOS)
add_compile_definitions(_HPP_VULKAN_LIBRARY="MoltenVK.framework/MoltenVK")
# unset FindVulkan.cmake cache variables so Vulkan loader, Validation Layer, and icd/layer json files are not embedded on iOS
# unset FindVulkan.cmake cache variables so Vulkan loader and Validation Layer libraries are not embedded on iOS Simulator
# the iOS Simulator supports arm64 & x86_64 hosts, but the Vulkan loader and Validation Layer are compiled for arm64 only
unset(Vulkan_LIBRARY CACHE)
unset(Vulkan_Layer_VALIDATION CACHE)

Expand All @@ -69,15 +72,18 @@ if(APPLE)
add_compile_definitions(_GLFW_VULKAN_LIBRARY="libMoltenVK.dylib")
set(ENV{DYLD_LIBRARY_PATH} "${MoltenVK_LIBRARY_PATH}:$ENV{DYLD_LIBRARY_PATH}")
else()
message(FATAL_ERROR "Vulkan library found in MoltenVK search path. Please set VULKAN_SDK to the MoltenVK project install location.")
message(FATAL_ERROR "Vulkan loader found in MoltenVK search path. Please set VULKAN_SDK to the MoltenVK project install location.")
endif()
message(STATUS "Using MoltenVK: ${Vulkan_MoltenVK_LIBRARY}")
message(STATUS "Using MoltenVK standalone: ${Vulkan_MoltenVK_LIBRARY}")
else()
message(FATAL_ERROR "Can't find MoltenVK library. Please install the Vulkan SDK or MoltenVK project and set VULKAN_SDK.")
endif()
elseif(IOS)
# if not using MoltenVK on iOS, set up global Vulkan Library define for iOS Vulkan loader
add_compile_definitions(_HPP_VULKAN_LIBRARY="vulkan.framework/vulkan")
#elseif(OTHER_VULKAN_DRIVER)
# handle any special processing here for other Vulkan driver (e.g. KosmicKrisp) for standalone usage on macOS or deployment to iOS
# would likely require extensions to CMake find_package() OPTIONAL_COMPONENTS and library variables to identify & use other driver
#else()
# if not using standalone driver, retain find_package() results for Vulkan driver, Vulkan loader, and Validation Layer library variables
# no need to override with _HPP_VULKAN_LIBRARY in this case since Vulkan DynamicLoader will find/load Vulkan library on macOS & iOS
endif()

if(CMAKE_GENERATOR MATCHES "Xcode")
Expand All @@ -103,6 +109,8 @@ if(APPLE)
set(CMAKE_SUPPRESS_REGENERATION ON)
endif()
endif()
else()
option(VKB_ENABLE_PORTABILITY "Enable portability enumeration and subset features in the framework. This is default OFF for non-Apple platforms." OFF)
endif()

set(VKB_WARNINGS_AS_ERRORS ON CACHE BOOL "Enable Warnings as Errors")
Expand Down
14 changes: 12 additions & 2 deletions framework/core/instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,9 +251,19 @@ inline bool enable_layer_setting(vk::LayerSettingEXT const &requested_lay
// Vulkan does not provide a reflection API for layer settings. Layer settings are described in each layer JSON manifest.
bool is_available = std::ranges::any_of(
enabled_layers, [&requested_layer_setting](auto const &available_layer) { return strcmp(available_layer, requested_layer_setting.pLayerName) == 0; });

#if defined(PLATFORM__MACOS)
// On Apple platforms the MoltenVK layer is implicitly enabled and available, and cannot be explicitly added or checked via enabled_layers.
is_available = is_available || strcmp(requested_layer_setting.pLayerName, "MoltenVK") == 0;
// On Apple the MoltenVK driver configuration layer is implicitly enabled and available, and cannot be explicitly added or checked via enabled_layers.
if (!is_available && strcmp(requested_layer_setting.pLayerName, "MoltenVK") == 0)
{
// Check for VK_EXT_layer_settings extension in the driver which indicates MoltenVK vs. KosmicKrisp (note: VK_MVK_moltenvk extension is deprecated).
std::vector<vk::ExtensionProperties> available_instance_extensions = vk::enumerateInstanceExtensionProperties();
if (std::ranges::any_of(available_instance_extensions,
[](vk::ExtensionProperties const &extension) { return strcmp(extension.extensionName, VK_EXT_LAYER_SETTINGS_EXTENSION_NAME) == 0; }))
{
is_available = true;
}
}
#endif

if (!is_available)
Expand Down
2 changes: 1 addition & 1 deletion framework/vulkan_sample.h
Original file line number Diff line number Diff line change
Expand Up @@ -1115,7 +1115,7 @@ inline bool VulkanSample<bindingType>::prepare(const ApplicationOptions &options
}

#ifdef VKB_ENABLE_PORTABILITY
// VK_KHR_portability_subset must be enabled if present in the implementation (e.g on macOS/iOS with beta extensions enabled)
// VK_KHR_portability_subset must be enabled if present in the implementation (e.g on macOS/iOS using MoltenVK with beta extensions enabled)
add_device_extension(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME, /*optional=*/true);
#endif

Expand Down
7 changes: 5 additions & 2 deletions samples/api/hello_triangle/hello_triangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ void HelloTriangle::init_device()
}

#if (defined(VKB_ENABLE_PORTABILITY))
// VK_KHR_portability_subset must be enabled if present in the implementation (e.g on macOS/iOS with beta extensions enabled)
// VK_KHR_portability_subset must be enabled if present in the implementation (e.g on macOS/iOS using MoltenVK with beta extensions enabled)
if (std::ranges::any_of(device_extensions,
[](VkExtensionProperties const &extension) { return strcmp(extension.extensionName, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME) == 0; }))
{
Expand Down Expand Up @@ -997,7 +997,10 @@ HelloTriangle::~HelloTriangle()
{
// When destroying the application, we need to make sure the GPU is no longer accessing any resources
// This is done by doing a device wait idle, which blocks until the GPU signals
vkDeviceWaitIdle(context.device);
if (context.device != VK_NULL_HANDLE)
{
vkDeviceWaitIdle(context.device);
}

for (auto &framebuffer : context.swapchain_framebuffers)
{
Expand Down
2 changes: 1 addition & 1 deletion samples/api/hello_triangle_1_3/hello_triangle_1_3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ void HelloTriangleV13::init_device()
}

#if (defined(VKB_ENABLE_PORTABILITY))
// VK_KHR_portability_subset must be enabled if present in the implementation (e.g on macOS/iOS with beta extensions enabled)
// VK_KHR_portability_subset must be enabled if present in the implementation (e.g on macOS/iOS using MoltenVK with beta extensions enabled)
if (std::ranges::any_of(device_extensions,
[](VkExtensionProperties const &extension) { return strcmp(extension.extensionName, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME) == 0; }))
{
Expand Down
17 changes: 13 additions & 4 deletions samples/api/hpp_hello_triangle/hpp_hello_triangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,10 @@ HPPHelloTriangle::HPPHelloTriangle()
HPPHelloTriangle::~HPPHelloTriangle()
{
// Don't release anything until the GPU is completely idle.
device.waitIdle();
if (device)
{
device.waitIdle();
}

teardown_framebuffers();

Expand Down Expand Up @@ -142,7 +145,10 @@ HPPHelloTriangle::~HPPHelloTriangle()
instance.destroyDebugUtilsMessengerEXT(debug_utils_messenger);
}

instance.destroy();
if (instance)
{
instance.destroy();
}
}

bool HPPHelloTriangle::prepare(const vkb::ApplicationOptions &options)
Expand Down Expand Up @@ -325,7 +331,7 @@ vk::Device HPPHelloTriangle::create_device(const std::vector<const char *> &requ
std::vector<const char *> active_device_extensions(required_device_extensions);

#if (defined(VKB_ENABLE_PORTABILITY))
// VK_KHR_portability_subset must be enabled if present in the implementation (e.g on macOS/iOS with beta extensions enabled)
// VK_KHR_portability_subset must be enabled if present in the implementation (e.g on macOS/iOS using MoltenVK with beta extensions enabled)
if (std::ranges::any_of(device_extensions,
[](vk::ExtensionProperties const &extension) { return strcmp(extension.extensionName, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME) == 0; }))
{
Expand Down Expand Up @@ -915,7 +921,10 @@ void HPPHelloTriangle::select_physical_device_and_surface()
void HPPHelloTriangle::teardown_framebuffers()
{
// Wait until device is idle before teardown.
queue.waitIdle();
if (queue)
{
queue.waitIdle();
}

for (auto &framebuffer : swapchain_data.framebuffers)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ void HPPHelloTriangleV13::init_device()
}

#if (defined(VKB_ENABLE_PORTABILITY))
// VK_KHR_portability_subset must be enabled if present in the implementation (e.g on macOS/iOS with beta extensions enabled)
// VK_KHR_portability_subset must be enabled if present in the implementation (e.g on macOS/iOS using MoltenVK with beta extensions enabled)
if (std::ranges::any_of(device_extensions,
[](vk::ExtensionProperties const &extension) { return strcmp(extension.extensionName, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME) == 0; }))
{
Expand Down
33 changes: 0 additions & 33 deletions samples/extensions/descriptor_indexing/descriptor_indexing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,23 +31,6 @@ DescriptorIndexing::DescriptorIndexing()
// Works around a validation layer bug with descriptor pool allocation with VARIABLE_COUNT.
// See: https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/2350.
add_device_extension(VK_KHR_MAINTENANCE1_EXTENSION_NAME);

#if defined(PLATFORM__MACOS)
// On Apple use layer setting to enable MoltenVK's Metal argument buffers - needed for descriptor indexing/scaling
add_instance_extension(VK_EXT_LAYER_SETTINGS_EXTENSION_NAME, /*optional*/ true);

VkLayerSettingEXT layerSetting;
layerSetting.pLayerName = "MoltenVK";
layerSetting.pSettingName = "MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS";
layerSetting.type = VK_LAYER_SETTING_TYPE_INT32_EXT;
layerSetting.valueCount = 1;

// Make this static so layer setting reference remains valid after leaving constructor scope
static const int32_t useMetalArgumentBuffers = 1;
layerSetting.pValues = &useMetalArgumentBuffers;

add_layer_setting(layerSetting);
#endif
}

DescriptorIndexing::~DescriptorIndexing()
Expand Down Expand Up @@ -212,14 +195,6 @@ void DescriptorIndexing::create_bindless_descriptors()
{
uint32_t descriptorCount = descriptor_indexing_properties.maxDescriptorSetUpdateAfterBindSampledImages;

#if defined(PLATFORM__MACOS)
// On Apple Vulkan API <= 1.2.283 variable descriptor counts don't work, use max expected count instead. Fixed in later versions.
if (get_device().get_gpu().get_properties().apiVersion <= VK_MAKE_API_VERSION(0, 1, 2, 283))
{
descriptorCount = std::max(NumDescriptorsStreaming, NumDescriptorsNonUniform);
}
#endif

VkDescriptorSetLayoutBinding binding = vkb::initializers::descriptor_set_layout_binding(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT, 0, descriptorCount);
VkDescriptorSetLayoutCreateInfo set_layout_create_info = vkb::initializers::descriptor_set_layout_create_info(&binding, 1);

Expand Down Expand Up @@ -262,14 +237,6 @@ void DescriptorIndexing::create_bindless_descriptors()
// For the non-uniform indexing part, we allocate few descriptors, and for the streaming case, we allocate a fairly large ring buffer of descriptors we can play around with.
uint32_t poolCount = NumDescriptorsStreaming + NumDescriptorsNonUniform;

#if defined(PLATFORM__MACOS)
// On Apple Vulkan API <= 1.2.283 variable descriptor counts don't work, use pool size of max expected count x 2 (for 2 allocations). Fixed in later versions.
if (get_device().get_gpu().get_properties().apiVersion <= VK_MAKE_API_VERSION(0, 1, 2, 283))
{
poolCount = std::max(NumDescriptorsStreaming, NumDescriptorsNonUniform) * 2;
}
#endif

VkDescriptorPoolSize pool_size = vkb::initializers::descriptor_pool_size(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, poolCount);
VkDescriptorPoolCreateInfo pool = vkb::initializers::descriptor_pool_create_info(1, &pool_size, 2);

Expand Down
85 changes: 47 additions & 38 deletions samples/extensions/portability/portability.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,12 @@ Portability::Portability() :
filter_pass()
{
title = "Portability";
// Portability is a Vulkan 1.3 extension
set_api_version(VK_API_VERSION_1_3);
add_instance_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
add_instance_extension(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME, /*optional*/ true);
// These instance extensions are conditionally added by the sample framework when VKB_ENABLE_PORTABILITY is enabled
// add_instance_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
// add_instance_extension(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME, /*optional=*/true);

// VK_KHR_portability_subset depends on VK_KHR_get_physical_device_properties2 or Vulkan 1.1 (default for project)
// This device extension is conditionally added by the sample framework when VKB_ENABLE_PORTABILITY is enabled
}

Portability::~Portability()
Expand Down Expand Up @@ -868,41 +870,48 @@ void Portability::render(float delta_time)
void Portability::on_update_ui_overlay(vkb::Drawer &drawer)
{
#ifdef VKB_ENABLE_PORTABILITY
std::string portability_support_list;
if (portability_features.constantAlphaColorBlendFactors)
portability_support_list += "constantAlphaColorBlendFactors\n";
if (portability_features.events)
portability_support_list += "events\n";
if (portability_features.imageView2DOn3DImage)
portability_support_list += "imageView2DOn3dImage\n";
if (portability_features.imageViewFormatReinterpretation)
portability_support_list += "imageViewFormatReinterpretation\n";
if (portability_features.imageViewFormatSwizzle)
portability_support_list += "imageViewFormatSwizzle\n";
if (portability_features.multisampleArrayImage)
portability_support_list += "multisampleArrayImage\n";
if (portability_features.mutableComparisonSamplers)
portability_support_list += "mutableComparisonSamplers\n";
if (portability_features.pointPolygons)
portability_support_list += "pointPolygons\n";
if (portability_features.samplerMipLodBias)
portability_support_list += "samplerMipLodBias\n";
if (portability_features.separateStencilMaskRef)
portability_support_list += "separateStencilMaskRef\n";
if (portability_features.shaderSampleRateInterpolationFunctions)
portability_support_list += "shaderSampleRateInterpolationFunctions\n";
if (portability_features.tessellationIsolines)
portability_support_list += "tessellationIsolines\n";
if (portability_features.tessellationPointMode)
portability_support_list += "tessellationPointMode\n";
if (portability_features.triangleFans)
portability_support_list += "triangleFans\n";
if (portability_features.vertexAttributeAccessBeyondStride)
portability_support_list += "vertexAttributeAccessBeyondStride\n";
drawer.text("Device Portability feature support list:\n%s", portability_support_list.c_str());
#else
drawer.text("VKB_ENABLE_PORTABILITY not enabled can't list portability feature set");
// VK_KHR_portability_subset extension must be available in the implementation to list device portability feature set
if (get_device().get_gpu().is_extension_supported(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME))
{
std::string portability_support_list;
if (portability_features.constantAlphaColorBlendFactors)
portability_support_list += "constantAlphaColorBlendFactors\n";
if (portability_features.events)
portability_support_list += "events\n";
if (portability_features.imageView2DOn3DImage)
portability_support_list += "imageView2DOn3dImage\n";
if (portability_features.imageViewFormatReinterpretation)
portability_support_list += "imageViewFormatReinterpretation\n";
if (portability_features.imageViewFormatSwizzle)
portability_support_list += "imageViewFormatSwizzle\n";
if (portability_features.multisampleArrayImage)
portability_support_list += "multisampleArrayImage\n";
if (portability_features.mutableComparisonSamplers)
portability_support_list += "mutableComparisonSamplers\n";
if (portability_features.pointPolygons)
portability_support_list += "pointPolygons\n";
if (portability_features.samplerMipLodBias)
portability_support_list += "samplerMipLodBias\n";
if (portability_features.separateStencilMaskRef)
portability_support_list += "separateStencilMaskRef\n";
if (portability_features.shaderSampleRateInterpolationFunctions)
portability_support_list += "shaderSampleRateInterpolationFunctions\n";
if (portability_features.tessellationIsolines)
portability_support_list += "tessellationIsolines\n";
if (portability_features.tessellationPointMode)
portability_support_list += "tessellationPointMode\n";
if (portability_features.triangleFans)
portability_support_list += "triangleFans\n";
if (portability_features.vertexAttributeAccessBeyondStride)
portability_support_list += "vertexAttributeAccessBeyondStride\n";
drawer.text("Device Portability feature support list:\n%s", portability_support_list.c_str());
}
else
#endif
{
drawer.text("VK_KHR_portability_subset not available can't list portability feature set");
}

if (drawer.header("Settings"))
{
if (drawer.checkbox("Bloom", &bloom))
Expand Down
Loading
Loading