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; +};