Merge pull request #605 from billhollings/master

Clear attachments using layered rendering only if framebuffer is layered.
diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md
index dbadfdd..3d6f6f5 100644
--- a/Docs/Whats_New.md
+++ b/Docs/Whats_New.md
@@ -30,7 +30,7 @@
 	- Fix tessellated indirect draws using wrong kernels to map parameters.
 	- Work around potential Metal bug with stage-in indirect buffers.
 	- Fix zero local threadgroup size in indirect tessellated rendering.
-- Fix crash with multisample layered rendering on older macOS devices.
+- Fix crash when clearing attachments using layered rendering on older macOS devices.
 - Fixes to Metal renderpass layered rendering settings.
 - `MoltenVKShaderConverter` tool: Add MSL version and platform command-line options.
 - Allow building external dependency libraries in `Debug` mode.
diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h
index 519e196..c26ecbf 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h
+++ b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h
@@ -115,7 +115,7 @@
 
 private:
 	uint32_t _firstViewport;
-	MVKVectorInline<MTLViewport, kMVKCachedViewportCount> _mtlViewports;
+	MVKVectorInline<MTLViewport, kMVKCachedViewportScissorCount> _mtlViewports;
 };
 
 
@@ -134,7 +134,7 @@
 
 private:
 	uint32_t _firstScissor;
-	MVKVectorInline<MTLScissorRect, kMVKCachedScissorCount> _mtlScissors;
+	MVKVectorInline<MTLScissorRect, kMVKCachedViewportScissorCount> _mtlScissors;
 };
 
 
diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.h b/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.h
index 91d7a65..31fd02a 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.h
+++ b/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.h
@@ -243,8 +243,8 @@
 
     std::vector<VkClearRect> _clearRects;
     std::vector<simd::float4> _vertices;
-    simd::float4 _clearColors[kMVKAttachmentFormatCount];
-    VkClearValue _vkClearValues[kMVKAttachmentFormatCount];
+    simd::float4 _clearColors[kMVKClearAttachmentCount];
+    VkClearValue _vkClearValues[kMVKClearAttachmentCount];
     MVKRPSKeyClearAtt _rpsKey;
     uint32_t _mtlStencilValue;
     bool _isClearingDepth;
diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm b/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm
index 0ea3925..2149cca 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm
+++ b/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm
@@ -816,7 +816,7 @@
                                         const VkClearAttachment* pAttachments,
                                         uint32_t rectCount,
                                         const VkClearRect* pRects) {
-    _rpsKey = kMVKRPSKeyClearAttDefault;
+	_rpsKey.reset();
     _mtlStencilValue = 0;
     _isClearingDepth = false;
     _isClearingStencil = false;
@@ -831,26 +831,26 @@
         if (mvkIsAnyFlagEnabled(clrAtt.aspectMask, VK_IMAGE_ASPECT_COLOR_BIT)) {
             uint32_t caIdx = clrAtt.colorAttachment;        // Might be VK_ATTACHMENT_UNUSED
             if (caIdx != VK_ATTACHMENT_UNUSED) {
-                _rpsKey.enable(caIdx);
+                _rpsKey.enableAttachment(caIdx);
                 _vkClearValues[caIdx] = clrAtt.clearValue;
             }
         }
 
         if (mvkIsAnyFlagEnabled(clrAtt.aspectMask, VK_IMAGE_ASPECT_DEPTH_BIT)) {
             _isClearingDepth = true;
-            _rpsKey.enable(kMVKAttachmentFormatDepthStencilIndex);
+            _rpsKey.enableAttachment(kMVKClearAttachmentDepthStencilIndex);
             mtlDepthVal = mvkMTLClearDepthFromVkClearValue(clrAtt.clearValue);
         }
 
         if (mvkIsAnyFlagEnabled(clrAtt.aspectMask, VK_IMAGE_ASPECT_STENCIL_BIT)) {
             _isClearingStencil = true;
-            _rpsKey.enable(kMVKAttachmentFormatDepthStencilIndex);
+            _rpsKey.enableAttachment(kMVKClearAttachmentDepthStencilIndex);
             _mtlStencilValue = mvkMTLClearStencilFromVkClearValue(clrAtt.clearValue);
         }
     }
 
     // The depth value (including vertex position Z value) is held in the last index.
-    _clearColors[kMVKAttachmentFormatDepthStencilIndex] = { mtlDepthVal, mtlDepthVal, mtlDepthVal, mtlDepthVal };
+    _clearColors[kMVKClearAttachmentDepthStencilIndex] = { mtlDepthVal, mtlDepthVal, mtlDepthVal, mtlDepthVal };
 
     _clearRects.clear();
     _clearRects.reserve(rectCount);
@@ -932,8 +932,9 @@
     uint32_t vtxCnt = (uint32_t)_vertices.size();
     uint32_t vtxBuffIdx = getDevice()->getMetalBufferIndexForVertexAttributeBinding(kMVKVertexContentBufferIndex);
 
-    // Populate the render pipeline state attachment key with attachment info from the subpass.
+    // Populate the render pipeline state attachment key with info from the subpass and framebuffer.
 	_rpsKey.mtlSampleCount = mvkSampleCountFromVkSampleCountFlagBits(subpass->getSampleCount());
+	if (cmdEncoder->_isUsingLayeredRendering) { _rpsKey.enableLayeredRendering(); }
 
     uint32_t caCnt = subpass->getColorAttachmentCount();
     for (uint32_t caIdx = 0; caIdx < caCnt; caIdx++) {
@@ -945,7 +946,7 @@
 
     VkFormat vkAttFmt = subpass->getDepthStencilFormat();
 	MTLPixelFormat mtlAttFmt = cmdPool->getMTLPixelFormatFromVkFormat(vkAttFmt);
-    _rpsKey.attachmentMTLPixelFormats[kMVKAttachmentFormatDepthStencilIndex] = mtlAttFmt;
+    _rpsKey.attachmentMTLPixelFormats[kMVKClearAttachmentDepthStencilIndex] = mtlAttFmt;
 	bool isClearingDepth = _isClearingDepth && mvkMTLPixelFormatIsDepthFormat(mtlAttFmt);
 	bool isClearingStencil = _isClearingStencil && mvkMTLPixelFormatIsStencilFormat(mtlAttFmt);
 
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h
index 8e2fa9b..c2d0356 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h
@@ -420,6 +420,9 @@
     /** The size of the threadgroup for the compute shader. */
     MTLSize _mtlThreadgroupSize;
 
+	/** Indicates whether the current render subpass is rendering to an array (layered) framebuffer. */
+	bool _isUsingLayeredRendering;
+
 
 #pragma mark Construction
 
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm
index 9ba1692..09356b4 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm
@@ -234,6 +234,7 @@
 void MVKCommandEncoder::encode(id<MTLCommandBuffer> mtlCmdBuff) {
 	_subpassContents = VK_SUBPASS_CONTENTS_INLINE;
 	_renderSubpassIndex = 0;
+	_isUsingLayeredRendering = false;
 
 	_mtlCmdBuffer = mtlCmdBuff;		// not retained
 
@@ -280,7 +281,12 @@
 	_subpassContents = subpassContents;
 	_renderSubpassIndex = subpassIndex;
 
-    beginMetalRenderPass(loadOverride, storeOverride);
+	_isUsingLayeredRendering = ((_framebuffer->getLayerCount() > 1) &&
+								_device->_pMetalFeatures->layeredRendering &&
+								(_device->_pMetalFeatures->multisampleLayeredRendering ||
+								 (getSubpass()->getSampleCount() == VK_SAMPLE_COUNT_1_BIT)));
+
+	beginMetalRenderPass(loadOverride, storeOverride);
 }
 
 // Creates _mtlRenderEncoder and marks cached render state as dirty so it will be set into the _mtlRenderEncoder.
@@ -293,11 +299,7 @@
     mtlRPDesc.visibilityResultBuffer = _occlusionQueryState.getVisibilityResultMTLBuffer();
 
 	// Only set the layered rendering properties if layered rendering is supported and the framebuffer really has multiple layers
-	if ((_framebuffer->getLayerCount() > 1) &&
-		_device->_pMetalFeatures->layeredRendering &&
-		(_device->_pMetalFeatures->multisampleLayeredRendering ||
-		 (getSubpass()->getSampleCount() == VK_SAMPLE_COUNT_1_BIT))) {
-
+	if (_isUsingLayeredRendering) {
 		VkExtent2D fbExtent = _framebuffer->getExtent2D();
 		mtlRPDesc.renderTargetWidthMVK = min(_renderArea.offset.x + _renderArea.extent.width, fbExtent.width);
 		mtlRPDesc.renderTargetHeightMVK = min(_renderArea.offset.y + _renderArea.extent.height, fbExtent.height);
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h
index 87646d2..843c209 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h
@@ -151,7 +151,7 @@
     void encodeImpl(uint32_t stage) override;
     void resetImpl() override;
 
-    MVKVectorInline<MTLViewport, kMVKCachedViewportCount> _mtlViewports, _mtlDynamicViewports;
+    MVKVectorInline<MTLViewport, kMVKCachedViewportScissorCount> _mtlViewports, _mtlDynamicViewports;
 };
 
 
@@ -180,7 +180,7 @@
     void encodeImpl(uint32_t stage) override;
     void resetImpl() override;
 
-    MVKVectorInline<MTLScissorRect, kMVKCachedScissorCount> _mtlScissors, _mtlDynamicScissors;
+    MVKVectorInline<MTLScissorRect, kMVKCachedViewportScissorCount> _mtlScissors, _mtlDynamicScissors;
 };
 
 
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandPool.h b/MoltenVK/MoltenVK/Commands/MVKCommandPool.h
index efabe55..253580f 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandPool.h
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandPool.h
@@ -20,7 +20,6 @@
 
 #include "MVKDevice.h"
 #include "MVKCommandBuffer.h"
-#include "MVKCommandResourceFactory.h"
 #include "MVKCommandEncodingPool.h"
 #include "MVKCommand.h"
 #include "MVKCmdPipeline.h"
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.h b/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.h
index a9ddfb0..55bef82 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.h
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.h
@@ -74,8 +74,9 @@
 #pragma mark -
 #pragma mark MVKRPSKeyClearAtt
 
-#define kMVKAttachmentFormatCount					9
-#define kMVKAttachmentFormatDepthStencilIndex		(kMVKAttachmentFormatCount - 1)
+#define kMVKClearAttachmentCount						(kMVKCachedColorAttachmentCount + 1)
+#define kMVKClearAttachmentDepthStencilIndex			(kMVKClearAttachmentCount - 1)
+#define kMVKClearAttachmentLayeredRenderingBitIndex		kMVKClearAttachmentCount
 
 /**
  * Key to use for looking up cached MTLRenderPipelineState instances.
@@ -85,37 +86,40 @@
  * This structure can be used as a key in a std::map and std::unordered_map.
  */
 typedef struct MVKRPSKeyClearAtt_t {
-    uint16_t attachmentMTLPixelFormats[kMVKAttachmentFormatCount];
+    uint16_t attachmentMTLPixelFormats[kMVKClearAttachmentCount];
 	uint16_t mtlSampleCount;
-    uint32_t enabledFlags;
+    uint16_t flags;			// bitcount > kMVKClearAttachmentLayeredRenderingBitIndex
 
     const static uint32_t bitFlag = 1;
 
-    void enable(uint32_t attIdx) { mvkEnableFlag(enabledFlags, bitFlag << attIdx); }
+    void enableAttachment(uint32_t attIdx) { mvkEnableFlag(flags, bitFlag << attIdx); }
 
-    bool isEnabled(uint32_t attIdx) { return mvkIsAnyFlagEnabled(enabledFlags, bitFlag << attIdx); }
+    bool isAttachmentEnabled(uint32_t attIdx) { return mvkIsAnyFlagEnabled(flags, bitFlag << attIdx); }
+
+	void enableLayeredRendering() { mvkEnableFlag(flags, bitFlag << kMVKClearAttachmentLayeredRenderingBitIndex); }
+
+	bool isLayeredRenderingEnabled() { return mvkIsAnyFlagEnabled(flags, bitFlag << kMVKClearAttachmentLayeredRenderingBitIndex); }
 
     bool operator==(const MVKRPSKeyClearAtt_t& rhs) const {
-        return ((enabledFlags == rhs.enabledFlags) &&
+        return ((flags == rhs.flags) &&
 				(mtlSampleCount == rhs.mtlSampleCount) &&
                 (memcmp(attachmentMTLPixelFormats, rhs.attachmentMTLPixelFormats, sizeof(attachmentMTLPixelFormats)) == 0));
     }
 
 	std::size_t hash() const {
-		std::size_t hash = mvkHash(&enabledFlags);
+		std::size_t hash = mvkHash(&flags);
 		hash = mvkHash(&mtlSampleCount, 1, hash);
-		return mvkHash(attachmentMTLPixelFormats, kMVKAttachmentFormatCount, hash);
+		return mvkHash(attachmentMTLPixelFormats, kMVKClearAttachmentCount, hash);
 	}
 
-	MVKRPSKeyClearAtt_t() {
+	void reset() {
 		memset(this, 0, sizeof(*this));
 		mtlSampleCount = mvkSampleCountFromVkSampleCountFlagBits(VK_SAMPLE_COUNT_1_BIT);
 	}
 
-} MVKRPSKeyClearAtt;
+	MVKRPSKeyClearAtt_t() { reset(); }
 
-/** An instance populated with default values, for use in resetting other instances to default state. */
-const MVKRPSKeyClearAtt kMVKRPSKeyClearAttDefault;
+} MVKRPSKeyClearAtt;
 
 /**
  * Hash structure implementation for MVKRPSKeyClearAtt in std namespace,
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.mm b/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.mm
index da458bc..29d56a7 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.mm
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.mm
@@ -95,12 +95,12 @@
 	plDesc.sampleCount = attKey.mtlSampleCount;
 	plDesc.inputPrimitiveTopologyMVK = MTLPrimitiveTopologyClassTriangle;
 
-    for (uint32_t caIdx = 0; caIdx < kMVKAttachmentFormatDepthStencilIndex; caIdx++) {
+    for (uint32_t caIdx = 0; caIdx < kMVKClearAttachmentDepthStencilIndex; caIdx++) {
         MTLRenderPipelineColorAttachmentDescriptor* colorDesc = plDesc.colorAttachments[caIdx];
         colorDesc.pixelFormat = (MTLPixelFormat)attKey.attachmentMTLPixelFormats[caIdx];
-        colorDesc.writeMask = attKey.isEnabled(caIdx) ? MTLColorWriteMaskAll : MTLColorWriteMaskNone;
+        colorDesc.writeMask = attKey.isAttachmentEnabled(caIdx) ? MTLColorWriteMaskAll : MTLColorWriteMaskNone;
     }
-    MTLPixelFormat mtlDSFormat = (MTLPixelFormat)attKey.attachmentMTLPixelFormats[kMVKAttachmentFormatDepthStencilIndex];
+    MTLPixelFormat mtlDSFormat = (MTLPixelFormat)attKey.attachmentMTLPixelFormats[kMVKClearAttachmentDepthStencilIndex];
     if (mvkMTLPixelFormatIsDepthFormat(mtlDSFormat)) { plDesc.depthAttachmentPixelFormat = mtlDSFormat; }
     if (mvkMTLPixelFormatIsStencilFormat(mtlDSFormat)) { plDesc.stencilAttachmentPixelFormat = mtlDSFormat; }
 
@@ -181,7 +181,6 @@
 
 id<MTLFunction> MVKCommandResourceFactory::getClearVertFunction(MVKRPSKeyClearAtt& attKey) {
 	id<MTLFunction> mtlFunc = nil;
-	bool allowLayers = _device->_pMetalFeatures->layeredRendering && (attKey.mtlSampleCount == 1 || _device->_pMetalFeatures->multisampleLayeredRendering);
 	@autoreleasepool {
 		NSMutableString* msl = [NSMutableString stringWithCapacity: (2 * KIBI) ];
 		[msl appendLineMVK: @"#include <metal_stdlib>"];
@@ -197,7 +196,7 @@
 		[msl appendLineMVK];
 		[msl appendLineMVK: @"typedef struct {"];
 		[msl appendLineMVK: @"    float4 v_position [[position]];"];
-		[msl appendFormat:  @"    uint layer%s;", allowLayers ? " [[render_target_array_index]]" : ""];
+		[msl appendFormat:  @"    uint layer%s;", attKey.isLayeredRenderingEnabled() ? " [[render_target_array_index]]" : ""];
 		[msl appendLineMVK: @"} VaryingsPos;"];
 		[msl appendLineMVK];
 
@@ -232,8 +231,8 @@
 		[msl appendLineMVK: @"} ClearColorsIn;"];
 		[msl appendLineMVK];
 		[msl appendLineMVK: @"typedef struct {"];
-		for (uint32_t caIdx = 0; caIdx < kMVKAttachmentFormatDepthStencilIndex; caIdx++) {
-			if (attKey.isEnabled(caIdx)) {
+		for (uint32_t caIdx = 0; caIdx < kMVKClearAttachmentDepthStencilIndex; caIdx++) {
+			if (attKey.isAttachmentEnabled(caIdx)) {
 				NSString* typeStr = getMTLFormatTypeString((MTLPixelFormat)attKey.attachmentMTLPixelFormats[caIdx]);
 				[msl appendFormat: @"    %@4 color%u [[color(%u)]];", typeStr, caIdx, caIdx];
 				[msl appendLineMVK];
@@ -246,8 +245,8 @@
 		[msl appendFormat: @"fragment ClearColorsOut %@(VaryingsPos varyings [[stage_in]], constant ClearColorsIn& ccIn [[buffer(0)]]) {", funcName];
 		[msl appendLineMVK];
 		[msl appendLineMVK: @"    ClearColorsOut ccOut;"];
-		for (uint32_t caIdx = 0; caIdx < kMVKAttachmentFormatDepthStencilIndex; caIdx++) {
-			if (attKey.isEnabled(caIdx)) {
+		for (uint32_t caIdx = 0; caIdx < kMVKClearAttachmentDepthStencilIndex; caIdx++) {
+			if (attKey.isAttachmentEnabled(caIdx)) {
 				NSString* typeStr = getMTLFormatTypeString((MTLPixelFormat)attKey.attachmentMTLPixelFormats[caIdx]);
 				[msl appendFormat: @"    ccOut.color%u = %@4(ccIn.colors[%u]);", caIdx, typeStr, caIdx];
 				[msl appendLineMVK];
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h
index 129e6ee..5680d9a 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h
@@ -67,8 +67,8 @@
 const static uint32_t kMVKVertexContentBufferIndex = 0;
 
 // Parameters to define the sizing of inline collections
-const static uint32_t kMVKCachedViewportCount = 16;
-const static uint32_t kMVKCachedScissorCount = 16;
+const static uint32_t kMVKCachedViewportScissorCount = 16;
+const static uint32_t kMVKCachedColorAttachmentCount = 8;
 
 
 #pragma mark -
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
index d2fdfd5..d2ea1af 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
@@ -1002,13 +1002,13 @@
 	// Limits
 #if MVK_IOS
     if ( [_mtlDevice supportsFeatureSet: MTLFeatureSet_iOS_GPUFamily2_v1] ) {
-        _properties.limits.maxColorAttachments = 8;
+        _properties.limits.maxColorAttachments = kMVKCachedColorAttachmentCount;
     } else {
-        _properties.limits.maxColorAttachments = 4;
+        _properties.limits.maxColorAttachments = 4;		// < kMVKCachedColorAttachmentCount
     }
 #endif
 #if MVK_MACOS
-    _properties.limits.maxColorAttachments = 8;
+    _properties.limits.maxColorAttachments = kMVKCachedColorAttachmentCount;
 #endif
 
     _properties.limits.maxFragmentOutputAttachments = _properties.limits.maxColorAttachments;
@@ -1038,7 +1038,7 @@
     float maxVPDim = max(_properties.limits.maxViewportDimensions[0], _properties.limits.maxViewportDimensions[1]);
     _properties.limits.viewportBoundsRange[0] = (-2.0 * maxVPDim);
     _properties.limits.viewportBoundsRange[1] = (2.0 * maxVPDim) - 1;
-    _properties.limits.maxViewports = _features.multiViewport ? 16 : 1;
+    _properties.limits.maxViewports = _features.multiViewport ? kMVKCachedViewportScissorCount : 1;
 
 	_properties.limits.maxImageDimension3D = (2 * KIBI);
 	_properties.limits.maxImageArrayLayers = (2 * KIBI);
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
index 63c94ff..b14f33c 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
@@ -608,6 +608,11 @@
 		setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Under Metal, depth/stencil formats may only be used with 2D images."));
 	}
 
+	bool isAttachment = mvkIsAnyFlagEnabled(pCreateInfo->usage, (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT));
+	if (isAttachment && (pCreateInfo->arrayLayers > 1) && !_device->_pMetalFeatures->layeredRendering) {
+		setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : This device does not support rendering to array (layered) attachments."));
+	}
+
 	if (mvkIsAnyFlagEnabled(pCreateInfo->flags, VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT)) {
 		setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Metal does not allow uncompressed views of compressed images."));
 	}
@@ -635,8 +640,8 @@
 			validSamples = VK_SAMPLE_COUNT_1_BIT;
 		}
 
-		if ( !_device->_pMetalFeatures->multisampleLayeredRendering && mvkIsAnyFlagEnabled(pCreateInfo->usage, (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
-																												VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT))) {
+		bool isAttachment = mvkIsAnyFlagEnabled(pCreateInfo->usage, (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT));
+		if (isAttachment && !_device->_pMetalFeatures->multisampleLayeredRendering) {
 			setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : This device does not support rendering to multisampled array (layered) attachments. Setting sample count to 1."));
 			validSamples = VK_SAMPLE_COUNT_1_BIT;
 		}
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h
index a685e4c..39f8543 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h
@@ -236,8 +236,8 @@
 	VkPipelineRasterizationStateCreateInfo _rasterInfo;
 	VkPipelineDepthStencilStateCreateInfo _depthStencilInfo;
 
-	MVKVectorInline<MTLViewport, kMVKCachedViewportCount> _mtlViewports;
-	MVKVectorInline<MTLScissorRect, kMVKCachedScissorCount> _mtlScissors;
+	MVKVectorInline<MTLViewport, kMVKCachedViewportScissorCount> _mtlViewports;
+	MVKVectorInline<MTLScissorRect, kMVKCachedViewportScissorCount> _mtlScissors;
 
 	MTLComputePipelineDescriptor* _mtlTessControlStageDesc = nil;