diff --git a/README.md b/README.md
index 3c2b22a93f..d7c2abb147 100644
--- a/README.md
+++ b/README.md
@@ -33,6 +33,10 @@ Note that you need [assimp](https://github.com/assimp/assimp) in order to compil
Building on Android is done using the [Android NDK](http://developer.android.com/tools/sdk/ndk/index.html) and requires a device that supports Vulkan. Please see the [Android readme](./android/README.md) on how to build and deploy the examples.
+## [iOS and macOS](xcode/)
+
+Building for *iOS* and *macOS* is done using the [examples](xcode/examples.xcodeproj) *Xcode* project found in the [xcode](xcode) directory. These examples use the [**MoltenVK**](https://moltengl.com/moltenvk) Vulkan driver to provide Vulkan support on *iOS* and *macOS*, and require an *iOS* or *macOS* device that supports *Metal*. Please see the [MoltenVK Examples readme](xcode/README_MoltenVK_Examples.md) for more info on acquiring **MoltenVK** and building and deploying the examples on *iOS* and *macOS*.
+
## Additional asset pack
**Note:** Binary assets (textures, models) will no longer be added directly to the repository to keep it's size down, so newer examples will require the download of an [additional asset pack](data/README.md).
diff --git a/base/VulkanSwapChain.hpp b/base/VulkanSwapChain.hpp
index 324e1b19e8..dbdce6cab5 100644
--- a/base/VulkanSwapChain.hpp
+++ b/base/VulkanSwapChain.hpp
@@ -107,6 +107,9 @@ class VulkanSwapChain
#ifdef __ANDROID__
ANativeWindow* window
#else
+#if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
+ void* view
+#else
#ifdef _DIRECT2DISPLAY
uint32_t width, uint32_t height
#else
@@ -117,6 +120,7 @@ class VulkanSwapChain
#endif
#endif
#endif
+#endif
#endif
)
{
@@ -136,6 +140,22 @@ class VulkanSwapChain
surfaceCreateInfo.window = window;
err = vkCreateAndroidSurfaceKHR(instance, &surfaceCreateInfo, NULL, &surface);
#else
+#ifdef VK_USE_PLATFORM_IOS_MVK
+ VkIOSSurfaceCreateInfoMVK surfaceCreateInfo = {};
+ surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK;
+ surfaceCreateInfo.pNext = NULL;
+ surfaceCreateInfo.flags = 0;
+ surfaceCreateInfo.pView = view;
+ err = vkCreateIOSSurfaceMVK(instance, &surfaceCreateInfo, nullptr, &surface);
+#else
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+ VkMacOSSurfaceCreateInfoMVK surfaceCreateInfo = {};
+ surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
+ surfaceCreateInfo.pNext = NULL;
+ surfaceCreateInfo.flags = 0;
+ surfaceCreateInfo.pView = view;
+ err = vkCreateMacOSSurfaceMVK(instance, &surfaceCreateInfo, NULL, &surface);
+#else
#if defined(_DIRECT2DISPLAY)
createDirect2DisplaySurface(width, height);
#else
@@ -154,6 +174,8 @@ class VulkanSwapChain
#endif
#endif
#endif
+#endif
+#endif
#endif
if (err != VK_SUCCESS) {
diff --git a/base/keycodes.hpp b/base/keycodes.hpp
index 98bc0db11b..5218110965 100644
--- a/base/keycodes.hpp
+++ b/base/keycodes.hpp
@@ -52,6 +52,56 @@
#define KEY_N 0xE
#define KEY_O 0xF
#define KEY_T 0x10
+
+#elif defined(VK_USE_PLATFORM_IOS_MVK)
+// Use numeric keys instead of function keys.
+// Use main keyboard plus/minus instead of keypad plus/minus
+// Use Delete key instead of Escape key.
+#define KEY_ESCAPE 0x33
+#define KEY_F1 '1'
+#define KEY_F2 '2'
+#define KEY_F3 '3'
+#define KEY_F4 '4'
+#define KEY_W 'w'
+#define KEY_A 'a'
+#define KEY_S 's'
+#define KEY_D 'd'
+#define KEY_P 'p'
+#define KEY_SPACE ' '
+#define KEY_KPADD '+'
+#define KEY_KPSUB '-'
+#define KEY_B 'b'
+#define KEY_F 'f'
+#define KEY_L 'l'
+#define KEY_N 'n'
+#define KEY_O 'o'
+#define KEY_T 't'
+
+#elif defined(VK_USE_PLATFORM_MACOS_MVK)
+// For compatibility with iOS UX and absent keypad on MacBook:
+// - Use numeric keys instead of function keys
+// - Use main keyboard plus/minus instead of keypad plus/minus
+// - Use Delete key instead of Escape key
+#define KEY_ESCAPE 0x33
+#define KEY_F1 0x12
+#define KEY_F2 0x13
+#define KEY_F3 0x14
+#define KEY_F4 0x15
+#define KEY_W 0x0D
+#define KEY_A 0x00
+#define KEY_S 0x01
+#define KEY_D 0x02
+#define KEY_P 0x23
+#define KEY_SPACE 0x31
+#define KEY_KPADD 0x18
+#define KEY_KPSUB 0x1B
+#define KEY_B 0x0B
+#define KEY_F 0x03
+#define KEY_L 0x25
+#define KEY_N 0x2D
+#define KEY_O 0x1F
+#define KEY_T 0x11
+
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
#include
diff --git a/base/vulkanexamplebase.cpp b/base/vulkanexamplebase.cpp
index fddbfc7f48..655493e179 100644
--- a/base/vulkanexamplebase.cpp
+++ b/base/vulkanexamplebase.cpp
@@ -73,6 +73,8 @@ std::string VulkanExampleBase::getWindowTitle()
return windowTitle;
}
+#if !(defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
+// iOS & macOS: VulkanExampleBase::getAssetPath() implemented externally to allow access to Objective-C components
const std::string VulkanExampleBase::getAssetPath()
{
#if defined(__ANDROID__)
@@ -81,6 +83,7 @@ const std::string VulkanExampleBase::getAssetPath()
return "./../data/";
#endif
}
+#endif
bool VulkanExampleBase::checkCommandBuffers()
{
@@ -215,6 +218,45 @@ VkPipelineShaderStageCreateInfo VulkanExampleBase::loadShader(std::string fileNa
return shaderStage;
}
+void VulkanExampleBase::renderFrame()
+{
+#if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
+ auto tStart = std::chrono::high_resolution_clock::now();
+ if (viewUpdated)
+ {
+ viewUpdated = false;
+ viewChanged();
+ }
+ render();
+ frameCounter++;
+ auto tEnd = std::chrono::high_resolution_clock::now();
+ auto tDiff = std::chrono::duration(tEnd - tStart).count();
+ frameTimer = tDiff / 1000.0f;
+ camera.update(frameTimer);
+ if (camera.moving())
+ {
+ viewUpdated = true;
+ }
+ // Convert to clamped timer value
+ if (!paused)
+ {
+ timer += timerSpeed * frameTimer;
+ if (timer > 1.0)
+ {
+ timer -= 1.0f;
+ }
+ }
+ fpsTimer += (float)tDiff;
+ if (fpsTimer > 1000.0f)
+ {
+ lastFPS = frameCounter;
+ updateTextOverlay();
+ fpsTimer = 0.0f;
+ frameCounter = 0;
+ }
+#endif
+}
+
void VulkanExampleBase::renderLoop()
{
destWidth = width;
@@ -1332,6 +1374,12 @@ void VulkanExampleBase::handleAppCommand(android_app * app, int32_t cmd)
break;
}
}
+#elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
+void* VulkanExampleBase::setupWindow(void* view)
+{
+ this->view = view;
+ return view;
+}
#elif defined(_DIRECT2DISPLAY)
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
/*static*/void VulkanExampleBase::registryGlobalCb(void *data,
@@ -2096,6 +2144,8 @@ void VulkanExampleBase::initSwapchain()
swapChain.initSurface(windowInstance, window);
#elif defined(__ANDROID__)
swapChain.initSurface(androidApp->window);
+#elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
+ swapChain.initSurface(view);
#elif defined(_DIRECT2DISPLAY)
swapChain.initSurface(width, height);
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
diff --git a/base/vulkanexamplebase.h b/base/vulkanexamplebase.h
index 32477f8b5c..41134176b3 100644
--- a/base/vulkanexamplebase.h
+++ b/base/vulkanexamplebase.h
@@ -209,6 +209,8 @@ class VulkanExampleBase
int64_t lastTapTime = 0;
/** @brief Product model and manufacturer of the Android device (via android.Product*) */
std::string androidProduct;
+#elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
+ void* view;
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
wl_display *display = nullptr;
wl_registry *registry = nullptr;
@@ -256,6 +258,8 @@ class VulkanExampleBase
#elif defined(__ANDROID__)
static int32_t handleAppInput(struct android_app* app, AInputEvent* event);
static void handleAppCommand(android_app* app, int32_t cmd);
+#elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
+ void* setupWindow(void* view);
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
wl_shell_surface *setupWindow();
void initWaylandConnection();
@@ -375,6 +379,9 @@ class VulkanExampleBase
// Start the main render loop
void renderLoop();
+ // Render one frame of a render loop on platforms that sync rendering
+ void renderFrame();
+
void updateTextOverlay();
/** @brief (Virtual) Called when the text overlay is updating, can be used to add custom text to the overlay */
@@ -489,4 +496,6 @@ int main(const int argc, const char *argv[]) \
delete(vulkanExample); \
return 0; \
}
+#elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
+#define VULKAN_EXAMPLE_MAIN()
#endif
diff --git a/hdr/hdr.cpp b/hdr/hdr.cpp
index d6025e784d..1ce7ad22cd 100644
--- a/hdr/hdr.cpp
+++ b/hdr/hdr.cpp
@@ -606,7 +606,7 @@ class VulkanExample : public VulkanExampleBase
std::vector filenames = { "geosphere.obj", "teapot.dae", "torusknot.obj", "venus.fbx" };
for (auto file : filenames) {
vks::Model model;
- model.loadFromFile(ASSET_PATH "models/" + file, vertexLayout, 0.05f * (file == "venus.fbx" ? 3.0f : 1.0f), vulkanDevice, queue);
+ model.loadFromFile(getAssetPath() + "models/" + file, vertexLayout, 0.05f * (file == "venus.fbx" ? 3.0f : 1.0f), vulkanDevice, queue);
models.objects.push_back(model);
}
// Load HDR cube map
diff --git a/images/applelogo.png b/images/applelogo.png
new file mode 100644
index 0000000000..31f83b0458
Binary files /dev/null and b/images/applelogo.png differ
diff --git a/images/vulkanlogo.png b/images/vulkanlogo.png
index c31b340cea..09bbb8687c 100644
Binary files a/images/vulkanlogo.png and b/images/vulkanlogo.png differ
diff --git a/multisampling/multisampling.cpp b/multisampling/multisampling.cpp
index aa6978d2ed..408757972e 100644
--- a/multisampling/multisampling.cpp
+++ b/multisampling/multisampling.cpp
@@ -8,9 +8,9 @@
#include
#include
-#include
#include
#include
+#include
#define GLM_FORCE_RADIANS
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
@@ -25,7 +25,6 @@
#define VERTEX_BUFFER_BIND_ID 0
#define ENABLE_VALIDATION false
-#define SAMPLE_COUNT VK_SAMPLE_COUNT_8_BIT
struct {
struct {
@@ -44,6 +43,7 @@ class VulkanExample : public VulkanExampleBase
{
public:
bool useSampleShading = false;
+ VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT;
struct {
vks::Texture2D colorMap;
@@ -123,7 +123,7 @@ class VulkanExample : public VulkanExampleBase
void setupMultisampleTarget()
{
// Check if device supports requested sample count for color and depth frame buffer
- assert((deviceProperties.limits.framebufferColorSampleCounts >= SAMPLE_COUNT) && (deviceProperties.limits.framebufferDepthSampleCounts >= SAMPLE_COUNT));
+ assert((deviceProperties.limits.framebufferColorSampleCounts >= sampleCount) && (deviceProperties.limits.framebufferDepthSampleCounts >= sampleCount));
// Color target
VkImageCreateInfo info = vks::initializers::imageCreateInfo();
@@ -136,7 +136,7 @@ class VulkanExample : public VulkanExampleBase
info.arrayLayers = 1;
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
info.tiling = VK_IMAGE_TILING_OPTIMAL;
- info.samples = SAMPLE_COUNT;
+ info.samples = sampleCount;
// Image will only be used as a transient target
info.usage = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
@@ -184,7 +184,7 @@ class VulkanExample : public VulkanExampleBase
info.arrayLayers = 1;
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
info.tiling = VK_IMAGE_TILING_OPTIMAL;
- info.samples = SAMPLE_COUNT;
+ info.samples = sampleCount;
// Image will only be used as a transient target
info.usage = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
@@ -230,7 +230,7 @@ class VulkanExample : public VulkanExampleBase
// Multisampled attachment that we render to
attachments[0].format = swapChain.colorFormat;
- attachments[0].samples = SAMPLE_COUNT;
+ attachments[0].samples = sampleCount;
attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
// No longer required after resolve, this may save some bandwidth on certain GPUs
attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
@@ -252,7 +252,7 @@ class VulkanExample : public VulkanExampleBase
// Multisampled depth attachment we render to
attachments[2].format = depthFormat;
- attachments[2].samples = SAMPLE_COUNT;
+ attachments[2].samples = sampleCount;
attachments[2].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attachments[2].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachments[2].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
@@ -630,7 +630,7 @@ class VulkanExample : public VulkanExampleBase
shaderStages[0] = loadShader(getAssetPath() + "shaders/mesh/mesh.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
shaderStages[1] = loadShader(getAssetPath() + "shaders/mesh/mesh.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
// Setup multi sampling
- multisampleState.rasterizationSamples = SAMPLE_COUNT; // Number of samples to use for rasterization
+ multisampleState.rasterizationSamples = sampleCount; // Number of samples to use for rasterization
VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.MSAA));
@@ -693,6 +693,7 @@ class VulkanExample : public VulkanExampleBase
void prepare()
{
+ sampleCount = getMaxUsableSampleCount();
VulkanExampleBase::prepare();
loadAssets();
setupVertexDescriptions();
@@ -733,6 +734,22 @@ class VulkanExample : public VulkanExampleBase
break;
}
}
+
+ // Returns the maximum sample count usable by the platform
+ VkSampleCountFlagBits getMaxUsableSampleCount()
+ {
+ VkSampleCountFlags counts = std::min(deviceProperties.limits.framebufferColorSampleCounts,
+ deviceProperties.limits.framebufferDepthSampleCounts);
+
+ if (counts & VK_SAMPLE_COUNT_64_BIT) { return VK_SAMPLE_COUNT_64_BIT; }
+ if (counts & VK_SAMPLE_COUNT_32_BIT) { return VK_SAMPLE_COUNT_32_BIT; }
+ if (counts & VK_SAMPLE_COUNT_16_BIT) { return VK_SAMPLE_COUNT_16_BIT; }
+ if (counts & VK_SAMPLE_COUNT_8_BIT) { return VK_SAMPLE_COUNT_8_BIT; }
+ if (counts & VK_SAMPLE_COUNT_4_BIT) { return VK_SAMPLE_COUNT_4_BIT; }
+ if (counts & VK_SAMPLE_COUNT_2_BIT) { return VK_SAMPLE_COUNT_2_BIT; }
+ return VK_SAMPLE_COUNT_1_BIT;
+ }
+
};
-VULKAN_EXAMPLE_MAIN()
\ No newline at end of file
+VULKAN_EXAMPLE_MAIN()
diff --git a/texture/texture.cpp b/texture/texture.cpp
index ffafd5b524..3e6e4d2f66 100644
--- a/texture/texture.cpp
+++ b/texture/texture.cpp
@@ -179,7 +179,7 @@ class VulkanExample : public VulkanExampleBase
void loadTexture()
{
// We use the Khronos texture format (https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/)
- std::string filename = ASSET_PATH "textures/metalplate01_rgba.ktx";
+ std::string filename = getAssetPath() + "textures/metalplate01_rgba.ktx";
// Texture data contains 4 channels (RGBA) with unnormalized 8-bit values, this is the most commonly supported format
VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
diff --git a/xcode/MVKExample.cpp b/xcode/MVKExample.cpp
new file mode 100644
index 0000000000..6db1c1cdfb
--- /dev/null
+++ b/xcode/MVKExample.cpp
@@ -0,0 +1,30 @@
+/*
+ * MVKExample.cpp
+ *
+ * Copyright (c) 2016-2017 The Brenwill Workshop Ltd.
+ * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+ */
+
+
+#include "MVKExample.h"
+#include "examples.h"
+
+void MVKExample::renderFrame() {
+ _vulkanExample->renderFrame();
+}
+
+void MVKExample::keyPressed(uint32_t keyCode) {
+ _vulkanExample->keyPressed(keyCode);
+}
+
+MVKExample::MVKExample(void* view) {
+ _vulkanExample = new VulkanExample();
+ _vulkanExample->initVulkan();
+ _vulkanExample->setupWindow(view);
+ _vulkanExample->initSwapchain();
+ _vulkanExample->prepare();
+}
+
+MVKExample::~MVKExample() {
+ delete _vulkanExample;
+}
diff --git a/xcode/MVKExample.h b/xcode/MVKExample.h
new file mode 100644
index 0000000000..93d921ec6e
--- /dev/null
+++ b/xcode/MVKExample.h
@@ -0,0 +1,27 @@
+/*
+ * MVKExample.h
+ *
+ * Copyright (c) 2016-2017 The Brenwill Workshop Ltd.
+ * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+ */
+
+#pragma once
+
+#include "vulkanexamplebase.h"
+
+// Wrapper class for the SW VulkanExample instance.
+class MVKExample {
+
+public:
+ void renderFrame();
+ void keyPressed(uint32_t keyCode);
+
+ MVKExample(void* view);
+ ~MVKExample();
+
+protected:
+ VulkanExampleBase* _vulkanExample;
+};
+
+
+
diff --git a/xcode/MoltenVK b/xcode/MoltenVK
new file mode 120000
index 0000000000..b8175b83f0
--- /dev/null
+++ b/xcode/MoltenVK
@@ -0,0 +1 @@
+../../../../../Molten/Package/Latest/MoltenVK
\ No newline at end of file
diff --git a/xcode/README_MoltenVK_Examples.md b/xcode/README_MoltenVK_Examples.md
new file mode 100755
index 0000000000..39d0f4168f
--- /dev/null
+++ b/xcode/README_MoltenVK_Examples.md
@@ -0,0 +1,142 @@
+
+
+
+
+#MoltenVK Vulkan Examples
+
+Copyright (c) 2016-2017 [The Brenwill Workshop Ltd.](http://www.brenwill.com).
+This document is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+*This document is written in [Markdown](http://en.wikipedia.org/wiki/Markdown) format.
+For best results, use a Markdown reader.*
+
+
+
+
+Introduction
+------------
+
+The *Xcode* project in this folder builds and runs the *Vulkan* examples in this
+repository on *iOS* and *macOS*, using the **MoltenVK** *Vulkan* driver.
+
+
+
+
+
+Installing MoltenVK
+-------------------
+
+The examples in this repository can be run on *iOS* and *macOS* by using
+the [**MoltenVK**](http://www.moltengl.com/moltenvk/) *Vulkan* driver.
+
+These examples require **MoltenVK 0.18.0** or greater.
+
+Follow these instructions to install **MoltenVK**:
+
+1. [Download](https://moltengl.com/free-trial/) the **Molten** free evaluation trial.
+ This free trial includes **MoltenVK**, is full-featured, and is not time-limited.
+ You must purchase a license if you wish to use **MoltenVK** for a production
+ application or game, but you can use the evaluation version to run these examples.
+
+2. Unzip the **Molten** package, and move it to a folder outside this repository.
+
+3. Open a *Terminal* session and navigate to the directory containing this document,
+ remove the existing `MoltenVK` symbolic link in this directory, and create a new
+ symbolic link pointing to the `MoltenVK` directory in the **Molten** package:
+
+ cd path-to-this-directory
+ rm MoltenVK
+ ln -s path-to-Molten-package/MoltenVK
+
+
+
+
+
+Installing AssImp
+-----------------
+
+The examples in this repository make use of the [*AssImp*](http://assimp.sourceforge.net)
+library to load resource assets from files. To run the examples you must download and
+install *AssImp* library as follows.
+
+>***Note:*** Due to the way that *AssImp* makes use of the *CMake* utility, an installation
+of *AssImp* can only be built for a single platform. To create *AssImp* libraries for both
+*iOS* and *macOS*, download a separate copy of the *AssImp* directory for each platform
+(or create a copy of the downloaded *AssImp* directory for each platform before building).
+
+
+####iOS
+
+1. Download [AssImp 3.3.1](https://github.com/assimp/assimp/releases/tag/v3.3.1/).
+
+2. Unzip and rename the directory to `assimp-3.3.1-ios`.
+
+3. Open the file `assimp-3.3.1-ios/port/iOS/IPHONEOS_ARM64_TOOLCHAIN.cmake` file and comment
+ out the following lines:
+
+ #SET (CC "${DEVROOT}/usr/bin/llvm-gcc")
+ #SET (CXX "${DEVROOT}/usr/bin/llvm-g++")
+ #CMAKE_FORCE_C_COMPILER (${CC} LLVM)
+ #CMAKE_FORCE_CXX_COMPILER (${CXX} LLVM)
+
+4. Open a *Terminal* session and navigate to the `assimp-3.3.1-ios/port/iOS` directory,
+ and run the following build command:
+
+ cd path-to-assimp-3.3.1-ios/port/iOS
+ ./build.sh --stdlib=libc++ --archs="arm64" --no-fat
+
+5. In the `assimp` directory within this directory, remove the existing `assimp-ios`
+ symbolic link, and create a new symbolic link pointing to the `assimp-3.3.1-ios` directory:
+
+ cd path-to-this-directory/assimp
+ rm assimp-ios
+ ln -s path-to-assimp-3.3.1-ios assimp-ios
+
+
+####macOS
+
+1. Download [AssImp 3.3.1](https://github.com/assimp/assimp/releases/tag/v3.3.1/).
+
+2. Unzip and rename the directory to `assimp-3.3.1-macos`.
+
+3. Open a *Terminal* session and navigate to the `assimp-3.3.1-ios/port/macOS` directory,
+ and run the following build commands:
+
+ cd path-to-assimp-3.3.1-macos
+ cmake CMakeLists.txt -G 'Unix Makefiles'
+ make
+
+4. In the `assimp` directory within this directory, remove the existing `assimp-macos`
+ symbolic link, and create a new symbolic link pointing to the `assimp-3.3.1-macos` directory:
+
+ cd path-to-this-directory/assimp
+ rm assimp-macos
+ ln -s path-to-assimp-3.3.1-macos assimp-macos
+
+
+
+
+
+Running the Vulkan Examples
+---------------------------
+
+The single `examples.xcodeproj` *Xcode* project can be used to run any of the examples
+in this repository on either *iOS* or *macOS*. To do so, follow these instructions:
+
+1. Open the `examples.xcodeproj` *Xcode* project.
+
+2. Specify which of the many examples within this respository you wish to run, by opening
+ the `examples.h` file within *Xcode*, and following the instructions in the comments
+ within that file to indicate which of the examples you wish to run.
+
+3. Run either the `examples-iOS` or `examples-macOS` *Xcode Scheme* to run the example in *iOS*
+ or *macOS*, repectively.
+
+4. Many of the examples include an option to press keys to control the display of features
+ and scene components:
+
+ - On *iOS*, tap on the scene to display the keyboard. Tap again on the scene to hide the keyboard.
+ - On both *iOS* and *macOS*, use the numeric keys (*1, 2, 3...*) instead of function keys (*F1, F2, F3...*).
+ - On both *iOS* and *macOS*, use the regular keyboard *+* and *-* keys instead of the numpad *+* and *-* keys.
+ - On both *iOS* and *macOS*, use the *delete* key instead of the *escape* key.
+
diff --git a/xcode/assimp/assimp-ios b/xcode/assimp/assimp-ios
new file mode 120000
index 0000000000..42d78e11f0
--- /dev/null
+++ b/xcode/assimp/assimp-ios
@@ -0,0 +1 @@
+../../../assimp-3.3.1-ios
\ No newline at end of file
diff --git a/xcode/assimp/assimp-macos b/xcode/assimp/assimp-macos
new file mode 120000
index 0000000000..2807a1f989
--- /dev/null
+++ b/xcode/assimp/assimp-macos
@@ -0,0 +1 @@
+../../../assimp-3.3.1-macos
\ No newline at end of file
diff --git a/xcode/examples.h b/xcode/examples.h
new file mode 100644
index 0000000000..82d2494d02
--- /dev/null
+++ b/xcode/examples.h
@@ -0,0 +1,189 @@
+/*
+ * examples.h
+ *
+ * Copyright (c) 2016-2017 The Brenwill Workshop Ltd.
+ * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+ *
+ *
+ * Loads the appropriate example code, as indicated by the appropriate compiler build setting below.
+ *
+ * To select an example to run, define one (and only one) of the macros below, either by
+ * adding a #define XXX statement at the top of this file, or more flexibily, by adding the
+ * macro value to the Preprocessor Macros (aka GCC_PREPROCESSOR_DEFINITIONS) compiler setting.
+ *
+ * To add a compiler setting, select the project in the Xcode Project Navigator panel,
+ * select the Build Settings panel, and add the value to the Preprocessor Macros
+ * (aka GCC_PREPROCESSOR_DEFINITIONS) entry.
+ *
+ * For example, to run the pipelines example, you would add the MVK_pipelines define macro
+ * to the Preprocessor Macros (aka GCC_PREPROCESSOR_DEFINITIONS) entry of the Xcode project,
+ * overwriting any otheor value there.
+ *
+ * If you choose to add a #define statement to this file, be sure to clear the existing macro
+ * from the Preprocessor Macros (aka GCC_PREPROCESSOR_DEFINITIONS) compiler setting in Xcode.
+ */
+
+
+// In the list below, the comments indicate entries that,
+// under certain conditions, that may not run as expected.
+
+
+// BASICS
+
+#ifdef MVK_pipelines
+# include "../pipelines/pipelines.cpp"
+#endif
+
+#ifdef MVK_texture
+# include "../texture/texture.cpp"
+#endif
+
+// Does not run. Metal does not support passing matrices between shader stages.
+#ifdef MVK_texturecubemap
+# include "../texturecubemap/texturecubemap.cpp"
+#endif
+
+// Runs in Release mode. Does not run in Debug mode, as Metal validation will
+// assert that UBO buffer length is too short for UBO size declared in shader.
+#ifdef MVK_texturearray
+# include "../texturearray/texturearray.cpp"
+#endif
+
+#ifdef MVK_mesh
+# include "../mesh/mesh.cpp"
+#endif
+
+#ifdef MVK_dynamicuniformbuffer
+# include "../dynamicuniformbuffer/dynamicuniformbuffer.cpp"
+#endif
+
+// Does not run. Metal does not support passing arrays between shader stages.
+#ifdef MVK_pushconstants
+# include "../pushconstants/pushconstants.cpp"
+#endif
+
+#ifdef MVK_specializationconstants
+# include "../specializationconstants/specializationconstants.cpp"
+#endif
+
+#ifdef MVK_offscreen
+# include "../offscreen/offscreen.cpp"
+#endif
+
+#ifdef MVK_radialblur
+# include "../radialblur/radialblur.cpp"
+#endif
+
+#ifdef MVK_textoverlay
+# include "../textoverlay/textoverlay.cpp"
+#endif
+
+#ifdef MVK_particlefire
+# include "../particlefire/particlefire.cpp"
+#endif
+
+
+// ADVANCED
+
+#ifdef MVK_multithreading
+# include "../multithreading/multithreading.cpp"
+#endif
+
+#ifdef MVK_scenerendering
+# include "../scenerendering/scenerendering.cpp"
+#endif
+
+#ifdef MVK_instancing
+# include "../instancing/instancing.cpp"
+#endif
+
+#ifdef MVK_indirectdraw
+# include "../indirectdraw/indirectdraw.cpp"
+#endif
+
+// Does not run. Metal does not support passing matrices between shader stages.
+#ifdef MVK_hdr
+# include "../hdr/hdr.cpp"
+#endif
+
+#ifdef MVK_occlusionquery
+# include "../occlusionquery/occlusionquery.cpp"
+#endif
+
+// Does not run. Sampler arrays require Metal 2.
+#ifdef MVK_texturemipmapgen
+# include "../texturemipmapgen/texturemipmapgen.cpp"
+#endif
+
+#ifdef MVK_multisampling
+# include "../multisampling/multisampling.cpp"
+#endif
+
+#ifdef MVK_shadowmapping
+# include "../shadowmapping/shadowmapping.cpp"
+#endif
+
+#ifdef MVK_shadowmappingomni
+# include "../shadowmappingomni/shadowmappingomni.cpp"
+#endif
+
+#ifdef MVK_skeletalanimation
+# include "../skeletalanimation/skeletalanimation.cpp"
+#endif
+
+#ifdef MVK_bloom
+# include "../bloom/bloom.cpp"
+#endif
+
+// Runs in Release mode. Debug mode Metal validation will assert
+// UBO buffer length is too short for UBO size declared in shader.
+#ifdef MVK_deferred
+# include "../deferred/deferred.cpp"
+#endif
+
+// Does not run. Metal does not support geometry shaders.
+#ifdef MVK_deferredshadows
+# include "../deferredshadows/deferredshadows.cpp"
+#endif
+
+// Runs in Release mode, but does not display content.
+// Metal does not support the use of specialization constants to set array lengths,
+#ifdef MVK_ssao
+# include "../ssao/ssao.cpp"
+#endif
+
+
+// COMPUTE - Currently unsupported by MoltenVK
+
+
+// TESSELLATION - Currently unsupported by MoltenVK
+
+
+// GEOMETRY SHADER - Unsupported by Metal
+
+
+// EXTENSIONS - Currently unsupported by MoltenVK
+
+
+// MISC
+
+#ifdef MVK_parallaxmapping
+# include "../parallaxmapping/parallaxmapping.cpp"
+#endif
+
+#ifdef MVK_sphericalenvmapping
+# include "../sphericalenvmapping/sphericalenvmapping.cpp"
+#endif
+
+#ifdef MVK_gears
+# include "../gears/gears.cpp"
+#endif
+
+#ifdef MVK_distancefieldfonts
+# include "../distancefieldfonts/distancefieldfonts.cpp"
+#endif
+
+#ifdef MVK_vulkanscene
+# include "../vulkanscene/vulkanscene.cpp"
+#endif
+
diff --git a/xcode/examples.xcodeproj/project.pbxproj b/xcode/examples.xcodeproj/project.pbxproj
new file mode 100644
index 0000000000..800d846e5a
--- /dev/null
+++ b/xcode/examples.xcodeproj/project.pbxproj
@@ -0,0 +1,631 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ A94C8D601EA047B400B3CE07 /* vulkangear.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A94C8D5E1EA047B400B3CE07 /* vulkangear.cpp */; };
+ A94C8D611EA047B400B3CE07 /* vulkangear.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A94C8D5E1EA047B400B3CE07 /* vulkangear.cpp */; };
+ A951FF171E9C349000FA9144 /* VulkanDebug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A951FF071E9C349000FA9144 /* VulkanDebug.cpp */; };
+ A951FF181E9C349000FA9144 /* VulkanDebug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A951FF071E9C349000FA9144 /* VulkanDebug.cpp */; };
+ A951FF191E9C349000FA9144 /* vulkanexamplebase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A951FF0A1E9C349000FA9144 /* vulkanexamplebase.cpp */; };
+ A951FF1A1E9C349000FA9144 /* vulkanexamplebase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A951FF0A1E9C349000FA9144 /* vulkanexamplebase.cpp */; };
+ A951FF1B1E9C349000FA9144 /* VulkanTools.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A951FF131E9C349000FA9144 /* VulkanTools.cpp */; };
+ A951FF1C1E9C349000FA9144 /* VulkanTools.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A951FF131E9C349000FA9144 /* VulkanTools.cpp */; };
+ A9532B761EF99894000A09E2 /* libMoltenVK.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = A9532B751EF99894000A09E2 /* libMoltenVK.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
+ A9532B771EF9991A000A09E2 /* libMoltenVK.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = A9532B751EF99894000A09E2 /* libMoltenVK.dylib */; };
+ A9532B781EF99937000A09E2 /* libMoltenVK.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = A9581BAB1EEB64EC00247309 /* libMoltenVK.dylib */; };
+ A9581BA61EEB648800247309 /* libassimp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A9581BA51EEB648800247309 /* libassimp.a */; };
+ A9581BA81EEB648C00247309 /* libzlibstatic.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A9581BA71EEB648C00247309 /* libzlibstatic.a */; };
+ A9581BAC1EEB64EC00247309 /* libMoltenVK.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = A9581BAB1EEB64EC00247309 /* libMoltenVK.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
+ A9581BAE1EEB651100247309 /* libassimp.3.3.1.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = A9581BAD1EEB651100247309 /* libassimp.3.3.1.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
+ A9581BAF1EEB651500247309 /* libassimp.3.3.1.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = A9581BAD1EEB651100247309 /* libassimp.3.3.1.dylib */; };
+ A98703D91E9D382A0066959C /* data in Resources */ = {isa = PBXBuildFile; fileRef = A98703D81E9D382A0066959C /* data */; };
+ A98703DA1E9D382A0066959C /* data in Resources */ = {isa = PBXBuildFile; fileRef = A98703D81E9D382A0066959C /* data */; };
+ A9B67B781C3AAE9800373FFD /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = A9B67B6C1C3AAE9800373FFD /* AppDelegate.m */; };
+ A9B67B7A1C3AAE9800373FFD /* DemoViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A9B67B6F1C3AAE9800373FFD /* DemoViewController.mm */; };
+ A9B67B7C1C3AAE9800373FFD /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = A9B67B711C3AAE9800373FFD /* main.m */; };
+ A9B67B7D1C3AAE9800373FFD /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = A9B67B741C3AAE9800373FFD /* Default-568h@2x.png */; };
+ A9B67B7E1C3AAE9800373FFD /* Default~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = A9B67B751C3AAE9800373FFD /* Default~ipad.png */; };
+ A9B67B7F1C3AAE9800373FFD /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = A9B67B761C3AAE9800373FFD /* Icon.png */; };
+ A9B67B801C3AAE9800373FFD /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A9B67B771C3AAE9800373FFD /* Main.storyboard */; };
+ A9B67B8C1C3AAEA200373FFD /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = A9B67B831C3AAEA200373FFD /* AppDelegate.m */; };
+ A9B67B8D1C3AAEA200373FFD /* DemoViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A9B67B851C3AAEA200373FFD /* DemoViewController.mm */; };
+ A9B67B8F1C3AAEA200373FFD /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = A9B67B871C3AAEA200373FFD /* main.m */; };
+ A9B67B901C3AAEA200373FFD /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A9B67B8A1C3AAEA200373FFD /* Main.storyboard */; };
+ A9B67B911C3AAEA200373FFD /* macOS.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A9B67B8B1C3AAEA200373FFD /* macOS.xcassets */; };
+ A9BC9B1C1EE8421F00384233 /* MVKExample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9BC9B1A1EE8421F00384233 /* MVKExample.cpp */; };
+ A9BC9B1D1EE8421F00384233 /* MVKExample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9BC9B1A1EE8421F00384233 /* MVKExample.cpp */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ A91227BB1E9D5E9D00108018 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 6;
+ files = (
+ A9581BAC1EEB64EC00247309 /* libMoltenVK.dylib in CopyFiles */,
+ A9581BAE1EEB651100247309 /* libassimp.3.3.1.dylib in CopyFiles */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ A9532B741EF9987C000A09E2 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 6;
+ files = (
+ A9532B761EF99894000A09E2 /* libMoltenVK.dylib in CopyFiles */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ 1D3623EB0D0F72F000981E51 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+ 1D6058910D05DD3D006BFB54 /* examples.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = examples.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 2D500B990D5A79CF00DBA0E3 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
+ A92F37071C7E1B2B008F8BC9 /* examples.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = examples.h; sourceTree = ""; };
+ A94A67231B7BDE9B00F6D7C4 /* MetalGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalGL.framework; path = ../../MetalGL/macOS/MetalGL.framework; sourceTree = ""; };
+ A94A67241B7BDE9B00F6D7C4 /* MetalGLShaderConverter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalGLShaderConverter.framework; path = ../../MetalGLShaderConverter/macOS/MetalGLShaderConverter.framework; sourceTree = ""; };
+ A94C8D5E1EA047B400B3CE07 /* vulkangear.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = vulkangear.cpp; path = ../gears/vulkangear.cpp; sourceTree = ""; };
+ A94C8D5F1EA047B400B3CE07 /* vulkangear.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = vulkangear.h; path = ../gears/vulkangear.h; sourceTree = ""; };
+ A951FF001E9C349000FA9144 /* camera.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = camera.hpp; sourceTree = ""; };
+ A951FF011E9C349000FA9144 /* frustum.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = frustum.hpp; sourceTree = ""; };
+ A951FF021E9C349000FA9144 /* keycodes.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = keycodes.hpp; sourceTree = ""; };
+ A951FF031E9C349000FA9144 /* threadpool.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = threadpool.hpp; sourceTree = ""; };
+ A951FF061E9C349000FA9144 /* VulkanBuffer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VulkanBuffer.hpp; sourceTree = ""; };
+ A951FF071E9C349000FA9144 /* VulkanDebug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VulkanDebug.cpp; sourceTree = ""; };
+ A951FF081E9C349000FA9144 /* VulkanDebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VulkanDebug.h; sourceTree = ""; };
+ A951FF091E9C349000FA9144 /* VulkanDevice.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VulkanDevice.hpp; sourceTree = ""; };
+ A951FF0A1E9C349000FA9144 /* vulkanexamplebase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vulkanexamplebase.cpp; sourceTree = ""; };
+ A951FF0B1E9C349000FA9144 /* vulkanexamplebase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vulkanexamplebase.h; sourceTree = ""; };
+ A951FF0C1E9C349000FA9144 /* VulkanFrameBuffer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VulkanFrameBuffer.hpp; sourceTree = ""; };
+ A951FF0D1E9C349000FA9144 /* VulkanHeightmap.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VulkanHeightmap.hpp; sourceTree = ""; };
+ A951FF0E1E9C349000FA9144 /* VulkanInitializers.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VulkanInitializers.hpp; sourceTree = ""; };
+ A951FF0F1E9C349000FA9144 /* VulkanModel.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VulkanModel.hpp; sourceTree = ""; };
+ A951FF101E9C349000FA9144 /* VulkanSwapChain.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VulkanSwapChain.hpp; sourceTree = ""; };
+ A951FF111E9C349000FA9144 /* VulkanTextOverlay.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VulkanTextOverlay.hpp; sourceTree = ""; };
+ A951FF121E9C349000FA9144 /* VulkanTexture.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VulkanTexture.hpp; sourceTree = ""; };
+ A951FF131E9C349000FA9144 /* VulkanTools.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VulkanTools.cpp; sourceTree = ""; };
+ A951FF141E9C349000FA9144 /* VulkanTools.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VulkanTools.h; sourceTree = ""; };
+ A9532B751EF99894000A09E2 /* libMoltenVK.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libMoltenVK.dylib; path = MoltenVK/iOS/libMoltenVK.dylib; sourceTree = ""; };
+ A9581BA51EEB648800247309 /* libassimp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libassimp.a; path = "assimp/assimp-ios/lib/iOS/arm64/libassimp.a"; sourceTree = ""; };
+ A9581BA71EEB648C00247309 /* libzlibstatic.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libzlibstatic.a; path = "assimp/assimp-ios/lib/libzlibstatic.a"; sourceTree = ""; };
+ A9581BAB1EEB64EC00247309 /* libMoltenVK.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libMoltenVK.dylib; path = MoltenVK/macOS/libMoltenVK.dylib; sourceTree = ""; };
+ A9581BAD1EEB651100247309 /* libassimp.3.3.1.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libassimp.3.3.1.dylib; path = "assimp/assimp-macos/lib/libassimp.3.3.1.dylib"; sourceTree = ""; };
+ A977BCFE1B66BB010067E5BF /* examples.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = examples.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ A977BD211B67186B0067E5BF /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/AppKit.framework; sourceTree = DEVELOPER_DIR; };
+ A977BD221B67186B0067E5BF /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; };
+ A977BD231B67186B0067E5BF /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
+ A977BD251B67186B0067E5BF /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/Metal.framework; sourceTree = DEVELOPER_DIR; };
+ A977BD261B67186B0067E5BF /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; };
+ A98703D81E9D382A0066959C /* data */ = {isa = PBXFileReference; lastKnownFileType = folder; name = data; path = ../data; sourceTree = ""; };
+ A9A222171B5D69F40050A5F9 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; };
+ A9B5D09B1CF8830B00D7CBDD /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; };
+ A9B67B6B1C3AAE9800373FFD /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
+ A9B67B6C1C3AAE9800373FFD /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
+ A9B67B6E1C3AAE9800373FFD /* DemoViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoViewController.h; sourceTree = ""; };
+ A9B67B6F1C3AAE9800373FFD /* DemoViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DemoViewController.mm; sourceTree = ""; };
+ A9B67B701C3AAE9800373FFD /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ A9B67B711C3AAE9800373FFD /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
+ A9B67B721C3AAE9800373FFD /* Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Prefix.pch; sourceTree = ""; };
+ A9B67B741C3AAE9800373FFD /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; };
+ A9B67B751C3AAE9800373FFD /* Default~ipad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default~ipad.png"; sourceTree = ""; };
+ A9B67B761C3AAE9800373FFD /* Icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Icon.png; sourceTree = ""; };
+ A9B67B771C3AAE9800373FFD /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; };
+ A9B67B821C3AAEA200373FFD /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
+ A9B67B831C3AAEA200373FFD /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
+ A9B67B841C3AAEA200373FFD /* DemoViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoViewController.h; sourceTree = ""; };
+ A9B67B851C3AAEA200373FFD /* DemoViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DemoViewController.mm; sourceTree = ""; };
+ A9B67B861C3AAEA200373FFD /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ A9B67B871C3AAEA200373FFD /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
+ A9B67B881C3AAEA200373FFD /* Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Prefix.pch; sourceTree = ""; };
+ A9B67B8A1C3AAEA200373FFD /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; };
+ A9B67B8B1C3AAEA200373FFD /* macOS.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = macOS.xcassets; sourceTree = ""; };
+ A9B6B7641C0F795D00A9E33A /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; };
+ A9BC9B1A1EE8421F00384233 /* MVKExample.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MVKExample.cpp; sourceTree = ""; };
+ A9BC9B1B1EE8421F00384233 /* MVKExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKExample.h; sourceTree = ""; };
+ A9CDEA271B6A782C00F7B008 /* GLKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLKit.framework; path = System/Library/Frameworks/GLKit.framework; sourceTree = SDKROOT; };
+ A9E264761B671B0A00FE691A /* libc++.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libc++.dylib"; path = "Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/lib/libc++.dylib"; sourceTree = DEVELOPER_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 1D60588F0D05DD3D006BFB54 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ A9532B771EF9991A000A09E2 /* libMoltenVK.dylib in Frameworks */,
+ A9581BA61EEB648800247309 /* libassimp.a in Frameworks */,
+ A9581BA81EEB648C00247309 /* libzlibstatic.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ A977BCF11B66BB010067E5BF /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ A9532B781EF99937000A09E2 /* libMoltenVK.dylib in Frameworks */,
+ A9581BAF1EEB651500247309 /* libassimp.3.3.1.dylib in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 19C28FACFE9D520D11CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 1D6058910D05DD3D006BFB54 /* examples.app */,
+ A977BCFE1B66BB010067E5BF /* examples.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = {
+ isa = PBXGroup;
+ children = (
+ A92F37071C7E1B2B008F8BC9 /* examples.h */,
+ A9BC9B1B1EE8421F00384233 /* MVKExample.h */,
+ A9BC9B1A1EE8421F00384233 /* MVKExample.cpp */,
+ A951FEFF1E9C349000FA9144 /* base */,
+ A94C8D5D1EA047A300B3CE07 /* extras */,
+ A98703D81E9D382A0066959C /* data */,
+ A9B67B6A1C3AAE9800373FFD /* iOS */,
+ A9B67B811C3AAEA200373FFD /* macOS */,
+ 29B97323FDCFA39411CA2CEA /* Frameworks */,
+ 19C28FACFE9D520D11CA2CBB /* Products */,
+ );
+ name = CustomTemplate;
+ sourceTree = "";
+ };
+ 29B97323FDCFA39411CA2CEA /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ A9581BAD1EEB651100247309 /* libassimp.3.3.1.dylib */,
+ A9581BAB1EEB64EC00247309 /* libMoltenVK.dylib */,
+ A9532B751EF99894000A09E2 /* libMoltenVK.dylib */,
+ A9581BA71EEB648C00247309 /* libzlibstatic.a */,
+ A9581BA51EEB648800247309 /* libassimp.a */,
+ A9B5D09B1CF8830B00D7CBDD /* libc++.tbd */,
+ A9B6B7641C0F795D00A9E33A /* CoreAudio.framework */,
+ A9ADEC601B6EC2EB00DBA48C /* iOS */,
+ A9ADEC611B6EC2F300DBA48C /* macOS */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+ A94C8D5D1EA047A300B3CE07 /* extras */ = {
+ isa = PBXGroup;
+ children = (
+ A94C8D5E1EA047B400B3CE07 /* vulkangear.cpp */,
+ A94C8D5F1EA047B400B3CE07 /* vulkangear.h */,
+ );
+ name = extras;
+ sourceTree = "";
+ };
+ A951FEFF1E9C349000FA9144 /* base */ = {
+ isa = PBXGroup;
+ children = (
+ A951FF001E9C349000FA9144 /* camera.hpp */,
+ A951FF011E9C349000FA9144 /* frustum.hpp */,
+ A951FF021E9C349000FA9144 /* keycodes.hpp */,
+ A951FF031E9C349000FA9144 /* threadpool.hpp */,
+ A951FF061E9C349000FA9144 /* VulkanBuffer.hpp */,
+ A951FF071E9C349000FA9144 /* VulkanDebug.cpp */,
+ A951FF081E9C349000FA9144 /* VulkanDebug.h */,
+ A951FF091E9C349000FA9144 /* VulkanDevice.hpp */,
+ A951FF0A1E9C349000FA9144 /* vulkanexamplebase.cpp */,
+ A951FF0B1E9C349000FA9144 /* vulkanexamplebase.h */,
+ A951FF0C1E9C349000FA9144 /* VulkanFrameBuffer.hpp */,
+ A951FF0D1E9C349000FA9144 /* VulkanHeightmap.hpp */,
+ A951FF0E1E9C349000FA9144 /* VulkanInitializers.hpp */,
+ A951FF0F1E9C349000FA9144 /* VulkanModel.hpp */,
+ A951FF101E9C349000FA9144 /* VulkanSwapChain.hpp */,
+ A951FF111E9C349000FA9144 /* VulkanTextOverlay.hpp */,
+ A951FF121E9C349000FA9144 /* VulkanTexture.hpp */,
+ A951FF131E9C349000FA9144 /* VulkanTools.cpp */,
+ A951FF141E9C349000FA9144 /* VulkanTools.h */,
+ );
+ name = base;
+ path = ../base;
+ sourceTree = "";
+ };
+ A9ADEC601B6EC2EB00DBA48C /* iOS */ = {
+ isa = PBXGroup;
+ children = (
+ A9A222171B5D69F40050A5F9 /* Metal.framework */,
+ 1D3623EB0D0F72F000981E51 /* CoreGraphics.framework */,
+ 2D500B990D5A79CF00DBA0E3 /* QuartzCore.framework */,
+ 1D30AB110D05D00D00671497 /* Foundation.framework */,
+ A9CDEA271B6A782C00F7B008 /* GLKit.framework */,
+ );
+ name = iOS;
+ sourceTree = "";
+ };
+ A9ADEC611B6EC2F300DBA48C /* macOS */ = {
+ isa = PBXGroup;
+ children = (
+ A94A67231B7BDE9B00F6D7C4 /* MetalGL.framework */,
+ A94A67241B7BDE9B00F6D7C4 /* MetalGLShaderConverter.framework */,
+ A9E264761B671B0A00FE691A /* libc++.dylib */,
+ A977BD251B67186B0067E5BF /* Metal.framework */,
+ A977BD261B67186B0067E5BF /* QuartzCore.framework */,
+ A977BD211B67186B0067E5BF /* AppKit.framework */,
+ A977BD221B67186B0067E5BF /* CoreGraphics.framework */,
+ A977BD231B67186B0067E5BF /* Foundation.framework */,
+ );
+ name = macOS;
+ sourceTree = "";
+ };
+ A9B67B6A1C3AAE9800373FFD /* iOS */ = {
+ isa = PBXGroup;
+ children = (
+ A9B67B6B1C3AAE9800373FFD /* AppDelegate.h */,
+ A9B67B6C1C3AAE9800373FFD /* AppDelegate.m */,
+ A9B67B6E1C3AAE9800373FFD /* DemoViewController.h */,
+ A9B67B6F1C3AAE9800373FFD /* DemoViewController.mm */,
+ A9B67B701C3AAE9800373FFD /* Info.plist */,
+ A9B67B711C3AAE9800373FFD /* main.m */,
+ A9B67B721C3AAE9800373FFD /* Prefix.pch */,
+ A9B67B731C3AAE9800373FFD /* Resources */,
+ );
+ path = iOS;
+ sourceTree = "";
+ };
+ A9B67B731C3AAE9800373FFD /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ A9B67B741C3AAE9800373FFD /* Default-568h@2x.png */,
+ A9B67B751C3AAE9800373FFD /* Default~ipad.png */,
+ A9B67B761C3AAE9800373FFD /* Icon.png */,
+ A9B67B771C3AAE9800373FFD /* Main.storyboard */,
+ );
+ path = Resources;
+ sourceTree = "";
+ };
+ A9B67B811C3AAEA200373FFD /* macOS */ = {
+ isa = PBXGroup;
+ children = (
+ A9B67B821C3AAEA200373FFD /* AppDelegate.h */,
+ A9B67B831C3AAEA200373FFD /* AppDelegate.m */,
+ A9B67B841C3AAEA200373FFD /* DemoViewController.h */,
+ A9B67B851C3AAEA200373FFD /* DemoViewController.mm */,
+ A9B67B861C3AAEA200373FFD /* Info.plist */,
+ A9B67B871C3AAEA200373FFD /* main.m */,
+ A9B67B881C3AAEA200373FFD /* Prefix.pch */,
+ A9B67B891C3AAEA200373FFD /* Resources */,
+ );
+ path = macOS;
+ sourceTree = "";
+ };
+ A9B67B891C3AAEA200373FFD /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ A9B67B8A1C3AAEA200373FFD /* Main.storyboard */,
+ A9B67B8B1C3AAEA200373FFD /* macOS.xcassets */,
+ );
+ path = Resources;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 1D6058900D05DD3D006BFB54 /* examples-ios */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "examples-ios" */;
+ buildPhases = (
+ 1D60588D0D05DD3D006BFB54 /* Resources */,
+ 1D60588E0D05DD3D006BFB54 /* Sources */,
+ 1D60588F0D05DD3D006BFB54 /* Frameworks */,
+ A9532B741EF9987C000A09E2 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "examples-ios";
+ productName = foo;
+ productReference = 1D6058910D05DD3D006BFB54 /* examples.app */;
+ productType = "com.apple.product-type.application";
+ };
+ A977BCBD1B66BB010067E5BF /* examples-macos */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = A977BCFB1B66BB010067E5BF /* Build configuration list for PBXNativeTarget "examples-macos" */;
+ buildPhases = (
+ A977BCBE1B66BB010067E5BF /* Resources */,
+ A977BCC91B66BB010067E5BF /* Sources */,
+ A977BCF11B66BB010067E5BF /* Frameworks */,
+ A91227BB1E9D5E9D00108018 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "examples-macos";
+ productName = foo;
+ productReference = A977BCFE1B66BB010067E5BF /* examples.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 29B97313FDCFA39411CA2CEA /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0820;
+ TargetAttributes = {
+ 1D6058900D05DD3D006BFB54 = {
+ DevelopmentTeam = VU3TCKU48B;
+ };
+ A977BCBD1B66BB010067E5BF = {
+ DevelopmentTeam = VU3TCKU48B;
+ };
+ };
+ };
+ buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "examples" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 1;
+ knownRegions = (
+ English,
+ Japanese,
+ French,
+ German,
+ );
+ mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 1D6058900D05DD3D006BFB54 /* examples-ios */,
+ A977BCBD1B66BB010067E5BF /* examples-macos */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 1D60588D0D05DD3D006BFB54 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ A9B67B7F1C3AAE9800373FFD /* Icon.png in Resources */,
+ A9B67B801C3AAE9800373FFD /* Main.storyboard in Resources */,
+ A9B67B7E1C3AAE9800373FFD /* Default~ipad.png in Resources */,
+ A9B67B7D1C3AAE9800373FFD /* Default-568h@2x.png in Resources */,
+ A98703D91E9D382A0066959C /* data in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ A977BCBE1B66BB010067E5BF /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ A9B67B911C3AAEA200373FFD /* macOS.xcassets in Resources */,
+ A98703DA1E9D382A0066959C /* data in Resources */,
+ A9B67B901C3AAEA200373FFD /* Main.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 1D60588E0D05DD3D006BFB54 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ A951FF171E9C349000FA9144 /* VulkanDebug.cpp in Sources */,
+ A9BC9B1C1EE8421F00384233 /* MVKExample.cpp in Sources */,
+ A9B67B7A1C3AAE9800373FFD /* DemoViewController.mm in Sources */,
+ A9B67B781C3AAE9800373FFD /* AppDelegate.m in Sources */,
+ A951FF1B1E9C349000FA9144 /* VulkanTools.cpp in Sources */,
+ A94C8D601EA047B400B3CE07 /* vulkangear.cpp in Sources */,
+ A951FF191E9C349000FA9144 /* vulkanexamplebase.cpp in Sources */,
+ A9B67B7C1C3AAE9800373FFD /* main.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ A977BCC91B66BB010067E5BF /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ A951FF181E9C349000FA9144 /* VulkanDebug.cpp in Sources */,
+ A9BC9B1D1EE8421F00384233 /* MVKExample.cpp in Sources */,
+ A9B67B8C1C3AAEA200373FFD /* AppDelegate.m in Sources */,
+ A9B67B8F1C3AAEA200373FFD /* main.m in Sources */,
+ A951FF1C1E9C349000FA9144 /* VulkanTools.cpp in Sources */,
+ A94C8D611EA047B400B3CE07 /* vulkangear.cpp in Sources */,
+ A951FF1A1E9C349000FA9144 /* vulkanexamplebase.cpp in Sources */,
+ A9B67B8D1C3AAEA200373FFD /* DemoViewController.mm in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 1D6058940D05DD3E006BFB54 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ DEVELOPMENT_TEAM = VU3TCKU48B;
+ GCC_PREFIX_HEADER = "$(SRCROOT)/iOS/Prefix.pch";
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "$(inherited)",
+ "DEBUG=1",
+ _DEBUG,
+ VK_USE_PLATFORM_IOS_MVK,
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
+ INFOPLIST_FILE = "$(SRCROOT)/iOS/Info.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ LD_RUNPATH_SEARCH_PATHS = "@executable_path";
+ LIBRARY_SEARCH_PATHS = (
+ "\"$(SRCROOT)/MoltenVK/iOS\"",
+ "\"$(SRCROOT)/assimp/assimp-ios/lib/iOS/arm64\"",
+ "\"$(SRCROOT)/assimp/assimp-ios/lib\"",
+ );
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALID_ARCHS = arm64;
+ };
+ name = Debug;
+ };
+ 1D6058950D05DD3E006BFB54 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ DEVELOPMENT_TEAM = VU3TCKU48B;
+ GCC_PREFIX_HEADER = "$(SRCROOT)/iOS/Prefix.pch";
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "$(inherited)",
+ VK_USE_PLATFORM_IOS_MVK,
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
+ INFOPLIST_FILE = "$(SRCROOT)/iOS/Info.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ LD_RUNPATH_SEARCH_PATHS = "@executable_path";
+ LIBRARY_SEARCH_PATHS = (
+ "\"$(SRCROOT)/MoltenVK/iOS\"",
+ "\"$(SRCROOT)/assimp/assimp-ios/lib/iOS/arm64\"",
+ "\"$(SRCROOT)/assimp/assimp-ios/lib\"",
+ );
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALID_ARCHS = arm64;
+ };
+ name = Release;
+ };
+ A977BCFC1B66BB010067E5BF /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ COMBINE_HIDPI_IMAGES = YES;
+ GCC_PREFIX_HEADER = "$(SRCROOT)/macOS/Prefix.pch";
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "$(inherited)",
+ "DEBUG=1",
+ _DEBUG,
+ VK_USE_PLATFORM_MACOS_MVK,
+ );
+ INFOPLIST_FILE = "$(SRCROOT)/macOS/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "@executable_path";
+ LIBRARY_SEARCH_PATHS = (
+ "\"$(SRCROOT)/MoltenVK/macOS\"",
+ "\"$(SRCROOT)/assimp/assimp-macos/lib\"",
+ "$(PROJECT_DIR)/MoltenVK/macOS",
+ );
+ MACOSX_DEPLOYMENT_TARGET = 10.11;
+ SDKROOT = macosx;
+ };
+ name = Debug;
+ };
+ A977BCFD1B66BB010067E5BF /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ COMBINE_HIDPI_IMAGES = YES;
+ GCC_PREFIX_HEADER = "$(SRCROOT)/macOS/Prefix.pch";
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "$(inherited)",
+ VK_USE_PLATFORM_MACOS_MVK,
+ );
+ INFOPLIST_FILE = "$(SRCROOT)/macOS/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "@executable_path";
+ LIBRARY_SEARCH_PATHS = (
+ "\"$(SRCROOT)/MoltenVK/macOS\"",
+ "\"$(SRCROOT)/assimp/assimp-macos/lib\"",
+ "$(PROJECT_DIR)/MoltenVK/macOS",
+ );
+ MACOSX_DEPLOYMENT_TARGET = 10.11;
+ SDKROOT = macosx;
+ };
+ name = Release;
+ };
+ C01FCF4F08A954540054247B /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = NO;
+ COPY_PHASE_STRIP = NO;
+ ENABLE_BITCODE = NO;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = c99;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = MVK_vulkanscene;
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ HEADER_SEARCH_PATHS = (
+ "\"$(SRCROOT)/MoltenVK/include\"",
+ "\"$(SRCROOT)/../external\"/**",
+ );
+ ONLY_ACTIVE_ARCH = YES;
+ PRODUCT_BUNDLE_IDENTIFIER = "com.moltenvk.${PRODUCT_NAME:identifier}";
+ PRODUCT_NAME = "${PROJECT}";
+ };
+ name = Debug;
+ };
+ C01FCF5008A954540054247B /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = NO;
+ ENABLE_BITCODE = NO;
+ GCC_C_LANGUAGE_STANDARD = c99;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = MVK_vulkanscene;
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ HEADER_SEARCH_PATHS = (
+ "\"$(SRCROOT)/MoltenVK/include\"",
+ "\"$(SRCROOT)/../external\"/**",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.moltenvk.${PRODUCT_NAME:identifier}";
+ PRODUCT_NAME = "${PROJECT}";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "examples-ios" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1D6058940D05DD3E006BFB54 /* Debug */,
+ 1D6058950D05DD3E006BFB54 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ A977BCFB1B66BB010067E5BF /* Build configuration list for PBXNativeTarget "examples-macos" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ A977BCFC1B66BB010067E5BF /* Debug */,
+ A977BCFD1B66BB010067E5BF /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ C01FCF4E08A954540054247B /* Build configuration list for PBXProject "examples" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ C01FCF4F08A954540054247B /* Debug */,
+ C01FCF5008A954540054247B /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 29B97313FDCFA39411CA2CEA /* Project object */;
+}
diff --git a/xcode/examples.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/xcode/examples.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000000..1a97dc6483
--- /dev/null
+++ b/xcode/examples.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/xcode/examples.xcodeproj/project.xcworkspace/xcshareddata/examples.xcscmblueprint b/xcode/examples.xcodeproj/project.xcworkspace/xcshareddata/examples.xcscmblueprint
new file mode 100644
index 0000000000..94c4fa0151
--- /dev/null
+++ b/xcode/examples.xcodeproj/project.xcworkspace/xcshareddata/examples.xcscmblueprint
@@ -0,0 +1,30 @@
+{
+ "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "5B3778DF088377325550251267213ED1422AF030",
+ "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : {
+
+ },
+ "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : {
+ "986064432ACD0B21E33CA886A95425627120351A" : 9223372036854775807,
+ "5B3778DF088377325550251267213ED1422AF030" : 9223372036854775807
+ },
+ "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "CD2D1537-0CC5-4969-BD35-AB1ED0A0FACA",
+ "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : {
+ "986064432ACD0B21E33CA886A95425627120351A" : "..\/..\/..\/Molten",
+ "5B3778DF088377325550251267213ED1422AF030" : "Vulkan-bw\/"
+ },
+ "DVTSourceControlWorkspaceBlueprintNameKey" : "examples",
+ "DVTSourceControlWorkspaceBlueprintVersion" : 204,
+ "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "xcode\/examples.xcodeproj",
+ "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [
+ {
+ "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/brenwill\/Vulkan.git",
+ "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
+ "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "5B3778DF088377325550251267213ED1422AF030"
+ },
+ {
+ "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/brenwill\/molten.git",
+ "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
+ "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "986064432ACD0B21E33CA886A95425627120351A"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/xcode/examples.xcodeproj/xcshareddata/xcschemes/examples-ios.xcscheme b/xcode/examples.xcodeproj/xcshareddata/xcschemes/examples-ios.xcscheme
new file mode 100644
index 0000000000..02b53a3440
--- /dev/null
+++ b/xcode/examples.xcodeproj/xcshareddata/xcschemes/examples-ios.xcscheme
@@ -0,0 +1,96 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/xcode/examples.xcodeproj/xcshareddata/xcschemes/examples-macos.xcscheme b/xcode/examples.xcodeproj/xcshareddata/xcschemes/examples-macos.xcscheme
new file mode 100644
index 0000000000..002a8eee6f
--- /dev/null
+++ b/xcode/examples.xcodeproj/xcshareddata/xcschemes/examples-macos.xcscheme
@@ -0,0 +1,96 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/xcode/images/MoltenVK-Logo-Banner.png b/xcode/images/MoltenVK-Logo-Banner.png
new file mode 100755
index 0000000000..8bd880f975
Binary files /dev/null and b/xcode/images/MoltenVK-Logo-Banner.png differ
diff --git a/xcode/ios/AppDelegate.h b/xcode/ios/AppDelegate.h
new file mode 100644
index 0000000000..5023d3ddd4
--- /dev/null
+++ b/xcode/ios/AppDelegate.h
@@ -0,0 +1,15 @@
+/*
+ * AppDelegate.h
+ *
+ * Copyright (c) 2016-2017 The Brenwill Workshop Ltd.
+ * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+ */
+
+#import
+
+@interface AppDelegate : UIResponder
+
+@property (strong, nonatomic) UIWindow *window;
+
+@end
+
diff --git a/xcode/ios/AppDelegate.m b/xcode/ios/AppDelegate.m
new file mode 100644
index 0000000000..8d69ac3b5f
--- /dev/null
+++ b/xcode/ios/AppDelegate.m
@@ -0,0 +1,44 @@
+/*
+ * AppDelegate.m
+ *
+ * Copyright (c) 2016-2017 The Brenwill Workshop Ltd.
+ * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+ */
+
+#import "AppDelegate.h"
+
+@interface AppDelegate ()
+
+@end
+
+@implementation AppDelegate
+
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ // Override point for customization after application launch.
+ return YES;
+}
+
+- (void)applicationWillResignActive:(UIApplication *)application {
+ // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
+ // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
+}
+
+- (void)applicationDidEnterBackground:(UIApplication *)application {
+ // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
+ // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
+}
+
+- (void)applicationWillEnterForeground:(UIApplication *)application {
+ // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
+}
+
+- (void)applicationDidBecomeActive:(UIApplication *)application {
+ // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
+}
+
+- (void)applicationWillTerminate:(UIApplication *)application {
+ // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
+}
+
+@end
diff --git a/xcode/ios/DemoViewController.h b/xcode/ios/DemoViewController.h
new file mode 100644
index 0000000000..81d0402147
--- /dev/null
+++ b/xcode/ios/DemoViewController.h
@@ -0,0 +1,25 @@
+/*
+ * DemoViewController.h
+ *
+ * Copyright (c) 2016-2017 The Brenwill Workshop Ltd.
+ * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+ */
+
+#import
+
+
+#pragma mark -
+#pragma mark DemoViewController
+
+/** The main view controller for the demo storyboard. */
+@interface DemoViewController : UIViewController
+@end
+
+
+#pragma mark -
+#pragma mark DemoView
+
+/** The Metal-compatibile view for the demo Storyboard. */
+@interface DemoView : UIView
+@end
+
diff --git a/xcode/ios/DemoViewController.mm b/xcode/ios/DemoViewController.mm
new file mode 100644
index 0000000000..2629623ff3
--- /dev/null
+++ b/xcode/ios/DemoViewController.mm
@@ -0,0 +1,117 @@
+/*
+ * DemoViewController.mm
+ *
+ * Copyright (c) 2016-2017 The Brenwill Workshop Ltd.
+ * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+ */
+
+#import "DemoViewController.h"
+
+#include "MVKExample.h"
+
+
+const std::string VulkanExampleBase::getAssetPath() {
+ return [NSBundle.mainBundle.resourcePath stringByAppendingString: @"/data/"].UTF8String;
+}
+
+
+#pragma mark -
+#pragma mark DemoViewController
+
+@implementation DemoViewController {
+ MVKExample* _mvkExample;
+ CADisplayLink* _displayLink;
+ BOOL _viewHasAppeared;
+}
+
+/** Since this is a single-view app, init Vulkan when the view is loaded. */
+-(void) viewDidLoad {
+ [super viewDidLoad];
+
+ self.view.contentScaleFactor = UIScreen.mainScreen.nativeScale;
+
+ _mvkExample = new MVKExample(self.view);
+
+ uint32_t fps = 60;
+ _displayLink = [CADisplayLink displayLinkWithTarget: self selector: @selector(renderFrame)];
+ [_displayLink setFrameInterval: 60 / fps];
+ [_displayLink addToRunLoop: NSRunLoop.currentRunLoop forMode: NSDefaultRunLoopMode];
+
+ // Setup tap gesture to toggle virtual keyboard
+ UITapGestureRecognizer* tapSelector = [[UITapGestureRecognizer alloc]
+ initWithTarget: self action: @selector(handleTapGesture:)];
+ tapSelector.numberOfTapsRequired = 1;
+ tapSelector.cancelsTouchesInView = YES;
+ [self.view addGestureRecognizer: tapSelector];
+
+ _viewHasAppeared = NO;
+}
+
+-(void) viewDidAppear: (BOOL) animated {
+ [super viewDidAppear: animated];
+ _viewHasAppeared = YES;
+}
+
+-(BOOL) canBecomeFirstResponder { return _viewHasAppeared; }
+
+-(void) renderFrame {
+ _mvkExample->renderFrame();
+}
+
+-(void) dealloc {
+ delete _mvkExample;
+ [super dealloc];
+}
+
+// Toggle the display of the virtual keyboard
+-(void) toggleKeyboard {
+ if (self.isFirstResponder) {
+ [self resignFirstResponder];
+ } else {
+ [self becomeFirstResponder];
+ }
+}
+
+// Display and hide the keyboard by tapping on the view
+-(void) handleTapGesture: (UITapGestureRecognizer*) gestureRecognizer {
+ if (gestureRecognizer.state == UIGestureRecognizerStateEnded) {
+ [self toggleKeyboard];
+ }
+}
+
+// Handle keyboard input
+-(void) handleKeyboardInput: (unichar) keycode {
+ _mvkExample->keyPressed(keycode);
+}
+
+
+#pragma mark UIKeyInput methods
+
+// Returns whether text is available
+-(BOOL) hasText { return YES; }
+
+// A key on the keyboard has been pressed.
+-(void) insertText: (NSString*) text {
+ unichar keycode = (text.length > 0) ? [text characterAtIndex: 0] : 0;
+ [self handleKeyboardInput: keycode];
+}
+
+// The delete backward key has been pressed.
+-(void) deleteBackward {
+ [self handleKeyboardInput: 0x33];
+}
+
+
+@end
+
+
+#pragma mark -
+#pragma mark DemoView
+
+@implementation DemoView
+
+/** Returns a Metal-compatible layer. */
++(Class) layerClass { return [CAMetalLayer class]; }
+
+@end
+
diff --git a/xcode/ios/Info.plist b/xcode/ios/Info.plist
new file mode 100644
index 0000000000..eb0fa65a1d
--- /dev/null
+++ b/xcode/ios/Info.plist
@@ -0,0 +1,44 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ English
+ CFBundleDisplayName
+ ${PRODUCT_NAME}
+ CFBundleExecutable
+ ${EXECUTABLE_NAME}
+ CFBundleIconFile
+ iOS/Resources/Icon.png
+ CFBundleIcons~ipad
+
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundlePackageType
+ APPL
+ CFBundleVersion
+ 1.0
+ LSApplicationCategoryType
+
+ UIMainStoryboardFile
+ Main
+ UIRequiresFullScreen
+
+ UIStatusBarHidden
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationLandscapeRight
+ UIInterfaceOrientationLandscapeLeft
+
+ UIViewControllerBasedStatusBarAppearance
+
+
+
diff --git a/xcode/ios/Resources/Default-568h@2x.png b/xcode/ios/Resources/Default-568h@2x.png
new file mode 100755
index 0000000000..1669d7b684
Binary files /dev/null and b/xcode/ios/Resources/Default-568h@2x.png differ
diff --git a/xcode/ios/Resources/Default~ipad.png b/xcode/ios/Resources/Default~ipad.png
new file mode 100755
index 0000000000..ec9a3dcd14
Binary files /dev/null and b/xcode/ios/Resources/Default~ipad.png differ
diff --git a/xcode/ios/Resources/Icon.png b/xcode/ios/Resources/Icon.png
new file mode 100755
index 0000000000..dc3b10f5ea
Binary files /dev/null and b/xcode/ios/Resources/Icon.png differ
diff --git a/xcode/ios/Resources/Main.storyboard b/xcode/ios/Resources/Main.storyboard
new file mode 100644
index 0000000000..6205491f9f
--- /dev/null
+++ b/xcode/ios/Resources/Main.storyboard
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/xcode/ios/main.m b/xcode/ios/main.m
new file mode 100644
index 0000000000..d179e4174b
--- /dev/null
+++ b/xcode/ios/main.m
@@ -0,0 +1,14 @@
+/******************************************************************************
+ *
+ * main.m
+ *
+ ******************************************************************************/
+
+#import
+
+int main(int argc, char * argv[]) {
+ @autoreleasepool {
+ return UIApplicationMain(argc, argv, nil, @"AppDelegate");
+ }
+}
+
diff --git a/xcode/macos/AppDelegate.h b/xcode/macos/AppDelegate.h
new file mode 100644
index 0000000000..3eb638e981
--- /dev/null
+++ b/xcode/macos/AppDelegate.h
@@ -0,0 +1,12 @@
+/*
+ * AppDelegate.h
+ *
+ * Copyright (c) 2016-2017 The Brenwill Workshop Ltd.
+ * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+ */
+
+#import
+
+@interface AppDelegate : NSObject
+
+@end
diff --git a/xcode/macos/AppDelegate.m b/xcode/macos/AppDelegate.m
new file mode 100644
index 0000000000..c3ce3b2403
--- /dev/null
+++ b/xcode/macos/AppDelegate.m
@@ -0,0 +1,28 @@
+/*
+ * AppDelegate.m
+ *
+ * Copyright (c) 2016-2017 The Brenwill Workshop Ltd.
+ * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+ */
+
+#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
diff --git a/xcode/macos/DemoViewController.h b/xcode/macos/DemoViewController.h
new file mode 100644
index 0000000000..3cbedc4892
--- /dev/null
+++ b/xcode/macos/DemoViewController.h
@@ -0,0 +1,25 @@
+/*
+ * DemoViewController.h
+ *
+ * Copyright (c) 2016-2017 The Brenwill Workshop Ltd.
+ * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+ */
+
+#import
+
+
+#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
+
diff --git a/xcode/macos/DemoViewController.mm b/xcode/macos/DemoViewController.mm
new file mode 100644
index 0000000000..657f0b5f02
--- /dev/null
+++ b/xcode/macos/DemoViewController.mm
@@ -0,0 +1,86 @@
+/*
+ * DemoViewController.mm
+ *
+ * Copyright (c) 2016-2017 The Brenwill Workshop Ltd.
+ * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+ */
+
+#import "DemoViewController.h"
+#import
+
+#include "MVKExample.h"
+
+
+const std::string VulkanExampleBase::getAssetPath() {
+ return [NSBundle.mainBundle.resourcePath stringByAppendingString: @"/data/"].UTF8String;
+}
+
+/** 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) {
+ ((MVKExample*)target)->renderFrame();
+ return kCVReturnSuccess;
+}
+
+
+#pragma mark -
+#pragma mark DemoViewController
+
+@implementation DemoViewController {
+ MVKExample* _mvkExample;
+ CVDisplayLinkRef _displayLink;
+}
+
+/** 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.
+
+ _mvkExample = new MVKExample(self.view);
+
+ CVDisplayLinkCreateWithActiveCGDisplays(&_displayLink);
+ CVDisplayLinkSetOutputCallback(_displayLink, &DisplayLinkCallback, _mvkExample);
+ CVDisplayLinkStart(_displayLink);
+}
+
+-(void) dealloc {
+ CVDisplayLinkRelease(_displayLink);
+ delete _mvkExample;
+ [super dealloc];
+}
+
+// Handle keyboard input
+-(void) keyDown:(NSEvent*) theEvent {
+ _mvkExample->keyPressed(theEvent.keyCode);
+}
+
+@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
diff --git a/xcode/macos/Info.plist b/xcode/macos/Info.plist
new file mode 100644
index 0000000000..e921bd0e65
--- /dev/null
+++ b/xcode/macos/Info.plist
@@ -0,0 +1,34 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ ${EXECUTABLE_NAME}
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ ${PRODUCT_NAME}
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1
+ LSApplicationCategoryType
+
+ LSMinimumSystemVersion
+ ${MACOSX_DEPLOYMENT_TARGET}
+ NSHumanReadableCopyright
+ Copyright (c) 2016-2017 The Brenwill Workshop Ltd.
+ NSMainStoryboardFile
+ Main
+ NSPrincipalClass
+ NSApplication
+
+
diff --git a/xcode/macos/Resources/Main.storyboard b/xcode/macos/Resources/Main.storyboard
new file mode 100644
index 0000000000..5291336637
--- /dev/null
+++ b/xcode/macos/Resources/Main.storyboard
@@ -0,0 +1,133 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/xcode/macos/Resources/macOS.xcassets/AppIcon.appiconset/Contents.json b/xcode/macos/Resources/macOS.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000000..4124516b14
--- /dev/null
+++ b/xcode/macos/Resources/macOS.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,63 @@
+{
+ "images" : [
+ {
+ "size" : "16x16",
+ "idiom" : "mac",
+ "filename" : "Icon-16.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "mac",
+ "size" : "16x16",
+ "scale" : "2x"
+ },
+ {
+ "size" : "32x32",
+ "idiom" : "mac",
+ "filename" : "Icon-32.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "mac",
+ "size" : "32x32",
+ "scale" : "2x"
+ },
+ {
+ "size" : "128x128",
+ "idiom" : "mac",
+ "filename" : "Icon-128.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "mac",
+ "size" : "128x128",
+ "scale" : "2x"
+ },
+ {
+ "size" : "256x256",
+ "idiom" : "mac",
+ "filename" : "Icon-256.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "mac",
+ "size" : "256x256",
+ "scale" : "2x"
+ },
+ {
+ "size" : "512x512",
+ "idiom" : "mac",
+ "filename" : "Icon-512.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "mac",
+ "size" : "512x512",
+ "scale" : "2x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/xcode/macos/Resources/macOS.xcassets/AppIcon.appiconset/Icon-128.png b/xcode/macos/Resources/macOS.xcassets/AppIcon.appiconset/Icon-128.png
new file mode 100644
index 0000000000..8c55f1bea0
Binary files /dev/null and b/xcode/macos/Resources/macOS.xcassets/AppIcon.appiconset/Icon-128.png differ
diff --git a/xcode/macos/Resources/macOS.xcassets/AppIcon.appiconset/Icon-16.png b/xcode/macos/Resources/macOS.xcassets/AppIcon.appiconset/Icon-16.png
new file mode 100644
index 0000000000..583d636d60
Binary files /dev/null and b/xcode/macos/Resources/macOS.xcassets/AppIcon.appiconset/Icon-16.png differ
diff --git a/xcode/macos/Resources/macOS.xcassets/AppIcon.appiconset/Icon-256.png b/xcode/macos/Resources/macOS.xcassets/AppIcon.appiconset/Icon-256.png
new file mode 100644
index 0000000000..bb35d46e2b
Binary files /dev/null and b/xcode/macos/Resources/macOS.xcassets/AppIcon.appiconset/Icon-256.png differ
diff --git a/xcode/macos/Resources/macOS.xcassets/AppIcon.appiconset/Icon-32.png b/xcode/macos/Resources/macOS.xcassets/AppIcon.appiconset/Icon-32.png
new file mode 100644
index 0000000000..d73e1f60ed
Binary files /dev/null and b/xcode/macos/Resources/macOS.xcassets/AppIcon.appiconset/Icon-32.png differ
diff --git a/xcode/macos/Resources/macOS.xcassets/AppIcon.appiconset/Icon-512.png b/xcode/macos/Resources/macOS.xcassets/AppIcon.appiconset/Icon-512.png
new file mode 100644
index 0000000000..f2d01ac262
Binary files /dev/null and b/xcode/macos/Resources/macOS.xcassets/AppIcon.appiconset/Icon-512.png differ
diff --git a/xcode/macos/Resources/macOS.xcassets/Contents.json b/xcode/macos/Resources/macOS.xcassets/Contents.json
new file mode 100644
index 0000000000..da4a164c91
--- /dev/null
+++ b/xcode/macos/Resources/macOS.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/xcode/macos/main.m b/xcode/macos/main.m
new file mode 100644
index 0000000000..01b929e174
--- /dev/null
+++ b/xcode/macos/main.m
@@ -0,0 +1,12 @@
+/*
+ * main.m
+ *
+ * Copyright (c) 2016-2017 The Brenwill Workshop Ltd.
+ * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+ */
+
+#import
+
+int main(int argc, const char * argv[]) {
+ return NSApplicationMain(argc, argv);
+}