diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 1de3d7b7e..22c817f0c 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -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 # @@ -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 @@ -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 /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 diff --git a/bldsys/cmake/global_options.cmake b/bldsys/cmake/global_options.cmake index a25d77110..a47ffbada 100644 --- a/bldsys/cmake/global_options.cmake +++ b/bldsys/cmake/global_options.cmake @@ -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}) @@ -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) @@ -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") @@ -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") diff --git a/framework/core/instance.h b/framework/core/instance.h index 4f4781f57..5d8c89428 100644 --- a/framework/core/instance.h +++ b/framework/core/instance.h @@ -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 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) diff --git a/framework/vulkan_sample.h b/framework/vulkan_sample.h index 6dda756c7..6c1c4d94b 100644 --- a/framework/vulkan_sample.h +++ b/framework/vulkan_sample.h @@ -1115,7 +1115,7 @@ inline bool VulkanSample::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 diff --git a/samples/api/hello_triangle/hello_triangle.cpp b/samples/api/hello_triangle/hello_triangle.cpp index 75e1d1839..e10954a1c 100644 --- a/samples/api/hello_triangle/hello_triangle.cpp +++ b/samples/api/hello_triangle/hello_triangle.cpp @@ -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; })) { @@ -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) { diff --git a/samples/api/hello_triangle_1_3/hello_triangle_1_3.cpp b/samples/api/hello_triangle_1_3/hello_triangle_1_3.cpp index 84d37f3d3..f0d23fe11 100644 --- a/samples/api/hello_triangle_1_3/hello_triangle_1_3.cpp +++ b/samples/api/hello_triangle_1_3/hello_triangle_1_3.cpp @@ -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; })) { diff --git a/samples/api/hpp_hello_triangle/hpp_hello_triangle.cpp b/samples/api/hpp_hello_triangle/hpp_hello_triangle.cpp index b1727a372..a8ccf3a63 100644 --- a/samples/api/hpp_hello_triangle/hpp_hello_triangle.cpp +++ b/samples/api/hpp_hello_triangle/hpp_hello_triangle.cpp @@ -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(); @@ -142,7 +145,10 @@ HPPHelloTriangle::~HPPHelloTriangle() instance.destroyDebugUtilsMessengerEXT(debug_utils_messenger); } - instance.destroy(); + if (instance) + { + instance.destroy(); + } } bool HPPHelloTriangle::prepare(const vkb::ApplicationOptions &options) @@ -325,7 +331,7 @@ vk::Device HPPHelloTriangle::create_device(const std::vector &requ std::vector 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; })) { @@ -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) { diff --git a/samples/api/hpp_hello_triangle_1_3/hpp_hello_triangle_1_3.cpp b/samples/api/hpp_hello_triangle_1_3/hpp_hello_triangle_1_3.cpp index e54a304ce..ce5c5a2c9 100644 --- a/samples/api/hpp_hello_triangle_1_3/hpp_hello_triangle_1_3.cpp +++ b/samples/api/hpp_hello_triangle_1_3/hpp_hello_triangle_1_3.cpp @@ -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; })) { diff --git a/samples/extensions/descriptor_indexing/descriptor_indexing.cpp b/samples/extensions/descriptor_indexing/descriptor_indexing.cpp index 7f853d0e7..178021faf 100644 --- a/samples/extensions/descriptor_indexing/descriptor_indexing.cpp +++ b/samples/extensions/descriptor_indexing/descriptor_indexing.cpp @@ -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() @@ -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); @@ -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); diff --git a/samples/extensions/portability/portability.cpp b/samples/extensions/portability/portability.cpp index a600960e7..9078a3fb0 100644 --- a/samples/extensions/portability/portability.cpp +++ b/samples/extensions/portability/portability.cpp @@ -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() @@ -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)) diff --git a/samples/extensions/shader_debugprintf/shader_debugprintf.cpp b/samples/extensions/shader_debugprintf/shader_debugprintf.cpp index 29f2ef96e..f851dcf81 100644 --- a/samples/extensions/shader_debugprintf/shader_debugprintf.cpp +++ b/samples/extensions/shader_debugprintf/shader_debugprintf.cpp @@ -497,7 +497,7 @@ std::unique_ptr ShaderDebugPrintf::create_instance() std::vector available_instance_extensions(available_extension_count); VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &available_extension_count, available_instance_extensions.data())); - // If VK_KHR_portability_enumeration is available in the portability implementation, then we must enable the extension + // If VK_KHR_portability_enumeration is available in the implementation, then we must enable the extension bool portability_enumeration_available = false; if (std::ranges::any_of(available_instance_extensions, [](VkExtensionProperties const &extension) { return strcmp(extension.extensionName, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME) == 0; })) diff --git a/samples/performance/async_compute/async_compute.cpp b/samples/performance/async_compute/async_compute.cpp index c87597a86..c39d2315f 100644 --- a/samples/performance/async_compute/async_compute.cpp +++ b/samples/performance/async_compute/async_compute.cpp @@ -42,7 +42,7 @@ void AsyncComputeSample::request_gpu_features(vkb::core::PhysicalDeviceC &gpu) { #ifdef VKB_ENABLE_PORTABILITY // Since sampler_info.compareEnable = VK_TRUE, must enable the mutableComparisonSamplers feature of VK_KHR_portability_subset - REQUEST_REQUIRED_FEATURE(gpu, VkPhysicalDevicePortabilitySubsetFeaturesKHR, mutableComparisonSamplers); + REQUEST_OPTIONAL_FEATURE(gpu, VkPhysicalDevicePortabilitySubsetFeaturesKHR, mutableComparisonSamplers); #endif } diff --git a/samples/performance/layout_transitions/layout_transitions.cpp b/samples/performance/layout_transitions/layout_transitions.cpp index 7667f4809..e050cbf35 100644 --- a/samples/performance/layout_transitions/layout_transitions.cpp +++ b/samples/performance/layout_transitions/layout_transitions.cpp @@ -39,7 +39,7 @@ LayoutTransitions::LayoutTransitions() #if defined(PLATFORM__MACOS) && TARGET_OS_IOS && TARGET_OS_SIMULATOR // On iOS Simulator use layer setting to disable MoltenVK's Metal argument buffers - otherwise blank display - add_instance_extension(VK_EXT_LAYER_SETTINGS_EXTENSION_NAME, /*optional*/ true); + add_instance_extension(VK_EXT_LAYER_SETTINGS_EXTENSION_NAME, /*optional=*/true); VkLayerSettingEXT layerSetting; layerSetting.pLayerName = "MoltenVK"; @@ -48,8 +48,8 @@ LayoutTransitions::LayoutTransitions() layerSetting.valueCount = 1; // Make this static so layer setting reference remains valid after leaving constructor scope - static const int32_t useMetalArgumentBuffers = 0; - layerSetting.pValues = &useMetalArgumentBuffers; + static const int32_t disableMetalArgumentBuffers = 0; + layerSetting.pValues = &disableMetalArgumentBuffers; add_layer_setting(layerSetting); #endif diff --git a/samples/performance/multithreading_render_passes/multithreading_render_passes.cpp b/samples/performance/multithreading_render_passes/multithreading_render_passes.cpp index ce7704b6f..e8d85f9bf 100644 --- a/samples/performance/multithreading_render_passes/multithreading_render_passes.cpp +++ b/samples/performance/multithreading_render_passes/multithreading_render_passes.cpp @@ -43,7 +43,7 @@ void MultithreadingRenderPasses::request_gpu_features(vkb::core::PhysicalDeviceC { #ifdef VKB_ENABLE_PORTABILITY // Since shadowmap_sampler_create_info.compareEnable = VK_TRUE, must enable the mutableComparisonSamplers feature of VK_KHR_portability_subset - REQUEST_REQUIRED_FEATURE(gpu, VkPhysicalDevicePortabilitySubsetFeaturesKHR, mutableComparisonSamplers); + REQUEST_OPTIONAL_FEATURE(gpu, VkPhysicalDevicePortabilitySubsetFeaturesKHR, mutableComparisonSamplers); #endif } diff --git a/samples/performance/pipeline_barriers/pipeline_barriers.cpp b/samples/performance/pipeline_barriers/pipeline_barriers.cpp index 1f8272427..717cd36ce 100644 --- a/samples/performance/pipeline_barriers/pipeline_barriers.cpp +++ b/samples/performance/pipeline_barriers/pipeline_barriers.cpp @@ -41,7 +41,7 @@ PipelineBarriers::PipelineBarriers() #if defined(PLATFORM__MACOS) && TARGET_OS_IOS && TARGET_OS_SIMULATOR // On iOS Simulator use layer setting to disable MoltenVK's Metal argument buffers - otherwise blank display - add_instance_extension(VK_EXT_LAYER_SETTINGS_EXTENSION_NAME, /*optional*/ true); + add_instance_extension(VK_EXT_LAYER_SETTINGS_EXTENSION_NAME, /*optional=*/true); VkLayerSettingEXT layerSetting; layerSetting.pLayerName = "MoltenVK"; @@ -50,8 +50,8 @@ PipelineBarriers::PipelineBarriers() layerSetting.valueCount = 1; // Make this static so layer setting reference remains valid after leaving constructor scope - static const int32_t useMetalArgumentBuffers = 0; - layerSetting.pValues = &useMetalArgumentBuffers; + static const int32_t disableMetalArgumentBuffers = 0; + layerSetting.pValues = &disableMetalArgumentBuffers; add_layer_setting(layerSetting); #endif diff --git a/samples/performance/subpasses/subpasses.cpp b/samples/performance/subpasses/subpasses.cpp index 42a66f78c..2872f0069 100644 --- a/samples/performance/subpasses/subpasses.cpp +++ b/samples/performance/subpasses/subpasses.cpp @@ -53,7 +53,7 @@ Subpasses::Subpasses() #if defined(PLATFORM__MACOS) && TARGET_OS_IOS && TARGET_OS_SIMULATOR // On iOS Simulator use layer setting to disable MoltenVK's Metal argument buffers - otherwise blank display - add_instance_extension(VK_EXT_LAYER_SETTINGS_EXTENSION_NAME, /*optional*/ true); + add_instance_extension(VK_EXT_LAYER_SETTINGS_EXTENSION_NAME, /*optional=*/true); VkLayerSettingEXT layerSetting; layerSetting.pLayerName = "MoltenVK"; @@ -62,8 +62,8 @@ Subpasses::Subpasses() layerSetting.valueCount = 1; // Make this static so layer setting reference remains valid after leaving constructor scope - static const int32_t useMetalArgumentBuffers = 0; - layerSetting.pValues = &useMetalArgumentBuffers; + static const int32_t disableMetalArgumentBuffers = 0; + layerSetting.pValues = &disableMetalArgumentBuffers; add_layer_setting(layerSetting); #endif diff --git a/samples/tooling/profiles/profiles.cpp b/samples/tooling/profiles/profiles.cpp index 040df2096..35e4601f7 100644 --- a/samples/tooling/profiles/profiles.cpp +++ b/samples/tooling/profiles/profiles.cpp @@ -47,13 +47,18 @@ Profiles::~Profiles() // Clean up used Vulkan resources // Note : Inherited destructor cleans up resources stored in base class for (auto &tex : textures) + { + vkDestroyImageView(get_device().get_handle(), tex.image_view, nullptr); + vkDestroyImage(get_device().get_handle(), tex.image, nullptr); vkFreeMemory(get_device().get_handle(), tex.memory, nullptr); + } vkDestroyPipeline(get_device().get_handle(), pipeline, nullptr); vkDestroyPipelineLayout(get_device().get_handle(), pipeline_layout, nullptr); vkDestroyDescriptorSetLayout(get_device().get_handle(), base_descriptor_set_layout, nullptr); vkDestroyDescriptorSetLayout(get_device().get_handle(), sampler_descriptor_set_layout, nullptr); + vkDestroySampler(get_device().get_handle(), sampler, nullptr); } } @@ -92,6 +97,14 @@ std::unique_ptr Profiles::create_device(vkb::core::PhysicalD std::vector enabled_extensions; enabled_extensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); +#if (defined(VKB_ENABLE_PORTABILITY)) + // VK_KHR_portability_subset must be enabled if present in the implementation (e.g on macOS/iOS using MoltenVK with beta extensions enabled) + if (gpu.is_extension_supported(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME); + } +#endif + VkDeviceCreateInfo create_info{VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO}; create_info.pNext = gpu.get_extension_feature_chain(); create_info.pQueueCreateInfos = &queue_create_info; @@ -153,12 +166,15 @@ std::unique_ptr Profiles::create_instance() VkInstanceCreateInfo create_info{}; #if (defined(VKB_ENABLE_PORTABILITY)) + enabled_extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); + + // Enumerate all instance extensions for the loader + driver to determine if VK_KHR_portability_enumeration is available uint32_t instance_extension_count; VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &instance_extension_count, nullptr)); std::vector available_instance_extensions(instance_extension_count); VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &instance_extension_count, available_instance_extensions.data())); - // If VK_KHR_portability_enumeration is available at runtime, enable the extension and flag for instance creation + // If VK_KHR_portability_enumeration is available in the implementation, then we must enable the extension if (std::ranges::any_of(available_instance_extensions, [](VkExtensionProperties const &extension) { return strcmp(extension.extensionName, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME) == 0; })) { @@ -167,27 +183,6 @@ std::unique_ptr Profiles::create_instance() } #endif -#if defined(PLATFORM__MACOS) - // On Apple use layer setting to enable MoltenVK's Metal argument buffers - needed for descriptor indexing/scaling - enabled_extensions.push_back(VK_EXT_LAYER_SETTINGS_EXTENSION_NAME); - - VkLayerSettingEXT layerSetting{}; - layerSetting.pLayerName = "MoltenVK"; - layerSetting.pSettingName = "MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS"; - layerSetting.type = VK_LAYER_SETTING_TYPE_INT32_EXT; - layerSetting.valueCount = 1; - - const int32_t useMetalArgumentBuffers = 1; - layerSetting.pValues = &useMetalArgumentBuffers; - - VkLayerSettingsCreateInfoEXT layerSettingsCreateInfo{}; - layerSettingsCreateInfo.sType = VK_STRUCTURE_TYPE_LAYER_SETTINGS_CREATE_INFO_EXT; - layerSettingsCreateInfo.settingCount = 1; - layerSettingsCreateInfo.pSettings = &layerSetting; - - create_info.pNext = &layerSettingsCreateInfo; -#endif - create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; create_info.ppEnabledExtensionNames = enabled_extensions.data(); create_info.enabledExtensionCount = static_cast(enabled_extensions.size()); @@ -464,6 +459,7 @@ void Profiles::setup_descriptor_pool() static_cast(pool_sizes.size()), pool_sizes.data(), 3); + descriptor_pool_create_info.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT; VK_CHECK(vkCreateDescriptorPool(get_device().get_handle(), &descriptor_pool_create_info, nullptr, &descriptor_pool)); } @@ -501,6 +497,7 @@ void Profiles::setup_descriptor_set_layout() static_cast(textures.size()))}; descriptor_layout_create_info.bindingCount = static_cast(set_layout_bindings.size()); descriptor_layout_create_info.pBindings = set_layout_bindings.data(); + descriptor_layout_create_info.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT; VK_CHECK(vkCreateDescriptorSetLayout(get_device().get_handle(), &descriptor_layout_create_info, nullptr, &base_descriptor_set_layout)); // Set layout for the samplers @@ -513,6 +510,7 @@ void Profiles::setup_descriptor_set_layout() static_cast(textures.size()))}; descriptor_layout_create_info.bindingCount = static_cast(set_layout_bindings.size()); descriptor_layout_create_info.pBindings = set_layout_bindings.data(); + descriptor_layout_create_info.pNext = nullptr; VK_CHECK(vkCreateDescriptorSetLayout(get_device().get_handle(), &descriptor_layout_create_info, nullptr, &sampler_descriptor_set_layout)); // Pipeline layout diff --git a/samples/tooling/profiles/vulkan_profiles.hpp b/samples/tooling/profiles/vulkan_profiles.hpp index aab81bcfe..499c121a6 100644 --- a/samples/tooling/profiles/vulkan_profiles.hpp +++ b/samples/tooling/profiles/vulkan_profiles.hpp @@ -33648,25 +33648,6 @@ VPAPI_ATTR VkResult vpCreateInstance( } } -#ifdef __APPLE__ - bool has_portability_ext = false; - for (std::size_t ext_index = 0, ext_count = extensions.size(); ext_index < ext_count; ++ext_index) - { - if (strcmp(extensions[ext_index], VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME) == 0) - { - has_portability_ext = true; - break; - } - } - - if (!has_portability_ext) - { - extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); - } - - createInfo.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; -#endif - if (!extensions.empty()) { createInfo.enabledExtensionCount = static_cast(extensions.size());