diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 516f1baa4..f0b543910 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -56,8 +56,9 @@ jobs:
--root ~/VulkanSDK/latest --accept-licenses --default-answer --confirm-command install
cd ~/VulkanSDK/latest
sudo python ./install_vulkan.py
+ brew install libomp
brew --prefix libomp
- name: Build
run: |
- cmake -G "Xcode" -DOpenMP_C_FLAGS=/usr/local/opt/libomp -DOpenMP_omp_LIBRARY=/usr/local/opt/libomp -DOpenMP_CXX_FOUND=/usr/local/opt/libomp
+ cmake -G "Xcode" -DOpenMP_omp_LIBRARY=/usr/local/opt/libomp/lib/libomp.dylib
cmake --build .
diff --git a/BUILD.md b/BUILD.md
index 0c3efec8a..c8fd756f1 100644
--- a/BUILD.md
+++ b/BUILD.md
@@ -50,28 +50,25 @@ If you want to build and install on a connected device or emulator image, run ``
If you want to build it through [Android Studio](https://developer.android.com/studio), open project folder ```android``` in Android Studio.
-### [iOS and macOS](xcode/)
+### macOS and iOS
-**Note:** Running these examples on Mac OS and iOS requires [**MoltenVK**](https://github.com/KhronosGroup/MoltenVK) and a device that supports the *Metal* api.
+**Note:** Running these examples on macOS and iOS requires [**MoltenVK**](https://github.com/KhronosGroup/MoltenVK) and a device that supports the *Metal* api.
-#### MacOS
-Install Libomp with:
--brew install libomp
-find the path
--brew --prefix libomp
-use the path from the above command to populate the path in the -DOpenMP_C_FLAGS, -DOpenMP_omp_LIBRARY & -DOpenMP_CXX_FOUND statement below
+#### macOS
+Download the most recent Vulkan SDK using:
+```curl -O https://sdk.lunarg.com/sdk/download/latest/mac/vulkan_sdk.dmg```
-Download Vulkan SDK and install it note the path as this will need to be configure in Xcode
-curl -O https://sdk.lunarg.com/sdk/download/latest/mac/vulkan_sdk.dmg
+Open **vulkan_sdk.dmg** and install the Vulkan SDK with *System Global Installation* selected.
-Open vulkan_sdk.dmg and install Vulkan SDK
-Navigate to the Vulkan SDK folder and run 'python install_vulkan.py'
+Install **libomp** from [homebrew](https://brew.sh) using:
+```brew install libomp```
-Use the provided CMakeLists.txt with [CMake](https://cmake.org) to generate a build configuration for your favorite IDE or compiler, e.g.:
-```
-Example of cmake with libraries defined
-cmake -G "Xcode" -DOpenMP_C_FLAGS=/usr/local/opt/libomp -DOpenMP_omp_LIBRARY=/usr/local/opt/libomp -DOpenMP_CXX_FOUND=/usr/local/opt/libomp
-```
+Find the **libomp** path prefix using:
+```brew --prefix libomp```
+Use the **libomp** path prefix to adjust the path for ```-DOpenMP_omp_LIBRARY=``` in the cmake command below.
+Use [CMake](https://cmake.org) to generate a build configuration for Xcode or your preferred build method (e.g. Unix Makefiles or Ninja).
+Example of cmake generating for Xcode with **libomp** path defined for homebrew on Apple Silicon:
+```cmake -G "Xcode" -DOpenMP_omp_LIBRARY=/opt/homebrew/opt/libomp/lib/libomp.dylib```
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b98e53d18..6bf6353e6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -91,7 +91,33 @@ ELSEIF(LINUX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVK_USE_PLATFORM_XCB_KHR")
ENDIF(USE_D2D_WSI)
ELSEIF(APPLE)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVK_USE_PLATFORM_MACOS_MVK -DVK_EXAMPLE_XCODE_GENERATED")
+ IF (CMAKE_GENERATOR MATCHES "Xcode")
+ # Suppress regeneration for Xcode since environment variables will be lost if not set in Xcode locations/custom paths
+ set(CMAKE_SUPPRESS_REGENERATION ON)
+ set(CMAKE_XCODE_GENERATE_SCHEME ON)
+ IF (Vulkan_FOUND)
+ # If the Vulkan loader was found and its environment variables are defined, make them available within Xcode schemes
+ IF (DEFINED ENV{VK_ADD_LAYER_PATH})
+ set(CMAKE_XCODE_SCHEME_ENVIRONMENT "${CMAKE_XCODE_SCHEME_ENVIRONMENT};VK_ADD_LAYER_PATH=$ENV{VK_ADD_LAYER_PATH}")
+ ENDIF()
+ IF (DEFINED ENV{VK_ICD_FILENAMES})
+ set(CMAKE_XCODE_SCHEME_ENVIRONMENT "${CMAKE_XCODE_SCHEME_ENVIRONMENT};VK_ICD_FILENAMES=$ENV{VK_ICD_FILENAMES}")
+ ENDIF()
+ IF (DEFINED ENV{VK_DRIVER_FILES})
+ set(CMAKE_XCODE_SCHEME_ENVIRONMENT "${CMAKE_XCODE_SCHEME_ENVIRONMENT};VK_DRIVER_FILES=$ENV{VK_DRIVER_FILES}")
+ ENDIF()
+ ENDIF()
+ ENDIF()
+ IF (NOT Vulkan_FOUND)
+ # If the Vulkan loader was not found, then look for libMoltenVK.dylib in the Vulkan SDK and legacy MoltenVK locations
+ set(CMAKE_FIND_FRAMEWORK NEVER)
+ find_library(Vulkan_LIBRARY NAMES MoltenVK HINTS "$ENV{VULKAN_SDK}/lib" "$ENV{VULKAN_SDK}/dylib/macOS" REQUIRED)
+ IF (Vulkan_LIBRARY)
+ set(Vulkan_FOUND ON)
+ MESSAGE(STATUS "Using MoltenVK Vulkan Portability library")
+ ENDIF()
+ ENDIF()
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVK_USE_PLATFORM_METAL_EXT -DVK_EXAMPLE_XCODE_GENERATED")
# Todo : android?
ENDIF(WIN32)
@@ -138,11 +164,11 @@ endif()
IF(MSVC)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc")
ELSEIF(APPLE)
- #if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
- # SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fobjc-arc -ObjC++")
- #ELSE()
+ IF(CMAKE_GENERATOR MATCHES "Makefiles" OR CMAKE_GENERATOR MATCHES "Ninja")
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fobjc-arc -ObjC++")
+ ELSE() # SRS - use objective-c++ language flag vs. ObjC++ for Xcode builds
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fobjc-arc -xobjective-c++")
- #ENDIF()
+ ENDIF()
ENDIF(MSVC)
IF(WIN32)
diff --git a/base/CommandLineParser.hpp b/base/CommandLineParser.hpp
index c958fcffc..2211bd85c 100644
--- a/base/CommandLineParser.hpp
+++ b/base/CommandLineParser.hpp
@@ -105,7 +105,7 @@ class CommandLineParser
std::string value = options[name].value;
if (value != "") {
char* numConvPtr;
- int32_t intVal = strtol(value.c_str(), &numConvPtr, 10);
+ int32_t intVal = (int32_t)strtol(value.c_str(), &numConvPtr, 10);
return (intVal > 0) ? intVal : defaultValue;
}
else {
diff --git a/base/VulkanDebug.cpp b/base/VulkanDebug.cpp
index eacd6ac33..a449c9d67 100644
--- a/base/VulkanDebug.cpp
+++ b/base/VulkanDebug.cpp
@@ -54,7 +54,12 @@ namespace vks
// Display message to default output (console/logcat)
std::stringstream debugMessage;
- debugMessage << prefix << "[" << pCallbackData->messageIdNumber << "][" << pCallbackData->pMessageIdName << "] : " << pCallbackData->pMessage;
+ if (pCallbackData->pMessageIdName) {
+ debugMessage << prefix << "[" << pCallbackData->messageIdNumber << "][" << pCallbackData->pMessageIdName << "] : " << pCallbackData->pMessage;
+ }
+ else {
+ debugMessage << prefix << "[" << pCallbackData->messageIdNumber << "] : " << pCallbackData->pMessage;
+ }
#if defined(__ANDROID__)
if (messageSeverity >= VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {
diff --git a/base/VulkanDevice.cpp b/base/VulkanDevice.cpp
index b4c4042a2..c32ce912f 100644
--- a/base/VulkanDevice.cpp
+++ b/base/VulkanDevice.cpp
@@ -8,7 +8,7 @@
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
*/
-#if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
+#if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT))
// SRS - Enable beta extensions and make VK_KHR_portability_subset visible
#define VK_ENABLE_BETA_EXTENSIONS
#endif
@@ -269,7 +269,7 @@ namespace vks
deviceCreateInfo.pNext = &physicalDeviceFeatures2;
}
-#if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK)) && defined(VK_KHR_portability_subset)
+#if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT)) && defined(VK_KHR_portability_subset)
// SRS - When running on iOS/macOS with MoltenVK and VK_KHR_portability_subset is defined and supported by the device, enable the extension
if (extensionSupported(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME))
{
diff --git a/base/VulkanSwapChain.cpp b/base/VulkanSwapChain.cpp
index 6e8e1565e..0920c941c 100644
--- a/base/VulkanSwapChain.cpp
+++ b/base/VulkanSwapChain.cpp
@@ -23,6 +23,8 @@ void VulkanSwapChain::initSurface(wl_display *display, wl_surface *window)
void VulkanSwapChain::initSurface(xcb_connection_t* connection, xcb_window_t window)
#elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
void VulkanSwapChain::initSurface(void* view)
+#elif defined(VK_USE_PLATFORM_METAL_EXT)
+void VulkanSwapChain::initSurface(CAMetalLayer* metalLayer)
#elif (defined(_DIRECT2DISPLAY) || defined(VK_USE_PLATFORM_HEADLESS_EXT))
void VulkanSwapChain::initSurface(uint32_t width, uint32_t height)
#elif defined(VK_USE_PLATFORM_SCREEN_QNX)
@@ -57,6 +59,13 @@ void VulkanSwapChain::initSurface(screen_context_t screen_context, screen_window
surfaceCreateInfo.flags = 0;
surfaceCreateInfo.pView = view;
err = vkCreateMacOSSurfaceMVK(instance, &surfaceCreateInfo, NULL, &surface);
+#elif defined(VK_USE_PLATFORM_METAL_EXT)
+ VkMetalSurfaceCreateInfoEXT surfaceCreateInfo = {};
+ surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT;
+ surfaceCreateInfo.pNext = NULL;
+ surfaceCreateInfo.flags = 0;
+ surfaceCreateInfo.pLayer = metalLayer;
+ err = vkCreateMetalSurfaceEXT(instance, &surfaceCreateInfo, NULL, &surface);
#elif defined(_DIRECT2DISPLAY)
createDirect2DisplaySurface(width, height);
#elif defined(VK_USE_PLATFORM_DIRECTFB_EXT)
@@ -264,7 +273,7 @@ void VulkanSwapChain::create(uint32_t *width, uint32_t *height, bool vsync, bool
// Determine the number of images
uint32_t desiredNumberOfSwapchainImages = surfCaps.minImageCount + 1;
-#if (defined(VK_USE_PLATFORM_MACOS_MVK) && defined(VK_EXAMPLE_XCODE_GENERATED))
+#if (defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT)) && defined(VK_EXAMPLE_XCODE_GENERATED)
// SRS - Work around known MoltenVK issue re 2x frame rate when vsync (VK_PRESENT_MODE_FIFO_KHR) enabled
struct utsname sysInfo;
uname(&sysInfo);
diff --git a/base/VulkanSwapChain.h b/base/VulkanSwapChain.h
index 0e7cd917e..bbd951da4 100644
--- a/base/VulkanSwapChain.h
+++ b/base/VulkanSwapChain.h
@@ -60,6 +60,8 @@ class VulkanSwapChain
void initSurface(xcb_connection_t* connection, xcb_window_t window);
#elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
void initSurface(void* view);
+#elif defined(VK_USE_PLATFORM_METAL_EXT)
+ void initSurface(CAMetalLayer* metalLayer);
#elif (defined(_DIRECT2DISPLAY) || defined(VK_USE_PLATFORM_HEADLESS_EXT))
void initSurface(uint32_t width, uint32_t height);
#if defined(_DIRECT2DISPLAY)
diff --git a/base/VulkanTools.cpp b/base/VulkanTools.cpp
index 37f2f9cd7..740737870 100644
--- a/base/VulkanTools.cpp
+++ b/base/VulkanTools.cpp
@@ -8,8 +8,8 @@
#include "VulkanTools.h"
-#if !(defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
-// iOS & macOS: VulkanExampleBase::getAssetPath() implemented externally to allow access to Objective-C components
+#if !(defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT))
+// iOS & macOS: getAssetPath() and getShaderBasePath() implemented externally for access to Obj-C++ path utilities
const std::string getAssetPath()
{
#if defined(VK_USE_PLATFORM_ANDROID_KHR)
@@ -20,10 +20,7 @@ const std::string getAssetPath()
return "./../assets/";
#endif
}
-#endif
-#if !(defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
-// iOS & macOS: VulkanExampleBase::getAssetPath() implemented externally to allow access to Objective-C components
const std::string getShaderBasePath()
{
#if defined(VK_USE_PLATFORM_ANDROID_KHR)
diff --git a/base/keycodes.hpp b/base/keycodes.hpp
index f683e245f..2f8b9d1cd 100644
--- a/base/keycodes.hpp
+++ b/base/keycodes.hpp
@@ -44,7 +44,7 @@
#define KEY_SPACE 0x3E // AKEYCODE_SPACE
#define KEY_KPADD 0x9D // AKEYCODE_NUMPAD_ADD
-#elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
+#elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT))
#if !defined(VK_EXAMPLE_XCODE_GENERATED)
// For iOS and macOS pre-configured Xcode example project: Use character keycodes
// - Use numeric keys as optional alternative to function keys
diff --git a/base/vulkanexamplebase.cpp b/base/vulkanexamplebase.cpp
index 4954de69a..e4ea1d10b 100644
--- a/base/vulkanexamplebase.cpp
+++ b/base/vulkanexamplebase.cpp
@@ -8,11 +8,18 @@
#include "vulkanexamplebase.h"
-#if (defined(VK_USE_PLATFORM_MACOS_MVK) && defined(VK_EXAMPLE_XCODE_GENERATED))
+#if defined(VK_EXAMPLE_XCODE_GENERATED)
+#if (defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT))
#include
#include
#include
#endif
+#else // !defined(VK_EXAMPLE_XCODE_GENERATED)
+#if defined(VK_USE_PLATFORM_METAL_EXT)
+// SRS - Metal layer is defined externally when using iOS/macOS displayLink-driven examples project
+extern CAMetalLayer* layer;
+#endif
+#endif
std::vector VulkanExampleBase::args;
@@ -50,6 +57,8 @@ VkResult VulkanExampleBase::createInstance(bool enableValidation)
instanceExtensions.push_back(VK_MVK_IOS_SURFACE_EXTENSION_NAME);
#elif defined(VK_USE_PLATFORM_MACOS_MVK)
instanceExtensions.push_back(VK_MVK_MACOS_SURFACE_EXTENSION_NAME);
+#elif defined(VK_USE_PLATFORM_METAL_EXT)
+ instanceExtensions.push_back(VK_EXT_METAL_SURFACE_EXTENSION_NAME);
#elif defined(VK_USE_PLATFORM_HEADLESS_EXT)
instanceExtensions.push_back(VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME);
#elif defined(VK_USE_PLATFORM_SCREEN_QNX)
@@ -71,7 +80,7 @@ VkResult VulkanExampleBase::createInstance(bool enableValidation)
}
}
-#if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
+#if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT))
// SRS - When running on iOS/macOS with MoltenVK, enable VK_KHR_get_physical_device_properties2 if not already enabled by the example (required by VK_KHR_portability_subset)
if (std::find(enabledInstanceExtensions.begin(), enabledInstanceExtensions.end(), VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) == enabledInstanceExtensions.end())
{
@@ -106,7 +115,7 @@ VkResult VulkanExampleBase::createInstance(bool enableValidation)
}
-#if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK)) && defined(VK_KHR_portability_enumeration)
+#if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT)) && defined(VK_KHR_portability_enumeration)
// SRS - When running on iOS/macOS with MoltenVK and VK_KHR_portability_enumeration is defined and supported by the instance, enable the extension and the flag
if (std::find(supportedInstanceExtensions.begin(), supportedInstanceExtensions.end(), VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME) != supportedInstanceExtensions.end())
{
@@ -262,7 +271,7 @@ void VulkanExampleBase::nextFrame()
render();
frameCounter++;
auto tEnd = std::chrono::high_resolution_clock::now();
-#if (defined(VK_USE_PLATFORM_IOS_MVK) || (defined(VK_USE_PLATFORM_MACOS_MVK) && !defined(VK_EXAMPLE_XCODE_GENERATED)))
+#if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT)) && !defined(VK_EXAMPLE_XCODE_GENERATED)
// SRS - Calculate tDiff as time between frames vs. rendering time for iOS/macOS displayLink-driven examples project
auto tDiff = std::chrono::duration(tEnd - tPrevEnd).count();
#else
@@ -306,7 +315,7 @@ void VulkanExampleBase::renderLoop()
{
// SRS - for non-apple plaforms, handle benchmarking here within VulkanExampleBase::renderLoop()
// - for macOS, handle benchmarking within NSApp rendering loop via displayLinkOutputCb()
-#if !(defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
+#if !(defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT))
if (benchmark.active) {
#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
while (!configured)
@@ -659,7 +668,7 @@ void VulkanExampleBase::renderLoop()
}
updateOverlay();
}
-#elif (defined(VK_USE_PLATFORM_MACOS_MVK) && defined(VK_EXAMPLE_XCODE_GENERATED))
+#elif (defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT)) && defined(VK_EXAMPLE_XCODE_GENERATED)
[NSApp run];
#elif defined(VK_USE_PLATFORM_SCREEN_QNX)
while (!quit) {
@@ -1583,7 +1592,7 @@ void VulkanExampleBase::handleAppCommand(android_app * app, int32_t cmd)
break;
}
}
-#elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
+#elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT))
#if defined(VK_EXAMPLE_XCODE_GENERATED)
@interface AppDelegate : NSObject
{
@@ -1638,10 +1647,20 @@ dispatch_group_t concurrentGroup;
@end
const std::string getAssetPath() {
+#if defined(VK_EXAMPLE_ASSETS_DIR)
+ return VK_EXAMPLE_ASSETS_DIR;
+#else
return [NSBundle.mainBundle.resourcePath stringByAppendingString: @"/../../assets/"].UTF8String;
+#endif
}
-const std::string getShaderBasePath() { return [NSBundle.mainBundle.resourcePath stringByAppendingString: @"/../../shaders/"].UTF8String; }
+const std::string getShaderBasePath() {
+#if defined(VK_EXAMPLE_SHADERS_DIR)
+ return VK_EXAMPLE_SHADERS_DIR;
+#else
+ return [NSBundle.mainBundle.resourcePath stringByAppendingString: @"/../../shaders/"].UTF8String;
+#endif
+}
static CVReturn displayLinkOutputCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *inNow,
const CVTimeStamp *inOutputTime, CVOptionFlags flagsIn, CVOptionFlags *flagsOut,
@@ -1899,8 +1918,14 @@ void* VulkanExampleBase::setupWindow(void* view)
[window setDelegate:nsView];
[window setContentView:nsView];
this->view = (__bridge void*)nsView;
+#if defined(VK_USE_PLATFORM_METAL_EXT)
+ this->metalLayer = (CAMetalLayer*)nsView.layer;
+#endif
#else
this->view = view;
+#if defined(VK_USE_PLATFORM_METAL_EXT)
+ this->metalLayer = (CAMetalLayer*)layer;
+#endif
#endif
return view;
}
@@ -3236,6 +3261,8 @@ void VulkanExampleBase::initSwapchain()
swapChain.initSurface(androidApp->window);
#elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
swapChain.initSurface(view);
+#elif defined(VK_USE_PLATFORM_METAL_EXT)
+ swapChain.initSurface(metalLayer);
#elif defined(VK_USE_PLATFORM_DIRECTFB_EXT)
swapChain.initSurface(dfb, surface);
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
diff --git a/base/vulkanexamplebase.h b/base/vulkanexamplebase.h
index c0cc83ea9..e461783b9 100644
--- a/base/vulkanexamplebase.h
+++ b/base/vulkanexamplebase.h
@@ -238,8 +238,11 @@ class VulkanExampleBase
bool touchDown = false;
double touchTimer = 0.0;
int64_t lastTapTime = 0;
-#elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
+#elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT))
void* view;
+#if defined(VK_USE_PLATFORM_METAL_EXT)
+ CAMetalLayer* metalLayer;
+#endif
#if defined(VK_EXAMPLE_XCODE_GENERATED)
bool quit = false;
#endif
@@ -295,7 +298,7 @@ class VulkanExampleBase
#elif defined(VK_USE_PLATFORM_ANDROID_KHR)
static int32_t handleAppInput(struct android_app* app, AInputEvent* event);
static void handleAppCommand(android_app* app, int32_t cmd);
-#elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
+#elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT))
void* setupWindow(void* view);
void displayLinkOutputCb();
void mouseDragged(float x, float y);
@@ -523,7 +526,7 @@ int main(const int argc, const char *argv[]) \
delete(vulkanExample); \
return 0; \
}
-#elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
+#elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT))
#if defined(VK_EXAMPLE_XCODE_GENERATED)
#define VULKAN_EXAMPLE_MAIN() \
VulkanExample *vulkanExample; \
diff --git a/benchmark-all-validate.py b/benchmark-all-validate.py
new file mode 100644
index 000000000..5796636a0
--- /dev/null
+++ b/benchmark-all-validate.py
@@ -0,0 +1,116 @@
+# Benchmark all examples
+import subprocess
+import sys
+import os
+import platform
+
+EXAMPLES = [
+ "bloom",
+ "computecloth",
+ "computecullandlod",
+ "computenbody",
+ "computeparticles",
+ "computeraytracing",
+ "computeshader",
+ "conditionalrender",
+ "conservativeraster",
+ "debugprintf",
+ "debugutils",
+ "deferred",
+ "deferredmultisampling",
+ "deferredshadows",
+ "descriptorbuffer",
+ "descriptorindexing",
+ "descriptorsets",
+ "displacement",
+ "distancefieldfonts",
+ "dynamicrendering",
+ "dynamicstate",
+ "dynamicuniformbuffer",
+ "gears",
+ "geometryshader",
+ "gltfloading",
+ "gltfscenerendering",
+ "gltfskinning",
+ "graphicspipelinelibrary",
+ "hdr",
+ "imgui",
+ "indirectdraw",
+ "inlineuniformblocks",
+ "inputattachments",
+ "instancing",
+ "meshshader",
+ "multisampling",
+ "multithreading",
+ "multiview",
+ "negativeviewportheight",
+ "occlusionquery",
+ "offscreen",
+ "oit",
+ "parallaxmapping",
+ "particlesystem",
+ "pbrbasic",
+ "pbribl",
+ "pbrtexture",
+ "pipelines",
+ "pipelinestatistics",
+ "pushconstants",
+ "pushdescriptors",
+ "radialblur",
+ "rayquery",
+ "raytracingbasic",
+ "raytracingcallable",
+ "raytracinggltf",
+ "raytracingintersection",
+ "raytracingpositionfetch",
+ "raytracingreflections",
+ "raytracingsbtdata",
+ "raytracingshadows",
+ "raytracingtextures",
+ "shaderobjects",
+ "shadowmapping",
+ "shadowmappingcascade",
+ "shadowmappingomni",
+ "specializationconstants",
+ "sphericalenvmapping",
+ "ssao",
+ "stencilbuffer",
+ "subpasses",
+ "terraintessellation",
+ "tessellation",
+ "textoverlay",
+ "texture",
+ "texture3d",
+ "texturearray",
+ "texturecubemap",
+ "texturecubemaparray",
+ "texturemipmapgen",
+ "texturesparseresidency",
+ "triangle",
+ "variablerateshading",
+ "vertexattributes",
+ "viewportarray",
+ "vulkanscene"
+]
+
+CURR_INDEX = 0
+
+ARGS = "-fullscreen -b -br 2 -v"
+
+print("Benchmarking all examples...")
+
+os.makedirs("./benchmark", exist_ok=True)
+
+for example in EXAMPLES:
+ print("---- (%d/%d) Running %s in benchmark mode ----" % (CURR_INDEX+1, len(EXAMPLES), example))
+ if platform.system() == 'Linux' or platform.system() == 'Darwin':
+ RESULT_CODE = subprocess.call("./%s %s -bf ./benchmark/%s.csv 5" % (example, ARGS, example), shell=True)
+ else:
+ RESULT_CODE = subprocess.call("%s %s -bf ./benchmark/%s.csv 5" % (example, ARGS, example))
+ if RESULT_CODE == 0:
+ print("Results written to ./benchmark/%s.csv" % example)
+ else:
+ print("Error, result code = %d" % RESULT_CODE)
+ CURR_INDEX += 1
+
+print("Benchmark run finished")
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 5d18d7d2b..f68d863fe 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -65,7 +65,9 @@ function(buildExample EXAMPLE_NAME)
endif()
find_package(OpenMP)
if(OpenMP_CXX_FOUND)
- link_directories(${OpenMP_CXX_LIBRARY_DIRS})
+ set_target_properties(${EXAMPLE_NAME} PROPERTIES COMPILE_FLAGS ${OpenMP_CXX_FLAGS})
+ target_include_directories(${EXAMPLE_NAME} PRIVATE ${OpenMP_CXX_INCLUDE_DIRS})
+ target_link_libraries(${EXAMPLE_NAME} ${OpenMP_CXX_LIBRARIES})
endif()
endif()
diff --git a/examples/computeheadless/computeheadless.cpp b/examples/computeheadless/computeheadless.cpp
index 2156a79d3..aef7a62f1 100644
--- a/examples/computeheadless/computeheadless.cpp
+++ b/examples/computeheadless/computeheadless.cpp
@@ -24,7 +24,7 @@
#include
#include
-#if defined(VK_USE_PLATFORM_MACOS_MVK)
+#if (defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT))
#define VK_ENABLE_BETA_EXTENSIONS
#endif
#include
@@ -177,7 +177,7 @@ class VulkanExample
instanceCreateInfo.enabledLayerCount = layerCount;
}
#endif
-#if defined(VK_USE_PLATFORM_MACOS_MVK)
+#if (defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT))
// SRS - When running on macOS with MoltenVK, enable VK_KHR_get_physical_device_properties2 (required by VK_KHR_portability_subset)
instanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
#if defined(VK_KHR_portability_enumeration)
@@ -260,7 +260,7 @@ class VulkanExample
deviceCreateInfo.queueCreateInfoCount = 1;
deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
std::vector deviceExtensions = {};
-#if defined(VK_USE_PLATFORM_MACOS_MVK) && defined(VK_KHR_portability_subset)
+#if (defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT)) && defined(VK_KHR_portability_subset)
// SRS - When running on macOS with MoltenVK and VK_KHR_portability_subset is defined and supported by the device, enable the extension
uint32_t deviceExtCount = 0;
vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &deviceExtCount, nullptr);
diff --git a/examples/computeraytracing/computeraytracing.cpp b/examples/computeraytracing/computeraytracing.cpp
index 04f0caaef..93c075706 100644
--- a/examples/computeraytracing/computeraytracing.cpp
+++ b/examples/computeraytracing/computeraytracing.cpp
@@ -86,7 +86,7 @@ class VulkanExample : public VulkanExampleBase
camera.rotationSpeed = 0.0f;
camera.movementSpeed = 2.5f;
-#if defined(VK_USE_PLATFORM_MACOS_MVK)
+#if (defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT))
// SRS - on macOS set environment variable to ensure MoltenVK disables Metal argument buffers for this example
setenv("MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS", "0", 1);
#endif
@@ -429,6 +429,8 @@ class VulkanExample : public VulkanExampleBase
VkBufferCopy copyRegion = { 0, 0, storageBufferSize};
vkCmdCopyBuffer(copyCmd, stagingBuffer.buffer, compute.objectStorageBuffer.buffer, 1, ©Region);
vulkanDevice->flushCommandBuffer(copyCmd, queue, true);
+
+ stagingBuffer.destroy();
}
// The descriptor pool will be shared between graphics and compute
diff --git a/examples/descriptorindexing/descriptorindexing.cpp b/examples/descriptorindexing/descriptorindexing.cpp
index d457a1145..202ee0c2f 100644
--- a/examples/descriptorindexing/descriptorindexing.cpp
+++ b/examples/descriptorindexing/descriptorindexing.cpp
@@ -56,6 +56,7 @@ class VulkanExample : public VulkanExampleBase
// [POI] Enable required extensions
enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
+ enabledDeviceExtensions.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME);
enabledDeviceExtensions.push_back(VK_KHR_MAINTENANCE3_EXTENSION_NAME);
enabledDeviceExtensions.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
@@ -67,7 +68,7 @@ class VulkanExample : public VulkanExampleBase
deviceCreatepNextChain = &physicalDeviceDescriptorIndexingFeatures;
-#if defined(VK_USE_PLATFORM_MACOS_MVK)
+#if (defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT))
// SRS - on macOS set environment variable to configure MoltenVK for using Metal argument buffers (needed for descriptor indexing)
// - MoltenVK supports Metal argument buffers on macOS, iOS possible in future (see https://github.com/KhronosGroup/MoltenVK/issues/1651)
setenv("MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS", "1", 1);
@@ -213,7 +214,7 @@ class VulkanExample : public VulkanExampleBase
vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, static_cast(textures.size()))
};
VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2);
-#if defined(VK_USE_PLATFORM_MACOS_MVK)
+#if (defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT))
// SRS - increase the per-stage descriptor samplers limit on macOS (maxPerStageDescriptorUpdateAfterBindSamplers > maxPerStageDescriptorSamplers)
descriptorPoolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT;
#endif
@@ -243,7 +244,7 @@ class VulkanExample : public VulkanExampleBase
setLayoutBindingFlags.pBindingFlags = descriptorBindingFlags.data();
VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings);
-#if defined(VK_USE_PLATFORM_MACOS_MVK)
+#if (defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT))
// SRS - increase the per-stage descriptor samplers limit on macOS (maxPerStageDescriptorUpdateAfterBindSamplers > maxPerStageDescriptorSamplers)
descriptorSetLayoutCI.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT;
#endif
diff --git a/examples/dynamicstate/dynamicstate.cpp b/examples/dynamicstate/dynamicstate.cpp
index 5cfe4b9d7..a8c200c39 100644
--- a/examples/dynamicstate/dynamicstate.cpp
+++ b/examples/dynamicstate/dynamicstate.cpp
@@ -94,23 +94,35 @@ class VulkanExample: public VulkanExampleBase
void getEnabledExtensions()
{
+ // Get the full list of extended dynamic state features supported by the device
+ extendedDynamicStateFeaturesEXT.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT;
+ extendedDynamicStateFeaturesEXT.pNext = &extendedDynamicState2FeaturesEXT;
+ extendedDynamicState2FeaturesEXT.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT;
+ extendedDynamicState2FeaturesEXT.pNext = &extendedDynamicState3FeaturesEXT;
+ extendedDynamicState3FeaturesEXT.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT;
+ extendedDynamicState3FeaturesEXT.pNext = nullptr;
+
+ VkPhysicalDeviceFeatures2 physicalDeviceFeatures2;
+ physicalDeviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
+ physicalDeviceFeatures2.pNext = &extendedDynamicStateFeaturesEXT;
+ vkGetPhysicalDeviceFeatures2(physicalDevice, &physicalDeviceFeatures2);
+
// Check what dynamic states are supported by the current implementation
- hasDynamicState = vulkanDevice->extensionSupported(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
- hasDynamicState2 = vulkanDevice->extensionSupported(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
- hasDynamicState3 = vulkanDevice->extensionSupported(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
+ // Checking for available features is probably sufficient, but retained redundant extension checks for clarity and consistency
+ hasDynamicState = vulkanDevice->extensionSupported(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME) && extendedDynamicStateFeaturesEXT.extendedDynamicState;
+ hasDynamicState2 = vulkanDevice->extensionSupported(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME) && extendedDynamicState2FeaturesEXT.extendedDynamicState2;
+ hasDynamicState3 = vulkanDevice->extensionSupported(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME) && extendedDynamicState3FeaturesEXT.extendedDynamicState3ColorBlendEnable && extendedDynamicState3FeaturesEXT.extendedDynamicState3ColorBlendEquation;
hasDynamicVertexState = vulkanDevice->extensionSupported(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
// Enable dynamic state extensions if present. This function is called after physical and before logical device creation, so we can enabled extensions based on a list of supported extensions
- if (vulkanDevice->extensionSupported(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME)) {
+ if (hasDynamicState) {
enabledDeviceExtensions.push_back(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
- extendedDynamicStateFeaturesEXT.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT;
- extendedDynamicStateFeaturesEXT.extendedDynamicState = VK_TRUE;
+ extendedDynamicStateFeaturesEXT.pNext = nullptr;
deviceCreatepNextChain = &extendedDynamicStateFeaturesEXT;
}
- if (vulkanDevice->extensionSupported(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME)) {
+ if (hasDynamicState2) {
enabledDeviceExtensions.push_back(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
- extendedDynamicState2FeaturesEXT.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT;
- extendedDynamicState2FeaturesEXT.extendedDynamicState2 = VK_TRUE;
+ extendedDynamicState2FeaturesEXT.pNext = nullptr;
if (hasDynamicState) {
extendedDynamicStateFeaturesEXT.pNext = &extendedDynamicState2FeaturesEXT;
}
@@ -118,11 +130,8 @@ class VulkanExample: public VulkanExampleBase
deviceCreatepNextChain = &extendedDynamicState2FeaturesEXT;
}
}
- if (vulkanDevice->extensionSupported(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME)) {
+ if (hasDynamicState3) {
enabledDeviceExtensions.push_back(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
- extendedDynamicState3FeaturesEXT.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT;
- extendedDynamicState3FeaturesEXT.extendedDynamicState3ColorBlendEnable = VK_TRUE;
- extendedDynamicState3FeaturesEXT.extendedDynamicState3ColorBlendEquation = VK_TRUE;
if (hasDynamicState2) {
extendedDynamicState2FeaturesEXT.pNext = &extendedDynamicState3FeaturesEXT;
}
@@ -131,7 +140,7 @@ class VulkanExample: public VulkanExampleBase
}
}
- if (vulkanDevice->extensionSupported(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME)) {
+ if (hasDynamicVertexState) {
enabledDeviceExtensions.push_back(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
}
}
@@ -377,7 +386,7 @@ class VulkanExample: public VulkanExampleBase
rebuildCB |= overlay->checkBox("Depth test", &dynamicState.depthTest);
rebuildCB |= overlay->checkBox("Depth write", &dynamicState.depthWrite);
} else {
- overlay->text("Extension not supported");
+ overlay->text("Extension or features not supported");
}
}
if (overlay->header("Dynamic state 2")) {
@@ -385,7 +394,7 @@ class VulkanExample: public VulkanExampleBase
rebuildCB |= overlay->checkBox("Rasterizer discard", &dynamicState2.rasterizerDiscardEnable);
}
else {
- overlay->text("Extension not supported");
+ overlay->text("Extension or features not supported");
}
}
if (overlay->header("Dynamic state 3")) {
@@ -394,7 +403,7 @@ class VulkanExample: public VulkanExampleBase
rebuildCB |= overlay->colorPicker("Clear color", clearColor);
}
else {
- overlay->text("Extension not supported");
+ overlay->text("Extension or features not supported");
}
}
if (rebuildCB) {
diff --git a/examples/oit/oit.cpp b/examples/oit/oit.cpp
index 41fab40bf..7c428220b 100644
--- a/examples/oit/oit.cpp
+++ b/examples/oit/oit.cpp
@@ -185,7 +185,7 @@ class VulkanExample : public VulkanExampleBase
imageInfo.mipLevels = 1;
imageInfo.arrayLayers = 1;
imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
-#if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
+#if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT))
// SRS - On macOS/iOS use linear tiling for atomic image access, see https://github.com/KhronosGroup/MoltenVK/issues/1027
imageInfo.tiling = VK_IMAGE_TILING_LINEAR;
#else
diff --git a/examples/particlesystem/particlesystem.cpp b/examples/particlesystem/particlesystem.cpp
index 507d919ff..ca01acbf7 100644
--- a/examples/particlesystem/particlesystem.cpp
+++ b/examples/particlesystem/particlesystem.cpp
@@ -189,7 +189,7 @@ class VulkanExample : public VulkanExampleBase
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.particles, 0, nullptr);
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.particles);
vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &particles.buffer, offsets);
- vkCmdDraw(drawCmdBuffers[i], static_cast(particles.size), 1, 0, 0);
+ vkCmdDraw(drawCmdBuffers[i], static_cast(particleBuffer.size()), 1, 0, 0);
drawUI(drawCmdBuffers[i]);
diff --git a/examples/raytracingcallable/raytracingcallable.cpp b/examples/raytracingcallable/raytracingcallable.cpp
index 933868d96..adb0a1cbd 100644
--- a/examples/raytracingcallable/raytracingcallable.cpp
+++ b/examples/raytracingcallable/raytracingcallable.cpp
@@ -463,12 +463,20 @@ class VulkanExample : public VulkanRaytracingSample
shaderGroups.push_back(shaderGroup);
}
+ // Get max pipeline ray tracing recursion depth for physical device
+ VkPhysicalDeviceRayTracingPipelinePropertiesKHR physicalDeviceRayTracingPipelinePropertiesKHR {};
+ physicalDeviceRayTracingPipelinePropertiesKHR.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR;
+ VkPhysicalDeviceProperties2 physicalDeviceProperties2;
+ physicalDeviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR;
+ physicalDeviceProperties2.pNext = &physicalDeviceRayTracingPipelinePropertiesKHR;
+ vkGetPhysicalDeviceProperties2(physicalDevice, &physicalDeviceProperties2);
+
VkRayTracingPipelineCreateInfoKHR rayTracingPipelineCI = vks::initializers::rayTracingPipelineCreateInfoKHR();
rayTracingPipelineCI.stageCount = static_cast(shaderStages.size());
rayTracingPipelineCI.pStages = shaderStages.data();
rayTracingPipelineCI.groupCount = static_cast(shaderGroups.size());
rayTracingPipelineCI.pGroups = shaderGroups.data();
- rayTracingPipelineCI.maxPipelineRayRecursionDepth = 2;
+ rayTracingPipelineCI.maxPipelineRayRecursionDepth = std::min(uint32_t(2), physicalDeviceRayTracingPipelinePropertiesKHR.maxRayRecursionDepth);
rayTracingPipelineCI.layout = pipelineLayout;
VK_CHECK_RESULT(vkCreateRayTracingPipelinesKHR(device, VK_NULL_HANDLE, VK_NULL_HANDLE, 1, &rayTracingPipelineCI, nullptr, &pipeline));
}
diff --git a/examples/raytracingintersection/raytracingintersection.cpp b/examples/raytracingintersection/raytracingintersection.cpp
index 013b8b918..d1e9cb8ed 100644
--- a/examples/raytracingintersection/raytracingintersection.cpp
+++ b/examples/raytracingintersection/raytracingintersection.cpp
@@ -431,12 +431,20 @@ class VulkanExample : public VulkanRaytracingSample
shaderGroups.push_back(shaderGroup);
}
+ // Get max pipeline ray tracing recursion depth for physical device
+ VkPhysicalDeviceRayTracingPipelinePropertiesKHR physicalDeviceRayTracingPipelinePropertiesKHR {};
+ physicalDeviceRayTracingPipelinePropertiesKHR.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR;
+ VkPhysicalDeviceProperties2 physicalDeviceProperties2;
+ physicalDeviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR;
+ physicalDeviceProperties2.pNext = &physicalDeviceRayTracingPipelinePropertiesKHR;
+ vkGetPhysicalDeviceProperties2(physicalDevice, &physicalDeviceProperties2);
+
VkRayTracingPipelineCreateInfoKHR rayTracingPipelineCI = vks::initializers::rayTracingPipelineCreateInfoKHR();
rayTracingPipelineCI.stageCount = static_cast(shaderStages.size());
rayTracingPipelineCI.pStages = shaderStages.data();
rayTracingPipelineCI.groupCount = static_cast(shaderGroups.size());
rayTracingPipelineCI.pGroups = shaderGroups.data();
- rayTracingPipelineCI.maxPipelineRayRecursionDepth = 2;
+ rayTracingPipelineCI.maxPipelineRayRecursionDepth = std::min(uint32_t(2), physicalDeviceRayTracingPipelinePropertiesKHR.maxRayRecursionDepth);
rayTracingPipelineCI.layout = pipelineLayout;
VK_CHECK_RESULT(vkCreateRayTracingPipelinesKHR(device, VK_NULL_HANDLE, VK_NULL_HANDLE, 1, &rayTracingPipelineCI, nullptr, &pipeline));
}
diff --git a/examples/raytracingreflections/raytracingreflections.cpp b/examples/raytracingreflections/raytracingreflections.cpp
index 32ba5c45e..5adc32077 100644
--- a/examples/raytracingreflections/raytracingreflections.cpp
+++ b/examples/raytracingreflections/raytracingreflections.cpp
@@ -393,12 +393,20 @@ class VulkanExample : public VulkanRaytracingSample
shaderGroups.push_back(shaderGroup);
}
+ // Get max pipeline ray tracing recursion depth for physical device
+ VkPhysicalDeviceRayTracingPipelinePropertiesKHR physicalDeviceRayTracingPipelinePropertiesKHR {};
+ physicalDeviceRayTracingPipelinePropertiesKHR.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR;
+ VkPhysicalDeviceProperties2 physicalDeviceProperties2;
+ physicalDeviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR;
+ physicalDeviceProperties2.pNext = &physicalDeviceRayTracingPipelinePropertiesKHR;
+ vkGetPhysicalDeviceProperties2(physicalDevice, &physicalDeviceProperties2);
+
VkRayTracingPipelineCreateInfoKHR rayTracingPipelineCI = vks::initializers::rayTracingPipelineCreateInfoKHR();
rayTracingPipelineCI.stageCount = static_cast(shaderStages.size());
rayTracingPipelineCI.pStages = shaderStages.data();
rayTracingPipelineCI.groupCount = static_cast(shaderGroups.size());
rayTracingPipelineCI.pGroups = shaderGroups.data();
- rayTracingPipelineCI.maxPipelineRayRecursionDepth = 4;
+ rayTracingPipelineCI.maxPipelineRayRecursionDepth = std::min(uint32_t(4), physicalDeviceRayTracingPipelinePropertiesKHR.maxRayRecursionDepth);
rayTracingPipelineCI.layout = pipelineLayout;
VK_CHECK_RESULT(vkCreateRayTracingPipelinesKHR(device, VK_NULL_HANDLE, VK_NULL_HANDLE, 1, &rayTracingPipelineCI, nullptr, &pipeline));
}
diff --git a/examples/raytracingshadows/raytracingshadows.cpp b/examples/raytracingshadows/raytracingshadows.cpp
index 6a575ade2..52ba54450 100644
--- a/examples/raytracingshadows/raytracingshadows.cpp
+++ b/examples/raytracingshadows/raytracingshadows.cpp
@@ -393,12 +393,20 @@ class VulkanExample : public VulkanRaytracingSample
shaderGroups.push_back(shaderGroup);
}
+ // Get max pipeline ray tracing recursion depth for physical device
+ VkPhysicalDeviceRayTracingPipelinePropertiesKHR physicalDeviceRayTracingPipelinePropertiesKHR {};
+ physicalDeviceRayTracingPipelinePropertiesKHR.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR;
+ VkPhysicalDeviceProperties2 physicalDeviceProperties2;
+ physicalDeviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR;
+ physicalDeviceProperties2.pNext = &physicalDeviceRayTracingPipelinePropertiesKHR;
+ vkGetPhysicalDeviceProperties2(physicalDevice, &physicalDeviceProperties2);
+
VkRayTracingPipelineCreateInfoKHR rayTracingPipelineCI = vks::initializers::rayTracingPipelineCreateInfoKHR();
rayTracingPipelineCI.stageCount = static_cast(shaderStages.size());
rayTracingPipelineCI.pStages = shaderStages.data();
rayTracingPipelineCI.groupCount = static_cast(shaderGroups.size());
rayTracingPipelineCI.pGroups = shaderGroups.data();
- rayTracingPipelineCI.maxPipelineRayRecursionDepth = 2;
+ rayTracingPipelineCI.maxPipelineRayRecursionDepth = std::min(uint32_t(2), physicalDeviceRayTracingPipelinePropertiesKHR.maxRayRecursionDepth);
rayTracingPipelineCI.layout = pipelineLayout;
VK_CHECK_RESULT(vkCreateRayTracingPipelinesKHR(device, VK_NULL_HANDLE, VK_NULL_HANDLE, 1, &rayTracingPipelineCI, nullptr, &pipeline));
}
diff --git a/examples/renderheadless/renderheadless.cpp b/examples/renderheadless/renderheadless.cpp
index 931cd4009..6b894b94d 100644
--- a/examples/renderheadless/renderheadless.cpp
+++ b/examples/renderheadless/renderheadless.cpp
@@ -30,7 +30,7 @@
#include
#include
-#if defined(VK_USE_PLATFORM_MACOS_MVK)
+#if (defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT))
#define VK_ENABLE_BETA_EXTENSIONS
#endif
#include
@@ -208,7 +208,7 @@ class VulkanExample
instanceCreateInfo.enabledLayerCount = layerCount;
}
#endif
-#if defined(VK_USE_PLATFORM_MACOS_MVK)
+#if (defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT))
// SRS - When running on macOS with MoltenVK, enable VK_KHR_get_physical_device_properties2 (required by VK_KHR_portability_subset)
instanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
#if defined(VK_KHR_portability_enumeration)
@@ -290,7 +290,7 @@ class VulkanExample
deviceCreateInfo.queueCreateInfoCount = 1;
deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
std::vector deviceExtensions = {};
-#if defined(VK_USE_PLATFORM_MACOS_MVK) && defined(VK_KHR_portability_subset)
+#if (defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT)) && defined(VK_KHR_portability_subset)
// SRS - When running on macOS with MoltenVK and VK_KHR_portability_subset is defined and supported by the device, enable the extension
uint32_t deviceExtCount = 0;
vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &deviceExtCount, nullptr);
diff --git a/examples/specializationconstants/specializationconstants.cpp b/examples/specializationconstants/specializationconstants.cpp
index fc1ed7bbf..80c6cdd0c 100644
--- a/examples/specializationconstants/specializationconstants.cpp
+++ b/examples/specializationconstants/specializationconstants.cpp
@@ -47,7 +47,7 @@ class VulkanExample: public VulkanExampleBase
camera.setRotation(glm::vec3(-40.0f, -90.0f, 0.0f));
camera.setTranslation(glm::vec3(0.0f, 0.0f, -2.0f));
-#if defined(VK_USE_PLATFORM_MACOS_MVK)
+#if (defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT))
// SRS - on macOS set environment variable to ensure MoltenVK disables Metal argument buffers for this example
setenv("MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS", "0", 1);
#endif
diff --git a/examples/textoverlay/textoverlay.cpp b/examples/textoverlay/textoverlay.cpp
index 41035bff2..1c81f73e3 100644
--- a/examples/textoverlay/textoverlay.cpp
+++ b/examples/textoverlay/textoverlay.cpp
@@ -516,7 +516,9 @@ class VulkanExample : public VulkanExampleBase
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr);
model.draw(drawCmdBuffers[i]);
- textOverlay->draw(drawCmdBuffers[i]);
+ if (textOverlay->visible) {
+ textOverlay->draw(drawCmdBuffers[i]);
+ }
vkCmdEndRenderPass(drawCmdBuffers[i]);
@@ -709,6 +711,7 @@ class VulkanExample : public VulkanExampleBase
case KEY_KPADD:
case KEY_SPACE:
textOverlay->visible = !textOverlay->visible;
+ buildCommandBuffers();
}
}
};
diff --git a/examples/triangle/triangle.cpp b/examples/triangle/triangle.cpp
index c71b8ef88..e9f24817d 100644
--- a/examples/triangle/triangle.cpp
+++ b/examples/triangle/triangle.cpp
@@ -1160,7 +1160,7 @@ int main(const int argc, const char *argv[])
delete(vulkanExample);
return 0;
}
-#elif (defined(VK_USE_PLATFORM_MACOS_MVK) && defined(VK_EXAMPLE_XCODE_GENERATED))
+#elif (defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT)) && defined(VK_EXAMPLE_XCODE_GENERATED)
VulkanExample *vulkanExample;
int main(const int argc, const char *argv[])
{
diff --git a/examples/variablerateshading/variablerateshading.h b/examples/variablerateshading/variablerateshading.h
index 32602e027..91afe1b2e 100644
--- a/examples/variablerateshading/variablerateshading.h
+++ b/examples/variablerateshading/variablerateshading.h
@@ -53,18 +53,18 @@ class VulkanExample : public VulkanExampleBase
VulkanExample();
~VulkanExample();
- virtual void getEnabledFeatures();
+ virtual void getEnabledFeatures() override;
void handleResize();
- void buildCommandBuffers();
+ void buildCommandBuffers() override;
void loadAssets();
void prepareShadingRateImage();
void setupDescriptors();
void preparePipelines();
void prepareUniformBuffers();
void updateUniformBuffers();
- void prepare();
+ void prepare() override;
void setupFrameBuffer() override;
void setupRenderPass() override;
- virtual void render();
- virtual void OnUpdateUIOverlay(vks::UIOverlay* overlay);
-};
\ No newline at end of file
+ virtual void render() override;
+ virtual void OnUpdateUIOverlay(vks::UIOverlay* overlay) override;
+};