Merge tag 'vulkan-cts-1.1.2.3' into master

Vulkan CTS 1.1.2.3

New tests:
 * Add convert tests for 8-bit integers
 * Add float <--> int conversion tests
 * Add operation tests for 8-bit integers
 * Add fp16 <-> fp64 conversion tests
 * Tests for VK_KHR_shader_float_controls
 * FP16 precision tests VK_KHR_shader_float16_int8
 * SPIR-V tests for VK_KHR_shader_float16_int8
 * Add tests for VK_EXT_scalar_block_layout
 * Add tests for OpSpecConstantOp INotEqual

Improvements:
 * Refactor: Compatible compute and graphics VerifyIO

Fixes: * Properly align and pad vec16x2 values in UBO array
 * Properly analyze edge0>=edge1 cases in smoothstep
 * Remove NaN from OpFOrd* and OpFUnord* tests
 * Fix array stride in uniform buffer for VK_KHR_16bit_storage
 * Don't include source files in other source files
 * Fix missing self dependency in renderpass tests
 * Add watchdog touches to dEQP-VK.api.descriptor_pool#repeated_reset_long
 * Fix swapchain creation in dEQP-VK.wsi.*.swapchain.*
 * Fix case when unsuported create flag was used for AHB
 * Correct vertex input tests on null driver
 * Correct image properties tests on Null driver
 * Fix non-constant Id in subgroupBroadcast
 * Remove texel_view uncompressed float formats
 * Fix: alloc_callback_fail.render_pass test
 * Fix: adds checking the maxPerStageResources limit
 * Fix pointer storage class for spirv_assembly tessellation tests.
 * Fix incorrect decoration on PushConstant
 * Remove unsupported image load store tests
 * Fix image feature checks for swapchain_mutable.*

MA-526
Test: hikey960:go/magma-tps#L0

Change-Id: I56b0c44ac0b885b9c84b30f75f03146fb7a58a23
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3caa6d4..ce315e5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -332,3 +332,7 @@
 	set_target_properties(deqp PROPERTIES XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY "1,2")
 	set_target_properties(deqp PROPERTIES XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "iPhone Developer: ${DEQP_IOS_CODE_SIGN_IDENTITY}")
 endif ()
+
+if (DE_OS_IS_FUCHSIA)
+	set_target_properties(deqp-vk PROPERTIES LINK_FLAGS "-Wl,-z,stack-size=0x100000")
+endif ()
\ No newline at end of file
diff --git a/execserver/CMakeLists.txt b/execserver/CMakeLists.txt
index b6d0005..5a58de3 100644
--- a/execserver/CMakeLists.txt
+++ b/execserver/CMakeLists.txt
@@ -38,17 +38,17 @@
 
 include_directories(.)
 
-if (DE_OS_IS_WIN32 OR DE_OS_IS_OSX OR DE_OS_IS_UNIX)
+if (DE_OS_IS_WIN32 OR DE_OS_IS_OSX OR DE_OS_IS_UNIX OR DE_OS_IS_FUCHSIA)
 	# Build standalone execserver binary
 	add_executable(execserver tools/xsMain.cpp)
-	target_link_libraries(execserver xscore)
+	target_link_libraries(execserver xscore ${DEQP_PLATFORM_LIBRARIES})
 
 	# Tests
 	add_executable(execserver-test tools/xsTest.cpp)
-	target_link_libraries(execserver-test xscore)
+	target_link_libraries(execserver-test xscore ${DEQP_PLATFORM_LIBRARIES})
 	add_dependencies(execserver-test execserver)
 
 	# Basic client
 	add_executable(execserver-client tools/xsClient.cpp)
-	target_link_libraries(execserver-client xscore)
+	target_link_libraries(execserver-client xscore ${DEQP_PLATFORM_LIBRARIES})
 endif ()
diff --git a/executor/CMakeLists.txt b/executor/CMakeLists.txt
index 117515a..73b3227 100644
--- a/executor/CMakeLists.txt
+++ b/executor/CMakeLists.txt
@@ -51,9 +51,9 @@
 
 include_directories(.)
 
-if (DE_OS_IS_WIN32 OR DE_OS_IS_UNIX OR DE_OS_IS_OSX OR DE_OS_IS_ANDROID)
+if (DE_OS_IS_WIN32 OR DE_OS_IS_UNIX OR DE_OS_IS_OSX OR DE_OS_IS_ANDROID OR DE_OS_IS_FUCHSIA)
 	add_executable(executor tools/xeCommandLineExecutor.cpp)
-	target_link_libraries(executor xecore)
+	target_link_libraries(executor xecore ${DEQP_PLATFORM_LIBRARIES})
 endif ()
 
 if (DE_OS_IS_WIN32 OR DE_OS_IS_UNIX OR DE_OS_IS_OSX)
diff --git a/external/fetch_sources.py b/external/fetch_sources.py
index 98fdbce..c84973d 100755
--- a/external/fetch_sources.py
+++ b/external/fetch_sources.py
@@ -244,28 +244,27 @@
 				os.path.join(path, "pnglibconf.h"))
 
 PACKAGES = [
-	SourcePackage(
-		"http://zlib.net/zlib-1.2.11.tar.gz",
-		"zlib-1.2.11.tar.gz",
-		"c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1",
+	GitRepo(
+		"https://fuchsia.googlesource.com/third_party/zlib",
+		None,
+		"master",
 		"zlib"),
-	SourcePackage(
-		"http://prdownloads.sourceforge.net/libpng/libpng-1.6.27.tar.gz",
-		"libpng-1.6.27.tar.gz",
-		"c9d164ec247f426a525a7b89936694aefbc91fb7a50182b198898b8fc91174b4",
-		"libpng",
-		postExtract = postExtractLibpng),
 	GitRepo(
-		"https://github.com/KhronosGroup/SPIRV-Tools.git",
+		"https://fuchsia.googlesource.com/third_party/libpng",
 		None,
-		"0c172a6b74fcf0baf221e8eb70b5c7c4d8b47088",
-		"spirv-tools"),
+		"master",
+		"libpng"),
 	GitRepo(
-		"https://github.com/KhronosGroup/glslang.git",
+		"https://fuchsia.googlesource.com/third_party/spirv-tools",
 		None,
-		"0bb930fc0fbe5258261e807ee875bb77258c1a86",
-		"glslang",
-		removeTags = ["master-tot"]),
+		"5a5904e6a5767d3b8f5534d92819bb8c59d1a063",
+		"spirv-tools",
+		removeTags=["master-tot"]),
+	GitRepo(
+		"https://fuchsia.googlesource.com/third_party/glslang",
+		None,
+		"b11a9e04b42f99e592d18f3317ea2952d966effa",
+		"glslang"),
 	GitRepo(
 		"https://github.com/KhronosGroup/SPIRV-Headers.git",
 		None,
diff --git a/external/vulkancts/framework/vulkan/vkBasicTypes.inl b/external/vulkancts/framework/vulkan/vkBasicTypes.inl
index 271d2d6..e918778 100644
--- a/external/vulkancts/framework/vulkan/vkBasicTypes.inl
+++ b/external/vulkancts/framework/vulkan/vkBasicTypes.inl
@@ -340,6 +340,12 @@
 	VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR							= 1000196000,
 	VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR					= 1000197000,
 	VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR				= 1000211000,
+	VK_STRUCTURE_TYPE_IMPORT_MEMORY_FUCHSIA_HANDLE_INFO_KHR							= 1001000000,
+	VK_STRUCTURE_TYPE_MEMORY_FUCHSIA_HANDLE_PROPERTIES_KHR							= 1001000001,
+	VK_STRUCTURE_TYPE_MEMORY_GET_FUCHSIA_HANDLE_INFO_KHR							= 1001000002,
+	VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FUCHSIA_HANDLE_INFO_KHR						= 1001001000,
+	VK_STRUCTURE_TYPE_SEMAPHORE_GET_FUCHSIA_HANDLE_INFO_KHR							= 1001001001,
+	VK_STRUCTURE_TYPE_MAGMA_SURFACE_CREATE_INFO_KHR									= 1001002000,
 	VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT				= 1000221000,
 };
 
@@ -1646,6 +1652,7 @@
 	VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT						= 0x00000020,
 	VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT					= 0x00000040,
 	VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID	= 0x00000400,
+	VK_EXTERNAL_MEMORY_HANDLE_TYPE_FUCHSIA_VMO_BIT_KHR					= 0x00000800,
 };
 typedef deUint32 VkExternalMemoryHandleTypeFlags;
 
@@ -1692,6 +1699,7 @@
 	VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT	= 0x00000004,
 	VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT		= 0x00000008,
 	VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT			= 0x00000010,
+	VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FUCHSIA_FENCE_BIT_KHR	= 0x00000020,
 };
 typedef deUint32 VkExternalSemaphoreHandleTypeFlags;
 
@@ -1924,6 +1932,7 @@
 VK_DEFINE_PLATFORM_TYPE(Win32SecurityAttributesPtr,	const void*);
 VK_DEFINE_PLATFORM_TYPE(AndroidHardwareBufferPtr,	void*);
 VK_DEFINE_PLATFORM_TYPE(RROutput,					void*);
+VK_DEFINE_PLATFORM_TYPE(ZXHandle,					deUint32);
 #define VK_COLORSPACE_SRGB_NONLINEAR_KHR VK_COLOR_SPACE_SRGB_NONLINEAR_KHR
 #define VK_DEPENDENCY_VIEW_LOCAL_BIT_KHR VK_DEPENDENCY_VIEW_LOCAL_BIT
 #define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES
diff --git a/external/vulkancts/framework/vulkan/vkConcreteDeviceInterface.inl b/external/vulkancts/framework/vulkan/vkConcreteDeviceInterface.inl
index 53235e3..deed8bd 100644
--- a/external/vulkancts/framework/vulkan/vkConcreteDeviceInterface.inl
+++ b/external/vulkancts/framework/vulkan/vkConcreteDeviceInterface.inl
@@ -200,3 +200,7 @@
 virtual VkResult			getValidationCacheDataEXT					(VkDevice device, VkValidationCacheEXT validationCache, deUintptr* pDataSize, void* pData) const;
 virtual VkResult			getAndroidHardwareBufferPropertiesANDROID	(VkDevice device, const struct pt::AndroidHardwareBufferPtr buffer, VkAndroidHardwareBufferPropertiesANDROID* pProperties) const;
 virtual VkResult			getMemoryAndroidHardwareBufferANDROID		(VkDevice device, const VkMemoryGetAndroidHardwareBufferInfoANDROID* pInfo, struct pt::AndroidHardwareBufferPtr* pBuffer) const;
+virtual VkResult			getMemoryFuchsiaHandleKHR					(VkDevice device, const VkMemoryGetFuchsiaHandleInfoKHR* pGetFuchsiaHandleInfo, deUint32* pFuchsiaHandle) const;
+virtual VkResult			getMemoryFuchsiaHandlePropertiesKHR			(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, deUint32 fuchsiaHandle, VkMemoryFuchsiaHandlePropertiesKHR* pMemoryFuchsiaHandleProperties) const;
+virtual VkResult			importSemaphoreFuchsiaHandleKHR				(VkDevice device, const VkImportSemaphoreFuchsiaHandleInfoKHR* pImportSemaphoreFuchsiaHandleInfo) const;
+virtual VkResult			getSemaphoreFuchsiaHandleKHR				(VkDevice device, const VkSemaphoreGetFuchsiaHandleInfoKHR* pGetFuchsiaHandleInfo, deUint32* pFuchsiaHandle) const;
diff --git a/external/vulkancts/framework/vulkan/vkConcreteInstanceInterface.inl b/external/vulkancts/framework/vulkan/vkConcreteInstanceInterface.inl
index bdb44dd..0904b46 100644
--- a/external/vulkancts/framework/vulkan/vkConcreteInstanceInterface.inl
+++ b/external/vulkancts/framework/vulkan/vkConcreteInstanceInterface.inl
@@ -67,3 +67,5 @@
 virtual VkResult	createIOSSurfaceMVK									(VkInstance instance, const VkIOSSurfaceCreateInfoMVK* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) const;
 virtual VkResult	createMacOSSurfaceMVK								(VkInstance instance, const VkMacOSSurfaceCreateInfoMVK* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) const;
 virtual void		getPhysicalDeviceMultisamplePropertiesEXT			(VkPhysicalDevice physicalDevice, VkSampleCountFlagBits samples, VkMultisamplePropertiesEXT* pMultisampleProperties) const;
+virtual VkResult	createMagmaSurfaceKHR								(VkInstance instance, const VkMagmaSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) const;
+virtual VkBool32	getPhysicalDeviceMagmaPresentationSupportKHR		(VkPhysicalDevice physicalDevice, deUint32 queueFamilyIndex) const;
diff --git a/external/vulkancts/framework/vulkan/vkDeviceDriverImpl.inl b/external/vulkancts/framework/vulkan/vkDeviceDriverImpl.inl
index dd64fdd..f58cf27 100644
--- a/external/vulkancts/framework/vulkan/vkDeviceDriverImpl.inl
+++ b/external/vulkancts/framework/vulkan/vkDeviceDriverImpl.inl
@@ -996,3 +996,23 @@
 {
 	return m_vk.getMemoryAndroidHardwareBufferANDROID(device, pInfo, pBuffer);
 }
+
+VkResult DeviceDriver::getMemoryFuchsiaHandleKHR (VkDevice device, const VkMemoryGetFuchsiaHandleInfoKHR* pGetFuchsiaHandleInfo, deUint32* pFuchsiaHandle) const
+{
+	return m_vk.getMemoryFuchsiaHandleKHR(device, pGetFuchsiaHandleInfo, pFuchsiaHandle);
+}
+
+VkResult DeviceDriver::getMemoryFuchsiaHandlePropertiesKHR (VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, deUint32 fuchsiaHandle, VkMemoryFuchsiaHandlePropertiesKHR* pMemoryFuchsiaHandleProperties) const
+{
+	return m_vk.getMemoryFuchsiaHandlePropertiesKHR(device, handleType, fuchsiaHandle, pMemoryFuchsiaHandleProperties);
+}
+
+VkResult DeviceDriver::importSemaphoreFuchsiaHandleKHR (VkDevice device, const VkImportSemaphoreFuchsiaHandleInfoKHR* pImportSemaphoreFuchsiaHandleInfo) const
+{
+	return m_vk.importSemaphoreFuchsiaHandleKHR(device, pImportSemaphoreFuchsiaHandleInfo);
+}
+
+VkResult DeviceDriver::getSemaphoreFuchsiaHandleKHR (VkDevice device, const VkSemaphoreGetFuchsiaHandleInfoKHR* pGetFuchsiaHandleInfo, deUint32* pFuchsiaHandle) const
+{
+	return m_vk.getSemaphoreFuchsiaHandleKHR(device, pGetFuchsiaHandleInfo, pFuchsiaHandle);
+}
diff --git a/external/vulkancts/framework/vulkan/vkDeviceFunctionPointers.inl b/external/vulkancts/framework/vulkan/vkDeviceFunctionPointers.inl
index 09ea12e..8579c78 100644
--- a/external/vulkancts/framework/vulkan/vkDeviceFunctionPointers.inl
+++ b/external/vulkancts/framework/vulkan/vkDeviceFunctionPointers.inl
@@ -200,3 +200,7 @@
 GetValidationCacheDataEXTFunc					getValidationCacheDataEXT;
 GetAndroidHardwareBufferPropertiesANDROIDFunc	getAndroidHardwareBufferPropertiesANDROID;
 GetMemoryAndroidHardwareBufferANDROIDFunc		getMemoryAndroidHardwareBufferANDROID;
+GetMemoryFuchsiaHandleKHRFunc					getMemoryFuchsiaHandleKHR;
+GetMemoryFuchsiaHandlePropertiesKHRFunc			getMemoryFuchsiaHandlePropertiesKHR;
+ImportSemaphoreFuchsiaHandleKHRFunc				importSemaphoreFuchsiaHandleKHR;
+GetSemaphoreFuchsiaHandleKHRFunc				getSemaphoreFuchsiaHandleKHR;
diff --git a/external/vulkancts/framework/vulkan/vkFunctionPointerTypes.inl b/external/vulkancts/framework/vulkan/vkFunctionPointerTypes.inl
index e938b0d..f7db5c5 100644
--- a/external/vulkancts/framework/vulkan/vkFunctionPointerTypes.inl
+++ b/external/vulkancts/framework/vulkan/vkFunctionPointerTypes.inl
@@ -297,3 +297,9 @@
 typedef VKAPI_ATTR VkResult				(VKAPI_CALL* GetValidationCacheDataEXTFunc)							(VkDevice device, VkValidationCacheEXT validationCache, deUintptr* pDataSize, void* pData);
 typedef VKAPI_ATTR VkResult				(VKAPI_CALL* GetAndroidHardwareBufferPropertiesANDROIDFunc)			(VkDevice device, const struct pt::AndroidHardwareBufferPtr buffer, VkAndroidHardwareBufferPropertiesANDROID* pProperties);
 typedef VKAPI_ATTR VkResult				(VKAPI_CALL* GetMemoryAndroidHardwareBufferANDROIDFunc)				(VkDevice device, const VkMemoryGetAndroidHardwareBufferInfoANDROID* pInfo, struct pt::AndroidHardwareBufferPtr* pBuffer);
+typedef VKAPI_ATTR VkResult				(VKAPI_CALL* GetMemoryFuchsiaHandleKHRFunc)							(VkDevice device, const VkMemoryGetFuchsiaHandleInfoKHR* pGetFuchsiaHandleInfo, deUint32* pFuchsiaHandle);
+typedef VKAPI_ATTR VkResult				(VKAPI_CALL* GetMemoryFuchsiaHandlePropertiesKHRFunc)				(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, deUint32 fuchsiaHandle, VkMemoryFuchsiaHandlePropertiesKHR* pMemoryFuchsiaHandleProperties);
+typedef VKAPI_ATTR VkResult				(VKAPI_CALL* ImportSemaphoreFuchsiaHandleKHRFunc)					(VkDevice device, const VkImportSemaphoreFuchsiaHandleInfoKHR* pImportSemaphoreFuchsiaHandleInfo);
+typedef VKAPI_ATTR VkResult				(VKAPI_CALL* GetSemaphoreFuchsiaHandleKHRFunc)						(VkDevice device, const VkSemaphoreGetFuchsiaHandleInfoKHR* pGetFuchsiaHandleInfo, deUint32* pFuchsiaHandle);
+typedef VKAPI_ATTR VkResult				(VKAPI_CALL* CreateMagmaSurfaceKHRFunc)								(VkInstance instance, const VkMagmaSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
+typedef VKAPI_ATTR VkBool32				(VKAPI_CALL* GetPhysicalDeviceMagmaPresentationSupportKHRFunc)		(VkPhysicalDevice physicalDevice, deUint32 queueFamilyIndex);
diff --git a/external/vulkancts/framework/vulkan/vkGetStructureTypeImpl.inl b/external/vulkancts/framework/vulkan/vkGetStructureTypeImpl.inl
index f1035c5..802e636 100644
--- a/external/vulkancts/framework/vulkan/vkGetStructureTypeImpl.inl
+++ b/external/vulkancts/framework/vulkan/vkGetStructureTypeImpl.inl
@@ -1191,6 +1191,36 @@
 	return VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR;
 }
 
+template<> VkStructureType getStructureType<VkImportMemoryFuchsiaHandleInfoKHR> (void)
+{
+	return VK_STRUCTURE_TYPE_IMPORT_MEMORY_FUCHSIA_HANDLE_INFO_KHR;
+}
+
+template<> VkStructureType getStructureType<VkMemoryFuchsiaHandlePropertiesKHR> (void)
+{
+	return VK_STRUCTURE_TYPE_MEMORY_FUCHSIA_HANDLE_PROPERTIES_KHR;
+}
+
+template<> VkStructureType getStructureType<VkMemoryGetFuchsiaHandleInfoKHR> (void)
+{
+	return VK_STRUCTURE_TYPE_MEMORY_GET_FUCHSIA_HANDLE_INFO_KHR;
+}
+
+template<> VkStructureType getStructureType<VkImportSemaphoreFuchsiaHandleInfoKHR> (void)
+{
+	return VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FUCHSIA_HANDLE_INFO_KHR;
+}
+
+template<> VkStructureType getStructureType<VkSemaphoreGetFuchsiaHandleInfoKHR> (void)
+{
+	return VK_STRUCTURE_TYPE_SEMAPHORE_GET_FUCHSIA_HANDLE_INFO_KHR;
+}
+
+template<> VkStructureType getStructureType<VkMagmaSurfaceCreateInfoKHR> (void)
+{
+	return VK_STRUCTURE_TYPE_MAGMA_SURFACE_CREATE_INFO_KHR;
+}
+
 template<> VkStructureType getStructureType<VkPhysicalDeviceScalarBlockLayoutFeaturesEXT> (void)
 {
 	return VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT;
diff --git a/external/vulkancts/framework/vulkan/vkInitDeviceFunctionPointers.inl b/external/vulkancts/framework/vulkan/vkInitDeviceFunctionPointers.inl
index 382e763..72538e7 100644
--- a/external/vulkancts/framework/vulkan/vkInitDeviceFunctionPointers.inl
+++ b/external/vulkancts/framework/vulkan/vkInitDeviceFunctionPointers.inl
@@ -230,3 +230,7 @@
 m_vk.getValidationCacheDataEXT					= (GetValidationCacheDataEXTFunc)					GET_PROC_ADDR("vkGetValidationCacheDataEXT");
 m_vk.getAndroidHardwareBufferPropertiesANDROID	= (GetAndroidHardwareBufferPropertiesANDROIDFunc)	GET_PROC_ADDR("vkGetAndroidHardwareBufferPropertiesANDROID");
 m_vk.getMemoryAndroidHardwareBufferANDROID		= (GetMemoryAndroidHardwareBufferANDROIDFunc)		GET_PROC_ADDR("vkGetMemoryAndroidHardwareBufferANDROID");
+m_vk.getMemoryFuchsiaHandleKHR					= (GetMemoryFuchsiaHandleKHRFunc)					GET_PROC_ADDR("vkGetMemoryFuchsiaHandleKHR");
+m_vk.getMemoryFuchsiaHandlePropertiesKHR		= (GetMemoryFuchsiaHandlePropertiesKHRFunc)			GET_PROC_ADDR("vkGetMemoryFuchsiaHandlePropertiesKHR");
+m_vk.importSemaphoreFuchsiaHandleKHR			= (ImportSemaphoreFuchsiaHandleKHRFunc)				GET_PROC_ADDR("vkImportSemaphoreFuchsiaHandleKHR");
+m_vk.getSemaphoreFuchsiaHandleKHR				= (GetSemaphoreFuchsiaHandleKHRFunc)				GET_PROC_ADDR("vkGetSemaphoreFuchsiaHandleKHR");
diff --git a/external/vulkancts/framework/vulkan/vkInitInstanceFunctionPointers.inl b/external/vulkancts/framework/vulkan/vkInitInstanceFunctionPointers.inl
index 7dbce45..0a08c90 100644
--- a/external/vulkancts/framework/vulkan/vkInitInstanceFunctionPointers.inl
+++ b/external/vulkancts/framework/vulkan/vkInitInstanceFunctionPointers.inl
@@ -99,3 +99,5 @@
 m_vk.createIOSSurfaceMVK									= (CreateIOSSurfaceMVKFunc)									GET_PROC_ADDR("vkCreateIOSSurfaceMVK");
 m_vk.createMacOSSurfaceMVK									= (CreateMacOSSurfaceMVKFunc)								GET_PROC_ADDR("vkCreateMacOSSurfaceMVK");
 m_vk.getPhysicalDeviceMultisamplePropertiesEXT				= (GetPhysicalDeviceMultisamplePropertiesEXTFunc)			GET_PROC_ADDR("vkGetPhysicalDeviceMultisamplePropertiesEXT");
+m_vk.createMagmaSurfaceKHR									= (CreateMagmaSurfaceKHRFunc)								GET_PROC_ADDR("vkCreateMagmaSurfaceKHR");
+m_vk.getPhysicalDeviceMagmaPresentationSupportKHR			= (GetPhysicalDeviceMagmaPresentationSupportKHRFunc)		GET_PROC_ADDR("vkGetPhysicalDeviceMagmaPresentationSupportKHR");
diff --git a/external/vulkancts/framework/vulkan/vkInstanceDriverImpl.inl b/external/vulkancts/framework/vulkan/vkInstanceDriverImpl.inl
index cde1b79..5fa8c98 100644
--- a/external/vulkancts/framework/vulkan/vkInstanceDriverImpl.inl
+++ b/external/vulkancts/framework/vulkan/vkInstanceDriverImpl.inl
@@ -381,3 +381,13 @@
 {
 	m_vk.getPhysicalDeviceMultisamplePropertiesEXT(physicalDevice, samples, pMultisampleProperties);
 }
+
+VkResult InstanceDriver::createMagmaSurfaceKHR (VkInstance instance, const VkMagmaSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) const
+{
+	return m_vk.createMagmaSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
+}
+
+VkBool32 InstanceDriver::getPhysicalDeviceMagmaPresentationSupportKHR (VkPhysicalDevice physicalDevice, deUint32 queueFamilyIndex) const
+{
+	return m_vk.getPhysicalDeviceMagmaPresentationSupportKHR(physicalDevice, queueFamilyIndex);
+}
diff --git a/external/vulkancts/framework/vulkan/vkInstanceFunctionPointers.inl b/external/vulkancts/framework/vulkan/vkInstanceFunctionPointers.inl
index 9853d6c..d26b971 100644
--- a/external/vulkancts/framework/vulkan/vkInstanceFunctionPointers.inl
+++ b/external/vulkancts/framework/vulkan/vkInstanceFunctionPointers.inl
@@ -77,3 +77,5 @@
 CreateIOSSurfaceMVKFunc									createIOSSurfaceMVK;
 CreateMacOSSurfaceMVKFunc								createMacOSSurfaceMVK;
 GetPhysicalDeviceMultisamplePropertiesEXTFunc			getPhysicalDeviceMultisamplePropertiesEXT;
+CreateMagmaSurfaceKHRFunc								createMagmaSurfaceKHR;
+GetPhysicalDeviceMagmaPresentationSupportKHRFunc		getPhysicalDeviceMagmaPresentationSupportKHR;
diff --git a/external/vulkancts/framework/vulkan/vkNullDriver.cpp b/external/vulkancts/framework/vulkan/vkNullDriver.cpp
index 52f2fe7..50701aa 100644
--- a/external/vulkancts/framework/vulkan/vkNullDriver.cpp
+++ b/external/vulkancts/framework/vulkan/vkNullDriver.cpp
@@ -206,6 +206,7 @@
 										SurfaceKHR		(VkInstance, const VkViSurfaceCreateInfoNN*)		{}
 										SurfaceKHR		(VkInstance, const VkIOSSurfaceCreateInfoMVK*)		{}
 										SurfaceKHR		(VkInstance, const VkMacOSSurfaceCreateInfoMVK*)	{}
+										SurfaceKHR		(VkInstance, const VkMagmaSurfaceCreateInfoKHR*)	{}
 										~SurfaceKHR		(void)												{}
 };
 
diff --git a/external/vulkancts/framework/vulkan/vkNullDriverImpl.inl b/external/vulkancts/framework/vulkan/vkNullDriverImpl.inl
index e81b3ab..ae7174a 100644
--- a/external/vulkancts/framework/vulkan/vkNullDriverImpl.inl
+++ b/external/vulkancts/framework/vulkan/vkNullDriverImpl.inl
@@ -223,6 +223,12 @@
 	VK_NULL_RETURN((*pValidationCache = allocateNonDispHandle<ValidationCacheEXT, VkValidationCacheEXT>(device, pCreateInfo, pAllocator)));
 }
 
+VKAPI_ATTR VkResult VKAPI_CALL createMagmaSurfaceKHR (VkInstance instance, const VkMagmaSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface)
+{
+	DE_UNREF(pAllocator);
+	VK_NULL_RETURN((*pSurface = allocateNonDispHandle<SurfaceKHR, VkSurfaceKHR>(instance, pCreateInfo, pAllocator)));
+}
+
 VKAPI_ATTR void VKAPI_CALL destroyInstance (VkInstance instance, const VkAllocationCallbacks* pAllocator)
 {
 	freeHandle<Instance, VkInstance>(instance, pAllocator);
@@ -1853,6 +1859,45 @@
 	return VK_SUCCESS;
 }
 
+VKAPI_ATTR VkResult VKAPI_CALL getMemoryFuchsiaHandleKHR (VkDevice device, const VkMemoryGetFuchsiaHandleInfoKHR* pGetFuchsiaHandleInfo, deUint32* pFuchsiaHandle)
+{
+	DE_UNREF(device);
+	DE_UNREF(pGetFuchsiaHandleInfo);
+	DE_UNREF(pFuchsiaHandle);
+	return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL getMemoryFuchsiaHandlePropertiesKHR (VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, deUint32 fuchsiaHandle, VkMemoryFuchsiaHandlePropertiesKHR* pMemoryFuchsiaHandleProperties)
+{
+	DE_UNREF(device);
+	DE_UNREF(handleType);
+	DE_UNREF(fuchsiaHandle);
+	DE_UNREF(pMemoryFuchsiaHandleProperties);
+	return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL importSemaphoreFuchsiaHandleKHR (VkDevice device, const VkImportSemaphoreFuchsiaHandleInfoKHR* pImportSemaphoreFuchsiaHandleInfo)
+{
+	DE_UNREF(device);
+	DE_UNREF(pImportSemaphoreFuchsiaHandleInfo);
+	return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL getSemaphoreFuchsiaHandleKHR (VkDevice device, const VkSemaphoreGetFuchsiaHandleInfoKHR* pGetFuchsiaHandleInfo, deUint32* pFuchsiaHandle)
+{
+	DE_UNREF(device);
+	DE_UNREF(pGetFuchsiaHandleInfo);
+	DE_UNREF(pFuchsiaHandle);
+	return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkBool32 VKAPI_CALL getPhysicalDeviceMagmaPresentationSupportKHR (VkPhysicalDevice physicalDevice, deUint32 queueFamilyIndex)
+{
+	DE_UNREF(physicalDevice);
+	DE_UNREF(queueFamilyIndex);
+	return VK_SUCCESS;
+}
+
 static const tcu::StaticFunctionLibrary::Entry s_platformFunctions[] =
 {
 	VK_NULL_FUNC_ENTRY(vkCreateInstance,						createInstance),
@@ -1941,6 +1986,8 @@
 	VK_NULL_FUNC_ENTRY(vkCreateIOSSurfaceMVK,								createIOSSurfaceMVK),
 	VK_NULL_FUNC_ENTRY(vkCreateMacOSSurfaceMVK,								createMacOSSurfaceMVK),
 	VK_NULL_FUNC_ENTRY(vkGetPhysicalDeviceMultisamplePropertiesEXT,			getPhysicalDeviceMultisamplePropertiesEXT),
+	VK_NULL_FUNC_ENTRY(vkCreateMagmaSurfaceKHR,								createMagmaSurfaceKHR),
+	VK_NULL_FUNC_ENTRY(vkGetPhysicalDeviceMagmaPresentationSupportKHR,		getPhysicalDeviceMagmaPresentationSupportKHR),
 };
 
 static const tcu::StaticFunctionLibrary::Entry s_deviceFunctions[] =
@@ -2159,5 +2206,9 @@
 	VK_NULL_FUNC_ENTRY(vkGetValidationCacheDataEXT,					getValidationCacheDataEXT),
 	VK_NULL_FUNC_ENTRY(vkGetAndroidHardwareBufferPropertiesANDROID,	getAndroidHardwareBufferPropertiesANDROID),
 	VK_NULL_FUNC_ENTRY(vkGetMemoryAndroidHardwareBufferANDROID,		getMemoryAndroidHardwareBufferANDROID),
+	VK_NULL_FUNC_ENTRY(vkGetMemoryFuchsiaHandleKHR,					getMemoryFuchsiaHandleKHR),
+	VK_NULL_FUNC_ENTRY(vkGetMemoryFuchsiaHandlePropertiesKHR,		getMemoryFuchsiaHandlePropertiesKHR),
+	VK_NULL_FUNC_ENTRY(vkImportSemaphoreFuchsiaHandleKHR,			importSemaphoreFuchsiaHandleKHR),
+	VK_NULL_FUNC_ENTRY(vkGetSemaphoreFuchsiaHandleKHR,				getSemaphoreFuchsiaHandleKHR),
 };
 
diff --git a/external/vulkancts/framework/vulkan/vkRefUtil.inl b/external/vulkancts/framework/vulkan/vkRefUtil.inl
index 55bca6c..c0024cb 100644
--- a/external/vulkancts/framework/vulkan/vkRefUtil.inl
+++ b/external/vulkancts/framework/vulkan/vkRefUtil.inl
@@ -40,3 +40,4 @@
 Move<VkSurfaceKHR>					createIOSSurfaceMVK				(const InstanceInterface& vk, VkInstance instance, const VkIOSSurfaceCreateInfoMVK* pCreateInfo, const VkAllocationCallbacks* pAllocator = DE_NULL);
 Move<VkSurfaceKHR>					createMacOSSurfaceMVK			(const InstanceInterface& vk, VkInstance instance, const VkMacOSSurfaceCreateInfoMVK* pCreateInfo, const VkAllocationCallbacks* pAllocator = DE_NULL);
 Move<VkValidationCacheEXT>			createValidationCacheEXT		(const DeviceInterface& vk, VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator = DE_NULL);
+Move<VkSurfaceKHR>					createMagmaSurfaceKHR			(const InstanceInterface& vk, VkInstance instance, const VkMagmaSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator = DE_NULL);
diff --git a/external/vulkancts/framework/vulkan/vkRefUtilImpl.inl b/external/vulkancts/framework/vulkan/vkRefUtilImpl.inl
index c2dfeaa..a4b0501 100644
--- a/external/vulkancts/framework/vulkan/vkRefUtilImpl.inl
+++ b/external/vulkancts/framework/vulkan/vkRefUtilImpl.inl
@@ -429,3 +429,10 @@
 	return Move<VkValidationCacheEXT>(check<VkValidationCacheEXT>(object), Deleter<VkValidationCacheEXT>(vk, device, pAllocator));
 }
 
+Move<VkSurfaceKHR> createMagmaSurfaceKHR (const InstanceInterface& vk, VkInstance instance, const VkMagmaSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator)
+{
+	VkSurfaceKHR object = 0;
+	VK_CHECK(vk.createMagmaSurfaceKHR(instance, pCreateInfo, pAllocator, &object));
+	return Move<VkSurfaceKHR>(check<VkSurfaceKHR>(object), Deleter<VkSurfaceKHR>(vk, instance, pAllocator));
+}
+
diff --git a/external/vulkancts/framework/vulkan/vkStrUtil.inl b/external/vulkancts/framework/vulkan/vkStrUtil.inl
index 63b810e..7cf99a4 100644
--- a/external/vulkancts/framework/vulkan/vkStrUtil.inl
+++ b/external/vulkancts/framework/vulkan/vkStrUtil.inl
@@ -607,4 +607,10 @@
 std::ostream&	operator<<	(std::ostream& s, const VkDescriptorPoolInlineUniformBlockCreateInfoEXT& value);
 std::ostream&	operator<<	(std::ostream& s, const VkPhysicalDeviceShaderAtomicInt64FeaturesKHR& value);
 std::ostream&	operator<<	(std::ostream& s, const VkPhysicalDeviceVulkanMemoryModelFeaturesKHR& value);
+std::ostream&	operator<<	(std::ostream& s, const VkImportMemoryFuchsiaHandleInfoKHR& value);
+std::ostream&	operator<<	(std::ostream& s, const VkMemoryFuchsiaHandlePropertiesKHR& value);
+std::ostream&	operator<<	(std::ostream& s, const VkMemoryGetFuchsiaHandleInfoKHR& value);
+std::ostream&	operator<<	(std::ostream& s, const VkImportSemaphoreFuchsiaHandleInfoKHR& value);
+std::ostream&	operator<<	(std::ostream& s, const VkSemaphoreGetFuchsiaHandleInfoKHR& value);
+std::ostream&	operator<<	(std::ostream& s, const VkMagmaSurfaceCreateInfoKHR& value);
 std::ostream&	operator<<	(std::ostream& s, const VkPhysicalDeviceScalarBlockLayoutFeaturesEXT& value);
diff --git a/external/vulkancts/framework/vulkan/vkStrUtilImpl.inl b/external/vulkancts/framework/vulkan/vkStrUtilImpl.inl
index 7856475..d965c16 100644
--- a/external/vulkancts/framework/vulkan/vkStrUtilImpl.inl
+++ b/external/vulkancts/framework/vulkan/vkStrUtilImpl.inl
@@ -56,6 +56,7 @@
 std::ostream& operator<< (std::ostream& s, Win32SecurityAttributesPtr	v) { return s << tcu::toHex(v.internal); }
 std::ostream& operator<< (std::ostream& s, AndroidHardwareBufferPtr		v) { return s << tcu::toHex(v.internal); }
 std::ostream& operator<< (std::ostream& s, RROutput						v) { return s << tcu::toHex(v.internal); }
+std::ostream& operator<< (std::ostream& s, ZXHandle						v) { return s << tcu::toHex(v.internal); }
 }
 
 const char* getPipelineCacheHeaderVersionName (VkPipelineCacheHeaderVersion value)
@@ -349,6 +350,12 @@
 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR:							return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR";
 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR:					return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR";
 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR:				return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR";
+		case VK_STRUCTURE_TYPE_IMPORT_MEMORY_FUCHSIA_HANDLE_INFO_KHR:							return "VK_STRUCTURE_TYPE_IMPORT_MEMORY_FUCHSIA_HANDLE_INFO_KHR";
+		case VK_STRUCTURE_TYPE_MEMORY_FUCHSIA_HANDLE_PROPERTIES_KHR:							return "VK_STRUCTURE_TYPE_MEMORY_FUCHSIA_HANDLE_PROPERTIES_KHR";
+		case VK_STRUCTURE_TYPE_MEMORY_GET_FUCHSIA_HANDLE_INFO_KHR:								return "VK_STRUCTURE_TYPE_MEMORY_GET_FUCHSIA_HANDLE_INFO_KHR";
+		case VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FUCHSIA_HANDLE_INFO_KHR:						return "VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FUCHSIA_HANDLE_INFO_KHR";
+		case VK_STRUCTURE_TYPE_SEMAPHORE_GET_FUCHSIA_HANDLE_INFO_KHR:							return "VK_STRUCTURE_TYPE_SEMAPHORE_GET_FUCHSIA_HANDLE_INFO_KHR";
+		case VK_STRUCTURE_TYPE_MAGMA_SURFACE_CREATE_INFO_KHR:									return "VK_STRUCTURE_TYPE_MAGMA_SURFACE_CREATE_INFO_KHR";
 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT:				return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT";
 		default:																				return DE_NULL;
 	}
@@ -1895,6 +1902,7 @@
 		tcu::Format::BitDesc(VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT,							"VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT"),
 		tcu::Format::BitDesc(VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT,						"VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT"),
 		tcu::Format::BitDesc(VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,	"VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID"),
+		tcu::Format::BitDesc(VK_EXTERNAL_MEMORY_HANDLE_TYPE_FUCHSIA_VMO_BIT_KHR,					"VK_EXTERNAL_MEMORY_HANDLE_TYPE_FUCHSIA_VMO_BIT_KHR"),
 	};
 	return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
 }
@@ -1959,6 +1967,7 @@
 		tcu::Format::BitDesc(VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,	"VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT"),
 		tcu::Format::BitDesc(VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT,			"VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT"),
 		tcu::Format::BitDesc(VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,				"VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT"),
+		tcu::Format::BitDesc(VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FUCHSIA_FENCE_BIT_KHR,	"VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FUCHSIA_FENCE_BIT_KHR"),
 	};
 	return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
 }
@@ -6447,6 +6456,74 @@
 	return s;
 }
 
+std::ostream& operator<< (std::ostream& s, const VkImportMemoryFuchsiaHandleInfoKHR& value)
+{
+	s << "VkImportMemoryFuchsiaHandleInfoKHR = {\n";
+	s << "\tsType = " << value.sType << '\n';
+	s << "\tpNext = " << value.pNext << '\n';
+	s << "\thandleType = " << value.handleType << '\n';
+	s << "\thandle = " << value.handle << '\n';
+	s << '}';
+	return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkMemoryFuchsiaHandlePropertiesKHR& value)
+{
+	s << "VkMemoryFuchsiaHandlePropertiesKHR = {\n";
+	s << "\tsType = " << value.sType << '\n';
+	s << "\tpNext = " << value.pNext << '\n';
+	s << "\tmemoryTypeBits = " << value.memoryTypeBits << '\n';
+	s << '}';
+	return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkMemoryGetFuchsiaHandleInfoKHR& value)
+{
+	s << "VkMemoryGetFuchsiaHandleInfoKHR = {\n";
+	s << "\tsType = " << value.sType << '\n';
+	s << "\tpNext = " << value.pNext << '\n';
+	s << "\tmemory = " << value.memory << '\n';
+	s << "\thandleType = " << value.handleType << '\n';
+	s << '}';
+	return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkImportSemaphoreFuchsiaHandleInfoKHR& value)
+{
+	s << "VkImportSemaphoreFuchsiaHandleInfoKHR = {\n";
+	s << "\tsType = " << value.sType << '\n';
+	s << "\tpNext = " << value.pNext << '\n';
+	s << "\tsemaphore = " << value.semaphore << '\n';
+	s << "\tflags = " << getSemaphoreImportFlagsStr(value.flags) << '\n';
+	s << "\thandleType = " << value.handleType << '\n';
+	s << "\thandle = " << value.handle << '\n';
+	s << '}';
+	return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkSemaphoreGetFuchsiaHandleInfoKHR& value)
+{
+	s << "VkSemaphoreGetFuchsiaHandleInfoKHR = {\n";
+	s << "\tsType = " << value.sType << '\n';
+	s << "\tpNext = " << value.pNext << '\n';
+	s << "\tsemaphore = " << value.semaphore << '\n';
+	s << "\thandleType = " << value.handleType << '\n';
+	s << '}';
+	return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkMagmaSurfaceCreateInfoKHR& value)
+{
+	s << "VkMagmaSurfaceCreateInfoKHR = {\n";
+	s << "\tsType = " << value.sType << '\n';
+	s << "\tpNext = " << value.pNext << '\n';
+	s << "\timagePipeHandle = " << value.imagePipeHandle << '\n';
+	s << "\twidth = " << value.width << '\n';
+	s << "\theight = " << value.height << '\n';
+	s << '}';
+	return s;
+}
+
 std::ostream& operator<< (std::ostream& s, const VkPhysicalDeviceScalarBlockLayoutFeaturesEXT& value)
 {
 	s << "VkPhysicalDeviceScalarBlockLayoutFeaturesEXT = {\n";
diff --git a/external/vulkancts/framework/vulkan/vkStructTypes.inl b/external/vulkancts/framework/vulkan/vkStructTypes.inl
index a7df481..ec4da59 100644
--- a/external/vulkancts/framework/vulkan/vkStructTypes.inl
+++ b/external/vulkancts/framework/vulkan/vkStructTypes.inl
@@ -3130,6 +3130,56 @@
 	VkBool32		vulkanMemoryModelDeviceScope;
 };
 
+struct VkImportMemoryFuchsiaHandleInfoKHR
+{
+	VkStructureType						sType;
+	const void*							pNext;
+	VkExternalMemoryHandleTypeFlagBits	handleType;
+	deUint32							handle;
+};
+
+struct VkMemoryFuchsiaHandlePropertiesKHR
+{
+	VkStructureType	sType;
+	void*			pNext;
+	deUint32		memoryTypeBits;
+};
+
+struct VkMemoryGetFuchsiaHandleInfoKHR
+{
+	VkStructureType						sType;
+	const void*							pNext;
+	VkDeviceMemory						memory;
+	VkExternalMemoryHandleTypeFlagBits	handleType;
+};
+
+struct VkImportSemaphoreFuchsiaHandleInfoKHR
+{
+	VkStructureType							sType;
+	const void*								pNext;
+	VkSemaphore								semaphore;
+	VkSemaphoreImportFlags					flags;
+	VkExternalSemaphoreHandleTypeFlagBits	handleType;
+	deUint32								handle;
+};
+
+struct VkSemaphoreGetFuchsiaHandleInfoKHR
+{
+	VkStructureType							sType;
+	const void*								pNext;
+	VkSemaphore								semaphore;
+	VkExternalSemaphoreHandleTypeFlagBits	handleType;
+};
+
+struct VkMagmaSurfaceCreateInfoKHR
+{
+	VkStructureType	sType;
+	const void*		pNext;
+	pt::ZXHandle	imagePipeHandle;
+	deUint32		width;
+	deUint32		height;
+};
+
 struct VkPhysicalDeviceScalarBlockLayoutFeaturesEXT
 {
 	VkStructureType	sType;
diff --git a/external/vulkancts/framework/vulkan/vkVirtualDeviceInterface.inl b/external/vulkancts/framework/vulkan/vkVirtualDeviceInterface.inl
index 028d6ca..5cbab5d 100644
--- a/external/vulkancts/framework/vulkan/vkVirtualDeviceInterface.inl
+++ b/external/vulkancts/framework/vulkan/vkVirtualDeviceInterface.inl
@@ -200,3 +200,7 @@
 virtual VkResult			getValidationCacheDataEXT					(VkDevice device, VkValidationCacheEXT validationCache, deUintptr* pDataSize, void* pData) const = 0;
 virtual VkResult			getAndroidHardwareBufferPropertiesANDROID	(VkDevice device, const struct pt::AndroidHardwareBufferPtr buffer, VkAndroidHardwareBufferPropertiesANDROID* pProperties) const = 0;
 virtual VkResult			getMemoryAndroidHardwareBufferANDROID		(VkDevice device, const VkMemoryGetAndroidHardwareBufferInfoANDROID* pInfo, struct pt::AndroidHardwareBufferPtr* pBuffer) const = 0;
+virtual VkResult			getMemoryFuchsiaHandleKHR					(VkDevice device, const VkMemoryGetFuchsiaHandleInfoKHR* pGetFuchsiaHandleInfo, deUint32* pFuchsiaHandle) const = 0;
+virtual VkResult			getMemoryFuchsiaHandlePropertiesKHR			(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, deUint32 fuchsiaHandle, VkMemoryFuchsiaHandlePropertiesKHR* pMemoryFuchsiaHandleProperties) const = 0;
+virtual VkResult			importSemaphoreFuchsiaHandleKHR				(VkDevice device, const VkImportSemaphoreFuchsiaHandleInfoKHR* pImportSemaphoreFuchsiaHandleInfo) const = 0;
+virtual VkResult			getSemaphoreFuchsiaHandleKHR				(VkDevice device, const VkSemaphoreGetFuchsiaHandleInfoKHR* pGetFuchsiaHandleInfo, deUint32* pFuchsiaHandle) const = 0;
diff --git a/external/vulkancts/framework/vulkan/vkVirtualInstanceInterface.inl b/external/vulkancts/framework/vulkan/vkVirtualInstanceInterface.inl
index c889707..7532cb4 100644
--- a/external/vulkancts/framework/vulkan/vkVirtualInstanceInterface.inl
+++ b/external/vulkancts/framework/vulkan/vkVirtualInstanceInterface.inl
@@ -67,3 +67,5 @@
 virtual VkResult	createIOSSurfaceMVK									(VkInstance instance, const VkIOSSurfaceCreateInfoMVK* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) const = 0;
 virtual VkResult	createMacOSSurfaceMVK								(VkInstance instance, const VkMacOSSurfaceCreateInfoMVK* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) const = 0;
 virtual void		getPhysicalDeviceMultisamplePropertiesEXT			(VkPhysicalDevice physicalDevice, VkSampleCountFlagBits samples, VkMultisamplePropertiesEXT* pMultisampleProperties) const = 0;
+virtual VkResult	createMagmaSurfaceKHR								(VkInstance instance, const VkMagmaSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) const = 0;
+virtual VkBool32	getPhysicalDeviceMagmaPresentationSupportKHR		(VkPhysicalDevice physicalDevice, deUint32 queueFamilyIndex) const = 0;
diff --git a/external/vulkancts/modules/vulkan/CMakeLists.txt b/external/vulkancts/modules/vulkan/CMakeLists.txt
index 74e515a..3e93b88 100644
--- a/external/vulkancts/modules/vulkan/CMakeLists.txt
+++ b/external/vulkancts/modules/vulkan/CMakeLists.txt
@@ -137,3 +137,8 @@
 	add_executable(vk-build-programs vktBuildPrograms.cpp)
 	target_link_libraries(vk-build-programs deqp-vk${MODULE_LIB_TARGET_POSTFIX})
 endif ()
+
+if (DE_OS_IS_FUCHSIA)
+	target_link_libraries(deqp-vk "${FUCHSIA_LIB_DIR}/libvulkan.so")
+endif ()
+
diff --git a/external/vulkancts/modules/vulkan/api/vktApiExternalMemoryTests.cpp b/external/vulkancts/modules/vulkan/api/vktApiExternalMemoryTests.cpp
index 7e0d8a4..84740b2 100755
--- a/external/vulkancts/modules/vulkan/api/vktApiExternalMemoryTests.cpp
+++ b/external/vulkancts/modules/vulkan/api/vktApiExternalMemoryTests.cpp
@@ -285,6 +285,16 @@
 		deviceExtensions.push_back("VK_KHR_external_fence_win32");
 	}
 
+	if (externalMemoryTypes & vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_FUCHSIA_VMO_BIT_KHR)
+	{
+		deviceExtensions.push_back("VK_KHR_external_memory_fuchsia");
+	}
+
+	if (externalSemaphoreTypes & vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FUCHSIA_FENCE_BIT_KHR)
+	{
+		deviceExtensions.push_back("VK_KHR_external_semaphore_fuchsia");
+	}
+
 	if ((externalMemoryTypes
 			& (vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
 			   | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT
@@ -4181,6 +4191,7 @@
 	semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT).release());
 	semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
 	semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
+	semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FUCHSIA_FENCE_BIT_KHR).release());
 
 	return semaphoreGroup;
 }
@@ -4285,6 +4296,7 @@
 	group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
 	group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
 	group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID).release());
+	group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_FUCHSIA_VMO_BIT_KHR).release());
 
 	return group;
 }
diff --git a/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationCrossInstanceSharingTests.cpp b/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationCrossInstanceSharingTests.cpp
index 25fc89e..13277da 100644
--- a/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationCrossInstanceSharingTests.cpp
+++ b/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationCrossInstanceSharingTests.cpp
@@ -433,6 +433,13 @@
 		extensions.push_back("VK_KHR_external_memory_fd");
 	}
 
+	if (memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_FUCHSIA_VMO_BIT_KHR
+		|| semaphoreHandleType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FUCHSIA_FENCE_BIT_KHR)
+	{
+		extensions.push_back("VK_KHR_external_semaphore_fuchsia");
+		extensions.push_back("VK_KHR_external_memory_fuchsia");
+	}
+
 	if (memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
 		|| memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT
 		|| semaphoreHandleType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
@@ -1309,6 +1316,11 @@
 			vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT,
 			"_win32"
 		},
+		{
+			vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_FUCHSIA_VMO_BIT_KHR,
+			vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FUCHSIA_FENCE_BIT_KHR,
+			"_fuchsia_handle"
+		},
 	};
 	de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "cross_instance", ""));
 
diff --git a/external/vulkancts/modules/vulkan/vktExternalMemoryUtil.cpp b/external/vulkancts/modules/vulkan/vktExternalMemoryUtil.cpp
index 4ced4a1..b57f7bd 100644
--- a/external/vulkancts/modules/vulkan/vktExternalMemoryUtil.cpp
+++ b/external/vulkancts/modules/vulkan/vktExternalMemoryUtil.cpp
@@ -46,6 +46,12 @@
 #	define BUILT_WITH_ANDROID_HARDWARE_BUFFER 1
 #endif
 
+
+#if (DE_OS == DE_OS_FUCHSIA)
+#	include <zircon/syscalls.h>
+#	include <zircon/types.h>
+#endif
+
 namespace vkt
 {
 namespace ExternalMemoryUtil
@@ -70,6 +76,7 @@
 
 NativeHandle::NativeHandle (void)
 	: m_fd						(-1)
+	, m_fuchsiaHandle	(0)
 	, m_win32HandleType			(WIN32HANDLETYPE_LAST)
 	, m_win32Handle				(DE_NULL)
 	, m_androidHardwareBuffer	(DE_NULL)
@@ -78,6 +85,7 @@
 
 NativeHandle::NativeHandle (const NativeHandle& other)
 	: m_fd						(-1)
+	, m_fuchsiaHandle	(0)
 	, m_win32HandleType			(WIN32HANDLETYPE_LAST)
 	, m_win32Handle				(DE_NULL)
 	, m_androidHardwareBuffer	(DE_NULL)
@@ -93,6 +101,15 @@
 		DE_FATAL("Platform doesn't support file descriptors");
 #endif
 	}
+	else if (other.m_fuchsiaHandle)
+	{
+#if (DE_OS == DE_OS_FUCHSIA)
+		DE_ASSERT(!other.m_win32Handle.internal);
+		zx_handle_duplicate(other.m_fuchsiaHandle, ZX_RIGHT_SAME_RIGHTS, &m_fuchsiaHandle);
+#else
+		DE_FATAL("Platform doesn't support fuchsia handles");
+#endif
+	}
 	else if (other.m_win32Handle.internal)
 	{
 #if (DE_OS == DE_OS_WIN32)
@@ -137,6 +154,7 @@
 
 NativeHandle::NativeHandle (int fd)
 	: m_fd						(fd)
+	, m_fuchsiaHandle	(0)
 	, m_win32HandleType			(WIN32HANDLETYPE_LAST)
 	, m_win32Handle				(DE_NULL)
 	, m_androidHardwareBuffer	(DE_NULL)
@@ -145,6 +163,7 @@
 
 NativeHandle::NativeHandle (Win32HandleType handleType, vk::pt::Win32Handle handle)
 	: m_fd						(-1)
+	, m_fuchsiaHandle	(0)
 	, m_win32HandleType			(handleType)
 	, m_win32Handle				(handle)
 	, m_androidHardwareBuffer	(DE_NULL)
@@ -153,6 +172,7 @@
 
 NativeHandle::NativeHandle (vk::pt::AndroidHardwareBufferPtr buffer)
 	: m_fd						(-1)
+	, m_fuchsiaHandle	(0)
 	, m_win32HandleType			(WIN32HANDLETYPE_LAST)
 	, m_win32Handle				(DE_NULL)
 	, m_androidHardwareBuffer	(buffer)
@@ -177,6 +197,15 @@
 #endif
 	}
 
+	if (m_fuchsiaHandle > 0) {
+#if (DE_OS == DE_OS_FUCHSIA)
+		zx_handle_close(m_fuchsiaHandle);
+#else
+		DE_FATAL("Platform doesn't support fuchsia handles");
+#endif
+	}
+
+
 	if (m_win32Handle.internal)
 	{
 #if (DE_OS == DE_OS_WIN32)
@@ -205,6 +234,7 @@
 		AndroidHardwareBufferExternalApi::getInstance()->release(m_androidHardwareBuffer);
 	}
 	m_fd					= -1;
+	m_fuchsiaHandle		= 0;
 	m_win32Handle			= vk::pt::Win32Handle(DE_NULL);
 	m_win32HandleType		= WIN32HANDLETYPE_LAST;
 	m_androidHardwareBuffer	= vk::pt::AndroidHardwareBufferPtr(DE_NULL);
@@ -236,9 +266,17 @@
 	m_win32Handle		= handle;
 }
 
+void NativeHandle::setFuchsiaHandle (uint32_t fuchsiaHandle)
+{
+	reset();
+
+	m_fuchsiaHandle 	= fuchsiaHandle;
+}
+
 void NativeHandle::disown (void)
 {
 	m_fd = -1;
+	m_fuchsiaHandle = 0;
 	m_win32Handle = vk::pt::Win32Handle(DE_NULL);
 	m_androidHardwareBuffer = vk::pt::AndroidHardwareBufferPtr(DE_NULL);
 }
@@ -257,6 +295,13 @@
 	return m_fd;
 }
 
+uint32_t NativeHandle::getFuchsiaHandle (void) const
+{
+	DE_ASSERT(!m_win32Handle.internal);
+
+	return m_fuchsiaHandle;
+}
+
 
 vk::pt::AndroidHardwareBufferPtr NativeHandle::getAndroidHardwareBuffer (void) const
 {
@@ -284,6 +329,9 @@
 		case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT:
 			return "sync_fd";
 
+		case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FUCHSIA_FENCE_BIT_KHR:
+			return "fuchsia_fence";
+
 		default:
 			DE_FATAL("Unknown external semaphore type");
 			return DE_NULL;
@@ -340,6 +388,10 @@
 		case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID:
 			return "android_hardware_buffer";
 
+		case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_FUCHSIA_VMO_BIT_KHR:
+			return "fuchsia_vmo";
+
+
 		default:
 			DE_FATAL("Unknown external memory type");
 			return DE_NULL;
@@ -361,6 +413,9 @@
 		case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT:
 			return permanence == PERMANENCE_TEMPORARY;
 
+		case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FUCHSIA_FENCE_BIT_KHR:
+			return permanence == PERMANENCE_PERMANENT || permanence == PERMANENCE_TEMPORARY;
+
 		default:
 			DE_FATAL("Unknown external semaphore type");
 			return false;
@@ -381,6 +436,9 @@
 		case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT:
 			return TRANSFERENCE_COPY;
 
+		case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FUCHSIA_FENCE_BIT_KHR:
+			return TRANSFERENCE_REFERENCE;
+
 		default:
 			DE_FATAL("Unknown external semaphore type");
 			return TRANSFERENCE_REFERENCE;
@@ -471,6 +529,21 @@
 		TCU_CHECK(fd >= 0);
 		nativeHandle = fd;
 	}
+	else if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_FUCHSIA_VMO_BIT_KHR)
+	{
+		const vk::VkMemoryGetFuchsiaHandleInfoKHR	info	=
+		{
+			vk::VK_STRUCTURE_TYPE_MEMORY_GET_FUCHSIA_HANDLE_INFO_KHR,
+			DE_NULL,
+
+			memory,
+			externalType
+		};
+		uint32_t							fuchsiaHandle		= -1;
+
+		VK_CHECK(vkd.getMemoryFuchsiaHandleKHR(device, &info, &fuchsiaHandle));
+		nativeHandle.setFuchsiaHandle(fuchsiaHandle);
+	}
 	else if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
 		|| externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
 	{
@@ -742,6 +815,21 @@
 		TCU_CHECK(fd >= 0);
 		nativeHandle = fd;
 	}
+	else if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FUCHSIA_FENCE_BIT_KHR)
+	{
+		const vk::VkSemaphoreGetFuchsiaHandleInfoKHR	info	=
+		{
+			vk::VK_STRUCTURE_TYPE_SEMAPHORE_GET_FUCHSIA_HANDLE_INFO_KHR,
+			DE_NULL,
+
+			semaphore,
+			externalType
+		};
+		unsigned int									fuchsiaHandle	= 0;
+
+		VK_CHECK(vkd.getSemaphoreFuchsiaHandleKHR(device, &info, &fuchsiaHandle));
+		nativeHandle.setFuchsiaHandle(fuchsiaHandle);
+	}
 	else if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
 		|| externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
 	{
@@ -798,6 +886,21 @@
 		VK_CHECK(vkd.importSemaphoreFdKHR(device, &importInfo));
 		handle.disown();
 	}
+	else if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FUCHSIA_FENCE_BIT_KHR)
+	{
+		const vk::VkImportSemaphoreFuchsiaHandleInfoKHR	importInfo	=
+		{
+			vk::VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FUCHSIA_HANDLE_INFO_KHR,
+			DE_NULL,
+			semaphore,
+			flags,
+			externalType,
+			handle.getFuchsiaHandle()
+		};
+
+		VK_CHECK(vkd.importSemaphoreFuchsiaHandleKHR(device, &importInfo));
+		handle.disown();
+	}
 	else if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
 			|| externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
 	{
@@ -966,6 +1069,35 @@
 			externalType,
 			handle.getFd()
 		};
+		const vk::VkMemoryDedicatedAllocateInfo	dedicatedInfo	=
+		{
+			vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
+			&importInfo,
+			image,
+			buffer,
+		};
+		const vk::VkMemoryAllocateInfo				info			=
+		{
+			vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+			(isDedicated ? (const void*)&dedicatedInfo : (const void*)&importInfo),
+			requirements.size,
+			(memoryTypeIndex == ~0U) ? chooseMemoryType(requirements.memoryTypeBits) : memoryTypeIndex
+		};
+		vk::Move<vk::VkDeviceMemory> memory (vk::allocateMemory(vkd, device, &info));
+
+		handle.disown();
+
+		return memory;
+	}
+	else if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_FUCHSIA_VMO_BIT_KHR)
+	{
+		const vk::VkImportMemoryFuchsiaHandleInfoKHR			importInfo		=
+		{
+			vk::VK_STRUCTURE_TYPE_IMPORT_MEMORY_FUCHSIA_HANDLE_INFO_KHR,
+			DE_NULL,
+			externalType,
+			handle.getFuchsiaHandle()
+		};
 		const vk::VkMemoryDedicatedAllocateInfo		dedicatedInfo	=
 		{
 			vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
diff --git a/external/vulkancts/modules/vulkan/vktExternalMemoryUtil.hpp b/external/vulkancts/modules/vulkan/vktExternalMemoryUtil.hpp
index 6b494b1..61ff512 100644
--- a/external/vulkancts/modules/vulkan/vktExternalMemoryUtil.hpp
+++ b/external/vulkancts/modules/vulkan/vktExternalMemoryUtil.hpp
@@ -52,16 +52,19 @@
 	NativeHandle&						operator=					(int fd);
 	NativeHandle&						operator=					(vk::pt::AndroidHardwareBufferPtr buffer);
 
+	void				setFuchsiaHandle(uint32_t fuchsiaHandle);
 	void								setWin32Handle				(Win32HandleType type, vk::pt::Win32Handle handle);
 
 	vk::pt::Win32Handle					getWin32Handle				(void) const;
 	int									getFd						(void) const;
 	vk::pt::AndroidHardwareBufferPtr	getAndroidHardwareBuffer	(void) const;
+	uint32_t			getFuchsiaHandle(void) const;
 	void								disown						(void);
 	void								reset						(void);
 
 private:
 	int									m_fd;
+	uint32_t			m_fuchsiaHandle;
 	Win32HandleType						m_win32HandleType;
 	vk::pt::Win32Handle					m_win32Handle;
 	vk::pt::AndroidHardwareBufferPtr	m_androidHardwareBuffer;
diff --git a/external/vulkancts/scripts/gen_framework.py b/external/vulkancts/scripts/gen_framework.py
index 2fd406d..7cb25d1 100644
--- a/external/vulkancts/scripts/gen_framework.py
+++ b/external/vulkancts/scripts/gen_framework.py
@@ -95,7 +95,9 @@
 	(["AHardwareBuffer", "*"],				["AndroidHardwareBufferPtr"],	"void*"),
 
 	# VK_EXT_acquire_xlib_display
-	(["RROutput"],							["RROutput"],					"void*")
+	(["RROutput"],							["RROutput"],					"void*"),
+
+	(["zx_handle_t"],						["ZXHandle"],					"deUint32")
 ]
 
 PLATFORM_TYPE_NAMESPACE	= "pt"
diff --git a/external/vulkancts/scripts/src/vulkan.h.in b/external/vulkancts/scripts/src/vulkan.h.in
index 8877a02..f0b3705 100755
--- a/external/vulkancts/scripts/src/vulkan.h.in
+++ b/external/vulkancts/scripts/src/vulkan.h.in
@@ -402,6 +402,12 @@
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR = 1000196000,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR = 1000197000,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR = 1000211000,
+    VK_STRUCTURE_TYPE_IMPORT_MEMORY_FUCHSIA_HANDLE_INFO_KHR = 1001000000,
+    VK_STRUCTURE_TYPE_MEMORY_FUCHSIA_HANDLE_PROPERTIES_KHR = 1001000001,
+    VK_STRUCTURE_TYPE_MEMORY_GET_FUCHSIA_HANDLE_INFO_KHR = 1001000002,
+    VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FUCHSIA_HANDLE_INFO_KHR = 1001001000,
+    VK_STRUCTURE_TYPE_SEMAPHORE_GET_FUCHSIA_HANDLE_INFO_KHR = 1001001001,
+    VK_STRUCTURE_TYPE_MAGMA_SURFACE_CREATE_INFO_KHR = 1001002000,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT = 1000221000,
     VK_STRUCTURE_TYPE_BEGIN_RANGE = VK_STRUCTURE_TYPE_APPLICATION_INFO,
     VK_STRUCTURE_TYPE_END_RANGE = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO,
@@ -3657,6 +3663,7 @@
     VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT = 0x00000020,
     VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT = 0x00000040,
     VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID = 0x00000400,
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_FUCHSIA_VMO_BIT_KHR = 0x00000800,
     VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkExternalMemoryHandleTypeFlagBits;
 typedef VkFlags VkExternalMemoryHandleTypeFlags;
@@ -3703,6 +3710,7 @@
     VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0x00000004,
     VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT = 0x00000008,
     VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT = 0x00000010,
+    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FUCHSIA_FENCE_BIT_KHR = 0x00000020,
     VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkExternalSemaphoreHandleTypeFlagBits;
 typedef VkFlags VkExternalSemaphoreHandleTypeFlags;
@@ -7949,6 +7957,117 @@
     VkBool32           vulkanMemoryModelDeviceScope;
 } VkPhysicalDeviceVulkanMemoryModelFeaturesKHR;
 
+#if VK_USE_PLATFORM_FUCHSIA_KHR
+
+#define VK_KHR_external_memory_fuchsia 1
+#define VK_KHR_EXTERNAL_MEMORY_FUCHSIA_SPEC_VERSION 1
+#define VK_KHR_EXTERNAL_MEMORY_FUCHSIA_EXTENSION_NAME "VK_KHR_external_memory_fuchsia"
+
+typedef struct VkImportMemoryFuchsiaHandleInfoKHR {
+    VkStructureType                       sType;
+    const void*                           pNext;
+    VkExternalMemoryHandleTypeFlagBits    handleType;
+    uint32_t                              handle;
+} VkImportMemoryFuchsiaHandleInfoKHR;
+
+typedef struct VkMemoryFuchsiaHandlePropertiesKHR {
+    VkStructureType    sType;
+    void*              pNext;
+    uint32_t           memoryTypeBits;
+} VkMemoryFuchsiaHandlePropertiesKHR;
+
+typedef struct VkMemoryGetFuchsiaHandleInfoKHR {
+    VkStructureType                       sType;
+    const void*                           pNext;
+    VkDeviceMemory                        memory;
+    VkExternalMemoryHandleTypeFlagBits    handleType;
+} VkMemoryGetFuchsiaHandleInfoKHR;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFuchsiaHandleKHR)(VkDevice device, const VkMemoryGetFuchsiaHandleInfoKHR* pGetFuchsiaHandleInfo, uint32_t* pFuchsiaHandle);
+typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFuchsiaHandlePropertiesKHR)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, uint32_t fuchsiaHandle, VkMemoryFuchsiaHandlePropertiesKHR* pMemoryFuchsiaHandleProperties);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFuchsiaHandleKHR(
+    VkDevice                                    device,
+    const VkMemoryGetFuchsiaHandleInfoKHR*      pGetFuchsiaHandleInfo,
+    uint32_t*                                   pFuchsiaHandle);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFuchsiaHandlePropertiesKHR(
+    VkDevice                                    device,
+    VkExternalMemoryHandleTypeFlagBits          handleType,
+    uint32_t                                    fuchsiaHandle,
+    VkMemoryFuchsiaHandlePropertiesKHR*         pMemoryFuchsiaHandleProperties);
+#endif
+
+#define VK_KHR_external_semaphore_fuchsia 1
+#define VK_KHR_EXTERNAL_SEMAPHORE_FUCHSIA_SPEC_VERSION 1
+#define VK_KHR_EXTERNAL_SEMAPHORE_FUCHSIA_EXTENSION_NAME "VK_KHR_external_semaphore_fuchsia"
+
+typedef struct VkImportSemaphoreFuchsiaHandleInfoKHR {
+    VkStructureType                          sType;
+    const void*                              pNext;
+    VkSemaphore                              semaphore;
+    VkSemaphoreImportFlags                   flags;
+    VkExternalSemaphoreHandleTypeFlagBits    handleType;
+    uint32_t                                 handle;
+} VkImportSemaphoreFuchsiaHandleInfoKHR;
+
+typedef struct VkSemaphoreGetFuchsiaHandleInfoKHR {
+    VkStructureType                          sType;
+    const void*                              pNext;
+    VkSemaphore                              semaphore;
+    VkExternalSemaphoreHandleTypeFlagBits    handleType;
+} VkSemaphoreGetFuchsiaHandleInfoKHR;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkImportSemaphoreFuchsiaHandleKHR)(VkDevice device, const VkImportSemaphoreFuchsiaHandleInfoKHR* pImportSemaphoreFuchsiaHandleInfo);
+typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreFuchsiaHandleKHR)(VkDevice device, const VkSemaphoreGetFuchsiaHandleInfoKHR* pGetFuchsiaHandleInfo, uint32_t* pFuchsiaHandle);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreFuchsiaHandleKHR(
+    VkDevice                                    device,
+    const VkImportSemaphoreFuchsiaHandleInfoKHR* pImportSemaphoreFuchsiaHandleInfo);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreFuchsiaHandleKHR(
+    VkDevice                                    device,
+    const VkSemaphoreGetFuchsiaHandleInfoKHR*   pGetFuchsiaHandleInfo,
+    uint32_t*                                   pFuchsiaHandle);
+#endif
+
+#define VK_KHR_magma_surface 1
+#define VK_KHR_MAGMA_SURFACE_SPEC_VERSION 1
+#define VK_KHR_MAGMA_SURFACE_EXTENSION_NAME "VK_KHR_magma_surface"
+
+typedef struct VkMagmaSurfaceCreateInfoKHR {
+    VkStructureType    sType;
+    const void*        pNext;
+    zx_handle_t        imagePipeHandle;
+    uint32_t           width;
+    uint32_t           height;
+} VkMagmaSurfaceCreateInfoKHR;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateMagmaSurfaceKHR)(VkInstance instance, const VkMagmaSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
+typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceMagmaPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateMagmaSurfaceKHR(
+    VkInstance                                  instance,
+    const VkMagmaSurfaceCreateInfoKHR*          pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkSurfaceKHR*                               pSurface);
+
+VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceMagmaPresentationSupportKHR(
+    VkPhysicalDevice                            physicalDevice,
+    uint32_t                                    queueFamilyIndex);
+#endif
+
+#define VK_GOOGLE_image_usage_scanout 1
+#define VK_GOOGLE_IMAGE_USAGE_SCANOUT_SPEC_VERSION 1
+#define VK_GOOGLE_IMAGE_USAGE_SCANOUT_EXTENSION_NAME "VK_GOOGLE_image_usage_scanout"
+
+#endif
 
 #define VK_EXT_scalar_block_layout 1
 #define VK_EXT_SCALAR_BLOCK_LAYOUT_SPEC_VERSION 1
diff --git a/external/zlib/CMakeLists.txt b/external/zlib/CMakeLists.txt
index 40ca18d..cfeeb9e 100644
--- a/external/zlib/CMakeLists.txt
+++ b/external/zlib/CMakeLists.txt
@@ -56,7 +56,7 @@
 	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Wall /wd4127 /wd4131 /wd4242 /wd4244 /wd4996")
 
 elseif (DE_COMPILER_IS_GCC OR DE_COMPILER_IS_CLANG)
-	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-implicit-function-declaration")
+	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-implicit-function-declaration -std=c99")
 
 endif ()
 
diff --git a/framework/delibs/cmake/Defs.cmake b/framework/delibs/cmake/Defs.cmake
index e65015b..3e2de09 100644
--- a/framework/delibs/cmake/Defs.cmake
+++ b/framework/delibs/cmake/Defs.cmake
@@ -66,6 +66,7 @@
 DE_MAKE_ENV_BOOL("DE_OS" "OSX")
 DE_MAKE_ENV_BOOL("DE_OS" "ANDROID")
 DE_MAKE_ENV_BOOL("DE_OS" "IOS")
+DE_MAKE_ENV_BOOL("DE_OS" "FUCHSIA")
 
 # Prevent mixed compile with GCC and Clang
 if (NOT (CMAKE_C_COMPILER_ID MATCHES "GNU") EQUAL (CMAKE_CXX_COMPILER_ID MATCHES "GNU"))
diff --git a/framework/delibs/debase/deDefs.c b/framework/delibs/debase/deDefs.c
index 18cf1bf..7075cc8 100644
--- a/framework/delibs/debase/deDefs.c
+++ b/framework/delibs/debase/deDefs.c
@@ -122,7 +122,7 @@
 	}
 #elif ((DE_OS == DE_OS_WIN32) && (DE_COMPILER == DE_COMPILER_CLANG))
 	_assert(reason, file, line);
-#elif (DE_OS == DE_OS_UNIX)
+#elif (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_FUCHSIA)
 	__assert_fail(reason, file, (unsigned int)line, "Unknown function");
 #elif (DE_OS == DE_OS_QNX)
     __assert(reason, file, (unsigned int)line, "Unknown function");
diff --git a/framework/delibs/debase/deDefs.h b/framework/delibs/debase/deDefs.h
index bff057f..7b70abd 100644
--- a/framework/delibs/debase/deDefs.h
+++ b/framework/delibs/debase/deDefs.h
@@ -78,6 +78,7 @@
 #define DE_OS_SYMBIAN	6			/*!< Symbian OS									*/
 #define DE_OS_IOS		7			/*!< iOS										*/
 #define DE_OS_QNX       8           /*!< QNX                                        */
+#define DE_OS_FUCHSIA   9           /*!< Fuchsia									*/
 
 /* OS detection (set to one of DE_OS_*). */
 #if defined(DE_OS)
diff --git a/framework/delibs/decpp/deDirectoryIterator.hpp b/framework/delibs/decpp/deDirectoryIterator.hpp
index 6e5b04d..abd0327 100644
--- a/framework/delibs/decpp/deDirectoryIterator.hpp
+++ b/framework/delibs/decpp/deDirectoryIterator.hpp
@@ -31,7 +31,7 @@
 
 #if (DE_OS == DE_OS_WIN32 && DE_COMPILER == DE_COMPILER_MSC)
 #	define DE_DIRITER DE_DIRITER_WIN32
-#elif (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_OSX) || (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_SYMBIAN) || (DE_OS == DE_OS_IOS) || (DE_OS == DE_OS_QNX) || (DE_OS == DE_OS_WIN32 && DE_COMPILER == DE_COMPILER_CLANG)
+#elif (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_OSX) || (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_SYMBIAN) || (DE_OS == DE_OS_IOS) || (DE_OS == DE_OS_QNX) || (DE_OS == DE_OS_WIN32 && DE_COMPILER == DE_COMPILER_CLANG) || (DE_OS == DE_OS_FUCHSIA)
 #	define DE_DIRITER DE_DIRITER_POSIX
 #endif
 
diff --git a/framework/delibs/decpp/deFilePath.cpp b/framework/delibs/decpp/deFilePath.cpp
index f27098f..553bef7 100644
--- a/framework/delibs/decpp/deFilePath.cpp
+++ b/framework/delibs/decpp/deFilePath.cpp
@@ -246,7 +246,7 @@
 #if (DE_OS == DE_OS_WIN32)
 	if (!CreateDirectory(path, DE_NULL))
 		throw std::runtime_error("Failed to create directory");
-#elif (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_OSX) || (DE_OS == DE_OS_IOS) || (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_SYMBIAN) || (DE_OS == DE_OS_QNX)
+#elif (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_OSX) || (DE_OS == DE_OS_IOS) || (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_SYMBIAN) || (DE_OS == DE_OS_QNX) || (DE_OS == DE_OS_FUCHSIA)
 	if (mkdir(path, 0777) != 0)
 		throw std::runtime_error("Failed to create directory");
 #else
diff --git a/framework/delibs/dethread/CMakeLists.txt b/framework/delibs/dethread/CMakeLists.txt
index 227bb71..a50b864 100644
--- a/framework/delibs/dethread/CMakeLists.txt
+++ b/framework/delibs/dethread/CMakeLists.txt
@@ -42,7 +42,7 @@
 	set(DETHREAD_LIBS ${DETHREAD_LIBS} pthread)
 endif ()
 
-if (DE_OS_IS_ANDROID OR DE_OS_IS_OSX OR DE_OS_IS_IOS OR DE_OS_IS_QNX)
+if (DE_OS_IS_ANDROID OR DE_OS_IS_OSX OR DE_OS_IS_IOS OR DE_OS_IS_QNX OR DE_OS_IS_FUCHSIA)
 	add_definitions(-D_XOPEN_SOURCE=600)
 endif ()
 
diff --git a/framework/delibs/dethread/unix/deMutexUnix.c b/framework/delibs/dethread/unix/deMutexUnix.c
index 42ba42a..43d2823 100644
--- a/framework/delibs/dethread/unix/deMutexUnix.c
+++ b/framework/delibs/dethread/unix/deMutexUnix.c
@@ -23,7 +23,7 @@
 
 #include "deMutex.h"
 
-#if (DE_OS == DE_OS_UNIX || DE_OS == DE_OS_ANDROID || DE_OS == DE_OS_SYMBIAN || DE_OS == DE_OS_QNX || DE_OS == DE_OS_OSX || DE_OS == DE_OS_IOS)
+#if (DE_OS == DE_OS_UNIX || DE_OS == DE_OS_ANDROID || DE_OS == DE_OS_SYMBIAN || DE_OS == DE_OS_QNX || DE_OS == DE_OS_OSX || DE_OS == DE_OS_IOS) || (DE_OS == DE_OS_FUCHSIA)
 
 #include "deMemory.h"
 
diff --git a/framework/delibs/dethread/unix/deSemaphoreUnix.c b/framework/delibs/dethread/unix/deSemaphoreUnix.c
index fae2b70..ca67ddc 100644
--- a/framework/delibs/dethread/unix/deSemaphoreUnix.c
+++ b/framework/delibs/dethread/unix/deSemaphoreUnix.c
@@ -23,7 +23,7 @@
 
 #include "deSemaphore.h"
 
-#if (DE_OS == DE_OS_UNIX || DE_OS == DE_OS_ANDROID || DE_OS == DE_OS_SYMBIAN || DE_OS == DE_OS_QNX)
+#if (DE_OS == DE_OS_UNIX || DE_OS == DE_OS_ANDROID || DE_OS == DE_OS_SYMBIAN || DE_OS == DE_OS_QNX) || (DE_OS == DE_OS_FUCHSIA)
 
 #include "deMemory.h"
 
diff --git a/framework/delibs/dethread/unix/deThreadLocalUnix.c b/framework/delibs/dethread/unix/deThreadLocalUnix.c
index c65be59..225cb5e 100644
--- a/framework/delibs/dethread/unix/deThreadLocalUnix.c
+++ b/framework/delibs/dethread/unix/deThreadLocalUnix.c
@@ -23,7 +23,7 @@
 
 #include "deThreadLocal.h"
 
-#if (DE_OS == DE_OS_UNIX || DE_OS == DE_OS_OSX || DE_OS == DE_OS_ANDROID || DE_OS == DE_OS_SYMBIAN || DE_OS == DE_OS_IOS || DE_OS == DE_OS_QNX)
+#if (DE_OS == DE_OS_UNIX || DE_OS == DE_OS_OSX || DE_OS == DE_OS_ANDROID || DE_OS == DE_OS_SYMBIAN || DE_OS == DE_OS_IOS || DE_OS == DE_OS_QNX || DE_OS == DE_OS_FUCHSIA)
 
 #if !defined(_XOPEN_SOURCE) || (_XOPEN_SOURCE < 500)
 #	error You are using too old posix API!
diff --git a/framework/delibs/dethread/unix/deThreadUnix.c b/framework/delibs/dethread/unix/deThreadUnix.c
index 2837291..8cca795 100644
--- a/framework/delibs/dethread/unix/deThreadUnix.c
+++ b/framework/delibs/dethread/unix/deThreadUnix.c
@@ -23,7 +23,7 @@
 
 #include "deThread.h"
 
-#if (DE_OS == DE_OS_UNIX || DE_OS == DE_OS_OSX || DE_OS == DE_OS_ANDROID || DE_OS == DE_OS_SYMBIAN || DE_OS == DE_OS_IOS || DE_OS == DE_OS_QNX)
+#if (DE_OS == DE_OS_UNIX || DE_OS == DE_OS_OSX || DE_OS == DE_OS_ANDROID || DE_OS == DE_OS_SYMBIAN || DE_OS == DE_OS_IOS || DE_OS == DE_OS_QNX || DE_OS == DE_OS_FUCHSIA)
 
 #include "deMemory.h"
 #include "deInt32.h"
diff --git a/framework/delibs/deutil/CMakeLists.txt b/framework/delibs/deutil/CMakeLists.txt
index fdfcb39..7902dc5 100644
--- a/framework/delibs/deutil/CMakeLists.txt
+++ b/framework/delibs/deutil/CMakeLists.txt
@@ -8,7 +8,6 @@
 	deDynamicLibrary.h
 	deFile.c
 	deFile.h
-	deProcess.c
 	deProcess.h
 	deSocket.c
 	deSocket.h
@@ -20,6 +19,16 @@
 
 set(DEUTIL_LIBS debase dethread depool)
 
+if (DE_OS_IS_FUCHSIA)
+	set(DEUTIL_SRCS ${DEUTIL_SRCS} deFuchsiaProcess.cc)
+	include_directories("${FUCHSIA_ROOT}/zircon/system/ulib/fdio/include")
+	set(DEUTIL_LIBS ${DEUTIL_LIBS} ${FUCHSIA_LIB_DIR}/libfdio.so zircon)
+	# These must be pulled into the application package while the libvulkan implementation depends on them
+	set(DEUTIL_LIBS ${DEUTIL_LIBS} ${FUCHSIA_LIB_DIR}/libasync-default.so ${FUCHSIA_LIB_DIR}/libtrace-engine.so)
+else ()
+	set(DEUTIL_SRCS ${DEUTIL_SRCS} deProcess.c)
+endif ()
+
 include_directories(
 	../debase
 	../dethread
diff --git a/framework/delibs/deutil/deClock.c b/framework/delibs/deutil/deClock.c
index a7f6aa8..22d9db6 100644
--- a/framework/delibs/deutil/deClock.c
+++ b/framework/delibs/deutil/deClock.c
@@ -55,7 +55,7 @@
 		return count.QuadPart / (freq.QuadPart / 1000000);
 	}
 
-#elif (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_QNX)
+#elif (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_QNX) || (DE_OS == DE_OS_FUCHSIA)
 	struct timespec currTime;
 	clock_gettime(CLOCK_MONOTONIC, &currTime);
 	return (deUint64)currTime.tv_sec*1000000 + ((deUint64)currTime.tv_nsec/1000);
diff --git a/framework/delibs/deutil/deCommandLine.c b/framework/delibs/deutil/deCommandLine.c
index d0ebb1c..0c0bf96 100644
--- a/framework/delibs/deutil/deCommandLine.c
+++ b/framework/delibs/deutil/deCommandLine.c
@@ -118,7 +118,7 @@
 	{
 		deCommandLine* cmdLine = (deCommandLine*)deCalloc(sizeof(deCommandLine));
 
-		if (!cmdLine || !(cmdLine->args = (char**)deCalloc(sizeof(char*)*(size_t)CharPtrArray_getNumElements(args))))
+		if (!cmdLine || !(cmdLine->args = (char**)deCalloc(sizeof(char*)*(1 + (size_t)CharPtrArray_getNumElements(args)))))
 		{
 			deFree(cmdLine);
 			deFree(buf);
@@ -131,6 +131,7 @@
 
 		for (argNdx = 0; argNdx < cmdLine->numArgs; argNdx++)
 			cmdLine->args[argNdx] = CharPtrArray_get(args, argNdx);
+		cmdLine->args[cmdLine->numArgs] = 0;
 
 		deMemPool_destroy(tmpPool);
 		return cmdLine;
diff --git a/framework/delibs/deutil/deDynamicLibrary.c b/framework/delibs/deutil/deDynamicLibrary.c
index 8d350ae..e16839b 100644
--- a/framework/delibs/deutil/deDynamicLibrary.c
+++ b/framework/delibs/deutil/deDynamicLibrary.c
@@ -24,7 +24,7 @@
 #include "deDynamicLibrary.h"
 #include "deMemory.h"
 
-#if (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_OSX) || (DE_OS == DE_OS_SYMBIAN) || (DE_OS == DE_OS_IOS) || (DE_OS == DE_OS_QNX)
+#if (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_OSX) || (DE_OS == DE_OS_SYMBIAN) || (DE_OS == DE_OS_IOS) || (DE_OS == DE_OS_QNX) || (DE_OS == DE_OS_FUCHSIA)
 /* Posix implementation. */
 
 #include <dlfcn.h>
diff --git a/framework/delibs/deutil/deFile.c b/framework/delibs/deutil/deFile.c
index 8cba3ec..10c889d 100644
--- a/framework/delibs/deutil/deFile.c
+++ b/framework/delibs/deutil/deFile.c
@@ -24,7 +24,7 @@
 #include "deFile.h"
 #include "deMemory.h"
 
-#if (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_OSX) || (DE_OS == DE_OS_IOS) || (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_SYMBIAN) || (DE_OS == DE_OS_QNX)
+#if (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_OSX) || (DE_OS == DE_OS_IOS) || (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_SYMBIAN) || (DE_OS == DE_OS_QNX) || (DE_OS == DE_OS_FUCHSIA)
 
 #include <sys/types.h>
 #include <sys/stat.h>
diff --git a/framework/delibs/deutil/deFuchsiaProcess.cc b/framework/delibs/deutil/deFuchsiaProcess.cc
new file mode 100644
index 0000000..318435f
--- /dev/null
+++ b/framework/delibs/deutil/deFuchsiaProcess.cc
@@ -0,0 +1,282 @@
+// Copyright 2016 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <assert.h>
+#include <lib/fdio/io.h>
+#include <lib/fdio/spawn.h>
+#include <lib/fdio/util.h>
+#include <memory.h>
+#include <memory>
+#include <string>
+#include <unistd.h>
+#include <vector>
+#include <zircon/process.h>
+#include <zircon/processargs.h>
+#include <zircon/syscalls.h>
+#include <zircon/syscalls/object.h>
+
+#include "deProcess.h"
+
+#if (DE_OS != DE_OS_FUCHSIA)
+#error DE_OS_FUCHSIA expected
+#endif
+
+#include "deCommandLine.h"
+
+struct deProcess_s {
+};
+
+class ModifiedEnviron {
+public:
+    explicit ModifiedEnviron(char** env)
+    {
+        for (size_t i = 0; env[i]; i++) {
+            envs_.push_back(env[i]);
+        }
+    }
+
+    void ReplacePwd(const char* working_directory)
+    {
+        assert(working_directory);
+        char pwd_string[strlen(working_directory) + 4 + 1];
+
+        sprintf(pwd_string, "PWD=%s", working_directory);
+        for (size_t i = 0; i < envs_.size(); i++) {
+            if (strstr(envs_[i].c_str(), "PWD=") == 0) {
+                envs_[i] = pwd_string;
+                return;
+            }
+        }
+        envs_.push_back(pwd_string);
+    }
+
+    // Return value must not outlive ModifiedEnviron. Invalidated if ReplacePwd
+    // is called.
+    std::vector<const char*> GetEnviron()
+    {
+        std::vector<const char*> env;
+        for (size_t i = 0; i < envs_.size(); i++) {
+            env.push_back(envs_[i].c_str());
+        }
+        env.push_back(nullptr);
+        return env;
+    }
+
+private:
+    std::vector<std::string> envs_;
+};
+
+class DeProcess : public deProcess_s {
+public:
+    static std::unique_ptr<DeProcess> Create()
+    {
+        return std::unique_ptr<DeProcess>(new DeProcess());
+    }
+
+    DeProcess() : proc_(ZX_HANDLE_INVALID), fstdin_(nullptr), fstdout_(nullptr), fstderr_(nullptr)
+    {
+    }
+
+    ~DeProcess()
+    {
+        if (proc_ != ZX_HANDLE_INVALID)
+            zx_handle_close(proc_);
+        closeStdIn();
+        closeStdOut();
+        closeStdErr();
+    }
+
+    bool start(const char* commandLine, const char* workingDirectory)
+    {
+        deCommandLine* cmdLine = deCommandLine_parse(commandLine);
+        assert(cmdLine->args[cmdLine->numArgs] == 0);
+        fdio_spawn_action_t spawn_actions[3];
+        int result;
+        int stdin_pipes[2];
+        result = pipe(stdin_pipes);
+        assert(result == 0);
+        int stdout_pipes[2];
+        result = pipe(stdout_pipes);
+        assert(result == 0);
+        int stderr_pipes[2];
+        result = pipe(stderr_pipes);
+        assert(result == 0);
+
+        spawn_actions[0].action = FDIO_SPAWN_ACTION_TRANSFER_FD;
+        spawn_actions[0].fd.local_fd = stdin_pipes[0];
+        spawn_actions[0].fd.target_fd = STDIN_FILENO;
+        fstdin_ = deFile_createFromHandle(stdin_pipes[1]);
+
+        spawn_actions[1].action = FDIO_SPAWN_ACTION_TRANSFER_FD;
+        spawn_actions[1].fd.local_fd = stdout_pipes[1];
+        spawn_actions[1].fd.target_fd = STDOUT_FILENO;
+        fstdout_ = deFile_createFromHandle(stdout_pipes[0]);
+
+#ifndef RAW_STDERR
+        spawn_actions[2].action = FDIO_SPAWN_ACTION_TRANSFER_FD;
+        spawn_actions[2].fd.local_fd = stderr_pipes[1];
+        spawn_actions[2].fd.target_fd = STDERR_FILENO;
+        fstderr_ = deFile_createFromHandle(stderr_pipes[0]);
+#else
+        // Printing to our stderr sometimes works better.
+        spawn_actions[2].action = FDIO_SPAWN_ACTION_CLONE_FD;
+        spawn_actions[2].fd.local_fd = STDERR_FILENO;
+        spawn_actions[2].fd.target_fd = STDERR_FILENO;
+        fstderr_ = deFile_createFromHandle(stderr_pipes[0]);
+#endif
+
+        ModifiedEnviron env(environ);
+        if (workingDirectory)
+            env.ReplacePwd(workingDirectory);
+
+        char err_msg_out[FDIO_SPAWN_ERR_MSG_MAX_LENGTH];
+
+        uint32_t spawn_flags = FDIO_SPAWN_CLONE_NAMESPACE | FDIO_SPAWN_CLONE_ENVIRON |
+                               FDIO_SPAWN_DEFAULT_LDSVC | FDIO_SPAWN_CLONE_JOB;
+        zx_status_t status = fdio_spawn_etc(
+            ZX_HANDLE_INVALID, spawn_flags, cmdLine->args[0], (const char* const*)&cmdLine->args[0],
+            env.GetEnviron().data(), 3, spawn_actions, &proc_, err_msg_out);
+
+        if (status != ZX_OK) {
+            fprintf(stderr, "fdio_spawn error: %d %s\n", status, err_msg_out);
+            return false;
+        }
+
+        return true;
+    }
+
+    bool IsRunning()
+    {
+        zx_signals_t pending = 0;
+        zx_status_t status = zx_object_wait_one(proc_, ZX_TASK_TERMINATED, 0, &pending);
+        if (pending & ZX_TASK_TERMINATED)
+            return false;
+        assert(status == ZX_ERR_TIMED_OUT);
+        return true;
+    }
+
+    bool Wait()
+    {
+        zx_status_t status = zx_object_wait_one(proc_, ZX_TASK_TERMINATED, ZX_TIME_INFINITE, NULL);
+        return status == ZX_OK;
+    }
+
+    int GetExitCode()
+    {
+        zx_info_process_t info;
+        zx_status_t status =
+            zx_object_get_info(proc_, ZX_INFO_PROCESS, &info, sizeof(info), NULL, NULL);
+        assert(status == ZX_OK);
+        return info.return_code;
+    }
+
+    static DeProcess* cast(deProcess* process) { return static_cast<DeProcess*>(process); }
+
+    deFile* fstdin() { return fstdin_; }
+    deFile* fstdout() { return fstdout_; }
+    deFile* fstderr() { return fstderr_; }
+
+    void closeStdIn()
+    {
+        if (fstdin_) {
+            deFile_destroy(fstdin_);
+            fstdin_ = nullptr;
+        }
+    }
+
+    void closeStdOut()
+    {
+        if (fstdout_) {
+            deFile_destroy(fstdout_);
+            fstdout_ = nullptr;
+        }
+    }
+
+    void closeStdErr()
+    {
+        if (fstderr_) {
+            deFile_destroy(fstderr_);
+            fstderr_ = nullptr;
+        }
+    }
+
+private:
+    zx_handle_t proc_;
+    deFile* fstdin_;
+    deFile* fstdout_;
+    deFile* fstderr_;
+};
+
+deProcess* deProcess_create()
+{
+    std::unique_ptr<DeProcess> process = DeProcess::Create();
+    if (!process)
+        return nullptr;
+
+    return process.release();
+}
+
+void deProcess_destroy(deProcess* process) { delete DeProcess::cast(process); }
+
+deBool deProcess_start(deProcess* de_process, const char* commandLine, const char* workingDirectory)
+{
+    (void)workingDirectory;
+
+    DeProcess* process = DeProcess::cast(de_process);
+
+    if (!process->start(commandLine, workingDirectory))
+        return false;
+
+    return true;
+}
+
+deBool deProcess_isRunning(deProcess* process) { return DeProcess::cast(process)->IsRunning(); }
+
+deBool deProcess_waitForFinish(deProcess* process)
+{
+    return DeProcess::cast(process)->Wait() ? DE_TRUE : DE_FALSE;
+}
+
+const char* deProcess_getLastError(const deProcess*) { return nullptr; }
+
+int deProcess_getExitCode(const deProcess* process)
+{
+    return DeProcess::cast((deProcess*)process)->GetExitCode();
+}
+
+deBool deProcess_terminate(deProcess*)
+{
+    printf("%s:%d Not implemented\n", __FILE__, __LINE__);
+    return DE_FALSE;
+}
+
+deBool deProcess_kill(deProcess*)
+{
+    printf("%s:%d Not implemented\n", __FILE__, __LINE__);
+    return DE_FALSE;
+}
+
+deFile* deProcess_getStdIn(deProcess* process) { return DeProcess::cast(process)->fstdin(); }
+
+deFile* deProcess_getStdOut(deProcess* process) { return DeProcess::cast(process)->fstdout(); }
+
+deFile* deProcess_getStdErr(deProcess* process) { return DeProcess::cast(process)->fstderr(); }
+
+deBool deProcess_closeStdIn(deProcess* process)
+{
+    DeProcess::cast(process)->closeStdIn();
+    return DE_TRUE;
+}
+
+deBool deProcess_closeStdOut(deProcess* process)
+{
+    DeProcess::cast(process)->closeStdOut();
+    return DE_TRUE;
+}
+
+deBool deProcess_closeStdErr(deProcess* process)
+{
+    DeProcess::cast(process)->closeStdErr();
+    return DE_TRUE;
+}
diff --git a/framework/delibs/deutil/deProcess.c b/framework/delibs/deutil/deProcess.c
index 2261478..fd9b0ca 100644
--- a/framework/delibs/deutil/deProcess.c
+++ b/framework/delibs/deutil/deProcess.c
@@ -422,6 +422,14 @@
 	return DE_TRUE;
 }
 
+#if (DE_OS == DE_OS_FUCHSIA)
+static deBool deProcess_sendSignal (deProcess* process, int sigNum)
+{
+	deProcess_setError(process, "Fuchsia doesn't support signals");
+	(void)sigNum;
+	return DE_FALSE;
+}
+#else
 static deBool deProcess_sendSignal (deProcess* process, int sigNum)
 {
 	if (process->state != PROCESSSTATE_RUNNING)
@@ -438,6 +446,7 @@
 		return DE_FALSE;
 	}
 }
+#endif
 
 deBool deProcess_terminate (deProcess* process)
 {
diff --git a/framework/delibs/deutil/deSocket.c b/framework/delibs/deutil/deSocket.c
index 97fc17e..75dca94 100644
--- a/framework/delibs/deutil/deSocket.c
+++ b/framework/delibs/deutil/deSocket.c
@@ -28,7 +28,7 @@
 
 #if (DE_OS == DE_OS_WIN32)
 #	define DE_USE_WINSOCK
-#elif (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_OSX) || (DE_OS == DE_OS_IOS) || (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_SYMBIAN) || (DE_OS == DE_OS_QNX)
+#elif (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_OSX) || (DE_OS == DE_OS_IOS) || (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_SYMBIAN) || (DE_OS == DE_OS_QNX) || (DE_OS == DE_OS_FUCHSIA)
 #	define DE_USE_BERKELEY_SOCKETS
 #else
 #	error Implement deSocket for your OS.
diff --git a/framework/delibs/deutil/deTimer.c b/framework/delibs/deutil/deTimer.c
index 02d51f8..64e09fb 100644
--- a/framework/delibs/deutil/deTimer.c
+++ b/framework/delibs/deutil/deTimer.c
@@ -336,14 +336,14 @@
 		if (sleepTime > 0)
 			deSleep(sleepTime);
 
+		if (thread->state == TIMERSTATE_DISABLED)
+			break;
+
 		lastCallback = (deInt64)deGetMicroseconds();
 		thread->callback(thread->callbackArg);
 		numCallbacks += 1;
 	}
 
-	/* State lock is held when loop is exited. */
-	deMutex_unlock(thread->lock);
-
 	if (destroy)
 	{
 		/* Destroy thread except thread->thread. */
diff --git a/framework/platform/CMakeLists.txt b/framework/platform/CMakeLists.txt
index f7858f5..83296a8 100644
--- a/framework/platform/CMakeLists.txt
+++ b/framework/platform/CMakeLists.txt
@@ -136,6 +136,11 @@
 			osx/tcuOSXMetalView.hpp
 			)
 
+	elseif (DE_OS_IS_FUCHSIA)
+		set(TCUTIL_PLATFORM_SRCS
+			fuchsia/tcuFuchsiaPlatform.cpp
+			)
+
 	else ()
 		set(TCUTIL_PLATFORM_SRCS
 			vanilla/tcuVanillaPlatform.cpp
diff --git a/framework/platform/fuchsia/tcuFuchsiaPlatform.cpp b/framework/platform/fuchsia/tcuFuchsiaPlatform.cpp
new file mode 100644
index 0000000..1af5615
--- /dev/null
+++ b/framework/platform/fuchsia/tcuFuchsiaPlatform.cpp
@@ -0,0 +1,54 @@
+// Copyright 2016 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tcuFunctionLibrary.hpp"
+#include "tcuPlatform.hpp"
+#include "vkPlatform.hpp"
+
+class FuchsiaVkLibrary : public vk::Library {
+public:
+    FuchsiaVkLibrary()
+        : library_("libvulkan.so"), driver_(library_) {}
+
+    const vk::PlatformInterface& getPlatformInterface() const {
+        return driver_;
+    }
+    const tcu::FunctionLibrary&             getFunctionLibrary              (void) const
+    {
+            return library_;
+    }
+
+private:
+    const tcu::DynamicFunctionLibrary library_;
+    const vk::PlatformDriver driver_;
+};
+
+class FuchsiaVkPlatform : public vk::Platform {
+public:
+    vk::Library* createLibrary() const { return new FuchsiaVkLibrary(); }
+
+    void getMemoryLimits(vk::PlatformMemoryLimits& limits) const {
+        // Copied from tcuX11VulkanPlatform.cpp
+        limits.totalSystemMemory = 256 * 1024 * 1024;
+        limits.totalDeviceLocalMemory = 0; // unified memory
+        limits.deviceMemoryAllocationGranularity = 64 * 1024;
+        limits.devicePageSize = 4096;
+        limits.devicePageTableEntrySize = 8;
+        limits.devicePageTableHierarchyLevels = 3;
+    }
+};
+
+class FuchsiaPlatform : public tcu::Platform {
+public:
+    ~FuchsiaPlatform() {}
+
+    const vk::Platform& getVulkanPlatform() const { return vk_platform_; }
+
+private:
+    FuchsiaVkPlatform vk_platform_;
+};
+
+tcu::Platform* createPlatform() {
+    return new FuchsiaPlatform();
+}
diff --git a/framework/platform/tcuMain.cpp b/framework/platform/tcuMain.cpp
index 5b0ccb0..5bf558d 100644
--- a/framework/platform/tcuMain.cpp
+++ b/framework/platform/tcuMain.cpp
@@ -44,7 +44,11 @@
 	try
 	{
 		tcu::CommandLine				cmdLine		(argc, argv);
+#if DE_OS == DE_OS_FUCHSIA
+		tcu::DirArchive					archive		("/pkg/data");
+#else
 		tcu::DirArchive					archive		(".");
+#endif
 		tcu::TestLog					log			(cmdLine.getLogFileName(), cmdLine.getLogFlags());
 		de::UniquePtr<tcu::Platform>	platform	(createPlatform());
 		de::UniquePtr<tcu::App>			app			(new tcu::App(*platform, archive, log, cmdLine));
diff --git a/fuchsia/BUILD.gn b/fuchsia/BUILD.gn
new file mode 100644
index 0000000..a026870
--- /dev/null
+++ b/fuchsia/BUILD.gn
@@ -0,0 +1,151 @@
+# Copyright 2018 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/package.gni")
+import("//garnet/lib/magma/gnbuild/magma.gni")
+import("resources.gni")
+
+action("build") {
+  script = "build.sh"
+  args = [
+    rebase_path(root_out_dir),
+    current_cpu,
+    host_cpu,
+    host_os,
+  ]
+  deps = [
+    "//garnet/public/sdk:zircon_sysroot_export",
+    "//third_party/vulkan_loader_and_validation_layers:vulkan",
+    "//zircon/public/lib/fdio:fdio_sdk",
+  ]
+
+  depfile = "$root_out_dir/build-vulkancts/vulkan-cts.d"
+  outputs = [
+    "$root_out_dir/build-vulkancts/external/vulkancts/modules/vulkan/deqp-vk",
+    "$root_out_dir/build-vulkancts/executor/executor",
+    "$root_out_dir/build-vulkancts/execserver/execserver",
+    "$root_out_dir/build-vulkancts/cases/dEQP-VK-cases.xml",
+  ]
+}
+
+copy("copy") {
+  sources = [
+    "$root_out_dir/build-vulkancts/external/vulkancts/modules/vulkan/deqp-vk",
+  ]
+  outputs = [
+    "$root_build_dir/vulkan-cts",
+  ]
+  deps = [
+    ":build",
+  ]
+}
+
+# Add a label of "vulkan-cts" for each environment given in the list
+# of general hardware environments for magma tests. The label ensures
+# that the Vulkan CTS will not be run in the general test pipeline;
+# the label will be keyed on so that the suite may be run in a special
+# builder.
+labeled_magma_hardware_envs = []
+foreach(env, magma_hardware_envs) {
+  labeled_env = {
+    forward_variables_from(env, "*")
+    label = "vulkan-cts"
+  }
+  labeled_magma_hardware_envs += [ labeled_env ]
+}
+
+# To run on device: run vulkan-cts
+# The following command line args are provided by the cmx:
+# --deqp-caselist-file=/pkg/data/vk-default.txt --deqp-log-images=disable --deqp-log-shader-sources=disable --deqp-log-filename=/data/TestResults.qpa
+package("vulkan-cts") {
+  deps = [
+    ":copy",
+  ]
+  tests = [
+    {
+      name = "vulkan-cts"
+      environments = labeled_magma_hardware_envs
+    },
+  ]
+
+  meta = [
+    {
+      path = rebase_path("meta/vulkan-cts.cmx")
+      dest = "vulkan-cts.cmx"
+    },
+    {
+      path = rebase_path("meta/vulkan-cts-no-args.cmx")
+      dest = "vulkan-cts-no-args.cmx"
+    },
+  ]
+  resources = cts_resources
+}
+
+# To run on device:
+# run vulkan-cts-executor --start-server=/pkg/bin/execserver --testset=dEQP-VK.* --caselistdir=/pkg/data/cases --out=/data/TestLog.qpa --info=/data/infolog.txt --binaryname=/pkg/bin/deqp-vk --workdir=/data
+# Note: the list of cases may include tests that aren't in vk-default.txt "mustpass".
+package("vulkan-cts-executor") {
+  deps = [
+    ":build",
+  ]
+
+  binary = "build-vulkancts/executor/executor"
+  binaries = [
+    {
+      name = "deqp-vk"
+      source = "$root_out_dir/build-vulkancts/external/vulkancts/modules/vulkan/deqp-vk"
+    },
+    {
+      name = "execserver"
+      source = "$root_out_dir/build-vulkancts/execserver/execserver"
+    },
+  ]
+  meta = [
+    {
+      path = rebase_path("meta/vulkan-cts-executor.cmx")
+      dest = "vulkan-cts-executor.cmx"
+    },
+  ]
+  resources = cts_resources
+
+  resources += [
+    {
+      path = rebase_path("$root_out_dir/build-vulkancts/cases/dEQP-VK-cases.xml")
+      dest = "cases/dEQP-VK-cases.xml"
+    },
+  ]
+}
+
+# On device:
+# run vulkan-cts-execserver
+# Run on host:
+# executor/executor --connect=192.168.42.80 --testset=dEQP-VK.* --caselistdir=cases/ --binaryname=/pkg/bin/deqp-vk --workdir=/data --cmdline="--deqp-log-images=disable --deqp-log-shader-sources=disable"
+# Note: the list of cases may include tests that aren't in vk-default.txt "mustpass".
+package("vulkan-cts-execserver") {
+  deps = [
+    ":build",
+  ]
+
+  binary = "build-vulkancts/execserver/execserver"
+  binaries = [
+    {
+      name = "deqp-vk"
+      source = "$root_out_dir/build-vulkancts/external/vulkancts/modules/vulkan/deqp-vk"
+    },
+  ]
+  meta = [
+    {
+      path = rebase_path("meta/vulkan-cts-execserver.cmx")
+      dest = "vulkan-cts-execserver.cmx"
+    },
+  ]
+  resources = cts_resources
+
+  resources += [
+    {
+      path = rebase_path("$root_out_dir/build-vulkancts/cases/dEQP-VK-cases.xml")
+      dest = "cases/dEQP-VK-cases.xml"
+    },
+  ]
+}
diff --git a/fuchsia/build.sh b/fuchsia/build.sh
new file mode 100755
index 0000000..fa0f33d
--- /dev/null
+++ b/fuchsia/build.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+
+# Copyright 2016 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+set -e
+root_out_dir=${1}
+target_cpu=${2}
+host_cpu=${3}
+host_os=${4}
+fuchsia_root=$root_out_dir/../..
+tools_path=$fuchsia_root/buildtools
+cmake=$tools_path/$host_os-$host_cpu/cmake/bin/cmake
+build_dir=$root_out_dir/build-vulkancts
+caselist_build_dir=$root_out_dir/build-vulkancts/cases-build
+caselist_out_dir=$root_out_dir/build-vulkancts/cases
+if [[ $target_cpu == "arm64" ]]; then
+	extra_args="-DFUCHSIA_SYSTEM_PROCESSOR=aarch64 -DDE_CPU=DE_CPU_ARM_64 -DDE_PTR_SIZE=8"
+else
+	extra_args="-DFUCHSIA_SYSTEM_PROCESSOR=x86_64"
+fi
+
+fuchsia_lib_path=$root_out_dir/$target_cpu-shared
+sysroot=$root_out_dir/sdk/exported/zircon_sysroot/arch/$target_cpu/sysroot
+
+if [ ! -d "$sysroot" ]; then
+	echo "Can't find sysroot: $sysroot"
+	exit 1
+fi
+
+# Export buildtools' cmake to the scripts below.
+export PATH="$PATH:$(dirname $cmake)"
+
+pushd $fuchsia_root/third_party/vulkan-cts
+python external/fetch_sources.py
+popd
+
+# builds the test executable for the host in order to write out test cases
+pushd $fuchsia_root/third_party/vulkan-cts
+mkdir -p $caselist_out_dir
+mkdir -p $caselist_build_dir
+python scripts/build_caselists.py -b $caselist_build_dir -m dEQP-VK $caselist_out_dir
+popd
+
+mkdir -p $build_dir
+$fuchsia_root/third_party/vulkan-cts/fuchsia/gendepsfile.py $build_dir/vulkan-cts.d $fuchsia_root/third_party/vulkan-cts
+pushd $build_dir
+$cmake $fuchsia_root/third_party/vulkan-cts -GNinja  -DCMAKE_BUILD_TYPE=Debug -DCMAKE_MAKE_PROGRAM=$tools_path/ninja -DFUCHSIA_SYSROOT=$sysroot -DCMAKE_TOOLCHAIN_FILE=$fuchsia_root/build/Fuchsia.cmake -DDE_OS=DE_OS_FUCHSIA -DDEQP_TARGET=fuchsia -DFUCHSIA_ROOT=$fuchsia_root -DFUCHSIA_LIB_DIR=$fuchsia_lib_path $extra_args
+$tools_path/ninja deqp-vk executor execserver
+popd
diff --git a/fuchsia/gen.py b/fuchsia/gen.py
new file mode 100644
index 0000000..edc78d6
--- /dev/null
+++ b/fuchsia/gen.py
@@ -0,0 +1,32 @@
+# Copyright 2018 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import subprocess
+
+out_file = open("resources.gni", "w")
+
+out_file.write("""\
+### NOTE: This file auto-generated from gen.py
+
+  cts_resources = [
+  {
+    path=rebase_path("../external/vulkancts/mustpass/1.0.2/vk-default.txt")
+    dest="vk-default.txt"
+  },
+""")
+
+files = subprocess.check_output(["find", "../external/vulkancts/data/vulkan", "-type", "f"])
+file_lines = files.splitlines()
+
+for file in file_lines:
+	file_split = file.split('/')
+	file_split = file_split[4:]
+	out_file.write('  {\n')
+	out_file.write('    path=rebase_path("%s")\n' % file)
+	out_file.write('    dest="%s"\n' % '/'.join(file_split))
+	out_file.write('  },\n')
+
+out_file.write('  ]\n')
+out_file.close()
diff --git a/fuchsia/gendepsfile.py b/fuchsia/gendepsfile.py
new file mode 100755
index 0000000..3b069cf
--- /dev/null
+++ b/fuchsia/gendepsfile.py
@@ -0,0 +1,32 @@
+#!/usr/bin/env python
+# Copyright 2018 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import os
+import subprocess
+import sys
+import pipes
+
+
+def main():
+  parser = argparse.ArgumentParser("Generate vulkan cts dep file")
+  parser.add_argument("depsfile")
+  parser.add_argument("input_dir")
+  args = parser.parse_args()
+
+  files = subprocess.check_output([
+      "find", args.input_dir, "-path", "*/.git", "-prune", "-o", "-type", "f",
+      "-print"
+  ])
+  file_lines = files.splitlines()
+
+  with open(args.depsfile, "w") as depsfile:
+    depsfile.write("build-vulkancts/external/vulkancts/modules/vulkan/deqp-vk: ")
+    depsfile.write(" ".join(x.replace(' ', '\\ ') for x in file_lines))
+  return 0
+
+
+if __name__ == "__main__":
+  sys.exit(main())
diff --git a/fuchsia/meta/vulkan-cts-execserver.cmx b/fuchsia/meta/vulkan-cts-execserver.cmx
new file mode 100644
index 0000000..f3117c7
--- /dev/null
+++ b/fuchsia/meta/vulkan-cts-execserver.cmx
@@ -0,0 +1,13 @@
+{
+    "program": {
+        "binary": "bin/app"
+    },
+    "sandbox": {
+        "dev": [ "class/framebuffer" ],
+        "features": [ "vulkan", "persistent-storage" ],
+        "services": [
+            "fuchsia.net.LegacySocketProvider",
+            "fuchsia.vulkan.loader.Loader"
+        ]
+    }
+}
diff --git a/fuchsia/meta/vulkan-cts-executor.cmx b/fuchsia/meta/vulkan-cts-executor.cmx
new file mode 100644
index 0000000..bad93b5
--- /dev/null
+++ b/fuchsia/meta/vulkan-cts-executor.cmx
@@ -0,0 +1,14 @@
+{
+    "program": {
+        "binary": "bin/app"
+    },
+    "sandbox": {
+        "dev": [ "class/framebuffer" ],
+        "features": [ "vulkan", "persistent-storage" ],
+        "services": [
+            "fuchsia.process.Launcher",
+            "fuchsia.net.LegacySocketProvider",
+            "fuchsia.vulkan.loader.Loader"
+        ]
+    }
+}
diff --git a/fuchsia/meta/vulkan-cts-no-args.cmx b/fuchsia/meta/vulkan-cts-no-args.cmx
new file mode 100644
index 0000000..0e83ca5
--- /dev/null
+++ b/fuchsia/meta/vulkan-cts-no-args.cmx
@@ -0,0 +1,12 @@
+{
+    "program": {
+        "binary": "test/vulkan-cts"
+    },
+    "sandbox": {
+        "dev": [ "class/framebuffer" ],
+        "features": [ "vulkan", "persistent-storage", "system-temp" ],
+        "services": [
+            "fuchsia.vulkan.loader.Loader"
+        ]
+    }
+}
diff --git a/fuchsia/meta/vulkan-cts.cmx b/fuchsia/meta/vulkan-cts.cmx
new file mode 100644
index 0000000..d0d88a5
--- /dev/null
+++ b/fuchsia/meta/vulkan-cts.cmx
@@ -0,0 +1,20 @@
+{
+    "program": {
+        "binary": "test/vulkan-cts",
+        "args": [ "--deqp-caselist-file=/pkg/data/vk-default.txt", "--deqp-log-images=disable", "--deqp-log-shader-sources=disable", "--deqp-log-filename=/data/TestResults.qpa" ]
+    },
+    "sandbox": {
+        "dev": [ "class/framebuffer" ],
+        "features": [ "vulkan", "persistent-storage" ],
+        "services": [
+            "fuchsia.vulkan.loader.Loader"
+        ]
+    },
+    "facets": {
+        "fuchsia.test": {
+            "injected-services": {
+                "fuchsia.vulkan.loader.Loader": "fuchsia-pkg://fuchsia.com/vulkan_loader#meta/vulkan_loader.cmx"
+            }
+        }
+    } 
+}
diff --git a/fuchsia/resources.gni b/fuchsia/resources.gni
new file mode 100644
index 0000000..a5f615f
--- /dev/null
+++ b/fuchsia/resources.gni
@@ -0,0 +1,612 @@
+### NOTE: This file auto-generated from gen.py
+
+  cts_resources = [
+  {
+    path=rebase_path("../external/vulkancts/mustpass/1.0.2/vk-default.txt")
+    dest="vk-default.txt"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/dynamic_state/VertexFetch.vert")
+    dest="vulkan/dynamic_state/VertexFetch.vert"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/dynamic_state/VertexFetch.frag")
+    dest="vulkan/dynamic_state/VertexFetch.frag"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/dynamic_state/ViewportArray.geom")
+    dest="vulkan/dynamic_state/ViewportArray.geom"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/draw/VertexFetch.vert")
+    dest="vulkan/draw/VertexFetch.vert"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/draw/VertexFetchInstanceIndex.vert")
+    dest="vulkan/draw/VertexFetchInstanceIndex.vert"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/draw/VertexFetch.frag")
+    dest="vulkan/draw/VertexFetch.frag"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/draw/VertexFetchShaderDrawParametersDrawIndex.vert")
+    dest="vulkan/draw/VertexFetchShaderDrawParametersDrawIndex.vert"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/draw/VertexFetchInstanced.vert")
+    dest="vulkan/draw/VertexFetchInstanced.vert"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/draw/VertexFetchShaderDrawParameters.vert")
+    dest="vulkan/draw/VertexFetchShaderDrawParameters.vert"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/draw/VertexFetchInstancedFirstInstance.vert")
+    dest="vulkan/draw/VertexFetchInstancedFirstInstance.vert"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/device_group/spherefilled.png")
+    dest="vulkan/data/device_group/spherefilled.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/device_group/sphere.png")
+    dest="vulkan/data/device_group/sphere.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/primitive_id_in.png")
+    dest="vulkan/data/geometry/primitive_id_in.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/line_strip_emit_1_end_1.png")
+    dest="vulkan/data/geometry/line_strip_emit_1_end_1.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/vertex_count_10.png")
+    dest="vulkan/data/geometry/vertex_count_10.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/triangles_adjacency.png")
+    dest="vulkan/data/geometry/triangles_adjacency.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_0_end_2.png")
+    dest="vulkan/data/geometry/triangle_strip_emit_0_end_2.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/output_vary_by_attribute_instancing.png")
+    dest="vulkan/data/geometry/output_vary_by_attribute_instancing.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/output_vary_by_uniform_instancing.png")
+    dest="vulkan/data/geometry/output_vary_by_uniform_instancing.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/line_strip_emit_0_end_2.png")
+    dest="vulkan/data/geometry/line_strip_emit_0_end_2.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/vertex_out_0_geometry_out_1.png")
+    dest="vulkan/data/geometry/vertex_out_0_geometry_out_1.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/output_10_and_100.png")
+    dest="vulkan/data/geometry/output_10_and_100.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/vertex_out_0_geometry_out_2.png")
+    dest="vulkan/data/geometry/vertex_out_0_geometry_out_2.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/vertex_out_1_geometry_out_0.png")
+    dest="vulkan/data/geometry/vertex_out_1_geometry_out_0.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/points_emit_0_end_2.png")
+    dest="vulkan/data/geometry/points_emit_0_end_2.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/points_emit_1_end_2.png")
+    dest="vulkan/data/geometry/points_emit_1_end_2.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/points_to_lines.png")
+    dest="vulkan/data/geometry/points_to_lines.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/vertex_count_0.png")
+    dest="vulkan/data/geometry/vertex_count_0.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/output_100_and_10.png")
+    dest="vulkan/data/geometry/output_100_and_10.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/triangles_to_lines.png")
+    dest="vulkan/data/geometry/triangles_to_lines.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/line_strip_emit_0_end_0.png")
+    dest="vulkan/data/geometry/line_strip_emit_0_end_0.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/lines_to_triangles.png")
+    dest="vulkan/data/geometry/lines_to_triangles.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/output_128_and_0.png")
+    dest="vulkan/data/geometry/output_128_and_0.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/vertex_count_8.png")
+    dest="vulkan/data/geometry/vertex_count_8.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_2_end_2.png")
+    dest="vulkan/data/geometry/triangle_strip_emit_2_end_2.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/points_emit_1_end_1.png")
+    dest="vulkan/data/geometry/points_emit_1_end_1.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/vertex_count_9.png")
+    dest="vulkan/data/geometry/vertex_count_9.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/line_strip_emit_2_end_2.png")
+    dest="vulkan/data/geometry/line_strip_emit_2_end_2.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/triangles_to_points.png")
+    dest="vulkan/data/geometry/triangles_to_points.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/output_vary_by_uniform.png")
+    dest="vulkan/data/geometry/output_vary_by_uniform.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/line_strip_adjacency.png")
+    dest="vulkan/data/geometry/line_strip_adjacency.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/output_max.png")
+    dest="vulkan/data/geometry/output_max.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_0_end_0.png")
+    dest="vulkan/data/geometry/triangle_strip_emit_0_end_0.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/lines.png")
+    dest="vulkan/data/geometry/lines.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/output_vary_by_texture_instancing.png")
+    dest="vulkan/data/geometry/output_vary_by_texture_instancing.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/output_vary_by_attribute.png")
+    dest="vulkan/data/geometry/output_vary_by_attribute.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_3_end_2_emit_3_end_0.png")
+    dest="vulkan/data/geometry/triangle_strip_emit_3_end_2_emit_3_end_0.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/points_emit_0_end_1.png")
+    dest="vulkan/data/geometry/points_emit_0_end_1.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_3_end_2.png")
+    dest="vulkan/data/geometry/triangle_strip_emit_3_end_2.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/vertex_no_op_geometry_out_1.png")
+    dest="vulkan/data/geometry/vertex_no_op_geometry_out_1.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/line_strip_emit_2_end_2_emit_2_end_0.png")
+    dest="vulkan/data/geometry/line_strip_emit_2_end_2_emit_2_end_0.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/output_128.png")
+    dest="vulkan/data/geometry/output_128.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/output_10.png")
+    dest="vulkan/data/geometry/output_10.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/vertex_count_5.png")
+    dest="vulkan/data/geometry/vertex_count_5.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/primitive_id_in_restarted.png")
+    dest="vulkan/data/geometry/primitive_id_in_restarted.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/vertex_count_6.png")
+    dest="vulkan/data/geometry/vertex_count_6.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/line_strip_emit_0_end_1.png")
+    dest="vulkan/data/geometry/line_strip_emit_0_end_1.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/vertex_count_3.png")
+    dest="vulkan/data/geometry/vertex_count_3.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/points.png")
+    dest="vulkan/data/geometry/points.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_1_end_2.png")
+    dest="vulkan/data/geometry/triangle_strip_emit_1_end_2.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/vertex_out_1_geometry_out_2.png")
+    dest="vulkan/data/geometry/vertex_out_1_geometry_out_2.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_0_end_1.png")
+    dest="vulkan/data/geometry/triangle_strip_emit_0_end_1.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/vertex_count_11.png")
+    dest="vulkan/data/geometry/vertex_count_11.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/triangle_fan.png")
+    dest="vulkan/data/geometry/triangle_fan.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/vertex_count_2.png")
+    dest="vulkan/data/geometry/vertex_count_2.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/lines_adjacency.png")
+    dest="vulkan/data/geometry/lines_adjacency.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/point_size.png")
+    dest="vulkan/data/geometry/point_size.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_2_end_1.png")
+    dest="vulkan/data/geometry/triangle_strip_emit_2_end_1.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/vertex_count_12.png")
+    dest="vulkan/data/geometry/vertex_count_12.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/line_strip.png")
+    dest="vulkan/data/geometry/line_strip.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/primitive_id.png")
+    dest="vulkan/data/geometry/primitive_id.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/triangle_strip.png")
+    dest="vulkan/data/geometry/triangle_strip.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/output_vary_by_texture.png")
+    dest="vulkan/data/geometry/output_vary_by_texture.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/points_to_triangles.png")
+    dest="vulkan/data/geometry/points_to_triangles.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/line_strip_emit_1_end_2.png")
+    dest="vulkan/data/geometry/line_strip_emit_1_end_2.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/triangles.png")
+    dest="vulkan/data/geometry/triangles.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/output_0_and_128.png")
+    dest="vulkan/data/geometry/output_0_and_128.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_3_end_1.png")
+    dest="vulkan/data/geometry/triangle_strip_emit_3_end_1.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/vertex_count_7.png")
+    dest="vulkan/data/geometry/vertex_count_7.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/lines_to_points.png")
+    dest="vulkan/data/geometry/lines_to_points.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/vertex_count_4.png")
+    dest="vulkan/data/geometry/vertex_count_4.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/line_strip_emit_2_end_1.png")
+    dest="vulkan/data/geometry/line_strip_emit_2_end_1.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/points_emit_0_end_0.png")
+    dest="vulkan/data/geometry/points_emit_0_end_0.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_1_end_1.png")
+    dest="vulkan/data/geometry/triangle_strip_emit_1_end_1.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/geometry/vertex_count_1.png")
+    dest="vulkan/data/geometry/vertex_count_1.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/brick.png")
+    dest="vulkan/data/brick.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_overlap_triangles_fractional_odd_spacing_ref_2.png")
+    dest="vulkan/data/tessellation/fill_overlap_triangles_fractional_odd_spacing_ref_2.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_overlap_triangles_fractional_even_spacing_ref_0.png")
+    dest="vulkan/data/tessellation/fill_overlap_triangles_fractional_even_spacing_ref_0.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_overlap_quads_equal_spacing_ref_2.png")
+    dest="vulkan/data/tessellation/fill_overlap_quads_equal_spacing_ref_2.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/gl_position_ref.png")
+    dest="vulkan/data/tessellation/gl_position_ref.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/isolines_equal_spacing_ref_2.png")
+    dest="vulkan/data/tessellation/isolines_equal_spacing_ref_2.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_overlap_triangles_fractional_odd_spacing_ref_1.png")
+    dest="vulkan/data/tessellation/fill_overlap_triangles_fractional_odd_spacing_ref_1.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/user_defined_io_isolines_ref.png")
+    dest="vulkan/data/tessellation/user_defined_io_isolines_ref.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/isolines_fractional_odd_spacing_ref_2.png")
+    dest="vulkan/data/tessellation/isolines_fractional_odd_spacing_ref_2.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_cover_triangles_fractional_even_spacing_ref_0.png")
+    dest="vulkan/data/tessellation/fill_cover_triangles_fractional_even_spacing_ref_0.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/isolines_fractional_even_spacing_ref_0.png")
+    dest="vulkan/data/tessellation/isolines_fractional_even_spacing_ref_0.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_overlap_quads_fractional_odd_spacing_ref_0.png")
+    dest="vulkan/data/tessellation/fill_overlap_quads_fractional_odd_spacing_ref_0.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/primitive_id_tcs_ref.png")
+    dest="vulkan/data/tessellation/primitive_id_tcs_ref.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_overlap_quads_fractional_odd_spacing_ref_2.png")
+    dest="vulkan/data/tessellation/fill_overlap_quads_fractional_odd_spacing_ref_2.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_overlap_quads_fractional_odd_spacing_ref_1.png")
+    dest="vulkan/data/tessellation/fill_overlap_quads_fractional_odd_spacing_ref_1.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_cover_quads_fractional_even_spacing_ref_2.png")
+    dest="vulkan/data/tessellation/fill_cover_quads_fractional_even_spacing_ref_2.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_cover_quads_equal_spacing_ref_1.png")
+    dest="vulkan/data/tessellation/fill_cover_quads_equal_spacing_ref_1.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_cover_triangles_fractional_odd_spacing_ref_1.png")
+    dest="vulkan/data/tessellation/fill_cover_triangles_fractional_odd_spacing_ref_1.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_overlap_triangles_fractional_even_spacing_ref_2.png")
+    dest="vulkan/data/tessellation/fill_overlap_triangles_fractional_even_spacing_ref_2.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_overlap_quads_equal_spacing_ref_0.png")
+    dest="vulkan/data/tessellation/fill_overlap_quads_equal_spacing_ref_0.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_cover_quads_fractional_odd_spacing_ref_2.png")
+    dest="vulkan/data/tessellation/fill_cover_quads_fractional_odd_spacing_ref_2.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/isolines_fractional_odd_spacing_ref_0.png")
+    dest="vulkan/data/tessellation/isolines_fractional_odd_spacing_ref_0.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_cover_quads_fractional_odd_spacing_ref_0.png")
+    dest="vulkan/data/tessellation/fill_cover_quads_fractional_odd_spacing_ref_0.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_overlap_quads_fractional_even_spacing_ref_2.png")
+    dest="vulkan/data/tessellation/fill_overlap_quads_fractional_even_spacing_ref_2.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/isolines_equal_spacing_ref_1.png")
+    dest="vulkan/data/tessellation/isolines_equal_spacing_ref_1.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/patch_vertices_5_in_10_out_ref.png")
+    dest="vulkan/data/tessellation/patch_vertices_5_in_10_out_ref.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_overlap_quads_fractional_even_spacing_ref_0.png")
+    dest="vulkan/data/tessellation/fill_overlap_quads_fractional_even_spacing_ref_0.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/barrier_ref.png")
+    dest="vulkan/data/tessellation/barrier_ref.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_cover_triangles_equal_spacing_ref_0.png")
+    dest="vulkan/data/tessellation/fill_cover_triangles_equal_spacing_ref_0.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_overlap_quads_equal_spacing_ref_1.png")
+    dest="vulkan/data/tessellation/fill_overlap_quads_equal_spacing_ref_1.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/user_defined_io_quads_ref.png")
+    dest="vulkan/data/tessellation/user_defined_io_quads_ref.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/patch_vertices_10_in_5_out_ref.png")
+    dest="vulkan/data/tessellation/patch_vertices_10_in_5_out_ref.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_overlap_triangles_fractional_odd_spacing_ref_0.png")
+    dest="vulkan/data/tessellation/fill_overlap_triangles_fractional_odd_spacing_ref_0.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_cover_triangles_fractional_even_spacing_ref_2.png")
+    dest="vulkan/data/tessellation/fill_cover_triangles_fractional_even_spacing_ref_2.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_overlap_triangles_equal_spacing_ref_2.png")
+    dest="vulkan/data/tessellation/fill_overlap_triangles_equal_spacing_ref_2.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_cover_quads_fractional_even_spacing_ref_1.png")
+    dest="vulkan/data/tessellation/fill_cover_quads_fractional_even_spacing_ref_1.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/primitive_id_tes_ref.png")
+    dest="vulkan/data/tessellation/primitive_id_tes_ref.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_overlap_quads_fractional_even_spacing_ref_1.png")
+    dest="vulkan/data/tessellation/fill_overlap_quads_fractional_even_spacing_ref_1.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/isolines_fractional_even_spacing_ref_1.png")
+    dest="vulkan/data/tessellation/isolines_fractional_even_spacing_ref_1.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_cover_triangles_equal_spacing_ref_2.png")
+    dest="vulkan/data/tessellation/fill_cover_triangles_equal_spacing_ref_2.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_cover_triangles_fractional_odd_spacing_ref_0.png")
+    dest="vulkan/data/tessellation/fill_cover_triangles_fractional_odd_spacing_ref_0.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_cover_triangles_fractional_odd_spacing_ref_2.png")
+    dest="vulkan/data/tessellation/fill_cover_triangles_fractional_odd_spacing_ref_2.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_cover_triangles_equal_spacing_ref_1.png")
+    dest="vulkan/data/tessellation/fill_cover_triangles_equal_spacing_ref_1.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_cover_quads_equal_spacing_ref_0.png")
+    dest="vulkan/data/tessellation/fill_cover_quads_equal_spacing_ref_0.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_overlap_triangles_fractional_even_spacing_ref_1.png")
+    dest="vulkan/data/tessellation/fill_overlap_triangles_fractional_even_spacing_ref_1.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/isolines_equal_spacing_ref_0.png")
+    dest="vulkan/data/tessellation/isolines_equal_spacing_ref_0.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_cover_quads_equal_spacing_ref_2.png")
+    dest="vulkan/data/tessellation/fill_cover_quads_equal_spacing_ref_2.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/isolines_fractional_even_spacing_ref_2.png")
+    dest="vulkan/data/tessellation/isolines_fractional_even_spacing_ref_2.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_cover_triangles_fractional_even_spacing_ref_1.png")
+    dest="vulkan/data/tessellation/fill_cover_triangles_fractional_even_spacing_ref_1.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/user_defined_io_triangles_ref.png")
+    dest="vulkan/data/tessellation/user_defined_io_triangles_ref.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_cover_quads_fractional_odd_spacing_ref_1.png")
+    dest="vulkan/data/tessellation/fill_cover_quads_fractional_odd_spacing_ref_1.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_overlap_triangles_equal_spacing_ref_1.png")
+    dest="vulkan/data/tessellation/fill_overlap_triangles_equal_spacing_ref_1.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_overlap_triangles_equal_spacing_ref_0.png")
+    dest="vulkan/data/tessellation/fill_overlap_triangles_equal_spacing_ref_0.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/isolines_fractional_odd_spacing_ref_1.png")
+    dest="vulkan/data/tessellation/isolines_fractional_odd_spacing_ref_1.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/data/tessellation/fill_cover_quads_fractional_even_spacing_ref_0.png")
+    dest="vulkan/data/tessellation/fill_cover_quads_fractional_even_spacing_ref_0.png"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/.gitignore")
+    dest="vulkan/.gitignore"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/glsl/440/linkage.test")
+    dest="vulkan/glsl/440/linkage.test"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/glsl/es310/constant_expressions.test")
+    dest="vulkan/glsl/es310/constant_expressions.test"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/glsl/es310/swizzles.test")
+    dest="vulkan/glsl/es310/swizzles.test"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/glsl/es310/conversions.test")
+    dest="vulkan/glsl/es310/conversions.test"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/glsl/es310/scoping.test")
+    dest="vulkan/glsl/es310/scoping.test"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/glsl/es310/functions.test")
+    dest="vulkan/glsl/es310/functions.test"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/glsl/es310/constants.test")
+    dest="vulkan/glsl/es310/constants.test"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/glsl/es310/linkage.test")
+    dest="vulkan/glsl/es310/linkage.test"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/glsl/es310/arrays.test")
+    dest="vulkan/glsl/es310/arrays.test"
+  },
+  {
+    path=rebase_path("../external/vulkancts/data/vulkan/glsl/es310/conditionals.test")
+    dest="vulkan/glsl/es310/conditionals.test"
+  },
+  ]
diff --git a/fuchsia/vulkan-cts b/fuchsia/vulkan-cts
new file mode 100644
index 0000000..4373359
--- /dev/null
+++ b/fuchsia/vulkan-cts
@@ -0,0 +1,10 @@
+{
+    "imports": [
+        "garnet/packages/prod/vulkan"
+    ],
+    "packages": [
+        "//third_party/vulkan-cts/fuchsia:vulkan-cts",
+        "//third_party/vulkan-cts/fuchsia:vulkan-cts-execserver",
+        "//third_party/vulkan-cts/fuchsia:vulkan-cts-executor"
+    ]
+}
diff --git a/targets/fuchsia/fuchsia.cmake b/targets/fuchsia/fuchsia.cmake
new file mode 100644
index 0000000..8d2d46a
--- /dev/null
+++ b/targets/fuchsia/fuchsia.cmake
@@ -0,0 +1,10 @@
+message("*** Fuchsia")
+set(DEQP_TARGET_NAME	"Fuchsia")
+
+# Probably these default to off...
+set(DEQP_SUPPORT_GLES2	OFF)
+set(DEQP_SUPPORT_GLES3	OFF)
+set(DEQP_SUPPORT_OPENGL	OFF)
+set(DEQP_SUPPORT_EGL	OFF)
+
+set(DEQP_PLATFORM_LIBRARIES "")