Merge pull request #911 from billhollings/master

Set maxVertexInputBindingStride and maxVertexInputAttributeOffset to min Vulkan values.
diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md
index 118881e..a114c71 100644
--- a/Docs/Whats_New.md
+++ b/Docs/Whats_New.md
@@ -21,6 +21,8 @@
 - Fix issue in reporting properties of substitutable `VkFormats`.
 - Fix vertex attribute offset adjustments when vertex buffer stride is zero.
 - Update `fetchDependencies` script to use pre-built `spirv-tools` files by default.
+- Update `maxVertexInputBindingStride` and `maxVertexInputAttributeOffset` 
+  to minimum Vulkan values.
 - Numerous documentation typo corrections.
 - Update `VK_MVK_MOLTENVK_SPEC_VERSION` to `26`.
 - Update Travis CI to Xcode 11.5.
diff --git a/MoltenVK/MoltenVK/Commands/MVKMTLBufferAllocation.mm b/MoltenVK/MoltenVK/Commands/MVKMTLBufferAllocation.mm
index 7e1bf25..a09386b 100644
--- a/MoltenVK/MoltenVK/Commands/MVKMTLBufferAllocation.mm
+++ b/MoltenVK/MoltenVK/Commands/MVKMTLBufferAllocation.mm
@@ -81,7 +81,7 @@
 	MVKAssert(length <= _maxAllocationLength, "This MVKMTLBufferAllocator has been configured to dispense MVKMTLBufferRegions no larger than %lu bytes.", (unsigned long)_maxAllocationLength);
 
     // Convert max length to the next power-of-two exponent to use as a lookup
-    uint32_t p2Exp = mvkPowerOfTwoExponent(length);
+    NSUInteger p2Exp = mvkPowerOfTwoExponent(length);
 	MVKMTLBufferAllocationPool* pRP = _regionPools[p2Exp];
 	return _makeThreadSafe ? pRP->acquireObjectSafely() : pRP->acquireObject();
 }
@@ -91,7 +91,7 @@
 	_makeThreadSafe = makeThreadSafe;
 
     // Convert max length to the next power-of-two exponent
-    uint32_t maxP2Exp = mvkPowerOfTwoExponent(_maxAllocationLength);
+    NSUInteger maxP2Exp = mvkPowerOfTwoExponent(_maxAllocationLength);
 
     // Populate the array of region pools to cover the maximum region size
     _regionPools.reserve(maxP2Exp + 1);
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
index aec27ae..7362b30 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
@@ -1253,8 +1253,8 @@
     _properties.limits.maxVertexInputAttributes = 31;
     _properties.limits.maxVertexInputBindings = 31;
 
-    _properties.limits.maxVertexInputAttributeOffset = (4 * KIBI);
-    _properties.limits.maxVertexInputBindingStride = _properties.limits.maxVertexInputAttributeOffset - 1;
+    _properties.limits.maxVertexInputBindingStride = (2 * KIBI);
+	_properties.limits.maxVertexInputAttributeOffset = _properties.limits.maxVertexInputBindingStride - 1;
 
 	_properties.limits.maxPerStageDescriptorSamplers = _metalFeatures.maxPerStageSamplerCount;
 	_properties.limits.maxPerStageDescriptorUniformBuffers = _metalFeatures.maxPerStageBufferCount;
diff --git a/MoltenVK/MoltenVK/Utility/MVKFoundation.h b/MoltenVK/MoltenVK/Utility/MVKFoundation.h
index a0f0eac..a8ea008 100644
--- a/MoltenVK/MoltenVK/Utility/MVKFoundation.h
+++ b/MoltenVK/MoltenVK/Utility/MVKFoundation.h
@@ -29,18 +29,6 @@
 
 #pragma mark Math
 
-/**
- * The following constants are used to indicate values that have no defined limit.
- * They are ridiculously large numbers, but low enough to be safely used as both
- * uint and int values without risking overflowing between positive and negative values.
- */
-static int32_t kMVKUndefinedLargeNegativeInt32 = std::numeric_limits<int32_t>::min() / 2;
-static int32_t kMVKUndefinedLargePositiveInt32 = std::numeric_limits<int32_t>::max() / 2;
-static uint32_t kMVKUndefinedLargeUInt32 = kMVKUndefinedLargePositiveInt32;
-static int64_t kMVKUndefinedLargeNegativeInt64 = std::numeric_limits<int64_t>::min() / 2;
-static int64_t kMVKUndefinedLargePositiveInt64 = std::numeric_limits<int64_t>::max() / 2;
-static uint64_t kMVKUndefinedLargeUInt64 = kMVKUndefinedLargePositiveInt64;
-
 // Common scaling multipliers
 #define KIBI		(1024)
 #define MEBI		(KIBI * KIBI)
@@ -136,21 +124,23 @@
 #pragma mark -
 #pragma mark Alignment functions
 
-/** Returns whether the specified value is a power-of-two. */
-static inline bool mvkIsPowerOfTwo(uintptr_t value) {
+/** Returns whether the specified positive value is a power-of-two. */
+template<typename T>
+static inline bool mvkIsPowerOfTwo(T value) {
 	// Test POT:  (x != 0) && ((x & (x - 1)) == 0)
 	return value && ((value & (value - 1)) == 0);
 }
 
 /**
- * Ensures the specified value is a power-of-two. Returns the specified value if it is a
- * power-of-two value. If it is not, returns the next power-of-two value that is larger
- * than the specified value is returned.
+ * Ensures the specified positive value is a power-of-two. Returns the specified value
+ * if it is a power-of-two value. If it is not, returns the next power-of-two value
+ * that is larger than the specified value is returned.
  */
-static inline uintptr_t mvkEnsurePowerOfTwo(uintptr_t value) {
+template<typename T>
+static inline T mvkEnsurePowerOfTwo(T value) {
 	if (mvkIsPowerOfTwo(value)) { return value; }
 
-	uintptr_t pot = 1;
+	T pot = 1;
 	while(pot <= value) { pot <<= 1; };
 	return pot;
 }
@@ -161,12 +151,13 @@
  *
  * This implementation returns zero for both zero and one as inputs.
  */
-static inline uint32_t mvkPowerOfTwoExponent(uintptr_t value) {
-    uintptr_t p2Value = mvkEnsurePowerOfTwo(value);
+template<typename T>
+static inline T mvkPowerOfTwoExponent(T value) {
+    T p2Value = mvkEnsurePowerOfTwo(value);
 
     // Count the trailing zeros
     p2Value = (p2Value ^ (p2Value - 1)) >> 1;  // Set trailing 0s to 1s and zero rest
-    uint32_t potExp = 0;
+    T potExp = 0;
     while (p2Value) {
         p2Value >>= 1;
         potExp++;
@@ -230,6 +221,18 @@
  */
 void mvkFlipVertically(void* rowMajorData, uint32_t rowCount, size_t bytesPerRow);
 
+/**
+ * The following constants are used to indicate values that have no defined limit.
+ * They are ridiculously large numbers, but low enough to be safely used as both
+ * uint and int values without risking overflowing between positive and negative values.
+ */
+static  int32_t kMVKUndefinedLargePositiveInt32 =  mvkEnsurePowerOfTwo(std::numeric_limits<int32_t>::max() / 2);
+static  int32_t kMVKUndefinedLargeNegativeInt32 = -kMVKUndefinedLargePositiveInt32;
+static uint32_t kMVKUndefinedLargeUInt32        =  kMVKUndefinedLargePositiveInt32;
+static  int64_t kMVKUndefinedLargePositiveInt64 =  mvkEnsurePowerOfTwo(std::numeric_limits<int64_t>::max() / 2);
+static  int64_t kMVKUndefinedLargeNegativeInt64 = -kMVKUndefinedLargePositiveInt64;
+static uint64_t kMVKUndefinedLargeUInt64        =  kMVKUndefinedLargePositiveInt64;
+
 
 #pragma mark Vulkan structure support functions