Merge pull request #326 from DiegoAce/master

Force Bitcode When Building
diff --git a/MoltenVK/MoltenVK.xcodeproj/project.pbxproj b/MoltenVK/MoltenVK.xcodeproj/project.pbxproj
index d3ee235..bb00895 100644
--- a/MoltenVK/MoltenVK.xcodeproj/project.pbxproj
+++ b/MoltenVK/MoltenVK.xcodeproj/project.pbxproj
@@ -875,7 +875,7 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "export MVK_OS=\"macosx\"\nexport MVK_ARCH=\"x86_64\"\nexport MVK_UX_FWK=\"AppKit\"\nexport MVK_MIN_OS_VERSION=${MACOSX_DEPLOYMENT_TARGET}\nexport MVK_IOSURFACE_FWK=\"-framework IOSurface\"\n\n\"${SRCROOT}/scripts/create_dylib.sh\"\n";
+			shellScript = "export MVK_OS=\"macosx\"\nexport MVK_UX_FWK=\"AppKit\"\nexport MVK_MIN_OS_VERSION=${MACOSX_DEPLOYMENT_TARGET}\nexport MVK_IOSURFACE_FWK=\"-framework IOSurface\"\n\n\"${SRCROOT}/scripts/create_dylib.sh\"\n";
 		};
 		A9731FAD1EDDAE39006B7298 /* Create Dynamic Library */ = {
 			isa = PBXShellScriptBuildPhase;
@@ -889,7 +889,7 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "export MVK_OS=\"ios\"\nexport MVK_ARCH=\"arm64\"\nexport MVK_UX_FWK=\"UIKit\"\nexport MVK_MIN_OS_VERSION=${IPHONEOS_DEPLOYMENT_TARGET}\nexport MVK_IOSURFACE_FWK=\"-framework IOSurface\"\n\n# Do not link to IOSurface if deploying to iOS versions below 11.0, doing so will\n# link IOSurface as a private framework, which will trigger App Store rejection.\nif [ $(echo \"${MVK_MIN_OS_VERSION} < 11.0\" | bc) -eq 1 ]; then\n    MVK_IOSURFACE_FWK=\"\"\nfi\n\n\"${SRCROOT}/scripts/create_dylib.sh\"\n";
+			shellScript = "export MVK_OS=\"ios\"\nexport MVK_UX_FWK=\"UIKit\"\nexport MVK_MIN_OS_VERSION=${IPHONEOS_DEPLOYMENT_TARGET}\nexport MVK_IOSURFACE_FWK=\"-framework IOSurface\"\n\n# Do not link to IOSurface if deploying to iOS versions below 11.0, doing so will\n# link IOSurface as a private framework, which will trigger App Store rejection.\nif [ $(echo \"${MVK_MIN_OS_VERSION} < 11.0\" | bc) -eq 1 ]; then\n    MVK_IOSURFACE_FWK=\"\"\nfi\n\n\"${SRCROOT}/scripts/create_dylib.sh\"\n";
 		};
 /* End PBXShellScriptBuildPhase section */
 
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
index 2e67a6a..ff9d0a9 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
@@ -1062,15 +1062,32 @@
 	//		- cmdbuff waitUntilCompleted (or completion handler)
 	//		- buffer/texture getBytes:
 
-	_memoryProperties.memoryHeapCount = 1;
-	_memoryProperties.memoryHeaps[0].flags = (VK_MEMORY_HEAP_DEVICE_LOCAL_BIT);
-	_memoryProperties.memoryHeaps[0].size = (VkDeviceSize)mvkRecommendedMaxWorkingSetSize(_mtlDevice);
-	_memoryProperties.memoryTypes[0].heapIndex = 0;
-	_memoryProperties.memoryTypes[0].propertyFlags = MVK_VK_MEMORY_TYPE_METAL_PRIVATE;	// Private storage
-	_memoryProperties.memoryTypes[1].heapIndex = 0;
-	_memoryProperties.memoryTypes[1].propertyFlags = MVK_VK_MEMORY_TYPE_METAL_SHARED;	// Shared storage
-	_memoryProperties.memoryTypes[2].heapIndex = 0;
-	_memoryProperties.memoryTypes[2].propertyFlags = MVK_VK_MEMORY_TYPE_METAL_MANAGED;	// Managed storage
+    _memoryProperties = (VkPhysicalDeviceMemoryProperties){
+        .memoryHeapCount = 1,
+        .memoryHeaps = {
+            {
+                .flags = (VK_MEMORY_HEAP_DEVICE_LOCAL_BIT),
+                .size = (VkDeviceSize)mvkRecommendedMaxWorkingSetSize(_mtlDevice),
+            },
+        },
+        // NB this list needs to stay sorted by propertyFlags (as bit sets)
+        .memoryTypes = {
+            {
+                .heapIndex = 0,
+                .propertyFlags = MVK_VK_MEMORY_TYPE_METAL_PRIVATE,    // Private storage
+            },
+#if MVK_MACOS
+            {
+                .heapIndex = 0,
+                .propertyFlags = MVK_VK_MEMORY_TYPE_METAL_MANAGED,    // Managed storage
+            },
+#endif
+            {
+                .heapIndex = 0,
+                .propertyFlags = MVK_VK_MEMORY_TYPE_METAL_SHARED,    // Shared storage
+            },
+        },
+    };
 
 #if MVK_MACOS
 	_memoryProperties.memoryTypeCount = 3;
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm
index 4ed44dc..d1aac44 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm
@@ -230,9 +230,20 @@
 
 	// "Dedicated" means this memory can only be used for this image or buffer.
 	if (dedicatedImage) {
+#if MVK_MACOS
 		if (isMemoryHostCoherent() ) {
-			setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_OUT_OF_DEVICE_MEMORY, "Host-coherent VkDeviceMemory objects cannot be associated with images."));
+			if (!((MVKImage*)dedicatedImage)->_isLinear) {
+				setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_OUT_OF_DEVICE_MEMORY, "Host-coherent VkDeviceMemory objects cannot be associated with optimal-tiling images."));
+			} else {
+				// Need to use the managed mode for images.
+				_mtlStorageMode = MTLStorageModeManaged;
+				// Nonetheless, we need a buffer to be able to map the memory at will.
+				if (!ensureMTLBuffer() ) {
+					setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_OUT_OF_DEVICE_MEMORY, "Could not allocate a host-coherent VkDeviceMemory of size %llu bytes. The maximum memory-aligned size of a host-coherent VkDeviceMemory is %llu bytes.", _allocationSize, _device->_pMetalFeatures->maxMTLBufferSize));
+				}
+			}
 		}
+#endif
 		_isDedicated = true;
 		_images.push_back((MVKImage*)dedicatedImage);
 		return;
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
index 3e0703b..b0a621b 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
@@ -720,9 +720,10 @@
 	if ((viewType == VK_IMAGE_VIEW_TYPE_2D || viewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY) && (imgType == VK_IMAGE_TYPE_3D)) {
 		if (pCreateInfo->subresourceRange.layerCount != image->_extent.depth) {
 			mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImageView(): Metal does not fully support views on a subset of a 3D texture.");
-		} else if (!(_usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)) {
+		}
+		if (!mvkAreFlagsEnabled(_usage, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)) {
 			setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImageView(): 2D views on 3D images are only supported for color attachments."));
-		} else if (_usage & ~VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
+		} else if (mvkIsAnyFlagEnabled(_usage, ~VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)) {
 			mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImageView(): 2D views on 3D images are only supported for color attachments.");
 		}
 	}
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
index 0c38b3b..fb8f2d4 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
@@ -407,6 +407,7 @@
     }
 
     // Color attachments
+    uint32_t caCnt = 0;
     if (pCreateInfo->pColorBlendState) {
         for (uint32_t caIdx = 0; caIdx < pCreateInfo->pColorBlendState->attachmentCount; caIdx++) {
             const VkPipelineColorBlendAttachmentState* pCA = &pCreateInfo->pColorBlendState->pAttachments[caIdx];
@@ -418,6 +419,7 @@
             // The pixel format will be MTLPixelFormatInvalid in that case, and
             // Metal asserts if we turn on blending with that pixel format.
             if (mvkRenderSubpass->isColorAttachmentUsed(caIdx)) {
+                caCnt++;
                 colorDesc.blendingEnabled = pCA->blendEnable;
                 colorDesc.rgbBlendOperation = mvkMTLBlendOperationFromVkBlendOp(pCA->colorBlendOp);
                 colorDesc.sourceRGBBlendFactor = mvkMTLBlendFactorFromVkBlendFactor(pCA->srcColorBlendFactor);
@@ -437,8 +439,7 @@
     // In Vulkan, it's perfectly valid to do rasterization with no attachments.
     // Not so in Metal. If we have no attachments and rasterization is enabled,
     // then we'll have to add a dummy attachment.
-    if (plDesc.rasterizationEnabled &&
-            (!pCreateInfo->pColorBlendState || !pCreateInfo->pColorBlendState->attachmentCount) &&
+    if (plDesc.rasterizationEnabled && !caCnt &&
             !mvkMTLPixelFormatIsDepthFormat(mtlDSFormat) &&
             !mvkMTLPixelFormatIsStencilFormat(mtlDSFormat)) {
         MTLRenderPipelineColorAttachmentDescriptor* colorDesc = plDesc.colorAttachments[0];
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm
index 69740dd..3dde4c8 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm
@@ -93,6 +93,8 @@
 				mtlColorAttDesc.clearColor = mvkMTLClearColorFromVkClearValue(clearValues[clrRPAttIdx], clrMVKRPAtt->getFormat());
 			}
 
+		} else {
+			caCnt--;
 		}
 	}
 
diff --git a/MoltenVK/scripts/create_dylib.sh b/MoltenVK/scripts/create_dylib.sh
index b6df2fa..4e5b81c 100755
--- a/MoltenVK/scripts/create_dylib.sh
+++ b/MoltenVK/scripts/create_dylib.sh
@@ -10,9 +10,10 @@
 	MVK_TSAN="-fsanitize=thread"
 fi
 
-clang \
+clang++ \
+-stdlib=${CLANG_CXX_LIBRARY} \
 -dynamiclib ${MVK_TSAN} \
--arch ${MVK_ARCH} \
+$(printf "-arch %s " ${ARCHS}) \
 -m${MVK_OS}-version-min=${MVK_MIN_OS_VERSION} \
 -compatibility_version 1.0.0 -current_version 1.0.0  \
 -install_name "@rpath/${MVK_DYLIB_NAME}"  \
@@ -22,6 +23,5 @@
 -iframework ${MVK_SYS_FWK_DIR}  \
 -framework Metal ${MVK_IOSURFACE_FWK} -framework ${MVK_UX_FWK} -framework QuartzCore -framework IOKit -framework Foundation \
 --library-directory ${MVK_USR_LIB_DIR} \
--lSystem  -lc++ \
 -o "${BUILT_PRODUCTS_DIR}/${MVK_DYLIB_NAME}" \
 -force_load "${BUILT_PRODUCTS_DIR}/lib${PRODUCT_NAME}.a"