diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5a78261d1d..f4896a704a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -187,12 +187,12 @@ jobs: - name: retrieve VulkanSDK if: steps.VulkanSDK.outputs.cache-hit != 'true' run: | - wget https://sdk.lunarg.com/sdk/download/1.4.304.1/mac/vulkansdk-macos-1.4.304.1.zip - unzip vulkansdk-macos-1.4.304.1.zip - sudo InstallVulkan-1.4.304.1.app/Contents/MacOS/InstallVulkan-1.4.304.1 --root ~/VulkanSDK --accept-licenses --default-answer --confirm-command install com.lunarg.vulkan.ios + wget https://sdk.lunarg.com/sdk/download/1.4.341.1/mac/vulkansdk-macos-1.4.341.1.zip + unzip vulkansdk-macos-1.4.341.1.zip + sudo vulkansdk-macOS-1.4.341.1.app/Contents/MacOS/vulkansdk-macOS-1.4.341.1 --root ~/VulkanSDK --accept-licenses --default-answer --confirm-command install com.lunarg.vulkan.ios - name: build_ios run: | source ~/VulkanSDK/iOS/setup-env.sh - cmake -H"." -B"build/ios" -DVKB_BUILD_TESTS=ON -DVKB_BUILD_SAMPLES=ON -G Xcode -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphoneos -DCMAKE_OSX_DEPLOYMENT_TARGET=16.3 -DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED=NO + cmake -G Xcode -B"build/ios" --toolchain bldsys/toolchain/ios.cmake -DVKB_BUILD_TESTS=ON -DVKB_BUILD_SAMPLES=ON -DCMAKE_OSX_SYSROOT=iphoneos -DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED=NO cmake --build "build/ios" --target vulkan_samples --config ${{ matrix.build_type }} -- -allowProvisioningUpdates diff --git a/CMakeLists.txt b/CMakeLists.txt index f40039a3ac..a218843276 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ -# Copyright (c) 2020-2025, Arm Limited and Contributors -# Copyright (c) 2024-2025, Mobica Limited -# Copyright (c) 2024-2025, Sascha Willems +# Copyright (c) 2020-2026, Arm Limited and Contributors +# Copyright (c) 2024-2026, Mobica Limited +# Copyright (c) 2024-2026, Sascha Willems # # SPDX-License-Identifier: Apache-2.0 # @@ -43,7 +43,9 @@ else () # search for Vulkan SDK find_package(Vulkan) -if(Vulkan_FOUND) +# Apple platforms always define Vulkan_SDK, so don't look for shader compilers otherwise we will build +# the shaders for every new config - instead use pre-built shaders which improves project build times. +if(Vulkan_FOUND AND NOT APPLE) if(NOT Vulkan_dxc_exe_FOUND) find_program(Vulkan_dxc_EXECUTABLE NAMES dxc diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 22c817f0ce..79eda8ce79 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2019-2025, Arm Limited and Contributors +# Copyright (c) 2019-2026, Arm Limited and Contributors # # SPDX-License-Identifier: Apache-2.0 # @@ -137,6 +137,7 @@ if(IOS) endif () # 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) + get_filename_component(Vulkan_Target_SDK "$ENV{VULKAN_SDK}/.." REALPATH) target_sources(${PROJECT_NAME} PRIVATE ${Vulkan_Target_SDK}/iOS/share/vulkan ) diff --git a/bldsys/cmake/global_options.cmake b/bldsys/cmake/global_options.cmake index 3c911aa2e6..4106aa6bba 100644 --- a/bldsys/cmake/global_options.cmake +++ b/bldsys/cmake/global_options.cmake @@ -1,5 +1,5 @@ #[[ - Copyright (c) 2019-2025, Arm Limited and Contributors + Copyright (c) 2019-2026, Arm Limited and Contributors SPDX-License-Identifier: Apache-2.0 @@ -78,10 +78,10 @@ if(APPLE) else() message(FATAL_ERROR "Can't find MoltenVK library. Please install the Vulkan SDK or MoltenVK project and set VULKAN_SDK.") endif() - #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() + elseif(IOS AND NOT Vulkan_Layer_VALIDATION) + # if building for iOS devices (not iOS Simulator as above) and Vulkan_Layer_VALIDATION is not defined or found, search in the Vulkan SDK + find_library(Vulkan_Layer_VALIDATION NAMES VkLayer_khronos_validation HINTS "$ENV{VULKAN_SDK}/lib") + 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() diff --git a/bldsys/toolchain/ios.cmake b/bldsys/toolchain/ios.cmake new file mode 100644 index 0000000000..1d2296b752 --- /dev/null +++ b/bldsys/toolchain/ios.cmake @@ -0,0 +1,44 @@ +#[[ + + Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + Copyright (c) 2026, Stephen Saunders + + SPDX-License-Identifier: Apache-2.0 + + Licensed under the Apache License, Version 2.0 the "License"; + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + ------------------------------------------------------------------------ + + Co-Authored-By: (Qualcomm) Giancane, Francesco + Co-Authored-By: Stephen Saunders + + ]] + +# As per upstream CMake recommendation in https://gitlab.kitware.com/cmake/cmake/-/issues/27661 +# for iOS we can use a toolchain file to set up search paths and simplify the command line +# +# iOS/setup-env.sh will first take care of defining the VULKAN_SDK environment variable +# Toolchain file shall define: +# - Target system name to iOS +# - Minimum deployment target to iOS 16.3 +# - Build only the active arch for devices and simulator +# - Export the $ENV{VULKAN_SDK} variable to `CMAKE_FIND_ROOT_PATH` +# +# Note: We define CMAKE_FIND_ROOT_PATH to locate the iOS Vulkan frameworks from the SDK. +# We don't define CMAKE_OSX_SYSROOT here since we need to build for both physical devices +# (iphoneos) and simulator (iphonesimulator) - do that instead on the cmake command line. + +set(CMAKE_SYSTEM_NAME iOS) +set(CMAKE_OSX_DEPLOYMENT_TARGET 16.3) +set(CMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH YES) +set(CMAKE_FIND_ROOT_PATH "$ENV{VULKAN_SDK}") diff --git a/docs/build.adoc b/docs/build.adoc index 7b98330d19..fd23b2ecc7 100644 --- a/docs/build.adoc +++ b/docs/build.adoc @@ -1,5 +1,5 @@ //// -- Copyright (c) 2019-2025, Arm Limited and Contributors +- Copyright (c) 2019-2026, Arm Limited and Contributors - - SPDX-License-Identifier: Apache-2.0 - @@ -327,14 +327,14 @@ source /PATH/TO/VULKAN/SDK/iOS/setup-env.sh `Step 1.` The following command will generate the project ---- -cmake -G Xcode -Bbuild/ios -DCMAKE_BUILD_TYPE=Release -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphoneos -DCMAKE_OSX_DEPLOYMENT_TARGET=16.3 -DCMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH=YES -DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_IOS_INSTALL_COMBINED=NO -DCMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM="XXXX" -DMACOSX_BUNDLE_GUI_IDENTIFIER="com.YYYY.vulkansamples" +cmake -G Xcode -Bbuild/ios --toolchain bldsys/toolchain/ios.cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_SYSROOT=iphoneos -DCMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM="XXXX" -DMACOSX_BUNDLE_GUI_IDENTIFIER="com.YYYY.vulkansamples" ---- NB: You MUST change the XXXX in the above to your TeamID (or Organizational Unit identifier in your Apple Development certificate) for code signing, and YYYY to your bundle identifier. iOS will NOT allow the application to run without code signing and bundle identifier setup. -Alternatively, you can build for the iOS Simulator (requires Vulkan SDK 1.4.321.0 or later) without code signing or specifying a bundle identifier (a default bundle id will be used). However, depending on your host architecture, you MUST select either arm64 (Apple Silicon) or x86_64 in the command below. _Note: On arm64 (Apple Silicon) hosts the Vulkan library may not load on iOS Simulator without specifying your TeamID and bundle identifier as shown above._ +Alternatively, you can build for the iOS Simulator (requires Vulkan SDK 1.4.321.0 or later) without code signing or specifying a bundle identifier (a default bundle id will be used). However, depending on your host architecture, you MUST select either arm64 (Apple Silicon) OR x86_64 in the command below. _Note: On arm64 hosts (Apple Silicon) the Vulkan library may not load on iOS Simulator without specifying your TeamID and bundle identifier as shown above._ ---- -cmake -G Xcode -Bbuild/ios-sim -DCMAKE_BUILD_TYPE=Release -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_OSX_DEPLOYMENT_TARGET=16.3 -DCMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH=YES -DCMAKE_OSX_ARCHITECTURES= -DCMAKE_IOS_INSTALL_COMBINED=NO +cmake -G Xcode -Bbuild/ios-sim --toolchain bldsys/toolchain/ios.cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_OSX_ARCHITECTURES= ---- `Step 2.` Build the project diff --git a/framework/vulkan_sample.h b/framework/vulkan_sample.h index e40afafdb7..89a652b50c 100644 --- a/framework/vulkan_sample.h +++ b/framework/vulkan_sample.h @@ -1362,7 +1362,8 @@ template inline void VulkanSample::request_layers(std::unordered_map &requested_layers) const { #if defined(VKB_DEBUG) || defined(VKB_VALIDATION_LAYERS) - requested_layers["VK_LAYER_KHRONOS_validation"] = vkb::RequestMode::Required; + // VK_LAYER_KHRONOS_validation must be optional in case layer not available for debug builds (e.g. running on Windows with no SDK installed or on iOS Simulator) + requested_layers["VK_LAYER_KHRONOS_validation"] = vkb::RequestMode::Optional; #endif } diff --git a/samples/api/texture_loading/texture_loading.cpp b/samples/api/texture_loading/texture_loading.cpp index 61b939ff08..ce49fb6a8f 100644 --- a/samples/api/texture_loading/texture_loading.cpp +++ b/samples/api/texture_loading/texture_loading.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2019-2025, Sascha Willems +/* Copyright (c) 2019-2026, Sascha Willems * * SPDX-License-Identifier: Apache-2.0 * @@ -408,10 +408,13 @@ void TextureLoading::load_texture() // Free all Vulkan resources used by a texture object void TextureLoading::destroy_texture(Texture texture) { - vkDestroyImageView(get_device().get_handle(), texture.view, nullptr); - vkDestroyImage(get_device().get_handle(), texture.image, nullptr); - vkDestroySampler(get_device().get_handle(), texture.sampler, nullptr); - vkFreeMemory(get_device().get_handle(), texture.device_memory, nullptr); + if (has_device()) + { + vkDestroyImageView(get_device().get_handle(), texture.view, nullptr); + vkDestroyImage(get_device().get_handle(), texture.image, nullptr); + vkDestroySampler(get_device().get_handle(), texture.sampler, nullptr); + vkFreeMemory(get_device().get_handle(), texture.device_memory, nullptr); + } } void TextureLoading::build_command_buffers() diff --git a/samples/api/texture_mipmap_generation/texture_mipmap_generation.cpp b/samples/api/texture_mipmap_generation/texture_mipmap_generation.cpp index 139aeb5684..bf4f28d0eb 100644 --- a/samples/api/texture_mipmap_generation/texture_mipmap_generation.cpp +++ b/samples/api/texture_mipmap_generation/texture_mipmap_generation.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2019-2025, Sascha Willems +/* Copyright (c) 2019-2026, Sascha Willems * * SPDX-License-Identifier: Apache-2.0 * @@ -285,9 +285,12 @@ void TextureMipMapGeneration::load_texture_generate_mipmaps(std::string file_nam // Free all Vulkan resources used by a texture object void TextureMipMapGeneration::destroy_texture(Texture texture) { - vkDestroyImageView(get_device().get_handle(), texture.view, nullptr); - vkDestroyImage(get_device().get_handle(), texture.image, nullptr); - vkFreeMemory(get_device().get_handle(), texture.device_memory, nullptr); + if (has_device()) + { + vkDestroyImageView(get_device().get_handle(), texture.view, nullptr); + vkDestroyImage(get_device().get_handle(), texture.image, nullptr); + vkFreeMemory(get_device().get_handle(), texture.device_memory, nullptr); + } } void TextureMipMapGeneration::load_assets() diff --git a/samples/performance/hpp_pipeline_cache/hpp_pipeline_cache.cpp b/samples/performance/hpp_pipeline_cache/hpp_pipeline_cache.cpp index ea88c65e90..e042942133 100644 --- a/samples/performance/hpp_pipeline_cache/hpp_pipeline_cache.cpp +++ b/samples/performance/hpp_pipeline_cache/hpp_pipeline_cache.cpp @@ -40,7 +40,10 @@ HPPPipelineCache::~HPPPipelineCache() get_device().get_handle().destroyPipelineCache(pipeline_cache); } - vkb::fs::write_temp(get_device().get_resource_cache().serialize(), "hpp_cache.data"); + if (has_device()) + { + vkb::fs::write_temp(get_device().get_resource_cache().serialize(), "hpp_cache.data"); + } } bool HPPPipelineCache::prepare(const vkb::ApplicationOptions &options) diff --git a/samples/performance/pipeline_cache/pipeline_cache.cpp b/samples/performance/pipeline_cache/pipeline_cache.cpp index c299f7b540..56e373ecbe 100644 --- a/samples/performance/pipeline_cache/pipeline_cache.cpp +++ b/samples/performance/pipeline_cache/pipeline_cache.cpp @@ -70,7 +70,10 @@ PipelineCache::~PipelineCache() vkDestroyPipelineCache(get_device().get_handle(), pipeline_cache, nullptr); } - vkb::fs::write_temp(get_device().get_resource_cache().serialize(), "cache.data"); + if (has_device()) + { + vkb::fs::write_temp(get_device().get_resource_cache().serialize(), "cache.data"); + } } bool PipelineCache::prepare(const vkb::ApplicationOptions &options)