Merge changes Ide16cac3,Id5d767fc

* changes:
  Update Marl to 246091e81
  Squashed 'third_party/marl/' changes from 14e4d862a..246091e81
diff --git a/BUILD.gn b/BUILD.gn
index eba6788..7d2a6f5 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -109,26 +109,28 @@
       ]
     } else if (target_cpu == "mipsel" && current_cpu == target_cpu) {
       cflags += [
-        "-march=mipsel",
+        "-EL",
         "-fPIC",
         "-mhard-float",
         "-mfp32",
+        "-mxgot",
       ]
       if (mips_arch_variant == "r1") {
         cflags += [
-          "-mcpu=mips32",
+          "-march=mips32",
         ]
       } else {
         cflags += [
-          "-mcpu=mips32r2",
+          "-march=mips32r2",
         ]
       }
     } else if (target_cpu == "mips64el" && current_cpu == target_cpu) {
       cflags += [
-        "-march=mips64el",
-        "-mcpu=mips64r2",
+        "-EL",
+        "-arch=mips64r2",
         "-mabi=64",
         "-fPIC",
+        "-mxgot",
       ]
     }
 
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6e6b867..02f903c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -475,15 +475,19 @@
         set_cpp_flag("-mtune=generic")
     endif()
     if(ARCH STREQUAL "mipsel")
+        set_cpp_flag("-EL")
         set_cpp_flag("-march=mips32r2")
         set_cpp_flag("-fPIC")
         set_cpp_flag("-mhard-float")
         set_cpp_flag("-mfp32")
+        set_cpp_flag("-mxgot")
     endif()
     if(ARCH STREQUAL "mips64el")
+        set_cpp_flag("-EL")
         set_cpp_flag("-march=mips64r2")
         set_cpp_flag("-mabi=64")
         set_cpp_flag("-fPIC")
+        set_cpp_flag("-mxgot")
     endif()
 
     if(SWIFTSHADER_LESS_DEBUG_INFO)
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index 4246880..0fe5b09 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -423,18 +423,20 @@
 
 			case spv::OpExtInstImport:
 			{
-				auto const extensionsByName = std::initializer_list<std::pair<const char *, Extension::Name>>{
+				static constexpr std::pair<const char *, Extension::Name> extensionsByName[] = {
 					{ "GLSL.std.450", Extension::GLSLstd450 },
 					{ "OpenCL.DebugInfo.100", Extension::OpenCLDebugInfo100 },
 				};
+				static constexpr auto extensionCount = sizeof(extensionsByName) / sizeof(extensionsByName[0]);
+
 				auto id = Extension::ID(insn.word(1));
 				auto name = insn.string(2);
 				auto ext = Extension{ Extension::Unknown };
-				for(auto it : extensionsByName)
+				for(size_t i = 0; i < extensionCount; i++)
 				{
-					if(0 == strcmp(name, it.first))
+					if(0 == strcmp(name, extensionsByName[i].first))
 					{
-						ext = Extension{ it.second };
+						ext = Extension{ extensionsByName[i].second };
 						break;
 					}
 				}
diff --git a/src/Reactor/Debug.cpp b/src/Reactor/Debug.cpp
index 5b10036..2df3e28 100644
--- a/src/Reactor/Debug.cpp
+++ b/src/Reactor/Debug.cpp
@@ -39,7 +39,7 @@
 #endif
 
 #ifndef REACTOR_LOGGING_LEVEL
-#	define REACTOR_LOGGING_LEVEL INFO
+#	define REACTOR_LOGGING_LEVEL Info
 #endif
 
 namespace {
@@ -98,11 +98,11 @@
 
 enum class Level
 {
-	DEBUG,
-	INFO,
-	WARN,
-	ERROR,
-	FATAL,
+	Debug,
+	Info,
+	Warn,
+	Error,
+	Fatal,
 };
 
 #ifdef __ANDROID__
@@ -110,19 +110,19 @@
 {
 	switch(level)
 	{
-		case Level::DEBUG:
+		case Level::Debug:
 			__android_log_write(ANDROID_LOG_DEBUG, "SwiftShader", msg);
 			break;
-		case Level::INFO:
+		case Level::Info:
 			__android_log_write(ANDROID_LOG_INFO, "SwiftShader", msg);
 			break;
-		case Level::WARN:
+		case Level::Warn:
 			__android_log_write(ANDROID_LOG_WARN, "SwiftShader", msg);
 			break;
-		case Level::ERROR:
+		case Level::Error:
 			__android_log_write(ANDROID_LOG_ERROR, "SwiftShader", msg);
 			break;
-		case Level::FATAL:
+		case Level::Fatal:
 			__android_log_write(ANDROID_LOG_FATAL, "SwiftShader", msg);
 			break;
 	}
@@ -132,13 +132,13 @@
 {
 	switch(level)
 	{
-		case Level::DEBUG:
-		case Level::INFO:
+		case Level::Debug:
+		case Level::Info:
 			fprintf(stdout, "%s", msg);
 			break;
-		case Level::WARN:
-		case Level::ERROR:
-		case Level::FATAL:
+		case Level::Warn:
+		case Level::Error:
+		case Level::Fatal:
 			fprintf(stderr, "%s", msg);
 			break;
 	}
@@ -187,7 +187,7 @@
 {
 	va_list vararg;
 	va_start(vararg, format);
-	logv(Level::DEBUG, format, vararg);
+	logv(Level::Debug, format, vararg);
 	va_end(vararg);
 }
 
@@ -195,7 +195,7 @@
 {
 	va_list vararg;
 	va_start(vararg, format);
-	logv(Level::WARN, format, vararg);
+	logv(Level::Warn, format, vararg);
 	va_end(vararg);
 }
 
@@ -204,7 +204,7 @@
 	va_list vararg;
 
 	va_start(vararg, format);
-	logv(Level::FATAL, format, vararg);
+	logv(Level::Fatal, format, vararg);
 	va_end(vararg);
 
 	::abort();
@@ -218,7 +218,7 @@
 		// Abort after tracing and printing to stderr
 		va_list vararg;
 		va_start(vararg, format);
-		logv(Level::FATAL, format, vararg);
+		logv(Level::Fatal, format, vararg);
 		va_end(vararg);
 
 		::abort();
@@ -227,7 +227,7 @@
 	{
 		va_list vararg;
 		va_start(vararg, format);
-		logv(Level::FATAL, format, vararg);
+		logv(Level::Fatal, format, vararg);
 		va_end(vararg);
 	}
 }
diff --git a/src/Reactor/SubzeroReactor.cpp b/src/Reactor/SubzeroReactor.cpp
index 4624064..7efeb5b 100644
--- a/src/Reactor/SubzeroReactor.cpp
+++ b/src/Reactor/SubzeroReactor.cpp
@@ -45,6 +45,7 @@
 #	include <Windows.h>
 #endif
 
+#include <array>
 #include <iostream>
 #include <limits>
 #include <mutex>
@@ -159,7 +160,7 @@
 		ret = function->makeVariable(retTy);
 	}
 
-	std::initializer_list<Ice::Variable *> iceArgs = { std::forward<RArgs>(args)... };
+	std::array<Ice::Variable *, sizeof...(args)> iceArgs {{ std::forward<RArgs>(args)... }};
 
 	auto call = Ice::InstCall::create(function, iceArgs.size(), ret, getConstantPointer(function->getContext(), reinterpret_cast<void const *>(fptr)), false);
 	for(auto arg : iceArgs)
diff --git a/src/System/Debug.cpp b/src/System/Debug.cpp
index f386156..8be91a1 100644
--- a/src/System/Debug.cpp
+++ b/src/System/Debug.cpp
@@ -39,7 +39,7 @@
 #endif
 
 #ifndef SWIFTSHADER_LOGGING_LEVEL
-#	define SWIFTSHADER_LOGGING_LEVEL INFO
+#	define SWIFTSHADER_LOGGING_LEVEL Info
 #endif
 
 namespace {
@@ -98,11 +98,11 @@
 
 enum class Level
 {
-	DEBUG,
-	INFO,
-	WARN,
-	ERROR,
-	FATAL,
+	Debug,
+	Info,
+	Warn,
+	Error,
+	Fatal,
 };
 
 #ifdef __ANDROID__
@@ -110,19 +110,19 @@
 {
 	switch(level)
 	{
-		case Level::DEBUG:
+		case Level::Debug:
 			__android_log_write(ANDROID_LOG_DEBUG, "SwiftShader", msg);
 			break;
-		case Level::INFO:
+		case Level::Info:
 			__android_log_write(ANDROID_LOG_INFO, "SwiftShader", msg);
 			break;
-		case Level::WARN:
+		case Level::Warn:
 			__android_log_write(ANDROID_LOG_WARN, "SwiftShader", msg);
 			break;
-		case Level::ERROR:
+		case Level::Error:
 			__android_log_write(ANDROID_LOG_ERROR, "SwiftShader", msg);
 			break;
-		case Level::FATAL:
+		case Level::Fatal:
 			__android_log_write(ANDROID_LOG_FATAL, "SwiftShader", msg);
 			break;
 	}
@@ -132,13 +132,13 @@
 {
 	switch(level)
 	{
-		case Level::DEBUG:
-		case Level::INFO:
+		case Level::Debug:
+		case Level::Info:
 			fprintf(stdout, "%s", msg);
 			break;
-		case Level::WARN:
-		case Level::ERROR:
-		case Level::FATAL:
+		case Level::Warn:
+		case Level::Error:
+		case Level::Fatal:
 			fprintf(stderr, "%s", msg);
 			break;
 	}
@@ -187,7 +187,7 @@
 {
 	va_list vararg;
 	va_start(vararg, format);
-	logv(Level::DEBUG, format, vararg);
+	logv(Level::Debug, format, vararg);
 	va_end(vararg);
 }
 
@@ -195,7 +195,7 @@
 {
 	va_list vararg;
 	va_start(vararg, format);
-	logv(Level::WARN, format, vararg);
+	logv(Level::Warn, format, vararg);
 	va_end(vararg);
 }
 
@@ -204,7 +204,7 @@
 	va_list vararg;
 
 	va_start(vararg, format);
-	logv(Level::FATAL, format, vararg);
+	logv(Level::Fatal, format, vararg);
 	va_end(vararg);
 
 	::abort();
@@ -218,7 +218,7 @@
 		// Abort after tracing and printing to stderr
 		va_list vararg;
 		va_start(vararg, format);
-		logv(Level::FATAL, format, vararg);
+		logv(Level::Fatal, format, vararg);
 		va_end(vararg);
 
 		::abort();
@@ -227,7 +227,7 @@
 	{
 		va_list vararg;
 		va_start(vararg, format);
-		logv(Level::FATAL, format, vararg);
+		logv(Level::Fatal, format, vararg);
 		va_end(vararg);
 	}
 }
diff --git a/src/Vulkan/VkGetProcAddress.cpp b/src/Vulkan/VkGetProcAddress.cpp
index 796596b..f293ca5 100644
--- a/src/Vulkan/VkGetProcAddress.cpp
+++ b/src/Vulkan/VkGetProcAddress.cpp
@@ -320,6 +320,15 @@
 	    {
 	        MAKE_VULKAN_DEVICE_ENTRY(vkGetDescriptorSetLayoutSupportKHR),
 	    } },
+	// VK_KHR_create_renderpass2
+	{
+	    VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME,
+	    {
+	        MAKE_VULKAN_DEVICE_ENTRY(vkCreateRenderPass2KHR),
+	        MAKE_VULKAN_DEVICE_ENTRY(vkCmdBeginRenderPass2KHR),
+	        MAKE_VULKAN_DEVICE_ENTRY(vkCmdNextSubpass2KHR),
+	        MAKE_VULKAN_DEVICE_ENTRY(vkCmdEndRenderPass2KHR),
+	    } },
 	// VK_EXT_line_rasterization
 	{
 	    VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME,
diff --git a/src/Vulkan/VkPhysicalDevice.cpp b/src/Vulkan/VkPhysicalDevice.cpp
index f3e62f5..70047a9 100644
--- a/src/Vulkan/VkPhysicalDevice.cpp
+++ b/src/Vulkan/VkPhysicalDevice.cpp
@@ -158,6 +158,11 @@
 	features->shaderDrawParameters = VK_FALSE;
 }
 
+void PhysicalDevice::getFeatures(VkPhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR* features) const
+{
+	features->separateDepthStencilLayouts = VK_TRUE;
+}
+
 void PhysicalDevice::getFeatures(VkPhysicalDeviceLineRasterizationFeaturesEXT *features) const
 {
 	features->rectangularLines = VK_TRUE;
diff --git a/src/Vulkan/VkPhysicalDevice.hpp b/src/Vulkan/VkPhysicalDevice.hpp
index 8e94466..2542e35 100644
--- a/src/Vulkan/VkPhysicalDevice.hpp
+++ b/src/Vulkan/VkPhysicalDevice.hpp
@@ -43,6 +43,7 @@
 	void getFeatures(VkPhysicalDeviceProtectedMemoryFeatures *features) const;
 	void getFeatures(VkPhysicalDeviceShaderDrawParameterFeatures *features) const;
 	void getFeatures(VkPhysicalDeviceLineRasterizationFeaturesEXT *features) const;
+	void getFeatures(VkPhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR* features) const;
 	void getFeatures(VkPhysicalDeviceProvokingVertexFeaturesEXT *features) const;
 	bool hasFeatures(const VkPhysicalDeviceFeatures &requestedFeatures) const;
 
diff --git a/src/Vulkan/VkRenderPass.cpp b/src/Vulkan/VkRenderPass.cpp
index 914c1d7..0830709 100644
--- a/src/Vulkan/VkRenderPass.cpp
+++ b/src/Vulkan/VkRenderPass.cpp
@@ -16,6 +16,112 @@
 #include "VkStringify.hpp"
 #include <cstring>
 
+namespace {
+
+template<class T>
+size_t ComputeRequiredAllocationSizeT(const T *pCreateInfo)
+{
+	size_t attachmentSize = pCreateInfo->attachmentCount * sizeof(VkAttachmentDescription) + pCreateInfo->attachmentCount * sizeof(int)  // first use
+	                        + pCreateInfo->attachmentCount * sizeof(uint32_t);                                                           // union of subpass view masks, per attachment
+	size_t subpassesSize = 0;
+	for(uint32_t i = 0; i < pCreateInfo->subpassCount; ++i)
+	{
+		const auto &subpass = pCreateInfo->pSubpasses[i];
+		uint32_t nbAttachments = subpass.inputAttachmentCount + subpass.colorAttachmentCount;
+		if(subpass.pResolveAttachments)
+		{
+			nbAttachments += subpass.colorAttachmentCount;
+		}
+		if(subpass.pDepthStencilAttachment)
+		{
+			nbAttachments += 1;
+		}
+		subpassesSize += sizeof(VkSubpassDescription) +
+		                 sizeof(VkAttachmentReference) * nbAttachments +
+		                 sizeof(uint32_t) * subpass.preserveAttachmentCount +
+		                 sizeof(uint32_t);  // view mask
+	}
+	size_t dependenciesSize = pCreateInfo->dependencyCount * sizeof(VkSubpassDependency);
+
+	return attachmentSize + subpassesSize + dependenciesSize;
+}
+
+template<class T>
+void CopySubpasses(VkSubpassDescription *dst, const T *src, uint32_t count)
+{
+	for(uint32_t i = 0; i < count; ++i)
+	{
+		dst[i].flags = src[i].flags;
+		dst[i].pipelineBindPoint = src[i].pipelineBindPoint;
+		dst[i].inputAttachmentCount = src[i].inputAttachmentCount;
+		dst[i].pInputAttachments = nullptr;
+		dst[i].colorAttachmentCount = src[i].colorAttachmentCount;
+		dst[i].pColorAttachments = nullptr;
+		dst[i].pResolveAttachments = nullptr;
+		dst[i].pDepthStencilAttachment = nullptr;
+		dst[i].preserveAttachmentCount = src[i].preserveAttachmentCount;
+		dst[i].pPreserveAttachments = nullptr;
+	}
+}
+
+template<class T>
+void CopyAttachmentDescriptions(VkAttachmentDescription *dst, const T *src, uint32_t count)
+{
+	for(uint32_t i = 0; i < count; ++i)
+	{
+		dst[i].flags = src[i].flags;
+		dst[i].format = src[i].format;
+		dst[i].samples = src[i].samples;
+		dst[i].loadOp = src[i].loadOp;
+		dst[i].storeOp = src[i].storeOp;
+		dst[i].stencilLoadOp = src[i].stencilLoadOp;
+		dst[i].stencilStoreOp = src[i].stencilStoreOp;
+		dst[i].initialLayout = src[i].initialLayout;
+		dst[i].finalLayout = src[i].finalLayout;
+	}
+}
+
+template<class T>
+void CopyAttachmentReferences(VkAttachmentReference *dst, const T *src, uint32_t count)
+{
+	for(uint32_t i = 0; i < count; ++i)
+	{
+		dst[i].attachment = src[i].attachment;
+		dst[i].layout = src[i].layout;
+	}
+}
+
+template<class T>
+void CopySubpassDependencies(VkSubpassDependency *dst, const T *src, uint32_t count)
+{
+	for(uint32_t i = 0; i < count; ++i)
+	{
+		dst[i].srcSubpass = src[i].srcSubpass;
+		dst[i].dstSubpass = src[i].dstSubpass;
+		dst[i].srcStageMask = src[i].srcStageMask;
+		dst[i].dstStageMask = src[i].dstStageMask;
+		dst[i].srcAccessMask = src[i].srcAccessMask;
+		dst[i].dstAccessMask = src[i].dstAccessMask;
+		dst[i].dependencyFlags = src[i].dependencyFlags;
+	}
+}
+
+bool GetViewMasks(const VkRenderPassCreateInfo *pCreateInfo, uint32_t *masks)
+{
+	return false;
+}
+
+bool GetViewMasks(const VkRenderPassCreateInfo2KHR *pCreateInfo, uint32_t *masks)
+{
+	for(uint32_t i = 0; i < pCreateInfo->subpassCount; ++i)
+	{
+		masks[i] = pCreateInfo->pSubpasses[i].viewMask;
+	}
+	return true;
+}
+
+}  // namespace
+
 namespace vk {
 
 RenderPass::RenderPass(const VkRenderPassCreateInfo *pCreateInfo, void *mem)
@@ -23,6 +129,25 @@
     , subpassCount(pCreateInfo->subpassCount)
     , dependencyCount(pCreateInfo->dependencyCount)
 {
+	init(pCreateInfo, mem);
+}
+
+RenderPass::RenderPass(const VkRenderPassCreateInfo2KHR *pCreateInfo, void *mem)
+    : attachmentCount(pCreateInfo->attachmentCount)
+    , subpassCount(pCreateInfo->subpassCount)
+    , dependencyCount(pCreateInfo->dependencyCount)
+{
+	init(pCreateInfo, mem);
+	// Note: the init function above ignores:
+	// - pCorrelatedViewMasks: This provides a potential performance optimization
+	// - VkAttachmentReference2::aspectMask : This specifies which aspects may be used
+	// - VkSubpassDependency2::viewOffset : This is the same as VkRenderPassMultiviewCreateInfo::pViewOffsets, which is currently ignored
+	// - Any pNext pointer in VkRenderPassCreateInfo2KHR's internal structures
+}
+
+template<class T>
+void RenderPass::init(const T *pCreateInfo, void *mem)
+{
 	char *hostMemory = reinterpret_cast<char *>(mem);
 
 	// subpassCount must be greater than 0
@@ -30,16 +155,16 @@
 
 	size_t subpassesSize = pCreateInfo->subpassCount * sizeof(VkSubpassDescription);
 	subpasses = reinterpret_cast<VkSubpassDescription *>(hostMemory);
-	memcpy(subpasses, pCreateInfo->pSubpasses, subpassesSize);
+	CopySubpasses(subpasses, pCreateInfo->pSubpasses, pCreateInfo->subpassCount);
 	hostMemory += subpassesSize;
 	uint32_t *masks = reinterpret_cast<uint32_t *>(hostMemory);
-	hostMemory += pCreateInfo->subpassCount * sizeof(uint32_t);
+	hostMemory += subpassCount * sizeof(uint32_t);
 
-	if(pCreateInfo->attachmentCount > 0)
+	if(attachmentCount > 0)
 	{
 		size_t attachmentSize = pCreateInfo->attachmentCount * sizeof(VkAttachmentDescription);
 		attachments = reinterpret_cast<VkAttachmentDescription *>(hostMemory);
-		memcpy(attachments, pCreateInfo->pAttachments, attachmentSize);
+		CopyAttachmentDescriptions(attachments, pCreateInfo->pAttachments, pCreateInfo->attachmentCount);
 		hostMemory += attachmentSize;
 
 		size_t firstUseSize = pCreateInfo->attachmentCount * sizeof(int);
@@ -70,7 +195,9 @@
 					masks[i] = multiviewCreateInfo->pViewMasks[i];
 					// This is now a multiview renderpass, so make the masks available
 					if(masks[i])
+					{
 						viewMasks = masks;
+					}
 				}
 
 				break;
@@ -83,22 +210,28 @@
 		extensionCreateInfo = extensionCreateInfo->pNext;
 	}
 
+	if(!viewMasks && (GetViewMasks(pCreateInfo, masks)))
+	{
+		for(auto i = 0u; i < pCreateInfo->subpassCount; i++)
+		{
+			if(masks[i])
+			{
+				viewMasks = masks;
+			}
+		}
+	}
+
 	// Deep copy subpasses
 	for(uint32_t i = 0; i < pCreateInfo->subpassCount; ++i)
 	{
 		const auto &subpass = pCreateInfo->pSubpasses[i];
-		subpasses[i].pInputAttachments = nullptr;
-		subpasses[i].pColorAttachments = nullptr;
-		subpasses[i].pResolveAttachments = nullptr;
-		subpasses[i].pDepthStencilAttachment = nullptr;
-		subpasses[i].pPreserveAttachments = nullptr;
 
 		if(subpass.inputAttachmentCount > 0)
 		{
 			size_t inputAttachmentsSize = subpass.inputAttachmentCount * sizeof(VkAttachmentReference);
 			subpasses[i].pInputAttachments = reinterpret_cast<VkAttachmentReference *>(hostMemory);
-			memcpy(const_cast<VkAttachmentReference *>(subpasses[i].pInputAttachments),
-			       pCreateInfo->pSubpasses[i].pInputAttachments, inputAttachmentsSize);
+			CopyAttachmentReferences(const_cast<VkAttachmentReference *>(subpasses[i].pInputAttachments),
+			                         pCreateInfo->pSubpasses[i].pInputAttachments, subpass.inputAttachmentCount);
 			hostMemory += inputAttachmentsSize;
 
 			for(auto j = 0u; j < subpasses[i].inputAttachmentCount; j++)
@@ -112,15 +245,15 @@
 		{
 			size_t colorAttachmentsSize = subpass.colorAttachmentCount * sizeof(VkAttachmentReference);
 			subpasses[i].pColorAttachments = reinterpret_cast<VkAttachmentReference *>(hostMemory);
-			memcpy(const_cast<VkAttachmentReference *>(subpasses[i].pColorAttachments),
-			       subpass.pColorAttachments, colorAttachmentsSize);
+			CopyAttachmentReferences(const_cast<VkAttachmentReference *>(subpasses[i].pColorAttachments),
+			                         subpass.pColorAttachments, subpass.colorAttachmentCount);
 			hostMemory += colorAttachmentsSize;
 
 			if(subpass.pResolveAttachments)
 			{
 				subpasses[i].pResolveAttachments = reinterpret_cast<VkAttachmentReference *>(hostMemory);
-				memcpy(const_cast<VkAttachmentReference *>(subpasses[i].pResolveAttachments),
-				       subpass.pResolveAttachments, colorAttachmentsSize);
+				CopyAttachmentReferences(const_cast<VkAttachmentReference *>(subpasses[i].pResolveAttachments),
+				                         subpass.pResolveAttachments, subpass.colorAttachmentCount);
 				hostMemory += colorAttachmentsSize;
 			}
 
@@ -137,8 +270,8 @@
 		if(subpass.pDepthStencilAttachment)
 		{
 			subpasses[i].pDepthStencilAttachment = reinterpret_cast<VkAttachmentReference *>(hostMemory);
-			memcpy(const_cast<VkAttachmentReference *>(subpasses[i].pDepthStencilAttachment),
-			       subpass.pDepthStencilAttachment, sizeof(VkAttachmentReference));
+			CopyAttachmentReferences(const_cast<VkAttachmentReference *>(subpasses[i].pDepthStencilAttachment),
+			                         subpass.pDepthStencilAttachment, 1);
 			hostMemory += sizeof(VkAttachmentReference);
 
 			if(subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED)
@@ -149,8 +282,10 @@
 		{
 			size_t preserveAttachmentSize = subpass.preserveAttachmentCount * sizeof(uint32_t);
 			subpasses[i].pPreserveAttachments = reinterpret_cast<uint32_t *>(hostMemory);
-			memcpy(const_cast<uint32_t *>(subpasses[i].pPreserveAttachments),
-			       pCreateInfo->pSubpasses[i].pPreserveAttachments, preserveAttachmentSize);
+			for(uint32_t j = 0u; j < subpass.preserveAttachmentCount; j++)
+			{
+				const_cast<uint32_t *>(subpasses[i].pPreserveAttachments)[j] = pCreateInfo->pSubpasses[i].pPreserveAttachments[j];
+			}
 			hostMemory += preserveAttachmentSize;
 
 			for(auto j = 0u; j < subpasses[i].preserveAttachmentCount; j++)
@@ -163,9 +298,8 @@
 
 	if(pCreateInfo->dependencyCount > 0)
 	{
-		size_t dependenciesSize = pCreateInfo->dependencyCount * sizeof(VkSubpassDependency);
 		dependencies = reinterpret_cast<VkSubpassDependency *>(hostMemory);
-		memcpy(dependencies, pCreateInfo->pDependencies, dependenciesSize);
+		CopySubpassDependencies(dependencies, pCreateInfo->pDependencies, pCreateInfo->dependencyCount);
 	}
 }
 
@@ -176,29 +310,12 @@
 
 size_t RenderPass::ComputeRequiredAllocationSize(const VkRenderPassCreateInfo *pCreateInfo)
 {
-	size_t attachmentSize = pCreateInfo->attachmentCount * sizeof(VkAttachmentDescription) + pCreateInfo->attachmentCount * sizeof(int)  // first use
-	                        + pCreateInfo->attachmentCount * sizeof(uint32_t);                                                           // union of subpass view masks, per attachment
-	size_t subpassesSize = 0;
-	for(uint32_t i = 0; i < pCreateInfo->subpassCount; ++i)
-	{
-		const auto &subpass = pCreateInfo->pSubpasses[i];
-		uint32_t nbAttachments = subpass.inputAttachmentCount + subpass.colorAttachmentCount;
-		if(subpass.pResolveAttachments)
-		{
-			nbAttachments += subpass.colorAttachmentCount;
-		}
-		if(subpass.pDepthStencilAttachment)
-		{
-			nbAttachments += 1;
-		}
-		subpassesSize += sizeof(VkSubpassDescription) +
-		                 sizeof(VkAttachmentReference) * nbAttachments +
-		                 sizeof(uint32_t) * subpass.preserveAttachmentCount +
-		                 sizeof(uint32_t);  // view mask
-	}
-	size_t dependenciesSize = pCreateInfo->dependencyCount * sizeof(VkSubpassDependency);
+	return ComputeRequiredAllocationSizeT(pCreateInfo);
+}
 
-	return attachmentSize + subpassesSize + dependenciesSize;
+size_t RenderPass::ComputeRequiredAllocationSize(const VkRenderPassCreateInfo2KHR *pCreateInfo)
+{
+	return ComputeRequiredAllocationSizeT(pCreateInfo);
 }
 
 void RenderPass::getRenderAreaGranularity(VkExtent2D *pGranularity) const
diff --git a/src/Vulkan/VkRenderPass.hpp b/src/Vulkan/VkRenderPass.hpp
index 2c2fe85..3f02f6b 100644
--- a/src/Vulkan/VkRenderPass.hpp
+++ b/src/Vulkan/VkRenderPass.hpp
@@ -25,9 +25,11 @@
 {
 public:
 	RenderPass(const VkRenderPassCreateInfo *pCreateInfo, void *mem);
+	RenderPass(const VkRenderPassCreateInfo2KHR *pCreateInfo, void *mem);
 	void destroy(const VkAllocationCallbacks *pAllocator);
 
 	static size_t ComputeRequiredAllocationSize(const VkRenderPassCreateInfo *pCreateInfo);
+	static size_t ComputeRequiredAllocationSize(const VkRenderPassCreateInfo2KHR *pCreateInfo);
 
 	void getRenderAreaGranularity(VkExtent2D *pGranularity) const;
 
@@ -93,6 +95,8 @@
 	uint32_t *attachmentViewMasks = nullptr;
 
 	void MarkFirstUse(int attachment, int subpass);
+	template<class T>
+	void init(const T *pCreateInfo, void *mem);
 };
 
 static inline RenderPass *Cast(VkRenderPass object)
diff --git a/src/Vulkan/libVulkan.cpp b/src/Vulkan/libVulkan.cpp
index 1d93641..61eb97c 100644
--- a/src/Vulkan/libVulkan.cpp
+++ b/src/Vulkan/libVulkan.cpp
@@ -165,6 +165,92 @@
 	(void)doOnce;
 }
 
+template<class T>
+void ValidateRenderPassPNextChain(VkDevice device, const T *pCreateInfo)
+{
+	const VkBaseInStructure *extensionCreateInfo = reinterpret_cast<const VkBaseInStructure *>(pCreateInfo->pNext);
+
+	while(extensionCreateInfo)
+	{
+		switch(extensionCreateInfo->sType)
+		{
+			case VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO:
+			{
+				const VkRenderPassInputAttachmentAspectCreateInfo *inputAttachmentAspectCreateInfo = reinterpret_cast<const VkRenderPassInputAttachmentAspectCreateInfo *>(extensionCreateInfo);
+
+				for(uint32_t i = 0; i < inputAttachmentAspectCreateInfo->aspectReferenceCount; i++)
+				{
+					const auto &aspectReference = inputAttachmentAspectCreateInfo->pAspectReferences[i];
+					ASSERT(aspectReference.subpass < pCreateInfo->subpassCount);
+					const auto &subpassDescription = pCreateInfo->pSubpasses[aspectReference.subpass];
+					ASSERT(aspectReference.inputAttachmentIndex < subpassDescription.inputAttachmentCount);
+					const auto &attachmentReference = subpassDescription.pInputAttachments[aspectReference.inputAttachmentIndex];
+					if(attachmentReference.attachment != VK_ATTACHMENT_UNUSED)
+					{
+						// If the pNext chain includes an instance of VkRenderPassInputAttachmentAspectCreateInfo, for any
+						// element of the pInputAttachments member of any element of pSubpasses where the attachment member
+						// is not VK_ATTACHMENT_UNUSED, the aspectMask member of the corresponding element of
+						// VkRenderPassInputAttachmentAspectCreateInfo::pAspectReferences must only include aspects that are
+						// present in images of the format specified by the element of pAttachments at attachment
+						vk::Format format(pCreateInfo->pAttachments[attachmentReference.attachment].format);
+						bool isDepth = format.isDepth();
+						bool isStencil = format.isStencil();
+						ASSERT(!(aspectReference.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) || (!isDepth && !isStencil));
+						ASSERT(!(aspectReference.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) || isDepth);
+						ASSERT(!(aspectReference.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) || isStencil);
+					}
+				}
+			}
+			break;
+			case VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO:
+			{
+				const VkRenderPassMultiviewCreateInfo *multiviewCreateInfo = reinterpret_cast<const VkRenderPassMultiviewCreateInfo *>(extensionCreateInfo);
+				ASSERT((multiviewCreateInfo->subpassCount == 0) || (multiviewCreateInfo->subpassCount == pCreateInfo->subpassCount));
+				ASSERT((multiviewCreateInfo->dependencyCount == 0) || (multiviewCreateInfo->dependencyCount == pCreateInfo->dependencyCount));
+
+				bool zeroMask = (multiviewCreateInfo->pViewMasks[0] == 0);
+				for(uint32_t i = 1; i < multiviewCreateInfo->subpassCount; i++)
+				{
+					ASSERT((multiviewCreateInfo->pViewMasks[i] == 0) == zeroMask);
+				}
+
+				if(zeroMask)
+				{
+					ASSERT(multiviewCreateInfo->correlationMaskCount == 0);
+				}
+
+				for(uint32_t i = 0; i < multiviewCreateInfo->dependencyCount; i++)
+				{
+					const auto &dependency = pCreateInfo->pDependencies[i];
+					if(multiviewCreateInfo->pViewOffsets[i] != 0)
+					{
+						ASSERT(dependency.srcSubpass != dependency.dstSubpass);
+						ASSERT(dependency.dependencyFlags & VK_DEPENDENCY_VIEW_LOCAL_BIT);
+					}
+					if(zeroMask)
+					{
+						ASSERT(!(dependency.dependencyFlags & VK_DEPENDENCY_VIEW_LOCAL_BIT));
+					}
+				}
+
+				// If the pNext chain includes an instance of VkRenderPassMultiviewCreateInfo,
+				// each element of its pViewMask member must not include a bit at a position
+				// greater than the value of VkPhysicalDeviceLimits::maxFramebufferLayers
+				// pViewMask is a 32 bit value. If maxFramebufferLayers > 32, it's impossible
+				// for pViewMask to contain a bit at an illegal position
+				// Note: Verify pViewMask values instead if we hit this assert
+				ASSERT(vk::Cast(device)->getPhysicalDevice()->getProperties().limits.maxFramebufferLayers >= 32);
+			}
+			break;
+			default:
+				WARN("pCreateInfo->pNext sType = %s", vk::Stringify(extensionCreateInfo->sType).c_str());
+				break;
+		}
+
+		extensionCreateInfo = extensionCreateInfo->pNext;
+	}
+}
+
 }  // namespace
 
 extern "C" {
@@ -212,6 +298,7 @@
 	// Vulkan 1.1 promoted extensions
 	{ VK_KHR_16BIT_STORAGE_EXTENSION_NAME, VK_KHR_16BIT_STORAGE_SPEC_VERSION },
 	{ VK_KHR_BIND_MEMORY_2_EXTENSION_NAME, VK_KHR_BIND_MEMORY_2_SPEC_VERSION },
+	{ VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME, VK_KHR_CREATE_RENDERPASS_2_SPEC_VERSION },
 	{ VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, VK_KHR_DEDICATED_ALLOCATION_SPEC_VERSION },
 	{ VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME, VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_SPEC_VERSION },
 	{ VK_KHR_DEVICE_GROUP_EXTENSION_NAME, VK_KHR_DEVICE_GROUP_SPEC_VERSION },
@@ -225,6 +312,7 @@
 	{ VK_KHR_MULTIVIEW_EXTENSION_NAME, VK_KHR_MULTIVIEW_SPEC_VERSION },
 	{ VK_KHR_RELAXED_BLOCK_LAYOUT_EXTENSION_NAME, VK_KHR_RELAXED_BLOCK_LAYOUT_SPEC_VERSION },
 	{ VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, VK_KHR_SAMPLER_YCBCR_CONVERSION_SPEC_VERSION },
+	{ VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_EXTENSION_NAME, VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_SPEC_VERSION },
 	// Only 1.1 core version of this is supported. The extension has additional requirements
 	//{ VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, VK_KHR_SHADER_DRAW_PARAMETERS_SPEC_VERSION },
 	{ VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME, VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION },
@@ -626,6 +714,14 @@
 				}
 			}
 			break;
+			case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES_KHR:
+			{
+				const VkPhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR* shaderDrawParametersFeatures = reinterpret_cast<const VkPhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR*>(extensionCreateInfo);
+
+				// Separate depth and stencil layouts is already supported
+				(void)(shaderDrawParametersFeatures->separateDepthStencilLayouts);
+			}
+			break;
 			case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT:
 			{
 				const VkPhysicalDeviceLineRasterizationFeaturesEXT *lineRasterizationFeatures = reinterpret_cast<const VkPhysicalDeviceLineRasterizationFeaturesEXT *>(extensionCreateInfo);
@@ -1884,88 +1980,24 @@
 		UNSUPPORTED("pCreateInfo->flags %d", int(pCreateInfo->flags));
 	}
 
-	const VkBaseInStructure *extensionCreateInfo = reinterpret_cast<const VkBaseInStructure *>(pCreateInfo->pNext);
+	ValidateRenderPassPNextChain(device, pCreateInfo);
 
-	while(extensionCreateInfo)
+	return vk::RenderPass::Create(pAllocator, pCreateInfo, pRenderPass);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass2KHR(VkDevice device, const VkRenderPassCreateInfo2KHR *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass)
+{
+	TRACE("(VkDevice device = %p, const VkRenderPassCreateInfo* pCreateInfo = %p, const VkAllocationCallbacks* pAllocator = %p, VkRenderPass* pRenderPass = %p)",
+	      device, pCreateInfo, pAllocator, pRenderPass);
+
+	if(pCreateInfo->flags != 0)
 	{
-		switch(extensionCreateInfo->sType)
-		{
-			case VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO:
-			{
-				const VkRenderPassInputAttachmentAspectCreateInfo *inputAttachmentAspectCreateInfo = reinterpret_cast<const VkRenderPassInputAttachmentAspectCreateInfo *>(extensionCreateInfo);
-
-				for(uint32_t i = 0; i < inputAttachmentAspectCreateInfo->aspectReferenceCount; i++)
-				{
-					const VkInputAttachmentAspectReference &aspectReference = inputAttachmentAspectCreateInfo->pAspectReferences[i];
-					ASSERT(aspectReference.subpass < pCreateInfo->subpassCount);
-					const VkSubpassDescription &subpassDescription = pCreateInfo->pSubpasses[aspectReference.subpass];
-					ASSERT(aspectReference.inputAttachmentIndex < subpassDescription.inputAttachmentCount);
-					const VkAttachmentReference &attachmentReference = subpassDescription.pInputAttachments[aspectReference.inputAttachmentIndex];
-					if(attachmentReference.attachment != VK_ATTACHMENT_UNUSED)
-					{
-						// If the pNext chain includes an instance of VkRenderPassInputAttachmentAspectCreateInfo, for any
-						// element of the pInputAttachments member of any element of pSubpasses where the attachment member
-						// is not VK_ATTACHMENT_UNUSED, the aspectMask member of the corresponding element of
-						// VkRenderPassInputAttachmentAspectCreateInfo::pAspectReferences must only include aspects that are
-						// present in images of the format specified by the element of pAttachments at attachment
-						vk::Format format(pCreateInfo->pAttachments[attachmentReference.attachment].format);
-						bool isDepth = format.isDepth();
-						bool isStencil = format.isStencil();
-						ASSERT(!(aspectReference.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) || (!isDepth && !isStencil));
-						ASSERT(!(aspectReference.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) || isDepth);
-						ASSERT(!(aspectReference.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) || isStencil);
-					}
-				}
-			}
-			break;
-			case VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO:
-			{
-				const VkRenderPassMultiviewCreateInfo *multiviewCreateInfo = reinterpret_cast<const VkRenderPassMultiviewCreateInfo *>(extensionCreateInfo);
-				ASSERT((multiviewCreateInfo->subpassCount == 0) || (multiviewCreateInfo->subpassCount == pCreateInfo->subpassCount));
-				ASSERT((multiviewCreateInfo->dependencyCount == 0) || (multiviewCreateInfo->dependencyCount == pCreateInfo->dependencyCount));
-
-				bool zeroMask = (multiviewCreateInfo->pViewMasks[0] == 0);
-				for(uint32_t i = 1; i < multiviewCreateInfo->subpassCount; i++)
-				{
-					ASSERT((multiviewCreateInfo->pViewMasks[i] == 0) == zeroMask);
-				}
-
-				if(zeroMask)
-				{
-					ASSERT(multiviewCreateInfo->correlationMaskCount == 0);
-				}
-
-				for(uint32_t i = 0; i < multiviewCreateInfo->dependencyCount; i++)
-				{
-					const VkSubpassDependency &dependency = pCreateInfo->pDependencies[i];
-					if(multiviewCreateInfo->pViewOffsets[i] != 0)
-					{
-						ASSERT(dependency.srcSubpass != dependency.dstSubpass);
-						ASSERT(dependency.dependencyFlags & VK_DEPENDENCY_VIEW_LOCAL_BIT);
-					}
-					if(zeroMask)
-					{
-						ASSERT(!(dependency.dependencyFlags & VK_DEPENDENCY_VIEW_LOCAL_BIT));
-					}
-				}
-
-				// If the pNext chain includes an instance of VkRenderPassMultiviewCreateInfo,
-				// each element of its pViewMask member must not include a bit at a position
-				// greater than the value of VkPhysicalDeviceLimits::maxFramebufferLayers
-				// pViewMask is a 32 bit value. If maxFramebufferLayers > 32, it's impossible
-				// for pViewMask to contain a bit at an illegal position
-				// Note: Verify pViewMask values instead if we hit this assert
-				ASSERT(vk::Cast(device)->getPhysicalDevice()->getProperties().limits.maxFramebufferLayers >= 32);
-			}
-			break;
-			default:
-				WARN("pCreateInfo->pNext sType = %s", vk::Stringify(extensionCreateInfo->sType).c_str());
-				break;
-		}
-
-		extensionCreateInfo = extensionCreateInfo->pNext;
+		// Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
+		UNSUPPORTED("pCreateInfo->flags %d", int(pCreateInfo->flags));
 	}
 
+	ValidateRenderPassPNextChain(device, pCreateInfo);
+
 	return vk::RenderPass::Create(pAllocator, pCreateInfo, pRenderPass);
 }
 
@@ -2415,6 +2447,14 @@
 	vk::Cast(commandBuffer)->beginRenderPass(vk::Cast(pRenderPassBegin->renderPass), vk::Cast(pRenderPassBegin->framebuffer), pRenderPassBegin->renderArea, pRenderPassBegin->clearValueCount, pRenderPassBegin->pClearValues, contents);
 }
 
+VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass2KHR(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin, const VkSubpassBeginInfoKHR *pSubpassBeginInfo)
+{
+	TRACE("(VkCommandBuffer commandBuffer = %p, const VkRenderPassBeginInfo* pRenderPassBegin = %p, const VkSubpassBeginInfoKHR* pSubpassBeginInfo = %p)",
+	      commandBuffer, pRenderPassBegin, pSubpassBeginInfo);
+
+	vk::Cast(commandBuffer)->beginRenderPass(vk::Cast(pRenderPassBegin->renderPass), vk::Cast(pRenderPassBegin->framebuffer), pRenderPassBegin->renderArea, pRenderPassBegin->clearValueCount, pRenderPassBegin->pClearValues, pSubpassBeginInfo->contents);
+}
+
 VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents)
 {
 	TRACE("(VkCommandBuffer commandBuffer = %p, VkSubpassContents contents = %d)",
@@ -2423,6 +2463,14 @@
 	vk::Cast(commandBuffer)->nextSubpass(contents);
 }
 
+VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass2KHR(VkCommandBuffer commandBuffer, const VkSubpassBeginInfoKHR *pSubpassBeginInfo, const VkSubpassEndInfoKHR *pSubpassEndInfo)
+{
+	TRACE("(VkCommandBuffer commandBuffer = %p, const VkSubpassBeginInfoKHR* pSubpassBeginInfo = %p, const VkSubpassEndInfoKHR* pSubpassEndInfo = %p)",
+	      commandBuffer, pSubpassBeginInfo, pSubpassEndInfo);
+
+	vk::Cast(commandBuffer)->nextSubpass(pSubpassBeginInfo->contents);
+}
+
 VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass(VkCommandBuffer commandBuffer)
 {
 	TRACE("(VkCommandBuffer commandBuffer = %p)", commandBuffer);
@@ -2430,6 +2478,13 @@
 	vk::Cast(commandBuffer)->endRenderPass();
 }
 
+VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass2KHR(VkCommandBuffer commandBuffer, const VkSubpassEndInfoKHR *pSubpassEndInfo)
+{
+	TRACE("(VkCommandBuffer commandBuffer = %p, const VkSubpassEndInfoKHR* pSubpassEndInfo = %p)", commandBuffer, pSubpassEndInfo);
+
+	vk::Cast(commandBuffer)->endRenderPass();
+}
+
 VKAPI_ATTR void VKAPI_CALL vkCmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer *pCommandBuffers)
 {
 	TRACE("(VkCommandBuffer commandBuffer = %p, uint32_t commandBufferCount = %d, const VkCommandBuffer* pCommandBuffers = %p)",
@@ -2700,6 +2755,12 @@
 				vk::Cast(physicalDevice)->getFeatures(features);
 			}
 			break;
+			case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES_KHR:
+			{
+				auto features = reinterpret_cast<VkPhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR*>(extensionFeatures);
+				vk::Cast(physicalDevice)->getFeatures(features);
+			}
+			break;
 			case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT:
 			{
 				auto features = reinterpret_cast<VkPhysicalDeviceLineRasterizationFeaturesEXT *>(extensionFeatures);