macOS: Add macOS support
diff --git a/layers/CMakeLists.txt b/layers/CMakeLists.txt
index 08b0e20..7a1390a 100644
--- a/layers/CMakeLists.txt
+++ b/layers/CMakeLists.txt
@@ -21,6 +21,11 @@
         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()
@@ -70,7 +75,7 @@
             )
         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})
@@ -85,6 +90,31 @@
             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)))
@@ -127,6 +157,17 @@
     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})
diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp
index c00c91f..74eae32 100644
--- a/layers/core_validation.cpp
+++ b/layers/core_validation.cpp
@@ -11076,6 +11076,20 @@
 }
 #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) {
@@ -12031,6 +12045,12 @@
     {"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},
diff --git a/layers/macos/VkLayer_core_validation.json b/layers/macos/VkLayer_core_validation.json
new file mode 100644
index 0000000..8c3d81b
--- /dev/null
+++ b/layers/macos/VkLayer_core_validation.json
@@ -0,0 +1,29 @@
+{
+    "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"
+                       ]
+             }
+         ]
+    }
+}
diff --git a/layers/macos/VkLayer_device_simulation.json b/layers/macos/VkLayer_device_simulation.json
new file mode 100644
index 0000000..b2eada6
--- /dev/null
+++ b/layers/macos/VkLayer_device_simulation.json
@@ -0,0 +1,11 @@
+{
+    "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"
+    }
+}
diff --git a/layers/macos/VkLayer_object_tracker.json b/layers/macos/VkLayer_object_tracker.json
new file mode 100644
index 0000000..ba84603
--- /dev/null
+++ b/layers/macos/VkLayer_object_tracker.json
@@ -0,0 +1,29 @@
+{
+    "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"
+                       ]
+             }
+         ]
+    }
+}
diff --git a/layers/macos/VkLayer_parameter_validation.json b/layers/macos/VkLayer_parameter_validation.json
new file mode 100644
index 0000000..579324a
--- /dev/null
+++ b/layers/macos/VkLayer_parameter_validation.json
@@ -0,0 +1,29 @@
+{
+    "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"
+                       ]
+             }
+         ]
+    }
+}
diff --git a/layers/macos/VkLayer_standard_validation.json b/layers/macos/VkLayer_standard_validation.json
new file mode 100644
index 0000000..1be9fee
--- /dev/null
+++ b/layers/macos/VkLayer_standard_validation.json
@@ -0,0 +1,17 @@
+{
+    "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"
+        ]
+    }
+}
diff --git a/layers/macos/VkLayer_threading.json b/layers/macos/VkLayer_threading.json
new file mode 100644
index 0000000..d6af6c0
--- /dev/null
+++ b/layers/macos/VkLayer_threading.json
@@ -0,0 +1,17 @@
+{
+    "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"
+             }
+         ]
+    }
+}
diff --git a/layers/macos/VkLayer_unique_objects.json b/layers/macos/VkLayer_unique_objects.json
new file mode 100644
index 0000000..63c5306
--- /dev/null
+++ b/layers/macos/VkLayer_unique_objects.json
@@ -0,0 +1,11 @@
+{
+    "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"
+    }
+}
diff --git a/layers/threading.h b/layers/threading.h
index 950d77c..e2301d0 100644
--- a/layers/threading.h
+++ b/layers/threading.h
@@ -96,8 +96,9 @@
                 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()) {
@@ -123,8 +124,9 @@
                 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()) {
@@ -181,8 +183,9 @@
             // 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()) {