*.files
*.includes
.vscode/
+.DS_Store
# Build Instructions
-Instructions for building this repository on Linux, Windows, and Android.
+Instructions for building this repository on Linux, Windows, Android, and MacOS.
## Index
3. [Windows Build](#windows-build)
4. [Linux Build](#linux-build)
5. [Android Build](#android-build)
+6. [MacOS build](#macos-build)
[](#contributing)
2. Execute `./update_external_sources.sh` -- this will download and build external components
3. Create a `build` directory, change into that directory, and run cmake:
- ```script
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Debug ..
- ```
-4. Change into the newly-created build directory
-5. Run `make -j8` to begin the build
+4. Run `make -j8` to begin the build
If your build system supports ccache, you can enable that via CMake option `-DUSE_CCACHE=On`
./build-and-install
adb shell am start -a android.intent.action.MAIN -c android-intent.category.LAUNCH -n com.example.Smoke/android.app.NativeActivity --es args "--validate"
+[](#macos-build)
+
+## Building on MacOS
+
+### MacOS Build Requirements
+
+Tested on OSX version 10.12.6
+
+Setup Homebrew and components
+
+- Follow instructions on [brew.sh](http://brew.sh) to get Homebrew installed.
+
+ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
+
+- Ensure Homebrew is at the beginning of your PATH:
+
+ export PATH=/usr/local/bin:$PATH
+
+- Add packages with the following (may need refinement)
+
+ brew install cmake python python3 git
+
+### Clone the Repository
+
+Clone the Vulkan-LoaderAndValidationLayers repository:
+
+ git clone https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers.git
+
+### Get the External Libraries
+
+Change to the cloned directory (`cd Vulkan-LoaderAndValidationLayers`) and run the script:
+
+ ./update_external_sources.sh
+
+This script downloads and builds the `glslang` and `MoltenVK` repositories.
+
+### MacOS build
+
+#### CMake Generators
+
+This repository uses CMake to generate build or project files that are
+then used to build the repository.
+The CMake generators explicitly supported in this repository are:
+
+- Unix Makefiles
+- Xcode
+
+#### Building with the Unix Makefiles Generator
+
+This generator is the default generator, so all that is needed for a debug
+build is:
+
+ mkdir build
+ cd build
+ cmake -DCMAKE_BUILD_TYPE=Debug ..
+ make
+
+To speed up the build on a multi-core machine, use the `-j` option for `make`
+to specify the number of cores to use for the build.
+For example:
+
+ make -j4
+
+You can now run the demo applications from the command line:
+
+ open demos/cube.app
+ open demos/cubepp.app
+ open demos/smoketest.app
+ open demos/vulkaninfo.app
+
+Or you can locate them from `Finder` and launch them from there.
+
+##### The Install Target and RPATH
+
+The applications you just built are "bundled applications", but the executables
+are using the `RPATH` mechanism to locate runtime dependencies that are still
+in your build tree.
+
+To see this, run this command from your `build` directory:
+
+ otool -l demos/cube.app/Contents/MacOS/cube
+
+and note that the `cube` executable contains loader commands:
+
+- `LC_LOAD_DYLIB` to load `libvulkan.1.dylib` via an `@rpath`
+- `LC_RPATH` that contains an absolute path to the build location of the Vulkan loader
+
+This makes the bundled application "non-transportable", meaning that it won't run
+unless the Vulkan loader is on that specific absolute path.
+This is useful for debugging the loader or other components built in this repository,
+but not if you want to move the application to another machine or remove your build tree.
+
+To address this problem, run:
+
+ make install
+
+This step "cleans up" the `RPATH` to remove any external references
+and performs other bundle fix-ups.
+After running `make install`, re-run the `otool` command again and note:
+
+- `LC_LOAD_DYLIB` is now `@executable_path/../MacOS/libvulkan.1.dylib`
+- `LC_RPATH` is no longer present
+
+The "bundle fix-up" operation also puts a copy of the Vulkan loader into the bundle,
+making the bundle completely self-contained and self-referencing.
+
+Note that the "install" target has a very different meaning compared to the Linux
+"make install" target.
+The Linux "install" copies the targets to system directories.
+In MacOS, "install" means fixing up application bundles.
+In both cases, the "install" target operations clean up the `RPATH`.
+
+##### The Non-bundled vulkaninfo Application
+
+There is also a non-bundled version of the `vulkaninfo` application that you can
+run from the command line:
+
+ demos/vulkaninfo
+
+If you run this before you run "make install", vulkaninfo's RPATH is already set
+to point to the Vulkan loader in the build tree, so it has no trouble finding it.
+But the loader will not find the MoltenVK driver and you'll see a message about an
+incompatible driver. To remedy this:
+
+ VK_ICD_FILENAMES=../external/MoltenVK/Package/Latest/MoltenVK/macOS/MoltenVK_icd.json demos/vulkaninfo
+
+If you run `vulkaninfo` after doing a "make install", the `RPATH` in the `vulkaninfo` application
+got removed and the OS needs extra help to locate the Vulkan loader:
+
+ DYLD_LIBRARY_PATH=loader VK_ICD_FILENAMES=../external/MoltenVK/Package/Latest/MoltenVK/macOS/MoltenVK_icd.json demos/vulkaninfo
+
+#### Building with the Xcode Generator
+
+To create and open an Xcode project:
+
+ mkdir build-xcode
+ cd build-xcode
+ cmake -GXcode ..
+ open VULKAN.xcodeproj
+
+Within Xcode, you can select Debug or Release builds in the project's Build Settings.
+You can also select individual schemes for working with specific applications like `cube`.
+
## Ninja Builds - All Platforms
The [Qt Creator IDE](https://qt.io/download-open-source/#section-2) can open a root CMakeList.txt
as a project directly, and it provides tools within Creator to configure and generate Vulkan SDK
build files for one to many targets concurrently.
-Alternatively, when invoking CMake, use the `-G Codeblocks` Ninja option to generate Ninja build
+Alternatively, when invoking CMake, use the `-G "Codeblocks - Ninja"` option to generate Ninja build
files to be used as project files for QtCreator
- Follow the steps defined elsewhere for the OS using the update\_external\_sources script or as
- In order to debug with QtCreator, a
[Microsoft WDK: eg WDK 10](http://go.microsoft.com/fwlink/p/?LinkId=526733) is required.
-Note that installing the WDK breaks the MSVC vcvarsall.bat build scripts provided by MSVC, requiring that the LIB, INCLUDE, and PATHenv variables be set to the WDK paths by some other means
+Note that installing the WDK breaks the MSVC vcvarsall.bat build scripts provided by MSVC,
+requiring that the LIB, INCLUDE, and PATHenv variables be set to the WDK paths by some other means
[](#update-external-sources)
3) Configure the glslang source tree with CMake and build it with your IDE of choice
-4) Enable the `CUSTOM_GLSLANG_BIN_PATH` and `CUSTOM_SPIRV_TOOLS_BIN_PATH` options in the Vulkan-LoaderAndValidationLayers CMake configuration and point the `GLSLANG_BINARY_PATH` and `SPIRV_TOOLS_BINARY_PATH` variables to the correct location
+4) Enable the `CUSTOM_GLSLANG_BIN_PATH` and `CUSTOM_SPIRV_TOOLS_BIN_PATH` options in the Vulkan-LoaderAndValidationLayers
+ CMake configuration and point the `GLSLANG_BINARY_PATH` and `SPIRV_TOOLS_BINARY_PATH` variables to the correct location
5) If building on Windows with MSVC, set `DISABLE_BUILDTGT_DIR_DECORATION` to _On_.
If building on Windows, but without MSVC set `DISABLE_BUILD_PATH_DECORATION` to _On_
endif(CCACHE_FOUND)
endif()
+if(APPLE)
+ # CMake versions 3 or later need CMAKE_MACOSX_RPATH defined.
+ # This avoids the CMP0042 policy message.
+ set(CMAKE_MACOSX_RPATH 1)
+ # The "install" target for MacOS fixes up bundles in place.
+ set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR})
+endif()
+
# Enable cmake folders
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(LVL_TARGET_FOLDER lvl_cmake_targets)
-if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "Darwin")
set(FALLBACK_CONFIG_DIRS "/etc/xdg" CACHE STRING
"Search path to use when XDG_CONFIG_DIRS is unset or empty or the current process is SUID/SGID. Default is freedesktop compliant.")
set(FALLBACK_DATA_DIRS "/usr/local/share:/usr/share" CACHE STRING
"Search path to use when XDG_DATA_DIRS is unset or empty or the current process is SUID/SGID. Default is freedesktop compliant.")
+endif()
+if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
include(FindPkgConfig)
option(BUILD_WSI_XCB_SUPPORT "Build XCB WSI support" ON)
option(BUILD_WSI_XLIB_SUPPORT "Build Xlib WSI support" ON)
set(COMMON_COMPILE_FLAGS "${COMMON_COMPILE_FLAGS} -Wimplicit-fallthrough=0")
endif()
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 ${COMMON_COMPILE_FLAGS}")
+ if (APPLE)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COMMON_COMPILE_FLAGS}")
+ else()
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 ${COMMON_COMPILE_FLAGS}")
+ endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMMON_COMPILE_FLAGS} -std=c++11 -fno-rtti")
if (UNIX)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")
option(BUILD_TESTS "Build tests" ON)
option(BUILD_LAYERS "Build layers" ON)
option(BUILD_DEMOS "Build demos" ON)
-option(BUILD_VKJSON "Build vkjson" ON)
+if (APPLE)
+ option(BUILD_VKJSON "Build vkjson" OFF)
+else()
+ option(BUILD_VKJSON "Build vkjson" ON)
+endif()
option(BUILD_ICD "Build icd" ON)
option(CUSTOM_GLSLANG_BIN_ROOT "Use the user defined GLSLANG_BINARY_ROOT" OFF)
option(CUSTOM_SPIRV_TOOLS_BIN_ROOT "Use the user defined SPIRV_TOOLS*BINARY_ROOT paths" OFF)
# Vulkan Ecosystem Components
-This project provides the Khronos official Vulkan ICD desktop loader and the Vulkan validation layers for Windows, Linux, and Android.
+This project provides the Khronos official Vulkan ICD desktop loader and the Vulkan validation layers for Windows, Linux, Android, and MacOS.
## CI Build Status
| Platform | Build Status |
include_directories ("${PROJECT_SOURCE_DIR}/icd/common")
link_libraries(${API_LOWERCASE} m)
+elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ add_definitions(-DVK_USE_PLATFORM_MACOS_MVK)
else()
message(FATAL_ERROR "Unsupported Platform!")
endif()
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CRT_SECURE_NO_WARNINGS -D_USE_MATH_DEFINES")
endif()
+# MacOS setup common to all demos
+if(APPLE)
+ include(macOS/common.cmake)
+endif()
+
+######################################################################################
+# vulkaninfo
+
add_executable(${API_LOWERCASE}info vulkaninfo.c)
target_link_libraries(${API_LOWERCASE}info ${LIBRARIES})
+if(APPLE)
+ set_target_properties(${API_LOWERCASE}info PROPERTIES
+ INSTALL_RPATH "@loader_path/../lib"
+ )
+ install(TARGETS ${API_LOWERCASE}info DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
+endif()
+
+# Create vulkaninfo application bundle for MacOS
+if(APPLE)
+ include(macOS/vulkaninfo/vulkaninfo.cmake)
+endif()
+
+if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
+ if(INSTALL_LVL_FILES)
+ install(TARGETS ${API_LOWERCASE}info DESTINATION ${CMAKE_INSTALL_BINDIR})
+ endif()
+endif()
+
+######################################################################################
+# cube
-if(NOT WIN32)
+if(APPLE)
+ include(macOS/cube/cube.cmake)
+elseif(NOT WIN32)
if (${CMAKE_SYSTEM_PROCESSOR} STREQUAL ${CMAKE_HOST_SYSTEM_PROCESSOR})
add_executable(cube cube.c ${PROJECT_SOURCE_DIR}/demos/cube.vert ${PROJECT_SOURCE_DIR}/demos/cube.frag cube.vert.inc cube.frag.inc)
target_link_libraries(cube ${LIBRARIES})
target_link_libraries(cube ${LIBRARIES})
endif()
-if(NOT WIN32)
+######################################################################################
+# cubepp
+
+if(APPLE)
+ include(macOS/cubepp/cubepp.cmake)
+elseif(NOT WIN32)
if (${CMAKE_SYSTEM_PROCESSOR} STREQUAL ${CMAKE_HOST_SYSTEM_PROCESSOR})
add_executable(cubepp cube.cpp ${PROJECT_SOURCE_DIR}/demos/cube.vert ${PROJECT_SOURCE_DIR}/demos/cube.frag cube.vert.inc cube.frag.inc)
target_link_libraries(cubepp ${LIBRARIES})
target_link_libraries(cubepp ${LIBRARIES})
endif()
+######################################################################################
+# smoke
+
if ((${CMAKE_SYSTEM_PROCESSOR} STREQUAL ${CMAKE_HOST_SYSTEM_PROCESSOR}))
- if ((DEMOS_WSI_SELECTION STREQUAL "XCB") OR (DEMOS_WSI_SELECTION STREQUAL "WAYLAND") OR WIN32 OR (CMAKE_SYSTEM_NAME STREQUAL "Android"))
+ if ((DEMOS_WSI_SELECTION STREQUAL "XCB") OR (DEMOS_WSI_SELECTION STREQUAL "WAYLAND") OR WIN32 OR
+ (CMAKE_SYSTEM_NAME STREQUAL "Android") OR (CMAKE_SYSTEM_NAME STREQUAL "Darwin"))
add_subdirectory(smoke)
endif()
endif()
-if(UNIX)
- if(INSTALL_LVL_FILES)
- install(TARGETS ${API_LOWERCASE}info DESTINATION ${CMAKE_INSTALL_BINDIR})
- endif()
-endif()
wl_pointer *pointer;
wl_keyboard *keyboard;
#elif defined(VK_USE_PLATFORM_MIR_KHR)
+#elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
+ void *window;
#endif
vk::SurfaceKHR surface;
platformSurfaceExtFound = 1;
extension_names[enabled_extension_count++] = VK_KHR_DISPLAY_EXTENSION_NAME;
}
+#elif defined(VK_USE_PLATFORM_IOS_MVK)
+ if (!strcmp(VK_MVK_IOS_SURFACE_EXTENSION_NAME, instance_extensions[i].extensionName)) {
+ platformSurfaceExtFound = 1;
+ extension_names[enabled_extension_count++] = VK_MVK_IOS_SURFACE_EXTENSION_NAME;
+ }
+#elif defined(VK_USE_PLATFORM_MACOS_MVK)
+ if (!strcmp(VK_MVK_MACOS_SURFACE_EXTENSION_NAME, instance_extensions[i].extensionName)) {
+ platformSurfaceExtFound = 1;
+ extension_names[enabled_extension_count++] = VK_MVK_MACOS_SURFACE_EXTENSION_NAME;
+ }
#endif
assert(enabled_extension_count < 64);
"Do you have a compatible Vulkan installable client driver (ICD) installed?\n"
"Please look at the Getting Started guide for additional information.\n",
"vkCreateInstance Failure");
+#elif defined(VK_USE_PLATFORM_IOS_MVK)
+ ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find the " VK_MVK_IOS_SURFACE_EXTENSION_NAME
+ " extension.\n\nDo you have a compatible "
+ "Vulkan installable client driver (ICD) installed?\nPlease "
+ "look at the Getting Started guide for additional "
+ "information.\n",
+ "vkCreateInstance Failure");
+#elif defined(VK_USE_PLATFORM_MACOS_MVK)
+ ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find the " VK_MVK_MACOS_SURFACE_EXTENSION_NAME
+ " extension.\n\nDo you have a compatible "
+ "Vulkan installable client driver (ICD) installed?\nPlease "
+ "look at the Getting Started guide for additional "
+ "information.\n",
+ "vkCreateInstance Failure");
#endif
}
auto const app = vk::ApplicationInfo()
auto result = inst.createXcbSurfaceKHR(&createInfo, nullptr, &surface);
VERIFY(result == vk::Result::eSuccess);
}
+#elif defined(VK_USE_PLATFORM_IOS_MVK)
+ {
+ auto const createInfo = vk::IOSSurfaceCreateInfoMVK().setPView(nullptr);
+
+ auto result = inst.createIOSSurfaceMVK(&createInfo, nullptr, &surface);
+ VERIFY(result == vk::Result::eSuccess);
+ }
+#elif defined(VK_USE_PLATFORM_MACOS_MVK)
+ {
+ auto const createInfo = vk::MacOSSurfaceCreateInfoMVK().setPView(window);
+
+ auto result = inst.createMacOSSurfaceMVK(&createInfo, nullptr, &surface);
+ VERIFY(result == vk::Result::eSuccess);
+ }
#elif defined(VK_USE_PLATFORM_DISPLAY_KHR)
{
auto result = create_display_surface();
}
bool Demo::loadTexture(const char *filename, uint8_t *rgba_data, vk::SubresourceLayout *layout, int32_t *width, int32_t *height) {
+#if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
+ filename = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@(filename)].UTF8String;
+#endif
+
FILE *fPtr = fopen(filename, "rb");
if (!fPtr) {
return false;
return validation_error;
}
+#elif defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK)
+
+// Global function invoked from NS or UI views and controllers to create demo
+static void demo_main(struct Demo &demo, void *view) {
+ const char *argv[] = {"CubeSample"};
+ int argc = sizeof(argv) / sizeof(char *);
+
+ demo.init(argc, (char **)argv);
+ demo.window = view;
+ demo.init_vk_swapchain();
+ demo.prepare();
+ demo.spin_angle = 0.4f;
+}
+
+// Global function invoked from NS or UI views and controllers on each demo frame
+static void demo_update_and_draw(struct Demo &demo) {
+ // Wait for work to finish before updating MVP.
+ vkDeviceWaitIdle(demo.device);
+ demo.update_data_buffer();
+ demo.draw();
+}
+
#else
#error "Platform not supported"
#endif
--- /dev/null
+# Set up common settings for building all demos on Apple platforms.
+
+# Source for the MoltenVK ICD library and JSON file
+set(MOLTENVK_DIR "${PROJECT_SOURCE_DIR}/external/MoltenVK")
+
+# MoltenVK JSON File
+
+# Modify the ICD JSON file to adjust the library path.
+# The ICD JSON file goes in the Resources/vulkan/icd.d directory, so adjust the
+# library_path to the relative path to the Frameworks directory in the bundle..
+# The regex does: substitute ':<whitespace>"<whitespace><all occurences of . and />' with:
+# ': "../../../Frameworks/'
+add_custom_target(MoltenVK_icd-staging-json ALL
+ COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/staging-json
+ COMMAND sed -e "/\"library_path\":/s$:[[:space:]]*\"[[:space:]]*[\\.\\/]*$: \"..\\/..\\/..\\/Frameworks\\/$"
+ ${MOLTENVK_DIR}/MoltenVK/icd/MoltenVK_icd.json >
+ ${CMAKE_CURRENT_BINARY_DIR}/staging-json/MoltenVK_icd.json
+ VERBATIM
+ DEPENDS "${MOLTENVK_DIR}/MoltenVK/icd/MoltenVK_icd.json"
+)
+set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/staging-json/MoltenVK_icd.json PROPERTIES
+ GENERATED TRUE
+)
+
+find_library(COCOA NAMES Cocoa)
+
+# Locate Interface Builder Tool, needed to build things like Storyboards outside of Xcode.
+if (NOT ${CMAKE_GENERATOR} MATCHES "^Xcode.*")
+ # Make sure we can find the 'ibtool' program. If we can NOT find it we
+ # skip generation of this project
+ find_program(IBTOOL ibtool HINTS "/usr/bin" "${OSX_DEVELOPER_ROOT}/usr/bin")
+ if (${IBTOOL} STREQUAL "IBTOOL-NOTFOUND")
+ message(SEND_ERROR
+ "ibtool can not be found and is needed to compile the .xib files. "
+ "It should have been installed with the Apple developer tools. "
+ "The default system paths were searched in addition to ${OSX_DEVELOPER_ROOT}/usr/bin."
+ )
+ endif()
+endif()
--- /dev/null
+/*
+ * AppDelegate.h
+ *
+ * Copyright (c) 2014-2018 The Brenwill Workshop Ltd. (http://www.brenwill.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import <Cocoa/Cocoa.h>
+
+@interface AppDelegate : NSObject<NSApplicationDelegate>
+
+@end
--- /dev/null
+/*
+ * AppDelegate.m
+ *
+ * Copyright (c) 2014-2018 The Brenwill Workshop Ltd. (http://www.brenwill.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "AppDelegate.h"
+
+@interface AppDelegate ()
+
+@end
+
+@implementation AppDelegate
+
+- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
+ // Insert code here to initialize your application
+}
+
+- (void)applicationWillTerminate:(NSNotification *)aNotification {
+ // Insert code here to tear down your application
+}
+
+- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {
+ return YES;
+}
+
+@end
--- /dev/null
+/*
+ * DemoViewController.h
+ *
+ * Copyright (c) 2014-2018 The Brenwill Workshop Ltd. (http://www.brenwill.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import <AppKit/AppKit.h>
+
+#pragma mark -
+#pragma mark DemoViewController
+
+/** The main view controller for the demo storyboard. */
+@interface DemoViewController : NSViewController
+@end
+
+#pragma mark -
+#pragma mark DemoView
+
+/** The Metal-compatibile view for the demo Storyboard. */
+@interface DemoView : NSView
+@end
--- /dev/null
+/*
+ * DemoViewController.m
+ *
+ * Copyright (c) 2014-2018 The Brenwill Workshop Ltd. (http://www.brenwill.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "DemoViewController.h"
+#import <QuartzCore/CAMetalLayer.h>
+
+#include <MoltenVK/mvk_vulkan.h>
+
+#include "cube.c"
+
+#pragma mark -
+#pragma mark DemoViewController
+
+@implementation DemoViewController {
+ CVDisplayLinkRef _displayLink;
+ struct demo demo;
+}
+
+- (void)dealloc {
+ demo_cleanup(&demo);
+ CVDisplayLinkRelease(_displayLink);
+ [super dealloc];
+}
+
+/** Since this is a single-view app, initialize Vulkan during view loading. */
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ self.view.wantsLayer = YES; // Back the view with a layer created by the makeBackingLayer method.
+
+ demo_main(&demo, self.view);
+
+ CVDisplayLinkCreateWithActiveCGDisplays(&_displayLink);
+ CVDisplayLinkSetOutputCallback(_displayLink, &DisplayLinkCallback, &demo);
+ CVDisplayLinkStart(_displayLink);
+}
+
+#pragma mark Display loop callback function
+
+/** Rendering loop callback function for use with a CVDisplayLink. */
+static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime,
+ CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* target) {
+ demo_update_and_draw((struct demo*)target);
+ return kCVReturnSuccess;
+}
+
+@end
+
+#pragma mark -
+#pragma mark DemoView
+
+@implementation DemoView
+
+/** Indicates that the view wants to draw using the backing layer instead of using drawRect:. */
+- (BOOL)wantsUpdateLayer {
+ return YES;
+}
+
+/** Returns a Metal-compatible layer. */
++ (Class)layerClass {
+ return [CAMetalLayer class];
+}
+
+/** If the wantsLayer property is set to YES, this method will be invoked to return a layer instance. */
+- (CALayer*)makeBackingLayer {
+ CALayer* layer = [self.class.layerClass layer];
+ CGSize viewScale = [self convertSizeToBacking:CGSizeMake(1.0, 1.0)];
+ layer.contentsScale = MIN(viewScale.width, viewScale.height);
+ return layer;
+}
+
+@end
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
+ <key>CFBundleGetInfoString</key>
+ <string>Cube</string>
+ <key>CFBundleIconFile</key>
+ <string>LunarGIcon.icns</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.lunarg.cube</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleLongVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleName</key>
+ <string>Cube</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>CSResourcesFileMapped</key>
+ <true/>
+ <key>NSHumanReadableCopyright</key>
+ <string>Copyright (c) 2018 The Khronos Group Inc. LunarG Inc. All rights reserved.</string>
+ <key>NSMainStoryboardFile</key>
+ <string>Main</string>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+</dict>
+</plist>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15G26a" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
+ <dependencies>
+ <deployment identifier="macosx"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10117"/>
+ </dependencies>
+ <scenes>
+ <!--Application-->
+ <scene sceneID="JPo-4y-FX3">
+ <objects>
+ <application id="hnw-xV-0zn" sceneMemberID="viewController">
+ <menu key="mainMenu" title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
+ <items>
+ <menuItem title="MoltenVK Demo" id="1Xt-HY-uBw">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="MoltenVK Demo" systemMenu="apple" id="uQy-DD-JDr">
+ <items>
+ <menuItem title="About Demo" id="5kV-Vb-QxS">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="orderFrontStandardAboutPanel:" target="Ady-hI-5gd" id="Exp-CZ-Vem"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
+ <menuItem title="Hide Demo" keyEquivalent="h" id="Olw-nP-bQN">
+ <connections>
+ <action selector="hide:" target="Ady-hI-5gd" id="PnN-Uc-m68"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
+ <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
+ <connections>
+ <action selector="hideOtherApplications:" target="Ady-hI-5gd" id="VT4-aY-XCT"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Show All" id="Kd2-mp-pUS">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="unhideAllApplications:" target="Ady-hI-5gd" id="Dhg-Le-xox"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
+ <menuItem title="Quit Demo" keyEquivalent="q" id="4sb-4s-VLi">
+ <connections>
+ <action selector="terminate:" target="Ady-hI-5gd" id="Te7-pn-YzF"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="Window" id="aUF-d1-5bR">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
+ <items>
+ <menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
+ <connections>
+ <action selector="performMiniaturize:" target="Ady-hI-5gd" id="VwT-WD-YPe"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Zoom" id="R4o-n2-Eq4">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="performZoom:" target="Ady-hI-5gd" id="DIl-cC-cCs"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
+ <menuItem title="Bring All to Front" id="LE2-aR-0XJ">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="arrangeInFront:" target="Ady-hI-5gd" id="DRN-fu-gQh"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="Help" id="wpr-3q-Mcd">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ">
+ <items>
+ <menuItem title="MoltenVK Demo Help" keyEquivalent="?" id="FKE-Sm-Kum">
+ <connections>
+ <action selector="showHelp:" target="Ady-hI-5gd" id="y7X-2Q-9no"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ </items>
+ </menu>
+ <connections>
+ <outlet property="delegate" destination="Voe-Tx-rLC" id="PrD-fu-P6m"/>
+ </connections>
+ </application>
+ <customObject id="Voe-Tx-rLC" customClass="AppDelegate"/>
+ <customObject id="Ady-hI-5gd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="83.5" y="-47"/>
+ </scene>
+ <!--Window Controller-->
+ <scene sceneID="R2V-B0-nI4">
+ <objects>
+ <windowController id="B8D-0N-5wS" sceneMemberID="viewController">
+ <window key="window" title="MoltenVK Demo" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="default" id="IQv-IB-iLA">
+ <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
+ <rect key="contentRect" x="1051" y="656" width="300" height="200"/>
+ <rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
+ <value key="minSize" type="size" width="300" height="200"/>
+ </window>
+ <connections>
+ <segue destination="XfG-lQ-9wD" kind="relationship" relationship="window.shadowedContentViewController" id="cq2-FE-JQM"/>
+ </connections>
+ </windowController>
+ <customObject id="Oky-zY-oP4" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="83" y="146"/>
+ </scene>
+ <!--Demo View Controller-->
+ <scene sceneID="hIz-AP-VOD">
+ <objects>
+ <viewController id="XfG-lQ-9wD" customClass="DemoViewController" sceneMemberID="viewController">
+ <view key="view" id="m2S-Jp-Qdl" customClass="DemoView">
+ <rect key="frame" x="0.0" y="0.0" width="400" height="300"/>
+ <autoresizingMask key="autoresizingMask"/>
+ </view>
+ </viewController>
+ <customObject id="rPt-NT-nkU" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="83" y="564"/>
+ </scene>
+ </scenes>
+</document>
--- /dev/null
+# Cube Application Bundle
+
+set(cube_SRCS
+ ${CMAKE_CURRENT_SOURCE_DIR}/macOS/cube/main.m
+ ${CMAKE_CURRENT_SOURCE_DIR}/macOS/cube/AppDelegate.m
+ ${CMAKE_CURRENT_SOURCE_DIR}/macOS/cube/DemoViewController.m
+)
+set(cube_HDRS
+ ${CMAKE_CURRENT_SOURCE_DIR}/macOS/cube/AppDelegate.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/macOS/cube/DemoViewController.h
+)
+set(cube_RESOURCES
+ ${CMAKE_CURRENT_SOURCE_DIR}/lunarg.ppm
+ ${CMAKE_CURRENT_BINARY_DIR}/staging-json/MoltenVK_icd.json
+ ${CMAKE_CURRENT_SOURCE_DIR}/macOS/cube/Resources/LunarGIcon.icns
+)
+
+# Have Xcode handle the Storyboard
+if(${CMAKE_GENERATOR} MATCHES "^Xcode.*")
+ set(cube_RESOURCES ${cube_RESOURCES}
+ ${CMAKE_CURRENT_SOURCE_DIR}/macOS/cube/Resources/Main.storyboard
+ )
+endif()
+
+add_executable(cube MACOSX_BUNDLE
+ ${cube_SRCS}
+ ${cube_HDRS}
+ ${cube_RESOURCES}
+ cube.vert.inc cube.frag.inc
+)
+
+# Handle the Storyboard ourselves
+if(NOT ${CMAKE_GENERATOR} MATCHES "^Xcode.*")
+ # Compile the storyboard file with the ibtool.
+ add_custom_command(TARGET cube POST_BUILD
+ COMMAND ${IBTOOL} --errors --warnings --notices --output-format human-readable-text
+ --compile ${CMAKE_CURRENT_BINARY_DIR}/cube.app/Contents/Resources/Main.storyboardc
+ ${CMAKE_CURRENT_SOURCE_DIR}/macOS/cube/Resources/Main.storyboard
+ COMMENT "Compiling storyboard"
+ )
+endif()
+
+add_dependencies(cube MoltenVK_icd-staging-json)
+
+# Include demo source code dir because the MacOS cube's Objective-C source includes
+# the "original" cube application C source code.
+# Also include the MoltenVK helper files.
+target_include_directories(cube PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${MOLTENVK_DIR}/MoltenVK/include
+)
+
+target_link_libraries(cube ${LIBRARIES} "-framework Cocoa -framework QuartzCore")
+
+set_target_properties(cube PROPERTIES
+ MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/macOS/cube/Info.plist
+)
+
+# The RESOURCE target property cannot be used in conjunction with the MACOSX_PACKAGE_LOCATION
+# property. We need fine-grained control over the Resource directory, so we have to specify
+# the destination of all the resource files on a per-destination-directory basis.
+# If all the files went into the top-level Resource directory, then we could simply set
+# the RESOURCE property to a list of all the resource files.
+set_source_files_properties(${cube_RESOURCES} PROPERTIES
+ MACOSX_PACKAGE_LOCATION "Resources"
+)
+set_source_files_properties("${CMAKE_CURRENT_BINARY_DIR}/staging-json/MoltenVK_icd.json" PROPERTIES
+ MACOSX_PACKAGE_LOCATION "Resources/vulkan/icd.d"
+)
+
+# Copy the MoltenVK lib into the bundle.
+if(${CMAKE_GENERATOR} MATCHES "^Xcode.*")
+ add_custom_command(TARGET cube POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy "${MOLTENVK_DIR}/MoltenVK/MacOS/libMoltenVK.dylib"
+ ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/cube.app/Contents/Frameworks/libMoltenVK.dylib
+ DEPENDS vulkan
+ )
+else()
+ add_custom_command(TARGET cube POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy "${MOLTENVK_DIR}/MoltenVK/MacOS/libMoltenVK.dylib"
+ ${CMAKE_CURRENT_BINARY_DIR}/cube.app/Contents/Frameworks/libMoltenVK.dylib
+ DEPENDS vulkan
+ )
+endif()
+
+# Fix up the library search path in the executable to find (loader) libraries in the bundle.
+install(CODE "
+ include(BundleUtilities)
+ fixup_bundle(${CMAKE_INSTALL_PREFIX}/demos/cube.app \"\" \"\")
+ " COMPONENT Runtime
+)
+
+# Not sure this is needed. When activated, it makes a symlink from
+# libvulkan.dylib to libvulkan.1.dylib (which in turn symlinks to libvulkan.1.0.xx.dylib.)
+# install(FILES
+# "${CMAKE_BINARY_DIR}/loader/libvulkan.dylib"
+# DESTINATION "demos/cube.app/Contents/MacOS"
+# COMPONENT Runtime)
--- /dev/null
+/*
+ * main.m
+ *
+ * Copyright (c) 2014-2018 The Brenwill Workshop Ltd. (http://www.brenwill.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import <Cocoa/Cocoa.h>
+
+int main(int argc, const char* argv[]) { return NSApplicationMain(argc, argv); }
--- /dev/null
+/*
+ * AppDelegate.h
+ *
+ * Copyright (c) 2014-2018 The Brenwill Workshop Ltd. (http://www.brenwill.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import <Cocoa/Cocoa.h>
+
+@interface AppDelegate : NSObject<NSApplicationDelegate>
+
+@end
--- /dev/null
+/*
+ * AppDelegate.m
+ *
+ * Copyright (c) 2014-2018 The Brenwill Workshop Ltd. (http://www.brenwill.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "AppDelegate.h"
+
+@interface AppDelegate ()
+
+@end
+
+@implementation AppDelegate
+
+- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
+ // Insert code here to initialize your application
+}
+
+- (void)applicationWillTerminate:(NSNotification *)aNotification {
+ // Insert code here to tear down your application
+}
+
+- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {
+ return YES;
+}
+
+@end
--- /dev/null
+/*
+ * DemoViewController.h
+ *
+ * Copyright (c) 2014-2018 The Brenwill Workshop Ltd. (http://www.brenwill.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import <AppKit/AppKit.h>
+
+#pragma mark -
+#pragma mark DemoViewController
+
+/** The main view controller for the demo storyboard. */
+@interface DemoViewController : NSViewController
+@end
+
+#pragma mark -
+#pragma mark DemoView
+
+/** The Metal-compatibile view for the demo Storyboard. */
+@interface DemoView : NSView
+@end
--- /dev/null
+/*
+ * DemoViewController.m
+ *
+ * Copyright (c) 2014-2018 The Brenwill Workshop Ltd. (http://www.brenwill.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "DemoViewController.h"
+#import <QuartzCore/CAMetalLayer.h>
+
+#include <MoltenVK/mvk_vulkan.h>
+
+#include "cube.cpp"
+
+#pragma mark -
+#pragma mark DemoViewController
+
+@implementation DemoViewController {
+ CVDisplayLinkRef _displayLink;
+ struct Demo demo;
+}
+
+- (void)dealloc {
+ demo.cleanup();
+ CVDisplayLinkRelease(_displayLink);
+ [super dealloc];
+}
+
+/** Since this is a single-view app, initialize Vulkan during view loading. */
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ self.view.wantsLayer = YES; // Back the view with a layer created by the makeBackingLayer method.
+
+ demo_main(demo, self.view);
+
+ CVDisplayLinkCreateWithActiveCGDisplays(&_displayLink);
+ CVDisplayLinkSetOutputCallback(_displayLink, &DisplayLinkCallback, &demo);
+ CVDisplayLinkStart(_displayLink);
+}
+
+#pragma mark Display loop callback function
+
+/** Rendering loop callback function for use with a CVDisplayLink. */
+static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime,
+ CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* target) {
+ demo_update_and_draw(reinterpret_cast<struct Demo&>(*(struct Demo*)target));
+ return kCVReturnSuccess;
+}
+
+@end
+
+#pragma mark -
+#pragma mark DemoView
+
+@implementation DemoView
+
+/** Indicates that the view wants to draw using the backing layer instead of using drawRect:. */
+- (BOOL)wantsUpdateLayer {
+ return YES;
+}
+
+/** Returns a Metal-compatible layer. */
++ (Class)layerClass {
+ return [CAMetalLayer class];
+}
+
+/** If the wantsLayer property is set to YES, this method will be invoked to return a layer instance. */
+- (CALayer*)makeBackingLayer {
+ CALayer* layer = [self.class.layerClass layer];
+ CGSize viewScale = [self convertSizeToBacking:CGSizeMake(1.0, 1.0)];
+ layer.contentsScale = MIN(viewScale.width, viewScale.height);
+ return layer;
+}
+
+@end
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
+ <key>CFBundleGetInfoString</key>
+ <string>Cubepp</string>
+ <key>CFBundleIconFile</key>
+ <string>LunarGIcon.icns</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.lunarg.cubepp</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleLongVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleName</key>
+ <string>Cubepp</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>CSResourcesFileMapped</key>
+ <true/>
+ <key>NSHumanReadableCopyright</key>
+ <string>Copyright (c) 2018 The Khronos Group Inc. LunarG Inc. All rights reserved.</string>
+ <key>NSMainStoryboardFile</key>
+ <string>Main</string>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+</dict>
+</plist>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15G26a" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
+ <dependencies>
+ <deployment identifier="macosx"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10117"/>
+ </dependencies>
+ <scenes>
+ <!--Application-->
+ <scene sceneID="JPo-4y-FX3">
+ <objects>
+ <application id="hnw-xV-0zn" sceneMemberID="viewController">
+ <menu key="mainMenu" title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
+ <items>
+ <menuItem title="MoltenVK Demo" id="1Xt-HY-uBw">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="MoltenVK Demo" systemMenu="apple" id="uQy-DD-JDr">
+ <items>
+ <menuItem title="About Demo" id="5kV-Vb-QxS">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="orderFrontStandardAboutPanel:" target="Ady-hI-5gd" id="Exp-CZ-Vem"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
+ <menuItem title="Hide Demo" keyEquivalent="h" id="Olw-nP-bQN">
+ <connections>
+ <action selector="hide:" target="Ady-hI-5gd" id="PnN-Uc-m68"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
+ <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
+ <connections>
+ <action selector="hideOtherApplications:" target="Ady-hI-5gd" id="VT4-aY-XCT"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Show All" id="Kd2-mp-pUS">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="unhideAllApplications:" target="Ady-hI-5gd" id="Dhg-Le-xox"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
+ <menuItem title="Quit Demo" keyEquivalent="q" id="4sb-4s-VLi">
+ <connections>
+ <action selector="terminate:" target="Ady-hI-5gd" id="Te7-pn-YzF"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="Window" id="aUF-d1-5bR">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
+ <items>
+ <menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
+ <connections>
+ <action selector="performMiniaturize:" target="Ady-hI-5gd" id="VwT-WD-YPe"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Zoom" id="R4o-n2-Eq4">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="performZoom:" target="Ady-hI-5gd" id="DIl-cC-cCs"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
+ <menuItem title="Bring All to Front" id="LE2-aR-0XJ">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="arrangeInFront:" target="Ady-hI-5gd" id="DRN-fu-gQh"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="Help" id="wpr-3q-Mcd">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ">
+ <items>
+ <menuItem title="MoltenVK Demo Help" keyEquivalent="?" id="FKE-Sm-Kum">
+ <connections>
+ <action selector="showHelp:" target="Ady-hI-5gd" id="y7X-2Q-9no"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ </items>
+ </menu>
+ <connections>
+ <outlet property="delegate" destination="Voe-Tx-rLC" id="PrD-fu-P6m"/>
+ </connections>
+ </application>
+ <customObject id="Voe-Tx-rLC" customClass="AppDelegate"/>
+ <customObject id="Ady-hI-5gd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="83.5" y="-47"/>
+ </scene>
+ <!--Window Controller-->
+ <scene sceneID="R2V-B0-nI4">
+ <objects>
+ <windowController id="B8D-0N-5wS" sceneMemberID="viewController">
+ <window key="window" title="MoltenVK Demo" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="default" id="IQv-IB-iLA">
+ <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
+ <rect key="contentRect" x="1051" y="656" width="300" height="200"/>
+ <rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
+ <value key="minSize" type="size" width="300" height="200"/>
+ </window>
+ <connections>
+ <segue destination="XfG-lQ-9wD" kind="relationship" relationship="window.shadowedContentViewController" id="cq2-FE-JQM"/>
+ </connections>
+ </windowController>
+ <customObject id="Oky-zY-oP4" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="83" y="146"/>
+ </scene>
+ <!--Demo View Controller-->
+ <scene sceneID="hIz-AP-VOD">
+ <objects>
+ <viewController id="XfG-lQ-9wD" customClass="DemoViewController" sceneMemberID="viewController">
+ <view key="view" id="m2S-Jp-Qdl" customClass="DemoView">
+ <rect key="frame" x="0.0" y="0.0" width="400" height="300"/>
+ <autoresizingMask key="autoresizingMask"/>
+ </view>
+ </viewController>
+ <customObject id="rPt-NT-nkU" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="83" y="564"/>
+ </scene>
+ </scenes>
+</document>
--- /dev/null
+# Cube Application Bundle
+
+set(cubepp_SRCS
+ ${CMAKE_CURRENT_SOURCE_DIR}/macOS/cubepp/main.mm
+ ${CMAKE_CURRENT_SOURCE_DIR}/macOS/cubepp/AppDelegate.mm
+ ${CMAKE_CURRENT_SOURCE_DIR}/macOS/cubepp/DemoViewController.mm
+)
+set(cubepp_HDRS
+ ${CMAKE_CURRENT_SOURCE_DIR}/macOS/cubepp/AppDelegate.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/macOS/cubepp/DemoViewController.h
+)
+set(cubepp_RESOURCES
+ ${CMAKE_CURRENT_SOURCE_DIR}/lunarg.ppm
+ ${CMAKE_CURRENT_BINARY_DIR}/staging-json/MoltenVK_icd.json
+ ${CMAKE_CURRENT_SOURCE_DIR}/macOS/cubepp/Resources/LunarGIcon.icns
+)
+
+# Have Xcode handle the Storyboard
+if(${CMAKE_GENERATOR} MATCHES "^Xcode.*")
+ set(cubepp_RESOURCES ${cubepp_RESOURCES}
+ ${CMAKE_CURRENT_SOURCE_DIR}/macOS/cubepp/Resources/Main.storyboard
+ )
+endif()
+
+add_executable(cubepp MACOSX_BUNDLE
+ ${cubepp_SRCS}
+ ${cubepp_HDRS}
+ ${cubepp_RESOURCES}
+ cube.vert.inc cube.frag.inc
+)
+
+# Handle the Storyboard ourselves
+if(NOT ${CMAKE_GENERATOR} MATCHES "^Xcode.*")
+ # Compile the storyboard file with the ibtool.
+ add_custom_command(TARGET cubepp POST_BUILD
+ COMMAND ${IBTOOL} --errors --warnings --notices --output-format human-readable-text
+ --compile ${CMAKE_CURRENT_BINARY_DIR}/cubepp.app/Contents/Resources/Main.storyboardc
+ ${CMAKE_CURRENT_SOURCE_DIR}/macOS/cubepp/Resources/Main.storyboard
+ COMMENT "Compiling storyboard"
+ )
+endif()
+
+add_dependencies(cubepp MoltenVK_icd-staging-json)
+
+# Include demo source code dir because the MacOS cubepp's Objective-C source includes
+# the "original" cubepp application C++ source code.
+# Also include the MoltenVK helper files.
+target_include_directories(cubepp PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${MOLTENVK_DIR}/MoltenVK/include
+)
+
+target_link_libraries(cubepp ${LIBRARIES} "-framework Cocoa -framework QuartzCore")
+
+set_target_properties(cubepp PROPERTIES
+ MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/macOS/cubepp/Info.plist
+)
+
+# The RESOURCE target property cannot be used in conjunction with the MACOSX_PACKAGE_LOCATION
+# property. We need fine-grained control over the Resource directory, so we have to specify
+# the destination of all the resource files on a per-destination-directory basis.
+# If all the files went into the top-level Resource directory, then we could simply set
+# the RESOURCE property to a list of all the resource files.
+set_source_files_properties(${cubepp_RESOURCES} PROPERTIES
+ MACOSX_PACKAGE_LOCATION "Resources"
+)
+set_source_files_properties("${CMAKE_CURRENT_BINARY_DIR}/staging-json/MoltenVK_icd.json" PROPERTIES
+ MACOSX_PACKAGE_LOCATION "Resources/vulkan/icd.d"
+)
+
+# Direct the MoltenVK library to the right place.
+install(FILES "${MOLTENVK_DIR}/MoltenVK/MacOS/libMoltenVK.dylib"
+ DESTINATION "demos/cubepp.app/Contents/Frameworks"
+ COMPONENT Runtime
+)
+
+# Copy the MoltenVK lib into the bundle.
+if(${CMAKE_GENERATOR} MATCHES "^Xcode.*")
+ add_custom_command(TARGET cubepp POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy "${MOLTENVK_DIR}/MoltenVK/MacOS/libMoltenVK.dylib"
+ ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/cubepp.app/Contents/Frameworks/libMoltenVK.dylib
+ DEPENDS vulkan
+ )
+else()
+ add_custom_command(TARGET cubepp POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy "${MOLTENVK_DIR}/MoltenVK/MacOS/libMoltenVK.dylib"
+ ${CMAKE_CURRENT_BINARY_DIR}/cubepp.app/Contents/Frameworks/libMoltenVK.dylib
+ DEPENDS vulkan
+ )
+endif()
+
+# Fix up the library search path in the executable to find (loader) libraries in the bundle.
+install(CODE "
+ include(BundleUtilities)
+ fixup_bundle(${CMAKE_INSTALL_PREFIX}/demos/cubepp.app \"\" \"\")
+ " COMPONENT Runtime
+)
+
+# Not sure this is needed. When activated, it makes a symlink from
+# libvulkan.dylib to libvulkan.1.dylib (which in turn symlinks to libvulkan.1.0.xx.dylib.)
+# install(FILES
+# "${CMAKE_BINARY_DIR}/loader/libvulkan.dylib"
+# DESTINATION "demos/cubepp.app/Contents/MacOS"
+# COMPONENT Runtime)
--- /dev/null
+/*
+ * main.m
+ *
+ * Copyright (c) 2014-2018 The Brenwill Workshop Ltd. (http://www.brenwill.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import <Cocoa/Cocoa.h>
+
+int main(int argc, const char* argv[]) { return NSApplicationMain(argc, argv); }
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>vulkaninfo.sh</string>
+ <key>CFBundleGetInfoString</key>
+ <string>VulkanInfo</string>
+ <key>CFBundleIconFile</key>
+ <string>LunarGIcon.icns</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.lunarg.vulkaninfo</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleLongVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleName</key>
+ <string>VulkanInfo</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>CSResourcesFileMapped</key>
+ <true/>
+ <key>NSHumanReadableCopyright</key>
+ <string>Copyright (c) 2018 The Khronos Group Inc. LunarG Inc. All rights reserved.</string>
+</dict>
+</plist>
--- /dev/null
+# Vulkaninfo Application Bundle
+
+# We already have a "vulkaninfo" target, so create a new target with a different name
+# and use the OUTPUT_NAME property to rename the target to the desired name.
+# The standalone binary is called "vulkaninfo" and the bundle is called "vulkaninfo.app".
+# Note that the executable is a script that launches Terminal to see the output.
+add_executable(vulkaninfo-bundle MACOSX_BUNDLE
+ vulkaninfo.c
+ ${CMAKE_CURRENT_BINARY_DIR}/staging-json/MoltenVK_icd.json
+ ${CMAKE_CURRENT_SOURCE_DIR}/macOS/vulkaninfo/vulkaninfo.sh
+ ${CMAKE_CURRENT_SOURCE_DIR}/macOS/vulkaninfo/Resources/LunarGIcon.icns
+)
+set_target_properties(vulkaninfo-bundle PROPERTIES
+ OUTPUT_NAME vulkaninfo
+ MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/macOS/vulkaninfo/Info.plist
+)
+target_link_libraries(vulkaninfo-bundle ${LIBRARIES})
+add_dependencies(vulkaninfo-bundle MoltenVK_icd-staging-json)
+set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/macOS/vulkaninfo/vulkaninfo.sh PROPERTIES
+ MACOSX_PACKAGE_LOCATION "MacOS"
+)
+set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/macOS/vulkaninfo/Resources/LunarGIcon.icns PROPERTIES
+ MACOSX_PACKAGE_LOCATION "Resources"
+)
+# Direct the MoltenVK library to the right place.
+install(FILES "${MOLTENVK_DIR}/MoltenVK/MacOS/libMoltenVK.dylib"
+ DESTINATION "demos/vulkaninfo.app/Contents/Frameworks"
+ COMPONENT Runtime
+)
+# Xcode projects need some extra help with what would be install steps.
+if(${CMAKE_GENERATOR} MATCHES "^Xcode.*")
+ add_custom_command(TARGET vulkaninfo-bundle POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy "${MOLTENVK_DIR}/MoltenVK/MacOS/libMoltenVK.dylib"
+ ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/vulkaninfo.app/Contents/Frameworks/libMoltenVK.dylib
+ DEPENDS vulkan
+ )
+else()
+ add_custom_command(TARGET vulkaninfo-bundle POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy "${MOLTENVK_DIR}/MoltenVK/MacOS/libMoltenVK.dylib"
+ ${CMAKE_CURRENT_BINARY_DIR}/vulkaninfo.app/Contents/Frameworks/libMoltenVK.dylib
+ DEPENDS vulkan
+ )
+endif()
+
+# Fix up the library search path in the executable to find (loader) libraries in the bundle.
+# When fixup_bundle() is passed a bundle in the first argument, it looks at the Info.plist file
+# to determine the BundleExecutable. In this case, the executable is a script, which can't be fixed up.
+# Instead pass it the explicit name of the executable.
+install(CODE "
+ include(BundleUtilities)
+ fixup_bundle(${CMAKE_INSTALL_PREFIX}/demos/vulkaninfo.app/Contents/MacOS/vulkaninfo \"\" \"\")
+ " COMPONENT Runtime
+)
--- /dev/null
+#!/bin/bash
+BASEDIR=`dirname $0`
+open /Applications/Utilities/Terminal.app $BASEDIR/vulkaninfo
set(libraries PRIVATE ${CMAKE_THREAD_LIBS_INIT})
if(TARGET vulkan)
- list(APPEND definitions PRIVATE -DUNINSTALLED_LOADER="$<TARGET_FILE:vulkan>")
+ if(APPLE)
+ # For macOS, the "uninstalled" location is in the bundle
+ list(APPEND definitions PRIVATE -DUNINSTALLED_LOADER="./libvulkan.1.dylib")
+ else()
+ list(APPEND definitions PRIVATE -DUNINSTALLED_LOADER="$<TARGET_FILE:vulkan>")
+ endif()
endif()
if(WIN32)
list(APPEND definitions PRIVATE -DWIN32_LEAN_AND_MEAN)
list(APPEND sources ShellWin32.cpp ShellWin32.h)
-else()
+elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
list(APPEND libraries PRIVATE -ldl -lrt)
if(BUILD_WSI_XCB_SUPPORT AND DEMOS_WSI_SELECTION STREQUAL "XCB")
list(APPEND includes PRIVATE ${WAYLAND_CLIENT_INCLUDE_DIR})
list(APPEND libraries PRIVATE ${WAYLAND_CLIENT_LIBRARIES})
endif()
+elseif(APPLE)
+ set(LIBRARIES)
+ list(APPEND sources
+ macOS/AppDelegate.h macOS/AppDelegate.m
+ macOS/DemoViewController.h macOS/DemoViewController.mm
+ macOS/main.m macOS/ShellMVK.cpp macOS/ShellMVK.h
+ )
+ list(APPEND includes
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${MOLTENVK_DIR}/MoltenVK/include)
+ list(APPEND libraries
+ "-framework Cocoa -framework QuartzCore")
+ set(smoketest_RESOURCES
+ ${CMAKE_BINARY_DIR}/demos/staging-json/MoltenVK_icd.json
+ ${CMAKE_CURRENT_SOURCE_DIR}/macOS/Resources/LunarGIcon.icns
+ ${CMAKE_CURRENT_SOURCE_DIR}/macOS/Resources/Main.storyboard
+ )
+ set_source_files_properties(${CMAKE_BINARY_DIR}/demos/staging-json/MoltenVK_icd.json PROPERTIES
+ GENERATED TRUE
+ )
+ # Have Xcode handle the Storyboard
+ if(${CMAKE_GENERATOR} MATCHES "^Xcode.*")
+ list(APPEND sources
+ macOS/Resources/Main.storyboard
+ )
+ endif()
endif()
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/..)
-add_executable(smoketest ${sources})
+add_executable(smoketest MACOSX_BUNDLE ${sources} ${smoketest_RESOURCES})
target_compile_definitions(smoketest ${definitions})
target_include_directories(smoketest ${includes})
target_link_libraries(smoketest ${libraries})
+if(APPLE)
+ # Handle the Storyboard ourselves
+ if(NOT ${CMAKE_GENERATOR} MATCHES "^Xcode.*")
+ # Compile the storyboard file with the ibtool.
+ add_custom_command(TARGET smoketest POST_BUILD
+ COMMAND ${IBTOOL} --errors --warnings --notices --output-format human-readable-text
+ --compile ${CMAKE_CURRENT_BINARY_DIR}/../smoketest.app/Contents/Resources/Main.storyboardc
+ ${CMAKE_CURRENT_SOURCE_DIR}/macOS/Resources/Main.storyboard
+ COMMENT "Compiling storyboard"
+ )
+ endif()
+
+ add_dependencies(smoketest MoltenVK_icd-staging-json)
+
+ set_target_properties(smoketest PROPERTIES
+ MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/macOS/Info.plist
+ )
+ set_source_files_properties(${smoketest_RESOURCES} PROPERTIES
+ MACOSX_PACKAGE_LOCATION "Resources"
+ )
+ set_source_files_properties("${CMAKE_BINARY_DIR}/demos/staging-json/MoltenVK_icd.json" PROPERTIES
+ MACOSX_PACKAGE_LOCATION "Resources/vulkan/icd.d"
+ )
+
+ # Direct the MoltenVK library to the right place.
+ install(FILES "${MOLTENVK_DIR}/MoltenVK/MacOS/libMoltenVK.dylib"
+ DESTINATION "demos/smoketest.app/Contents/Frameworks"
+ COMPONENT Runtime
+ )
+
+ # Xcode projects need some extra help with what would be install steps.
+ # Vulkan lib needs to be copied manually since smoke does not link it.
+ if(${CMAKE_GENERATOR} MATCHES "^Xcode.*")
+ add_custom_command(TARGET smoketest POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy "$<TARGET_FILE:vulkan>"
+ ${CMAKE_CURRENT_BINARY_DIR}/../$<CONFIG>/smoketest.app/Contents/MacOS/libvulkan.1.dylib
+ COMMAND ${CMAKE_COMMAND} -E copy "${MOLTENVK_DIR}/MoltenVK/MacOS/libMoltenVK.dylib"
+ ${CMAKE_CURRENT_BINARY_DIR}/../$<CONFIG>/smoketest.app/Contents/Frameworks/libMoltenVK.dylib
+ DEPENDS vulkan
+ )
+ else()
+ add_custom_command(TARGET smoketest POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy "$<TARGET_FILE:vulkan>"
+ ${CMAKE_CURRENT_BINARY_DIR}/../smoketest.app/Contents/MacOS/libvulkan.1.dylib
+ COMMAND ${CMAKE_COMMAND} -E copy "${MOLTENVK_DIR}/MoltenVK/MacOS/libMoltenVK.dylib"
+ ${CMAKE_CURRENT_BINARY_DIR}/../smoketest.app/Contents/Frameworks/libMoltenVK.dylib
+ DEPENDS vulkan
+ )
+ endif()
+
+ # Fix up the library search path in the executable to find (loader) libraries in the bundle.
+ install(CODE "
+ include(BundleUtilities)
+ fixup_bundle(${CMAKE_INSTALL_PREFIX}/demos/smoketest.app \"\" \"\")
+ " COMPONENT Runtime
+ )
+endif()
+
if(UNIX)
if(INSTALL_LVL_FILES)
install(TARGETS smoketest DESTINATION ${CMAKE_INSTALL_BINDIR})
Game *create_game(const std::vector<std::string> &args) { return new Smoke(args); }
#endif
+#if !defined(VK_USE_PLATFORM_MACOS_MVK)
Game *create_game(int argc, char **argv) {
std::vector<std::string> args(argv, argv + argc);
return new Smoke(args);
}
+#endif
} // namespace
Command(name='DebugReportMessageEXT', dispatch='VkInstance'),
])
+vk_mvk_ios_surface = Extension(name='VK_MVK_ios_surface', version=1, guard='VK_USE_PLATFORM_IOS_MVK', commands=[
+ Command(name='CreateIOSSurfaceMVK', dispatch='VkInstance'),
+])
+
+vk_mvk_macos_surface = Extension(name='VK_MVK_macos_surface', version=1, guard='VK_USE_PLATFORM_MACOS_MVK', commands=[
+ Command(name='CreateMacOSSurfaceMVK', dispatch='VkInstance'),
+])
+
extensions = [
vk_core,
vk_khr_surface,
vk_khr_android_surface,
vk_khr_win32_surface,
vk_ext_debug_report,
+ vk_mvk_ios_surface,
+ vk_mvk_macos_surface,
]
def generate_header(guard):
--- /dev/null
+/*
+ * AppDelegate.h
+ *
+ * Copyright (c) 2014-2018 The Brenwill Workshop Ltd. (http://www.brenwill.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import <Cocoa/Cocoa.h>
+
+@interface AppDelegate : NSObject<NSApplicationDelegate>
+
+@end
--- /dev/null
+/*
+ * AppDelegate.m
+ *
+ * Copyright (c) 2014-2018 The Brenwill Workshop Ltd. (http://www.brenwill.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "AppDelegate.h"
+
+@interface AppDelegate ()
+
+@end
+
+@implementation AppDelegate
+
+- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
+ // Insert code here to initialize your application
+}
+
+- (void)applicationWillTerminate:(NSNotification *)aNotification {
+ // Insert code here to tear down your application
+}
+
+- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {
+ return YES;
+}
+
+@end
--- /dev/null
+/*
+ * DemoViewController.h
+ *
+ * Copyright (c) 2014-2018 The Brenwill Workshop Ltd. (http://www.brenwill.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import <AppKit/AppKit.h>
+
+#pragma mark -
+#pragma mark DemoViewController
+
+/** The main view controller for the demo storyboard. */
+@interface DemoViewController : NSViewController
+@end
+
+#pragma mark -
+#pragma mark DemoView
+
+/** The Metal-compatibile view for the demo Storyboard. */
+@interface DemoView : NSView
+@end
--- /dev/null
+/*
+ * DemoViewController.mm
+ *
+ * Copyright (c) 2014-2018 The Brenwill Workshop Ltd. (http://www.brenwill.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "DemoViewController.h"
+#import <QuartzCore/CAMetalLayer.h>
+
+#include "ShellMVK.h"
+#include "Smoke.h"
+
+#pragma mark -
+#pragma mark DemoViewController
+
+@implementation DemoViewController {
+ CVDisplayLinkRef _displayLink;
+ ShellMVK* _shell;
+ Game* _game;
+}
+
+- (void)dealloc {
+ delete _shell;
+ delete _game;
+ CVDisplayLinkRelease(_displayLink);
+ [super dealloc];
+}
+
+/** Since this is a single-view app, initialize Vulkan during view loading. */
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ self.view.wantsLayer = YES; // Back the view with a layer created by the makeBackingLayer method.
+
+ std::vector<std::string> args;
+ // args.push_back("-p"); // Uncomment to use push constants
+ // args.push_back("-s"); // Uncomment to use a single thread
+ _game = new Smoke(args);
+
+ _shell = new ShellMVK(*_game);
+ _shell->run(self.view);
+
+ CVDisplayLinkCreateWithActiveCGDisplays(&_displayLink);
+ CVDisplayLinkSetOutputCallback(_displayLink, &DisplayLinkCallback, _shell);
+ CVDisplayLinkStart(_displayLink);
+}
+
+#pragma mark Display loop callback function
+
+/** Rendering loop callback function for use with a CVDisplayLink. */
+static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime,
+ CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* target) {
+ ((ShellMVK*)target)->update_and_draw();
+ return kCVReturnSuccess;
+}
+
+- (void)viewDidAppear {
+ self.view.window.initialFirstResponder = self.view;
+}
+
+// Delegated from the view as first responder.
+- (void)keyDown:(NSEvent*)theEvent {
+ Game::Key key;
+ switch (theEvent.keyCode) {
+ case 53:
+ key = Game::KEY_ESC;
+ break;
+ case 126:
+ key = Game::KEY_UP;
+ break;
+ case 125:
+ key = Game::KEY_DOWN;
+ break;
+ case 49:
+ key = Game::KEY_SPACE;
+ break;
+ default:
+ key = Game::KEY_UNKNOWN;
+ break;
+ }
+
+ _game->on_key(key);
+}
+
+@end
+
+#pragma mark -
+#pragma mark DemoView
+
+@implementation DemoView
+
+/** Indicates that the view wants to draw using the backing layer instead of using drawRect:. */
+- (BOOL)wantsUpdateLayer {
+ return YES;
+}
+
+/** Returns a Metal-compatible layer. */
++ (Class)layerClass {
+ return [CAMetalLayer class];
+}
+
+/** If the wantsLayer property is set to YES, this method will be invoked to return a layer instance. */
+- (CALayer*)makeBackingLayer {
+ CALayer* layer = [self.class.layerClass layer];
+ CGSize viewScale = [self convertSizeToBacking:CGSizeMake(1.0, 1.0)];
+ layer.contentsScale = MIN(viewScale.width, viewScale.height);
+ return layer;
+}
+
+- (BOOL)acceptsFirstResponder {
+ return YES;
+}
+
+@end
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleExecutable</key>
+ <string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
+ <key>CFBundleIconFile</key>
+ <string>LunarGIcon.icns</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.lunarg.smoketest</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>LSApplicationCategoryType</key>
+ <string></string>
+ <key>LSMinimumSystemVersion</key>
+ <string>${MACOSX_DEPLOYMENT_TARGET}</string>
+ <key>NSHumanReadableCopyright</key>
+ <string>Copyright (c) 2015-2017 The Brenwill Workshop Ltd. All rights reserved.</string>
+ <key>NSMainStoryboardFile</key>
+ <string>Main</string>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+</dict>
+</plist>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15E65" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
+ <dependencies>
+ <deployment identifier="macosx"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10117"/>
+ </dependencies>
+ <scenes>
+ <!--Application-->
+ <scene sceneID="JPo-4y-FX3">
+ <objects>
+ <application id="hnw-xV-0zn" sceneMemberID="viewController">
+ <menu key="mainMenu" title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
+ <items>
+ <menuItem title="MoltenVK Demo" id="1Xt-HY-uBw">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="MoltenVK Demo" systemMenu="apple" id="uQy-DD-JDr">
+ <items>
+ <menuItem title="About Demo" id="5kV-Vb-QxS">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="orderFrontStandardAboutPanel:" target="Ady-hI-5gd" id="Exp-CZ-Vem"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
+ <menuItem title="Hide Demo" keyEquivalent="h" id="Olw-nP-bQN">
+ <connections>
+ <action selector="hide:" target="Ady-hI-5gd" id="PnN-Uc-m68"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
+ <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
+ <connections>
+ <action selector="hideOtherApplications:" target="Ady-hI-5gd" id="VT4-aY-XCT"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Show All" id="Kd2-mp-pUS">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="unhideAllApplications:" target="Ady-hI-5gd" id="Dhg-Le-xox"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
+ <menuItem title="Quit Demo" keyEquivalent="q" id="4sb-4s-VLi">
+ <connections>
+ <action selector="terminate:" target="Ady-hI-5gd" id="Te7-pn-YzF"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="Window" id="aUF-d1-5bR">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
+ <items>
+ <menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
+ <connections>
+ <action selector="performMiniaturize:" target="Ady-hI-5gd" id="VwT-WD-YPe"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Zoom" id="R4o-n2-Eq4">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="performZoom:" target="Ady-hI-5gd" id="DIl-cC-cCs"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
+ <menuItem title="Bring All to Front" id="LE2-aR-0XJ">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="arrangeInFront:" target="Ady-hI-5gd" id="DRN-fu-gQh"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="Help" id="wpr-3q-Mcd">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ">
+ <items>
+ <menuItem title="MoltenVK Demo Help" keyEquivalent="?" id="FKE-Sm-Kum">
+ <connections>
+ <action selector="showHelp:" target="Ady-hI-5gd" id="y7X-2Q-9no"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ </items>
+ </menu>
+ <connections>
+ <outlet property="delegate" destination="Voe-Tx-rLC" id="PrD-fu-P6m"/>
+ </connections>
+ </application>
+ <customObject id="Voe-Tx-rLC" customClass="AppDelegate"/>
+ <customObject id="Ady-hI-5gd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="83.5" y="-47"/>
+ </scene>
+ <!--Window Controller-->
+ <scene sceneID="R2V-B0-nI4">
+ <objects>
+ <windowController id="B8D-0N-5wS" sceneMemberID="viewController">
+ <window key="window" title="MoltenVK Hologram Demo" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="default" id="IQv-IB-iLA">
+ <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
+ <rect key="contentRect" x="1051" y="656" width="1024" height="768"/>
+ <rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
+ <value key="minSize" type="size" width="1024" height="768"/>
+ <value key="maxSize" type="size" width="1024" height="768"/>
+ </window>
+ <connections>
+ <segue destination="XfG-lQ-9wD" kind="relationship" relationship="window.shadowedContentViewController" id="cq2-FE-JQM"/>
+ </connections>
+ </windowController>
+ <customObject id="Oky-zY-oP4" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="83" y="146"/>
+ </scene>
+ <!--Demo View Controller-->
+ <scene sceneID="hIz-AP-VOD">
+ <objects>
+ <viewController id="XfG-lQ-9wD" customClass="DemoViewController" sceneMemberID="viewController">
+ <view key="view" id="m2S-Jp-Qdl" customClass="DemoView">
+ <rect key="frame" x="0.0" y="0.0" width="1024" height="768"/>
+ <autoresizingMask key="autoresizingMask"/>
+ </view>
+ </viewController>
+ <customObject id="rPt-NT-nkU" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="83" y="564"/>
+ </scene>
+ </scenes>
+</document>
--- /dev/null
+/*
+ * Copyright (C) 2016-2018 The Brenwill Workshop Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "ShellMVK.h"
+#include <mach/mach_time.h>
+#include <mach-o/dyld.h>
+#include <cassert>
+#include <sstream>
+#include <dlfcn.h>
+#include "Helpers.h"
+#include "Game.h"
+
+PosixTimer::PosixTimer() {
+ _tsBase = mach_absolute_time();
+ mach_timebase_info_data_t timebase;
+ mach_timebase_info(&timebase);
+ _tsPeriod = (double)timebase.numer / (double)timebase.denom;
+}
+
+double PosixTimer::get() { return (double)(mach_absolute_time() - _tsBase) * _tsPeriod / 1e9; }
+
+ShellMVK::ShellMVK(Game& game) : Shell(game) {
+ _timer = PosixTimer();
+ _current_time = _timer.get();
+ _profile_start_time = _current_time;
+ _profile_present_count = 0;
+
+#ifdef VK_USE_PLATFORM_IOS_MVK
+ instance_extensions_.push_back(VK_MVK_IOS_SURFACE_EXTENSION_NAME);
+#endif
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+ instance_extensions_.push_back(VK_MVK_MACOS_SURFACE_EXTENSION_NAME);
+#endif
+
+ init_vk();
+}
+
+ShellMVK::~ShellMVK() {
+ destroy_context();
+ cleanup_vk();
+}
+
+PFN_vkGetInstanceProcAddr ShellMVK::load_vk() {
+ const char filename[] = "libvulkan.1.dylib";
+ void* handle = NULL;
+ void* symbol = NULL;
+
+#ifdef UNINSTALLED_LOADER
+ // Try to load the loader from the defined location.
+ handle = dlopen(UNINSTALLED_LOADER, RTLD_LAZY);
+#endif
+ // If still no loader, try in the bundle executable directory.
+ if (!handle) {
+ unsigned int bufferSize = 512;
+ std::vector<char> buffer(bufferSize + 1);
+ if (_NSGetExecutablePath(&buffer[0], &bufferSize)) {
+ buffer.resize(bufferSize);
+ _NSGetExecutablePath(&buffer[0], &bufferSize);
+ }
+ std::string s = &buffer[0];
+ size_t i = s.rfind("smoketest");
+ s.replace(i, std::string::npos, filename);
+ handle = dlopen(s.c_str(), RTLD_LAZY);
+ }
+ // If still no luck, try the default system libs with the default lib name.
+ if (!handle) handle = dlopen(filename, RTLD_LAZY);
+
+ if (handle) symbol = dlsym(handle, "vkGetInstanceProcAddr");
+
+ if (!handle || !symbol) {
+ std::stringstream ss;
+ ss << "failed to load " << dlerror();
+
+ if (handle) dlclose(handle);
+
+ throw std::runtime_error(ss.str());
+ }
+
+ return reinterpret_cast<PFN_vkGetInstanceProcAddr>(symbol);
+}
+
+bool ShellMVK::can_present(VkPhysicalDevice phy, uint32_t queue_family) { return true; }
+
+VkSurfaceKHR ShellMVK::create_surface(VkInstance instance) {
+ VkSurfaceKHR surface;
+
+ VkResult err;
+#ifdef VK_USE_PLATFORM_IOS_MVK
+ VkIOSSurfaceCreateInfoMVK surface_info;
+ surface_info.sType = VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK;
+ surface_info.pNext = NULL;
+ surface_info.flags = 0;
+ surface_info.pView = _view;
+ err = vk::CreateIOSSurfaceMVK(instance, &surface_info, NULL, &surface);
+#endif
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+ VkMacOSSurfaceCreateInfoMVK surface_info;
+ surface_info.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
+ surface_info.pNext = NULL;
+ surface_info.flags = 0;
+ surface_info.pView = _view;
+ err = vk::CreateMacOSSurfaceMVK(instance, &surface_info, NULL, &surface);
+#endif
+ assert(!err);
+
+ return surface;
+}
+
+void ShellMVK::update_and_draw() {
+ acquire_back_buffer();
+
+ double t = _timer.get();
+ add_game_time(static_cast<float>(t - _current_time));
+
+ present_back_buffer();
+
+ _current_time = t;
+
+ _profile_present_count++;
+ if (_current_time - _profile_start_time >= 5.0) {
+ const double fps = _profile_present_count / (_current_time - _profile_start_time);
+ std::stringstream ss;
+ ss << _profile_present_count << " presents in " << _current_time - _profile_start_time << " seconds "
+ << "(FPS: " << fps << ")";
+ log(LOG_INFO, ss.str().c_str());
+
+ _profile_start_time = _current_time;
+ _profile_present_count = 0;
+ }
+}
+
+void ShellMVK::run(void* view) {
+ _view = view; // not retained
+ create_context();
+ resize_swapchain(settings_.initial_width, settings_.initial_height);
+}
--- /dev/null
+/*
+ * Copyright (C) 2016-2018 The Brenwill Workshop Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SHELL_MVK_H
+#define SHELL_MVK_H
+
+#include <MoltenVK/mvk_vulkan.h>
+#include "Shell.h"
+#include <sys/time.h>
+
+class PosixTimer {
+ public:
+ double get();
+ PosixTimer();
+
+ protected:
+ uint64_t _tsBase;
+ double _tsPeriod;
+};
+
+class ShellMVK : public Shell {
+ public:
+ ShellMVK(Game& game);
+ ~ShellMVK();
+
+ void run(void* view);
+ void update_and_draw();
+
+ void run() { run(nullptr); };
+ void quit() {}
+
+ protected:
+ void* _view;
+ PosixTimer _timer;
+ double _current_time;
+ double _profile_start_time;
+ int _profile_present_count;
+
+ PFN_vkGetInstanceProcAddr load_vk();
+ bool can_present(VkPhysicalDevice phy, uint32_t queue_family);
+
+ VkSurfaceKHR create_surface(VkInstance instance);
+};
+
+#endif // SHELL_MVK_H
--- /dev/null
+/*
+ * main.m
+ *
+ * Copyright (c) 2014-2018 The Brenwill Workshop Ltd. (http://www.brenwill.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import <Cocoa/Cocoa.h>
+
+int main(int argc, const char* argv[]) { return NSApplicationMain(argc, argv); }
add_definitions(-DVK_USE_PLATFORM_MIR_KHR -DVK_USE_PLATFORM_MIR_KHX)
include_directories(${MIR_INCLUDE_DIR})
endif()
+elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ add_definitions(-DVK_USE_PLATFORM_MACOS_MVK)
else()
message(FATAL_ERROR "Unsupported Platform!")
endif()
#target_link_Libraries(VkICD_${target} VkICD_utils)
#add_dependencies(VkICD_${target} generate_helper_files VkICD_utils)
endmacro()
+elseif(APPLE)
+ macro(add_vk_icd target)
+ add_library(VkICD_${target} SHARED ${ARGN})
+ #target_link_Libraries(VkICD_${target} VkICD_utils)
+ add_dependencies(VkICD_${target} generate_icd_files)
+ set_target_properties(VkICD_${target} PROPERTIES LINK_FLAGS "-Wl")
+ install(TARGETS VkICD_${target} DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
+ endmacro()
else()
macro(add_vk_icd target)
add_library(VkICD_${target} SHARED ${ARGN})
#define CURRENT_LOADER_ICD_INTERFACE_VERSION 5
#define MIN_SUPPORTED_LOADER_ICD_INTERFACE_VERSION 0
#define MIN_PHYS_DEV_EXTENSION_ICD_INTERFACE_VERSION 4
-typedef VkResult (VKAPI_PTR *PFN_vkNegotiateLoaderICDInterfaceVersion)(uint32_t *pVersion);
+typedef VkResult(VKAPI_PTR *PFN_vkNegotiateLoaderICDInterfaceVersion)(uint32_t *pVersion);
// This is defined in vk_layer.h which will be found by the loader, but if an ICD is building against this
// file directly, it won't be found.
#ifndef PFN_GetPhysicalDeviceProcAddr
-typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_GetPhysicalDeviceProcAddr)(VkInstance instance, const char* pName);
+typedef PFN_vkVoidFunction(VKAPI_PTR *PFN_GetPhysicalDeviceProcAddr)(VkInstance instance, const char *pName);
#endif
/*
VK_ICD_WSI_PLATFORM_WIN32,
VK_ICD_WSI_PLATFORM_XCB,
VK_ICD_WSI_PLATFORM_XLIB,
+ VK_ICD_WSI_PLATFORM_ANDROID,
+ VK_ICD_WSI_PLATFORM_MACOS,
+ VK_ICD_WSI_PLATFORM_IOS,
VK_ICD_WSI_PLATFORM_DISPLAY
} VkIcdWsiPlatform;
MirConnection *connection;
MirSurface *mirSurface;
} VkIcdSurfaceMir;
-#endif // VK_USE_PLATFORM_MIR_KHR
+#endif // VK_USE_PLATFORM_MIR_KHR
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
typedef struct {
struct wl_display *display;
struct wl_surface *surface;
} VkIcdSurfaceWayland;
-#endif // VK_USE_PLATFORM_WAYLAND_KHR
+#endif // VK_USE_PLATFORM_WAYLAND_KHR
#ifdef VK_USE_PLATFORM_WIN32_KHR
typedef struct {
HINSTANCE hinstance;
HWND hwnd;
} VkIcdSurfaceWin32;
-#endif // VK_USE_PLATFORM_WIN32_KHR
+#endif // VK_USE_PLATFORM_WIN32_KHR
#ifdef VK_USE_PLATFORM_XCB_KHR
typedef struct {
xcb_connection_t *connection;
xcb_window_t window;
} VkIcdSurfaceXcb;
-#endif // VK_USE_PLATFORM_XCB_KHR
+#endif // VK_USE_PLATFORM_XCB_KHR
#ifdef VK_USE_PLATFORM_XLIB_KHR
typedef struct {
Display *dpy;
Window window;
} VkIcdSurfaceXlib;
-#endif // VK_USE_PLATFORM_XLIB_KHR
+#endif // VK_USE_PLATFORM_XLIB_KHR
#ifdef VK_USE_PLATFORM_ANDROID_KHR
typedef struct {
- ANativeWindow* window;
+ VkIcdSurfaceBase base;
+ ANativeWindow *window;
} VkIcdSurfaceAndroid;
-#endif //VK_USE_PLATFORM_ANDROID_KHR
+#endif // VK_USE_PLATFORM_ANDROID_KHR
+
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+typedef struct {
+ VkIcdSurfaceBase base;
+ const void *pView;
+} VkIcdSurfaceMacOS;
+#endif // VK_USE_PLATFORM_MACOS_MVK
+
+#ifdef VK_USE_PLATFORM_IOS_MVK
+typedef struct {
+ VkIcdSurfaceBase base;
+ const void *pView;
+} VkIcdSurfaceIOS;
+#endif // VK_USE_PLATFORM_IOS_MVK
typedef struct {
VkIcdSurfaceBase base;
VkExtent2D imageExtent;
} VkIcdSurfaceDisplay;
-#endif // VKICD_H
+#endif // VKICD_H
add_definitions(-DVK_USE_PLATFORM_MIR_KHR -DVK_USE_PLATFORM_MIR_KHX)
include_directories(${MIR_INCLUDE_DIR})
endif()
+elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ add_definitions(-DVK_USE_PLATFORM_MACOS_MVK)
+ if(CMAKE_GENERATOR MATCHES "^Xcode.*")
+ add_custom_target(mk_layer_config_dir ALL COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>)
+ endif()
else()
message(FATAL_ERROR "Unsupported Platform!")
endif()
)
set_target_properties(vk_validation_error_messages PROPERTIES FOLDER ${LVL_TARGET_FOLDER})
endif()
-else()
+elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
# extra setup for out-of-tree builds
if (NOT (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR))
foreach (config_file ${LAYER_JSON_FILES})
VERBATIM
)
endif()
+elseif(APPLE)
+ # extra setup for out-of-tree builds
+ if (NOT (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR))
+ if (CMAKE_GENERATOR MATCHES "^Xcode.*")
+ foreach (config_file ${LAYER_JSON_FILES})
+ add_custom_target(${config_file}-json ALL
+ DEPENDS mk_layer_config_dir
+ COMMAND ln -sf ${CMAKE_CURRENT_SOURCE_DIR}/macos/${config_file}.json $<CONFIG>
+ VERBATIM
+ )
+ endforeach(config_file)
+ else()
+ foreach (config_file ${LAYER_JSON_FILES})
+ add_custom_target(${config_file}-json ALL
+ COMMAND ln -sf ${CMAKE_CURRENT_SOURCE_DIR}/macos/${config_file}.json
+ VERBATIM
+ )
+ endforeach(config_file)
+ endif()
+ # Add link to vk_validation_error_messages.h in build dir for scripts to pick up
+ add_custom_target(vk_validation_error_messages ALL
+ COMMAND ln -sf ${CMAKE_CURRENT_SOURCE_DIR}/vk_validation_error_messages.h
+ VERBATIM
+ )
+ endif()
endif()
# If a layer has a direct dependency on a project with the same name, use it.
if ((Win32) OR (NOT (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)))
target_link_Libraries(VkLayer_${target} VkLayer_utils)
add_dependencies(VkLayer_${target} generate_helper_files VkLayer_utils)
endmacro()
+elseif(APPLE)
+ macro(add_vk_layer target)
+ add_library(VkLayer_${target} SHARED ${ARGN})
+ target_link_Libraries(VkLayer_${target} VkLayer_utils)
+ add_dependencies(VkLayer_${target} generate_helper_files VkLayer_utils)
+ set_target_properties(VkLayer_${target} PROPERTIES
+ LINK_FLAGS "-Wl"
+ INSTALL_RPATH "@loader_path/"
+ )
+ install(TARGETS VkLayer_${target} DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
+ endmacro()
else()
macro(add_vk_layer target)
add_library(VkLayer_${target} SHARED ${ARGN})
}
#endif // VK_USE_PLATFORM_ANDROID_KHR
+#ifdef VK_USE_PLATFORM_IOS_MVK
+VKAPI_ATTR VkResult VKAPI_CALL CreateIOSSurfaceMVK(VkInstance instance, const VkIOSSurfaceCreateInfoMVK *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
+ return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateIOSSurfaceMVK);
+}
+#endif // VK_USE_PLATFORM_IOS_MVK
+
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+VKAPI_ATTR VkResult VKAPI_CALL CreateMacOSSurfaceMVK(VkInstance instance, const VkMacOSSurfaceCreateInfoMVK *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
+ return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateMacOSSurfaceMVK);
+}
+#endif // VK_USE_PLATFORM_MACOS_MVK
+
#ifdef VK_USE_PLATFORM_MIR_KHR
VKAPI_ATTR VkResult VKAPI_CALL CreateMirSurfaceKHR(VkInstance instance, const VkMirSurfaceCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
{"vkCreateXlibSurfaceKHR", (void *)CreateXlibSurfaceKHR},
{"vkGetPhysicalDeviceXlibPresentationSupportKHR", (void *)GetPhysicalDeviceXlibPresentationSupportKHR},
#endif
+#ifdef VK_USE_PLATFORM_IOS_MVK
+ {"vkCreateIOSSurfaceMVK", (void *)CreateIOSSurfaceMVK},
+#endif
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+ {"vkCreateMacOSSurfaceMVK", (void *)CreateMacOSSurfaceMVK},
+#endif
{"vkCreateDisplayPlaneSurfaceKHR", (void *)CreateDisplayPlaneSurfaceKHR},
{"vkDestroySurfaceKHR", (void *)DestroySurfaceKHR},
{"vkGetPhysicalDeviceSurfaceCapabilitiesKHR", (void *)GetPhysicalDeviceSurfaceCapabilitiesKHR},
--- /dev/null
+{
+ "file_format_version" : "1.1.0",
+ "layer" : {
+ "name": "VK_LAYER_LUNARG_core_validation",
+ "type": "GLOBAL",
+ "library_path": "./libVkLayer_core_validation.dylib",
+ "api_version": "1.0.69",
+ "implementation_version": "1",
+ "description": "LunarG Validation Layer",
+ "instance_extensions": [
+ {
+ "name": "VK_EXT_debug_report",
+ "spec_version": "6"
+ }
+ ],
+ "device_extensions": [
+ {
+ "name": "VK_EXT_debug_marker",
+ "spec_version": "4",
+ "entrypoints": ["vkDebugMarkerSetObjectTagEXT",
+ "vkDebugMarkerSetObjectNameEXT",
+ "vkCmdDebugMarkerBeginEXT",
+ "vkCmdDebugMarkerEndEXT",
+ "vkCmdDebugMarkerInsertEXT"
+ ]
+ }
+ ]
+ }
+}
--- /dev/null
+{
+ "file_format_version" : "1.1.0",
+ "layer" : {
+ "name": "VK_LAYER_LUNARG_device_simulation",
+ "type": "GLOBAL",
+ "library_path": "./libVkLayer_device_simulation.dylib",
+ "api_version": "1.0.69",
+ "implementation_version": "1.2.0",
+ "description": "LunarG device simulation layer"
+ }
+}
--- /dev/null
+{
+ "file_format_version" : "1.1.0",
+ "layer" : {
+ "name": "VK_LAYER_LUNARG_object_tracker",
+ "type": "GLOBAL",
+ "library_path": "./libVkLayer_object_tracker.dylib",
+ "api_version": "1.0.69",
+ "implementation_version": "1",
+ "description": "LunarG Validation Layer",
+ "instance_extensions": [
+ {
+ "name": "VK_EXT_debug_report",
+ "spec_version": "6"
+ }
+ ],
+ "device_extensions": [
+ {
+ "name": "VK_EXT_debug_marker",
+ "spec_version": "4",
+ "entrypoints": ["vkDebugMarkerSetObjectTagEXT",
+ "vkDebugMarkerSetObjectNameEXT",
+ "vkCmdDebugMarkerBeginEXT",
+ "vkCmdDebugMarkerEndEXT",
+ "vkCmdDebugMarkerInsertEXT"
+ ]
+ }
+ ]
+ }
+}
--- /dev/null
+{
+ "file_format_version" : "1.1.0",
+ "layer" : {
+ "name": "VK_LAYER_LUNARG_parameter_validation",
+ "type": "GLOBAL",
+ "library_path": "./libVkLayer_parameter_validation.dylib",
+ "api_version": "1.0.69",
+ "implementation_version": "1",
+ "description": "LunarG Validation Layer",
+ "instance_extensions": [
+ {
+ "name": "VK_EXT_debug_report",
+ "spec_version": "6"
+ }
+ ],
+ "device_extensions": [
+ {
+ "name": "VK_EXT_debug_marker",
+ "spec_version": "4",
+ "entrypoints": ["vkDebugMarkerSetObjectTagEXT",
+ "vkDebugMarkerSetObjectNameEXT",
+ "vkCmdDebugMarkerBeginEXT",
+ "vkCmdDebugMarkerEndEXT",
+ "vkCmdDebugMarkerInsertEXT"
+ ]
+ }
+ ]
+ }
+}
--- /dev/null
+{
+ "file_format_version": "1.1.1",
+ "layer": {
+ "name": "VK_LAYER_LUNARG_standard_validation",
+ "type": "GLOBAL",
+ "api_version": "1.0.69",
+ "implementation_version": "1",
+ "description": "LunarG Standard Validation",
+ "component_layers": [
+ "VK_LAYER_GOOGLE_threading",
+ "VK_LAYER_LUNARG_parameter_validation",
+ "VK_LAYER_LUNARG_object_tracker",
+ "VK_LAYER_LUNARG_core_validation",
+ "VK_LAYER_GOOGLE_unique_objects"
+ ]
+ }
+}
--- /dev/null
+{
+ "file_format_version" : "1.1.0",
+ "layer" : {
+ "name": "VK_LAYER_GOOGLE_threading",
+ "type": "GLOBAL",
+ "library_path": "./libVkLayer_threading.dylib",
+ "api_version": "1.0.69",
+ "implementation_version": "1",
+ "description": "Google Validation Layer",
+ "instance_extensions": [
+ {
+ "name": "VK_EXT_debug_report",
+ "spec_version": "6"
+ }
+ ]
+ }
+}
--- /dev/null
+{
+ "file_format_version" : "1.1.0",
+ "layer" : {
+ "name": "VK_LAYER_GOOGLE_unique_objects",
+ "type": "GLOBAL",
+ "library_path": "./libVkLayer_unique_objects.dylib",
+ "api_version": "1.0.69",
+ "implementation_version": "1",
+ "description": "Google Validation Layer"
+ }
+}
if (use_data->thread != tid) {
skipCall |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, objectType, (uint64_t)(object), 0,
THREADING_CHECKER_MULTIPLE_THREADS, "THREADING",
- "THREADING ERROR : object of type %s is simultaneously used in thread %ld and thread %ld",
- typeName, use_data->thread, tid);
+ "THREADING ERROR : object of type %s is simultaneously used in "
+ "thread 0x%" PRIx64 " and thread 0x%" PRIx64,
+ typeName, (uint64_t)use_data->thread, (uint64_t)tid);
if (skipCall) {
// Wait for thread-safe access to object instead of skipping call.
while (uses.find(object) != uses.end()) {
if (use_data->thread != tid) {
skipCall |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, objectType, (uint64_t)(object), 0,
THREADING_CHECKER_MULTIPLE_THREADS, "THREADING",
- "THREADING ERROR : object of type %s is simultaneously used in thread %ld and thread %ld",
- typeName, use_data->thread, tid);
+ "THREADING ERROR : object of type %s is simultaneously used in "
+ "thread 0x%" PRIx64 " and thread 0x%" PRIx64,
+ typeName, (uint64_t)use_data->thread, (uint64_t)tid);
if (skipCall) {
// Wait for thread-safe access to object instead of skipping call.
while (uses.find(object) != uses.end()) {
// There is a writer of the object.
skipCall |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, objectType, (uint64_t)(object), 0,
THREADING_CHECKER_MULTIPLE_THREADS, "THREADING",
- "THREADING ERROR : object of type %s is simultaneously used in thread %ld and thread %ld", typeName,
- uses[object].thread, tid);
+ "THREADING ERROR : object of type %s is simultaneously used in "
+ "thread 0x%" PRIx64 " and thread 0x%" PRIx64,
+ typeName, (uint64_t)uses[object].thread, (uint64_t)tid);
if (skipCall) {
// Wait for thread-safe access to object instead of skipping call.
while (uses.find(object) != uses.end()) {
add_definitions(-DVK_USE_PLATFORM_MIR_KHR)
include_directories(${MIR_INCLUDE_DIR})
endif()
+elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ add_definitions(-DVK_USE_PLATFORM_MACOS_MVK)
else()
message(FATAL_ERROR "Unsupported Platform!")
endif()
set(OPT_LOADER_SRCS ${OPT_LOADER_SRCS} unknown_ext_chain.c)
add_custom_target(loader_asm_gen_files)
endif()
+elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ # For MacOS, use the C code and force the compiler's tail-call optimization instead of using assembly code.
+ set(OPT_LOADER_SRCS ${OPT_LOADER_SRCS} unknown_ext_chain.c)
+ set_source_files_properties(${OPT_LOADER_SRCS} PROPERTIES COMPILE_FLAGS -O)
+ add_custom_target(loader_asm_gen_files) # This causes no assembly files to be generated.
else()
enable_language(ASM-ATT)
set(CMAKE_ASM-ATT_COMPILE_FLAGS "${CMAKE_ASM-ATT_COMPILE_FLAGS} $ENV{ASFLAGS}")
COMMAND xcopy /Y /I ${COPY_SRC_PATH} ${COPY_DST_TEST_PATH})
else()
+ # Linux and MacOS
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wpointer-arith")
# Clang (and not gcc) warns about redefining a typedef with the same types, so disable that warning.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-typedef-redefinition")
endif()
- add_library(${API_LOWERCASE} SHARED ${NORMAL_LOADER_SRCS} ${OPT_LOADER_SRCS})
+ add_library(${API_LOWERCASE} SHARED ${NORMAL_LOADER_SRCS} ${OPT_LOADER_SRCS} ${FRAMEWORK_HEADERS})
add_dependencies(${API_LOWERCASE} generate_helper_files loader_gen_files loader_asm_gen_files)
target_compile_definitions(${API_LOWERCASE} PUBLIC -DLOADER_DYNAMIC_LIB)
set_target_properties(${API_LOWERCASE} PROPERTIES SOVERSION "1" VERSION "1.0.${vk_header_version}")
target_link_libraries(${API_LOWERCASE} -ldl -lpthread -lm)
+ if(APPLE)
+ find_library(COREFOUNDATION_LIBRARY NAMES CoreFoundation)
+ target_link_libraries(${API_LOWERCASE} "-framework CoreFoundation")
+
+ # Build vulkan.framework
+ set(FRAMEWORK_HEADERS
+ ${PROJECT_SOURCE_DIR}/include/vulkan/vk_icd.h
+ ${PROJECT_SOURCE_DIR}/include/vulkan/vk_layer.h
+ ${PROJECT_SOURCE_DIR}/include/vulkan/vk_platform.h
+ ${PROJECT_SOURCE_DIR}/include/vulkan/vk_sdk_platform.h
+ ${PROJECT_SOURCE_DIR}/include/vulkan/vulkan.h
+ ${PROJECT_SOURCE_DIR}/include/vulkan/vulkan.hpp
+ )
+ add_library(vulkan-framework SHARED ${NORMAL_LOADER_SRCS} ${OPT_LOADER_SRCS} ${FRAMEWORK_HEADERS})
+ add_dependencies(vulkan-framework generate_helper_files loader_gen_files loader_asm_gen_files)
+ target_compile_definitions(vulkan-framework PUBLIC -DLOADER_DYNAMIC_LIB)
+ target_link_libraries(vulkan-framework -ldl -lpthread -lm "-framework CoreFoundation")
+
+ # The FRAMEWORK_VERSION needs to be "A" here so that Xcode code-signing works when
+ # a user adds their framework to an Xcode project and does "Sign on Copy".
+ # It would have been nicer to use "1" to denote Vulkan 1.
+ # Although Apple docs say that a framework version does not have to be "A",
+ # this part of the Apple toolchain expects it.
+ # https://forums.developer.apple.com/thread/65963
+ set_target_properties(vulkan-framework PROPERTIES
+ OUTPUT_NAME vulkan
+ FRAMEWORK TRUE
+ FRAMEWORK_VERSION A
+ VERSION "1.0.${vk_header_version}" # "current version"
+ SOVERSION "1.0.0" # "compatibility version"
+ MACOSX_FRAMEWORK_IDENTIFIER com.lunarg.vulkanFramework
+ PUBLIC_HEADER "${FRAMEWORK_HEADERS}"
+ )
+ install(TARGETS vulkan-framework
+ PUBLIC_HEADER DESTINATION vulkan
+ FRAMEWORK DESTINATION loader
+ )
+ endif(APPLE)
+
if(INSTALL_LVL_FILES)
install(TARGETS ${API_LOWERCASE} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif()
- # Generate pkg-config file.
- include(FindPkgConfig QUIET)
- if(PKG_CONFIG_FOUND)
- set(VK_API_VERSION "1.0.${vk_header_version}")
- foreach(LIB ${CMAKE_CXX_IMPLICIT_LINK_LIBRARIES} ${PLATFORM_LIBS})
- set(PRIVATE_LIBS "${PRIVATE_LIBS} -l${LIB}")
- endforeach()
- configure_file("vulkan.pc.in" "vulkan.pc" @ONLY)
- if(INSTALL_LVL_FILES)
- install(FILES "${CMAKE_CURRENT_BINARY_DIR}/vulkan.pc"
- DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
+ if(NOT APPLE)
+ # Generate pkg-config file.
+ include(FindPkgConfig QUIET)
+ if(PKG_CONFIG_FOUND)
+ set(VK_API_VERSION "1.0.${vk_header_version}")
+ foreach(LIB ${CMAKE_CXX_IMPLICIT_LINK_LIBRARIES} ${PLATFORM_LIBS})
+ set(PRIVATE_LIBS "${PRIVATE_LIBS} -l${LIB}")
+ endforeach()
+ configure_file("vulkan.pc.in" "vulkan.pc" @ONLY)
+ if(INSTALL_LVL_FILES)
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/vulkan.pc"
+ DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
+ endif()
endif()
endif()
endif()
+
+
![High Level View of Loader](./images/high_level_loader.png)
The general concepts in this document are applicable to the loaders available
-for Windows, Linux and Android based systems.
+for Windows, Linux, Android and MacOS based systems.
#### Who Should Read This Document
##### Vulkan Direct Exports
-The loader library on Windows, Linux and Android will export all core Vulkan
+The loader library on Windows, Linux, Android and MacOS will export all core Vulkan
and all appropriate Window System Interface (WSI) extensions. This is done to
make it simpler to get started with Vulkan development. When an application
links directly to the loader library in this way, the Vulkan calls are simple
###### Dynamic Linking
The loader is ordinarily distributed as a dynamic library (.dll on Windows or
-.so on Linux) which gets installed to the system path for dynamic libraries.
+.so on Linux or .dylib on MacOS) which gets installed to the system path
+for dynamic libraries.
Linking to the dynamic library is generally the preferred method of linking to
the loader, as doing so allows the loader to be updated for bug fixes and
improvements. Furthermore, the dynamic library is generally installed to Windows
![Instance Call Chain](./images/loader_instance_chain.png)
This is also how a Vulkan Device function call chain looks if you query it
-using `vkGetInstanceProcAddr`. On the otherhand, a Device
-function doesn't need to worry about the broadcast becuase it knows specifically
+using `vkGetInstanceProcAddr`. On the other hand, a Device
+function doesn't need to worry about the broadcast because it knows specifically
which associated ICD and which associated Physical Device the call should
terminate at. Because of this, the loader doesn't need to get involved between
any enabled layers and the ICD. Thus, if you used a loader-exported Vulkan
version of the loader with the same name can be found in the windows/sysWOW64
directory).
-For Linux, shared libraries are versioned based on a suffix. Thus, the ABI
+For Linux and MacOS, shared libraries are versioned based on a suffix. Thus, the ABI
number is not encoded in the base of the library filename as on Windows. On
Linux an application wanting to link to the latest Vulkan ABI version would
just link to the name vulkan (libvulkan.so). A specific Vulkan ABI version can
also be linked to by applications (e.g. libvulkan.so.1).
+On MacOS, the libraries are libvulkan.dylib abd libvulkan.1.dylib.
#### Application Layer Usage
require being able to be disabled by an environmental variable. This is due
to the fact that they are not visible to the application and could cause issues.
A good principle to keep in mind would be to define both an enable and disable
-environment variable so the users can deterministicly enable the functionality.
-On Desktop platforms (Windows and Linux), these enable/disable settings are
+environment variable so the users can deterministically enable the functionality.
+On Desktop platforms (Windows, Linux, and MacOS), these enable/disable settings are
defined in the layer's JSON file.
Discovery of system-installed implicit and explicit layers is described later in
| Windows | Implicit Layers are located in a different Windows registry location than Explicit Layers. |
| Linux | Implicit Layers are located in a different directory location than Explicit Layers. |
| Android | There is **No Support For Implicit Layers** on Android. |
+| MacOS | Implicit Layers are located in a different directory location than Explicit Layers. |
##### Forcing Layer Source Folders
system-installed layers. You can direct the loader to look for layers in a
specific folder by defining the "VK\_LAYER\_PATH" environment variable. This
will override the mechanism used for finding system-installed layers. Because
-layers of interest may exist in several disinct folders on a system, this
-environment variable can containis several paths seperated by the operating
+layers of interest may exist in several distinct folders on a system, this
+environment variable can contains several paths separated by the operating
specific path separator. On Windows, each separate folder should be separated
-in the list using a semi-colon. On Linux, each folder name should be separated
+in the list using a semi-colon. On Linux and MacOS, each folder name should be separated
using a colon.
If "VK\_LAYER\_PATH" exists, **only** the folders listed in it will be scanned
containing layer manifest files.
-##### Forcing Layers to be Enabled on Windows and Linux
+##### Forcing Layers to be Enabled on Windows, Linux and MacOS
Developers may want to enable layers that are not enabled by the given
-application they are using. On Linux and Windows, the environment variable
+application they are using. On desktop systems, the environment variable
"VK\_INSTANCE\_LAYERS" can be used to enable additional layers which are
not specified (enabled) by the application at `vkCreateInstance`.
-"VK\_INSTANCE\_LAYERS" is a colon (Linux)/semi-colon (Windows) separated
+"VK\_INSTANCE\_LAYERS" is a colon (Linux and MacOS)/semi-colon (Windows) separated
list of layer names to enable. Order is relevant with the first layer in the
list being the top-most layer (closest to the application) and the last
layer in the list being the bottom-most layer (closest to the driver).
application) while layers specified by the application are bottommost.
An example of using these environment variables to activate the validation
-layer `VK_LAYER_LUNARG_parameter_validation` on Windows or Linux is as follows:
+layer `VK_LAYER_LUNARG_parameter_validation` on Windows, Linux or MacOS is as follows:
```
> $ export VK_INSTANCE_LAYERS=VK_LAYER_LUNARG_parameter_validation
Integration support for various execution environments. It is important to
understand that some WSI extensions are valid for all targets, but others are
particular to a given execution environment (and loader). This desktop loader
-(currently targeting Windows and Linux) only enables and directly exports those
+(currently targeting Windows, Linux, and MacOS) only enables and directly exports those
WSI extensions that are appropriate to the current environment. For the most
part, the selection is done in the loader using compile-time preprocessor flags.
All versions of the desktop loader currently expose at least the following WSI
| Linux (Default) | VK_KHR_xcb_surface and VK_KHR_xlib_surface |
| Linux (Wayland) | VK_KHR_wayland_surface |
| Linux (Mir) | VK_KHR_mir_surface |
+| MacOS (MoltenVK) | VK_MVK_macos_surface |
**NOTE:** Wayland and Mir targets are not fully supported at this time. Wayland
support is present, but should be considered Beta quality. Mir support is not
loader knows nothing about. If the extension is a device extension, the loader
will pass the unknown entry-point down the device call chain ending with the
appropriate ICD entry-points. The same thing will happen, if the extension is
-an instance extension which takes a physical device paramater as it's first
+an instance extension which takes a physical device parameter as it's first
component. However, for all other instance extensions the loader will fail to
load it.
extensions when an application calls `vkEnumerateInstanceExtensionProperties`.
Additionally, this behavior will cause the loader to throw an error during
`vkCreateInstance` if you still attempt to use one of these extensions. The intent is
-to protect applications so that they don't inadvertantly use functionality
+to protect applications so that they don't inadvertently use functionality
which could lead to a crash.
On the other-hand, if you know you can safely use the extension, you may disable
* [Android Layer Discovery](#android-layer-discovery)
* [Windows Layer Discovery](#windows-layer-discovery)
* [Linux Layer Discovery](#linux-layer-discovery)
+ * [MacOS Layer Discovery](#macos-layer-discovery)
* [Layer Version Negotiation](#layer-version-negotiation)
* [Layer Call Chains and Distributed Dispatch](#layer-call-chains-and-distributed-dispatch)
* [Layer Unknown Physical Device Extensions](#layer-unknown-physical-device-extensions)
* Explicit Layers
The main difference between the two is that Implicit Layers are automatically
-enabled, unless overriden, and Explicit Layers must be enabled. Remember,
+enabled, unless overridden, and Explicit Layers must be enabled. Remember,
Implicit Layers are not present on all Operating Systems (like Android).
On any system, the loader looks in specific areas for information on the
##### Layer Manifest File Usage
-On Windows and Linux systems, JSON formatted manifest files are used to store
+On Windows, Linux, and MacOS systems, JSON formatted manifest files are used to store
layer information. In order to find system-installed layers, the Vulkan loader
will read the JSON files to identify the names and attributes of layers and
their extensions. The use of manifest files allows the loader to avoid loading
In general, applications should install layers into the `SOFTWARE\Khrosos\Vulkan`
paths. The PnP registry locations are intended specifically for layers that are
-distrubuted as part of a driver installation. An application installer should not
+distributed as part of a driver installation. An application installer should not
modify the device-specific registries, while a device driver should not modify
the system wide registries.
$HOME/.local/share/vulkan/explicit_layer.d
$HOME/.local/share/vulkan/implicit_layer.d
-Of course, ther are some things you have to know about the above folders:
+Of course, there are some things you have to know about the above folders:
1. The "/usr/local/*" directories can be configured to be other directories at
build time.
2. $HOME is the current home directory of the application's user id; this path
[Forcing Layer Source Folders](#forcing-layer-source-folders) for more
information on this.
+##### MacOS Layer Discovery
+
+On MacOS, the Vulkan loader will scan the files in the following directories:
+
+ <bundle>/Contents/Resources/vulkan/explicit_layer.d
+ <bundle>/Contents/Resources/vulkan/implicit_layer.d
+ /etc/vulkan/explicit_layer.d
+ /etc/vulkan/implicit_layer.d
+ /usr/local/share/vulkan/explicit_layer.d
+ /usr/local/share/vulkan/implicit_layer.d
+ /usr/share/vulkan/explicit_layer.d
+ /usr/share/vulkan/implicit_layer.d
+ $HOME/.local/share/vulkan/explicit_layer.d
+ $HOME/.local/share/vulkan/implicit_layer.d
+
+1. <bundle> is the directory containing a bundled application. It is scanned first.
+1. The "/usr/local/*" directories can be configured to be other directories at
+build time.
+1. $HOME is the current home directory of the application's user id; this path
+will be ignored for suid programs.
+
+As on Windows, if VK\_LAYER\_PATH is defined, then the
+loader will instead look at the paths defined by that variable instead of using
+the information provided by these default paths. However, these
+environment variables are only used for non-suid programs. See
+[Forcing Layer Source Folders](#forcing-layer-source-folders) for more
+information on this.
#### Layer Version Negotiation
You'll notice the `VkNegotiateLayerInterface` structure is similar to other
Vulkan structures. The "sType" field, in this case takes a new enum defined
just for internal loader/layer interfacing use. The valid values for "sType"
-could grow in the future, but right only havs the one value
+could grow in the future, but right now only has the one value
"LAYER_NEGOTIATE_INTERFACE_STRUCT".
This function (`vkNegotiateLoaderLayerInterfaceVersion`) should be exported by
-the layer so that using "GetProcAddress" on Windows or "dlsym" on Linux, should
+the layer so that using "GetProcAddress" on Windows or "dlsym" on Linux or MacOS, should
return a valid function pointer to it. Once the loader has grabbed a valid
address to the layers function, the loader will create a variable of type
`VkNegotiateLayerInterface` and initialize it in the following ways:
the loader will use the “fpGetInstanceProcAddr” and “fpGetDeviceProcAddr”
functions from the “VkNegotiateLayerInterface” structure. Prior to these
changes, the loader would query each of those functions using "GetProcAddress"
-on Windows or "dlsym" on Linux.
+on Windows or "dlsym" on Linux or MacOS.
#### Layer Call Chains and Distributed Dispatch
to the application when queried.
Restrictions to defining and using a meta-layer are:
- 1. A Meta-layer Manifest file **must** be a properly formated that contains one
+ 1. A Meta-layer Manifest file **must** be a properly formatted that contains one
or more component layers.
3. All component layers **must be** present on a system for the meta-layer to
be used.
#### Layer Manifest File Format
-On Windows and Linux (desktop), the loader uses manifest files to discover
+On Windows, Linux and MacOS (desktop), the loader uses manifest files to discover
layer libraries and layers. The desktop loader doesn't directly query the
layer library except during chaining. This is to reduce the likelihood of
loading a malicious layer into memory. Instead, details are read from the
| "name" | The string used to uniquely identify this layer to applications. | vkEnumerateInstanceLayerProperties |
| "type" | This field indicates the type of layer. The values can be: GLOBAL, or INSTANCE | vkEnumerate*LayerProperties |
| | **NOTES:** Prior to deprecation, the "type" node was used to indicate which layer chain(s) to activate the layer upon: instance, device, or both. Distinct instance and device layers are deprecated; there are now just layers. Allowable values for type (both before and after deprecation) are "INSTANCE", "GLOBAL" and, "DEVICE." "DEVICE" layers are skipped over by the loader as if they were not found. | |
-| "library\_path" | The "library\_path" specifies either a filename, a relative pathname, or a full pathname to a layer shared library file. If "library\_path" specifies a relative pathname, it is relative to the path of the JSON manifest file (e.g. for cases when an application provides a layer that is in the same folder hierarchy as the rest of the application files). If "library\_path" specifies a filename, the library must live in the system's shared object search path. There are no rules about the name of the layer shared library files other than it should end with the appropriate suffix (".DLL" on Windows, and ".so" on Linux). **This field must not be present if "component_layers" is defined** | N/A |
+| "library\_path" | The "library\_path" specifies either a filename, a relative pathname, or a full pathname to a layer shared library file. If "library\_path" specifies a relative pathname, it is relative to the path of the JSON manifest file (e.g. for cases when an application provides a layer that is in the same folder hierarchy as the rest of the application files). If "library\_path" specifies a filename, the library must live in the system's shared object search path. There are no rules about the name of the layer shared library files other than it should end with the appropriate suffix (".DLL" on Windows, ".so" on Linux, and ".dylib" on MacOS). **This field must not be present if "component_layers" is defined** | N/A |
| "api\_version" | The major.minor.patch version number of the Vulkan API that the shared library file for the library was built against. For example: 1.0.33. | vkEnumerateInstanceLayerProperties |
| "implementation_version" | The version of the layer implemented. If the layer itself has any major changes, this number should change so the loader and/or application can identify it properly. | vkEnumerateInstanceLayerProperties |
| "description" | A high-level description of the layer and it's intended use. | vkEnumerateInstanceLayerProperties |
[Layer Unknown Physical Device Extensions](#layer-unknown-physical-device-
extensions)
and the associated `vk_layerGetPhysicalDeviceProcAddr` function. Finally, it
-changed the manifest file defition to 1.1.0.
+changed the manifest file definition to 1.1.0.
##### Layer Library API Version 1
* [ICD Manifest File Usage](#icd-manifest-file-usage)
* [ICD Discovery on Windows](#icd-discovery-on-windows)
* [ICD Discovery on Linux](#icd-discovery-on-linux)
- * [Using Pre-Production ICDs on Windows and Linux](#using-pre-production-icds-on-windows-and-linux)
+ * [ICD Discovery on MacOS](#icd-discovery-on-macos)
+ * [Using Pre-Production ICDs on Windows, Linux and MacOS](#using-pre-production-icds-on-windows-and-linux)
* [ICD Discovery on Android](#icd-discovery-on-android)
* [ICD Manifest File Format](#icd-manifest-file-format)
* [ICD Manifest File Versions](#icd-manifest-file-versions)
* [ICD Dispatchable Object Creation](#icd-dispatchable-object-creation)
* [Handling KHR Surface Objects in WSI Extensions](#handling-khr-surface-objects-in-wsi-extensions)
* [Loader and ICD Interface Negotiation](#loader-and-icd-interface-negotiation)
- * [Windows and Linux ICD Negotiation](#windows-and-linux-icd-negotiation)
+ * [Windows, Linux, and MacOS ICD Negotiation](#windows-and-linux-icd-negotiation)
* [Version Negotiation Between Loader and ICDs](#version-negotiation-between-loader-and-icds)
* [Interfacing With Legacy ICDs or Loader](#interfacing-with-legacy-icds-or-loader)
* [Loader Version 5 Interface Requirements](#loader-version-5-interface-requirements)
of available ICDs, the loader can enumerate all the physical devices available
for an application and return this information to the application. The process
in which the loader discovers the available Installable Client Drivers (ICDs)
-on a system is platform dependent. Windows, Linux and Android ICD discovery
+on a system is platform dependent. Windows, Linux, Android, and MacOS ICD discovery
details are listed below.
#### Overriding the Default ICD Usage
This is an example which is using the `VK_ICD_FILENAMES` override on Linux to point
to the Intel Mesa driver's ICD Manifest file.
+##### On MacOS
+
+```
+export VK_ICD_FILENAMES=/home/user/MoltenVK/Package/Latest/MoltenVK/macOS/MoltenVK_icd.json
+```
+
+This is an example which is using the `VK_ICD_FILENAMES` override on MacOS to point
+to an installation and build of the MoltenVK GitHub repository that contains the MoltenVK ICD.
#### ICD Manifest File Usage
-As with layers, on Windows and Linux systems, JSON formatted manifest files are
+As with layers, on Windows, Linux and MacOS systems, JSON formatted manifest files are
used to store ICD information. In order to find system-installed drivers, the
Vulkan loader will read the JSON files to identify the names and attributes of
each driver. One thing you will notice is that ICD Manifest files are much
See the [ICD Manifest File Format](#icd-manifest-file-format) section for more
details.
+#### ICD Discovery on MacOS
+
+In order to find installed ICDs, the Vulkan loader will scan the files
+in the following directories:
+
+```
+ <bundle>/Contents/Resources/vulkan/icd.d
+ /etc/vulkan/icd.d
+ /usr/local/share/vulkan/icd.d
+ /usr/share/vulkan/icd.d
+ $HOME/.local/share/vulkan/icd.d
+```
+
+The "/usr/local/*" directories can be configured to be other directories at
+build time.
+
+The typical usage of the directories is indicated in the table below.
+
+| Location | Details |
+|-------------------|------------------------|
+| <bundle>/Contents/Resources/vulkan/icd.d | Directory for ICDs that are bundled with the application (searched first) |
+| "/etc/vulkan/icd.d" | Location of ICDs installed manually |
+| "/usr/local/share/vulkan/icd.d" | Directory for locally built ICDs |
+| "/usr/share/vulkan/icd.d" | Location of ICDs installed from packages |
+| $HOME/.local/share/vulkan/icd.d | $HOME is the current home directory of the application's user id; this path will be ignored for suid programs |
+
+The Vulkan loader will open each manifest file found to obtain the name or
+pathname of an ICD shared library (".dylib") file.
+
+See the [ICD Manifest File Format](#icd-manifest-file-format) section for more
+details.
+
##### Additional Settings For ICD Debugging
If you are seeing issues which may be related to the ICD. A possible option to debug is to enable the
to fail on loading the ICD. It is recommended that you enable `LD_BIND_NOW` along with `VK_LOADER_DEBUG=warn`
to expose any issues.
-#### Using Pre-Production ICDs on Windows and Linux
+#### Using Pre-Production ICDs on Windows, Linux and MacOS
Independent Hardware Vendor (IHV) pre-production ICDs. In some cases, a
pre-production ICD may be in an installable package. In other cases, a
The "VK\_ICD\_FILENAMES" environment variable is a list of ICD
manifest files, containing the full path to the ICD JSON Manifest file. This
-list is colon-separated on Linux, and semi-colon separated on Windows.
+list is colon-separated on Linux and MacOS, and semi-colon separated on Windows.
Typically, "VK\_ICD\_FILENAMES" will only contain a full pathname to one info
file for a developer-built ICD. A separator (colon or semi-colon) is only used
if more than one ICD is listed.
-**NOTE:** On Linux, this environment variable will be ignored for suid programs.
+**NOTE:** On Linux and MacOS, this environment variable will be ignored for suid programs.
#### ICD Discovery on Android
|----------------|--------------------|
| "file\_format\_version" | The JSON format major.minor.patch version number of this file. Currently supported version is 1.0.0. |
| "ICD" | The identifier used to group all ICD information together. |
-| "library_path" | The "library\_path" specifies either a filename, a relative pathname, or a full pathname to a layer shared library file. If "library\_path" specifies a relative pathname, it is relative to the path of the JSON manifest file. If "library\_path" specifies a filename, the library must live in the system's shared object search path. There are no rules about the name of the ICD shared library files other than it should end with the appropriate suffix (".DLL" on Windows, and ".so" on Linux). | N/A |
+| "library_path" | The "library\_path" specifies either a filename, a relative pathname, or a full pathname to a layer shared library file. If "library\_path" specifies a relative pathname, it is relative to the path of the JSON manifest file. If "library\_path" specifies a filename, the library must live in the system's shared object search path. There are no rules about the name of the ICD shared library files other than it should end with the appropriate suffix (".DLL" on Windows, ".so" on Linux and "*.dylib" on MacOS). | N/A |
| "api_version" | The major.minor.patch version number of the Vulkan API that the shared library files for the ICD was built against. For example: 1.0.33. |
**NOTE:** If the same ICD shared library supports multiple, incompatible
### Handling KHR Surface Objects in WSI Extensions
Normally, ICDs handle object creation and destruction for various Vulkan
-objects. The WSI surface extensions for Linux and Windows
+objects. The WSI surface extensions for Linux, Windows, and MacOS
("VK\_KHR\_win32\_surface", "VK\_KHR\_xcb\_surface", "VK\_KHR\_xlib\_surface",
-"VK\_KHR\_mir\_surface", "VK\_KHR\_wayland\_surface", and "VK\_KHR\_surface")
+"VK\_KHR\_mir\_surface", "VK\_KHR\_wayland\_surface", "VK\_MVK\_macos\_surface"
+and "VK\_KHR\_surface")
are handled differently. For these extensions, the `VkSurfaceKHR` object
creation and destruction may be handled by either the loader, or an ICD.
* Xlib
* Windows
* Android
+ * MacOS (`vkCreateMacOSSurfaceMVK`)
2. The loader creates a `VkIcdSurfaceXXX` object for the corresponding
`vkCreateXXXSurfaceKHR` call.
* The `VkIcdSurfaceXXX` structures are defined in `include/vulkan/vk_icd.h`.
object. This object acts as a container for each ICD's version of the
`VkSurfaceKHR` object. If an ICD does not support the creation of its own
`VkSurfaceKHR` object, the loader's container stores a NULL for that ICD. On
-the otherhand, if the ICD does support `VkSurfaceKHR` creation, the loader will
+the other hand, if the ICD does support `VkSurfaceKHR` creation, the loader will
make the appropriate `vkCreateXXXSurfaceKHR` call to the ICD, and store the
returned pointer in it's container object. The loader then returns the
`VkSurfaceIcdXXX` as a `VkSurfaceKHR` object back up the call chain. Finally,
functions or their parameters, but simply calls the ICDs entry-point for that
function. There are specific additional interface requirements an ICD needs to
comply with that are not part of any requirements from the Vulkan specification.
-These addtional requirements are versioned to allow flexibility in the future.
+These additional requirements are versioned to allow flexibility in the future.
-#### Windows and Linux ICD Negotiation
+#### Windows, Linux and MacOS ICD Negotiation
##### Version Negotiation Between Loader and ICDs
table as described above. The only difference is that the Android
loader queries layer and extension information directly from the
respective libraries and does not use the json manifest files used
-by the Windows and Linux loaders.
+by the Windows, Linux and MacOS loaders.
## Table of Debug Environment Variables
| VK_ICD_FILENAMES | Force the loader to use the specific ICD JSON files. The value should contain a list of delimited full path listings to ICD JSON Manifest files. **NOTE:** If you fail to use the global path to a JSON file, you may encounter issues. | `export VK_ICD_FILENAMES=<folder_a>\intel.json:<folder_b>\amd.json`<br/><br/>`set VK_ICD_FILENAMES=<folder_a>\nvidia.json;<folder_b>\mesa.json` |
| VK_INSTANCE_LAYERS | Force the loader to add the given layers to the list of Enabled layers normally passed into `vkCreateInstance`. These layers are added first, and the loader will remove any duplicate layers that appear in both this list as well as that passed into `ppEnabledLayerNames`. | `export VK_INSTANCE_LAYERS=<layer_a>:<layer_b>`<br/><br/>`set VK_INSTANCE_LAYERS=<layer_a>;<layer_b>` |
| VK_LAYER_PATH | Override the loader's standard Layer library search folders and use the provided delimited folders to search for layer Manifest files. | `export VK_LAYER_PATH=<path_a>:<path_b>`<br/><br/>`set VK_LAYER_PATH=<path_a>;<pathb>` |
-| VK_LOADER_DISABLE_INST_EXT_FILTER | Disable the filtering out of instance extensions that the loader doesn't know about. This will allow applications to enable instance extensions exposed by ICDs but that the loader has no support for. **NOTE:** This may cause the loader or applciation to crash. | `export VK_LOADER_DISABLE_INST_EXT_FILTER=1`<br/><br/>`set VK_LOADER_DISABLE_INST_EXT_FILTER=1` |
+| VK_LOADER_DISABLE_INST_EXT_FILTER | Disable the filtering out of instance extensions that the loader doesn't know about. This will allow applications to enable instance extensions exposed by ICDs but that the loader has no support for. **NOTE:** This may cause the loader or application to crash. | `export VK_LOADER_DISABLE_INST_EXT_FILTER=1`<br/><br/>`set VK_LOADER_DISABLE_INST_EXT_FILTER=1` |
| VK_LOADER_DEBUG | Enable loader debug messages. Options are:<br/>- error (only errors)<br/>- warn (warnings and errors)<br/>- info (info, warning, and errors)<br/> - debug (debug + all before) <br/> -all (report out all messages) | `export VK_LOADER_DEBUG=all`<br/><br/>`set VK_LOADER_DEBUG=warn` |
## Glossary of Terms
| Field Name | Field Value |
|:---:|--------------------|
| Android Loader | The loader designed to work primarily for the Android OS. This is generated from a different code-base than the desktop loader. But, in all important aspects, should be functionally equivalent. |
-| Desktop Loader | The loader designed to work on both Windows and Linux. This is generated from a different [code-base](#https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers) than the Android loader. But in all important aspects, should be functionally equivalent. |
+| Desktop Loader | The loader designed to work on Windows, Linux and MacOS. This is generated from a different [code-base](#https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers) than the Android loader. But in all important aspects, should be functionally equivalent. |
| Core Function | A function that is already part of the Vulkan core specification and not an extension. For example, vkCreateDevice(). |
| Device Call Chain | The call chain of functions followed for device functions. This call chain for a device function is usually as follows: first the application calls into a loader trampoline, then the loader trampoline calls enabled layers, the final layer calls into the ICD specific to the device. See the [Dispatch Tables and Call Chains](#dispatch-tables-and-call-chains) section for more information |
| Device Function | A Device function is any Vulkan function which takes a `VkDevice`, `VkQueue`, `VkCommandBuffer`, or any child of these, as its first parameter. Some Vulkan Device functions are: `vkQueueSubmit`, `vkBeginCommandBuffer`, `vkCreateEvent`. See the [Instance Versus Device](#instance-versus-device) section for more information. |
-| Discovery | The process of the loader searching for ICD and Layer files to setup the internal list of Vulkan objects available. On Windows/Linux, the discovery process typically focuses on searching for Manifest files. While on Android, the process focuses on searching for library files. |
+| Discovery | The process of the loader searching for ICD and Layer files to setup the internal list of Vulkan objects available. On Windows/Linux/MacOS, the discovery process typically focuses on searching for Manifest files. While on Android, the process focuses on searching for library files. |
| Dispatch Table | An array of function pointers (including core and possibly extension functions) used to step to the next entity in a call chain. The entity could be the loader, a layer or an ICD. See [Dispatch Tables and Call Chains](#dispatch-tables-and-call-chains) for more information. |
| Extension | A concept of Vulkan used to expand the core Vulkan functionality. Extensions may be IHV-specific, platform-specific, or more broadly available. You should always query if an extension exists, and enable it during `vkCreateInstance` (if it is an instance extension) or during `vkCreateDevice` (if it is a device extension). |
| ICD | Acronym for Installable Client Driver. These are drivers that are provided by IHVs to interact with the hardware they provide. See [Installable Client Drivers](#installable-client-drivers) section for more information.
#include <stdbool.h>
#include <string.h>
#include <stddef.h>
-
+#if defined(__APPLE__)
+#include <CoreFoundation/CoreFoundation.h>
+#include <sys/param.h>
+#endif
#include <sys/types.h>
#if defined(_WIN32)
#include "dirent_on_windows.h"
}
// Environment variables
-#if defined(__linux__)
+#if defined(__linux__) || defined(__APPLE__)
static inline char *loader_getenv(const char *name, const struct loader_instance *inst) {
// No allocation of memory necessary for Linux, but we should at least touch
}
static inline char *loader_secure_getenv(const char *name, const struct loader_instance *inst) {
- // No allocation of memory necessary for Linux, but we should at least touch
- // the inst pointer to get rid of compiler warnings.
- (void)inst;
-
+#if defined(__APPLE__)
+ // Apple does not appear to have a secure getenv implementation.
+ // The main difference between secure getenv and getenv is that secure getenv
+ // returns NULL if the process is being run with elevated privileges by a normal user.
+ // The idea is to prevent the reading of malicious environment variables by a process
+ // that can do damage.
+ // This algorithm is derived from glibc code that sets an internal
+ // variable (__libc_enable_secure) if the process is running under setuid or setgid.
+ return geteuid() != getuid() || getegid() != getgid() ? NULL : loader_getenv(name, inst);
+#else
+// Linux
#ifdef HAVE_SECURE_GETENV
+ (void)inst;
return secure_getenv(name);
#elif defined(HAVE___SECURE_GETENV)
+ (void)inst;
return __secure_getenv(name);
#else
#pragma message( \
" updating to a different libc.")
return loader_getenv(name, inst);
#endif
+#endif
}
static inline void loader_free_getenv(char *val, const struct loader_instance *inst) {
override = override_getenv = loader_secure_getenv(env_override, inst);
}
}
-
#if !defined(_WIN32)
if (relative_location == NULL) {
#else
#if defined(EXTRASYSCONFDIR)
loc_size += strlen(EXTRASYSCONFDIR) + rel_size + 1;
#endif
+#if defined(__APPLE__)
+ // For bundle path
+ loc_size += MAXPATHLEN;
+#endif
#else
loc_size += strlen(location) + 1;
#endif
const char *loc_read;
size_t start, stop;
+#if defined(__APPLE__)
+ // Add the bundle's Resources dir to the beginning of the search path.
+ // Looks for manifests in the bundle first, before any system directories.
+ CFBundleRef main_bundle = CFBundleGetMainBundle();
+ if (NULL != main_bundle) {
+ CFURLRef ref = CFBundleCopyResourcesDirectoryURL(main_bundle);
+ if (NULL != ref) {
+ if (CFURLGetFileSystemRepresentation(ref, TRUE, (UInt8 *)loc_write, loc_size)) {
+ loc_write += strlen(loc_write);
+ memcpy(loc_write, relative_location, rel_size);
+ loc_write += rel_size;
+ *loc_write++ = PATH_SEPARATOR;
+ }
+ CFRelease(ref);
+ }
+ }
+#endif
loc_read = &xdgconfdirs[0];
start = 0;
while (loc_read[start] != '\0') {
#ifdef VK_USE_PLATFORM_ANDROID_KHR
bool wsi_android_surface_enabled;
#endif
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+ bool wsi_macos_surface_enabled;
+#endif
+#ifdef VK_USE_PLATFORM_IOS_MVK
+ bool wsi_ios_surface_enabled;
+#endif
bool wsi_display_enabled;
};
#include "vulkan/vk_platform.h"
#include "vulkan/vk_sdk_platform.h"
-#if defined(__linux__)
+#if defined(__linux__) || defined(__APPLE__)
/* Linux-specific common code: */
// Headers:
#ifdef VK_USE_PLATFORM_ANDROID_KHR
ptr_instance->wsi_android_surface_enabled = false;
#endif // VK_USE_PLATFORM_ANDROID_KHR
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+ ptr_instance->wsi_macos_surface_enabled = false;
+#endif // VK_USE_PLATFORM_MACOS_MVK
+#ifdef VK_USE_PLATFORM_IOS_MVK
+ ptr_instance->wsi_ios_surface_enabled = false;
+#endif // VK_USE_PLATFORM_IOS_MVK
ptr_instance->wsi_display_enabled = false;
continue;
}
#endif // VK_USE_PLATFORM_ANDROID_KHR
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+ if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_MVK_MACOS_SURFACE_EXTENSION_NAME) == 0) {
+ ptr_instance->wsi_macos_surface_enabled = true;
+ continue;
+ }
+#endif // VK_USE_PLATFORM_MACOS_MVK
+#ifdef VK_USE_PLATFORM_IOS_MVK
+ if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_MVK_IOS_SURFACE_EXTENSION_NAME) == 0) {
+ ptr_instance->wsi_ios_surface_enabled = true;
+ continue;
+ }
+#endif // VK_USE_PLATFORM_IOS_MVK
if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_DISPLAY_EXTENSION_NAME) == 0) {
ptr_instance->wsi_display_enabled = true;
continue;
}
VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo,
- const VkAllocationCallbacks *pAllocator,
- VkSwapchainKHR *pSwapchain) {
+ const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain) {
uint32_t icd_index = 0;
struct loader_device *dev;
struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, &icd_index);
}
pIcdSurface->base.platform = VK_ICD_WSI_PLATFORM_ANDROID;
- pIcdSurface->dpy = dpy;
pIcdSurface->window = window;
*pSurface = (VkSurfaceKHR)pIcdSurface;
#endif // VK_USE_PLATFORM_ANDROID_KHR
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+
+// Functions for the VK_MVK_macos_surface extension:
+
+// This is the trampoline entrypoint for CreateMacOSSurfaceMVK
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateMacOSSurfaceMVK(VkInstance instance,
+ const VkMacOSSurfaceCreateInfoMVK *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkSurfaceKHR *pSurface) {
+ const VkLayerInstanceDispatchTable *disp;
+ disp = loader_get_instance_layer_dispatch(instance);
+ VkResult res;
+
+ res = disp->CreateMacOSSurfaceMVK(instance, pCreateInfo, pAllocator, pSurface);
+ return res;
+}
+
+// This is the instance chain terminator function for CreateMacOSSurfaceKHR
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateMacOSSurfaceMVK(VkInstance instance, const VkMacOSSurfaceCreateInfoMVK *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
+ VkResult vkRes = VK_SUCCESS;
+ VkIcdSurface *pIcdSurface = NULL;
+ uint32_t i = 0;
+
+ // First, check to ensure the appropriate extension was enabled:
+ struct loader_instance *ptr_instance = loader_get_instance(instance);
+ if (!ptr_instance->wsi_macos_surface_enabled) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "VK_MVK_macos_surface extension not enabled. vkCreateMacOSSurfaceMVK not executed!\n");
+ vkRes = VK_ERROR_EXTENSION_NOT_PRESENT;
+ goto out;
+ }
+
+ // Next, if so, proceed with the implementation of this function:
+ pIcdSurface = AllocateIcdSurfaceStruct(ptr_instance, sizeof(pIcdSurface->macos_surf.base), sizeof(pIcdSurface->macos_surf));
+ if (pIcdSurface == NULL) {
+ vkRes = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ pIcdSurface->macos_surf.base.platform = VK_ICD_WSI_PLATFORM_MACOS;
+ pIcdSurface->macos_surf.pView = pCreateInfo->pView;
+
+ // Loop through each ICD and determine if they need to create a surface
+ for (struct loader_icd_term *icd_term = ptr_instance->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
+ if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
+ if (NULL != icd_term->dispatch.CreateMacOSSurfaceMVK) {
+ vkRes = icd_term->dispatch.CreateMacOSSurfaceMVK(icd_term->instance, pCreateInfo, pAllocator,
+ &pIcdSurface->real_icd_surfaces[i]);
+ if (VK_SUCCESS != vkRes) {
+ goto out;
+ }
+ }
+ }
+ }
+
+ *pSurface = (VkSurfaceKHR)pIcdSurface;
+
+out:
+
+ if (VK_SUCCESS != vkRes && NULL != pIcdSurface) {
+ if (NULL != pIcdSurface->real_icd_surfaces) {
+ i = 0;
+ for (struct loader_icd_term *icd_term = ptr_instance->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
+ if ((VkSurfaceKHR)NULL != pIcdSurface->real_icd_surfaces[i] && NULL != icd_term->dispatch.DestroySurfaceKHR) {
+ icd_term->dispatch.DestroySurfaceKHR(icd_term->instance, pIcdSurface->real_icd_surfaces[i], pAllocator);
+ }
+ }
+ loader_instance_heap_free(ptr_instance, pIcdSurface->real_icd_surfaces);
+ }
+ loader_instance_heap_free(ptr_instance, pIcdSurface);
+ }
+
+ return vkRes;
+}
+
+#endif // VK_USE_PLATFORM_MACOS_MVK
+
+#ifdef VK_USE_PLATFORM_IOS_MVK
+
+// Functions for the VK_MVK_ios_surface extension:
+
+// This is the trampoline entrypoint for CreateIOSSurfaceMVK
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateIOSSurfaceMVK(VkInstance instance,
+ const VkIOSSurfaceCreateInfoMVK *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkSurfaceKHR *pSurface) {
+ const VkLayerInstanceDispatchTable *disp;
+ disp = loader_get_instance_layer_dispatch(instance);
+ VkResult res;
+
+ res = disp->CreateIOSSurfaceMVK(instance, pCreateInfo, pAllocator, pSurface);
+ return res;
+}
+
+// This is the instance chain terminator function for CreateIOSSurfaceKHR
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateIOSSurfaceMVK(VkInstance instance, const VkIOSSurfaceCreateInfoMVK *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
+ // First, check to ensure the appropriate extension was enabled:
+ struct loader_instance *ptr_instance = loader_get_instance(instance);
+ if (!ptr_instance->wsi_ios_surface_enabled) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "VK_MVK_ios_surface extension not enabled. vkCreateIOSSurfaceMVK not executed!\n");
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+
+ // Next, if so, proceed with the implementation of this function:
+ VkIcdSurfaceIOS *pIcdSurface =
+ loader_instance_heap_alloc(ptr_instance, sizeof(VkIcdSurfaceIOS), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ if (pIcdSurface == NULL) {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+
+ pIcdSurface->base.platform = VK_ICD_WSI_PLATFORM_IOS;
+ pIcdSurface->pView = pCreateInfo->pView;
+
+ *pSurface = (VkSurfaceKHR)pIcdSurface;
+
+ return VK_SUCCESS;
+}
+
+#endif // VK_USE_PLATFORM_IOS_MVK
+
// Functions for the VK_KHR_display instance extension:
LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physicalDevice,
uint32_t *pPropertyCount,
// Functions for the VK_KHR_android_surface extension:
if (!strcmp("vkCreateAndroidSurfaceKHR", name)) {
- *addr = ptr_instance->wsi_xlib_surface_enabled ? (void *)vkCreateAndroidSurfaceKHR : NULL;
+ *addr = ptr_instance->wsi_android_surface_enabled ? (void *)vkCreateAndroidSurfaceKHR : NULL;
return true;
}
#endif // VK_USE_PLATFORM_ANDROID_KHR
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+
+ // Functions for the VK_MVK_macos_surface extension:
+ if (!strcmp("vkCreateMacOSSurfaceMVK", name)) {
+ *addr = ptr_instance->wsi_macos_surface_enabled ? (void *)vkCreateMacOSSurfaceMVK : NULL;
+ return true;
+ }
+#endif // VK_USE_PLATFORM_MACOS_MVK
+#ifdef VK_USE_PLATFORM_IOS_MVK
+
+ // Functions for the VK_MVK_ios_surface extension:
+ if (!strcmp("vkCreateIOSSurfaceMVK", name)) {
+ *addr = ptr_instance->wsi_ios_surface_enabled ? (void *)vkCreateIOSSurfaceMVK : NULL;
+ return true;
+ }
+#endif // VK_USE_PLATFORM_IOS_MVK
// Functions for VK_KHR_display extension:
if (!strcmp("vkGetPhysicalDeviceDisplayPropertiesKHR", name)) {
#ifdef VK_USE_PLATFORM_XLIB_KHR
VkIcdSurfaceXlib xlib_surf;
#endif // VK_USE_PLATFORM_XLIB_KHR
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+ VkIcdSurfaceMacOS macos_surf;
+#endif // VK_USE_PLATFORM_MACOS_MVK
VkIcdSurfaceDisplay display_surf;
};
uint32_t base_size; // Size of VkIcdSurfaceBase
uint32_t queueFamilyIndex, Display *dpy,
VisualID visualID);
#endif
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateMacOSSurfaceMVK(VkInstance instance, const VkMacOSSurfaceCreateInfoMVK *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface);
+#endif
+#ifdef VK_USE_PLATFORM_IOS_MVK
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateIOSSurfaceMVK(VkInstance instance, const VkIOSSurfaceCreateInfoMVK *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface);
+#endif
VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physicalDevice,
uint32_t *pPropertyCount,
VkDisplayPropertiesKHR *pProperties);
const VkAllocationCallbacks *pAllocator,
VkSwapchainKHR *pSwapchains);
-#endif // WSI_H
+#endif // WSI_H
'VK_KHR_mir_surface',
'VK_KHR_win32_surface',
'VK_KHR_android_surface',
+ 'VK_MVK_macos_surface',
+ 'VK_MVK_ios_surface',
'VK_KHR_swapchain',
'VK_KHR_display_swapchain']
add_definitions(-DVK_USE_PLATFORM_MIR_KHR)
include_directories(${MIR_INCLUDE_DIR})
endif()
+elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ add_definitions(-DVK_USE_PLATFORM_MACOS_MVK)
else()
message(FATAL_ERROR "Unsupported Platform!")
endif()
${gtest_SOURCE_DIR})
# Where Google Test's libraries can be found.
-link_directories(${gtest_BINARY_DIR}/src)
+link_directories(${gtest_BINARY_DIR})
########################################################################
#
set_target_properties(${config_file}-json PROPERTIES FOLDER ${LVL_TARGET_FOLDER})
endforeach(config_file)
endif()
+elseif(APPLE)
+ # extra setup for out-of-tree builds
+ if (NOT (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR))
+ foreach (config_file ${LAYER_JSON_FILES})
+ add_custom_target(${config_file}-json ALL
+ COMMAND ln -sf ${CMAKE_CURRENT_SOURCE_DIR}/macos/${config_file}.json
+ VERBATIM
+ )
+ endforeach(config_file)
+ endif()
else()
# extra setup for out-of-tree builds
if (NOT (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR))
add_library(VkLayer_${target} SHARED ${ARGN} VkLayer_${target}.def)
add_dependencies(VkLayer_${target} generate_helper_files VkLayer_utils)
endmacro()
+elseif(APPLE)
+ macro(add_vk_layer target)
+ add_library(VkLayer_${target} SHARED ${ARGN})
+ add_dependencies(VkLayer_${target} generate_helper_files VkLayer_utils)
+ set_target_properties(VkLayer_${target} PROPERTIES LINK_FLAGS "-Wl")
+ endmacro()
else()
macro(add_vk_layer target)
add_library(VkLayer_${target} SHARED ${ARGN})
add_custom_command(TARGET VkLayer_device_profile_api POST_BUILD
COMMAND xcopy /Y /I ${SRC_LAYER} ${DST_LAYER}
COMMAND xcopy /Y /I ${SRC_JSON} ${DST_LAYER})
+elseif(APPLE)
+ if (CMAKE_GENERATOR MATCHES "^Xcode.*")
+ add_custom_command(TARGET VkLayer_device_profile_api POST_BUILD
+ COMMAND ln -sf ${CMAKE_CURRENT_BINARY_DIR}/VkLayer_device_profile_api.json ${CMAKE_BINARY_DIR}/layers/$<CONFIG>
+ COMMAND ln -sf ${CMAKE_CURRENT_BINARY_DIR}/libVkLayer_device_profile_api.dylib ${CMAKE_BINARY_DIR}/layers/$<CONFIG>
+ VERBATIM
+ )
+ else()
+ add_custom_command(TARGET VkLayer_device_profile_api POST_BUILD
+ COMMAND ln -sf ${CMAKE_CURRENT_BINARY_DIR}/VkLayer_device_profile_api.json ${CMAKE_BINARY_DIR}/layers
+ COMMAND ln -sf ${CMAKE_CURRENT_BINARY_DIR}/libVkLayer_device_profile_api.dylib ${CMAKE_BINARY_DIR}/layers
+ VERBATIM
+ )
+ endif()
else()
add_custom_command(TARGET VkLayer_device_profile_api POST_BUILD
COMMAND ln -sf ${CMAKE_CURRENT_BINARY_DIR}/VkLayer_device_profile_api.json ${PROJECT_BINARY_DIR}/layers
--- /dev/null
+{
+ "file_format_version" : "1.1.0",
+ "layer" : {
+ "name": "VK_LAYER_LUNARG_device_profile_api",
+ "type": "GLOBAL",
+ "library_path": "./libVkLayer_device_profile_api.dylib",
+ "api_version": "1.0.69",
+ "implementation_version": "2",
+ "description": "LunarG Device Profile Api Layer",
+ "device_extensions": [
+ {
+ "name": "VK_LUNARG_LayerDeviceProfileApiEXT",
+ "spec_version": "0",
+ "entrypoints": ["vkSetPhysicalDeviceLimitsEXT", "vkGetOriginalPhysicalDeviceLimitsEXT"]
+ }
+ ]
+ }
+}
--- /dev/null
+{
+ "file_format_version" : "1.0.0",
+ "layer" : {
+ "name": "VK_LAYER_LUNARG_test",
+ "type": "GLOBAL",
+ "library_path": "./libVkLayer_test.dylib",
+ "api_version": "1.0.69",
+ "implementation_version": "1",
+ "description": "LunarG Test Layer",
+ "enable_environment": {
+ "ENABLE_LAYER_TEST_1": "enable"
+ },
+ "disable_environment": {
+ "DISABLE_LAYER_TEST_1": ""
+ }
+ }
+}
--- /dev/null
+{
+ "file_format_version" : "1.0.0",
+ "layer" : {
+ "name": "VK_LAYER_LUNARG_wrap_objects",
+ "type": "GLOBAL",
+ "library_path": "./libVkLayer_wrap_objects.dylib",
+ "api_version": "1.0.69",
+ "implementation_version": "1",
+ "description": "LunarG Dispatchable Object Wrapping Layer"
+ }
+}
ADD_FAILURE_AT(file, line) << "Assertion: `" << expr << "'";
}
-#if defined(__linux__)
+#if defined(__linux__) || defined(__APPLE__)
/* Linux-specific common code: */
#include <pthread.h>
make install
}
+function create_moltenvk () {
+ rm -rf "${BASEDIR}"/MoltenVK
+ echo "Creating local MoltenVK repository (${BASEDIR}/MoltenVK)."
+ mkdir -p "${BASEDIR}"/MoltenVK
+ cd "${BASEDIR}"/MoltenVK
+ git clone --recurse-submodules https://github.com/KhronosGroup/MoltenVK.git "${BASEDIR}"/MoltenVK
+}
+
+function update_moltenvk () {
+ echo "Updating ${BASEDIR}/MoltenVK"
+ cd "${BASEDIR}"/MoltenVK
+ git pull
+}
+
+function build_moltenvk () {
+ echo "Building ${BASEDIR}/MoltenVK"
+ cd "${BASEDIR}"/MoltenVK/External
+ ./makeAll
+ cd "${BASEDIR}"/MoltenVK
+ xcodebuild -project MoltenVKPackaging.xcodeproj \
+ GCC_PREPROCESSOR_DEFINITIONS='$GCC_PREPROCESSOR_DEFINITIONS MVK_LOGGING_ENABLED=0' \
+ -scheme "MoltenVK (Release)" build
+}
+
INCLUDE_GLSLANG=false
+INCLUDE_MOLTENVK=false
NO_SYNC=false
NO_BUILD=false
USE_IMPLICIT_COMPONENT_LIST=true
USE_IMPLICIT_COMPONENT_LIST=false
echo "Building glslang ($option)"
;;
+ # options to specify build of moltenvk components
+ -m|--moltenvk)
+ if [[ $(uname) == "Darwin" ]]; then
+ INCLUDE_MOLTENVK=true
+ USE_IMPLICIT_COMPONENT_LIST=false
+ echo "Building MoltenVK ($option)"
+ fi
+ ;;
# options to specify build of spirv-tools components
-s|--spirv-tools)
echo "($option) is deprecated and is no longer necessary"
echo "Usage: update_external_sources.sh [options]"
echo " Available options:"
echo " -g | --glslang # enable glslang component"
+ if [[ $(uname) == "Darwin" ]]; then
+ echo " -m | --moltenvk # enable moltenvk component"
+ fi
echo " --no-sync # skip sync from git"
echo " --no-build # skip build"
echo " If any component enables are provided, only those components are enabled."
if [ ${USE_IMPLICIT_COMPONENT_LIST} == "true" ]; then
echo "Building glslang"
INCLUDE_GLSLANG=true
+ if [[ $(uname) == "Darwin" ]]; then
+ echo "Building MoltenVK"
+ INCLUDE_MOLTENVK=true
+ fi
fi
if [ ${INCLUDE_GLSLANG} == "true" ]; then
build_glslang
fi
fi
+
+if [ ${INCLUDE_MOLTENVK} == "true" ]; then
+ if [ ${NO_SYNC} == "false" ]; then
+ if [ ! -d "${BASEDIR}/MoltenVK" -o ! -d "${BASEDIR}/MoltenVK/.git" ]; then
+ create_moltenvk
+ fi
+ update_moltenvk
+ fi
+ if [ ${NO_BUILD} == "false" ]; then
+ echo "Building moltenvk"
+ build_moltenvk
+ fi
+fi
+